hdu3487 Play with Chain 伸展树splay

来源:互联网 发布:淘宝怎么加入游戏专营 编辑:程序博客网 时间:2024/05/17 23:22

       一个长度为n的数列,初始状态为1,2...n。现有两种操作,CUT a,b,c 将从a开始到b结束这段数取出,并把这段插入到取出之后这个数列的第c个数后面;FLIP a,b 将从a开始到c结束的这段数颠倒顺序。 还是基本的splay操作,为了操作方便,先添加虚拟的头结点和尾节点,再把这串数插入到头尾之间。CUT操作就把a伸展到根,把b+2伸展到根的下面,这样b+2的左孩子就是目标段a+1,b+1了(因为有个虚拟节点所以a+1,b+1对应的就是原先的a,b),然后删掉b+2的左子树,再把c伸展到根,c+1伸展到根的下面,把刚刚删除的子树插入到根的右孩子的左孩子就ok了。FLIP还是把a伸展到根,b+2伸展到根的下面,给目标段上标记就可以了。最后中序遍历的时候不要忘了下传下标..
       
       一个长度为n的数列,初始状态为1,2...n。现有两种操作,CUT a,b,c 将从a开始到b结束这段数取出,并把这段插入到取出之后这个数列的第c个数后面;FLIP a,b 将从a开始到c结束的这段数颠倒顺序。 还是基本的splay操作,为了操作方便,先添加虚拟的头结点和尾节点,再把这串数插入到头尾之间。CUT操作就把a伸展到根,把b+2伸展到根的下面,这样b+2的左孩子就是目标段a+1,b+1了(因为有个虚拟节点所以a+1,b+1对应的就是原先的a,b),然后删掉b+2的左子树,再把c伸展到根,c+1伸展到根的下面,把刚刚删除的子树插入到根的右孩子的左孩子就ok了。FLIP还是把a伸展到根,b+2伸展到根的下面,给目标段上标记就可以了。最后中序遍历的时候记得下传下标...


#include <iostream>#include <cstdio>#include <algorithm>#include <memory.h>#include <cmath>#include <string>#include <cstring>using namespace std;typedef long long ll;const int maxn=300000+300;int pre[maxn],ch[maxn][2];int size[maxn],key[maxn];int flip[maxn];int root,n;int tot;int m,p,q,r,t,tt;int k1,k2;int a[maxn];int b[maxn];int num;struct splaytree{    void pushup(int r)    {        size[r]=1+size[ch[r][0]]+size[ch[r][1]];    }    void go_f(int r)    {        flip[r]^=1;        swap(ch[r][0],ch[r][1]);    }    void pushdown(int r)    {        if (flip[r])        {            go_f(ch[r][0]);            go_f(ch[r][1]);            flip[r]=0;        }    }    void rotate(int x,int kind)    {        int y=pre[x];        pushdown(y);        pushdown(x);        ch[y][!kind]=ch[x][kind];        pre[ch[x][kind]]=y;        if (pre[y])        {            ch[pre[y]][ch[pre[y]][1]==y]=x;        }        pre[x]=pre[y];        ch[x][kind]=y;        pre[y]=x;        pushup(y);        pushup(x);    }    void splay(int x,int tgt)    {        pushdown(x);        while(pre[x]!=tgt)        {            int y=pre[x];            pushdown(pre[y]);            pushdown(y);            pushdown(x);            if (pre[pre[x]]==tgt)            {                rotate(x,ch[pre[x]][0]==x);            }            else            {                int kind=ch[pre[y]][0]==y;                if (ch[y][kind]==x)                {                    rotate(x,kind^1);                    rotate(x,kind);                }                else                {                    rotate(y,kind);                    rotate(x,kind);                }            }        }        pushup(x);        if (tgt==0) root=x;    }    void select(int k,int tgt)    {        int rt=root;        pushdown(rt);        while(true)        {            if (k<=size[ch[rt][0]]) rt=ch[rt][0];            else if (k==size[ch[rt][0]]+1) break;            else k-=(size[ch[rt][0]]+1),rt=ch[rt][1];            pushdown(rt);        }        splay(rt,tgt);    }    void newnode(int &r,int father,int k)    {        r=++tot;        pre[r]=father;        size[r]=1;        flip[r]=0;        key[r]=k;        ch[r][0]=ch[r][1]=0;    }    void build(int l,int r,int &x,int rt)    {        if (l>r) return;        int m=(l+r)>>1;        newnode(x,rt,m);        build(l,m-1,ch[x][0],x);        build(m+1,r,ch[x][1],x);        pushup(x);    }    void init()    {        tot=root=0;        newnode(root,0,0);        newnode(ch[root][1],root,0);        build(1,n,ch[ch[root][1]][0],ch[root][1]);        pushup(ch[root][1]);        pushup(root);    }    void Flip(int p1,int p2)    {        select(p1,0);        select(p2+2,root);        go_f(ch[ch[root][1]][0]);    }    void cut(int l1,int l2,int l3)    {        int t;        select(l1,0);        select(l2+2,root);        t=ch[ch[root][1]][0];        pre[t]=0;        ch[ch[root][1]][0]=0;        pushup(ch[root][1]);        select(l3+1,0);        select(l3+2,root);        ch[ch[root][1]][0]=t;        pre[t]=ch[root][1];    }    void print(int rt)    {        if (rt==0) return;        pushdown(rt);        print(ch[rt][0]);        if (key[rt])        {            num++;            b[num]=key[rt];        }        print(ch[rt][1]);    }    void out()    {        num=0;        print(root);        for (int i=1; i<num; i++)        printf("%d ",b[i]);        printf("%d\n",b[num]);    }}spt;char cmd[20];int x,y,z;int main(){//    freopen("in.txt","r",stdin);    while(~scanf("%d%d\n",&n,&m) && (n!=-1 || m!=-1))    {        spt.init();        for (int i=1; i<=m; i++)        {            scanf("%s ",cmd);            if (cmd[0]=='C')            {                scanf("%d%d%d",&x,&y,&z);                spt.cut(x,y,z);            }            else            {                scanf("%d%d",&x,&y);                spt.Flip(x,y);            }        }        spt.out();    }    return 0;}


原创粉丝点击