n<=100000的数列支持以下操作:一、区间加;二、区间赋值;三、查区间最大;四、查区间历史版本最大。
恶心死我了。。可能很水,但我调了半天。
错误!调了两天。
这里有一个棘手问题:历史版本。
首先不看赋值操作。记俩标记——区间加add和区间历史加标记pre。其中后者的含义是“从上一次这个区间标记下传到现在,区间加(前者)标记的最大值”。这样,比如某点i的标记下传给儿子x,标记如此叠加:$pre_x>?=pre_i+add_x$,$add_x+=add_i$,同时更新区间历史版本最大值:$his_x>?=Max_x+pre_x-add_x$。
然后加入赋值操作。可以发现一个区间在标记下传前只有两个阶段:一开始只有加标记,后来只有赋值标记:打上赋值标记后,如果该区间还要加,相当于更新赋值标记。因此,分两种历史标记来搞,一个记第一阶段的$add$的最大值,一个记第二阶段$be$的最大值。下传时注意顺序。
关键点截图留念:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<math.h> 6 //#include<complex> 7 //#include<ctime> 8 #include<algorithm> 9 using namespace std; 10 11 int n,m; 12 #define maxn 100011 13 const int inf=0x3f3f3f3f; 14 int num[maxn]; 15 struct SMT 16 { 17 struct Node 18 { 19 int ls,rs; 20 int add,pa,be,pb; 21 int Max,pmax; 22 }a[maxn<<1]; 23 int size,root; 24 SMT() {size=root=0; a[0].Max=a[0].pmax=-inf;} 25 void up(int x,int L,int R) 26 { 27 int &p=a[x].ls,&q=a[x].rs; 28 a[x].Max=max(a[p].Max,a[q].Max); 29 a[x].pmax=max(a[p].pmax,a[q].pmax); 30 } 31 void addsingle(int x,int L,int R,int v,int pv) 32 { 33 if (a[x].be!=-inf) 34 {besingle(x,L,R,a[x].be+v,a[x].be+pv); return;} 35 a[x].pa=max(a[x].pa,a[x].add+pv),a[x].add+=v; 36 a[x].Max+=v; a[x].pmax=max(a[x].pmax,a[x].pa+a[x].Max-a[x].add); 37 } 38 void besingle(int x,int L,int R,int v,int pv) 39 { 40 a[x].pb=max(a[x].pb,pv); a[x].add=0; a[x].be=v; 41 a[x].Max=v; a[x].pmax=max(a[x].pmax,a[x].pb); 42 } 43 void down(int x,int L,int R) 44 { 45 int &p=a[x].ls,&q=a[x].rs,mid=(L+R)>>1; 46 if (a[x].add || a[x].pa) 47 addsingle(p,L,mid,a[x].add,a[x].pa),addsingle(q,mid+1,R,a[x].add,a[x].pa),a[x].add=a[x].pa=0; 48 if (a[x].be!=-inf || a[x].pb!=-inf) 49 besingle(p,L,mid,a[x].be,a[x].pb),besingle(q,mid+1,R,a[x].be,a[x].pb),a[x].be=a[x].pb=-inf; 50 } 51 void build(int &x,int L,int R) 52 { 53 x=++size; 54 a[x].add=a[x].pa=0; a[x].be=a[x].pb=-inf; 55 if (L==R) {a[x].ls=a[x].rs=0; a[x].Max=a[x].pmax=num[L];return;} 56 int mid=(L+R)>>1; 57 build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x,L,R); 58 } 59 void build() {build(root,1,n);} 60 int ql,qr,v; 61 void Add(int &x,int L,int R) 62 { 63 if (ql<=L && R<=qr) {addsingle(x,L,R,v,v); return;} 64 down(x,L,R); 65 int mid=(L+R)>>1; 66 if (ql<=mid) Add(a[x].ls,L,mid); 67 if (qr> mid) Add(a[x].rs,mid+1,R); 68 up(x,L,R); 69 } 70 void add(int L,int R,int v) 71 { 72 ql=L; qr=R; this->v=v; 73 Add(root,1,n); 74 } 75 void Be(int &x,int L,int R) 76 { 77 if (ql<=L && R<=qr) {besingle(x,L,R,v,v); return;} 78 down(x,L,R); 79 int mid=(L+R)>>1; 80 if (ql<=mid) Be(a[x].ls,L,mid); 81 if (qr> mid) Be(a[x].rs,mid+1,R); 82 up(x,L,R); 83 } 84 void be(int L,int R,int v) 85 { 86 ql=L; qr=R; this->v=v; 87 Be(root,1,n); 88 } 89 int Qmax(int &x,int L,int R) 90 { 91 if (ql<=L && R<=qr) return a[x].Max; 92 down(x,L,R); 93 int mid=(L+R)>>1,ans=-inf; 94 if (ql<=mid) ans=Qmax(a[x].ls,L,mid); 95 if (qr> mid) ans=max(ans,Qmax(a[x].rs,mid+1,R)); 96 return ans; 97 } 98 int qmax(int L,int R) 99 { 100 ql=L; qr=R; 101 return Qmax(root,1,n); 102 } 103 int Qpmax(int &x,int L,int R) 104 { 105 if (ql<=L && R<=qr) return a[x].pmax; 106 down(x,L,R); 107 int mid=(L+R)>>1,ans=-inf; 108 if (ql<=mid) ans=Qpmax(a[x].ls,L,mid); 109 if (qr> mid) ans=max(ans,Qpmax(a[x].rs,mid+1,R)); 110 return ans; 111 } 112 int qpmax(int L,int R) 113 { 114 ql=L; qr=R; 115 return Qpmax(root,1,n); 116 } 117 }t; 118 119 int main() 120 { 121 scanf("%d",&n); 122 for (int i=1;i<=n;i++) scanf("%d",&num[i]); 123 t.build(); 124 125 scanf("%d",&m); 126 int x,y,z; char id; 127 while (m--) 128 { 129 while ((id=getchar())<‘A‘ || id>‘Z‘); 130 if (id==‘A‘) scanf("%d%d",&x,&y),printf("%d\n",t.qpmax(x,y)); 131 else if (id==‘Q‘) scanf("%d%d",&x,&y),printf("%d\n",t.qmax(x,y)); 132 else if (id==‘P‘) scanf("%d%d%d",&x,&y,&z),t.add(x,y,z); 133 else scanf("%d%d%d",&x,&y,&z),t.be(x,y,z); 134 } 135 return 0; 136 }