bzoj3223 文艺平衡树 (treap or splay分裂+合并)

3223: Tyvj 1729 文艺平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3313  Solved: 1883
[Submit][Status][Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 

Input

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n 

Output

 

输出一行n个数字,表示原始序列经过m次变换后的结果 

Sample Input

5 3

1 3

1 3

1 4

Sample Output

4 3 2 1 5

HINT



N,M<=100000

Source

RunID

  User Problem Result Memory Time Language Code_Length Submit_Time
1538282 ksq2013 3223 Accepted 5396 kb 2576 ms C++/Edit 2878 B 2016-07-08 20:57:17

区间翻转裸题,废话不多说,直接放代码:

#include<cstdio>
#include<iostream>
#define INF 0x3f3f3f3f
#define Key_value ch[ch[root][1]][0]
using namespace std;
bool rev[200100];
int n,m,root,tot,size[200100],key[200100],pre[200100],ch[200100][2];
void NewNode(int &x,int father,int val)
{
    x=++tot;
    size[x]=1;
    key[x]=val;
    pre[x]=father;
}
void Update_Rev(int x)
{
    rev[x]^=1;
    swap(ch[x][0],ch[x][1]);
}
void Push_Up(int x)
{
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void Push_Down(int x)
{
    if(rev[x]){
        Update_Rev(ch[x][0]);
        Update_Rev(ch[x][1]);
        rev[x]=0;
    }
}
void build(int &x,int father,int l,int r)
{
    if(l>r)return;
    int mid=(l+r)>>1;
    NewNode(x,father,mid);
    build(ch[x][0],x,l,mid-1);
    build(ch[x][1],x,mid+1,r);
    Push_Up(x);
}
void Init()
{
    NewNode(root,0,INF);
    NewNode(ch[root][1],root,INF);
    build(Key_value,ch[root][1],1,n);
}
int Get_Kth(int x,int k)
{
    Push_Down(x);//mistaken codes;
    int t=size[ch[x][0]]+1;
    if(t==k)return x;
    if(t>k)return Get_Kth(ch[x][0],k);
    return Get_Kth(ch[x][1],k-t);
}
void Rotate(int x,int kind)
{
    int y=pre[x];
    Push_Down(y);Push_Down(x);
    ch[y][!kind]=ch[x][kind];
    pre[ch[x][kind]]=y;
    if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;//unfixed;
    pre[x]=pre[y];
    ch[x][kind]=y;
    pre[y]=x;
    Push_Up(y);
}
void Splay(int x,int goal)
{
    Push_Down(x);
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal){
            Push_Down(pre[x]);
            Push_Down(x);
            Rotate(x,ch[pre[x]][0]==x);
        }
        else{
            int y=pre[x];
            int kind=ch[pre[y]][0]==y;
            Push_Down(pre[y]);//mistaken codes&&一遇到向下的操作就Push_Down;
            Push_Down(y);//mistaken codes
            Push_Down(x);//mistaken codes
            if(ch[y][kind]==x){
                Rotate(x,!kind);
                Rotate(x,kind);
            }
            else{
                Rotate(y,kind);
                Rotate(x,kind);
            }
        }
    }
    Push_Up(x);
    if(goal==0)root=x;
}
void Rev(int l,int r)
{
    Splay(Get_Kth(root,l),0);
    Splay(Get_Kth(root,r+2),root);
    Update_Rev(Key_value);
    Push_Up(ch[root][1]);
    Push_Up(root);
}
void dfs(int x)
{
    if(!x)return;
    Push_Down(x);
    dfs(ch[x][0]);
    if(1<=key[x]&&key[x]<=n)printf("%d ",key[x]);
    dfs(ch[x][1]);
}
int main()
{
    scanf("%d%d",&n,&m);
    Init();
    for(int x,y;m;m--){
        scanf("%d%d",&x,&y);
        Rev(x,y);
    }dfs(root);
    return 0;
}

新splay模板上线,更简洁

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
inline int Rin(){
    int x=0,c=getchar(),f=1;
    for(;c<48||c>57;c=getchar())
        if(!(c^45))f=-1;
    for(;c>47&&c<58;c=getchar())
        x=(x<<1)+(x<<3)+c-48;
    return x*f;
}
struct node{
    node*ch[2];
    int r,s,v;bool b;
    node (int v,node*k):v(v){
        r=rand();
        b=0;s=1;
        ch[0]=ch[1]=k;
    }
    void exc(node*&x,node*&y)
    {node*k=y;y=x;x=k;}
    void pu(){s=ch[0]->s+ch[1]->s+1;}
    void pd(){
        if(b){
            b=0;
            exc(ch[0],ch[1]);
            ch[0]->b^=1;
            ch[1]->b^=1;
        }
    }
}*rt,*bf;
inline void rot(node*&o,int d){
    node*k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->pu();k->pu();o=k;
}
inline int cmk(node*o,int k){
    if(o->ch[0]->s+1==k)return -1;
    if(o->ch[0]->s>=k)return 0;
    return 1;
}
inline void ins(node*&o,int x){
    if(o==bf){o=new node(x,bf);return;}
    ins(o->ch[1],x);
    o->ch[1]->r>o->r?rot(o,0):o->pu();
}
inline void splay(node*&o,int k){
    if(o==bf)return;
    o->pd();int d=cmk(o,k);
    if(!(d^1))k-=o->ch[0]->s+1;
    if(d!=-1&&o->ch[d]!=bf){
        node*p=o->ch[d];p->pd();
        int dd=cmk(p,k);
        if(dd!=-1&&p->ch[dd]!=bf){
            int kk=(dd?k-p->ch[0]->s-1:k);
            splay(p->ch[dd],kk);
            d^dd?rot(o->ch[d],d):rot(o,d^1);
        }
        rot(o,d^1);
    }
}
inline node*mrg(node*l,node*r){
    splay(l,l->s);l->ch[1]=r;
    l->pu();return l;
}
inline void slt(node*o,int k,node*&l,node*&r){
    if(!k){l=bf;r=o;return;}
    if(!(k^o->s)){l=o;r=bf;return;}
    splay(o,k);l=o;r=o->ch[1];
    o->ch[1]=bf;l->pu();
}
inline void ini(){
    bf=new node(0,0);
    bf->r=INT_MAX;bf->s=bf->v=0;
    bf->ch[0]=bf->ch[1]=bf;rt=bf;
    ins(rt,0);rt->r=-999;
}
void opt(node*o){
    if(o==bf)return;
    o->pd();
    opt(o->ch[0]);
    if(o->r!=-999)printf("%d ",o->v);
    opt(o->ch[1]);
}
int n,m;
int main(){
    n=Rin(),m=Rin();ini();
    for(int i=1;i<=n;i++)ins(rt,i);
    while(m--){
        int l=Rin(),r=Rin();
        node *ll,*rr,*mm;
        slt(rt,l,ll,rr);
        slt(rr,r-l+1,mm,rr);
        mm->b^=1;
        rt=mrg(mrg(ll,mm),rr);
    }
    opt(rt);
    return 0;
}

 

posted @ 2016-07-08 21:00  keshuqi  阅读(163)  评论(0编辑  收藏  举报