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

题目描述

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

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

输入格式

第一行为n,表示操作的个数,下面n行每行有两个数 opt和xopt 表示操作的序号(1opt6 )

输出格式

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

说明/提示

【数据范围】
对于100%的数据,1n105x107

来源:Tyvj1728 原名:普通平衡树

在此鸣谢

纯纯的模板题,可恶的是我竟调了两个小时,在第六个操作的时候将l写成了r。

复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
    int l,r,key,val,si;
}tr[200010];
int n,idx,dl,dr,tmp,rt;
int getrand(int x){
    tr[++idx].key = x;
    tr[idx].val = rand();
    tr[idx].si = 1;
    return idx;
}
void pushup(int p){
    tr[p].si = tr[tr[p].l].si+tr[tr[p].r].si+1;
}
void split(int p,int x,int &l,int &r){
    if(!p){
        l = r = 0;
        return ;
    }
    if(tr[p].key<=x){
        l = p;
        split(tr[l].r,x,tr[l].r,r);
    }else{
        r = p;
        split(tr[r].l,x,l,tr[r].l);
    }
    pushup(p);
}
int merge(int l,int r){
    if(!l||!r)
        return l|r;
    if(tr[l].val<=tr[r].val){
        tr[l].r = merge(tr[l].r,r);
        pushup(l);
        return l;
    }else{
        tr[r].l = merge(l,tr[r].l);
        pushup(r);
        return r;
    }
}
void insert(int x){
    split(rt,x-1,dl,dr);
    rt = merge(merge(dl,getrand(x)),dr);
}
void delet(int x){
    split(rt,x-1,dl,dr);
    split(dr,x,tmp,dr);
    tmp = merge(tr[tmp].l,tr[tmp].r);
    rt = merge(dl,merge(tmp,dr));
}
int getrk(int x){
    split(rt,x-1,dl,dr);
    int rnk = tr[dl].si+1;
    rt = merge(dl,dr);
    return rnk;
}
int getnum(int p,int x){
    int u = tr[tr[p].l].si+1;
    if(u==x) return tr[p].key;
    if(u>x) return getnum(tr[p].l,x);
    else return getnum(tr[p].r,x-u);
}
int main(){
    scanf("%d",&n);
    int op,x;
    while(n--){
        scanf("%d%d",&op,&x);
        if(op==1) insert(x);
        else if(op==2) delet(x);
        else if(op==3) printf("%d\n",getrk(x));
        else if(op==4) printf("%d\n",getnum(rt,x));
        else if(op==5){
            split(rt,x-1,dl,dr);
            printf("%d\n",getnum(dl,tr[dl].si));
            rt = merge(dl,dr);
        }else{
            split(rt,x,dl,dr);
            printf("%d\n",getnum(dr,1));
            rt = merge(dl,dr);
        }
    }
    return 0;
}
复制代码

 综上所述,我还是太弱了

2022-10-28 13:57:03

posted @   cztq  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示