平衡树裸题。
对于加减操作,可以用lazy-tag思想,对一个标记进行加减。然后添加结点和删除不符合条件结点时考虑一下标记即可。添加薪水为k的结点,就是在平衡树中添加k-tag的结点;删掉薪水小于minwage的结点,就是在平衡树中删除minwage-tag的结点。然后随意玩即可。
我是用treap实现的。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <algorithm> 4 5 using namespace std; 6 7 void Get_Val(int &Ret) 8 { 9 Ret = 0; 10 char ch; 11 bool Neg(false); 12 while (ch = getchar(), (ch > ‘9‘ || ch < ‘0‘) && ch != ‘-‘) 13 ; 14 if (ch == ‘-‘) 15 { 16 Neg = true; 17 while (ch = getchar(), ch > ‘9‘ || ch < ‘0‘) 18 ; 19 } 20 do 21 { 22 (Ret *= 10) += ch - ‘0‘; 23 } 24 while (ch = getchar(), ch >= ‘0‘ && ch <= ‘9‘); 25 if (Neg) 26 Ret = -Ret; 27 } 28 29 int N, Min_Wage; 30 int Tag; 31 int Ans_Del; 32 33 struct Treap 34 { 35 Treap(const int &v) : v(v), num(1), size(1) {priority = rand(); ch[0] = ch[1] = NULL;} 36 int priority; 37 int v; 38 int num, size; 39 Treap *ch[2]; 40 inline int cmp(const int &x) 41 { 42 return x == v ? -1 : x > v; 43 } 44 }; 45 46 void pushup(Treap *&o) 47 { 48 o -> size = o -> num; 49 if (o -> ch[0] != NULL) 50 o -> size += o -> ch[0] -> size; 51 if (o -> ch[1] != NULL) 52 o -> size += o -> ch[1] -> size; 53 } 54 55 void rotate(Treap *&o, const int &d) 56 { 57 Treap *k = o -> ch[d ^ 1]; 58 o -> ch[d ^ 1] = k -> ch[d]; 59 k -> ch[d] = o; 60 pushup(o), pushup(k); 61 o = k; 62 } 63 64 void insert(Treap *&o, const int &v) 65 { 66 if (o == NULL) 67 o = new Treap(v); 68 else 69 { 70 int d = o -> cmp(v); 71 if (d == -1) 72 ++(o -> num); 73 else 74 { 75 insert(o -> ch[d], v); 76 if (o -> ch[d] -> priority > o -> priority) 77 rotate(o, d ^ 1); 78 } 79 } 80 pushup(o); 81 } 82 83 void remove(Treap *&o, const int &v) //删掉所有小于v的结点 84 { 85 if (o == NULL) 86 return; 87 int d = o -> cmp(v); 88 if (d == -1) 89 { 90 Ans_Del += (o -> ch[0] == NULL ? 0 : o -> ch[0] -> size); 91 o -> ch[0] = NULL; 92 } 93 else 94 if (d == 1) 95 { 96 Ans_Del += (o -> ch[0] == NULL ? 0 : o -> ch[0] -> size) + o -> num; 97 remove(o -> ch[1], v); 98 o = o -> ch[1]; 99 } 100 else 101 remove(o -> ch[0], v); 102 if (o != NULL) 103 pushup(o); 104 } 105 106 int kth(Treap *o, const int &k) 107 { 108 if (o == NULL) 109 return 0; 110 int s = o -> ch[1] == NULL ? 0 : o -> ch[1] -> size; 111 if (k > s && k <= s + o -> num) 112 return o -> v; 113 if (k <= s) 114 return kth(o -> ch[1], k); 115 else 116 return kth(o -> ch[0], k - (s + o -> num)); 117 } 118 119 Treap *root; 120 121 int main() 122 { 123 srand(20160224); 124 root = NULL; 125 char op[2]; 126 int k; 127 Get_Val(N), Get_Val(Min_Wage); 128 while (N--) 129 { 130 scanf("%s", op), Get_Val(k); 131 if (*op == ‘I‘) 132 if (k >= Min_Wage) 133 insert(root, k - Tag); 134 if (*op == ‘A‘) 135 Tag += k; 136 if (*op == ‘S‘) 137 { 138 Tag -= k; 139 remove(root, Min_Wage - Tag); 140 } 141 if (*op == ‘F‘) 142 if (root == NULL || k > root -> size) 143 printf("-1\n"); 144 else 145 printf("%d\n", kth(root, k) + Tag); 146 } 147 printf("%d\n", Ans_Del); 148 return 0; 149 }
BZOJ 1503
时间: 2024-10-06 20:42:21