【bzoj1500】[NOI2005]维修数列
题目描述:
输入:
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
输出:
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
样例输入:
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
样例输出:
-1
10
1
10
题解:
splay果体。
immortalCO:用treap更快,而且还更好写。
反正这题机房里的其他神犇都是1A+差不多1h写完的,而我蒟蒻调了整整三天才调出来。QAQ
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #else #define debug(...) #endif #define R register #define getc() (S == T&&(T = (S = B) + fread(B, 1, 1<<15, stdin), S == T)?EOF: * S ++ ) #define gmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define gmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1<<15], * S = B, * T = B; inline int FastIn() { R char ch;R int cnt = 0;R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ?minus = 1:cnt = ch-'0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus?-cnt:cnt; } #define maxn 1000010 int fa[maxn], ch[maxn][2], a[maxn], size[maxn], cnt; int sum[maxn], lmx[maxn], rmx[maxn], mx[maxn], v[maxn], id[maxn], root; bool rev[maxn], tag[maxn]; inline void swap(int &a, int &b) { R int tmp = a;a = b;b = tmp; } inline void update(R int x) { R int ls = ch[x][0], rs = ch[x][1]; size[x] = size[ls] + size[rs] + 1; sum[x] = sum[ls] + sum[rs] + v[x]; mx[x] = gmax(mx[ls], mx[rs]); cmax(mx[x], lmx[rs] + rmx[ls] + v[x]); lmx[x] = gmax(lmx[ls], sum[ls] + v[x] + lmx[rs]); rmx[x] = gmax(rmx[rs], sum[rs] + v[x] + rmx[ls]); } inline void pushdown(R int x) { R int ls = ch[x][0], rs = ch[x][1]; if (tag[x]) { rev[x] = tag[x] = 0; if (ls) tag[ls] = 1, v[ls] = v[x], sum[ls] = size[ls] * v[x]; if (rs) tag[rs] = 1, v[rs] = v[x], sum[rs] = size[rs] * v[x]; if (v[x]>= 0) { if (ls) lmx[ls] = rmx[ls] = mx[ls] = sum[ls]; if (rs) lmx[rs] = rmx[rs] = mx[rs] = sum[rs]; } else { if (ls) lmx[ls] = rmx[ls] = 0, mx[ls] = v[x]; if (rs) lmx[rs] = rmx[rs] = 0, mx[rs] = v[x]; } } if (rev[x]) { rev[x] ^= 1; rev[ls] ^= 1; rev[rs] ^= 1; swap(lmx[ls], rmx[ls]);swap(lmx[rs], rmx[rs]); swap(ch[ls][0], ch[ls][1]); swap(ch[rs][0], ch[rs][1]); } } inline void rotate(R int x) { R int f = fa[x], gf = fa[f], d = ch[f][1] == x; if (f == root) root = x; (ch[f][d] = ch[x][d ^ 1]) > 0 ? fa[ch[f][d]] = f : 0; (fa[x] = gf) > 0 ? ch[gf][ch[gf][1] == f] = x : 0; fa[ch[x][d ^ 1] = f] = x; update(f); } inline void splay(R int x, R int rt) { while (fa[x] != rt) { R int f = fa[x], gf = fa[f]; if (gf != rt) rotate((ch[gf][1] == f) ^ (ch[f][1] == x) ? x : f); rotate(x); } update(x); } void build(R int l, R int r, R int rt) { if (l > r) return ; R int mid = l + r >> 1, now = id[mid], last = id[rt]; if (l == r) { sum[now] = a[l]; size[now] = 1; tag[now] = rev[now] = 0; if (a[l] >= 0) lmx[now] = rmx[now] = mx[now] = a[l]; else lmx[now] = rmx[now] = 0, mx[now] = a[l]; } else { build(l, mid - 1, mid); build(mid + 1, r, mid); } v[now] = a[mid]; fa[now] = last; update(now); ch[last][mid >= rt] = now; } int find(R int x, R int rank) { if (tag[x] || rev[x]) pushdown(x); R int ls = ch[x][0], rs = ch[x][1], lsize = size[ls]; if (lsize + 1 == rank) return x; if (lsize >= rank) return find(ls, rank); else return find(rs, rank - lsize - 1); } inline int prepare(R int l, R int tot) { R int x = find(root, l - 1), y = find(root, l + tot); splay(x, 0); splay(y, x); return ch[y][0]; } std::queue <int> q; inline void Insert(R int left, R int tot) { for (R int i = 1; i <= tot; ++i ) a[i] = FastIn(); for (R int i = 1; i <= tot; ++i ) if (!q.empty()) id[i] = q.front(), q.pop(); else id[i] = ++cnt; build(1, tot, 0); R int z = id[(1 + tot) >> 1]; R int x = find(root, left), y = find(root, left + 1); splay(x, 0); splay(y, x); fa[z] = y; ch[y][0] = z; update(y); update(x); } void rec(R int x) { if (!x) return ; R int ls = ch[x][0], rs = ch[x][1]; rec(ls); rec(rs); q.push(x); fa[x] = ch[x][0] = ch[x][1] = 0; tag[x] = rev[x] = 0; } inline void Delete(R int l, R int tot) { R int x = prepare(l, tot), f = fa[x]; rec(x); ch[f][0] = 0; update(f); update(fa[f]); } inline void Makesame(R int l, R int tot, R int val) { R int x = prepare(l, tot), y = fa[x]; v[x] = val; tag[x] = 1; sum[x] = size[x] * val; if (val >= 0) lmx[x] = rmx[x] = mx[x] = sum[x]; else lmx[x] = rmx[x] = 0, mx[x] = val; update(y); update(fa[y]); } inline void Reverse(R int l, R int tot) { R int x = prepare(l, tot), y = fa[x]; if (!tag[x]) { rev[x] ^= 1; swap(ch[x][0], ch[x][1]); swap(lmx[x], rmx[x]); update(y); update(fa[y]); } } inline void Query(R int l, R int tot) { R int x = prepare(l, tot); printf("%d\n",sum[x] ); } #define inf ((1 << 30)) int main() { R int n = FastIn(), m = FastIn(), l, tot, val; R char op, op2; mx[0] = a[1] = a[n + 2] = -inf; for (R int i = 2; i <= n + 1; i++ ) { a[i] = FastIn(); } for (R int i = 1; i <= n + 2; ++i) id[i] = i; n += 2; cnt = n; root = (n + 1) >> 1; build(1, n, 0); for (R int i = 1; i <= m; i++ ) { op = getc(); while (op < 'A' || op > 'Z') op = getc(); getc(); op2 = getc();getc();getc();getc();getc(); if (op == 'M' && op2 == 'X') { printf("%d\n",mx[root] ); } else { l = FastIn() + 1; tot = FastIn(); if (op == 'I') Insert(l, tot); if (op == 'D') Delete(l, tot); if (op == 'M') val = FastIn(), Makesame(l, tot, val); if (op == 'R') Reverse(l, tot); if (op == 'G') Query(l, tot); } } return 0; } /* 9 14 2 -6 3 5 1 -5 -3 6 3 GET-SUM 5 4 MAX-SUM INSERT 8 3 -5 7 2 GET-SUM 8 4 MAX-SUM DELETE 12 1 GET-SUM 8 4 MAX-SUM MAKE-SAME 3 3 2 GET-SUM 5 4 MAX-SUM REVERSE 3 6 GET-SUM 5 4 MAX-SUM */