ZOJ_2112
之前用线段树套平衡树写这个题目,现在发现那样写弱爆了……再次写这个题就是为了学习“主席树”,其实也就是可持久化数据结构的思想,思想来自于这篇博客:http://seter.is-programmer.com/posts/31907.html,写法来自于那个博主的代码:http://ideone.com/2Jp5W。
由于刚刚接触“主席树”就不再额外发表言论了。
#include<stdio.h> #include<string.h> #include<algorithm> #define MAXM 10010 #define MAXD 60010 #define LN 16 struct Di { int id, v; bool operator < (const Di &t) const { return v < t.v; } }di[MAXD]; struct List { int x, y, k; }list[MAXM]; int N, M, S, rank[MAXD], node; struct SegTree { int ls, rs, size; }st[2560000]; // 尽量开大些... namespace ST { int build(int x = 0, int y = S) { int cur = ++ node, mid = x + y >> 1; st[cur].size = 0; if(x < y) st[cur].ls = build(x, mid), st[cur].rs = build(mid + 1, y); return cur; } int insert(int pre, int v, int d) { int t = ++ node, cur = t, x = 0, y = S; for(;;) { int mid = x + y >> 1; st[cur].size = st[pre].size + d; if(x == y) break; if(v <= mid) { st[cur].rs = st[pre].rs, st[cur].ls = ++ node; cur = node, pre = st[pre].ls, y = mid; } else { st[cur].ls = st[pre].ls, st[cur].rs = ++ node; cur = node, pre = st[pre].rs, x = mid + 1; } } return t; } } struct ChairTree { int T[20], n; ChairTree() : n(0){} ChairTree(int x) : n(1){T[0] = x;} operator int() const { int i, ans = 0; for(i = 0; i < n; i ++) ans += st[st[T[i]].ls].size; return ans; } void operator += (int x) { T[n ++] = x; } int operator ^= (int C) { for(int i = 0; i < n; i ++) T[i] = C ? st[T[i]].rs : st[T[i]].ls; return C; } }; namespace BIT { int T[MAXD]; void init() { T[1] = ST::build(); for(int i = 2; i <= N; i ++) T[i] = T[1]; } void insert(int x, int v, int d) { for(;x <= N; x += x & -x) T[x] = ST::insert(T[x], v, d); } void query(ChairTree &ct, int x) { for(; x > 0; x -= x & -x) ct += T[x]; } } int A[MAXD]; void init() { int i, n = 0; char op[5]; scanf("%d%d", &N, &M); for(i = 1; i <= N; i ++) scanf("%d", &di[n].v), di[n].id = n + 1, ++ n; for(i = 0; i < M; i ++) { scanf("%s", op); if(op[0] == 'Q') scanf("%d%d%d", &list[i].x, &list[i].y, &list[i].k); else scanf("%d%d", &list[i].x, &di[n].v), list[i].k = -1, di[n].id = n + 1, ++ n; } std::sort(di, di + n); rank[di[0].id] = 0; for(i = 1, S = 0; i < n; i ++) { if(di[i].v != di[i - 1].v) di[++ S].v = di[i].v; rank[di[i].id] = S; } node = 0; BIT::init(); for(A[0] = BIT::T[0], i = 1; i <= N; i ++) A[i] = ST::insert(A[i - 1], rank[i], 1); } void solve() { int i, n = N, C; for(i = 0; i < M; i ++) { if(list[i].k == -1) { BIT::insert(list[i].x, rank[list[i].x], -1); BIT::insert(list[i].x, rank[list[i].x] = rank[++ n], 1); } else { int x = 0, y = S, k = list[i].k; ChairTree a, b, c = A[list[i].y], d = A[list[i].x - 1]; BIT::query(a, list[i].y), BIT::query(b, list[i].x - 1); for(;;) { if(x == y) break; int mid = x + y >> 1, t = a + c - b - d; if(k <= t) a ^= b ^= c ^= d ^= 0, y = mid; else k -= t, a ^= b ^= c ^= d ^= 1, x = mid + 1; } printf("%d\n", di[x].v); } } } int main() { int t; scanf("%d", &t); while(t --) { init(); solve(); } return 0; }