评价一下,周六和周一调的半死,今天看一眼就知道哪里错了。
只经过 $\leq x$ 的路径,容易想到 Kruskal 重构树,然后看到第 $k$ 大,容易想到主席树。
那就做完了。3.43kb 代码也不过如此。
下面放的是有强制在线的代码。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 15, M = 1e6 + 15;
int n, n1, cnt, m, q, a[N], b[N];
int rt[N];
struct Segment_Tree {
int tot = 0;
struct Tree {
int ls, rs;
int sum;
} tr[N << 5];
void build(int &u, int l, int r) {
u = ++tot, tr[u].sum = 0;
if (l == r) return;
int mid = l + r >> 1;
build(tr[u].ls, l, mid);
build(tr[u].rs, mid + 1, r);
}
void change(int &u, int l, int r, int x) {
tr[++tot] = tr[u], u = tot;
if (l == r) { tr[u].sum++; return; }
int mid = l + r >> 1;
if (x <= mid) change(tr[u].ls, l, mid, x);
else change(tr[u].rs, mid + 1, r, x);
tr[u].sum = tr[tr[u].ls].sum + tr[tr[u].rs].sum;
}
int query(int u, int v, int l, int r, int k) { //线段树二分
if (l == r) return l;
int mid = l + r >> 1, delta = tr[ tr[u].rs ].sum - tr[ tr[v].rs ].sum;
if (k <= delta) return query(tr[u].rs, tr[v].rs, mid + 1, r, k);
else return query(tr[u].ls, tr[v].ls, l, mid, k - delta);
}
int qry(int l, int r, int k) { return query(rt[r], rt[l - 1], 1, cnt, k); }
} t;
struct edges {
int u, v, w;
} edge[M];
bool cmp(edges a, edges b) { return a.w < b.w; }
int p[N];
int find(int x) { return (x == p[x]) ? x : p[x] = find(p[x]); }
int h[N], e[M], ne[M], idx = 0;
void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }
int l[N], r[N], w[N], high[N], tot = 0;
//w: 虚点代表的边权; high:原图中山的高度(离散化后)
int fa[N][25], dep[N];
void dfs(int u, int father) {
fa[u][0] = father, dep[u] = dep[father] + 1;
if (u <= n) {
++tot;
l[u] = r[u] = tot, high[tot] = a[u];
return;
}
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (v == father) continue;
dfs(v, u);
l[u] = min(l[u], l[v]);
r[u] = max(r[u], r[v]);
}
}
void init() {
for (int i = 1; i <= 20; i++)
for (int j = 1; j <= n1; j++) fa[j][i] = fa[fa[j][i - 1]][i - 1];
}
int main() {
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
sort(b + 1, b + 1 + n);
cnt = unique(b + 1, b + 1 + n) - b - 1;
for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;
for (int i = 1; i <= m; i++) scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].w);
sort(edge + 1, edge + 1 + m, cmp);
for (int i = 1; i <= 2 * n; i++) p[i] = i, h[i] = -1, l[i] = 0x3f3f3f3f, r[i] = 0;
n1 = n;
for (int i = 1; i <= m; i++) {
int u = edge[i].u, v = edge[i].v;
int fu = find(u), fv = find(v);
if (fu == fv) continue;
n1++, p[fu] = n1, p[fv] = n1;
w[n1] = edge[i].w;
add(n1, fu), add(fu, n1);
add(n1, fv), add(fv, n1);
// cout << '\t' << n1 << ' ' << fu << ' ' << w[n1] << endl;
// cout << '\t' << n1 << ' ' << fv << ' ' << w[n1] << endl;
}
dfs(n1, 0);
init();
// for (int i = 1; i <= n1; i++) cout << i << ' ' << l[i] << ' ' << r[i] << endl;
t.build(rt[0], 1, cnt);
for (int i = 1; i <= tot; i++) rt[i] = rt[i - 1], t.change(rt[i], 1, cnt, high[i]);
int lst = 0;
while (q--) {
int x, lim, k; scanf("%d%d%d", &x, &lim, &k);
x = (x ^ lst) % n + 1, k = (k ^ lst) % n + 1, lim ^= lst;
for (int i = 20; i >= 0; i--)
if (fa[x][i] && w[fa[x][i]] <= lim) x = fa[x][i];
// cout << '\t' << x << endl;
if (r[x] - l[x] + 1 < k) { lst = 0; puts("-1"); continue; }
printf("%d\n", lst = b[t.qry(l[x], r[x], k)]);
}
return 0;
}