[bzoj1861][Zjoi2006]Book 书架
题目大意:有一串长度为$n$的序列,为$1\sim n$的一个排列,五个操作:
- $Top\;S:$把$S$放在序列开头
- $Bottom\;S:$把$S$放在序列结尾
- $Insert\;S\;T:$把$S$向后移动$T$个位置
- $Ask\;S:$询问$S$前有几个元素
- $Query\;S:$询问第$S$个元素是什么
题解:平衡树维护序列
卡点:无
C++ Code:
#include <cstdio> #include <cstdlib> #define maxn 80010 namespace Treap { int P[maxn], sz[maxn]; int lc[maxn], rc[maxn], fa[maxn]; int root, idx; int ta, tb, tmp, res, s; inline int nw(int p) { sz[p] = 1; P[p] = rand(); return p; } inline int update(int rt) { sz[rt] = sz[lc[rt]] + sz[rc[rt]] + 1; fa[lc[rt]] = rt, fa[rc[rt]] = rt; return rt; } inline void split(int rt, int k, int &x, int &y) { if (!rt) x = y = 0; else { if (sz[lc[rt]] < k) split(rc[rt], k - sz[lc[rt]] - 1, rc[rt], y), x = update(rt); else split(lc[rt], k, x, lc[rt]), y = update(rt); } } inline int merge(int x, int y) { if (!x || !y) return x | y; if (P[x] > P[y]) { rc[x] = merge(rc[x], y); return update(x); } else { lc[y] = merge(x, lc[y]); return update(y); } } inline int gtrnk(int x) { res = sz[lc[x]] + 1; while (fa[x]) { if (rc[fa[x]] == x) res += sz[lc[fa[x]]] + 1; x = fa[x]; } return res; } inline int k_th(int k, int p = root) { while (true) { if (sz[lc[p]] >= k) p = lc[p]; else { if (sz[lc[p]] + 1 == k) return p; else k -= sz[lc[p]] + 1, p = rc[p]; } } } inline void insert(int p) { if (!root) root = nw(p); else { root = merge(root, nw(p)); } } inline void top(int p) { s = gtrnk(p); split(root, s - 1, ta, tmp); split(tmp, 1, tmp, tb); root = merge(tmp, merge(ta, tb)); } inline void bottom(int p) { s = gtrnk(p); split(root, s - 1, ta, tmp); split(tmp, 1, tmp, tb); root = merge(merge(ta, tb), tmp); } inline void Insert(int p, int pos) { if (!pos) return ; s = gtrnk(p); split(root, s - 1, ta, tmp); split(tmp, 1, tmp, tb); root = merge(ta, tb); s = s + pos - 1; split(root, s, ta, tb); root = merge(merge(ta, tmp), tb); } inline int ask(int p) { return gtrnk(p) - 1; } inline int query(int p) { return k_th(p); } } int n, m; int main() { srand(20040826); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { int a; scanf("%d", &a); Treap::insert(a); } while (m --> 0) { char op[20]; int a, b; scanf("%s%d", op, &a); switch (*op) { case 'T' : Treap::top(a); break; case 'B' : Treap::bottom(a); break; case 'I' : { scanf("%d", &b); Treap::Insert(a, b); break; } case 'A' : printf("%d\n", Treap::ask(a)); break; case 'Q' : printf("%d\n", Treap::query(a)); } } return 0; }