【NOI2005】【splay】维护数列

来源:互联网 发布:临床医学生必备软件 编辑:程序博客网 时间:2024/05/18 01:49

这题貌似比operation还要恶心一点。。。

为了练习splay硬着头皮写的虽然现在AC了但我还是完全没有信心能够在考场上写出来,细节太多下面进入正题

1、最大序列和的询问,仿照线段树,需要维护Max,Maxl,Maxr,sum这几个量,在上传的时候更新。

2、由于内存限制,需要回收内存的操作,就是将下标回收进入一个数组,具体见代码

3、标记要向下传递两层(Ps:这个我也不知道为什么,我在这里卡了很久)

4、两个虚拟节点以及Max的初始值为-inf

5、不要将lazy标记与lazy标记的值合并,多开一个bool来标记

这道题的trick暂时就想到这些,至于其他的操作就与一般的splay维护数列的题无异了。

代码

#include<cstdio>#include<algorithm>#include<cstring>#define keyTree ch[ ch[root][1] ][0]using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 550000 + 10;const int bh = maxn - 10;struct SplayTree{    int ch[maxn][2],pre[maxn],num[maxn];    int ss[maxn],que[maxn];    int val[maxn],sum[maxn],sz[maxn];    int Maxl[maxn],Maxr[maxn],Max[maxn];    int lazy[maxn];    bool reserve[maxn],same[maxn];    int root,top1,top2;    int max(int a,int b)    {        return a > b ? a : b;    }    int max(int a,int b,int c)    {        return max(max(a,b),c);    }    void swap(int &a,int &b)    {        int t = a;a = b;b = t;    }    void push_up(int x)    {        sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;        sum[x] = val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];        Maxl[x] = max(Maxl[ ch[x][0] ],sum[ ch[x][0] ] + val[x] + max(0,Maxl[ ch[x][1] ]));        Maxr[x] = max(Maxr[ ch[x][1] ],sum[ ch[x][1] ] + val[x] + max(0,Maxr[ ch[x][0] ]));        Max[x] = max(Max[ ch[x][0] ],Max[ ch[x][1] ],val[x]);        Max[x] = max(Max[x],max(Maxr[ ch[x][0] ],Maxl[ ch[x][1] ]) + val[x]);        Max[x] = max(Max[x],Maxr[ ch[x][0] ] + val[x] + Maxl[ ch[x][1] ]);    }void deal1(int x,int tmp){same[x] = true,lazy[x] = tmp;sum[x] = tmp * sz[x];Max[x] = Maxl[x] = Maxr[x] = max(sum[x],tmp);}    void deal2(int x)    {        reserve[x] = !reserve[x];        swap(Maxl[x],Maxr[x]);    }    void push_down(int x)    {        if(same[x])        {val[x] = lazy[x];if(ch[x][0])deal1(ch[x][0],lazy[x]);if(ch[x][1])deal1(ch[x][1],lazy[x]);same[x] = reserve[x] = false;        }        if(reserve[x])        {            swap(ch[x][0],ch[x][1]);            swap(Maxl[x],Maxr[x]);            if(ch[x][0])deal2(ch[x][0]);            if(ch[x][1])deal2(ch[x][1]);            reserve[x] = false;        }    }    void Rotate(int x,int f)    {        int y = pre[x];        push_down(y);push_down(x);        ch[y][!f] = ch[x][f];        pre[ ch[x][f] ] = y;        pre[x] = pre[y];        if(pre[x])ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;        ch[x][f] = y;        pre[y] = x;        push_up(y);    }    void Splay(int x,int goal)    {        push_down(x);        while(pre[x] != goal)        {            if(pre[pre[x]] == goal)Rotate(x, ch[pre[x]][0] == x);            else            {                int y = pre[x],z = pre[y];                int f = (ch[z][0] == y);                if(ch[y][f] == x)Rotate(x,!f),Rotate(x,f);                else Rotate(y,f),Rotate(x,f);            }        }        push_up(x);        if(goal == 0)root = x;    }    void RotateTo(int k,int goal)    {        int x = root;        push_down(x);        while(sz[ ch[x][0] ] != k)        {            if(k < sz[ ch[x][0] ])x = ch[x][0];            else            {                k -= (sz[ ch[x][0] ] + 1);                x = ch[x][1];            }            push_down(x);        }        Splay(x,goal);    }    void Newnode(int &x,int c)    {        if(top2)x = ss[--top2];        else x = ++top1;        ch[x][0] = ch[x][1] = pre[x] = 0;        sz[x] = 1;        lazy[x] = 0;        reserve[x] = same[x] = false;        val[x] = sum[x] = c;        Maxl[x] = Maxr[x] = Max[x] = c;    }    void makeTree(int &x,int l,int r,int f,int *p)    {        if(l > r)return;        int m = (l + r) >> 1;        Newnode(x,p[m]);        makeTree(ch[x][0],l , m - 1,x,p);        makeTree(ch[x][1],m + 1 , r,x,p);        pre[x] = f;        push_up(x);    }    void erase(int x)    {        int father = pre[x];        int head = 0,tail = 0;        for(que[tail++] = x;head < tail;head ++)        {            ss[top2++] = que[head];            if(ch[ que[head] ][0])que[tail++] = ch[ que[head] ][0];            if(ch[ que[head] ][1])que[tail++] = ch[ que[head] ][1];        }        ch[ father ][ ch[father][1] == x ] = 0;        push_up(father);     }    void init(int n)    {memset(Max,~0x3f,sizeof(Max));        ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;        root = top1 = top2 = 0;        Newnode(root,-inf);        Newnode(ch[root][1],-inf);        pre[ch[root][1]] = root;        sz[root] = 2;        for(int i = 1;i <= n;i++)scanf("%d",&num[i]);        makeTree(keyTree,1,n,ch[root][1],num);        push_up(ch[root][1]);        push_up(root);    }    void ins(int pos,int tot,int *tmp)    {        RotateTo(pos,0);RotateTo(pos + 1,root);        makeTree(keyTree,1,tot,ch[root][1],tmp);        Splay(keyTree,0);    }    void update(int pos,int tot,int c)    {        RotateTo(pos - 1,0);RotateTo(pos + tot,root);deal1(keyTree,c);        Splay(keyTree,0);    }    void del(int pos,int tot)    {        RotateTo(pos - 1,0);RotateTo(pos + tot,root);        erase(keyTree);        Splay(ch[root][1],0);    }    void res(int pos,int tot)    {        RotateTo(pos - 1,0);RotateTo(pos + tot,root);        reserve[ keyTree ] = !reserve[ keyTree ];        Splay(keyTree,0);    }    int getsum(int pos,int tot)    {        RotateTo(pos - 1,0);RotateTo(pos + tot,root);        return sum[ keyTree ];    }    int query(){return Max[root];}}Spt;int n,m;int tmp[maxn];void init(){    freopen("bzoj1500.in","r",stdin);    freopen("bzoj1500.out","w",stdout);}   void readdata(){    scanf("%d%d",&n,&m);    Spt.init(n);    for(int i = 1;i <= m;i++)    {        char op[10];        int pos,tot;        scanf("%s",op);        if(!strcmp(op,"MAX-SUM"))printf("%d\n",Spt.query());        else        {            scanf("%d%d",&pos,&tot);            if(!strcmp(op,"INSERT"))            {                for(int j = 1;j <= tot;j++)scanf("%d",&tmp[j]);                       Spt.ins(pos,tot,tmp);            }            if(!strcmp(op,"DELETE"))Spt.del(pos,tot);            if(!strcmp(op,"MAKE-SAME"))            {                int c;                scanf("%d",&c);                Spt.update(pos,tot,c);            }            if(!strcmp(op,"REVERSE"))Spt.res(pos,tot);            if(!strcmp(op,"GET-SUM"))printf("%d\n",Spt.getsum(pos,tot));        }    }}   int main(){    init();    readdata();    return 0;}