UVa 11922 Permutation Transformer(splay)

題目鏈接

題意:根據m條指令改變排列{1,2,3......n}。每條指令(a,b)表示取出第a~b個元素,翻轉後天添加到排列的尾部。
題解:可以分解出三個操作,刪除一個區間,添加一個區間,翻轉一個區間。spaly的基本應用。
代碼如下:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<string.h>
#include<string>
#include<stdlib.h>
typedef long long LL;
typedef unsigned long long LLU;
const int nn=20;
const int inf=0x3fffffff;
const LL inf64=(LL)inf*inf;
using namespace std;
int n,m;
struct node
{
    int val;
    int cnt;
    bool fz;
    node* pre;
    node* ch[2];
}*root;
void push_up(node *o)
{
    if(o==NULL)
        return ;
    o->cnt=1;
    if(o->ch[0]!=NULL)
        o->cnt+=o->ch[0]->cnt;
    if(o->ch[1]!=NULL)
        o->cnt+=o->ch[1]->cnt;
}
void build(node* &o,node* fa,int l,int r)
{
    int mid=(l+r)/2;
    o=new node;
    o->pre=fa;
    o->val=mid;
    o->cnt=(r-l+1);
    o->ch[0]=o->ch[1]=NULL;
    o->fz=false;
    if(l==r)
        return ;
    if(l<=mid-1)
        build(o->ch[0],o,l,mid-1);
    if(mid+1<=r)
        build(o->ch[1],o,mid+1,r);
    push_up(o);
}
void push_down(node* o)
{
    if(o->fz)
    {
        o->fz=false;
        if(o->ch[0]!=NULL)
        {
            o->ch[0]->fz=!o->ch[0]->fz;
            swap(o->ch[0]->ch[0],o->ch[0]->ch[1]);
        }
        if(o->ch[1]!=NULL)
        {
            o->ch[1]->fz=!o->ch[1]->fz;
            swap(o->ch[1]->ch[0],o->ch[1]->ch[1]);
        }
    }
}
void Rotate(node *o)
{
    node* x=o->pre;
    push_down(x);
    push_down(o);
    int d;
    if(x->ch[0]==o) d=0;
    else d=1;
    x->ch[d]=o->ch[d^1];
    if(o->ch[d^1]!=NULL)
    {
        o->ch[d^1]->pre=x;
    }
    if(x->pre!=NULL)
    {
        if(x->pre->ch[0]==x)
            x->pre->ch[0]=o;
        else
            x->pre->ch[1]=o;
    }
    o->pre=x->pre;
    o->ch[d^1]=x;
    x->pre=o;
    push_up(x);
//    push_up(o);
}
void splay(node* o,node* f)
{
    node* x;
    node* y;
    while(o->pre!=f)
    {
        if(o->pre->pre==f)
            Rotate(o);
        else
        {
            x=o->pre;
            y=x->pre;
            int d1,d2;
            if(y->ch[0]==x) d1=0;
            else d1=1;
            if(x->ch[0]==o) d2=0;
            else d2=1;
            if(d1==d2)
            {
                Rotate(x);
                Rotate(o);
            }
            else
            {
                Rotate(o);
                Rotate(o);
            }
        }
    }
    push_up(o);
    if(f==NULL)
        root=o;
}
void select(int k,node* f)
{
    node* o=root;
    int tem;
    while(1)
    {
        tem=0;
        push_down(o);
        if(o->ch[0]!=NULL)
        {
            tem+=o->ch[0]->cnt;
        }
        if(tem>=k)
            o=o->ch[0];
        else if(tem+1==k)
            break;
        else
        {
            o=o->ch[1];
            k-=tem+1;
        }
    }
    splay(o,f);
}
void init()
{
    root=NULL;
    root=new node;
    root->val=0;
    root->cnt=2;
    root->fz=false;
    root->pre=NULL;
    root->ch[0]=root->ch[1]=NULL;

    root->ch[1]=new node;
    root->ch[1]->val=0;
    root->ch[1]->cnt=1;
    root->ch[1]->fz=false;
    root->ch[1]->pre=root;
    root->ch[1]->ch[0]=root->ch[1]->ch[1]=NULL;
}
void display(node* o)
{
    if(o==NULL)
        return ;
    push_down(o);
    display(o->ch[0]);
    if(o->val)
        printf("%d\n",o->val);
    display(o->ch[1]);
}
void solve(int l,int r)
{
    select(l,NULL);
    select(r+2,root);
    node* o=root->ch[1]->ch[0];
    root->ch[1]->ch[0]=NULL;
    splay(root->ch[1],NULL);

    o->fz=!o->fz;
    swap(o->ch[0],o->ch[1]);

    select(n-r+l,NULL);
    select(n-r+l+1,root);
    root->ch[1]->ch[0]=o;
    o->pre=root->ch[1];
    splay(root->ch[1]->ch[0],NULL);
}
int main()
{
    int a,b;
    scanf("%d%d",&n,&m);
    init();
    build(root->ch[1]->ch[0],root->ch[1],1,n);
    splay(root->ch[1]->ch[0],NULL);
    while(m--)
    {
        scanf("%d%d",&a,&b);
        solve(a,b);
    }
    display(root);
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章