P3369 【模板】普通平衡树 平衡树

  

题目描述

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

  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 61opt6 )

输出格式

对于操作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


维护权值的平衡树模板题
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define pb push_back
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
typedef pair<int,int>pii;
//////////////////////////////////
const int N=2e6+10;


int son[N][2],fa[N],siz[N],cnt[N],val[N],ncnt,root;

int chk(int x)
{
    return son[fa[x]][1]==x;
}

void up(int x)
{
    siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
}

void rotate(int x)
{
    int y=fa[x],z=fa[y],k=chk(x),w=son[x][k^1];
    son[y][k]=w;fa[w]=y;
    son[z][chk(y)]=x;fa[x]=z;
    son[x][k^1]=y;fa[y]=x;
    up(x);up(y);
}

void splay(int x,int goal=0)
{
    while(fa[x]!=goal)
    {
        int y=fa[x],z=fa[y];
        if(z!=goal)
        {
            if(chk(y)==chk(z))rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
    if(!goal)root=x;
}

void find(int x)
{
    if(!root)return ;
    int pos=root;
    while(son[pos][x>val[pos]]&&x!=val[pos])
    pos=son[pos][x>val[pos]];

    splay(pos);
}


void insert(int x)
{
    int pos=root,p=0;
    while(pos&&val[pos]!=x)
    {
        p=pos;
        pos=son[pos][x>val[pos]];
    }
    if(pos)cnt[pos]++;
    else
    {
        pos=++ncnt;
        if(p)son[p][x>val[p]]=pos;
        son[pos][0]=son[pos][1]=0;
        val[pos]=x;fa[pos]=p;
        cnt[pos]=siz[pos]=1;
    }
    splay(pos);
}

int kth(int k)
{
    int pos=root;
    while(1)
    {
        if(son[pos][0]&&siz[son[pos][0]]>=k)
        pos=son[pos][0];
        else if(k>siz[son[pos][0]]+cnt[pos])
        k-=siz[son[pos][0]]+cnt[pos],pos=son[pos][1];
        else {splay(pos);return pos;}
    }
}


int pre(int x)
{
    find(x);
    if(val[root]<x)return root;
    int pos=son[root][0];
    while(son[pos][1])pos=son[pos][1];
    splay(pos);return pos;
}

int succ(int x)
{
    find(x);
    if(val[root]>x)return root;
    int pos=son[root][1];
    while(son[pos][0])pos=son[pos][0];
    splay(pos);return pos;
}

void remove(int x)
{
    int last=pre(x),nex=succ(x);
    splay(last);splay(nex,last);
    int pos=son[nex][0];
    if(cnt[pos]>1)
    {
        cnt[pos]--;splay(pos);
    }
    else son[nex][0]=0;
    up(root);up(nex);
}

void rank1(int x)
{
    find(x);
    if(val[root]<=x) printf("%d\n",siz[son[root][0]]);
    else if(val[root]>x) printf("%d\n",siz[son[root][0]]+cnt[root]);


int main()
{
    int m;cin>>m; int a,b;
    insert(0x3f3f3f3f);
    insert(0xcfcfcfcf);
    while(m--)
    {
       scanf("%d%d",&a,&b);
        if(a==1)insert(b);
        if(a==2)remove(b);
        if(a==3)rank1(b);
        if(a==4)printf("%d\n", val[kth(b+1)] );
        if(a==5)printf("%d\n",val[pre(b)]);
        if(a==6)printf("%d\n",val[succ(b)]);
    }
    return 0;
}
View Code




猜你喜欢

转载自www.cnblogs.com/bxd123/p/11297914.html