[BZOJ3223]Tyvj 1729 文艺平衡树

Tyvj 1729 文艺平衡树

题面

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

思路

模板splay(不带区间操作)是按照权值来排序维护二叉查找树的。如果把splay推广到区间操作,我们需要进行一些修改。把一个元素在区间中的下标(即第几个)作为splay树的权值。所以对于这棵splay树的根节点,左边的所有节点在序列中的位置都在根节点之前。这样如果我们需要操作区间\([l,r]\),我们就先把l-1转到root,再把r+1转到root的右儿子,那么root的右儿子的左子树则是区间\([l,r]\)对应的所有节点。splay树中排名为k的节点则是序列中第k个节点。

我们可以发现,对于一个子树,子树的根节点的左子树就是在根节点左侧的点,右子树就是在根节点右侧的点。那么我们容易发现,如果把左右子树换一下,然后递归的更新左右子树即可。

为了优化时间,我们可以像线段树一样打个tag来维护翻转操作。同时Push_Down操作就是下传tag同时交换左右子树。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define maxn (int)(1e5+1000)
#define inf (int)(1e9+1000)
using namespace std;
int
val[maxn],tag[maxn],size[maxn],son[maxn][2],fa[maxn],cnt[maxn],s[maxn];
int n,m,idx,root;
void push_down(int x){
    if(!tag[x])return;
    if(son[x][0]){
        tag[son[x][0]]^=1;
    }
    if(son[x][1]){
        tag[son[x][1]]^=1;
    }
    tag[x]=0;
    swap(son[x][0],son[x][1]);
    return;
}
void push_up(int x){
    size[x]=cnt[x];
    if(son[x][0]){
        size[x]+=size[son[x][0]];
    }
    if(son[x][1]){
        size[x]+=size[son[x][1]];
    }
    return;
}
void Down(int x){
    if(!x)return;
    Down(fa[x]);
    push_down(x);
    return;
}
void rotate(int x){
    int y=fa[x],z=fa[y],o=(son[y][1]==x);
    son[y][o]=son[x][o^1];
    fa[son[x][o^1]]=y;

    son[x][o^1]=y;
    fa[y]=x;

    son[z][son[z][1]==y]=x;
    fa[x]=z;

    push_up(y);
    push_up(x);
    return;
}
void splay(int x,int v=0){
    Down(x);
    for(int y;fa[x]!=v&&fa[x];rotate(x)){
        y=fa[x];
        if(fa[y]==v)continue;
        rotate((son[fa[x]][0]==x)^(son[fa[y]][0]==y)?x:y);
    }
    if(!v)root=x;
}
void insert(int x,int a){
    int y=0;
    while(x&&val[x]!=a){
        y=x;
        x=son[x][val[x]<a];
    }
    if(x){
        cnt[x]++;push_up(x);
    }
    else{
        x=++idx;
        val[x]=a;
        tag[x]=son[x][0]=son[x][1]=0;
        cnt[x]=size[x]=1;
        son[y][val[y]<a]=x;
        fa[x]=y;
    }
    splay(x);
    return;
}
int kth(int x,int a){
    push_down(x);
    if(size[son[x][0]]>=a){
        return kth(son[x][0],a);
    }
    if(size[son[x][0]]+cnt[x]>=a){
        splay(x);
        return x;
    }
    return kth(son[x][1],a-cnt[x]-size[son[x][0]]);
}
void write(int x){
    if(!x)return;
    push_down(x);
    write(son[x][0]);
    if(-1e9<=val[x]&&val[x]<=1e9)printf("%d ",val[x]);
    write(son[x][1]);
    return;
}
int main(){
//	freopen("in","r",stdin);
    scanf("%d%d",&n,&m);
    insert(root,inf);insert(root,-inf);
    for(int i=1;i<=n;i++){insert(root,i);}
    for(int i=1;i<=m;i++){
        int l,r;scanf("%d%d",&l,&r);
        l=kth(root,l+1-1);r=kth(root,r+1+1);
        splay(l);splay(r,root);
        tag[son[son[root][1]][0]]^=1;
        push_down(son[son[root][1]][0]);
    }
    write(root);
    return 0;
}
posted @ 2019-04-27 00:41  GavinZheng  阅读(195)  评论(0编辑  收藏  举报