【封装】替罪羊树

NCC79601

2019-04-09 13:35:06

Personal

替罪羊树学会好久了,但是从来没有认真用$class$成功封装过。这里记录一种封装了正常$BST$操作的$class$,供以后复习使用。 实际上这是一种比较奇葩的写法,在查询前驱后继的时候比较暴力,导致常数大了一些,不过拿去跑二逼平衡树**不吸氧**也是能过的。~~暴力大法好啊~~ 这里所谓的**暴力写法** 就是这个地方: ```cpp inline int Prefix(int x, int v) { if(!x) return -INF; if(v(x) < v) { if(c(x)) return max(v(x), Prefix(r(x), v)); else return max(Prefix(l(x), v), Prefix(r(x), v)); } else return Prefix(l(x), v); } inline int Suffix(int x, int v) { if(!x) return INF; if(v(x) > v) { if(c(x)) return min(v(x), Suffix(l(x), v)); else return min(Suffix(r(x), v), Suffix(l(x), v)); } else return Suffix(r(x), v); } ``` 注意第二层$if()$的$else$,是不是非常暴力!当前节点不存在就**合并左右儿子的信息**,因为你也不知道左右儿子到底存不存在。要想完美地解决这个判断问题非常麻烦,因此我干脆就不解决了,直接拉常数解决,~~反正不太可能会TLE~~ 注意使用前需要$Init()$,以为低版本C++是不支持在$private$里头初始化的。 --- 完整代码 ```cpp #include<bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 10; const double alpha = 0.67; const int INF = 2147483647; class ScapeGoatTree { #define l(x) tree[x].lson #define r(x) tree[x].rson #define v(x) tree[x].val #define s(x) tree[x].size #define c(x) tree[x].cnt #define d(x) tree[x].del private: int cnt; int cache[MAXN]; int len; struct BST { int lson, rson; int val, size, cnt, del; } tree[MAXN]; inline void update(int &x) { s(x) = s(l(x)) + s(r(x)) + c(x); d(x) = d(l(x)) + d(r(x)) + c(x); return; } inline bool isbad(int x) { return ((double)s(x) * alpha > d(x)) || ((double)s(x) * alpha < max(s(l(x)), s(r(x)))); } inline void flatten(int x) { if(!x) return; flatten(l(x)); if(c(x)) cache[++len] = x; flatten(r(x)); return; } inline void build(int &x, int l, int r) { if(l > r) { x = 0; return; } int mid = (l + r) >> 1; x = cache[mid]; build(l(x), l, mid - 1); build(r(x), mid + 1, r); update(x); return; } inline void rebuild(int &x) { len = 0; flatten(x); build(x, 1, len); return; } public: inline void Init() { cnt = len = 0; return; } inline void Insert(int &x, int v) { if(!x) { x = ++cnt; v(x) = v; l(x) = r(x) = 0; c(x) = s(x) = d(x) = 1; return; } if(v == v(x)) { c(x)++; } else { if(v < v(x)) Insert(l(x), v); else Insert(r(x), v); } update(x); if(isbad(x)) rebuild(x); return; } inline void Delete(int &x, int v) { if(!x) return; d(x)--; if(v == v(x)) { if(c(x)) c(x)--; } else { if(v < v(x)) Delete(l(x), v); else Delete(r(x), v); } update(x); if(isbad(x)) rebuild(x); return; } inline int QueryKth(int x, int k) { if(!k) return 0; if(d(l(x)) < k && k <= d(l(x)) + c(x)) return v(x); else { if(k <= d(l(x))) return QueryKth(l(x), k); else return QueryKth(r(x), k - d(l(x)) - c(x)); } } inline int PreRank(int x, int v) { if(!x) return 0; if(v == v(x)) return d(l(x)); else { if(v < v(x)) return PreRank(l(x), v); else return PreRank(r(x), v) + c(x) + d(l(x)); } } inline int QueryRank(int x, int v) { return PreRank(x, v) + 1; } inline int Prefix(int x, int v) { if(!x) return -INF; if(v(x) < v) { if(c(x)) { if(d(r(x))) return max(v(x), Prefix(r(x), v)); else return v(x); } else { if(d(r(x))) return Prefix(r(x), v); else return Prefix(l(x), v); } } else return Prefix(l(x), v); } inline int Suffix(int x, int v) { if(!x) return INF; if(v(x) > v) { if(c(x)) { if(d(l(x))) return min(v(x), Suffix(l(x), v)); else return v(x); } else { if(d(l(x))) return Suffix(l(x), v); else return Suffix(r(x), v); } } else return Suffix(r(x), v); } inline void Debug(int x) { if(!x) return; Debug(l(x)); printf("node#%d: v=%d, l=%d, r=%d, c=%d, d=%d, s=%d\n", x, v(x), l(x), r(x), c(x), d(x), s(x)); Debug(r(x)); return; } }; ScapeGoatTree s; inline int read() { int res = 0, uz = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') uz = -1; ch = getchar(); } while(isdigit(ch)) { res = (res << 3) + (res << 1) + (ch ^ '0'); ch = getchar(); } return res * uz; } int main() { s.Init(); int n = read(); int root = 0; while(n--) { int opt = read(), x = read(); switch(opt) { case 1: { s.Insert(root, x); break; } case 2: { s.Delete(root, x); break; } case 3: { printf("%d\n", s.QueryRank(root, x)); break; } case 4: { printf("%d\n", s.QueryKth(root, x)); break; } case 5: { printf("%d\n", s.Prefix(root, x)); break; } default: { printf("%d\n", s.Suffix(root, x)); break; } } } return 0; } ```