P3369 【模板】普通平衡树 treap树旋转版

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include<bits/stdc++.h>
#define INF INT_MAX
using namespace std;
const int maxn=100010;
int sum=0,R=0;
int sz[maxn],v[maxn],num[maxn],rd[maxn],son[maxn][2];
//更新p子树的大小
void pushup(int p){
     sz[p]=sz[son[p][0]]+sz[son[p][1]]+num[p];
}
//旋转
void rot(int&p,int d){
     int k=son[p][d^1];
     son[p][d^1]=son[k][d];
     son[k][d]=p;
     pushup(p);
     pushup(k);
     p=k;
}
//插入
void ins(int &p,int x){
     if (!p){
        p=++sum;
        sz[p]=num[p]=1;
        v[p]=x;
        rd[p]=rand();
        return ;
     }
     if(v[p]==x){
        num[p]++;
        sz[p]++;
        return ;
     }
     int d=(x>v[p]);//右子树
     ins(son[p][d],x);
     if (rd[p]<rd[son[p][d]]) rot(p,d^1);
     pushup(p);
}
//删除
void del(int &p,int x){
     if(!p) return ;
     if(x<v[p]) del(son[p][0],x);
     else if(x>v[p]) del(son[p][1],x);
     else {
          if(!son[p][0]&&!son[p][1]){
              num[p]--;sz[p]--;
              if (!num[p]) p=0;
          }
          else if(!son[p][1]){
               rot(p,1);
               del(son[p][1],x);
          }
          else if(!son[p][0]){
               rot(p,0);
               del(son[p][0],x);
          }
          else{
               int d=(rd[son[p][0]]>rd[son[p][1]]);
               rot(p,d);
               del(son[p][d],x);
          }
     }
     pushup(p);
}
//x的排名
int get_rank(int p,int x){
    if(!p) return 0;
    if(v[p]==x) return sz[son[p][0]]+1;
    if(v[p]<x) return sz[son[p][0]]+num[p]+get_rank(son[p][1],x);
    if(v[p]>x) return get_rank(son[p][0],x);
}
//排名x的值
int func_find(int p,int x){
    if(!p) return 0;
    if(sz[son[p][0]]>=x) return func_find(son[p][0],x);
    else if(sz[son[p][0]]+num[p]<x)
         return func_find(son[p][1],x-num[p]-sz[son[p][0]]);
    else return v[p];
}
//前驱
int pre(int p,int x){
    if (!p) return -INF;
    if (v[p]>=x) return pre(son[p][0],x);
    else return max(v[p],pre(son[p][1],x));
}
//后继
int suc(int p,int x){
    if (!p) return INF;
    if(v[p]<=x) return suc(son[p][1],x);
    else return min(v[p],suc(son[p][0],x));
}
int main()
{
    int n,op,x;
    cin>>n;
    while(n--)
    {
        cin>>op>>x;
        if (op==1) ins(R,x);
        else if(op==2) del(R,x);
        else if(op==3) cout<<get_rank(R,x)<<endl;
        else if(op==4) cout<<func_find(R,x)<<endl;
        else if(op==5) cout<<pre(R,x)<<endl;
        else if(op==6) cout<<suc(R,x)<<endl;
    }
}

  

posted @   心悟&&星际  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示