洛谷.3391.[模板]文艺平衡树(Splay)

本文介绍了一种使用C++实现的二叉搜索树及其旋转调整操作,通过旋转保持树的平衡,确保高效的查找、插入和删除操作。此外,还展示了如何利用这种数据结构进行区间反转等高级操作。

题目链接

//注意建树 
#include<cstdio>
#include<algorithm>
const int N=1e5+5;
//using std::swap;

int n,m,root,t[N],sz[N],son[N][2],fa[N];
bool tag[N];

inline void Update(int rt)
{
    sz[rt]=sz[son[rt][0]]+sz[son[rt][1]]+1;
}
inline void Down(int rt)
{
    tag[rt]^=1;
    if(son[rt][0]) tag[son[rt][0]]^=1;
    if(son[rt][1]) tag[son[rt][1]]^=1;
    std::swap(son[rt][0],son[rt][1]);
}
void Rotate(int x,int &k)
{
    int a=fa[x],b=fa[a],l=(son[a][1]==x),r=l^1;
//  if(tag[a]) Down(a);
    if(a==k) k=x;
    else son[b][son[b][1]==a]=x;
    fa[x]=b, fa[a]=x, fa[son[x][r]]=a;
    son[a][l]=son[x][r], son[x][r]=a;
    Update(a),Update(x);
}
void Splay(int x,int &k)
{
    while(x!=k)
    {
        int a=fa[x],b=fa[a];
        if(tag[b]) Down(b);
        if(tag[a]) Down(a);
        if(tag[x]) Down(x);
        if(a!=k)
        {
            if((son[a][1]==x)^(son[b][1]==a)) Rotate(x,k);
            else Rotate(a,k);
        }
        Rotate(x,k);
    }
}
void Build(int l,int r,int f)
{
    if(l>r) return;
    int m=l+r>>1;
    fa[m]=f, son[f][m>f]=m, sz[m]=1;
    if(l==r) return;
    Build(l,m-1,m),Build(m+1,r,m);
    Update(m);
}
int Find(int x)
{
    int k=root;
    while(1)
    {
        if(tag[k]) Down(k);//!
//      printf("%d %d\n",x,k);
        if(sz[son[k][0]]+1==x) return k;
        if(sz[son[k][0]]>=x) k=son[k][0];
        else x-=sz[son[k][0]]+1, k=son[k][1];
    }
}
void Reverse(int L,int R)
{
    int l=Find(L),r=Find(R+2);
//  printf("[%d,%d]:[%d,%d]\n",L,R+2,l,r);
    Splay(l,root),Splay(r,son[root][1]);
    tag[son[r][0]]^=1;
}
void Print(int x)
{
    if(tag[x]) Down(x);
    if(son[x][0]) Print(son[x][0]);
    if(x!=1 && x!=n+2) printf("%d ",x-1);
    if(son[x][1]) Print(son[x][1]);
}

int main()
{
    scanf("%d%d",&n,&m);
    Build(1,n+2,0);
    root=n+3>>1;
    int l,r;
    while(m--) scanf("%d%d",&l,&r),Reverse(l,r);
//  Splay(n+3>>1,root);
    Print(root);

    return 0;
}

转载于:https://www.cnblogs.com/SovietPower/p/8435026.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值