牛客网暑期ACM多校训练营(第三场) C Shuffle Cards (SPLAY)

这个题就是每次把一段区间移动到区间的最前面,问你若干次操作后的序列

按照题解说,这个题就是一个平衡树的操作题,之前没有做过平衡树的题,但是移动区间的时候想到了连续的翻转操作可以使得区间移动,所以,然后找了一个splay区间翻转的板子过了这个题,赛后发现stl 中有十分简单的工具可以实现。
看来要学习的东西还有很多

#include<stdio.h>
#include<algorithm>
using namespace std;

struct node
{
    int sum,flag,siz;
    node *ch[2],*fa;
    void pushdown(node *nd)
    {
        if(flag)
        {
            swap(ch[0],ch[1]);
            if(ch[0]!=nd) ch[0]->flag^=1;
            if(ch[1]!=nd) ch[1]->flag^=1;
            flag=0;
        }
    }
    void update()
    {
        siz=ch[0]->siz+ch[1]->siz+1;
    }
}state[4000010],*tail=state,*root,*null;

int n,m;

void init()
{
    null=++tail;
    null->siz=0;
    null->ch[0]=null->ch[1]=null;
    null->sum=null->flag=0;
}

node* newnode(node *fa)
{
    node *nd=++tail;
    nd->fa=fa;
    nd->siz=1;
    nd->ch[1]=nd->ch[0]=null;
    nd->flag=0;
    return nd;
}

void rot ( node*& x, int d )
{
    node* y=x->fa;
    y->ch[!d]=x->ch[d];
    if(x->ch[d]!= null) x->ch[d]->fa=y ;
    x->fa=y->fa ;
    if(y->fa!=null)
        (y==y->fa->ch[0]) ? y->fa->ch[0]=x : y->fa->ch[1]=x;
    x->ch[d]=y;
    y->fa =x;
    x->update();
    y->update();
}

node *build(node *fa,int lf,int rg)
{
    if(lf>rg) return null;
    node *nd=newnode(fa);
    if(lf==rg)
    {
        nd->sum=lf;
        return nd;
    }
    int mid=(lf+rg)>>1;
    nd->sum=mid;
    nd->ch[0]=build(nd,lf,mid-1);
    nd->ch[1]=build(nd,mid+1,rg);
    nd->update();
    return nd;
}


void Splay(node *nd,node *tar)
{
    while(nd->fa!=tar)
    {
        node *ne=nd->fa;
        if(nd==ne->ch[0])
        {
            if(ne->fa!=tar&&ne==ne->fa->ch[0])
               rot(ne,1);
            rot(nd,1);
        }
        else
        {
            if(ne->fa!=tar&&ne==ne->fa->ch[1])
               rot(ne,0);
            rot(nd,0);
        }
    }
    if(tar==null) root=nd;
}

node *kth(node *nd,int K)
{
    nd->pushdown(null);
    if(nd->ch[0]->siz+1==K) return nd;
    if(nd->ch[0]->siz+1>K) return kth(nd->ch[0],K);
    else return kth(nd->ch[1],K-nd->ch[0]->siz-1);
}

void rev(int L,int R)
{
    node *x=kth(root,L);node *y=kth(root,R+2);
    Splay(x,null);
    Splay(y,root);
    y->ch[0]->flag^=1;
}

void GrandOrder(node *nd)
{
    if(nd==null) return ;
    nd->pushdown(null);
    GrandOrder(nd->ch[0]);
    if(nd->sum>=1&&nd->sum<=n)
    printf("%d ",nd->sum);
    GrandOrder(nd->ch[1]);
}

int main()
{
    init();
    int L,R;
    scanf("%d%d",&n,&m);
    root=build(null,0,n+1);
    while(m--)
    {
        scanf("%d%d",&L,&R);
        rev(1,L-1);
        rev(L,L+R-1);
        rev(1,L+R-1);
    }
    GrandOrder(root);
    return 0;
}
全部评论

相关推荐

贺兰星辰:不要漏个人信息,除了简历模板不太好以外你这个个人简介是不是太夸大了...
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务