title: ‘BZOJ 1552 [Cerc2007]robotic sort’
categories: BZOJ
date: 2016-1-1 01:01:04
tags: [Splay]
Description
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;
}