其他分享
首页 > 其他分享> > 洛谷P3369 【模板】普通平衡树(无旋treap数组版)

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

作者:互联网

题目传送门: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