bzoj 3545: [ONTAK2010]Peaks
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
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
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 ;
}
bzoj 3545: [ONTAK2010]Peaks的更多相关文章
- BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )
这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...
- BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]
3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...
- ●BZOJ 3545 [ONTAK2010]Peaks(离线)
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3545 http://www.lydsy.com/JudgeOnline/problem.ph ...
- BZOJ.3545.[ONTAK2010]Peaks(线段树合并)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...
- bzoj 3545: [ONTAK2010]Peaks Kruskal重构树
题目: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...
- BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay
Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询 ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
- BZOJ 3551/3545: [ONTAK2010]Peaks加强版 (Kruskal树+dfs序上的主席树+倍增)
Orz PoPoQQQ 学到了维护子树信息的时候用dfsdfsdfs序套主席树节省线段树空间. 学到了怎么用指针写可持久化线段树-emmm- CODE 只贴上3551加强版带强制在线的代码 #incl ...
- bzoj 3551: [ONTAK2010]Peaks加强版
Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...
随机推荐
- JavaScript 禁止表单提交
有时我们需要在表单真正提交之前,做一些检查工作,检查通过之后再进行提交. <form name="myForm" onsubmit = "validateMyFor ...
- 160317(二)、按sort排序,sort为空的在后面
按sort排序,sort为空的在后面 select * from 表名 order by (case when sort is null or sort='' then 1 else 0 end),s ...
- Javascript-const 常量
const 常量 常量是块级作用域,很像使用 let语句定义的变量.常量的值不能通过重新赋值来改变,并且不能重新声明. 此声明创建一个常量,其作用域可以是全局或本地声明的块. 与var变量不同,全局常 ...
- java generic super, extend
//Apple Orange 都继承自Fruit类,同时Jonathan是Apple的子类 List<? extends Fruit> list = new ArrayList< ...
- 一篇搞定MongoDB
MongoDB最基础的东西,我这边就不多说了,这提供罗兄三篇给大家热身 MongoDB初始 MongoDB逻辑与物理存储结构 MongoDB的基础操作 最后对上述内容和关系型数据做个对比 非关系型数据 ...
- 前端开发 - JQuery&Bootstrap - 总结
一.JavaScript和Jquery的区别 1.javascript的缺点: 1.书写繁琐,代码量大 2.代码复杂 3.动画效果,很难实现.使用定时器 各种操作和处理 2.定义: 1.Javascr ...
- Python 进程(process)
1. 进程 1.1 进程的创建 fork 正在运行着的代码,就称为进程 # 示例: import os # 注意: fork 函数,只在 Unix/Linux/Mac 上运行, windows 不可以 ...
- MapReduce分析流量汇总
一.MapReduce编程规范 一.MapReduce编程规范 用户编写mr程序主要分为三个部分:Mapper,Reducer,Driver 1.Mapper阶段 (1)用户自定义Mapper类 要继 ...
- HDFS集群启动start-dfs.sh报错
[root@master sbin]# start-dfs.sh Starting namenodes on [master] master: Error: JAVA_HOME is not set ...
- URL地址中的字符串转换
url出现了有+,空格,/,?,%,#,&,=等特殊符号的时候,可能在服务器端无法获得正确的参数值,怎么解决?解决办法将这些字符转化成服务器可以识别的字符,对应关系如下:URL字符转义 用其它 ...