hdu 1890 Robotic Sort (splay树 翻转 +删点)

题目

题意:n个数排成一列,每次选择序列中的最小值(如有多个,取原始位置最小的),把它和它前面的所有数翻转,然后把这个数从序列中删去。输出每次选择的最小值的下标。

思路:用数组原下标建树,然后排序,将小的排在前面,只要按照顺序将这数的下标翻转到根节点,他的左子树加上自己就是他要的答案,然后删点。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node
{
    int num,id;
}a[N];
int sz,root;
int key[N],ch[N][2],f[N],size[N],lazy[N];
bool get(int x)
{
    return ch[f[x]][1]==x;
}
void pushup(int x)
{
     size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void pushdown(int x)
{
    if(lazy[x])
    {
        lazy[ch[x][0]]^=1;
        lazy[ch[x][1]]^=1;
        lazy[x]=0;
        swap(ch[x][0],ch[x][1]);
    }
}
bool cmp(node a,node b)
{
    if(a.num!=b.num)return a.num<b.num;
    return a.id<b.id;
}
void rotate(int x)
{
    int old=f[x],oldf=f[old],whichx=get(x);
    ch[old][whichx]=ch[x][whichx^1];
    f[ch[old][whichx]]=old;
    ch[x][whichx^1]=old;
    f[old]=x;
    f[x]=oldf;
    if(oldf)
        ch[oldf][ch[oldf][1]==old]=x;
    pushup(old);
    pushup(x);
}
void splay(int x,int goal)
{
    int y,z;
    pushdown(x);
    while(f[x] != goal)
    {
        y = f[x],z = f[y];
        if(z == goal)
        {
            pushdown(y);
            pushdown(x);
            rotate(x);
        }
        else
        {
            pushdown(z);
            pushdown(y);
            pushdown(x);
            if((ch[z][0]==y) == (ch[y][0]==x)) rotate(y);
            else rotate(x);
        }
    }
    if(goal == 0) root = x;
}
int pre()
{
    int now=ch[root][0];
    pushdown(now);
    while(ch[now][1])
    {
        now=ch[now][1];
        pushdown(now);
    }
    return now;
}
int build(int l,int r,int x)
{
    if(l>r)return 0;
    int mid=(l+r)/2;
    int now=mid;
    f[now]=x;
    size[now]=1;
    ch[now][0]=build(l,mid-1,now);
    ch[now][1]=build(mid+1,r,now);
    pushup(now);
    return now;
}
void del()
{
    if(!ch[root][0])
    {
        root=ch[root][1];
        f[root]=0;
        return ;
    }
    else if(!ch[root][1])
    {
        root=ch[root][0];
        f[root]=0;
        return ;
    }
    int x=pre();
    splay(x,root);
    ch[x][1]=ch[root][1];
    f[ch[root][1]]=x;
    root=x;
    f[root]=0;
    pushup(root);
    return;
}
void init()
{
    root=0;
    memset(size,0,sizeof(size));
    memset(lazy,0,sizeof(lazy));
    memset(ch,0,sizeof(ch));
    memset(f,0,sizeof(f));
}
int main()
{
    int n;
    while(~scanf("%d",&n)&&n)
    {
        init();
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].num);
            a[i].id=i;
        }
        sort(a+1,a+1+n,cmp);
        root=build(1,n,0);
        for(int i = 1; i <=n; i++)
        {
            splay(a[i].id,0);
            lazy[ch[root][0]] ^= 1;
            if(i>1)printf(" ");
            printf("%d",i+size[ch[root][0]]);
            del();
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81266158
今日推荐