填坑计划。。。
这是历史最值线段树的裸蹄,考察的也就是对打(xjb)标(tao)记(lun)的应用,也就是merge函数
考虑在维护最大值的基础上记录历史最值,以及一个历史最值懒标记
假设这个懒标记为二元组(add,cover)表示历史最值是当前的最大值(未下放最大值的懒标记)加上add,或就是cover,反正保证的是先加再覆盖,和最大值的懒标记刚好反过来,是为了合并方便
那么对于只cover的那相当于加0再cover咯
标记的下放,设当前为1,有(add1,cover1)+(add2,cover2)=(add1,max(cover1,cover2,lastcover+add2))注意这里add2加的是当前未下发标记时最后一次覆盖的值
还有一种特殊情况,就是当前还没有覆盖过,此时(add1,cover1)+(add2,cover2)=(max(add1,lastadd+add2),cover2)
非常值得注意的是,关于last的东西都是靠最大值的懒标记得来的,我打懒标记是cover的时候顺便清空add,假如add和cover均有值说明add是在cover之后,那么对lastcover是cover+add的
还有就是初始设为-inf的cover是有可以+一个乱七八糟的东西然后和另一个-inf比较更新历史懒标记的。。。。假如你打==-inf的话就会调成sb了。。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #define mid (ql+qr)/2 #define lc now<<1 #define rc now<<1|1 using namespace std; const int inf=(1<<30); struct pa { int ad,cv; pa(){ad=0,cv=-inf;} void clear(){ad=0,cv=-inf;} pa(int AD,int CV){ad=AD,cv=CV;} };int a[110000]; //~~~~~~~~~~~tab~~~~~~~~~~~~~~~~~~ struct node { int mx; pa la; //only use for now int hmx; pa ha; //only use for history pa merge(pa ne) { if(ha.cv==-inf)ha=pa(max(ha.ad,la.ad+ne.ad),ne.cv); else ha=pa(ha.ad,max(la.ad+la.cv+ne.ad*(la.cv!=-inf),max(ha.cv,ne.cv))); } }tr[310000]; void pushdown(int now) { pa h=tr[now].ha,l=tr[now].la; tr[now].ha.clear(),tr[now].la.clear(); if(lc!=0) { tr[lc].hmx=max(tr[lc].hmx,max(tr[lc].mx+h.ad,h.cv)); tr[lc].merge(h); if(l.cv!=-inf) tr[lc].mx=l.cv, tr[lc].la.cv=l.cv,tr[lc].la.ad=0; tr[lc].mx+=l.ad; tr[lc].la.ad+=l.ad; } if(rc!=0) { tr[rc].hmx=max(tr[rc].hmx,max(tr[rc].mx+h.ad,h.cv)); tr[rc].merge(h); if(l.cv!=-inf) tr[rc].mx=l.cv, tr[rc].la.cv=l.cv,tr[rc].la.ad=0; tr[rc].mx+=l.ad; tr[rc].la.ad+=l.ad; } } void update(int now) { tr[now].mx=max(tr[lc].mx,tr[rc].mx); tr[now].hmx=max(tr[lc].hmx,tr[rc].hmx); } //~~~~~~~~~~~~~~in~~~~~~~~~~~~~~~~~~~ void bt(int now,int ql,int qr) { if(ql==qr) tr[now].mx=tr[now].hmx=a[ql]; else bt(lc,ql,mid),bt(rc,mid+1,qr), update(now); } void add(int now,int ql,int qr,int l,int r,int d) { if(ql==l&&qr==r) { tr[now].merge(pa(d,-inf)); tr[now].mx+=d; tr[now].la.ad+=d; tr[now].hmx=max(tr[now].hmx,tr[now].mx); return ; } pushdown(now); if(r<=mid) add(lc,ql,mid,l,r,d); else if(mid+1<=l)add(rc,mid+1,qr,l,r,d); else add(lc,ql,mid,l,mid,d),add(rc,mid+1,qr,mid+1,r,d); update(now); } void change(int now,int ql,int qr,int l,int r,int d) { if(ql==l&&qr==r) { tr[now].merge(pa(0,d)); tr[now].mx=d; tr[now].la.cv=d,tr[now].la.ad=0; tr[now].hmx=max(tr[now].hmx,tr[now].mx); return ; } pushdown(now); if(r<=mid) change(lc,ql,mid,l,r,d); else if(mid+1<=l)change(rc,mid+1,qr,l,r,d); else change(lc,ql,mid,l,mid,d),change(rc,mid+1,qr,mid+1,r,d); update(now); } //.......change........ int findmax(int now,int ql,int qr,int l,int r,bool op) { if(ql==l&&qr==r)return op==1?tr[now].mx:tr[now].hmx; pushdown(now); if(r<=mid) return findmax(lc,ql,mid,l,r,op); else if(mid+1<=l)return findmax(rc,mid+1,qr,l,r,op); else return max(findmax(lc,ql,mid,l,mid,op),findmax(rc,mid+1,qr,mid+1,r,op)); } //........getans...... //~~~~~~~~~~~~~~~out~~~~~~~~~~~~~~~~~~~~~~ char ss[5]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a[i]); bt(1,1,n); int Q,x,y,d; scanf("%d",&Q); while(Q--) { scanf("%s",ss+1); if(ss[1]=='Q'||ss[1]=='A') { scanf("%d%d",&x,&y); printf("%d ",findmax(1,1,n,x,y,ss[1]=='Q')); } else { scanf("%d%d%d",&x,&y,&d); if(ss[1]=='P')add(1,1,n,x,y,d); else change(1,1,n,x,y,d); } } return 0; }