cychester

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 }
View Code

 

posted on 2018-09-10 19:29  cychester  阅读(191)  评论(0编辑  收藏  举报

导航