ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷P3369 【模板】普通平衡树(无旋treap数组版)

2022-07-24 10:35:01  阅读:173  来源: 互联网

标签:洛谷 val int 无旋 tree tot treap now left


题目传送门:https://www.luogu.com.cn/problem/P3369

模板:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<iostream>
  5 using namespace std;
  6 const int MAXN = 100005;
  7 const int MOD = 2147483647;
  8 
  9 struct Node
 10 {
 11      int left;      //左子树
 12      int right;     //右子树
 13      int size;      //大小
 14      int val;       //值
 15      int key;       //平衡种子
 16 }tree[MAXN];
 17 
 18 int root,tot;
 19 
 20 int add(int val){
 21     tot++;
 22     tree[tot].size = 1;
 23     tree[tot].val = val;
 24     tree[tot].key = rand()%MOD;
 25     tree[tot].left = 0;
 26     tree[tot].right = 0;
 27 
 28     return tot;
 29 }
 30 
 31 void update_root(int now){
 32     int left,right;
 33 
 34     left = tree[now].left;
 35     right = tree[now].right;
 36 
 37     tree[now].size = tree[left].size + tree[right].size + 1;
 38 }
 39 
 40 //拆分(now原treap,a左子树,b右子树,val值)
 41 void split_new(int now, int &a, int &b, int val){
 42     if(now == 0){
 43         a = 0;
 44         b = 0;
 45         return;
 46     }
 47 
 48     if(tree[now].val <= val){//now左子树中的所有值都小于now,
 49         a = now;
 50         split_new(tree[now].right, tree[a].right, b, val);
 51     }else{
 52         b = now;
 53         split_new(tree[now].left, a, tree[b].left, val);
 54     }
 55 
 56     update_root(now);
 57 }
 58 
 59 void merge_new(int &now, int a, int b){
 60     if(a==0 || b==0){
 61         now = a+b;
 62         return;
 63     }
 64 
 65     //按照key值合并(堆性质)
 66     if(tree[a].key<tree[b].key){
 67         /**
 68          * a树key值小于b树,那么b树属于a树的后代,因为b树恒大于a树,那么b树一定属于a树的右后代,
 69          * a的左子树不变,直接赋给now,递归合并a的右子树和b
 70          */
 71         now = a;
 72         merge_new(tree[now].right, tree[a].right, b);
 73     }else{
 74         now = b;
 75         merge_new(tree[now].left, a, tree[b].left);
 76     }
 77 
 78     update_root(now);
 79 }
 80 
 81 void find_new(int now, int rank){//找第k大
 82     while (tree[tree[now].left].size+1 != rank){
 83         if(tree[tree[now].left].size >= rank){
 84             now = tree[now].left;
 85         }else{
 86             rank -= tree[tree[now].left].size + 1;
 87             now = tree[now].right;
 88         }
 89     }
 90     cout << tree[now].val << "\n";
 91 }
 92 
 93 void insert_new(int val){
 94     int x,y,z;
 95 
 96     x = 0;
 97     y = 0;
 98     z = add(val);
 99     split_new(root, x, y, val);
100     merge_new(x,x,z);
101     merge_new(root, x, y);
102 }
103 
104 void del_new(int val){
105     int x,y,z;
106 
107     x = y = z = 0;
108     split_new(root, x, y, val);
109     split_new(x, x, z, val-1);
110     merge_new(z, tree[z].left, tree[z].right);
111     merge_new(x, x, z);
112     merge_new(root, x, y);
113 }
114 
115 void get_rank(int val){
116     int x,y;
117 
118     x = y = 0;
119     split_new(root, x, y, val-1);
120     cout << tree[x].size + 1 << "\n";
121     merge_new(root,x,y);
122 }
123 
124 void get_val(int rank){
125     find_new(root, rank);
126 }
127 
128 void get_pre(int val){
129     int x,y;
130 
131     x = y = 0;
132     split_new(root, x, y, val-1);
133     find_new(x, tree[x].size);
134     merge_new(root, x, y);
135 }
136 
137 void get_next(int val){
138     int x,y;
139 
140     x = y = 0;
141     split_new(root,x,y,val);
142     find_new(y,1);
143     merge_new(root,x,y);
144 }
145 
146 
147 int main(){
148     
149     ios::sync_with_stdio(false);
150     cin.tie(0);
151     
152     int n,op,x,i;
153     cin >> n;
154 
155     memset(tree, 0, sizeof(tree));
156 
157     add(MOD);
158     root = 1;
159     tree[root].size = 0;
160 
161     for(i=0;i<n;i++){
162         cin >> op >> x;
163 
164         switch (op){
165             case 1:
166                 insert_new(x);
167                 break;
168             case 2:
169                 del_new(x);//删除x数(若有多个相同的数,则只删除一个)
170                 break;
171             case 3:
172                 get_rank(x);//查询x数的排名(排名定义为比当前数小的数的个数+1,若有多个相同的数则输出最小的排名)
173                 break;
174             case 4:
175                 get_val(x);//查询排名为x的数
176                 break;
177             case 5:
178                 get_pre(x);//求x的前驱(前驱定义为小于x,且最大的数)
179                 break;
180             case 6:
181                 get_next(x);//求x的后继(后继定义为大于x,且最小的数)
182                 break;
183         }
184     }
185     
186     return 0;
187 }

 

 

标签:洛谷,val,int,无旋,tree,tot,treap,now,left
来源: https://www.cnblogs.com/wabi/p/16514006.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有