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
    评论
以下是一份使用Treap实现的C++代码,仅供参考。 ```c++ #include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 1e5 + 5; int n, m; int root, cnt; struct Node { int val, key; int size; int ch[2]; } tr[MAXN]; inline int new_node(int val) { tr[++cnt].val = val; tr[cnt].key = rand(); tr[cnt].size = 1; return cnt; } inline void pushup(int p) { tr[p].size = 1 + tr[tr[p].ch[0]].size + tr[tr[p].ch[1]].size; } inline void split(int p, int k, int &x, int &y) { if (!p) { x = y = 0; return; } if (tr[p].val <= k) { x = p; split(tr[p].ch[1], k, tr[p].ch[1], y); } else { y = p; split(tr[p].ch[0], k, x, tr[p].ch[0]); } pushup(p); } inline int merge(int x, int y) { if (!x || !y) return x + y; if (tr[x].key < tr[y].key) { tr[x].ch[1] = merge(tr[x].ch[1], y); pushup(x); return x; } else { tr[y].ch[0] = merge(x, tr[y].ch[0]); pushup(y); return y; } } inline void insert(int val) { int x, y; split(root, val, x, y); root = merge(merge(x, new_node(val)), y); } inline void remove(int val) { int x, y, z; split(root, val, x, z); split(x, val - 1, x, y); y = merge(tr[y].ch[0], tr[y].ch[1]); root = merge(merge(x, y), z); } inline int kth(int k) { int p = root; while (p) { if (tr[tr[p].ch[0]].size >= k) { p = tr[p].ch[0]; } else if (tr[tr[p].ch[0]].size + 1 == k) { return tr[p].val; } else { k -= tr[tr[p].ch[0]].size + 1; p = tr[p].ch[1]; } } return -1; } inline int query_min() { int p = root; int res = INF; while (p) { res = min(res, tr[p].val); p = tr[p].ch[0]; } return res; } int main() { srand(time(NULL)); scanf("%d%d", &n, &m); for (int i = 1, opt, x; i <= n; ++i) { scanf("%d%d", &opt, &x); if (opt == 1) { insert(x); } else { remove(tr[cnt].val); } } printf("%d\n", query_min()); while (m--) { int k; scanf("%d", &k); printf("%d\n", kth(k)); } return 0; } ``` 代码实现中使用了一个结构体 `Node` 来表示平衡树的每一个节点。其中 `val` 表示节点存储的值,`key` 表示随机生成的优先级,`size` 表示以该节点为根的子树大小,`ch[0]` 和 `ch[1]` 分别表示左右儿子的下标。接下来就是一些经典的平衡树操作,例如 `split` 和 `merge` 用于分裂和合并平衡树,`insert` 和 `remove` 用于插入和删除节点,`kth` 和 `query_min` 用于查询平衡树中第 $k$ 小的数和最小值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值