1552: [Cerc2007]robotic sort
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 740 Solved: 303
[ Submit][ Status][ Discuss]
Description
Input
输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。
Output
输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。
Sample Input
6
3 4 5 1 6 2
3 4 5 1 6 2
Sample Output
4 6 4 5 6 6
HINT
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 1000003
#define inf 1000000000
using namespace std;
int n,a[N],key[N],b[N],p[N],root,sz;
int fa[N],ch[N][3],size[N],rev[N],pos[N];
int cmp(int x,int y)
{
return a[x]<a[y]||a[x]==a[y]&&x<y;
}
int get(int x)
{
return ch[fa[x]][1]==x;
}
void update(int x)
{
size[x]=1;
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
void pushdown(int x)
{
if (!rev[x]) return ;
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
rev[x]=0;
}
void rotate(int x)
{
pushdown(fa[x]); pushdown(x);
int y=fa[x]; int z=fa[y]; int which=get(x);
if (z) ch[z][ch[z][1]==y]=x;
fa[x]=z; fa[y]=x; ch[y][which]=ch[x][which^1];
fa[ch[y][which]]=y; ch[x][which^1]=y;
update(y); update(x);
}
void splay(int x,int tar)
{
for (int f;(f=fa[x])!=tar;rotate(x))
if (fa[f]!=tar)
rotate(get(x)==get(f)?f:x);
if (!tar)
root=x;
}
int find(int x)
{
int now=root;
while (true)
{
pushdown(now);
if (x<=size[ch[now][0]])
now=ch[now][0];
else
{
int temp=size[ch[now][0]]+1;
if (temp==x) return now;
x-=temp;
now=ch[now][1];
}
}
}
int build(int l,int r)
{
if(l==r)
{
sz++; pos[b[l]]=sz; size[sz]=1;
return sz;
}
if (l>r) return 0;
int now=++sz; int mid=(l+r)/2; pos[b[mid]]=now;
ch[now][0]=build(l,mid-1);
ch[now][1]=build(mid+1,r);
fa[ch[now][0]]=now; fa[ch[now][1]]=now;
size[now]=size[ch[now][0]]+size[ch[now][1]]+1;
return now;
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]),p[i]=i;
sort(p+1,p+n+1,cmp);
int cnt=0;
b[1]=0; b[n+2]=n+2;
for (int i=1;i<=n;i++)
b[p[i]+1]=i;
root=build(1,n+2);
for (int i=1;i<=n;i++)
{
splay(pos[i],0);
int ans=size[ch[root][0]];
if (i!=n) printf("%d ",ans);
else printf("%d\n",ans);
int aa=find(i); int bb=find(ans+2);
splay(aa,0);
splay(bb,aa);
rev[ch[ch[root][1]][0]]^=1;
}
}