1552/3506. [CQOI2014]排序机械臂【平衡树-splay】

时间:2023-03-08 19:39:00

Description

1552/3506. [CQOI2014]排序机械臂【平衡树-splay】

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

Sample Output

4 6 4 5 6 6
记录下每个装置对应位置然后依次splay翻转区间即可。
 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N (100000+100)
using namespace std;
struct node
{
int id,num;
} b[N];
int Key[N],Rev[N],Size[N];
int Father[N],Son[N][];
int n,Root,a[N],Rank[N]; bool cmp(node a,node b)
{
return a.num==b.num?a.id<b.id:a.num<b.num;
}
inline int Get(int x)
{
return Son[Father[x]][]==x;
} inline void Update(int x)
{
Size[x]=Size[Son[x][]]+Size[Son[x][]]+;
} inline void Pushdown(int x)
{
if (Rev[x])
{
Rev[x]=;
swap(Son[x][],Son[x][]);
Rev[Son[x][]]^=;
Rev[Son[x][]]^=;
}
} inline void Rotate(int x)
{
Pushdown(Father[x]);
Pushdown(x);
int wh=Get(x);
int fa=Father[x],fafa=Father[fa];
Son[fa][wh]=Son[x][wh^];
Father[fa]=x;
if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
Son[x][wh^]=fa;
Father[x]=fafa;
if (fafa) Son[fafa][Son[fafa][]==fa]=x;
Update(fa);
Update(x);
} inline void Splay(int x,int tar)
{
for (int fa;(fa=Father[x])!=tar;Rotate(x))
if (Father[fa]!=tar)
Rotate(Get(fa)==Get(x)?fa:x);
if (!tar) Root=x;
} void Build(int l,int r,int fa)
{
if (l>r) return;
if (l==r)
{
Size[l]=;
Father[l]=fa;
Son[fa][l>fa]=l;
return;
}
int mid=(l+r)>>;
Build(l,mid-,mid);
Build(mid+,r,mid);
Father[mid]=fa;
Son[fa][mid>fa]=mid;
Update(mid);
} int Findx(int x)
{
int now=Root;
while ()
{
Pushdown(now);
if (Size[Son[now][]]>=x)
now=Son[now][];
else
{
x-=Size[Son[now][]];
if (x==)
{
Splay(now,);
return now;
}
x--;
now=Son[now][];
}
}
} inline int Split(int x,int y)
{
int xx=Findx(x),yy=Findx(y);
Splay(xx,);
Splay(yy,xx);
return Son[yy][];
} int main()
{
scanf("%d",&n);
for (int i=; i<=n; ++i)
{
scanf("%d",&a[i+]);
b[i].id=i+;
b[i].num=a[i+];
}
sort(b+,b+n+,cmp);
for (int i=; i<=n; ++i)
Rank[i]=b[i].id;
Build(,n+,);
Root=(n+)/;
for (int i=; i<=n; ++i)
{
Splay(Rank[i],);
int ans=Size[Son[Root][]]+;
printf("%d ",ans-);
int hh=Split(i,ans+);
Rev[hh]^=;
}
}