题意
维护一个多重集合 $S$ , 支持:
① 插入一个数 $w$ .
② 删除一个数 $w$ .
③ 查询 $w$ 在集合中的排名.
④ 查询集合中排名第 $r$ 的数.
⑤ 求集合中 $w$ 的前驱.
⑥ 求集合中 $w$ 的后继.
$N \le 100000$ .
小结
要总结一些常见的写法和想法, 减小实现时的复杂度.
实现
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #define F(i, a, b) for (register int i = (a); i <= (b); i++) const int N = 100005; int n; int rt, tot, c[N][2], siz[N], fix[N], key[N]; struct D { int c[2]; }; inline int rd(void) { int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -1; int x = 0; for (; isdigit(c); c = getchar()) x = x*10+c-‘0‘; return x*f; } inline void Pushup(int x) { siz[x] = siz[c[x][0]] + siz[c[x][1]] + 1; } inline int Merge(int x, int y) { if (!x || !y) return x+y; if (fix[x] < fix[y]) { c[x][1] = Merge(c[x][1], y); Pushup(x); return x; } else { c[y][0] = Merge(x, c[y][0]); Pushup(y); return y; } } inline D Split(int x, int k) { if (!x) return D(); if (key[x] > k) { D t = Split(c[x][0], k); c[x][0] = t.c[1], Pushup(x); t.c[1] = x; return t; } else { D t = Split(c[x][1], k); c[x][1] = t.c[0], Pushup(x); t.c[0] = x; return t; } } inline D Split_r(int x, int k) { if (!x) return D(); if (siz[c[x][0]] + 1 > k) { D t = Split_r(c[x][0], k); c[x][0] = t.c[1], Pushup(x); t.c[1] = x; return t; } else { D t = Split_r(c[x][1], k-siz[c[x][0]]-1); c[x][1] = t.c[0], Pushup(x); t.c[0] = x; return t; } } inline int Newnode(int w) { return siz[++tot] = 1, fix[tot] = rand(), key[tot] = w, tot; } inline void Insert(int w) { int x = Newnode(w); D t = Split(rt, w); rt = Merge(Merge(t.c[0], x), t.c[1]); } inline void Delete(int w) { //It‘s guaranteed that w exists! D t = Split(rt, w-1); D tx = Split_r(t.c[1], 1); rt = Merge(t.c[0], tx.c[1]); } inline int Get(int w) { D t = Split(rt, w-1); int res = siz[t.c[0]] + 1; rt = Merge(t.c[0], t.c[1]); return res; } inline int Rank(int k) { D t = Split_r(rt, k-1); D tx = Split_r(t.c[1], 1); int res = key[tx.c[0]]; rt = Merge(t.c[0], Merge(tx.c[0], tx.c[1])); return res; } inline int Pre(int w) { D t = Split(rt, w-1); D tx = Split_r(t.c[0], siz[t.c[0]]-1); int res = key[tx.c[1]]; rt = Merge(Merge(tx.c[0], tx.c[1]), t.c[1]); return res; } inline int Nxt(int w) { D t = Split(rt, w); D tx = Split_r(t.c[1], 1); int res = key[tx.c[0]]; rt = Merge(t.c[0], Merge(tx.c[0], tx.c[1])); return res; } int main(void) { #ifndef ONLINE_JUDGE freopen("bzoj3224.in", "r", stdin); freopen("bzoj3224.out", "w", stdout); #endif n = rd(); F(i, 1, n) { int k = rd(), x = rd(); if (k == 1) Insert(x); else if (k == 2) Delete(x); else if (k == 3) printf("%d\n", Get(x)); else if (k == 4) printf("%d\n", Rank(x)); else if (k == 5) printf("%d\n", Pre(x)); else printf("%d\n", Nxt(x)); } return 0; }
时间: 2024-10-23 22:30:51