BZOJ 1552 [Cerc2007]robotic sort

title: ‘BZOJ 1552 [Cerc2007]robotic sort’
categories: BZOJ
date: 2016-1-1 01:01:04
tags: [Splay]


Description

SORT公司是一个专门为人提供排序服务的公司。

Input

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

Output

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,(1<=Pi<=N),Pi表示第i次操作前第i小的物品所在的位置。注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

Sample

input.txt
6
3 4 5 1 6 2

output.txt
4 6 4 5 6 6

Solution

先离散化,我们考虑把排第x大的元素放在splay下标为x的节点,方便查找。由于省去了find的过程,我们要先找到节点x到root这条路上的所有点放入栈中,然后把flip标记依次pushdown才能进行接下来的翻转。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

#define maxn 100000+5

using namespace std;

struct Splay_Tree{
    int ch[2];
    int sz,fa,flip;
}tr[maxn<<1];

struct Node{
    int val,pos;
}a[maxn];

int p[maxn],stack[maxn];
int n,root,top;

inline bool cmp(const Node &a,const Node &b){
    if(a.val==b.val) return a.pos<b.pos;
    return a.val<b.val;
}

inline int in(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}

void Pushdown(int k){
    if(tr[k].flip){
        tr[k].flip^=1;
        swap(tr[k].ch[0],tr[k].ch[1]);
        tr[tr[k].ch[0]].flip^=1;
        tr[tr[k].ch[1]].flip^=1;
    }
}

void Update(int k){
    tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz+1;
    tr[tr[k].ch[0]].fa=tr[tr[k].ch[1]].fa=k;
}

void Rotate(int &k,int d){
    int t=tr[k].ch[d^1],Fa=tr[t].fa;
    if(tr[t].ch[d]) tr[tr[t].ch[d]].fa=k; tr[k].fa=t;
    tr[k].ch[d^1]=tr[t].ch[d]; tr[t].ch[d]=k;
    Update(k); Update(t); k=t; tr[t].fa=Fa;
}

void Splay(int &k,int x){
    Pushdown(k);
    if(tr[k].ch[0]) Pushdown(tr[k].ch[0]);
    if(tr[k].ch[1]) Pushdown(tr[k].ch[1]);
    int d1=(tr[tr[k].ch[0]].sz<x?1:0),t=tr[k].ch[d1];
    if(d1==1) x-=tr[tr[k].ch[0]].sz+1;
    if(x){
        int d2=(tr[tr[t].ch[0]].sz<x?1:0);
        if(d2==1) x-=tr[tr[t].ch[0]].sz+1;
        if(x){
            Splay(tr[t].ch[d2],x);
            if(d1==d2) Rotate(k,d1^1);
            else Rotate(tr[k].ch[d1],d1);
        }
        Rotate(k,d1^1);
    }
}

void Build(int l,int r,int &k){
    if(l>r) return;
    if(l==r){
        k=p[l];
        tr[k].flip=tr[k].ch[0]=tr[k].ch[1]=0;
        tr[k].sz=1;
        return;
    }
    int mid=(l+r)>>1; k=p[mid];
    Build(l,mid-1,tr[k].ch[0]);
    Build(mid+1,r,tr[k].ch[1]);
    if(tr[k].ch[0]) tr[tr[k].ch[0]].fa=k;
    if(tr[k].ch[1]) tr[tr[k].ch[1]].fa=k;
    Update(k);
}

int get_rank(int k){
    int res=tr[tr[k].ch[0]].sz+1;
    stack[++top]=k;
    while(k!=root){
        int p=tr[k].fa;
        if(tr[p].ch[0]!=k)
            res+=tr[tr[p].ch[0]].sz+1;
        k=p; stack[++top]=k;
    }
    return res;
}

int main(){
    freopen("1552.in","r",stdin);
    n=in();
    for(int i=1;i<=n;i++) a[i].val=in(),a[i].pos=i;
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++) p[a[i].pos]=i; p[0]=n+1; p[n+1]=n+2;
    Build(0,n+1,root);
    for(int i=1;i<=n;i++){
        int r=get_rank(i);
        while(top) Pushdown(stack[top--]);
        r=get_rank(i);
        Splay(root,i); tr[root].fa=0;
        Splay(tr[root].ch[1],r-tr[tr[root].ch[0]].sz); tr[tr[root].ch[1]].fa=root;
        int pos=tr[tr[root].ch[1]].ch[0];
        tr[pos].flip^=1;
        if(i==1) printf("%d",r-1);
        else printf(" %d",r-1);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值