题目链接:http://darkbzoj.tk/problem/3551
题解:
对原图求一遍kruskal重构树,考虑在重构树上倍增,求出深度最小的点权 ≤ k \le k ≤k的点(显然不是原图上的点),然后只需要求子树第k大,这显然可以主席树解决
代码:
// by Balloons
#include
#include
#include
#include
#define mpr make_pair
#define debug() puts("okkkkkkkk")
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
using namespace std;
typedef long long LL;
const int inf = 1e9, maxn=5e5+5;
int n,m,q;
int a[maxn],b[maxn],nn,w[maxn];
struct edge{
int x,y,v;
bool operator < (const edge b) const {
return v<b.v;
}
}e[maxn];
struct edges{
int to,nxt;
}ed[maxn << 1];
int head[maxn], ecnt=0;
int fa[maxn],totp,f[maxn][22];
int len[maxn][2], dfs_clock;
int find(int x){return fa[x] == x?fa[x]:fa[x] = find(fa[x]);}
void add(int x,int y){
ed[++ ecnt].to = y;ed[ecnt].nxt = head[x];head[x] = ecnt;
}
struct segm{
int ls,rs,v;
}se[maxn << 5];
int curs = 0,rt[maxn];
void update(int &num,int now,int x,int y,int k){
num = ++ curs;se[num] = se[now];++ se[num].v;
if(x == y)return ;
int mid=x+y>>1;
if(k<=mid)update(se[num].ls,se[now].ls,x,mid,k);
else update(se[num].rs,se[now].rs,mid+1,y,k);
}
int query(int num,int now,int k,int x,int y){
if(x == y)return x;
int mid=x+y>>1;
int vv = se[se[now].rs].v - se[se[num].rs].v;
if(k <= vv)return query(se[num].rs,se[now].rs,k,mid+1,y);
else return query(se[num].ls,se[now].ls,k-vv,x,mid);
}
void kruskal(){
totp = n;
sort(e+1,e+m+1);
for(int i=1;i<=2*n;i++)fa[i] = i;
int inmst = 0;
for(int i=1;i<=m;i++){
int x = e[i].x, y = e[i].y;
int fx = find(x), fy = find(y);
if(fx == fy)continue;
fa[fy] = fa[fx] = ++ totp;
w[totp] = e[i].v;
add(totp,fx);add(fx,totp);
add(totp,fy);add(fy,totp);
++ inmst;
if(inmst == n-1)break;
}
}
void dfs(int x,int fat=0){
f[x][0] = fat;
len[x][0] = dfs_clock;
int isleaf = 0;
for(int i=head[x];~i;i=ed[i].nxt){
int u=ed[i].to;
if(u == fat)continue;
dfs(u,x);
isleaf = 1;
}
if(!isleaf){
len[x][0] = ++dfs_clock;
update(rt[dfs_clock],rt[dfs_clock-1],1,nn,a[x]);
return ;
}
len[x][1] = dfs_clock;
}
int main(){
// freopen("Luogu4197.in","r",stdin);
memset(head,-1,sizeof head);
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)scanf("%d",&a[i]), b[i] = a[i];
sort(b+1,b+n+1);
nn = unique(b+1,b+n+1) - (b+1);
for(int i=1;i<=n;i++)a[i] = lower_bound(b+1,b+nn+1,a[i]) - b;
for(int i=1;i<=m;i++){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
e[i] = (edge){x,y,z};
}
kruskal();
dfs(totp);
for(int j=1;j<=20;j++){
for(int i=1;i<=totp;i++)f[i][j] = f[f[i][j-1]][j-1];
}
int lstans = -1;
while(q --){
int x,d,k;scanf("%d%d%d",&x,&d,&k);
if(~lstans)x ^= lstans, d ^= lstans, k ^= lstans;
for(int i=20;i>=0;i--){
if(f[x][i] && w[f[x][i]] <= d)x = f[x][i];
}
if(len[x][1] - len[x][0] < k){puts("-1");lstans = -1;continue;}
printf("%d\n",lstans = b[query(rt[len[x][0]], rt[len[x][1]],k,1,nn)]);
}
return 0;
}