[luoguP2596] [ZJOI2006]书架(splay)
题目中的几个操作,直接splay搞一下即可:
- 把s旋转到根,左子树接到右子树
- 把s旋转到根,右子树接到左子树
- 交换s相邻的信息即可
- 把s旋转到根,左子树的大小即为答案
- 找第k大
没了
#include <cstdio> #include <cstring> #include <iostream> #define N 100000 using namespace std; int n, m, cnt, rt; int son[N][2], size[N], f[N], pos[N], w[N]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline int get(int x) { return son[f[x]][1] == x; } inline void update(int x) { size[x] = size[son[x][0]] + size[son[x][1]] + 1; } inline void rotate(int x) { int fa = f[x], ffa = f[fa], p = get(x); son[fa][p] = son[x][p ^ 1], f[son[x][p ^ 1]] = fa; son[x][p ^ 1] = fa, f[fa] = x; if(ffa) son[ffa][son[ffa][1] == fa] = x; f[x] = ffa; update(fa), update(x); } inline void splay(int x, int y) { for(int fa; (fa = f[x]) != y; rotate(x)) if(f[fa] != y) rotate(get(fa) == get(x) ? fa : x); if(!y) rt = x; } inline void top_bottom(int x, int p) { splay(pos[x], 0); if(!son[rt][p]) return; if(!son[rt][p ^ 1]) son[rt][p ^ 1] = son[rt][p], son[rt][p] = 0; else { x = son[rt][p ^ 1]; while(son[x][p]) x = son[x][p]; son[x][p] = son[rt][p], f[son[rt][p]] = x; son[rt][p] = 0, splay(son[x][p], 0); } } inline int build(int l, int r, int fa) { if(l > r) return 0; int mid = (l + r) >> 1, now = ++cnt; son[now][0] = build(l, mid - 1, now); w[now] = read(), size[now] = 1, f[now] = fa, pos[w[now]] = now; son[now][1] = build(mid + 1, r, now); update(now); return now; } inline void ist(int p, int x) { if(!p) return; splay(pos[x], 0); if(p == -1) p = 0; x = son[rt][p]; while(son[x][p ^ 1]) x = son[x][p ^ 1]; if(x) swap(pos[w[rt]], pos[w[x]]), swap(w[rt], w[x]); } inline void ask(int x) { splay(pos[x], 0); printf("%d\n", size[son[rt][0]]); } inline int query(int k) { int x = rt; while(x) { if(size[son[x][0]] + 1 == k) return w[x]; else if(size[son[x][0]] >= k) x = son[x][0]; else k -= size[son[x][0]] + 1, x = son[x][1]; } } int main() { int i, x; char s[10]; n = read(); m = read(); rt = build(1, n, 0); for(i = 1; i <= m; i++) { scanf("%s", s); switch(s[0]) { case 'T': top_bottom(read(), 0); break; case 'B': top_bottom(read(), 1); break; case 'I': ist(read(), read()); break; case 'A': ask(read()); break; case 'Q': printf("%d\n", query(read())); break; } } return 0; }