线段树·二重标记(什么鬼
用(a,b)标记表示先执行+a操作,然后对b取max,维护历史/当前最大值和历史/当前标记。然后我们发现区间加$x$就是$(x,-inf)$,区间赋$x$就是$(-inf,x)$。标记有两种更新,一种是和当前的标记合并,一种是更新历史标记。
把一个标记tag合并进当前标记ntag,显然新标记即
$(ntag.a+tag.a,max(ntag.b+tag.a,tag.b))$
把历史标记htag用一个标记tag更新更简单,其实就是对应取max
那么就可以做了:修改标记即先把当前标记和要加的标记合并,然后更新历史标记;修改最大值将当前最大值按标记意思改,然后历史最大值和当前最大值取max。下放标记类似
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=100005,inf=0x3f3f3f3f; 6 struct a 7 { 8 int ad,mx; 9 void init() 10 { 11 ad=0,mx=-inf; 12 } 13 }hist[4*N],nowt[4*N]; 14 a operator + (a x,a y) 15 { 16 return (a){max(-inf,x.ad+y.ad),max(x.mx+y.ad,y.mx)}; 17 } 18 a operator ^ (a x,a y) 19 { 20 return (a){max(x.ad,y.ad),max(x.mx,y.mx)}; 21 } 22 int seq[N],hmax[4*N],nmax[4*N]; 23 int n,m,t1,t2,t3; char str[10]; 24 void Pushup(int nde) 25 { 26 int ls=2*nde,rs=2*nde+1; 27 hmax[nde]=max(hmax[ls],hmax[rs]); 28 nmax[nde]=max(nmax[ls],nmax[rs]); 29 } 30 void Apply(int nde,int tsk) 31 { 32 hist[nde]=hist[nde]^(nowt[nde]+hist[tsk]); nowt[nde]=nowt[nde]+nowt[tsk]; 33 hmax[nde]=max(hmax[nde],max(nmax[nde]+hist[tsk].ad,hist[tsk].mx)); 34 nmax[nde]=max(nmax[nde]+nowt[tsk].ad,nowt[tsk].mx); 35 } 36 void Release(int nde) 37 { 38 int ls=2*nde,rs=2*nde+1; 39 Apply(ls,nde),Apply(rs,nde); 40 hist[nde].init(),nowt[nde].init(); 41 } 42 void Create(int nde,int l,int r) 43 { 44 hist[nde].init(),nowt[nde].init(); 45 if(l==r) 46 hmax[nde]=nmax[nde]=seq[l]; 47 else 48 { 49 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; 50 Create(ls,l,mid),Create(rs,mid+1,r); 51 Pushup(nde); 52 } 53 } 54 void Change(int nde,int l,int r,int nl,int nr,a tsk) 55 { 56 if(l>nr||r<nl) 57 return ; 58 else if(l>=nl&&r<=nr) 59 { 60 hist[nde]=hist[nde]^(nowt[nde]+tsk); nowt[nde]=nowt[nde]+tsk; 61 hmax[nde]=max(hmax[nde],max(nmax[nde]+tsk.ad,tsk.mx)); 62 nmax[nde]=max(nmax[nde]+tsk.ad,tsk.mx); 63 } 64 else 65 { 66 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde); 67 Change(ls,l,mid,nl,nr,tsk),Change(rs,mid+1,r,nl,nr,tsk); 68 Pushup(nde); 69 } 70 } 71 int Query(int nde,int l,int r,int nl,int nr,int typ) 72 { 73 if(l>nr||r<nl) 74 return -inf; 75 else if(l>=nl&&r<=nr) 76 return typ?nmax[nde]:hmax[nde]; 77 else 78 { 79 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde); 80 return max(Query(ls,l,mid,nl,nr,typ),Query(rs,mid+1,r,nl,nr,typ)); 81 } 82 } 83 int main() 84 { 85 scanf("%d",&n); 86 for(int i=1;i<=n;i++) 87 scanf("%d",&seq[i]); 88 Create(1,1,n),scanf("%d",&m); 89 for(int i=1;i<=m;i++) 90 { 91 scanf("%s%d%d",str,&t1,&t2); 92 if(str[0]=='Q') printf("%d\n",Query(1,1,n,t1,t2,1)); 93 else if(str[0]=='A') printf("%d\n",Query(1,1,n,t1,t2,0)); 94 else if(str[0]=='P') scanf("%d",&t3),Change(1,1,n,t1,t2,(a){t3,-inf}); 95 else if(str[0]=='C') scanf("%d",&t3),Change(1,1,n,t1,t2,(a){-inf,t3}); 96 } 97 return 0; 98 }