您的位置:首页 > 其它

【bzoj1552/3506】[Cerc2007]robotic sort

2017-04-26 16:07 316 查看
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

6

3 4 5 1 6 2

Sample Output

4 6 4 5 6 6

题解

用splay维护序列的最小值位置以及实现翻转

找到最小值的节点,转到根,它左子树的结点个数+1就是它在序列中的位置

最小节点顺序提前排序预处理好。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 100005
int n,rt;
int size
,rev
,c
[2],fa
,id
,stk
;
struct data{int v,p;}a
;
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
bool cmp(data a,data b)
{
return a.v<b.v||(a.v==b.v&&a.p<b.p);
}
void update(int x)
{
size[x]=1+size[c[x][0]]+size[c[x][1]];
}
void pushdown(int x)
{
if (rev[x])
{
int l=c[x][0],r=c[x][1];
rev[x]^=1;rev[l]^=1;rev[r]^=1;
swap(c[x][0],c[x][1]);
}
}
void build(int l,int r,int f)
{
if (l>r) return;
int mid=(l+r)/2;
fa[id[mid]]=id[f];
size[id[mid]]=1;
if (mid>f) c[id[f]][1]=id[mid];else c[id[f]][0]=id[mid];
if (l==r) return;
build(l,mid-1,mid);build(mid+1,r,mid);
update(id[mid]);
}
void rotate(int x,int &k)
{
int l,r,y=fa[x],z=fa[y];
if (c[y][0]==x) l=0;else l=1;r=l^1;
if (y==k) k=x;
else if (c[z][0]==y) c[z][0]=x;else c[z][1]=x;
fa[x]=z;fa[y]=x;
fa[c[x][r]]=y;
c[y][l]=c[x][r];
c[x][r]=y;
update(y);update(x);
}
void splay(int x,int &k)
{
int top=0;
stk[++top]=x;
for (int i=x;fa[i];i=fa[i]) stk[++top]=fa[i];
while (top) pushdown(stk[top--]);
while (x!=k)
{
int y=fa[x],z=fa[y];
if (y!=k)
{
if (c[y][0]==x^c[z][0]==y) rotate(x,k);else rotate(y,k);
}
rotate(x,k);
}
}
int find(int x,int rk)
{
if (rev[x]) pushdown(x);
int l=c[x][0],r=c[x][1];
if (size[l]==rk) return x;
if (size[l]>rk) return find(l,rk);
else return find(r,rk-size[l]-1);
}
void rever(int l,int r)
{
int x=find(rt,l-1),y=find(rt,r+1);
splay(x,rt);splay(y,c[rt][1]);
rev[c[y][0]]^=1;
}
int main()
{
n=read();
for (int i=1;i<=n;i++)
{
a[i].v=read();
a[i].p=i;
}
sort(a+1,a+n+1,cmp);
id[0]=n+1;id[n+1]=n+2;
for (int i=1;i<=n;i++)
{
id[a[i].p]=i;
}
build(0,n+1,n+2);
rt=id[(n+1)/2];
for (int i=1;i<=n;i++)
{
splay(i,rt);
printf("%d",size[c[rt][0]]);
if (i!=n) printf(" ");
rever(i,size[c[rt][0]]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: