平衡树大巩固——part.2:序列处理
鉴于noip将近,我就把超纲的工作缩了一点水,本来要做一批题的,现在就只做了一个维护序列了:
这道题目恶心啊,不理一下思路怕写不出来:
由于是单旋splay,为了使操作方便,加了一个0节点和一个n + 1节点,由于0节点的特殊性,就把整个序列向右平移一个。
0:初始化
一开始读入初始数列时,要把它们加入树,就先把它们预处理成一颗平衡树就好,于是从这里开始有了一个函数build(pos, l, r)表示把l到r这段建树,以pos为当前树的根,递归处理即可,最后递归回来不要忘记更新标记。
1:插入
同样把读进来的数列先预处理成一颗平衡树,然后再把l这个节点splay到根,把l+1节点splay到l右边,此时l[r[root]]为空,直接把树接上去再维护标记吧。
2:删除
Getrange(pos, pos + tot – 1),此时就可以直接把r[l[root]]删掉再维护标记吧
3:修改
Getrange(pos, pos + tot – 1),把r[l[root]]的same标记更新即可
4:翻转
Getrange(pos, pos + tot – 1),把r[l[root]]的rese标记更新即可
5:求和
Getrange(pos, pos + tot – 1),输出r[l[root]]的sum信息
6:求最大子段和
输出r[l[root]]的submax信息
现在剩下的就是节点维护信息的确定,有smax,lmax,rmax,sum,还有标记sameflag,samenum,reserveflag;
现在麻烦的就是pushdown和update和rotate
Pushdown是每次深入节点的时候要做的,目的是将当前节点的lazy信息清空并维护
那么如果有sameflag,更新当前节点信息
否则再看是否有reserveflag,有的话交换左右子树,交换当前节点相关信息
将标记下传,将当前标记清空
Update是将当前节点的信息真实化的操作
Lmax[i] = max(lmax[ls[i]], lmax[rs[i]] + sum[ls[i]] + a[i], sum[ls[i]] + a[i])
Rmax[i] = max(rmax[rs[i]], rmax[ls[i]] + sum[rs[i]] + a[i], sum[rs[i]] + a[i])
Sum[i] = sum[ls[i]] + sum[rs[i]] + a[i]
Smax[i] = max(smax[l[i]], smax[r[i]], rmax[ls[i]] + a[i] + lmax[rs[i]])
Rotate需要利用update;
需要注意的是每次splay的时候标记下放需要把当前节点的子树的标记都下放,这个地方调理好久!
超丑的程序,还没写内存回收,不过速度倒还不错!
#include <stdio.h> const int nmax = 4000000, mmax = 20, oo = (~0U >> 3); struct typesplay { int sm[2], ms, chi[2], vue, sze, fsn, sum; bool fs, fr; }say[nmax + 18]; int n, m, tk, tl, tr, tkk; int root, tot; char str[mmax + 18]; int bot(int x) {return x > 0 ? x : 0;} int max(int a, int b) { return a > b ? a : b; } void update(int p) { tl = say[p].chi[0]; tr = say[p].chi[1]; tk = bot(say[tr].sm[0]); tkk = bot(say[tl].sm[1]); say[p].sze = say[tl].sze + say[tr].sze + 1; say[p].sm[0] = max(say[tl].sm[0], say[tl].sum + say[p].vue + tk); say[p].sm[1] = max(say[tr].sm[1], say[tr].sum + say[p].vue + tkk); say[p].sum = say[tr].sum + say[p].vue + say[tl].sum; say[p].ms = max(say[tl].ms, max(say[tr].ms, tk + say[p].vue + tkk)); } void rotate(int &p, int m) { int b = say[p].chi[!m]; say[p].chi[!m] = say[b].chi[m]; say[b].chi[m] = p; update(p); p = b; } void pushdown1(int p) { tk = say[p].fsn; tl = say[p].chi[0]; tr = say[p].chi[1]; say[p].vue = tk; if (tl) say[tl].fs = 1, say[tl].fsn = tk; if (tr) say[tr].fs = 1, say[tr].fsn = tk; say[p].sum = tk * say[p].sze; say[p].sm[0] = say[p].sm[1] = say[p].ms = tk > 0 ? tk * say[p].sze : tk; say[p].fs = 0; } void pushdown2(int p) { if (say[p].chi[0]) say[say[p].chi[0]].fr ^= 1; if (say[p].chi[1]) say[say[p].chi[1]].fr ^= 1; say[p].fr = 0; tk = say[p].sm[0]; say[p].sm[0] = say[p].sm[1]; say[p].sm[1] = tk; tk = say[p].chi[0]; say[p].chi[0] = say[p].chi[1]; say[p].chi[1] = tk; say[p].fr = 0; } void pushdownall(int p) { if (!p) return; if (say[p].fs) pushdown1(p); else if (say[p].fr) pushdown2(p); say[p].fs = say[p].fr = 0; } void pushdownsonall(int p) { pushdownall(say[p].chi[0]); pushdownall(say[p].chi[1]); } void splay(int &p, int l) { pushdownsonall(p); tk = say[say[p].chi[0]].sze + 1; if (tk > l) splay(say[p].chi[0], l), rotate(p, 1); else if (tk < l) splay(say[p].chi[1], l - tk), rotate(p, 0); } void splays(int &p, int l) { splay(p, l); update(p); } void getrange(int &rt, int pos, int len) { splays(rt, pos + 1); splays(say[rt].chi[1], len); } void build(int &i, int l, int r) { if (l > r) return; i = (l + r) >> 1; build(say[i].chi[0], l, i - 1); build(say[i].chi[1], i + 1, r); update(i); } int main() { freopen("sequence.in", "r", stdin); freopen("sequence.out", "w", stdout); scanf("%d%d", &n, &m); for (int i = 2; i <= n + 1; ++i) scanf("%d", &say[i].vue); say[0].vue = say[1].vue = say[n + 2].vue = -oo; say[1].sm[0] = say[1].sm[1] = say[1].ms = say[n + 2].sm[0] = say[n + 2].sm[1] = say[n + 2].ms = say[0].ms = say[1].ms = say[n + 2].ms = -oo; build(root, 1, tot = n + 2); for (int i = 1, l, pos, c; i <= m; ++i) { scanf("%s", str); if (str[2] == 'S') { scanf("%d%d", &pos, &l); int tmp = tot; while (l--) scanf("%d", &say[++tot].vue); build(l, tmp + 1, tot); getrange(root, pos, 1); say[say[root].chi[1]].chi[0] = l; update(say[root].chi[1]); update(root); } else if (str[2] == 'L') { scanf("%d%d", &pos, &l); getrange(root, pos - 1, l + 1); say[say[root].chi[1]].chi[0] = 0; update(say[root].chi[1]); update(root); } else if (str[2] == 'K') { scanf("%d%d%d", &pos, &l, &c); getrange(root, pos - 1, l + 1); say[say[say[root].chi[1]].chi[0]].fs = 1; say[say[say[root].chi[1]].chi[0]].fsn = c; pushdown1(say[say[root].chi[1]].chi[0]); update(say[root].chi[1]); update(root); } else if (str[2] == 'V') { scanf("%d%d", &pos, &l); getrange(root, pos - 1, l + 1); if (say[say[say[root].chi[1]].chi[0]].fr ^= 1) pushdown2(say[say[root].chi[1]].chi[0]); update(say[root].chi[1]); update(root); } else if (str[2] == 'T') { scanf("%d%d", &pos, &l); getrange(root, pos - 1, l + 1); printf("%d\n", say[say[say[root].chi[1]].chi[0]].sum); } else printf("%d\n", say[root].ms); } return 0; }