洛谷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