平衡树大巩固——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;
}

  

posted @ 2011-10-31 22:04  Neroysq  阅读(301)  评论(0编辑  收藏  举报