[模板]普通平衡树

【模板】普通平衡树

题目链接

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入 xx 数
  2. 删除 xx 数(若有多个相同的数,因只删除一个)
  3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
  4. 查询排名为 xx 的数
  5. 求 xx 的前驱(前驱定义为小于 xx ,且最大的数)
  6. 求 xx 的后继(后继定义为大于 xx ,且最小的数)

输入输出格式

输入格式:

第一行为 nn ,表示操作的个数,下面 nn 行每行有两个数 optopt 和 xx , optopt 表示操作的序号( 1 leq opt leq 61≤opt≤6 )

输出格式:

对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案

输入输出样例

输入样例#1:

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

输出样例#1:

106465
84185
492737

说明

时空限制:1000ms,128M

1.n的数据范围: (n≤100000)

2.每个数的数据范围: ([-10^7,10^7])

替罪羊树

学习总结

#include<bits/stdc++.h>
using namespace std;
int read()
{
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*w;
}
double alpha=0.75;
int n,x,opt,cnt,root,need,top;
int s[100010];
struct node{
    int son[2],v,die,s;
}t[100010];
bool exist(int k){return (t[k].die^1);}
bool bad(int k)
{
    int k1=t[k].son[0],k2=t[k].son[1];
    return (double)max(t[k1].s,t[k2].s)>=(double)t[k].s*alpha;
}
void dfs(int k)
{
    if(!k) return;
    dfs(t[k].son[0]);if(!t[k].die)s[++top]=k;dfs(t[k].son[1]);
}
void build(int &k,int l,int r)
{
    if(l>r)return;int mid=(l+r)/2;k=s[mid];
    if(l==r)
    {
        t[k].s=1;t[k].son[0]=t[k].son[1]=t[k].die=0;return;
    }
    if(l<mid) build(t[k].son[0],l,mid-1);else t[k].son[0]=0;
    if(r>mid) build(t[k].son[1],mid+1,r);else t[k].son[1]=0;
    t[k].s=t[t[k].son[0]].s+t[t[k].son[1]].s+1;return;
}
void rebuild(int &k)
{
    top=0;dfs(k);if(top)build(k,1,top);
}
void insert(int &k,int v)
{
    if(!k)
    {
        k=++cnt;t[k].v=v;t[k].s=1;return;
    }
    if(v<=t[k].v) insert(t[k].son[0],v);
    else insert(t[k].son[1],v);
    int k1=t[k].son[0],k2=t[k].son[1];
    t[k].s=t[k1].s+t[k2].s+exist(k);
    if(!bad(k))
    {
        if(need)
        {
            if(need==t[k].son[0]) rebuild(t[k].son[0]);
            else rebuild(t[k].son[1]);
        }
        need=0;
    }
    else need=k;
}
void delet(int k,int v)
{
    if(!k) return;
    int k1=t[k].son[0],k2=t[k].son[1];
    if(!t[k].die&&t[k1].s+1==v){t[k].die=1;t[k].s--;return;}
    if(t[k1].s>=v) delet(k1,v);
    else delet(k2,v-t[k1].s-exist(k));
    t[k].s=t[k1].s+t[k2].s+exist(k);
    if(!bad(k))
    {
        if(need)
        {
            if(need==t[k].son[0]) rebuild(t[k].son[0]);
            else rebuild(t[k].son[1]);
        }
        need=0;
    }
    else need=k;
}
int getrank(int k,int v)
{
    if(!k) return 0;
    int k1=t[k].son[0],k2=t[k].son[1];
    if(t[k].v<v) return t[k1].s+exist(k)+getrank(k2,v);
    return getrank(k1,v);
}
int kth(int k,int v)
{
    if(!k) return 0;
    int k1=t[k].son[0],k2=t[k].son[1];
    if(!t[k].die&&t[k1].s+1==v) return t[k].v;
    if(t[k1].s>=v) return kth(k1,v);
    return kth(k2,v-t[k1].s-exist(k));
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        opt=read();x=read();
        if(opt==1){insert(root,x);if(need)rebuild(root),need=0;}
        if(opt==2)
        {
            int d=getrank(root,x)+1;
            delet(root,d);
            if(need)rebuild(root),need=0;
        }
        if(opt==3) printf("%d
",getrank(root,x)+1);
        if(opt==4) printf("%d
",kth(root,x));
        if(opt==5) printf("%d
",kth(root,getrank(root,x)));
        if(opt==6) printf("%d
",kth(root,getrank(root,x+1)+1));
    }
}

Splay

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*w;
}
int root,cnt,inf=2100000000;
struct node{
int fa,son[2],size,cnt,v;
}tree[100010];
void push_up(int);
void splay(int,int);
bool get(int);
void rotate(int);
void insert(int);
void delet(int);
int getrank(int);
int getsum(int);
int find(int);
int kth(int,int);
int main()
{
    int n=read(),opt,x;
    insert(inf);insert(-inf);
    for(int i=1;i<=n;i++)
    {
        opt=read();x=read();
        if(opt==1) insert(x);
        else if(opt==2) delet(x);
        else if(opt==3) printf("%d
",getrank(x));
        else if(opt==4) printf("%d
",getsum(x+1));
        else if(opt==5) printf("%d
",tree[kth(x,0)].v);
        else if(opt==6) printf("%d
",tree[kth(x,1)].v);
    }
}
void push_up(int k)
{
    tree[k].size=tree[tree[k].son[0]].size+tree[tree[k].son[1]].size+tree[k].cnt;
}
bool get(int k)
{
    return k==tree[tree[k].fa].son[1];
}
void rotate(int k)
{
    int fa=tree[k].fa,gfa=tree[fa].fa,d1=get(k),d2=get(fa);
    tree[fa].son[d1]=tree[k].son[d1^1];tree[tree[k].son[d1^1]].fa=fa;
    tree[k].son[d1^1]=fa;tree[fa].fa=k;
    tree[gfa].son[d2]=k;tree[k].fa=gfa;
    push_up(fa);push_up(k);
}
void splay(int k,int goal)
{
    while(tree[k].fa!=goal)
    {
        int fa=tree[k].fa,gfa=tree[fa].fa,d1=get(k),d2=get(fa);
        if(gfa!=goal)
        {
            if(d1==d2) rotate(fa);
            else rotate(k);
        }
        rotate(k);
    }
    if(goal==0) root=k;
}
void insert(int k)
{
    int now=root,fa=0;
    while(tree[now].v!=k&&now)
    fa=now,now=tree[now].son[k>tree[now].v];
    if(now) 
    tree[now].cnt++;
    else
    {
        now=++cnt;
        if(fa) tree[fa].son[k>tree[fa].v]=now;
        tree[now].v=k;
        tree[now].fa=fa;
        tree[now].cnt=1;
        tree[now].size=1;
    }
    splay(now,0);
}
void delet(int k)
{
    int last=kth(k,0),next=kth(k,1);
    splay(last,0);splay(next,last);
    if(tree[tree[next].son[0]].cnt>1) 
    {
        tree[tree[next].son[0]].cnt--;
        splay(tree[next].son[0],0);
    }
    else tree[next].son[0]=0;
}
int find(int k)
{
    int now=root;
    while(tree[now].v!=k&&tree[now].son[tree[now].v<k])
    now=tree[now].son[tree[now].v<k];
    return now;
}
int getrank(int k)
{
    splay(find(k),0);
    return tree[tree[root].son[0]].size;
}
int getsum(int k)
{
    int now=root;
    while(1)
    {
        if(k>tree[tree[now].son[0]].size&&k<=tree[tree[now].son[0]].size+tree[now].cnt) return tree[now].v;
        else if(k>tree[tree[now].son[0]].size+tree[now].cnt) k-=tree[tree[now].son[0]].size+tree[now].cnt,now=tree[now].son[1];
        else now=tree[now].son[0];
    }
}
int kth(int k,int judge)
{
    int x=find(k);
    splay(x,0);
    if(judge==0&&k>tree[root].v) return root;
    if(judge==1&&k<tree[root].v) return root;
    int now=tree[root].son[judge];
    while(tree[now].son[judge^1])
    now=tree[now].son[judge^1];
    return now;
}
原文地址:https://www.cnblogs.com/lsgjcya/p/9349229.html