bzoj3223(文艺平衡树 splay区间翻转模板)

题目
在这里插入图片描述思路: 以下标建立一颗平衡树。splay之后序列顺序并不改变,就像splay之后不改变数的大小关系。翻转区间[l,r]先把 l-1 翻转到根部,然后把r+1翻转到根部的右儿子。此时根部右儿子的左儿子就是区间[l,r]。此时对这个区间tag[ch[ch[root][1]][0]]^=1;
每次route的时候需要pushdown(f[x]),pushdown(x).
将l-1旋转到根部的操作是:找到当前第l-1个数。那么需要用到_rank(l-1)函数。为了找到当前序列第l-1个数(下标排名)的时候也需要pushdown.

//Problem: 3223   Time:3704 ms   Memory:4028 kb
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+5,INF=0x3f3f3f3f;
int ch[N][2],f[N],sz[N],val[N],tag[N];
int tot,root;
int a[N];
inline void update(int x){
    if(x) sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
}
void pushdown(int x){
    if(!x||!tag[x]) return;
    tag[ch[x][0]]^=1,tag[ch[x][1]]^=1;
    swap(ch[x][0],ch[x][1]);
    tag[x]=0;
}
inline void route(int x){
    pushdown(f[x]),pushdown(x);
    int y=f[x],z=f[y],w=(ch[y][1]==x);
    ch[y][w]=ch[x][w^1],f[ch[y][w]]=y;
    ch[x][w^1]=y,f[y]=x;
    f[x]=z;
    if(z) ch[z][ch[z][1]==y]=x;
    update(y),update(x);
}
inline void splay(int x,int tar){
    for(int fa;(fa=f[x])!=tar;route(x))
        if(f[fa]!=tar) ((ch[fa][1]==x)^(ch[f[fa]][1]==fa))?route(x):route(fa);
    if(!tar) root=x;
}
int build(int l,int r,int fa){
    if(l>r) return 0;
    int mid=(l+r)>>1,now=++tot;
    val[now]=a[mid],f[now]=fa,tag[now]=0;
    ch[now][0]=build(l,mid-1,now),ch[now][1]=build(mid+1,r,now);
    update(now);
    return now;
}
int _rank(int x){
    int now=root;
    while(1)
    {
        pushdown(now);
        if(x<=sz[ch[now][0]]) now=ch[now][0];
        else
        {
            x-=sz[ch[now][0]]+1;
            if(!x) return now;
            now=ch[now][1];
        }
    }
}
int n,m;
void print(int now)
{
    pushdown(now);
    if(ch[now][0]) print(ch[now][0]);
    if(val[now]>0&&val[now]<=n) printf("%d ",val[now]);
    if(ch[now][1]) print(ch[now][1]);
}
int main()
{
    scanf("%d%d",&n,&m);
    a[1]=0,a[n+2]=n+1;
    for(int i=1;i<=n;++i) a[i+1]=i;
    root=build(1,n+2,0);
    while(m--)
    {
        int l,r;scanf("%d%d",&l,&r);
        l=_rank(l),r=_rank(r+2);
        splay(l,0),splay(r,l);
        tag[ch[ch[root][1]][0]]^=1;
    }
    print(root);
}
©️2020 CSDN 皮肤主题: 终极编程指南 设计师:CSDN官方博客 返回首页