BZOJ 1500: [NOI2005] 维修数列
Input
输入的第 1 行包含两个数 N 和 M(M ≤20 000),N 表示初始时数列中数的个数,M 表示要进行的操作数目。
第 2 行包含 N 个数字,描述初始时的数列。
以下 M 行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有 500 000 个数,数列中任何一个数字均在 [-1 000, 1 000] 内。
插入的数字总数不超过 4 000 000 个,输入文件大小不超过 20MBytes。
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
传说中巨变态的一道题。。。调了一下午终于AC了。。。模板:Orz神犇黄学长 @hzwer
血的教训:
边界值一定要初始化!边界值一定要初始化!边界值一定要初始化!重要的事情说三遍!
放代码:
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAXN = 1000005, INF = 0x3f3f3f3f; int N, M, root, spa[MAXN], top, A[MAXN], id[MAXN], tot; int rd(){ int x=0, f=0, ch = getchar(); while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}; while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}; return f?-x:x; } struct SplayTree{ int fa[MAXN], ch[MAXN][2]; int v[MAXN], sz[MAXN], sum[MAXN], lx[MAXN], rx[MAXN], mx[MAXN]; int cov[MAXN], rev[MAXN]; void trace(){ printf("root=%d, tot=%d\n", root, tot); for(int i = 0; i <= N+2; ++i){ printf("%d: ", i); printf("fa=%d, ch[0]=%d, ch[1]=%d, v=%d, sz=%d,\n", fa[i], ch[i][0], ch[i][1], v[i], sz[i]); printf("sum=%d, lx=%d, rx=%d, mx=%d, cov=%d, rev=%d;\n", sum[i], lx[i], rx[i], mx[i], cov[i], rev[i]); } } void dfs(int x){ if(x == 0) return; dfs(ch[x][0]); if(v[x] != -INF)printf("%d ", v[x]); dfs(ch[x][1]); } void pushup(int x){ int l = ch[x][0], r = ch[x][1]; sz[x] = 1 + sz[l] + sz[r]; sum[x] = v[x] + sum[l] + sum[r]; lx[x] = max(lx[l], sum[l] + v[x] + lx[r]); rx[x] = max(rx[r], sum[r] + v[x] + rx[l]); mx[x] = max(rx[l] + v[x] + lx[r], max(mx[l], mx[r])); } void pushdown(int x){ int l = ch[x][0], r = ch[x][1]; if(cov[x] != INF){ if(l){ v[l] = cov[x]; sum[l] = sz[l] * cov[x]; lx[l] = rx[l] = cov[x] > 0 ? sum[l] : 0; mx[l] = cov[x] > 0 ? sum[l] : cov[x]; cov[l] = cov[x]; rev[l] = 0; } if(r){ v[r] = cov[x]; sum[r] = sz[r] * cov[x]; lx[r] = rx[r] = cov[x] > 0 ? sum[r] : 0; mx[r] = cov[x] > 0 ? sum[r] : cov[x]; cov[r] = cov[x]; rev[r] = 0; } cov[x] = INF; rev[x] = 0; } else if(rev[x]){ rev[l] ^= 1; rev[r] ^= 1; rev[x] = 0; swap(lx[l], rx[l]); swap(lx[r], rx[r]); swap(ch[l][0], ch[l][1]); swap(ch[r][0], ch[r][1]); } } void rot(int x, int &k){ int y = fa[x], z = fa[y], l = ch[y][1] == x, r = l ^ 1; if(y == k) k = x; else ch[z][ch[z][1] == y] = x; fa[ch[x][r]] = y; fa[y] = x; fa[x] = z; ch[y][l] = ch[x][r]; ch[x][r] = y; pushup(y); pushup(x); } void splay(int x, int &k){ while(x != k){ int y = fa[x], z = fa[y]; if(y != k){ if((ch[y][1] == x) ^ (ch[z][1] == y)) rot(x, k); else rot(y, k); } rot(x, k); } } int srch(int x, int k){ pushdown(x); int l = ch[x][0], r = ch[x][1]; if(k == sz[l] + 1) return x; if(k <= sz[l]) return srch(l, k); return srch(r, k - sz[l] - 1); } int &split(int k, int t){ int x = srch(root, k), y = srch(root, k + t + 1); splay(x, root); splay(y, ch[x][1]); return ch[y][0]; } void build(int &x, int f, int L, int R){ if(L > R) return; if(L == R){ x = id[L]; fa[x] = f; v[x] = sum[x] = mx[x] = A[L]; sz[x] = 1; cov[x] = INF; rev[x] = 0; if(A[L] > 0) lx[x] = rx[x] = A[L]; else lx[x] = rx[x] = 0; return; } int mid = (L + R) >> 1; x = id[mid]; fa[x] = f; v[x] = A[mid]; cov[x] = INF; rev[x] = 0; build(ch[x][0], x, L, mid-1); build(ch[x][1], x, mid+1, R); pushup(x); } void ins(){ int k = rd(), t = rd(), x, y; for(int i = 1; i <= t; ++i){ A[i] = rd(); id[i] = top ? spa[--top] : ++tot; } x = srch(root, k+1), y = srch(root, k+2); splay(x, root); splay(y, ch[x][1]); build(ch[y][0], y, 1, t); pushup(y); pushup(x); } void rec(int x){ if(!x) return; rec(ch[x][0]); rec(ch[x][1]); fa[x] = ch[x][0] = ch[x][1] = 0; cov[x] = INF; rev[x] = 0; spa[top++] = x; } void del(){ int k = rd(), t = rd(); int &x = split(k, t), y = fa[x]; rec(x); x = 0; pushup(y); pushup(fa[y]); } void modify(){ int k = rd(), t = rd(), c = rd(); int &x = split(k, t), y = fa[x]; cov[x] = v[x] = c; sum[x] = c * sz[x]; rev[x] = 0; if(c < 0){ lx[x] = rx[x] = 0; mx[x] = c; }else{ lx[x] = rx[x] = mx[x] = sum[x]; } pushup(y); pushup(fa[y]); } void rever(){ int k = rd(), t = rd(); int x = split(k, t), y = fa[x]; rev[x] ^= 1; swap(ch[x][0], ch[x][1]); swap(lx[x], rx[x]); pushup(y); pushup(fa[y]); } void gsum(){ int k = rd(), t = rd(); if(t == 0){printf("0\n"); return; } int x = split(k, t); printf("%d\n", sum[x]); } void gmax(){ printf("%d\n", mx[root]); } }spt; char opt[128]; int main(){ freopen("sequence9.in", "r", stdin); freopen("my.txt", "w", stdout); scanf("%d%d", &N, &M); for(int i = 2; i <= N + 1; ++i){ A[i] = rd(); id[i] = ++tot; } spt.mx[0] = A[1] = A[N+2] = -INF; id[1] = ++tot; id[N+2] = ++tot; //重要! spt.build(root, 0, 1, N+2); memset(spt.cov, 0x3f, sizeof(spt.cov)); for(int i = 1; i <= M; ++i){ // spt.trace(); // spt.dfs(root); putchar('\n'); scanf("%s", opt); // printf("%d: %s %d\n", i, opt, spt.sz[root]); switch(opt[0]){ case 'I': spt.ins(); break; case 'D': spt.del(); break; case 'R': spt.rever(); break; case 'G': spt.gsum(); break; case 'M': if(opt[2] == 'K'){ spt.modify(); }else{ spt.gmax(); } break; } } return 0; }
退役