首页 > 代码库 > P3391 【模板】文艺平衡树(Splay)

P3391 【模板】文艺平衡树(Splay)

题目背景

这是一道经典的Splay模板题——文艺平衡树。

题目描述

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

输入输出格式

输入格式:

 

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n?1,n) m表示翻转操作次数

接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n1lrn

 

输出格式:

 

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

 

输入输出样例

输入样例#1:
5 3
1 3
1 3
1 4
输出样例#1:
4 3 2 1 5

说明

n, m \leq 100000n,m100000

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,m,tot;
int root,siz[MAXN],fa[MAXN],flag[MAXN],key[MAXN],ch[MAXN][2],cnt[MAXN],ans[MAXN];
void updeat(int rt){
    int l=ch[rt][0],r=ch[rt][1];
    siz[rt]=siz[l]+siz[r]+1;
}
void pushdown(int now){
    if(flag[now]){
        flag[ch[now][0]]^=1;
        flag[ch[now][1]]^=1;
        swap(ch[now][0],ch[now][1]);
        flag[now]=0;
    }
}
int getson(int x){
    return ch[fa[x]][1]==x;
}

void rotate(int x){
    int y=fa[x],z=fa[y],b=getson(x),c=getson(y),a=ch[x][!b];
    if(z) ch[z][c]=x; else root=x; fa[x]=z;
    if(a) fa[a]=y; ch[y][b]=a;
    ch[x][!b]=y;fa[y]=x;
    updeat(y);updeat(x);
}

void splay(int x,int i){
    while(fa[x]!=i){
        int y=fa[x],z=fa[y];
        if(z==i){
            rotate(x);
        }else{
            if(getson(x)==getson(y)){
               rotate(y); rotate(x);
            }else{
               rotate(x); rotate(x);
            }
        }
    }
}
int findx(int x){
    int now=root;
    while(1){
        pushdown(now);
        if(ch[now][0]&&x<=siz[ch[now][0]])
            now=ch[now][0];
        else{
            int tmp=(ch[now][0]?siz[ch[now][0]]:0)+1;
            if(x<=tmp)    return now;
            x-=tmp;
            now=ch[now][1];
        }
    }
}
int build(int l,int r,int f){
    int now=(l+r)/2;
    fa[now]=f;
    key[now]=ans[now];
    if(l<now)    ch[now][0]=build(l,now-1,now);
    if(r>now)    ch[now][1]=build(now+1,r,now);
    updeat(now);
    return now;
}
void print(int now){
    pushdown(now);
    if(ch[now][0])    print(ch[now][0]);
    ans[++tot]=key[now];
    if(ch[now][1])    print(ch[now][1]);    
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+2;i++)
        ans[i]=i-1;
    root=build(1,n+2,0);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        y=y+2;
        int xx=findx(x),yy=findx(y);
        splay(xx,0);splay(yy,xx);
        flag[ch[ch[root][1]][0]]^=1;
    }
    print(root);
    for(int i=1;i<=n;i++)
        printf("%d ",ans[i+1]);
}

 

P3391 【模板】文艺平衡树(Splay)