Luogu4197 Peaks

题目链接:洛谷


看到“只经过困难值小于等于$x$的路径”。

感觉有点眼熟。

ow,就是[NOI2018]归程。


和那道题一样,可以直接建出Kruskal重构树,每次倍增寻找祖先中最上面的不大于$x$的节点$v$,$v$的子树就是可以到达的范围。

根据Kruskal重构树的dfs序建出主席树求第$K$大。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define Rint register int
 4 using namespace std;
 5 const int N = 500003;
 6 struct Edge {
 7     int u, v, w;
 8     inline bool operator < (const Edge &o) const {return w < o.w;}
 9 } e[N];
10 int n, m, q, _n, h[N], b[N], val[N], head[N], to[N << 1], nxt[N << 1], fa[N], tot;
11 inline int getfa(int x){return x == fa[x] ? x : fa[x] = getfa(fa[x]);}
12 inline void add(int a, int b){
13     static int cnt = 0;
14     to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
15 }
16 int root[N], ls[N << 5], rs[N << 5], seg[N << 5], cnt;
17 inline void change(int &now, int pre, int L, int R, int pos){
18     now = ++ cnt; seg[now] = seg[pre] + 1;
19     if(L == R) return;
20     int mid = L + R >> 1;
21     if(pos <= mid) rs[now] = rs[pre], change(ls[now], ls[pre], L, mid, pos);
22     else ls[now] = ls[pre], change(rs[now], rs[pre], mid + 1, R, pos);
23 }
24 inline int query(int nowl, int nowr, int L, int R, int k){
25     if(L == R) return L;
26     int mid = L + R >> 1, minused = seg[rs[nowr]] - seg[rs[nowl]];
27     if(k <= minused) return query(rs[nowl], rs[nowr], mid + 1, R, k);
28     else return query(ls[nowl], ls[nowr], L, mid, k - minused);
29 }
30 int st[19][N], dfn[N], out[N], tim;
31 inline void dfs(int x){
32     dfn[x] = ++ tim;
33     if(x <= n) change(root[dfn[x]], root[dfn[x] - 1], 1, _n, h[x]);
34     else root[dfn[x]] = root[dfn[x] - 1];
35     for(Rint i = head[x];i;i = nxt[i]) dfs(to[i]);
36     out[x] = tim;
37 }
38 inline int query(int v, int x, int k){
39     for(Rint i = 18;~i;i --)
40         if(st[i][v] && val[st[i][v]] <= x) v = st[i][v];
41     int lx = root[dfn[v] - 1], rx = root[out[v]];
42     return seg[rx] - seg[lx] >= k ? b[query(lx, rx, 1, _n, k)] : -1;
43 }
44 int main(){
45     scanf("%d%d%d", &n, &m, &q); tot = n;
46     for(Rint i = 1;i <= n;i ++) scanf("%d", h + i), b[i] = h[i];
47     sort(b + 1, b + n + 1);
48     _n = unique(b + 1, b + n + 1) - b - 1;
49     for(Rint i = 1;i <= n;i ++) h[i] = lower_bound(b + 1, b + _n + 1, h[i]) - b;
50     for(Rint i = 1;i <= m;i ++)
51         scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
52     sort(e + 1, e + m + 1);
53     for(Rint i = 1;i <= n;i ++) fa[i] = i;
54     for(Rint i = 1;i <= m && tot < (n << 1) - 1;i ++){
55         int fa1 = getfa(e[i].u), fa2 = getfa(e[i].v);
56         if(fa1 != fa2){
57             ++ tot;
58             fa[tot] = fa[fa1] = fa[fa2] = tot;
59             st[0][fa1] = st[0][fa2] = tot;
60             add(tot, fa1); add(tot, fa2);
61             val[tot] = e[i].w;
62         }
63     }
64     for(Rint i = tot;i;i --) if(!dfn[i]) dfs(i);
65     for(Rint i = 1;i <= 18;i ++)
66         for(Rint j = 1;j <= tot;j ++) st[i][j] = st[i - 1][st[i - 1][j]];
67     while(q --){
68         int v, x, k;
69         scanf("%d%d%d", &v, &x, &k);
70         printf("%d
", query(v, x, k));
71     }
72 }
Luogu4197
原文地址:https://www.cnblogs.com/AThousandMoons/p/10682931.html