BZOJ 1500 维修数列
Description
Input
输入文件的第1行包含两个数N和M,N表示初始时数列中数的个数,M表示要进行的操作数目。第2行包含N个数字,描述初始时的数列。以下M行,每行一条命令,格式参见问题描述中的表格。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
Sample Input
9 8
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
2 -6 3 5 1 -5 -3 6 3
GET-SUM 5 4
MAX-SUM
INSERT 8 3 -5 7 2
DELETE 12 1
MAKE-SAME 3 3 2
REVERSE 3 6
GET-SUM 5 4
MAX-SUM
Sample Output
-1
10
1
10
10
1
10
HINT
Source
这题也是醉了~拍了两三天。。。看上去也就是个splay裸题。
最大字段和的维护:splay每个节点i记录从i的左子树最左起的最大字段和lb,右子树最右起的最大字段和rb,以及它所表示的整个区间的最大字段和。 lb[i]=max(lb[lc],sum[lc]+key[i]+lb[rc]),rb[i]=max(rb[rc],sum[rc]+key[i]+rb[lc]),wb[i]=max(wb[lc],wb[rc],rb[lc]+lb[rc]+key[i]),其中sum表示区间和,key表示该点的权值,lc与rc分别表示左右孩子。有许多细节请自己脑补。。。
1 #include<queue> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<cstdlib> 6 using namespace std; 7 8 #define maxn 500010 9 #define inf (1 << 20) 10 int n,m,TEMP[maxn],stack[maxn]; 11 queue <int> team; 12 13 inline int Max(int a,int b) {if (a > b) return a; return b;} 14 15 struct node 16 { 17 int fa[maxn],ch[maxn][2],key[maxn],sum[maxn],lm[maxn],rm[maxn],wm[maxn],size[maxn],cnt,root; 18 bool rev[maxn],change[maxn]; 19 20 inline int newnode() 21 { 22 if (team.empty()) return ++cnt; 23 int ret = team.front(); team.pop(); 24 return ret; 25 } 26 27 inline void updata(int a) 28 { 29 int lc = ch[a][0],rc = ch[a][1]; 30 pushdown(a); pushdown(lc); pushdown(rc); 31 size[a] = size[lc] + size[rc] + 1; 32 { 33 sum[a] = sum[lc] + sum[rc] + key[a]; 34 lm[a] = rm[a] = wm[a] = -inf; 35 lm[a] = Max(lm[a],sum[lc]+key[a]); 36 lm[a] = Max(lm[a],sum[lc]+lm[rc]+key[a]); 37 if (lc) lm[a] = Max(lm[a],lm[lc]); 38 rm[a] = Max(rm[a],sum[rc]+key[a]); 39 rm[a] = Max(rm[a],sum[rc]+rm[lc]+key[a]); 40 if (rc) rm[a] = Max(rm[a],rm[rc]); 41 wm[a] = Max(lm[a],rm[a]); 42 wm[a] = Max(wm[a],rm[lc]+lm[rc]+key[a]); 43 wm[a] = Max(wm[a],key[a]); 44 wm[a] = Max(wm[a],rm[lc]+key[a]); 45 wm[a] = Max(wm[a],lm[rc]+key[a]); 46 if (rc) wm[a] = Max(wm[a],Max(lm[rc],wm[rc])); 47 if (lc) wm[a] = Max(wm[a],Max(rm[lc],wm[lc])); 48 } 49 } 50 51 inline void pushdown(int a) 52 { 53 if (a == 0) { rev[a] = false; change[a] = false; return; } 54 else 55 { 56 int lc = ch[a][0],rc = ch[a][1]; 57 if (rev[a]) 58 { 59 rev[a] = false; 60 swap(lm[a],rm[a]); swap(ch[a][0],ch[a][1]); 61 if (lc) rev[lc] ^= 1; if (rc) rev[rc] ^= 1; 62 } 63 if (change[a]) 64 { 65 change[a] = false; 66 if (lc) key[lc] = key[a],change[lc] = true; 67 if (rc) key[rc] = key[a],change[rc] = true; 68 sum[a] = key[a] * size[a]; 69 if (key[a] >= 0) wm[a] = lm[a] = rm[a] = sum[a]; 70 else wm[a] = lm[a] = rm[a] = key[a]; 71 } 72 } 73 } 74 75 inline int find(int rank,int have,int now) 76 { 77 pushdown(now); 78 if (have+size[ch[now][0]]+1==rank) return now; 79 if (have+size[ch[now][0]]+1>rank) return find(rank,have,ch[now][0]); 80 else return find(rank,have+size[ch[now][0]]+1,ch[now][1]); 81 } 82 83 inline void rotate(int x) 84 { 85 int y = fa[x],z = fa[y],l,r; 86 if (ch[y][0] == x) l = 0; else l = 1; r = l ^ 1; 87 if (z != 0) 88 { 89 if (ch[z][0] == y) ch[z][0] = x; else ch[z][1] = x; 90 } 91 fa[x] = z; fa[y] = x; fa[ch[x][r]] = y; 92 ch[y][l] = ch[x][r]; ch[x][r] = y; 93 updata(y); updata(x); 94 } 95 96 inline void splay(int x,int aim) 97 { 98 int t = fa[aim],top = 0; 99 for (int i = x;i != t;i = fa[i]) stack[++top] = i; 100 while (top) pushdown(stack[top--]); 101 while (fa[x] != t) 102 { 103 int y = fa[x],z = fa[y]; 104 if (fa[y] != t) 105 { 106 if ((ch[y][0] == x)^(ch[z][0] == y)) rotate(x); 107 else rotate(y); 108 } 109 rotate(x); 110 } 111 if (aim == root) root = x; 112 } 113 114 inline int build(int l,int r) 115 { 116 int now = newnode(),mid = (l + r) >> 1; 117 ch[now][0] = ch[now][1] = 0; 118 rev[now] = change[now] = false; 119 if (l == r) 120 { 121 key[now] = TEMP[l]; updata(now); 122 return now; 123 } 124 if (l < mid) 125 { 126 ch[now][0] = build(l,mid - 1); 127 fa[ch[now][0]] = now; 128 } 129 if (mid < r) 130 { 131 ch[now][1] = build(mid + 1,r); 132 fa[ch[now][1]] = now; 133 } 134 key[now] = TEMP[mid]; 135 updata(now); 136 return now; 137 } 138 139 inline void init(int l,int r) 140 { 141 root = build(l,r); int p; 142 p = find(n,0,root); 143 splay(p,root); 144 key[++cnt] = -inf; 145 fa[cnt] = p; ch[p][1] = cnt; 146 updata(cnt); updata(p); 147 p = find(1,0,root); 148 splay(p,root); 149 key[++cnt] = -inf; 150 fa[cnt] = p; ch[p][0] = cnt; 151 updata(cnt); updata(p); 152 } 153 154 inline void insert(int a,int b) 155 { 156 int p = find(a + 1,0,root),q = find(a + 2,0,root); 157 splay(p,root); splay(q,ch[p][1]); 158 int tr = build(1,b); 159 fa[tr] = q; ch[q][0] = tr; 160 updata(q); updata(p); 161 } 162 163 inline void rec(int now) 164 { 165 if (now == 0) return; 166 team.push(now); 167 rec(ch[now][0]); rec(ch[now][1]); 168 } 169 170 inline void del(int a,int b) 171 { 172 int p = find(a,0,root),q = find(a+b+1,0,root); 173 splay(p,root); splay(q,ch[p][1]); 174 rec(ch[q][0]); 175 fa[ch[q][0]] = 0; ch[q][0] = 0; 176 updata(q); updata(p); 177 } 178 179 inline void reverse(int a,int b) 180 { 181 int p = find(a,0,root),q = find(a+b+1,0,root); 182 splay(p,root); splay(q,ch[p][1]); 183 rev[ch[q][0]] ^= 1; pushdown(ch[q][0]); 184 updata(q); updata(p); 185 } 186 187 inline int getsum(int a,int b) 188 { 189 int p = find(a,0,root),q = find(a+b+1,0,root); 190 splay(p,root); splay(q,ch[p][1]); 191 return sum[ch[q][0]]; 192 } 193 194 inline int maxsum() { updata(root); return wm[root];} 195 196 inline void modify(int a,int b,int c) 197 { 198 int p = find(a,0,root),q = find(a+b+1,0,root); 199 splay(p,root); splay(q,ch[p][1]); 200 key[ch[q][0]] = c; change[ch[q][0]] = true; 201 pushdown(ch[q][0]); 202 updata(ch[q][0]); updata(q); updata(p); 203 return; 204 } 205 }tree; 206 207 inline int read() 208 { 209 int x=0,f=1;char ch=getchar(); 210 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 211 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 212 return x*f; 213 } 214 215 int main() 216 { 217 freopen("1500.in","r",stdin); 218 freopen("1500.out","w",stdout); 219 n = read(); m = read(); 220 for (int i = 1;i <= n;++i) TEMP[i] = read(); 221 tree.init(1,n); 222 char opt[20]; 223 while (m--) 224 { 225 scanf("%s",opt); 226 if (opt[0] == 'I') 227 { 228 int a = read(),b = read(); 229 for (int i = 1;i <= b;++i) TEMP[i] = read(); 230 tree.insert(a,b); 231 } 232 else if (opt[0] == 'D') 233 { 234 int a = read(),b =read(); 235 tree.del(a,b); 236 } 237 else if (opt[0] == 'R') 238 { 239 int a = read(),b = read(); 240 tree.reverse(a,b); 241 } 242 else if (opt[0] == 'G') 243 { 244 int a = read(),b = read(); 245 printf("%d\n",tree.getsum(a,b)); 246 } 247 else if (opt[0] == 'M'&&opt[2] == 'K') 248 { 249 int a = read(),b = read(),c = read(); 250 tree.modify(a,b,c); 251 } 252 else printf("%d\n",tree.maxsum()); 253 } 254 fclose(stdin); fclose(stdout); 255 return 0; 256 }
高考结束,重新回归。