1. 程式人生 > >[線段樹 區間最值操作 模板 Segment tree Beats!] BZOJ 4695 最假女選手

[線段樹 區間最值操作 模板 Segment tree Beats!] BZOJ 4695 最假女選手

鬼畜線段樹的大模板題 具體見吉麗的集訓隊論文
我終於會寫線段樹了 不對 我好像還不會歷史最值

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  return
*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=500005; const int M=N<<2; int mx[M],sx[M],cx[M],mn[M],sn[M],cn[M]; ll sum[M]; int ta[M]; inline
void update(int x){ int l=x<<1,r=x<<1|1; sum[x]=sum[l]+sum[r]; if (mx[l]==mx[r]) mx[x]=mx[l],cx[x]=cx[l]+cx[r],sx[x]=max(sx[l],sx[r]); else{ // r>l if (mx[l]>mx[r]) swap(l,r); mx[x]=mx[r]; cx[x]=cx[r]; sx[x]=max(sx[r],mx[l]); } if (mn[l]==mn[r]) mn[x]=mn[l],cn[x]=cn[l]+cn[r],sn[x]=min(sn[l],sn[r]); else
{ // r<l if (mn[l]<mn[r]) swap(l,r); mn[x]=mn[r]; cn[x]=cn[r]; sn[x]=min(sn[r],mn[l]); } } inline void Build(int x,int l,int r){ if (l==r){ int a; read(a); sum[x]=mx[x]=mn[x]=a; cx[x]=cn[x]=1; sx[x]=-1<<30; sn[x]=1<<30; ta[x]=0; return; } int mid=(l+r)>>1; Build(x<<1,l,mid); Build(x<<1|1,mid+1,r); update(x); } inline void _add(int x,int l,int r,int t){ sum[x]+=(ll)(r-l+1)*t; mn[x]+=t; sn[x]+=t; mx[x]+=t; sx[x]+=t; ta[x]+=t; } inline void _min(int x,int l,int r,int t){ sum[x]-=(ll)cx[x]*(mx[x]-t); mx[x]=t; mn[x]=min(mn[x],t); if (mn[x]==mx[x]){ sum[x]=(ll)(r-l+1)*t; cx[x]=cn[x]=r-l+1; sx[x]=-1<<30; sn[x]=1<<30; }else sn[x]=min(sn[x],t); } inline void _max(int x,int l,int r,int t){ sum[x]+=(ll)cn[x]*(t-mn[x]); mn[x]=t; mx[x]=max(mx[x],t); if (mn[x]==mx[x]){ sum[x]=(ll)(r-l+1)*t; cx[x]=cn[x]=r-l+1; sx[x]=-1<<30; sn[x]=1<<30; }else sx[x]=max(sx[x],t); } inline void push(int x,int l,int r){ int mid=(l+r)>>1; if (ta[x]){ _add(x<<1,l,mid,ta[x]); _add(x<<1|1,mid+1,r,ta[x]); ta[x]=0; } if (mx[x<<1]>mx[x] && sx[x<<1]<mx[x]) _min(x<<1,l,mid,mx[x]); if (mx[x<<1|1]>mx[x] && sx[x<<1|1]<mx[x]) _min(x<<1|1,mid+1,r,mx[x]); if (mn[x<<1]<mn[x] && sn[x<<1]>mn[x]) _max(x<<1,l,mid,mn[x]); if (mn[x<<1|1]<mn[x] && sn[x<<1|1]>mn[x]) _max(x<<1|1,mid+1,r,mn[x]); } int ql,qr,qt; inline void Mmax(int x,int l,int r){ if (mn[x]>=qt) return; if (ql<=l && r<=qr && qt<sn[x]){ _max(x,l,r,qt); return; } push(x,l,r); int mid=(l+r)>>1; if (ql<=mid) Mmax(x<<1,l,mid); if (qr>mid) Mmax(x<<1|1,mid+1,r); update(x); } inline void Mmin(int x,int l,int r){ if (mx[x]<=qt) return; if (ql<=l && r<=qr && qt>sx[x]){ _min(x,l,r,qt); return; } push(x,l,r); int mid=(l+r)>>1; if (ql<=mid) Mmin(x<<1,l,mid); if (qr>mid) Mmin(x<<1|1,mid+1,r); update(x); } inline void Add(int x,int l,int r){ if (ql<=l && r<=qr){ _add(x,l,r,qt); return; } push(x,l,r); int mid=(l+r)>>1; if (ql<=mid) Add(x<<1,l,mid); if (qr>mid) Add(x<<1|1,mid+1,r); update(x); } inline int Max(int x,int l,int r){ if (ql<=l && r<=qr) return mx[x]; push(x,l,r); int ret=-1<<30; int mid=(l+r)>>1; if (ql<=mid) ret=max(ret,Max(x<<1,l,mid)); if (qr>mid) ret=max(ret,Max(x<<1|1,mid+1,r)); return ret; } inline int Min(int x,int l,int r){ if (ql<=l && r<=qr) return mn[x]; push(x,l,r); int ret=1<<30; int mid=(l+r)>>1; if (ql<=mid) ret=min(ret,Min(x<<1,l,mid)); if (qr>mid) ret=min(ret,Min(x<<1|1,mid+1,r)); return ret; } inline ll Sum(int x,int l,int r){ if (ql<=l && r<=qr) return sum[x]; push(x,l,r); ll ret=0; int mid=(l+r)>>1; if (ql<=mid) ret+=Sum(x<<1,l,mid); if (qr>mid) ret+=Sum(x<<1|1,mid+1,r); return ret; } int n; int main(){ int Q,order,t; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); Build(1,1,n); read(Q); while (Q--){ read(order); read(ql); read(qr); if (order==1){ read(qt),Add(1,1,n); }else if (order==2){ read(qt),Mmax(1,1,n); }else if (order==3){ read(qt),Mmin(1,1,n); }else if (order==4){ printf("%lld\n",Sum(1,1,n)); }else if (order==5){ printf("%d\n",Max(1,1,n)); }else if (order==6){ printf("%d\n",Min(1,1,n)); } } return 0; }