题目链接
怎么说呢,虽然码量有点长,但是一遍调过还是很开森的哈哈哈哈哈哈哈!嗝~~~
首先“困难值小于等于 x 的路径”,那么,其实就是Kruskal重构树的暗示了,之后又不带边权的修改,那么更显然是Kruskal重构树了!然后就是树上不带修改的询问第K大,其实就是暗示着主席树了,所以这里必须是要去建可持久化线段树的。
然后就是树上跑可持久化线段树的问题了,之前试过了启发式合并,但是很没有办法会TLE,那么,我们就得去试着用别的方法,一种很显然的手段就是dfs序跑出来的时间戳来建可持久化线段树了。这里我们可以知道,所有的原树上的结点一定会是重构树的叶子结点,那么,其余的新构结点我们就不给他们dfs序,给他们的是他的子树的dfs序的区间岂不是更好,节约空间。
那么,在一棵树上的问题就解决了,但是题目中并没有说原图联通,所以,在这里引入超级源点,对于所有的树的根结点连接到超级源点上去,于是就把森林重新变成了一棵树,我们再来跑这样的操作就可以完成上述的任务了。
其实,想想还是很简单的,实现起来也不是太难,debug就是了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
//#define INF 10000007.
#define eps 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7, maxM = 5e5 + 7;
int N, M, Q, h[maxN], lsan[maxN], _UP, root[maxN], head[maxN], cnt, ex_N, W[maxN];
int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
struct Graph
{
int u, v, w;
inline void In_Put() { scanf("%d%d%d", &u, &v, &w); }
friend bool operator < (Graph e1, Graph e2) { return e1.w < e2.w; }
} E[maxM];
struct Eddge
{
int nex, to;
Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN];
inline void addEddge(int u, int v)
{
edge[cnt] = Eddge(head[u], v);
head[u] = cnt++;
}
struct Endless_Tree
{
int root[maxN], tot, tree[30 * maxN], lc[30 * maxN], rc[30 * maxN];
inline void clear() { root[0] = 0; tot = 0; tree[0] = lc[0] = rc[0] = 0; }
inline void pushup(int rt) { tree[rt] = tree[lc[rt]] + tree[rc[rt]]; }
void update(int &now, int old, int l, int r, int qx)
{
now = ++tot;
tree[now] = tree[old] + 1; lc[now] = lc[old]; rc[now] = rc[old];
if(l == r) return;
int mid = HalF;
if(qx <= mid) update(lc[now], lc[old], l, mid, qx);
else update(rc[now], rc[old], mid + 1, r, qx);
}
int query(int root_L, int root_R, int l, int r, int kth)
{
if(l == r) return l;
int mid = HalF;
if(tree[rc[root_R]] - tree[rc[root_L]] >= kth) return query(rc[root_L], rc[root_R], mid + 1, r, kth);
else return query(lc[root_L], lc[root_R], l, mid, kth - (tree[rc[root_R]] - tree[rc[root_L]]));
}
int Range_check(int L, int R, int kth) { return query(root[L - 1], root[R], 1, _UP, kth); }
} ET;
pair<int, int> each_new_id[maxN]; //每个重构点的左右区间(dfs序)
struct dfs_ID
{
int dfn[maxN], tot, fa[maxN][20], deep[maxN];
void clear() { tot = 0; }
void dfs(int u)
{
if(u > N) each_new_id[u].first = tot + 1;
else
{
dfn[u] = ++tot;
ET.update(ET.root[tot], ET.root[tot - 1], 1, _UP, h[u]);
}
for(int i=0; (1 << (i + 1)) < N; i++) fa[u][i + 1] = fa[fa[u][i]][i];
for(int i=head[u], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
fa[v][0] = u; deep[v] = deep[u] + 1;
dfs(v);
}
if(u > N) each_new_id[u].second = tot;
}
} dfs_id;
inline void init()
{
cnt = 0; ex_N = N;
for(int i = 1; i <= N << 1; i++)
{
head[i] = -1;
root[i] = i;
}
}
int LOG[maxN];
inline void Pre()
{
for(int i = 1, j = 0, nex = 2; i<maxN; i++)
{
if(i == nex) { j++; nex <<= 1; }
LOG[i] = j;
}
}
int main()
{
Pre();
scanf("%d%d%d", &N, &M, &Q);
init();
for(int i=1; i<=N; i++) { scanf("%d", &h[i]); lsan[i] = h[i]; }
sort(lsan + 1, lsan + N + 1);
_UP = (int)(unique(lsan + 1, lsan + N + 1) - lsan - 1);
for(int i=1; i<=N; i++) h[i] = (int)(lower_bound(lsan + 1, lsan + _UP + 1, h[i]) - lsan);
for(int i=1; i<=M; i++) E[i].In_Put();
sort(E + 1, E + M + 1);
for(int i=1, fu, fv; i<=M; i++)
{
fu = fid(E[i].u); fv = fid(E[i].v);
if(fu ^ fv)
{
ex_N ++; W[ex_N] = E[i].w;
addEddge(ex_N, fu); addEddge(ex_N, fv);
root[fu] = root[fv] = ex_N;
}
}
ex_N++; W[ex_N] = INF;
for(int i=1; i<ex_N; i++) //存在森林的情况,我们需要拉出来考虑,现在重构树的根结点就是ex_N
{
if(fid(i) == i)
{
addEddge(ex_N, i);
}
}
ET.clear();
dfs_id.clear();
dfs_id.deep[ex_N] = 0;
dfs_id.dfs(ex_N);
int u, v, x, k, siz;
while(Q--)
{
scanf("%d%d%d", &v, &x, &k);
u = v;
for(int i=LOG[dfs_id.deep[u]]; i>=0; i--)
{
if(!dfs_id.fa[u][i]) continue;
if(W[dfs_id.fa[u][i]] <= x)
{
u = dfs_id.fa[u][i];
}
}
if(u == v)
{
if(k == 1) printf("%d\n", lsan[h[v]]);
else printf("-1\n");
continue;
}
siz = each_new_id[u].second - each_new_id[u].first + 1;
if(siz < k) { printf("-1\n"); continue; }
printf("%d\n", lsan[ET.Range_check(each_new_id[u].first, each_new_id[u].second, k)]);
}
return 0;
}