题解:历史最值线段树
参见吉司机的论文
还是不熟,自己打打不出来
维护当前和历史两套标记,最大值,加法标记,减法标记
每到一个节点先pushdown(不知道为什么)
正确性不是很理解QWQ
还是自己太弱了
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100009; typedef long long Lint; const Lint inf=1000000000000000; int n,m; Lint a[maxn]; struct SegmentTree{ int l,r; Lint mx[2],tag[2],st[2]; }tree[maxn<<3]; void pushup(int now){ tree[now].mx[0]=max(tree[now<<1].mx[0],tree[now<<1|1].mx[0]); tree[now].mx[1]=max(tree[now<<1].mx[1],tree[now<<1|1].mx[1]); } void pushdown(int now){ int son; for(int i=0;i<=1;++i){ son=now<<1|i; tree[son].mx[0]=max(tree[son].mx[0],max(tree[now].st[0],tree[son].mx[1]+tree[now].tag[0])); if(tree[son].st[1]==-inf){ tree[son].tag[0]=max(tree[son].tag[0],tree[son].tag[1]+tree[now].tag[0]); }else{ tree[son].st[0]=max(tree[son].st[0],tree[son].st[1]+tree[now].tag[0]); } if(tree[now].tag[1]){ if(tree[son].st[1]!=-inf)tree[son].st[1]+=tree[now].tag[1]; else tree[son].tag[1]+=tree[now].tag[1]; tree[son].mx[1]+=tree[now].tag[1]; } if(tree[now].st[1]!=-inf){ tree[son].st[1]=tree[son].mx[1]=tree[now].st[1]; tree[son].tag[1]=0; } tree[son].st[0]=max(tree[son].st[0],max(tree[son].st[1],tree[now].st[0])); tree[son].tag[0]=max(tree[son].tag[0],tree[son].tag[1]); } tree[now].tag[0]=tree[now].tag[1]=0; tree[now].st[0]=tree[now].st[1]=-inf; } void BuildTree(int now,int l,int r){ tree[now].l=l;tree[now].r=r; tree[now].tag[0]=tree[now].tag[1]=0; tree[now].st[0]=tree[now].st[1]=-inf; if(l==r){ tree[now].mx[0]=tree[now].mx[1]=a[l]; return; } int mid=(l+r)>>1; BuildTree(now<<1,l,mid); BuildTree(now<<1|1,mid+1,r); pushup(now); } void Updatasec(int now,int ll,int rr,Lint x,int opty){ if(tree[now].l!=tree[now].r)pushdown(now); if(tree[now].l>=ll&&tree[now].r<=rr){ if(opty==0){ tree[now].mx[1]+=x;tree[now].tag[1]+=x;tree[now].tag[0]=x; }else{ tree[now].st[1]=tree[now].st[0]=tree[now].mx[1]=x; } tree[now].mx[0]=max(tree[now].mx[0],tree[now].mx[1]); return; } int mid=(tree[now].l+tree[now].r)>>1; if(ll<=mid)Updatasec(now<<1,ll,rr,x,opty); if(rr>mid)Updatasec(now<<1|1,ll,rr,x,opty); pushup(now); } Lint Querymax(int now,int ll,int rr,int opty){ if(tree[now].l!=tree[now].r)pushdown(now); if(tree[now].l>=ll&&tree[now].r<=rr){ return tree[now].mx[opty]; } Lint ans=-inf; int mid=(tree[now].l+tree[now].r)>>1; if(ll<=mid)ans=max(ans,Querymax(now<<1,ll,rr,opty)); if(rr>mid)ans=max(ans,Querymax(now<<1|1,ll,rr,opty)); return ans; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%lld",&a[i]); BuildTree(1,1,n); scanf("%d",&m); while(m--){ char opty=getchar(); while(opty<‘A‘||opty>‘Z‘)opty=getchar(); int l,r,x; scanf("%d%d",&l,&r); if(opty==‘Q‘)printf("%lld\n",Querymax(1,l,r,1)); if(opty==‘A‘)printf("%lld\n",Querymax(1,l,r,0)); if(opty==‘P‘){ scanf("%d",&x);Updatasec(1,l,r,x,0); } if(opty==‘C‘){ scanf("%d",&x);Updatasec(1,l,r,x,1); } } return 0; }