替罪羊樹
阿新 • • 發佈:2020-07-22
替罪羊樹
暴力重構的思想,如果樹不夠平衡,那麼就拍扁重構即可
和 treap 的操作大致都一樣就是了,但常數挺小的,可以卡常使用
const int N = 2005000; struct node { int ls, rs, siz, sum; int key, val; #define key(k) p[k].key #define val(k) p[k].val #define ls(k) p[k].ls #define rs(k) p[k].rs #define siz(k) p[k].siz #define sum(k) p[k].sum }p[N]; int rt, cnt; const double A = 0.8; bool judge(int k) { return val(k) && A * siz(k) < max(siz(ls(k)), siz(rs(k))); } void update(int k) { siz(k) = siz(ls(k)) + siz(rs(k)) + (val(k) ? 1 : 0); sum(k) = sum(ls(k)) + sum(rs(k)) + val(k); } int st[N], tp; void pia(int k) { if (ls(k)) pia(ls(k)); if (val(k)) st[++tp] = k; if (rs(k)) pia(rs(k)); return; } int rebuild(int l, int r) { if (l > r) return 0; int mid = (l + r) >> 1; ls(st[mid]) = rebuild(l, mid - 1); rs(st[mid]) = rebuild(mid + 1, r); return update(st[mid]), st[mid]; } int maintain(int p) { return tp = 0, pia(p), rebuild(1, tp); } void insert(int &x, int val) { if (!x) { x = ++cnt, key(x) = val; val(x) = siz(x) = sum(x) = 1; } else { if (key(x) == val) val(x)++; else if (val < key(x)) insert(ls(x), val); else insert(rs(x), val); update(x); judge(x) && (x = maintain(x)); } } void del(int &x, int val) { sum(x)--; if (key(x) == val) val(x)--; else key(x) > val ? del(ls(x), val) : del(rs(x), val); update(x), judge(x) && (x = maintain(x)); } int rkup(int x, int k) { int nw = 0; while (1) { if (!x) return nw; if (key(x) == k) return nw + sum(ls(x)) + val(x); if (key(x) <= k) nw += sum(ls(x)) + val(x), x = rs(x); else x = ls(x); } } int rkdw(int x, int k) { int nw = 1; while (1) { if (!x) return nw; if (key(x) == k) return nw + sum(ls(x)); if (key(x) <= k) nw += sum(ls(x)) + val(x), x = rs(x); else x = ls(x); } } int get(int k) { int x = rt; while (1) { if (sum(ls(x)) >= k) x = ls(x); else if (sum(ls(x)) + val(x) >= k) return key(x); else k -= sum(ls(x)) + val(x), x = rs(x); } return 1; } int n, t, x, m, las, ans; int main() { for (read(n), read(m); n; n--) read(x), insert(rt, x); for (; m; m--) { read(t), read(x), x ^= las; if (t == 1) insert(rt, x); else if (t == 2) del(rt, x); else if (t == 3) las = rkdw(rt, x); else if (t == 4) las = get(x); else if (t == 5) las = get(rkdw(rt, x) - 1); else las = get(rkup(rt, x) + 1); if (t >= 3) ans ^= las; } write(ans); return 0; }