hdu-1890-Robotic Sort-splay tree-区间翻转

伸展树对于区间的翻转操作尤其的方便。

对于区间翻转的时候,同样使用lazy标记。

但是在splay操作的时候注意要先更新孩子,然后在判断改左旋还是右旋。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 110000
#define mem(a,b) memset(a,b,sizeof(a))
struct splaytree
{
    int pre[maxn];
    int ch[maxn][2];
    int key[maxn];
    int rev[maxn];
    int size[maxn];
    int val[maxn];
    int sum[maxn];
    int root,tot;
    int n;
    void Treaval(int x)
    {
        if(x)
        {
            Treaval(ch[x][0]);
            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d , sum = %2d \n",x,ch[x][0],ch[x][1],pre[x],size[x],val[x],sum[x]);
            Treaval(ch[x][1]);
        }
    }
    void debug()
    {
        printf("%d\n",root);
        Treaval(root);
    }
    //debug专用
    struct list
    {
        int x;
        int st;
        friend bool operator < (const list &a,const list &b)
        {
            if(a.x!=b.x)return a.x<b.x;
            return a.st<b.st;
        }
    } node[maxn];
    void init()
    {
        root=tot=0;
        mem(pre,0);
        mem(ch,0);
        mem(rev,0);
        mem(size,0);
    }
    void newnode(int &x,int father,int k)
    {
        x=k;
        pre[x]=father;
        ch[x][0]=ch[x][1]=0;
        rev[x]=0;
        key[x]=k;
        size[x]=1;
    }
    void push_down(int x)
    {
        if(rev[x])
        {
            rev[ch[x][0]]^=1;
            rev[ch[x][1]]^=1;
            swap(ch[x][0],ch[x][1]);
            rev[x]=0;
        }
    }
    void push_up(int x)
    {
        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
    }
    void rot(int x,int kind)
    {
        int y=pre[x];
        push_down(y);
        push_down(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;
        push_up(y);
        push_up(x);
    }
    void splay(int x,int goal)
    {
        push_down(x);
        while(pre[x]!=goal)
        {
            if(pre[pre[x]]==goal)
            {
                push_down(pre[x]);
                push_down(x);
                rot(x,ch[pre[x]][0]==x);
            }
            else
            {
                int y=pre[x];
                push_down(pre[y]);
                push_down(pre[x]);
                push_down(x);
                int kind=ch[pre[y]][0]==y;
                if(ch[y][kind]==x)
                {
                    rot(x,!kind);
                    rot(x,kind);
                }
                else
                {
                    rot(y,kind);
                    rot(x,kind);
                }
            }
        }
        push_up(x);
        if(goal==0)root=x;
    }
    int getmax(int x)
    {
        push_down(x);
        while(ch[x][1])
        {
            x=ch[x][1];
            push_down(x);
        }
        return x;
    }
    void erase(int x)
    {
        if(ch[root][0]==0)
        {
            root=ch[root][1];
            pre[root]=0;
        }
        else
        {
            int m=getmax(ch[root][0]);
            splay(m,root);
            ch[m][1]=ch[root][1];
            pre[ch[root][1]]=m;
            root=m;
            pre[root]=0;
            push_up(root);
        }
    }
    void buildtree(int &x,int l,int r,int father)
    {
        if(l>r)return ;
        int mid=(l+r)/2;
        //  cout<<x<<"--->";
        newnode(x,father,mid);
        // cout<<x<<endl;
        buildtree(ch[x][0],l,mid-1,x);
        buildtree(ch[x][1],mid+1,r,x);
        push_up(x);
    }
    void start()
    {
        sort(node+1,node+n+1);
        buildtree(root,1,n,0);
    }
} T;
int main()
{
    int n,i;
    while(scanf("%d",&n)!=EOF&&n)
    {
        T.init();
        T.n=n;
        for(i=1; i<=n; i++)
        {
            scanf("%d",&T.node[i].x);
            T.node[i].st=i;
        }
        T.start();
        //  T.debug();
        for(int i=1; i<n; i++)
        {
            //T.debug();
            T.splay(T.node[i].st,0);
            T.rev[T.ch[T.root][0]]^=1;
            printf("%d ",i+T.size[T.ch[T.root][0]]);
            T.erase(T.root);
        }
        printf("%d\n",n);
    }
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值