【splay】BZOJ 1152 && 3506:[cqoi2014]排序机械臂

来源:互联网 发布:网络机顶盒怎么设置 编辑:程序博客网 时间:2024/05/22 17:07

BZOJ 1152 && 3506:[cqoi2014]排序机械臂


Description

这里写图片描述


Input

输入共两行,第一行为一个整数N,N表示物品的个数,第二行为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


HINT

1<=N<=100000


Solution

普通的序列splay…
每个数对应在splay中的编号不变
维护区间最小值所在的编号
每次rev标记一下即可
初始要离散化

Code

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define maxn 100233struct splay{    int ch[2],fa,size,v;    bool rev;}t[maxn*2];int pos[maxn],mn[maxn],ans[maxn];inline int in(){    int x=0;char ch=getchar();    while(ch<'0'||ch>'9')ch=getchar();    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();    return x;}int root;struct sor{    int pos,v;}a[maxn];bool cmp(const sor A,const sor B){return (A.v<B.v||(A.v==B.v&&A.pos<B.pos));}bool cmp1(const sor A,const sor B){return A.pos<B.pos;}void pushdown(int k){    t[k].rev=0,t[t[k].ch[0]].rev^=1;t[t[k].ch[1]].rev^=1;    swap(t[k].ch[0],t[k].ch[1]);}int find(int k,int x){    if(t[k].rev)pushdown(k);    if(t[t[k].ch[0]].size>=x)return find(t[k].ch[0],x);    else if(x>t[t[k].ch[0]].size+1)return find(t[k].ch[1],x-t[t[k].ch[0]].size-1);    else return k;}void update(int k){    int l=t[k].ch[0],r=t[k].ch[1];    t[k].size=t[l].size+t[r].size+1;    mn[k]=t[k].v,pos[k]=k;    if(mn[l]<mn[k]){mn[k]=mn[l];pos[k]=pos[l];}    if(mn[r]<mn[k]){mn[k]=mn[r];pos[k]=pos[r];}}void rotate(int x,int &k,int d){    int y,z;    y=t[x].fa;z=t[y].fa;    if(y==k)k=x;    else {if(t[z].ch[0]==y)t[z].ch[0]=x;else t[z].ch[1]=x;}    t[y].fa=x,t[x].fa=z,t[t[x].ch[d]].fa=y;    t[y].ch[d^1]=t[x].ch[d];t[x].ch[d]=y;    update(y),update(x);}int s[maxn],top=0;void splay(int x,int &k){    top=0;s[++top]=x;    for(int i=x;t[i].fa;i=t[i].fa)        s[++top]=t[i].fa;    for(;top;top--)        if(t[s[top]].rev)pushdown(s[top]);    int y,z;    while(x!=k)    {        y=t[x].fa;z=t[y].fa;        if(y!=k)        {            if(t[z].ch[0]==y&&t[y].ch[0]==x)rotate(y,k,1);            else if(t[z].ch[1]==y&&t[y].ch[1]==x)rotate(y,k,0);            else if(t[z].ch[0]==y&&t[y].ch[1]==x)rotate(x,k,0);            else if(t[z].ch[1]==y&&t[y].ch[0]==x)rotate(x,k,1);        }        if(t[t[x].fa].ch[0]==x)rotate(x,k,1);        else rotate(x,k,0);    }}void build(int l,int r,int f){    if(r<l)return;    if(l==r)    {        mn[l]=a[l].v;        t[l].size=1;t[l].fa=f;        t[l].v=a[l].v;        pos[l]=l;        t[f].ch[r>f]=r;        return;    }    int mid=(l+r)>>1;    build(l,mid-1,mid);build(mid+1,r,mid);    t[mid].v=a[mid].v;    update(mid);t[mid].fa=f;    t[f].ch[mid>f]=mid;}int querymn(int L,int R){    int ans1=find(root,L),ans2=find(root,R+2);    splay(ans1,root),splay(ans2,t[root].ch[1]);    return pos[t[ans2].ch[0]];}void rever(int L,int R){    int ans1=find(root,L),ans2=find(root,R+2);    splay(ans1,root),splay(ans2,t[root].ch[1]);    t[t[ans2].ch[0]].rev^=1;}int main(){    freopen("1552.in","r",stdin);    int n;    n=in();    a[1].v=a[n+2].v=99999999,mn[0]=99999999;    for(int i=2;i<=n+1;i++)    {        a[i].v=in();        a[i].pos=i-1;    }    sort(a+2,2+a+n,cmp);    for(int i=2;i<=n+1;i++)a[i].v=i-1;    sort(a+2,a+2+n,cmp1);    build(1,n+2,0);    root=(n+3)>>1;    for(int i=1;i<=n;i++)    {        int x=querymn(i,n);        splay(x,root);        ans[i]=t[t[x].ch[0]].size;        rever(i,ans[i]);    }    for(int i=1;i<=n;i++)printf("%d ",ans[i]);    return 0;}
1 0
原创粉丝点击