听说这题有在线做法……?YY了一下似乎要把各种东西都给可持久化掉。。。好麻烦。。。
反正这题没强制在线
先把询问按他给的那个阀值排序,然后搞像Kurscal的过程,按边权从小到大枚举边,每次合并连接的两个点所能到的权值集合,这个可以用平衡树的启发式合并实现。于是询问就在对应的平衡树里查K大就可以了。
根据势能分析,n棵只有1个节点的splay启发式合并复杂度是 O(nlogn) 的。如果同样级别treap直接启发式合并的话复杂度是 O(nlog2n) 的。但是某十多年前的论文证明了两棵大小分别为 n,m(n≤m) 的treap的合并是 O(nlognm) 的。于是同样级别的treap合并也是 O(nlogn) 的了。
treap的合并就是代码里写的那样。
时间复杂度 O(mlogm+nlogn)
我还以为能跑多快结果才rank21
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = a , _ = b ; i <= _ ; i ++)
#define per(i,a,b) for (int i = a , _ = b ; i >= _ ; i --)
#define gprintf(...) //fprintf(stderr , __VA_ARGS__)
inline int rd() {
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar() ; int x = 0 , f = 1;
if (c == '-') f = -1; else x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x * f;
}
inline int rnd() {
static int rand_seed = 42071823;
rand_seed += (rand_seed << 1 | 1);
return rand_seed;
}
const int maxn = 1000007;
const int maxm = 1000007;
typedef int arr[maxn];
typedef int que[maxm];
typedef pair<int , int> pii;
arr fa , rk , h , ans;
pii H[maxn];
int n , m , q;
int find(int u) { return u == fa[u] ? u : fa[u] = find(fa[u]); }
void init_UFS() {
rep (i , 1 , n) fa[i] = i , rk[i] = 1;
}
struct edge {
int u , v , w;
edge(int u = 0 , int v = 0 , int w = 0): u(u) , v(v) , w(w) { }
}E[maxm];
struct info {
int v , x , k , id;
info(int v = 0 , int x = 0 , int k = 0 , int id = 0):v(v) , x(x) , k(k) , id(id) { }
}Q[maxm];
inline bool cmp_edge(const edge a , const edge b) {
return a.w < b.w;
}
inline bool cmp_info_key(const info a , const info b) {
return a.x < b.x;
}
struct node {
node *l , *r;
int key , pri;
int sz;
node (int key = 0): key(key) , pri(rnd()) , l(NULL) , r(NULL) , sz(1) { }
inline void upd() {
sz = 1;
if (l) sz += l->sz;
if (r) sz += r->sz;
}
}mem_pool[maxn];
struct Droot {
node *l , *r;
Droot (node *a = NULL , node *b = NULL): l(a) , r(b) { }
};
int mem_top;
inline node *newnode(int key) {
node *u = &mem_pool[mem_top ++];
*u = node(key);
return u;
}
inline int Size(node *u) {
return u ? u->sz : 0;
}
node *join(node *u , node *v) {
if (!u) return v;
if (!v) return u;
if (u->pri < v->pri) {
u->r = join(u->r , v);
u->upd();
return u;
} else {
v->l = join(u , v->l);
v->upd();
return v;
}
}
Droot split(node *u , int v) {
if (!u) return Droot();
Droot t;
if (u->key < v) {
t = split(u->r , v);
u->r = t.l , t.l = u;
} else {
t = split(u->l , v);
u->l = t.r , t.r = u;
}
u->upd();
return t;
}
node *merge(node *u , node *v) {
if (!u) return v;
if (!v) return u;
if (u->pri > v->pri) swap(u , v);
Droot t = split(v , u->key);
u->l = merge(u->l , t.l);
u->r = merge(u->r , t.r);
u->upd();
return u;
}
struct Treap {
node *rt;
void init(int key) {
rt = newnode(key);
}
inline void merge_to(Treap&v) {
rt = merge(rt , v.rt);
}
inline int kth(int k) {
if (k <= 0 || k > rt->sz) return -1;
k = rt->sz - k + 1;
for (node *u = rt;;) {
int t = Size(u->l) + 1;
if (k == t) return u->key;
else if (k < t) u = u->l;
else k -= t , u = u->r;
}
}
}path[maxn];
void input() {
n = rd() , m = rd() , q = rd();
rep (i , 1 , n) h[i] = rd();
rep (i , 1 , n) H[i] = pii(h[i] , i);
rep (i , 1 , m) {
int u = rd() , v = rd() , w = rd();
E[i] = edge(u , v , w);
}
rep (i , 1 , q) {
int u = rd() , x = rd() , k = rd();
Q[i] = info(u , x , k , i);
}
sort(H + 1 , H + n + 1);
rep (i , 1 , n) h[i] = lower_bound(H + 1 , H + n + 1 , pii(h[i] , i)) - H;
init_UFS();
}
inline void link(int u , int v) {
u = find(u) , v = find(v);
if (u == v) return;
if (rk[u] < rk[v]) swap(u , v);
if (rk[u] == rk[v]) rk[u] ++;
path[u].merge_to(path[v]);
fa[v] = u;
}
void solve() {
sort(E + 1 , E + m + 1 , cmp_edge);
sort(Q + 1 , Q + q + 1 , cmp_info_key);
rep (i , 1 , n) path[i].init(h[i]);
for (int i = 1 , j = 0 ; i <= q && j <= m ; i ++) {
for ( ; j + 1 <= m && E[j + 1].w <= Q[i].x ; j ++)
link(E[j + 1].u , E[j + 1].v);
int u = find(Q[i].v);
ans[Q[i].id] = path[u].kth(Q[i].k);
}
rep (i , 1 , q) printf("%d\n" , ans[i] == -1 ? -1 : H[ans[i]].first);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
input();
solve();
return 0;
}