首页 技术 正文
技术 2022年11月12日
0 收藏 969 点赞 3,782 浏览 2769 个字

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1124  Solved: 304
[Submit][Status][Discuss]

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。

题解:

  把M+Q个操作全部存起来,准备离线操作,添加路径的flag为1,询问的flag为0,id为i-M方便记录答案。以困难值为第一关键字,flag为第二关键字排序。这样碰到询问操作则当前的的所有连通块之间的边的困难值满足要求,记录连通块之间的信息用并查集维护一下就好了。

  本题用可持久化线段树的来维护,建立N棵线段树,如果a和b之间连了一条边,则把线段树a和线段树b合并起来,由于所有线段树的形态均相同,所以只要对应的权值相加减即可。

  具体看代码。

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1e5+;
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int N,M,Q,ans[*maxn];
int H[maxn],h[maxn],hash[maxn],tot;
int root[maxn],siz;
struct Tree{
int lc,rc,w;
}tr[maxn*];
inline int find(int x){
int l=,r=tot;
while(l<=r){
int mid=(l+r)>>;
if(hash[mid]<x) l=mid+;
else if(hash[mid]>x) r=mid-;
else if(hash[mid]==x) return mid;
}
return l;
} struct node{
int a,b,w;
int flag,id;
}g[maxn*];
int cmp(const node&q,const node&e){
return q.w<e.w||(q.w==e.w&&q.flag>e.flag);
} int fa[maxn];
inline int getfa(int r){
if(r!=fa[r]) fa[r]=getfa(fa[r]);
return fa[r];
} inline void insert(int &i,int l,int r,int w){
i=++siz;
tr[i].w=;
if(l==r) return ;
int mid=(l+r)>>;
if(w<=mid) insert(tr[i].lc,l,mid,w);
else insert(tr[i].rc,mid+,r,w);
}
inline int query(int i,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)>>;
if(tr[tr[i].lc].w>=k)return query(tr[i].lc,l,mid,k);
else return query(tr[i].rc,mid+,r,k-tr[tr[i].lc].w);
}
inline int merge(int x,int y){
if(x==) return y;
if(y==) return x;
if(tr[x].lc==&&tr[x].rc==){
tr[x].w=tr[x].w+tr[y].w;
return x;
}
tr[x].lc=merge(tr[x].lc,tr[y].lc);
tr[x].rc=merge(tr[x].rc,tr[y].rc);
tr[x].w=tr[tr[x].lc].w+tr[tr[x].rc].w;
return x;
}
int main(){
N=read(); M=read(); Q=read();
for(int i=;i<=N;i++) H[i]=read(),h[i]=H[i];
sort(h+,h+N+);
hash[++tot]=h[];
for(int i=;i<=N;i++){//按照山的高度离散化+去重
if(h[i]!=h[i-]) hash[++tot]=h[i];
} for(int i=,a,b,w;i<=M+Q;i++){
a=read(); b=read(); w=read();
if(i<=M){
g[i].flag=;
g[i].a=a; g[i].b=b; g[i].w=w;
}
else{
g[i].id=i-M;
g[i].a=a; g[i].w=b; g[i].b=w;
}
}
sort(g+,g+M+Q+,cmp);
for(int i=;i<=N;i++) fa[i]=i;
for(int i=;i<=N;i++){
int w=find(H[i]);
insert(root[i],,tot,w);
}
for(int i=;i<=M+Q;i++){
if(g[i].flag==){//在图中加入一条边
int p=getfa(g[i].a),q=getfa(g[i].b);
if(p!=q){
fa[p]=q;
root[q]=merge(root[p],root[q]);
}
}
else{//询问
int v=getfa(g[i].a);
if(tr[root[v]].w<g[i].b) ans[g[i].id]=-;
else ans[g[i].id]=hash[query(root[v],,tot,tr[root[v]].w-g[i].b+)];
}
}
for(int i=;i<=Q;i++){
printf("%d\n",ans[i]);
}
return ;
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,989
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,504
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,348
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,131
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,765
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,842