BZOJ 2733 [HNOI2012]永无乡 - 启发式合并主席树
Description
1: 查询一个集合内的K大值
2: 合并两个集合
Solution
启发式合并主席树板子
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rd read() 5 #define rep(i,a,b) for(register int i = (a); i <= (b); ++i) 6 #define per(i,a,b) for(register int i = (a); i >= (b); --i) 7 using namespace std; 8 9 const int N = 1e5 + 1e4; 10 11 int a[N], id[N], b[N]; 12 int root[N], lson[N * 100], rson[N * 100], sum[N * 100]; 13 int n, m, nd_num; 14 int father[N], num[N]; 15 16 int read() { 17 int X = 0, p = 1; char c = getchar(); 18 for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1; 19 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 20 return X * p; 21 } 22 23 int cmp(int x, int y) { 24 return a[x] < a[y]; 25 } 26 27 int find_anc(int x) { 28 return father[x] == x? x : father[x] = find_anc(father[x]); 29 } 30 31 int fd(int x) { 32 return lower_bound(b + 1, b + 1 + n, x) - b; 33 } 34 35 void ins(int l, int r, int pos, int &nd) { 36 if(!nd) nd = ++nd_num; 37 sum[nd]++; 38 if(l == r) return; 39 int mid = (l + r) >> 1; 40 if(pos <= mid) ins(l, mid, pos, lson[nd]); 41 else ins(mid + 1, r, pos, rson[nd]); 42 } 43 44 int query(int l, int r, int k, int nd) { 45 if(l == r) return l; 46 int mid = (l + r) >> 1; 47 if(sum[lson[nd]] >= k) return query(l, mid, k, lson[nd]); 48 else return query(mid + 1, r, k - sum[lson[nd]], rson[nd]); 49 } 50 51 int mg(int l, int r, int x, int y) { 52 if(!x || !y) return x + y; 53 int nd = ++nd_num; 54 sum[nd] = sum[x] + sum[y]; 55 if(l == r) return nd; 56 int mid = ( l + r) >> 1; 57 lson[nd] = mg(l, mid, lson[x], lson[y]); 58 rson[nd] = mg(mid + 1, r, rson[x], rson[y]); 59 return nd; 60 } 61 62 int main() 63 { 64 n = rd; m = rd; 65 rep(i, 1, n) id[i] = father[i] = i, num[i] = 1; 66 rep(i, 1, n) b[i] = a[i] = rd; 67 sort(id + 1, id + 1 + n, cmp); 68 sort(b + 1, b + 1 + n); 69 rep(i, 1, n) ins(1, n, fd(a[i]), root[i]); 70 rep(i, 1, m) { 71 int u = rd, v = rd; 72 int x = find_anc(u), y = find_anc(v); 73 if(num[x] < num[y]) swap(x, y); 74 father[y] = x; 75 num[x] += num[y]; 76 root[x] = mg(1, n, root[x], root[y]); 77 } 78 int T = rd; 79 for(; T; T--) { 80 char c = getchar(); 81 while(c != 'Q' && c != 'B') c = getchar(); 82 int u = rd, v = rd; 83 if(c == 'Q') { 84 int x = find_anc(u), re; 85 if(num[x] < v) {puts("-1"); continue;} 86 re = query(1, n, v, root[x]); 87 printf("%d\n", id[re]); 88 } 89 else { 90 int x = find_anc(u), y = find_anc(v); 91 if(x == y) continue; 92 if(num[x] < num[y]) swap(x, y); 93 father[y] = x; 94 num[x] += num[y]; 95 root[x] = mg(1, n, root[x], root[y]); 96 } 97 } 98 }