题目描述:
在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值c,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰的高度,如果无解输出-1。
N
<
=
1
0
5
,
M
,
Q
<
=
5
∗
1
0
5
,
h
i
,
c
,
x
<
=
1
0
9
。
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
N<=105,M,Q<=5∗105,hi,c,x<=109。
题目分析:
原题题面有误,我在上面修改了,原题面没有“的高度”,然后我就WA自闭
加强版是在线的,就先把边排序,把kruskal树中的点每个开一个动态开点的线段树,父亲由两个儿子合并而来。
询问的时候直接从那个点往上倍增找到瓶颈点,在它的线段树中找第k大即可。
(第k高是指有k-1个比它高,所以找的时候要么判右子树的siz,要么在外面把k反过来)
线段树的空间一开始开的maxn*20,结果又RE又WA,开成*30就过了。。。
Code:
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define LL long long
#define maxn 200005
#define maxm 500005
#define maxp maxn*30
using namespace std;
char cb[1<<18],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<18,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
char c;while(!isdigit(c=getc()));
for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
int n,m,Q,ans,h[maxn],f[maxn][20],F[maxn];
struct node{
int x,y,z;
bool operator < (const node &p)const{return z<p.z;}
}e[maxm];
int find(int x){return x==F[x]?x:F[x]=find(F[x]);}
int search(int x,int v){
for(int i=17;i>=0;i--) if(h[f[x][i]]<=v) x=f[x][i];
return x;
}
int rt[maxn],lc[maxp],rc[maxp],s[maxp],id[maxp],tot;
void insert(int &now,int l,int r,int x){
s[++tot]=s[now]+1,lc[tot]=lc[now],rc[tot]=rc[now];
now=tot;
if(l==r) return;
int mid=(l+r)>>1;
if(x<=mid) insert(lc[now],l,mid,x);
else insert(rc[now],mid+1,r,x);
}
void merge(int &now,int x,int y){
if(!x||!y) now=x+y;
else{
s[now=++tot]=s[x]+s[y];
merge(lc[now],lc[x],lc[y]);
merge(rc[now],rc[x],rc[y]);
}
}
int query(int now,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)>>1;
if(k<=s[lc[now]]) return query(lc[now],l,mid,k);
else return query(rc[now],mid+1,r,k-s[lc[now]]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("H.in","r",stdin);
#endif
int x,y,k;
read(n),read(m),read(Q);
for(int i=1;i<=n;i++) read(h[i]),insert(rt[i],1,1e9,h[i]);
for(int i=1;i<=m;i++) read(e[i].x),read(e[i].y),read(e[i].z);
sort(e+1,e+1+m);
for(int i=1;i<=n;i++) F[i]=i;
for(int i=1;i<=m;i++){
x=find(e[i].x),y=find(e[i].y);
if(x!=y){
++n,F[n]=F[x]=F[y]=f[x][0]=f[y][0]=n;
h[n]=e[i].z,merge(rt[n],rt[x],rt[y]);
}
}
h[0]=1<<30;
for(int j=1;j<=17;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
while(Q--){
read(x),read(y),read(k);
if(ans>0) x^=ans,y^=ans,k^=ans;
x=search(x,y);
if(s[rt[x]]<k) printf("%d\n",ans=-1);
else printf("%d\n",ans=query(rt[x],1,1e9,s[rt[x]]-k+1));
}
}