HDU 1890 Robotic Sort(SplayTree)

来源:互联网 发布:手机淘宝加不了购物车 编辑:程序博客网 时间:2024/05/30 04:35

HDU 1890 Robotic Sort(SplayTree)

http://acm.hdu.edu.cn/showproblem.php?pid=1890

题意:给你N个数,要你执行一系列(题目要求的)翻转操作,使得这N个数按升序排列.要你输出翻转的区间右端点.而且还需要稳定的排序方式.

分析:

假设一棵SplayTree树有n个房间.现在我们将1到n个数放入这n个房间:表示初始的第1到第n个数分别放入了对应的房间了.

在接下来的操作里,只要我们不删除,就算我们rotate,Splay等操作都不会改变第i号房间里面放的数,我们改变的只是其他房间与第i号房间的相对关系.(上面这句好好体会下).我们改变的是pre,ch,root.但是我们改变不了key[i].(此题没用到key数组,但是默认了key[i]=I,表示第i号房间放的是初始数列的第i个数)

所以如果之后我们要找初始序列中的第3个数,我们应该去3号房间找,因为它只要没被删除,肯定在3号房间里面.

下面我们将初始序列稳定排序,然后我们可以得出最小的数在原始数列的第i个位置(也就说明了在SplayTree的i号房间),所以我们Splay(i,0)把它旋转到根部,那么它的左儿子的节点数+1就是当前我们需要翻转的区间右边界.然后对根的左子树执行翻转操作.并且删除根.

接下来我们找第二小的数在原始数列的第j个位置(通过node[2].id=j知道的),所以我们把j号节点翻转到根,执行上一步类似的操作得出这次的区间右边界.

以此类推.该SplayTree需要rev,size,pre,ch 4个信息.本题能不能不删除节点,每次翻转[1,id]这个区间并维护整个数列呢?(比较难,因为你不知道id后面的那个房间是第几号房间,房间的相对位置时刻在变)

AC代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=100000+100;int n;struct SplayTree{    int pre[maxn],ch[maxn][2],size[maxn],rev[maxn],root;    void Update_Rev(int r)    {        if(r==0) return;        rev[r]^=1;        swap(ch[r][0],ch[r][1]);    }    void Push_Down(int r)    {        if(rev[r])        {            Update_Rev(ch[r][0]);            Update_Rev(ch[r][1]);            rev[r]=0;        }    }    void Push_Up(int r)    {        size[r]=1+size[ch[r][0]]+size[ch[r][1]];    }    void Rotate(int x,int kind)    {        int y=pre[x];        Push_Down(y);        Push_Down(x);        ch[y][kind^1]=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);    }    void Splay(int r,int goal)    {        Push_Down(r);        while(pre[r]!=goal)        {            if(pre[pre[r]]==goal)                Rotate(r,ch[pre[r]][0]==r);            else            {                int y=pre[r];                int kind=ch[pre[y]][0]==y;                if(ch[y][kind]==r)                {                    Rotate(r,kind^1);                    Rotate(r,kind);                }                else                {                    Rotate(y,kind);                    Rotate(r,kind);                }            }        }        Push_Up(r);        if(goal==0) root=r;    }    void New_Node(int &r,int fa,int k)    {        r=k;        pre[r]=fa;        ch[r][0]=ch[r][1]=rev[r]=0;        size[r]=1;    }    void Build(int &x,int l,int r,int fa)    {        if(l>r)return ;        int mid=(l+r)>>1;        New_Node(x,fa,mid);        Build(ch[x][0],l,mid-1,x);        Build(ch[x][1],mid+1,r,x);        Push_Up(x);    }    void Init()    {        root=0;        ch[root][0]=ch[root][1]=rev[root]=size[root]=pre[root]=0;        Build(root,1,n,0);    }    int Get_Max(int r)    {        Push_Down(r);        while(ch[r][1])        {            r=ch[r][1];            Push_Down(r);        }        return r;    }    void Remove()    {        if(ch[root][0]==0)        {            root=ch[root][1];            pre[root]=0;        }        else        {            int m=Get_Max(ch[root][0]);            Splay(m,root);            ch[m][1]=ch[root][1];            pre[ch[root][1]]=m;            root=m;            pre[m]=0;            Push_Up(root);        }    }}st;struct Node{    int num;    int id;    bool operator<(const Node&b)const    {        if(num==b.num) return id<b.id;        return num<b.num;    }}nodes[maxn];int main(){    while(scanf("%d",&n)==1&&n)    {        st.Init();        for(int i=1;i<=n;i++)        {            scanf("%d",&nodes[i].num);            nodes[i].id=i;        }        sort(nodes+1,nodes+1+n);        for(int i=1;i<n;i++)        {            st.Splay(nodes[i].id,0);            st.Update_Rev(st.ch[st.root][0]);            printf("%d ",st.size[st.ch[st.root][0]]+i);            st.Remove();        }        printf("%d\n",n);    }}


0 0
原创粉丝点击