题目:Luogu 1486
一道平衡树入门题,把员工工资的增减转化成工资下界的增减就可以了。
不过写指针版平衡树的坑很多,注意 maintain( ) 当前节点和调用儿子节点的值前判断是否为 NULL。
代码第95行在调用 cur->size 前需判断。
1 #include <cstdio> 2 #include <string> 3 #include <cstdlib> 4 5 const int N = 100005; 6 7 int read() { 8 int x = 0; char c = getchar(); 9 while (!isdigit(c)) c = getchar(); 10 while (isdigit(c)) { 11 x = (x << 3) + (x << 1) + (c ^ 48); 12 c = getchar(); 13 } return x; 14 } 15 16 int low, delt, tot; 17 18 struct Node { 19 Node *ch[2]; 20 int val, size, num, key; 21 void in(int x) { 22 val = x, size = num = 1, key = rand(), ch[0] = ch[1] = NULL; 23 } 24 int cmp(int x) { 25 return x == val ? -1 : x < val ? 0 : 1; 26 } 27 void maintain() { 28 size = num; 29 if (ch[0]) size += ch[0]->size; 30 if (ch[1]) size += ch[1]->size; 31 } 32 } *root, Pool[N << 1]; 33 34 Node *newNode() { 35 static int cnt = 0; 36 return &Pool[++cnt]; 37 } 38 39 void rotate(Node *&cur, int d) { 40 Node *tmp = cur->ch[d ^ 1]; 41 cur->ch[d ^ 1] = tmp->ch[d], tmp->ch[d] = cur; 42 cur->maintain(), tmp->maintain(); 43 cur = tmp; 44 } 45 46 void insert(Node *&cur, int val) { 47 if (!cur) cur = newNode(), cur->in(val); 48 else { 49 int d = cur->cmp(val); 50 if (d == -1) ++cur->num; 51 else { 52 insert(cur->ch[d], val); 53 if (cur->ch[d]->key > cur->key) rotate(cur, d ^ 1); 54 } 55 cur->maintain(); 56 } 57 } 58 59 void remove(Node *&cur) { 60 if (!cur) return; 61 if (cur->val >= low) remove(cur->ch[0]); 62 else { 63 tot += cur->num + (cur->ch[0] ? cur->ch[0]->size : 0); 64 cur->ch[0] = NULL; 65 remove(cur->ch[1]); 66 cur = cur->ch[1]; 67 } 68 if (cur) cur->maintain(); 69 } 70 71 int kth(Node *&cur, int k) { 72 if (!cur) return -1; 73 int ls = cur->ch[0] ? cur->ch[0]->size : 0; 74 if (ls + 1 <= k && k <= ls + cur->num) return cur->val; 75 if (ls >= k) return kth(cur->ch[0], k); 76 return kth(cur->ch[1], k - ls - cur->num); 77 } 78 79 int main() { 80 int n = read(); low = read(); 81 while (n--) { 82 char opt = getchar(); 83 while (opt != ‘I‘ && opt != ‘A‘ && opt != ‘S‘ && opt != ‘F‘) opt = getchar(); 84 int x = read(); 85 if (opt == ‘I‘) { 86 x += delt; 87 if (x < low) continue; 88 insert(root, x); 89 } else if (opt == ‘A‘) { 90 low -= x, delt -= x; 91 } else if (opt == ‘S‘) { 92 low += x, delt += x; 93 remove(root); 94 } else { 95 if (!root || x > root->size) puts("-1"); 96 else { 97 x = root->size - x + 1; 98 int ans = kth(root, x); 99 printf("%d\n", ans - delt); 100 } 101 } 102 } 103 printf("%d\n", tot); 104 return 0; 105 }