【HDU 1890】Robotic Sort(Splay)

这道题就是Splay基础的旋转和删点,先将需要删的点的位置记录下来并且按照翻转的先后顺序排序

然后每一次都将该点旋转至根,答案就是左儿子的大小加上i,再将左儿子旋转且将根删除就可以了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int SIZEN = 100015;
struct elem{
    int val,id;
    bool operator < (const elem &a)const{
        if(val != a.val) return val < a.val;
        return id < a.id;
    }
};
elem ss[SIZEN];
struct SplayTree{
    int ch[SIZEN][2];
    int pre[SIZEN];
    int sz[SIZEN];
    int val[SIZEN];
    int top,root;
    void exchange(int x){
        swap(ch[x][0],ch[x][1]);
    }
    inline void pushdown(int x){
        if(lazy[x]){
            lazy[ ch[x][0] ] ^= 1;
            lazy[ ch[x][1] ] ^= 1;
            exchange(ch[x][0]);
            exchange(ch[x][1]);
            lazy[x] = 0;
        }
    }
    inline void pushup(int x){
        sz[x] = sz[ ch[x][0] ] + sz[ ch[x][1] ] + 1;
    }
    inline void Rotate(int x,int f){
        int y = pre[x];
        pushdown(y);
        pushdown(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;
        pushup(y);
    }
    inline void Splay(int x,int goal) {
        pushdown(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);
                }
            }
        }
        pushup(x);
        if(goal == 0) root = x;
    }
    void debug(){
        printf("root:%d\n",root);
        Travel(root);
    }
    void Travel(int x){
        pushdown(x);
        if(ch[x][0]) Travel(ch[x][0]);
        printf("node:%d lson:%d rson:%d sz:%d pre:%d val:%d\n",x,ch[x][0],ch[x][1],sz[x],pre[x],val[x]);
        if(ch[x][1]) Travel(ch[x][1]);
    }
    void Newnode(int x){
        ch[x][0] = ch[x][1] = 0;
        sz[x] = 1;
        lazy[x] = 0;
    }
    inline void init(){
        ch[0][0] = ch[0][1] = pre[0] = 0;
        sz[0] = lazy[0] = 0;
        root = top = 0;
    }
    inline void build(int &x,int l,int r,int f){
        if(l > r) return;
        int mid = (l + r) >> 1;
        x = mid;
        Newnode(x);
        build(ch[x][0],l,mid - 1,x);
        build(ch[x][1],mid + 1,r,x);
        pre[x] = f;
        pushup(x);
    }
    int findmax(int x){
        pushdown(x);
        while(ch[x][1]){
            x  = ch[x][1];
            pushdown(x);
        }
        return x;
    }
    void del(){
        int ls,rs;
        ls = ch[root][0];rs = ch[root][1];
        if(!ls){
            root = rs;
            pre[ rs ] = 0;
            return;
        }
        int m = findmax(ch[root][0]);
        Splay(m,root);
        ch[m][1] = rs;
        pre[rs] = m;
        ch[root][0] = ch[root][1] = 0;
        root = m;
        pre[root] = 0;
        pushup(root);
    }
    inline int change(int i){
        Splay(ss[i].id,0);
        int ans = sz[ ch[root][0] ] + i;
        lazy[ ch[root][0] ] ^= 1;
        exchange(ch[root][0]);
        del();
        return ans;
    }

    int num[SIZEN];
    int lazy[SIZEN];
};
SplayTree spt;
void solve(int n){
    for(int i = 1 ; i <= n ; i++){
        scanf("%d",&spt.num[i]);
        ss[i].val = spt.num[i];
        ss[i].id = i;
    }
    sort(ss + 1,ss + n + 1);
    spt.init();
    spt.build(spt.root,1,n,0);
    for(int i = 1 ; i < n ; i++)
        printf("%d ",spt.change(i));
    printf("%d\n",n);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF&&n) solve(n);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值