bzoj 1552

首先用splay维护嘛

然后查询的时候就把对应的节点转到根,左子树大小就是排名

然后再做个区间翻转即可

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct node
{
    int v,num;
    friend bool operator < (node a,node b)
    {
        return a.v==b.v?a.num<b.num:a.v<b.v;
    }
}p[100005];
int ch[100005][2];
int siz[100005];
int a[100005];
int f[100005];
int fl[100005];
int rot;
int n;
void pushdown(int x)
{
    if(fl[x])
    {
        swap(ch[ch[x][0]][0],ch[ch[x][0]][1]),fl[ch[x][0]]^=1;
        swap(ch[ch[x][1]][0],ch[ch[x][1]][1]),fl[ch[x][1]]^=1;
        fl[x]=0;
    }
}
void update(int x)
{
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
void rotate(int x)
{
    int y=f[x],z=f[y],k=(ch[y][1]==x);
    ch[z][ch[z][1]==y]=x,f[x]=z;
    ch[y][k]=ch[x][!k],f[ch[x][!k]]=y;
    ch[x][!k]=y,f[y]=x;
    update(y),update(x);
}
void dfs_pushdown(int x)
{
    if(!x)return;
    dfs_pushdown(f[x]);
    pushdown(x);
}
void splay(int x,int ed)
{
    dfs_pushdown(x);
    while(f[x]!=ed)
    {
        int y=f[x],z=f[y];
        if(z!=ed)
        {
            if((ch[y][1]==x)^(ch[z][1]==y))rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
    if(!ed)rot=x;
}
int get_pos(int x,int k)
{
    pushdown(x);
    if(siz[ch[x][0]]>=k)return get_pos(ch[x][0],k);
    else if(siz[ch[x][0]]+1<k)return get_pos(ch[x][1],k-1-siz[ch[x][0]]);
    else return x;
}
int split(int l,int r)
{
    int v1=get_pos(rot,l-1),v2=get_pos(rot,r+1);
    splay(v1,0),splay(v2,v1);
    return ch[v2][0];
}
void rever(int l,int r)
{
    int p=split(l,r);
    swap(ch[p][0],ch[p][1]),fl[p]^=1;
}
int buildtree(int l,int r,int fa)
{
    int mid=(l+r)>>1;
    f[a[mid]]=a[fa];
    fl[a[mid]]=0;
    if(l==r){fl[a[mid]]=0;ch[a[mid]][0]=ch[a[mid]][1]=0;siz[a[mid]]=1;return a[mid];}
    if(l<mid)ch[a[mid]][0]=buildtree(l,mid-1,mid);
    else ch[a[mid]][0]=0;
    if(r>mid)ch[a[mid]][1]=buildtree(mid+1,r,mid);
    else ch[a[mid]][1]=0;
    update(a[mid]);
    return a[mid];
}
int query(int x)
{
    splay(x,0);
    return siz[ch[x][0]];
}
int main()
{
    while(1)
    {
        scanf("%d",&n);
        if(!n)return 0;
        for(int i=1;i<=n;i++)scanf("%d",&p[i].v),p[i].num=i;
        sort(p+1,p+n+1);
        for(int i=1;i<=n;i++)a[p[i].num+1]=i+1;
        a[1]=1,a[n+2]=n+2;
        rot=buildtree(1,n+2,0);
        for(int i=1;i<=n;i++)
        {
            int t=query(i+1);
            if(t>i)rever(i+1,t+1);
            printf("%d ",t);
        }
        printf("\n");
    }
    return 0;
}

 

posted @ 2019-07-02 19:58  lleozhang  Views(146)  Comments(0Edit  收藏  举报
levels of contents