P3391 【模板】文艺平衡树 区间翻转更新+查询操作 splay

这是线段树无法取代splay的地方。

#include
using namespace std;
const int N=101000;
int ch[N][2];
int size[N],rev[N],fa[N];//rev[x],x节点是否需要左右子树互换 
int n,m,rt=0;
int read(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();}
    while ('0'<=ch && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
void pushup(int x)//更新节点x的size值 
{
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void pushdown(int x)//下推节点x的标记 
{
    if (rev[x]){
        int &lc=ch[x][0],&rc=ch[x][1];
        swap(lc,rc);
        rev[lc]^=1;rev[rc]^=1;rev[x]=0;
    }
}
void build(int l,int r,int &rt)//建树,根据初始序列id建 ,默认初始1,2,3,4,5 
{
    if (l>r) return;
    int mid=(l+r)>>1;
    if (midk)return select(ch[rt][0],k);
    return select(ch[rt][1],k-sum);
}
void rever(int L,int R)//翻转区间L,R 
{
    splay(L,rt);splay(R,ch[L][1]);
    rev[ch[R][0]]^=1;
}
void print(int rt)//符合BST性质的中序遍历 
{
    pushdown(rt);//下推懒标记 
    if (ch[rt][0])print(ch[rt][0]);
    if (2<=rt && rt<=n+1)printf("%d ",rt-1);
    if (ch[rt][1])print(ch[rt][1]);
}
int main(){
    n=read(),m=read();
    rt=(3+n)>>1;build(1,n+2,rt);//将询问区间[l,r]转换成[l+1,r+1],那么我们翻转l-1,r+1时就不需要特判了。
    for (int i=1;i<=m;i++)
	{
        int L=read(),R=read();
        L=select(rt,L);R=select(rt,R+2);
        rever(L,R);
    }
    print(rt);//打印最终序列的id 
    return 0;
}

 

你可能感兴趣的:(数据结构————平衡树)