线段树套 splay 求卡常

P3380 【模板】树套树

``` #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int N = 5e6 + 10, INF = 2e9; int idx, w[N], n, m; #define IN stdin->_IO_read_ptr<stdin->_IO_read_end?*stdin->_IO_read_ptr++:__uflow(stdin) #define OUT(_ch) stdout->_IO_write_ptr<stdout->_IO_write_end?*stdout->_IO_write_ptr++=_ch:__overflow(stdout,_ch) inline void read(int &x){ x=0; char ch=IN; while(ch<47)ch=IN; while(ch>47)x=(x<<1)+(x<<3)+(ch^48),ch=IN; } inline void write(int x) { static char buf[16]; static int len=-1; if(x<0)putchar('-'),x=-x; do buf[++len]=x%10,x/=10;while(x); while(len>=0)putchar(buf[len--]+'0'); putchar('\n'); } struct Splay { int s[2], p, v, size; void init(int _p, int _v) { p = _p, v = _v, size = 1; } }; struct Mathods_Splay { Splay tr[N]; inline void pushup(int x) { tr[x].size = tr[tr[x].s[0]].size + tr[tr[x].s[1]].size + 1; } inline void rotate(int x) { int y = tr[x].p, z = tr[y].p, k = tr[y].s[1] == x; if (z) tr[z].s[tr[z].s[1] == y] = x; tr[x].p = z; tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y; tr[x].s[k ^ 1] = y, tr[y].p = x; pushup(y), pushup(x); } inline void splay(int &root, int x, int k) { while (tr[x].p != k) { int y = tr[x].p, z = tr[y].p; if (z != k) rotate(((tr[z].s[1] == y) ^ (tr[y].s[1] == x)) ? y : x); rotate(x); } if (!k) root = x; } inline int find(int &root, int v) { int u = root; if (!u) return -1; while (v != tr[u].v && tr[u].s[v > tr[u].v]) u = tr[u].s[v > tr[u].v]; splay(root, u, 0); return u; } inline void insert(int &root, int v) { int u = root, fa = 0; while (u) fa = u, u = tr[u].s[v > tr[u].v]; u = ++ idx; if (fa) tr[fa].s[v > tr[fa].v] = u; tr[u].init(fa, v); splay(root, u, 0); } inline int get_rank(int &root, int v) { int u = root, res = 0; while (u) { if (tr[u].v < v) res += tr[tr[u].s[0]].size + 1, u = tr[u].s[1]; else u = tr[u].s[0]; } // splay(root, u, 0); return res; } inline void update(int &root, int x, int y) { int u = root; while (u) { if (tr[u].v == x) break; if (tr[u].v < x) u = tr[u].s[1]; else u = tr[u].s[0]; } splay(root, u, 0); int l = tr[u].s[0], r = tr[u].s[1]; while (tr[l].s[1]) l = tr[l].s[1]; while (tr[r].s[0]) r = tr[r].s[0]; splay(root, l, 0), splay(root, r, l); tr[r].s[0] = 0; pushup(r), pushup(l); insert(root, y); } inline int get_pre(int &root, int v) { int u = root, res = -2147483647; while (u) { if (tr[u].v < v) res = max(res, tr[u].v), u = tr[u].s[1]; else u = tr[u].s[0]; } // splay(root, u, 0); return res; } inline int get_next(int &root, int v) { int u = root, res = 2147483647; while (u) { if (tr[u].v > v) res = min(res, tr[u].v), u = tr[u].s[0]; else u = tr[u].s[1]; } // splay(root, u, 0); return res; } }s; struct Tree { int l, r; int root; }tr[N << 2]; inline void build(int u, int l, int r) { tr[u].l = l, tr[u].r = r; s.insert(tr[u].root, -INF), s.insert(tr[u].root, INF); for (register int i = l; i <= r; i ++ ) s.insert(tr[u].root, w[i]); if (l == r) return; int mid = l + r >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); } inline int query_rank(int u, int l, int r, int v) { if (tr[u].l >= l && tr[u].r <= r) return s.get_rank(tr[u].root, v) - 1; int mid = tr[u].l + tr[u].r >> 1, res = 0; if (l <= mid) res += query_rank(u << 1, l, r, v); if (r > mid) res += query_rank(u << 1 | 1, l, r, v); return res; } inline void modify(int u, int x, int v) { s.update(tr[u].root, w[x], v); if (tr[u].l == tr[u].r) return; int mid = tr[u].l + tr[u].r >> 1; if (x <= mid) modify(u << 1, x, v); else modify(u << 1 | 1, x, v); } inline int query_pre(int u, int l, int r, int x) { if (tr[u].l >= l && tr[u].r <= r) return s.get_pre(tr[u].root, x); int mid = tr[u].l + tr[u].r >> 1, res = -2147483647; if (l <= mid) res = max(res, query_pre(u << 1, l, r, x)); if (r > mid) res = max(res, query_pre(u << 1 | 1, l, r, x)); return res; } inline int query_next(int u, int l, int r, int x) { if (tr[u].l >= l && tr[u].r <= r) return s.get_next(tr[u].root, x); int mid = tr[u].l + tr[u].r >> 1, res = 2147483647; if (l <= mid) res = min(res, query_next(u << 1, l, r, x)); if (r > mid) res = min(res, query_next(u << 1 | 1, l, r, x)); return res; } int main() { read(n), read(m); int minn = INF, maxn = -INF; for (register int i = 1; i <= n; i ++ ) { read(w[i]); minn = min(minn, w[i]), maxn = max(maxn, w[i]); } build(1, 1, n); int op, l, r, k; while (m -- ) { read(op), read(l), read(r); if (op == 1) { read(k); printf("%d\n", query_rank(1, l, r, k) + 1); } if (op == 2) { read(k); int L = minn, R = maxn; while (L < R) { int mid = L + R + 1 >> 1; if (query_rank(1, l, r, mid) + 1 <= k) L = mid; else R = mid - 1; } printf("%d\n", R); } if (op == 3) { minn = min(minn, r), maxn = max(maxn, r); modify(1, l, r); w[l] = r; } if (op == 4) { read(k); printf("%d\n", query_pre(1, l, r, k) == -INF ? -2147483647 : query_pre(1, l, r, k)); } if (op == 5) { read(k); printf("%d\n", query_next(1, l, r, k) == INF ? 2147483647 : query_next(1, l, r, k)); } } return 0; } ```
by Link_Cut_Y @ 2022-07-29 19:24:54


你快读没负数?
by 黑影洞人 @ 2022-07-29 19:31:01


@[黑影洞人](/user/285617) 本题没负数啊。
by Usada_Pekora @ 2022-07-29 19:50:06


@[黑影洞人](/user/285617) 知道错哪了,主要是因为权值平衡树插点的时候,应该记一个 $\texttt{cnt}$ 表示出现该权值的次数,这样能够有效减少 $\texttt{splay}$ 中点的数量,从而降低复杂度。
by Link_Cut_Y @ 2022-07-29 22:19:39


@[Mount_](/user/519384) 这毛病我之前犯过
by 黑影洞人 @ 2022-07-29 22:22:10


@[黑影洞人](/user/285617) hh,看来还是我太弱了
by Link_Cut_Y @ 2022-07-29 22:24:16


@[Mount_](/user/519384) 我树套树一直0分,没调出来,干脆放弃去学fhq-treap了,你比我强耶
by 黑影洞人 @ 2022-07-29 22:27:46


|