bzoj3224 Tyvj 1728 普通平衡树
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3224
【题解】
写起来跟*一样,但是还是挺快调出来了。
主要就是每个数可以有多个,我们可以用一个splay节点存多个数,然后find即可。
注意的是每个操作过后基本都要splay一下保证复杂度。
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 1e5 + 10; const int mod = 1e9+7; const int inf = 2e9 + 10; # define RG register # define ST static struct Splay { int ch[M][2], fa[M]; int val[M], sz[M], rt, siz, s[M]; inline void set() { siz = 2; rt = 1; ch[1][0] = ch[2][0] = ch[2][1] = fa[1] = 0, ch[1][1] = 2; fa[2] = 1; sz[1] = 2, sz[2] = 1; val[1] = -inf, val[2] = inf; s[1] = s[2] = 1; } inline void up(int x) { if(!x) return ; sz[x] = s[x] + sz[ch[x][0]] + sz[ch[x][1]]; } inline void rotate(int x, int &rt) { int y = fa[x], z = fa[y], ls = ch[y][1] == x, rs = ls^1; if(rt == y) rt = x; else ch[z][ch[z][1] == y] = x; fa[ch[x][rs]] = y, fa[y] = x, fa[x] = z; ch[y][ls] = ch[x][rs]; ch[x][rs] = y; up(y); up(x); } inline void splay(int x, int &rt) { while(x != rt) { int y = fa[x], z = fa[y]; if(y != rt) { if((ch[z][0] == y) ^ (ch[y][0] == x)) rotate(x, rt); else rotate(y, rt); } rotate(x, rt); } } inline void ins(int &x, int lst, int p) { if(!x) { x = ++siz; fa[x] = lst; ch[x][0] = ch[x][1] = 0; sz[x] = 1; val[x] = p; s[x] = 1; return; } if(p == val[x]) { s[x] ++; sz[x] ++; return ; } if(p < val[x]) ins(ch[x][0], x, p); else ins(ch[x][1], x, p); up(x); } inline void INS(int p) { ins(rt, 0, p); splay(siz, rt); } inline int find(int x, int p) { if(!x) return inf; if(val[x] == p) return x; if(p < val[x]) return find(ch[x][0], p); else return find(ch[x][1], p); } inline int gpre(int x, int p) { if(!x) return inf; if(val[x] < p) { int y = gpre(ch[x][1], p); if(y != inf) return y; else return x; } else return gpre(ch[x][0], p); } inline int gsuf(int x, int p) { if(!x) return inf; if(val[x] > p) { int y = gsuf(ch[x][0], p); if(y != inf) return y; else return x; } else return gsuf(ch[x][1], p); } inline int pre(int x) { while(ch[x][1]) x = ch[x][1]; return x; } inline int suf(int x) { while(ch[x][0]) x = ch[x][0]; return x; } inline void DEL(int p) { int x = find(rt, p); splay(x, rt); if(s[x] > 1) { --s[x]; up(x); return ; } int y = pre(ch[x][0]); splay(y, ch[x][0]); rt = y; fa[y] = 0; ch[y][1] = ch[x][1]; fa[ch[x][1]] = y; up(y); fa[x] = ch[x][0] = ch[x][1] = s[x] = sz[x] = 0; } inline void PRE(int p) { int x = find(rt, p); if(x == inf) { int y = gpre(rt, p); splay(y, rt); printf("%d\n", val[y]); return ; } splay(x, rt); int y = pre(ch[x][0]); printf("%d\n", val[y]); } inline void SUF(int p) { int x = find(rt, p); if(x == inf) { int y = gsuf(rt, p); splay(y, rt); printf("%d\n", val[y]); return ; } splay(x, rt); int y = suf(ch[x][1]); printf("%d\n", val[y]); } inline void getrank(int p) { int x = find(rt, p); splay(x, rt); printf("%d\n", sz[ch[x][0]]); } inline int findrk(int x, int p) { if(sz[ch[x][0]] + 1 <= p && p <= sz[ch[x][0]] + s[x]) return x; if(sz[ch[x][0]] + 1 > p) return findrk(ch[x][0], p); else return findrk(ch[x][1], p - s[x] - sz[ch[x][0]]); } inline void prank(int x) { int y = findrk(rt, x+1); splay(y, rt); printf("%d\n", val[y]); } }T; int main() { int Q, op, x; cin >> Q; T.set(); while(Q--) { scanf("%d%d", &op, &x); if(op == 1) T.INS(x); else if(op == 2) T.DEL(x); else if(op == 3) T.getrank(x); else if(op == 4) T.prank(x); else if(op == 5) T.PRE(x); else T.SUF(x); } return 0; }