题意:多次求从点x出发经过边权不超过k的边能走到的点中第k大的权值。
解:离线排序 + 并查集 + 线段树合并。
题面有锅...是第k大的权值不是第k大的山。
1 #include <cstdio> 2 #include <algorithm> 3 4 const int N = 100010, M = 500010, V = 7000010; 5 6 struct Edge { 7 int x, y, h; 8 inline bool operator <(const Edge &w) const { 9 return h < w.h; 10 } 11 }edge[M]; 12 13 struct Ask { 14 int x, h, k, id; 15 inline bool operator <(const Ask &w) const { 16 return h < w.h; 17 } 18 }ask[M]; 19 20 int fa[N], rt[N], ls[V], rs[V], sum[V], siz[N], tot, ans[M], X[N], val[N]; 21 22 int find(int x) { 23 if(x == fa[x]) { 24 return x; 25 } 26 return fa[x] = find(fa[x]); 27 } 28 29 int merge(int x, int y) { 30 if(!x || !y) { 31 return x | y; 32 } 33 int o = ++tot; 34 sum[o] = sum[x] + sum[y]; 35 ls[o] = merge(ls[x], ls[y]); 36 rs[o] = merge(rs[x], rs[y]); 37 return o; 38 } 39 40 int query(int k, int l, int r, int o) { 41 if(l == r) { 42 return r; 43 } 44 int mid = (l + r) >> 1; 45 if(k > sum[rs[o]]) { 46 return query(k - sum[rs[o]], l, mid, ls[o]); 47 } 48 else { 49 return query(k, mid + 1, r, rs[o]); 50 } 51 } 52 53 inline void Xmerge(int x, int y) { 54 x = find(x); 55 y = find(y); 56 if(x == y) { 57 return; 58 } 59 fa[y] = x; 60 siz[x] += siz[y]; 61 // printf("siz %d += %d = %d \n", x, siz[y], siz[x]); 62 rt[x] = merge(rt[x], rt[y]); 63 return; 64 } 65 66 void insert(int p, int l, int r, int &o) { 67 if(!o) { 68 o = ++tot; 69 } 70 sum[o] = 1; 71 if(l == r) { 72 return; 73 } 74 int mid = (l + r) >> 1; 75 if(p <= mid) { 76 insert(p, l, mid, ls[o]); 77 } 78 else { 79 insert(p, mid + 1, r, rs[o]); 80 } 81 return; 82 } 83 84 int main() { 85 int n, m, q; 86 scanf("%d%d%d", &n, &m, &q); 87 for(int i = 1; i <= n; i++) { 88 scanf("%d", &val[i]); 89 X[i] = val[i]; 90 } 91 std::sort(X + 1, X + n + 1); 92 int xx = std::unique(X + 1, X + n + 1) - X - 1; 93 for(int i = 1; i <= n; i++) { 94 val[i] = std::lower_bound(X + 1, X + xx + 1, val[i]) - X; 95 insert(val[i], 1, xx, rt[i]); 96 fa[i] = i; siz[i] = 1; 97 } 98 for(int i = 1; i <= m; i++) { 99 scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].h); 100 } 101 for(int i = 1; i <= q; i++) { 102 scanf("%d%d%d", &ask[i].x, &ask[i].h, &ask[i].k); 103 ask[i].id = i; 104 } 105 std::sort(edge + 1, edge + m + 1); 106 std::sort(ask + 1, ask + q + 1); 107 108 int p = 1; 109 for(int i = 1; i <= q; i++) { 110 while(p <= m && edge[p].h <= ask[i].h) { 111 Xmerge(edge[p].x, edge[p].y); 112 p++; 113 // printf("Xmerge %d %d \n", edge[p].x, edge[p].y); 114 } 115 int x = find(ask[i].x); 116 // printf("x = %d \n", x); 117 // printf("%d < %d \n", siz[x], ask[i].k); 118 if(siz[x] < ask[i].k) ans[ask[i].id] = -1; 119 else ans[ask[i].id] = X[query(ask[i].k, 1, xx, rt[x])]; 120 } 121 for(int i = 1; i <= q; i++) { 122 printf("%d\n", ans[i]); 123 } 124 return 0; 125 }