题意:
给你一张图,有
n
n
n个山峰,每个山峰高度为
h
i
h_i
hi,有
m
m
m条边,每条边有个难度值
w
i
w_i
wi,现在有
q
q
q个询问,每次询问给定一个山峰
v
v
v,问从这个山峰开始走,经过难度不超过
x
x
x的路径能走到的山峰中,第
k
k
k大的山峰高度是多少。
n
≤
1
e
5
,
m
,
q
≤
5
e
5
,
h
i
,
w
i
<
=
1
e
9
n\le1e5,m,q\le5e5,h_i,w_i<=1e9
n≤1e5,m,q≤5e5,hi,wi<=1e9
思路:
K r u s k a l Kruskal Kruskal重构树维护连通性经典题啦,把边从小到大排序,让后建重构树,这样每两个点之间的最大路径是他们的 l c a lca lca的点权,那么我们从 v v v这个点往上跳,一直跳到深度最小的且 v a l f ≤ x val_f\le x valf≤x的点,让后这颗子树中所有叶子节点就是能到的山峰,找第 k k k大的问题当然是留给主席树解决啦,按照 d f s dfs dfs序建主席树,查询第 k k k大就好了。
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;
//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const int N=200010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;
int n,m,q;
int a[N],p[N],fa[N][22],in[N],ed[N],se[N],tot;
int root[N],idx,h[N];
vector<int>v[N],li;
struct Edge
{
int a,b,w;
bool operator < (const Edge &W) const
{
return w<W.w;
}
}edge[N*3];
struct Node
{
int l,r;
int cnt;
}tr[N*40];
int find(int x)
{
return x==p[x]? x:p[x]=find(p[x]);
}
int get(int x)
{
return lower_bound(li.begin(),li.end(),x)-li.begin();
}
void insert(int p,int &q,int l,int r,int pos)
{
q=++idx; tr[q]=tr[p];
tr[q].cnt++;
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) insert(tr[p].l,tr[q].l,l,mid,pos);
else insert(tr[p].r,tr[q].r,mid+1,r,pos);
}
int query(int p,int q,int l,int r,int k)
{
if(l==r) return li[l];
int mid=(l+r)>>1,cnt=tr[tr[q].l].cnt-tr[tr[p].l].cnt;
if(k<=cnt) return query(tr[p].l,tr[q].l,l,mid,k);
else return query(tr[p].r,tr[q].r,mid+1,r,k-cnt);
}
void dfs(int u,int f)
{
se[u]=1;
in[u]=++tot; fa[u][0]=f;
for(int i=1;i<=19;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
if(u<=n) insert(root[tot-1],root[tot],0,li.size()-1,get(a[u]));
else root[tot]=root[tot-1];
for(auto x:v[u]) if(x!=f) dfs(x,u),se[u]+=se[x];
ed[u]=tot;
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),li.pb(a[i]);
sort(li.begin(),li.end()); li.erase(unique(li.begin(),li.end()),li.end());
for(int i=1;i<=n*2;i++) p[i]=i;
for(int i=1;i<=m;i++)
{
int a,b,w; scanf("%d%d%d",&a,&b,&w);
edge[i]={a,b,w};
}
sort(edge+1,edge+1+m);
for(int i=1,tot=n;i<=m;i++)
{
int aa=edge[i].a,b=edge[i].b,w=edge[i].w;
int pa=find(aa),pb=find(b);
if(pa==pb) continue;
tot++; p[pa]=tot; p[pb]=tot;
v[tot].pb(pa); v[tot].pb(pb);
a[tot]=w;
if(tot==n*2-1) break;
//cout<<pa<<' '<<pb<<' '<<tot<<' '<<w<<endl;
}
a[0]=INF;
for(int i=1;i<=n*2-1;i++) if(i==find(i)) dfs(i,0);
int ans=0;
while(q--)
{
int v,x,k; scanf("%d%d%d",&v,&x,&k);
v^=ans; x^=ans; k^=ans;
for(int i=19;i>=0;i--) if(a[fa[v][i]]<=x) v=fa[v][i];
int sum=tr[root[ed[v]]].cnt-tr[root[in[v]-1]].cnt;
if(k>sum) ans=-1;
else ans=query(root[in[v]-1],root[ed[v]],0,li.size()-1,sum-k+1);
printf("%d\n",ans);
ans=ans==-1? 0:ans;
}
return 0;
}
/*
*/