题目链接
题解
对于<=x的边集构成多个联通块,对于询问离线,维护单调递增的<=x的联通块,每次线段树合并,查询k大。
代码
/*
苟活者在淡红的血色中,会看见依稀的微茫
*/
#include<bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-')f =- 1; c = getchar();}
while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
return x * f;
}
const int maxn = 250007;
struct node {
int u,v,w;
bool operator < (const node & a) const {
return w < a.w;
}
} edge[(maxn << 1) + 7];
struct Query {
int u,v,k,id;
bool operator < (const Query & a) const {
return v < a.v;
}
}q[maxn * 2] ;
#define lc son[x][0]
#define rc son[x][1]
int n,m,Q,cnt;
int h[maxn],ans[maxn * 2],sz[maxn * 20],son[maxn * 20][2],tot = 0;
void insert(int &x ,int l,int r,int rk) {
sz[x = ++ tot] = 1;
if(l == r) return ;
int mid = l + r >> 1;
if(rk <= mid) insert(lc,l,mid,rk);
else insert(rc,mid + 1,r,rk);
}
int Merge(int x,int y) {
if(!x || !y) return x ^ y;
lc = Merge(lc,son[y][0]);rc = Merge(rc,son[y][1]);
sz[x] += sz[y];sz[y] = 0; return x;
}
int Query(int x,int l,int r,int k) {
if(l == r) return l;
int lz = sz[lc],mid = l + r >> 1;
if(k <= lz) return Query(lc,l,mid,k);
else return Query(rc,mid + 1,r,k - lz);
}
int fa[maxn],ref[maxn];
int find(int x ) {
if(fa[x] != x)fa[x] = find(fa[x]);
return fa[x];
}
int root[maxn * 15];
void merge(int x,int y) {
int r1 = find(x),r2 = find(y);
if(r1 == r2) return;
fa[r2] = r1,root[r1] = Merge(root[r1],root[r2]);
}
int query(int x,int k) {
int rt = find(x);
return sz[root[rt]] < k ? - 1 : ref[Query(root[rt],1,cnt,sz[root[rt]] - k + 1)];
}
int main() {
n = read(),m = read(),Q = read();
for(int i = 1;i <= n;++ i) ref[i] = h[i] = read(),fa[i] = i;
std::sort(ref + 1, ref + n + 1),cnt = 1;
for(int i = 2;i <= n;++ i) if(ref[i] != ref[i - 1]) ref[++ cnt] = ref[i];
for(int i = 1;i <= n;++ i) insert(root[i],1,cnt,lower_bound(ref + 1,ref + cnt + 1,h[i]) - ref);
for(int i = 1;i <= m;++ i) edge[i].u = read(),edge[i].v = read(), edge[i].w = read();
std::sort(edge + 1,edge + m + 1);
for(int i = 1;i <= Q;++ i)
q[i].u = read(),q[i].v = read(),q[i].k = read(),q[i].id = i;
std::sort(q + 1,q + Q + 1);
for(int i = 1,now = 1; i <= Q;++ i) {
while(now <= m && edge[now].w <= q[i].v) merge(edge[now].u,edge[now].v),++ now;
ans[q[i].id] = query(q[i].u,q[i].k);
}
for(int i = 1;i <= Q;++ i) printf("%d
",ans[i]);
return 0;
}