Description
在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
Solution
一个比较好想的做法就是离线询问然后splay启发式合并,这样写常数可能比较大但是非常直观
另一个比较好写的做法就是离线询问然后权值线段树合并,这样比较好写
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=500005;
const int E=800005;
struct edge {int x,y,w,id;} e[E],q[E];
struct treeNode {int son[2],fa,v,size;} t[N*2];
std:: vector <int> vec[N];
int fa[N],root[N],tot;
int ans[N],h[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int x) {
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
}
void rotate(int x) {
int y=t[x].fa; int z=t[y].fa;
int k=t[y].son[1]==x;
t[z].son[t[z].son[1]==y]=x; t[x].fa=z;
t[y].son[k]=t[x].son[!k]; t[t[x].son[!k]].fa=y;
t[y].fa=x; t[x].son[!k]=y;
push_up(y); push_up(x);
}
void splay(int x,int &root) {
while (t[x].fa) {
int y=t[x].fa; int z=t[y].fa;
if (z) {
if ((t[y].son[1]==x)^(t[z].son[1]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
root=x;
}
void ins(int &root,int v) {
int x=root,y;
while (x) {
y=x;
x=t[x].son[v>t[x].v];
}
t[++tot]=(treeNode) {{0,0},y,v,1};
t[y].son[v>t[y].v]=tot;
splay(tot,root);
}
int kth(int x,int k) {
while (233) {
if (t[t[x].son[0]].size+1==k) return t[x].v;
if (t[t[x].son[0]].size>=k) x=t[x].son[0];
else {
k-=t[t[x].son[0]].size+1;
x=t[x].son[1];
}
}
}
int get_father(int x) {
if (!fa[x]) return x;
return fa[x]=get_father(fa[x]);
}
void merge(int x,int y) {
x=get_father(x); y=get_father(y);
if (x==y) return ;
if (t[root[x]].size<t[root[y]].size) std:: swap(x,y);
fa[y]=x;
for (int i=0;i<vec[y].size();i++) {
int v=vec[y][i];
ins(root[x],v);
vec[x].push_back(v);
}
}
bool cmp1(edge a,edge b) {
return a.w<b.w;
}
bool cmp2(edge a,edge b) {
return a.y<b.y;
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n=read(),m=read(),T=read();
rep(i,1,n) { h[i]=-read();
root[i]=++tot;
t[tot].v=h[i]; t[tot].size=1;
vec[i].push_back(h[i]);
}
rep(i,1,m) e[i]=(edge) {read(),read(),read()};
rep(i,1,T) q[i]=(edge) {read(),read(),read(),i};
std:: sort(e+1,e+m+1,cmp1);
std:: sort(q+1,q+T+1,cmp2);
int now=1;
rep(gg,1,T) {
while (now<=m&&e[now].w<=q[gg].y) {
merge(e[now].x,e[now].y);
now++;
}
int x=get_father(q[gg].x);
if (q[gg].w>t[root[x]].size) ans[q[gg].id]=-1;
else ans[q[gg].id]=-kth(root[x],q[gg].w);
}
rep(i,1,T) printf("%d\n", ans[i]);
return 0;
}