【bzoj1552/3506】[Cerc2007]robotic sort

来源:互联网 发布:jquery 1.8.3.min.js 编辑:程序博客网 时间:2024/06/05 09:57

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 100005int n,rt;int size[N],rev[N],c[N][2],fa[N],id[N],stk[N];struct data{int v,p;}a[N];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;}
0 0
原创粉丝点击