BZOJ-1552/3506:[Cerc2007]robotic sort

[文章目录]

Description


1<=N<=100000

splay。发现还有坑啊。
有影响查询的标记,并且只能定位节点地址的查询怎么办???
由于标记下传是不影响节点的fa的,所以,我们可以将路径上的节点扔到栈里,然后一路pushdown。
如果是查排名的话,其实还可以进行递归,由于儿子的排名跟父亲的排名有一定的关系,所以先查询父亲的排名,将其pushdown,再计算当前节点的排名,注意root需要pushdown。
两种方法好像都可以,感性理解上感觉好像第一种全能一些。
建树的时候维护序列,然后下标为rank,便于直接找节点。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
struct ques
{
    int w,id,rank;
}a[101000];
bool cmp(ques x,ques y){return x.w==y.w?x.id<y.id:x.w<y.w;}
bool cmp1(ques x,ques y){return x.id<y.id;}
struct node
{
    node *fa,*c[2];
    bool tur;int siz;
    node();
    void pushup(){siz=c[0]->siz+c[1]->siz+1;}
    void reverse(){swap(c[0],c[1]); tur^=1;}
    void pushdown();
}*null=new node(),*root,*tre[101000];
node:: node()
{
    fa=c[0]=c[1]=null;
    siz=null?1:0;
    tur=0;
}
void node:: pushdown()
{
    if(tur)
    {
        if(c[0]!=null) c[0]->reverse();
        if(c[1]!=null) c[1]->reverse();
        tur^=1;
    }
}
node *build(int l,int r)
{
    if(r<l) return null;
    int mid=l+r>>1;
    tre[a[mid].rank]=new node();
    tre[a[mid].rank]->c[0]=build(l,mid-1);
    tre[a[mid].rank]->c[1]=build(mid+1,r);
    tre[a[mid].rank]->c[0]->fa=tre[a[mid].rank];
    tre[a[mid].rank]->c[1]->fa=tre[a[mid].rank];
    tre[a[mid].rank]->pushup();
}
void initialize()
{
    root=new node();
    root->c[1]=new node();
    root->c[1]->fa=root;
    root->c[1]->c[0]=build(1,n);
    root->c[1]->c[0]->fa=root->c[1];
    root->c[1]->pushup();
    root->pushup();
}
int getrank(node *x)//返回节点左面的节点个数
{
    if(root==x) {x->pushdown(); return x->c[0]->siz;}
    int tmp=getrank(x->fa);
    x->pushdown();
    if(x==x->fa->c[0]) return tmp-x->c[1]->siz-1;
    else return tmp+x->c[0]->siz+1;
}
void rotate(node *x)
{
    node *y=x->fa; bool l=(x==y->c[1]),r=l^1;
    y->c[l]=x->c[r]; x->c[r]->fa=y;
    x->fa=y->fa; x->c[r]=y;
    if(y==y->fa->c[0]) y->fa->c[0]=x;
    else y->fa->c[1]=x;
    y->fa=x; y->pushup(); x->pushup();
    if(root==y) root=x;
}
void splay(node *x,node *tar)
{
    while(x->fa!=tar)
    {
        node *y=x->fa,*z=y->fa;
        if(z==tar) {rotate(x); break;}
        if((x==y->c[0])^(y==z->c[0])) rotate(x);
        else rotate(y); rotate(x);
    }
}
void find(node *x,int y,node *z)
{
    while(1)
    {
        x->pushdown();
        if(y<=x->c[0]->siz) x=x->c[0];
        else
        {
            y-=x->c[0]->siz+1;
            if(!y) break;
            x=x->c[1];
        }
    }
    splay(x,z);
}
void Reverse(int l,int r)
{
    find(root,l,null);
    find(root,r+2,root);
    root->c[1]->c[0]->reverse();
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].w);
        a[i].id=i;
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++) a[i].rank=i;
    sort(a+1,a+n+1,cmp1);
    initialize();
    for(int i=1;i<=n;i++)
    {
        int tmp=getrank(tre[i]);
        printf("%d%c",tmp,(i==n)?'\n':' ');
        Reverse(i,tmp);
    }
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注