传送门
文章目录
- 题意:
- 思路:
题意:
给你一张图,有nnn个山峰,每个山峰高度为hih_ihi,有mmm条边,每条边有个难度值wiw_iwi,现在有qqq个询问,每次询问给定一个山峰vvv,问从这个山峰开始走,经过难度不超过xxx的路径能走到的山峰中,第kkk大的山峰高度是多少。
n≤1e5,m,q≤5e5,hi,wi<=1e9n\le1e5,m,q\le5e5,h_i,w_i<=1e9n≤1e5,m,q≤5e5,hi,wi<=1e9
思路:
KruskalKruskalKruskal重构树维护连通性经典题啦,把边从小到大排序,让后建重构树,这样每两个点之间的最大路径是他们的lcalcalca的点权,那么我们从vvv这个点往上跳,一直跳到深度最小的且valf≤xval_f\le xvalf≤x的点,让后这颗子树中所有叶子节点就是能到的山峰,找第kkk大的问题当然是留给主席树解决啦,按照dfsdfsdfs序建主席树,查询第kkk大就好了。
//#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;
}
/**/