bzoj3545 Peaks

题意:多次求从点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 }
AC代码

 

转载于:https://www.cnblogs.com/huyufeifei/p/10414738.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值