BZOJ3224普通平衡树splay,SBT代码

splay

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int v[100010],fa[100010],ch[100010][2],sz[100010],tot[100010],rt,n,op,x,cnt,pred,succ;
char c;
inline void GET(int &n)
{
    int f=1;n=0;
    do{c=getchar();if(c=='-')f=-1;}while(c>'9'||c<'0');
    while(c<='9'&&c>='0'){n=n*10+c-'0';c=getchar();}
    n*=f;
}
inline void pushup(int x)
{
    sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+tot[x];
}
inline void rotate(int x)
{
    int y=fa[x],z=fa[y];
    bool flag=(ch[y][1]==x);
    ch[y][flag]=ch[x][!flag];
    fa[ch[y][flag]]=y;
    ch[x][!flag]=y;
    fa[ch[x][!flag]]=x;
    fa[x]=z;
    ch[z][y==ch[z][1]]=x;
    pushup(x);
    pushup(y);
}
inline void splay(int x,int goal)
{
    for(int y;(y=fa[x])!=goal;rotate(x))
    {
        int z=fa[y];
        if(fa[y]!=goal)
        {
            if((ch[z][0]==y)^(ch[y][0]==x))rotate(x);
            else rotate(y);
        }
    }
    if(!goal)rt=x;
    pushup(x);
}
inline void insert(int val)
{
    int x=rt,y=0;
    while(x)
    {
        if(v[x]==val){++tot[x];splay(x,0);return;}
        y=x;
        x=ch[x][val>v[x]];
    }
    x=++cnt;
    v[x]=val;
    sz[x]=tot[x]=1;
    fa[x]=y;
    ch[y][v[x]>v[y]]=x;
    splay(x,0);
}
int kth(int r,int x)
{
    if(x>=sz[ch[r][0]]+1&&x<=sz[ch[r][0]]+tot[r])return v[r];
    if(x<sz[ch[r][0]]+1)return kth(ch[r][0],x);
    return kth(ch[r][1],x-sz[ch[r][0]]-tot[r]);
}
int rnk(int r,int x)
{
    if(x==v[r])return sz[ch[r][0]]+1;
    if(x<v[r])return rnk(ch[r][0],x);
    return rnk(ch[r][1],x)+sz[ch[r][0]]+tot[r];
}
void predecessor(int r,int x)
{
    if(0==r)return;
    if(x>v[r])
    {
        pred=r;
        predecessor(ch[r][1],x);
    }
    else predecessor(ch[r][0],x);
}
void successor(int r,int x)
{
    if(0==r)return;
    if(x<v[r])
    {
        succ=r;
        successor(ch[r][0],x);
    }
    else successor(ch[r][1],x);
}
void del(int val)
{
    successor(rt,val);
    predecessor(rt,val);
    splay(pred,0);
    splay(succ,pred);
    if(tot[ch[succ][0]]>1)
    {
        --tot[ch[succ][0]];
        splay(ch[succ][0],0);
    }
    else
    {
        ch[succ][0]=0;
        splay(succ,0);
    }
}
int main()
{
    GET(n);
    insert(999999999);
    insert(-999999999);
    while(n--)
    {
        GET(op);GET(x);
        if(op==1)insert(x);
        else if(op==2)del(x);
        else if(op==3)printf("%d\n",rnk(rt,x)-1);
        else if(op==4)printf("%d\n",kth(rt,x+1));
        else if(op==5){predecessor(rt,x);printf("%d\n",v[pred]);}
        else if(op==6){successor(rt,x);printf("%d\n",v[succ]);}
    }
}

像这样删除,一开始要放进去两个上下限,然后统计的时候记得要绕开。
SBT

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
    int lc,rc,sz,v;
}tree[500010];
int n,op,x,pred,succ,cnt,rt;
char c;
inline void GET(int &n)
{
    n=0;
    int f=1;
    do{c=getchar();if(c=='-')f=-1;}while(c>'9'||c<'0');
    while(c<='9'&&c>='0'){n=n*10+c-'0';c=getchar();}
    n*=f;
}
inline void zig(int &r)
{
    int t=tree[r].lc;
    tree[r].lc=tree[t].rc;
    tree[t].rc=r;
    tree[r].sz=tree[tree[r].lc].sz+tree[tree[r].rc].sz+1;
    tree[t].sz=tree[tree[t].lc].sz+tree[tree[t].rc].sz+1;
    r=t;
}
inline void zag(int &r)
{
    int t=tree[r].rc;
    tree[r].rc=tree[t].lc;
    tree[t].lc=r;
    tree[r].sz=tree[tree[r].lc].sz+tree[tree[r].rc].sz+1;
    tree[t].sz=tree[tree[t].lc].sz+tree[tree[t].rc].sz+1;
    r=t;
}
inline void zigzag(int &r)
{
    zig(tree[r].rc);
    zag(r);
}
inline void zagzig(int &r)
{
    zag(tree[r].lc);
    zig(r);
}
inline void maintain(int &r,bool flag)
{
    if(!flag)
    {
        if(tree[tree[r].rc].sz<tree[tree[tree[r].lc].lc].sz)zig(r);
        else if(tree[tree[r].rc].sz<tree[tree[tree[r].lc].rc].sz)zagzig(r);
        else return;
    }
    else
    {
        if(tree[tree[r].lc].sz<tree[tree[tree[r].rc].rc].sz)zag(r);
        else if(tree[tree[r].lc].sz<tree[tree[tree[r].rc].lc].sz)zigzag(r);
        else return;
    }
    maintain(tree[r].lc,0);
    maintain(tree[r].rc,1);
    maintain(r,0);
    maintain(r,1);
}
void insert(int &r,int x)
{
    if(0==r)
    {
        tree[++cnt].sz=1;
        tree[cnt].v=x;
        r=cnt;
        return;
    }
    ++tree[r].sz;
    if(x<tree[r].v)insert(tree[r].lc,x);
    else insert(tree[r].rc,x);
    maintain(r,x>=tree[r].v);
}
int del(int &r,int x)
{
    int res;
    --tree[r].sz;
    if(tree[r].v==x||(0==tree[r].lc&&x<tree[r].v)||(0==tree[r].rc&&x>tree[r].v))
    {
        res=tree[r].v;
        if(0==tree[r].lc||0==tree[r].rc)r=tree[r].lc+tree[r].rc;
        else tree[r].v=del(tree[r].lc,x);
    }
    else
    {
        if(x<tree[r].v)res=del(tree[r].lc,x);
        else res=del(tree[r].rc,x);
    }
    return res;
}
void predecessor(int r,int x)
{
    if(0==r)return;
    if(x>tree[r].v)
    {
        pred=tree[r].v;
        predecessor(tree[r].rc,x);
    }
    else predecessor(tree[r].lc,x);
}
void successor(int r,int x)
{
    if(0==r)return;
    if(x<tree[r].v)
    {
        succ=tree[r].v;
        successor(tree[r].lc,x);
    }
    else successor(tree[r].rc,x);
}
int kth(int r,int x)
{
    if(x==tree[tree[r].lc].sz+1)return tree[r].v;
    if(x<tree[tree[r].lc].sz+1)return kth(tree[r].lc,x);
    return kth(tree[r].rc,x-tree[tree[r].lc].sz-1);
}
int rnk(int r,int x)
{
    if(r==0)return 1;
    if(x<=tree[r].v)return rnk(tree[r].lc,x);
    return rnk(tree[r].rc,x)+tree[tree[r].lc].sz+1;
}
int main()
{
    GET(n);
    while(n--)
    {
        GET(op);GET(x);
        if(op==1)insert(rt,x);
        else if(op==2)del(rt,x);
        else if(op==3)printf("%d\n",rnk(rt,x));
        else if(op==4)printf("%d\n",kth(rt,x));
        else if(op==5){predecessor(rt,x);printf("%d\n",pred);}
        else if(op==6){successor(rt,x);printf("%d\n",succ);}
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值