BZOJ_1552_[Cerc2007]robotic sort_splay

BZOJ_1552_[Cerc2007]robotic sort_splay

题意:

 

分析:

splay维护区间操作

可以先把编号排序,给每个编号分配一个固定的点,映射过去

查找编号的排名时先找到这个点,找出到根的路径

从上至下pushdown标记,顺便求出这个点的排名

然后翻转啥的就好做了

 

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 100050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int a[N],ch[N][2],f[N],siz[N],val[N],turn[N],rt;
int n,w[N];
struct A{
    int num,id;
}b[N];
bool cmp(const A &x,const A &y)
{
    if(x.num==y.num)return x.id<y.id;
    return x.num<y.num;
}
void print(int p)
{
    if(!p)return ;
    if(ls)print(ls);
    printf("p=%d ,val[p]=%d ",p,val[p]);
    if(rs)print(rs);
}
void pushup(int p){ if(p) siz[p]=siz[ls]+siz[rs]+1; }
void pushdown(int p)
{
    if(turn[p])
    {
        turn[p]=0;
        turn[ls]^=1;turn[rs]^=1;
        swap(ch[ls][0],ch[ls][1]);
        swap(ch[rs][0],ch[rs][1]);
    }
}
void rotate(int x)
{
    int y=f[x],z=f[y],k=get(x);
    ch[y][k]=ch[x][k^1];f[ch[y][k]]=y;ch[x][k^1]=y;
    f[y]=x;f[x]=z;if(z)ch[z][ch[z][1]==y]=x;
    pushup(y),pushup(x);if(rt==y)rt=x;
}
void splay(int x,int y)
{
    for(int fa;(fa=f[x])!=y;rotate(x))
        if(f[fa]!=y)
            rotate((get(x)==get(fa)) ? fa : x);
}
int find(int x)
{
    int p=rt;
    while(1){
        pushdown(p);
        if(x<=siz[ls])p=ls;
        else{
            x-=siz[ls]+1;
            if(!x)return p;
            p=rs;
        }
    }
}
void build(int fa,int l,int r,int flg)
{
    if(l>r)return ;
    int mid=l+r>>1;
    ch[fa][flg]=mid;
    f[mid]=fa;
    siz[mid]=1;
    val[mid]=a[mid-1];
    w[a[mid-1]]=mid;
    build(mid,l,mid-1,0);
    build(mid,mid+1,r,1);
    pushup(mid);
}
int getrank(int p)
{
    int cnt=0;
    while(p)
    {
        a[++cnt]=p;
        p=f[p];
    }
    int i;
    for(i=cnt;i;i--) pushdown(a[i]);
    splay(a[1],0);
    return siz[ch[a[1]][0]];
}
void reverse(int x,int p)
{
    x=find(x);
    p=find(p);
    splay(x,0);
    splay(p,rt);
    turn[ls]=1;
    swap(ch[ls][0],ch[ls][1]);
    pushup(p);pushup(x);
}
int main()
{
    scanf("%d",&n);
    int i;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&b[i].num);
        b[i].id=i;
    }
    sort(b+1,b+n+1,cmp);
    for(i=1;i<=n;i++)
    {
        a[b[i].id]=i;
    }
    build(0,1,n+2,1);
    rt=n+3>>1;
    for(i=1;i<=n;i++)
    {
        int tmp=getrank(w[i]);
        if(i-1)printf(" %d",tmp);
        else printf("%d",tmp);
        reverse(i,tmp+2);
    }
}

 

posted @ 2018-03-17 21:54  fcwww  阅读(128)  评论(0编辑  收藏  举报