洛谷【模板】文艺平衡树

题面

主要新操作是区间翻转,转一个区间[l,r],需要把l-1转到根,把r+1转到l-1(现在的根)的左儿子,使[l,r]独立出来成为r+1的子树

这样便可以操作了(子树上每个节点都交换左右儿子(想一想)),优化的话打个lazy就是了

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<map>
#define rg register
#define _ (int)1e5+5
using namespace std;
int n,m,num,root;
struct pp
{
    int son[2],dad,cnt,it,size;
    bool lazy;
}tr[_];
inline int read()
{
    rg int save=0,w=1;rg char q=getchar();
    while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();}
    while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar();
    return save*w;
}
inline void pushup(rg int x)
{
    tr[x].size=tr[tr[x].son[0]].size+tr[tr[x].son[1]].size+tr[x].cnt;
}/*
inline void doit(rg int x)
{
    rg int y=tr[x].dad,z=tr[y].dad;
    rg bool k=tr[y].son[1]==x;
    tr[x].dad=z;
    tr[z].son[tr[z].son[1]==y]=x;
    tr[y].son[k]=tr[x].son[!k];
    tr[tr[y].son[k]].dad=y;
    tr[y].dad=x;
    tr[x].son[!k]=y;
    pushup(y),pushup(x);//记住要更新size!!!
}*/
inline void doit(rg int x)//一个结点的旋转
{
    rg int y=tr[x].dad,z=tr[y].dad;
    rg bool k=tr[y].son[1]==x;
    tr[x].dad=z;
    tr[z].son[tr[z].son[1]==y]=x;
    tr[y].son[k]=tr[x].son[!k];
    tr[tr[y].son[k]].dad=y;
    tr[y].dad=x;
    tr[x].son[!k]=y;
    pushup(y),pushup(x);//记住要更新size!!!
}
inline void splay(rg int x,rg int to)//x是坐标
{
    while(tr[x].dad!=to)
    {
        rg int y=tr[x].dad,z=tr[y].dad;
        if(z!=to)
            (tr[z].son[1]==y)^(tr[y].son[1]==x)?doit(x):doit(y);
        doit(x);
    }
    if(!to)root=x;
}
inline void insert(rg int x)//x是值
{
    rg int now=root,fa=0;
    while(now&&tr[now].it!=x)
        fa=now,now=tr[now].son[x>tr[now].it];
    if(!now)
    {
        now=++num;
        tr[now].it=x,tr[now].cnt=1;
        tr[now].size=1;
        tr[now].dad=fa;
        tr[now].son[0]=tr[now].son[1]=0;
        if(fa)tr[fa].son[x>tr[fa].it]=now;
    }
    else
        tr[now].cnt++;
    splay(now,0);
}
inline void down(rg int x)//x是坐标
{
    rg int l=tr[x].son[0],r=tr[x].son[1];
    tr[l].lazy^=1,tr[r].lazy^=1;
    tr[x].lazy=0;
    tr[x].son[1]=l,tr[x].son[0]=r;
//    swap(l,r);
}
inline int Kth(rg int x)//第x个
{
    rg int now=root;
    if(x>tr[root].size)return 0;
    while(2233)
    {
        if(tr[now].lazy)down(now);
        rg int front=tr[tr[now].son[0]].size+tr[now].cnt;
        if(x<=tr[tr[now].son[0]].size)now=tr[now].son[0];
        else
            if(x>front)now=tr[now].son[1],x-=front;
            else return now;
    }
}
inline void solve(rg int l,rg int r)//把l-1转到根,把r+1转到根的右节点,[l,r]就被放在同一颗子树里了
{
    rg int ll=Kth(l),rr=Kth(r+2);
    splay(ll,0);splay(rr,ll);
    tr[tr[rr/*tr[root].son[1]*/].son[0]].lazy^=1;
}
void putout(rg int now)
{
    if(tr[now].lazy)
        down(now);
    if(tr[now].son[0])putout(tr[now].son[0]);
    if(tr[now].it!=-2147483647&&tr[now].it!=2147483647)printf("%d ",tr[now].it);
    if(tr[now].son[1])putout(tr[now].son[1]);
}
int main()
{
    n=read(),m=read();
    insert(-2147483647),insert(2147483647);
    rg int i,j;
    for(i=1;i<=n;++i)insert(i);
    for(i=1;i<=m;++i)
    {
        rg int l=read(),r=read();
        solve(l,r);
    }
    putout(root);
    puts("");
    return 0;
}

 

posted @ 2018-06-10 17:18  Cwen_oier  阅读(144)  评论(0编辑  收藏  举报