AC 第一个点,其余 MLE。
做法:考虑构建 Kruskal 重构树,每次查询倍增寻找深度最前的 val≤x 的祖先,查询子树第 k 大的数,考虑可持久化权值线段树(主席树)。
自己算了一下所需空间大约在 63 mb 左右,应该不存在数组开大的情况。
代码中没有分配动态内存,也没有使用指针,不存在内存泄漏的情况,2 gb 的空间情况下爆栈也不可能。
这里是代码:
#include <bits/stdc++.h>
#define il inline
using namespace std;
const int N = 1e5 + 10;
const int M = 5e5 + 10;
int n, m, q, h[N], tot = 0, t[N], cnt;
int ls[N << 1], rs[N << 1], val[N << 1];
struct Edge{
int u, v, w;
Edge(){}
Edge(int u_, int v_, int w_){
u = u_, v = v_, w = w_;
}
il bool operator < (const Edge& b) const{
return w < b.w;
}
}e[M];
struct Disjoint_Set{
static const int MR = 1e5 + 10;
int fa[MR];
il void INIT(){
for (int i = 1; i <= (n << 1); i++)
fa[i] = i;
}
il int FIND(int x){
return (fa[x] == x ? x : (fa[x] = FIND(fa[x])));
}
il void MERGE(int x, int y, int w){
x = FIND(x), y = FIND(y);
++cnt;
fa[x] = fa[y] = cnt;
ls[cnt] = x, rs[cnt]= y;
val[cnt] = w;
}
}ds;
int fa[N << 1][20], dfncnt = 0, dfn[N], rk[N];
int in[N << 1], out[N << 1];
il void EX_Kruskal(){
ds.INIT();
cnt = n;
sort(e + 1, e + m + 1);
for (int i = 1, u, v, w; i <= m; i++){
u = ds.FIND(e[i].u);
v = ds.FIND(e[i].v);
w = e[i].w;
if (u ^ v)
ds.MERGE(u, v, w);
}
}
il void DFS(int u, int fno){
fa[u][0] = fno;
for (int i = 1; i < 20; i++)
fa[u][i] = fa[fa[u][i - 1]][i - 1];
if (u <= n){
++dfncnt;
dfn[u] = in[u] = out[u] = dfncnt;
rk[dfncnt] = u;
return;
}
in[u] = dfncnt + 1;
DFS(ls[u], u), DFS(rs[u], u);
out[u] = dfncnt;
}
struct Segment_Tree{
static const int MR = 1e5 + 10;
int tot = 0, root[MR];
int xds[MR << 5], ls[MR << 5], rs[MR << 5];
il void Push_Up(int rt){
xds[rt] = xds[ls[rt]] + xds[rs[rt]];
}
il void Update(int &rt1, int rt2, int l, int r, int x){
rt1 = (rt1 ? rt1 : (++tot));
xds[rt1] = xds[rt2] + 1;
if (l == r)
return;
int md = (l + r) >> 1;
if (x <= md)
Update(ls[rt1], ls[rt2], l, md, x), rs[rt1] = rs[rt2];
else Update(rs[rt1], rs[rt2], md + 1, r, x), ls[rt1] = ls[rt2];
Push_Up(rt1);
}
il int Query(int rt1, int rt2, int l, int r, int k){
if (l == r)
return t[l];
int cnt = xds[rs[rt2]] - xds[rs[rt1]];
//cout << rt1 << " " << rt2 << " " << l << " " << r << " " << cnt << endl;
int md = (l + r) >> 1;
return (k <= cnt ? Query(rs[rt1], rs[rt2], md + 1, r, k) :
Query(ls[rt1], ls[rt2], l, md, k - cnt));
}
}sgt;
il void Solve(){
int v, x, k;
cin >> v >> x >> k;
for (int i = 19; i >= 0; i--)
if (fa[v][i] && val[fa[v][i]] <= x)
v = fa[v][i];
//cout << v << " " << in[v] << " " << out[v] << endl;
if (out[v] - in[v] + 1 < k)
cout << -1 << endl;
else cout << sgt.Query(sgt.root[in[v] - 1], sgt.root[out[v]], 1, tot, k) << endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m >> q;
for (int i = 1; i <= n; i++){
cin >> h[i];
t[++tot] = h[i];
}
sort(t + 1, t + tot + 1);
tot = unique(t + 1, t + tot + 1) - t - 1;
for (int i = 1; i <= n; i++)
h[i] = lower_bound(t + 1, t + tot + 1, h[i]) - t;
for (int i = 1, u, v, w; i <= m; i++){
cin >> u >> v >> w;
e[i] = Edge(u, v, w);
}
EX_Kruskal();
DFS(cnt, 0);
//for (int i = 1; i <= cnt; i++)
//cout << ls[i] << " " << rs[i] << " " << val[i] << endl;
for (int i = 1; i <= n; i++){
sgt.Update(sgt.root[i], sgt.root[i - 1], 1, tot, h[rk[i]]);
//cout << rk[i] << " " << h[rk[i]] << endl;
}
//cout << sgt.Query(sgt.root[1], sgt.root[8], 1, tot, 1) << endl;
while (q--)
Solve();
return 0;
}