AVL平衡树(版)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
 
const int MAXN=500005;
const int inf=0x3f3f3f3f;
using namespace std;
struct node{
    int lc,rc,h,data,num;
}tree[MAXN+5];
int cnt,root;
 
inline void Read(int &Ret){
    char ch;bool flag=0;
    for(;ch=getchar(),ch<'0'||ch>'9';)if(ch=='-')flag=1;
    for(Ret=ch-'0';ch=getchar(),'0'<=ch&&ch<='9';Ret=Ret*10+ch-'0');
    flag&&(Ret=-Ret);
}
inline void update(int i){
    tree[i].h=max(tree[tree[i].lc].h,tree[tree[i].rc].h)+1;
    tree[i].num=tree[tree[i].lc].num+tree[tree[i].rc].num+1;
}
int zig(int i){
    int t=tree[i].lc;
    tree[i].lc=tree[t].rc;
    tree[t].rc=i;
    update(i); update(t);
    return t;
}
int zag(int i){
    int t=tree[i].rc;
    tree[i].rc=tree[t].lc;
    tree[t].lc=i;
    update(i); update(t);
    return t;
}
int zigzag(int i){
    tree[i].rc=zig(tree[i].rc);
    return zag(i);
}
int zagzig(int i){
    tree[i].lc=zag(tree[i].lc);
    return zig(i);
}
 
void maintain(int &i){
    if(tree[tree[i].lc].h==tree[tree[i].rc].h+2)
    {
        int t=tree[i].lc;
        if(tree[tree[t].rc].h==tree[tree[i].rc].h+1) i=zagzig(i);
        else if(tree[tree[t].lc].h==tree[tree[i].rc].h+1) i=zig(i);
    }
    else if(tree[tree[i].rc].h==tree[tree[i].lc].h+2)
    {
        int t=tree[i].rc;
        if(tree[tree[t].lc].h==tree[tree[i].lc].h+1) i=zigzag(i);
        else if(tree[tree[t].rc].h==tree[tree[i].lc].h+1) i=zag(i);
    }
    update(i);
}
void Insert(int &i,int x){
    if(!i)
    {
        tree[++cnt].data=x;
        tree[cnt].h=tree[cnt].num=1;
        i=cnt; return;
    }
    if(x<=tree[i].data) Insert(tree[i].lc,x);
    else Insert(tree[i].rc,x);
    maintain(i); return;
}
int Delete(int &i,int x){
    int res;
    if(tree[i].data==x||(x>tree[i].data&&!tree[i].rc)||(x<tree[i].data&&!tree[i].lc))
    {
        res=tree[i].data;
        if(!tree[i].rc||!tree[i].lc)
            {i=tree[i].rc+tree[i].lc;return res;}
        else tree[i].data=Delete(tree[i].lc,x);
    }
    else
    {
        if(x<tree[i].data) res=Delete(tree[i].lc,x);
        else res=Delete(tree[i].rc,x);
    }
    maintain(i); return res;
}
int getdata(int i,int x){
    if(!i) return 0;
    if(tree[tree[i].lc].num+1==x)
        return tree[i].data;
    else if(tree[tree[i].lc].num+1>x) return getdata(tree[i].lc,x);
    else return getdata(tree[i].rc,x-tree[tree[i].lc].num-1);
}
int getrank(int i,int x){
    if(!i) return 1;
    if(x<=tree[i].data) return getrank(tree[i].lc,x);
    else  return tree[tree[i].lc].num+1+getrank(tree[i].rc,x);
}
int lower(int x){
    int i=root,res=-inf;
    while(i)
    {
        if(tree[i].data==x) i=tree[i].lc;
        else if(tree[i].data<x)
            res=max(res,tree[i].data),i=tree[i].rc;
        else i=tree[i].lc;
    }
    return res;
}
int upper(int x){
    int i=root,res=inf;
    while(i)
    {
        if(tree[i].data==x) i=tree[i].rc;
        else if(tree[i].data>x)
            res=min(res,tree[i].data),i=tree[i].lc;
        else i=tree[i].rc;
    }
    return res;
}
int main()
{
    int n,opt,x; Read(n);
    for(int i=1;i<=n;i++)
    {
        Read(opt); Read(x);
        switch(opt)
        {
            case 1: Insert(root,x); break;
            case 2: Delete(root,x); break;
            case 3: printf("%d\n",getrank(root,x)); break;
            case 4: printf("%d\n",getdata(root,x)); break;
            case 5: printf("%d\n",lower(x)); break;
            case 6: printf("%d\n",upper(x)); break;
        }
    }
    return 0;
}
 




这其实是一道题,但是差不多就是一个模板了,附上题目:
你需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入一个整数x
2. 删除一个整数x(若有多个相同的数,只删除一个)
3. 查询整数x的排名(若有多个相同的数,输出最小的排名),相同的数依次排名,不并列排名
4. 查询排名为x的数,排名的概念同3
5. 求x的前驱(前驱定义为小于x,且最大的数),保证x有前驱
6. 求x的后继(后继定义为大于x,且最小的数),保证x有后继
输入

第一行为n,表示操作的个数(n <= 500000)

下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6,   -10^7 <= x <= 10^7)

大规模输入数据,建立读入优化

输出

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



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值