题目链接:洛谷
看到“只经过困难值小于等于$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 }