题目链接:[ONTAK2010]Peaks加强版
做一遍Kruscal,对于要合并联通块的两个点x,y新建节点z令fa[x]=fa[y]=z,并且节点z的权值为这条边的边权
那么我们对于一个询问<v,x,k>只需要倍增出最后一个权值>x的节点,这颗子树就是我们要找到的联通块
主席树维护即可
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=300010;
const int maxN=5000000;
const int inf=0x7fffffff/2-1;
int n,m,f[maxn],tmp[maxn],a[maxn];
struct edge{int a,b,w;}e[maxn<<1];
int lson[maxN],rson[maxN],T[maxn];
int tot=0,cnt=0,N=0,totr=0,ind=0;
int s[maxN],fa[maxn][20],st[maxn];
int h[maxn],ed[maxn],dep[maxn],Q;
struct edges{int to,next;}G[maxn<<2];
int read(){
int x=0; char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
int getpos(int x){
int l=1,r=N,ret=-1;
while (l<=r){
int mid=(l+r)>>1;
if (tmp[mid]>x) r=mid-1;
else l=mid+1,ret=mid;
}return ret;
}
bool cmp(const edge &a,const edge &b){
return a.w<b.w;
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
void add(int x,int y){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;
}
void ins(int pre,int &rt,int l,int r,int pos){
rt=++totr; s[rt]=s[pre]+1;
if (l==r) return;
int mid=(l+r)>>1;
if (pos<=mid) rson[rt]=rson[pre],ins(lson[pre],lson[rt],l,mid,pos);
else lson[rt]=lson[pre],ins(rson[pre],rson[rt],mid+1,r,pos);
}
void dfs(int x){
dep[x]=dep[fa[x][0]]+1;
st[x]=++ind;
for (int i=1;i<=18;++i){
if (dep[x]<(1<<i)) break;
fa[x][i]=fa[fa[x][i-1]][i-1];
}
if (x<=n) ins(T[ind-1],T[ind],1,N,a[x]);
else T[ind]=T[ind-1];
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
fa[v][0]=x; dfs(v);
}
ed[x]=ind;
}
int query(int pre,int rt,int l,int r,int k){
if (l==r) return tmp[l];
int mid=(l+r)>>1,sum=s[rson[rt]]-s[rson[pre]];
if (sum>=k) return query(rson[pre],rson[rt],mid+1,r,k);
else return query(lson[pre],lson[rt],l,mid,k-sum);
}
int main(){
n=read(); m=read(); Q=read(); cnt=n;
for (int i=1;i<=n;++i) a[i]=read(),tmp[i]=a[i];
sort(tmp+1,tmp+n+1); tmp[0]=-inf;
for (int i=1;i<=n;++i) if (tmp[i]!=tmp[i-1]) tmp[++N]=tmp[i];
for (int i=1;i<=n;++i) a[i]=getpos(a[i]);
for (int i=1;i<=m;++i)
e[i].a=read(),e[i].b=read(),e[i].w=read();
sort(e+1,e+m+1,cmp);
for (int i=1;i<n<<1;++i) f[i]=i;
for (int i=1;i<=m;++i){
int x=find(e[i].a),y=find(e[i].b);
if (x!=y){
f[x]=f[y]=++cnt;
add(cnt,x); add(cnt,y);
a[cnt]=e[i].w;
if (cnt==(n<<1)-1) break;
}
}
for (int i=1;i<=n;++i){
int x=find(i);
if (!st[x]) dfs(x);
}
int lastans=0; a[0]=inf;
for (int i=1;i<=Q;++i){
int x=read()^lastans,y=read()^lastans,z=read()^lastans;
int rt=x;
for (int j=18;j>=0;--j){
if (dep[rt]<(1<<j)) continue;
if (a[fa[rt][j]]<=y) rt=fa[rt][j];
}
if (s[T[ed[rt]]]-s[T[st[rt]-1]]<z) lastans=-1;
else lastans=query(T[st[rt]-1],T[ed[rt]],1,N,z);
printf("%d\n",lastans);
lastans=lastans<0?0:lastans;
}
}