优雅即是暴力!
替罪羊树的构建其实就是暴力的构建。
-> 即每次插入的时候我们都判断是否需要重构。
要注意什么什么时候传的是一个引用,什么时候不需要传引用
1 #include <stdio.h> 2 #include <algorithm> 3 #include <iostream> 4 #include <stdbool.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <stack> 8 #include <map> 9 #include <vector> 10 11 #define INF 0x3f3f3f3f 12 using namespace std; 13 const int maxn = 1e5 + 5; 14 const double alpha = 0.75; 15 16 17 struct Node { 18 int l,r,val; 19 int size,fact; 20 bool exist; 21 }tzy[maxn]; 22 23 int cnt,root; 24 25 void newnode(int &now,int val){ 26 now = ++cnt; 27 tzy[now].val = val; 28 tzy[now].size = tzy[now].fact = 1; 29 tzy[now].exist = true; 30 } 31 32 33 // 判断是否需要重构的条件: 34 // 当前结点的左子树或右子树的大小大于当前结点的大小 或者 以当前结点为根的子树内被删除结点的个数大于该结点个数的30% 35 bool imbalence(int now){ 36 if (max(tzy[tzy[now].l].size,tzy[tzy[now].r].size) > tzy[now].size*alpha 37 ||tzy[now].size-tzy[now].fact>tzy[now].size*0.3){ 38 return true; 39 } 40 return false; 41 } 42 43 vector<int > v; 44 45 void ldr(int now){ // 中序遍历 46 if (!now) 47 return ; 48 ldr(tzy[now].l); 49 if (tzy[now].exist) 50 v.push_back(now); 51 ldr(tzy[now].r); 52 } 53 54 void lift(int l,int r,int &now){ // now代表当前拎到哪里 55 if (l == r){ 56 now = v[l]; 57 tzy[now].l = tzy[now].r = 0; 58 tzy[now].size = tzy[now].fact = 1; 59 return ; 60 } 61 int m = (l + r) >> 1; 62 while (l < m && tzy[v[m]].val == tzy[v[m-1]].val) 63 m--; 64 now = v[m]; 65 if (l < m) 66 lift(l,m-1,tzy[now].l); 67 else 68 tzy[now].l = 0; 69 lift(m+1,r,tzy[now].r); 70 tzy[now].size = tzy[tzy[now].l].size + tzy[tzy[now].r].size + 1; 71 tzy[now].fact = tzy[tzy[now].l].fact + tzy[tzy[now].r].size + 1; 72 } 73 74 void rebuild(int &now){ // 重构now这个点 75 v.clear(); 76 ldr(now); 77 if (v.empty()){ 78 now = 0; 79 return ; 80 } 81 lift(0,v.size()-1,now); 82 } 83 84 void update(int now,int end){ 85 if (!now){ 86 return; 87 } 88 if (tzy[end].val < tzy[now].val){ 89 update(tzy[now].l,end); 90 } 91 else 92 update(tzy[now].r,end); 93 tzy[now].size = tzy[tzy[now].l].size + tzy[tzy[now].r].size; 94 } 95 96 void check(int &now,int end){ 97 if (now == end){ 98 return; 99 } 100 if (imbalence(now)){ 101 rebuild(now); 102 update(now,end); 103 return ; 104 } 105 if (tzy[end].val < tzy[now].val){ 106 check(tzy[now].l,end); 107 } 108 else 109 check(tzy[now].r,end); 110 } 111 112 void ins(int &now,int val){ 113 if (!now){ 114 newnode(now,val); 115 check(root,now); 116 return ; 117 } 118 tzy[now].size++; 119 tzy[now].fact++; 120 if (val < tzy[now].val){ 121 ins(tzy[now].l,val); 122 } 123 else 124 ins(tzy[now].r,val); 125 } 126 127 void del(int now,int val){ 128 if (tzy[now].exist && tzy[now].val == val){ 129 tzy[now].exist = false; 130 tzy[now].fact--; 131 check(root,now); 132 return ; 133 } 134 tzy[now].fact--; 135 if (val < tzy[now].val) 136 del(tzy[now].l,val); 137 else 138 del(tzy[now].r,val); 139 } 140 141 int getrank(int val){ 142 int now = root,rank = 1; 143 while (now){ 144 if (val <= tzy[now].val) 145 now = tzy[now].l; 146 else{ 147 rank += tzy[now].exist+tzy[tzy[now].l].fact; 148 now = tzy[now].r; 149 } 150 } 151 return rank; 152 } 153 154 int getnum(int rank) 155 { 156 int now=root; 157 while(now) 158 { 159 if(tzy[now].exist&&tzy[tzy[now].l].fact+tzy[now].exist==rank) 160 break; 161 else if(tzy[tzy[now].l].fact>=rank) 162 now=tzy[now].l; 163 else 164 { 165 rank-=tzy[tzy[now].l].fact+tzy[now].exist; 166 now=tzy[now].r; 167 } 168 } 169 return tzy[now].val; 170 } 171 172 int main(){ 173 int t; 174 scanf("%d",&t); 175 while(t--) 176 { 177 int opt,x; 178 scanf("%d%d",&opt,&x); 179 switch(opt) 180 { 181 case 1: 182 ins(root,x); 183 break; 184 case 2: 185 del(root,x); 186 break; 187 case 3: 188 printf("%d ",getrank(x)); 189 break; 190 case 4: 191 printf("%d ",getnum(x)); 192 break; 193 case 5: 194 printf("%d ",getnum(getrank(x)-1)); 195 break; 196 case 6: 197 printf("%d ",getnum(getrank(x+1))); 198 break; 199 } 200 } 201 return 0; 202 }