博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj 3545: [ONTAK2010]Peaks
阅读量:6413 次
发布时间:2019-06-23

本文共 3343 字,大约阅读时间需要 11 分钟。

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

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合并起来,由于所有线段树的形态均相同,所以只要对应的权值相加减即可。

  具体看代码。

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 using namespace std; 10 const int maxn=1e5+10; 11 inline int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){ if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 int N,M,Q,ans[5*maxn]; 18 int H[maxn],h[maxn],hash[maxn],tot; 19 int root[maxn],siz; 20 struct Tree{ 21 int lc,rc,w; 22 }tr[maxn*50]; 23 inline int find(int x){ 24 int l=1,r=tot; 25 while(l<=r){ 26 int mid=(l+r)>>1; 27 if(hash[mid]
x) r=mid-1; 29 else if(hash[mid]==x) return mid; 30 } 31 return l; 32 } 33 34 struct node{ 35 int a,b,w; 36 int flag,id; 37 }g[maxn*12]; 38 int cmp(const node&q,const node&e){ 39 return q.w
e.flag); 40 } 41 42 int fa[maxn]; 43 inline int getfa(int r){ 44 if(r!=fa[r]) fa[r]=getfa(fa[r]); 45 return fa[r]; 46 } 47 48 inline void insert(int &i,int l,int r,int w){ 49 i=++siz; 50 tr[i].w=1; 51 if(l==r) return ; 52 int mid=(l+r)>>1; 53 if(w<=mid) insert(tr[i].lc,l,mid,w); 54 else insert(tr[i].rc,mid+1,r,w); 55 } 56 inline int query(int i,int l,int r,int k){ 57 if(l==r) return l; 58 int mid=(l+r)>>1; 59 if(tr[tr[i].lc].w>=k)return query(tr[i].lc,l,mid,k); 60 else return query(tr[i].rc,mid+1,r,k-tr[tr[i].lc].w); 61 } 62 inline int merge(int x,int y){ 63 if(x==0) return y; 64 if(y==0) return x; 65 if(tr[x].lc==0&&tr[x].rc==0){ 66 tr[x].w=tr[x].w+tr[y].w; 67 return x; 68 } 69 tr[x].lc=merge(tr[x].lc,tr[y].lc); 70 tr[x].rc=merge(tr[x].rc,tr[y].rc); 71 tr[x].w=tr[tr[x].lc].w+tr[tr[x].rc].w; 72 return x; 73 } 74 int main(){ 75 N=read(); M=read(); Q=read(); 76 for(int i=1;i<=N;i++) H[i]=read(),h[i]=H[i]; 77 sort(h+1,h+N+1); 78 hash[++tot]=h[1]; 79 for(int i=2;i<=N;i++){ //按照山的高度离散化+去重 80 if(h[i]!=h[i-1]) hash[++tot]=h[i]; 81 } 82 83 for(int i=1,a,b,w;i<=M+Q;i++){ 84 a=read(); b=read(); w=read(); 85 if(i<=M){ 86 g[i].flag=1; 87 g[i].a=a; g[i].b=b; g[i].w=w; 88 } 89 else{ 90 g[i].id=i-M; 91 g[i].a=a; g[i].w=b; g[i].b=w; 92 } 93 } 94 sort(g+1,g+M+Q+1,cmp); 95 for(int i=1;i<=N;i++) fa[i]=i; 96 for(int i=1;i<=N;i++){ 97 int w=find(H[i]); 98 insert(root[i],1,tot,w); 99 }100 for(int i=1;i<=M+Q;i++){101 if(g[i].flag==1){ //在图中加入一条边 102 int p=getfa(g[i].a),q=getfa(g[i].b);103 if(p!=q){104 fa[p]=q;105 root[q]=merge(root[p],root[q]);106 }107 }108 else{ //询问 109 int v=getfa(g[i].a);110 if(tr[root[v]].w

 

 

 

转载于:https://www.cnblogs.com/CXCXCXC/p/5239313.html

你可能感兴趣的文章
在Linux服务器、客户端中构建密钥对验证进行远程连接
查看>>
揪出MySQL磁盘消耗迅猛的真凶
查看>>
和“C”的再遇
查看>>
linux 的日志系统
查看>>
[转]一个python‘非多态’的问题
查看>>
一键安装kubernetes 1.13.0 集群
查看>>
Java内存模型
查看>>
第一讲 机器学习中的数学
查看>>
RabbitMq的集群搭建
查看>>
asp.net web常用控件FileUpload(文件上传控件)
查看>>
动态网页的建立
查看>>
参数展开与特殊字符
查看>>
linux下使用nginx搭建流媒体服务器
查看>>
解读MySQL驱动加载逻辑
查看>>
Python的time模块(一)
查看>>
Spring控制器注解
查看>>
根据日期分组,查询数量、总量等信息
查看>>
spring boot + mybatis 同时访问多数据源
查看>>
Linux服务器(CentOS)安装SVN(subversion)教程
查看>>
Oracle官网下载jdk 版本
查看>>