Description
在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。
Input
第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。
Output
对于每组询问,输出一个整数表示答案。
Sample Input
10 11 4
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2
Sample Output
6
1
-1
8
HINT
【数据范围】
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
Source
By Sbullet
题解:
排序+离散化+并查集+线段树合并,具体看代码。
不知为啥这题线段树合并这么慢。
#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar(); }
return x*f;
}
struct Tre{
int l,r,a;
}tree[100005*40];
struct Edg{
int fro,poi,cost;
}e[1000005];
struct Que{
int v,x,k,id;
}a[1000005];
int root[1000005],b[1000005],c[1000005],rt=0,fa[1000005],ans[1000005];
bool tmp2(Que a,Que b){
return (a.x<b.x)||(a.x==b.x&&a.id<b.id);
}
int find(int x){
if (x==fa[x]) return x;
fa[x]=find(fa[x]); return fa[x];
}
void insert(int &u,int l,int r,int x){
if (!u) u=++rt;
tree[u].a++;
if (l==r){return;}
int mid=(l+r)>>1;
if (x<=mid) insert(tree[u].l,l,mid,x);
else insert(tree[u].r,mid+1,r,x);
}
int merge(int x,int y){
if (!y) return x;
if (!x) return y;
if (!tree[x].l&&!tree[x].r){
tree[x].a=tree[x].a+tree[y].a; return x;}
tree[x].l=merge(tree[x].l,tree[y].l);
tree[x].r=merge(tree[x].r,tree[y].r);
tree[x].a=tree[tree[x].l].a+tree[tree[x].r].a;
return x;
}
int query(int u,int l,int r,int k){
int num=tree[tree[u].l].a;
int mid=(l+r)>>1;
if (l==r) return l;
if (k<=num) return query(tree[u].l,l,mid,k);
else query(tree[u].r,mid+1,r,k-num);
}
int main(){
int n=read(),m=read(),q=read();
for (int i=1;i<=n;i++){
b[i]=read(); c[i]=b[i]; fa[i]=i; }
sort(c+1,c+1+n);
for (int i=1;i<=n;i++){
b[i]=lower_bound(c+1,c+1+n,b[i])-c;
insert(root[i],1,n,b[i]);
}
for (int i=1;i<=m;i++){
a[i].id=0; a[i].v=read(); a[i].k=read(); a[i].x=read();}
for (int i=m+1;i<=m+q;i++){
a[i].v=read(); a[i].x=read(); a[i].k=read(); a[i].id=i-m;
}
sort(a+1,a+1+q+m,tmp2);
for (int i=1;i<=m+q;i++){
if (a[i].id==0){
int x=a[i].v,y=a[i].k;
int fx=find(x),fy=find(y);
if (fx!=fy){
fa[fy]=fx;
root[fx]=merge(root[fx],root[fy]);
}
} else{
int fx=find(a[i].v);
if (tree[root[fx]].a<a[i].k) ans[a[i].id]=-1;
else ans[a[i].id]=c[query(root[fx],1,n,tree[root[fx]].a-a[i].k+1)];
}
}
for (int i=1;i<=q;i++)
printf("%d\n",ans[i]);
return 0;
}