鉴于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;
}