bzoj3065: 带插入区间K小值
无聊来写了下
一开始发现树高是O(n)的,然后就MLE了,进去看了下发现没有重构!
看了半天发现调用错了函数
然后进去又发现不满足sz = ch[0]->sz + ch[1]->sz + 1
然而全都是maintain过的啊
发现后来受某个代码的影响
返回重建节点时把引用去掉了
这样这个点的父亲的信息就不对了
又仔细去看了一下那个人为什么这样做没问题
结果他每次都把内存回收了,而且重建的根节点是最后删除第一个拿出来的(然后他竟然用的队列,当我什么都没说,我还是不知道为什么是对的。。)
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<iostream> 6 //#include<cassert> 7 8 using namespace std; 9 10 #define ALL_VALUE 0, 70000 11 const int N = 70000 + 10; 12 13 int CNT1 = 0, CNT2 = 0; 14 15 namespace ST { 16 struct Node *stk[N * 60]; int top; 17 struct Node { 18 int sz; 19 Node* ch[2]; 20 21 Node() {} 22 Node(int sz) : sz(sz) { 23 ch[0] = ch[1] = 0; 24 } 25 26 void *operator new (size_t) { 27 // if(!++CNT1 % 100000) cerr << CNT1 << endl; 28 if(top) return stk[top--]; 29 static Node *pis; 30 static int left = 0; 31 if(!left) left = N, pis = new Node[N] (); 32 return left--, pis++; 33 } 34 35 void operator delete(void *p) { 36 // ++CNT2; 37 stk[++top] = (Node*) p; 38 } 39 }; 40 41 #define mid ((l + r) >> 1) 42 #define ls o->ch[0], l, mid 43 #define rs o->ch[1], mid + 1, r 44 45 void insert(Node*& o, int l, int r, int v, int d) { 46 if(!o) o = new Node(0); 47 o->sz += d; 48 if(l == r) return; 49 if(v <= mid) insert(ls, v, d); 50 else insert(rs, v, d); 51 if(!o->sz) delete o, o = 0; 52 } 53 54 int query(Node* o, int l, int r, int v) {// <=v µÄÊýµÄ¸öÊý 55 if(!o) return 0; 56 if(r <= v) return o->sz; 57 return query(ls, v) + (v > mid ? query(rs, v) : 0); 58 } 59 60 void remove(Node*& o) { 61 if(!o) return; 62 remove(o->ch[0]); 63 remove(o->ch[1]); 64 delete o, o = 0; 65 } 66 67 #undef mid 68 #undef ls 69 #undef rs 70 } 71 72 int a[N], dep = 0; 73 74 namespace SGT { 75 struct Node *pis; 76 struct Node { 77 int sz, v; 78 79 Node *ch[2]; 80 ST::Node *da; 81 82 int cmp(int k) const { 83 int s = ch[0]->size() + 1; 84 if(s == k) return -1; 85 return k < s ? 0 : 1; 86 } 87 88 Node(int v = 0) : v(v) { 89 ch[0] = ch[1] = 0; 90 da = 0; 91 sz = 1; 92 } 93 94 int size() const { 95 return this ? sz : 0; 96 } 97 98 void maintain() { 99 sz = ch[0]->size() + ch[1]->size() + 1; 100 } 101 102 int query(int k, int v) const {//²éѯ1-kÀï <= vµÄÊýµÄÊýÁ¿ 103 if(!this || !k) return 0; 104 // cerr << ch[0]->size() << endl; 105 if(ch[0]->size() >= k) return ch[0]->query(k, v); 106 return (ch[0] ? ST::query(ch[0]->da, ALL_VALUE, v) : 0) + (this->v <= v) + ch[1]->query(k - ch[0]->size() - 1, v); 107 } 108 109 void *operator new(size_t) { 110 return pis++; 111 } 112 }*null, *root, pool[N]; 113 114 Node *rec[N]; int tot; 115 116 void print(Node *o) { 117 if(!o) return; 118 print(o->ch[0]); 119 ST::remove(o->da); 120 rec[++tot] = o; 121 print(o->ch[1]); 122 } 123 124 /*void check(Node *o) { 125 if(!o) return; 126 assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1); 127 check(o->ch[0]); 128 check(o->ch[1]); 129 }*/ 130 131 void rebuild(Node*& o, int l, int r) { 132 if(l > r) return o = 0, void(); 133 int mid = (l + r) >> 1; 134 o = rec[mid]; 135 for(int i = l; i <= r; i++) ST::insert(o->da, ALL_VALUE, rec[i]->v, 1); 136 rebuild(o->ch[0], l, mid - 1); 137 rebuild(o->ch[1], mid + 1, r); 138 o->maintain(); 139 // assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1); 140 } 141 142 void build(Node*& o, int l, int r) { 143 if(l > r) return; 144 int mid = (l + r) >> 1; 145 o = new Node(a[mid]); 146 for(int i = l; i <= r; i++) ST::insert(o->da, ALL_VALUE, a[i], 1); 147 build(o->ch[0], l, mid - 1); 148 build(o->ch[1], mid + 1, r); 149 o->maintain(); 150 } 151 152 Node*& insert(Node*& o, int k, int x) { // ÔÚµÚx¸öλÖúó²åÈëx 153 if(!o) { 154 o = new Node(x); 155 ST::insert(o->da, ALL_VALUE, x, 1); 156 return null; 157 } 158 // assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1); 159 int d = o->ch[0]->size() >= k ? 0 : 1; 160 if(d == 1) k -= o->ch[0]->size() + 1; 161 Node*& res = insert(o->ch[d], k, x); 162 o->maintain(); 163 ST::insert(o->da, ALL_VALUE, x, 1); 164 if(o->ch[d]->size() > o->size() * 0.75) return o; 165 else return res; 166 // assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1); 167 } 168 169 int modify(Node*& o, int k, int x) { 170 // assert(o->sz == o->ch[0]->size() + o->ch[1]->size() + 1); 171 int d = o->cmp(k), old; 172 if(d == 1) k -= o->ch[0]->size() + 1; 173 if(d == -1) old = o->v, o->v = x; 174 else old = modify(o->ch[d], k, x); 175 ST::insert(o->da, ALL_VALUE, old, -1); 176 ST::insert(o->da, ALL_VALUE, x, 1); 177 return old; 178 } 179 180 void insert(int k, int x) { 181 // SGT::check(SGT::root); 182 Node*& res = insert(root, k, x); 183 // SGT::check(SGT::root); 184 if(res != null) { 185 tot = 0; 186 print(res); 187 rebuild(res, 1, tot); 188 // SGT::check(SGT::root); 189 } 190 } 191 } 192 193 int query(int l, int r, int k) { 194 int L = 0, R = 70000, res = -1; 195 while(L <= R) { 196 int mid = (L + R) >> 1; 197 int t1 = SGT::root->query(r, mid); 198 int t2 = SGT::root->query(l - 1, mid); 199 if(t1 - t2 >= k) R = mid - 1, res = mid; 200 else L = mid + 1; 201 } 202 return res; 203 } 204 205 int main() { 206 #ifdef DEBUG 207 freopen("in.txt", "r", stdin); 208 freopen("out.txt", "w", stdout); 209 #endif 210 211 SGT::pis = SGT::pool; 212 213 int x, n, m; 214 scanf("%d", &n); 215 216 for(int i = 1; i <= n; i++) { 217 scanf("%d", a + i); 218 } 219 220 int la = 0; 221 222 SGT::build(SGT::root, 1, n); 223 224 scanf("%d", &m); 225 char opt[10]; int y, k, v; 226 227 for(int i = 1; i <= m; i++) { 228 // if(i == 2859) 229 // int debug = 1; 230 // SGT::check(SGT::root); 231 232 scanf("%s", opt); 233 if(opt[0] == 'Q') { 234 scanf("%d%d%d", &x, &y, &k); 235 x ^= la, y ^= la, k ^= la; 236 printf("%d\n", query(x, y, k)); 237 }else if(opt[0] == 'M') { 238 scanf("%d%d", &x, &v); 239 x ^= la, v ^= la; 240 SGT::modify(SGT::root, x, v); 241 }else { 242 scanf("%d%d", &x, &v); 243 x ^= la, v ^= la; 244 // int last = CNT1; dep = 0; 245 SGT::insert(x - 1, v); 246 // cerr << SGT::root->sz << endl; 247 // cerr << CNT1 - last << ' ' << dep << endl; 248 } 249 } 250 251 return 0; 252 }
原文出处http://www.cnblogs.com/showson/