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的双向路径. 接下来 ...
随机推荐
- Zabbix监控web,MySQL,TCP状态,Nginx
接上篇Zabbix使用SMTP发送邮件报警并且制定报警内容 Zabbix怎么设置声音告警 web监控 在zabbix server选择web 创建一个监控web的场景 添加后这里有数字1 查看 假如在 ...
- 读取properties文件------servletcontext及dao层读取
用servletcontext读取properties文件-------1) 重点在于:InputStream in=this.getServletContext().getResourceAsStr ...
- 20165330 2017-2018-2 《Java程序设计》第6周学习总结
课本知识总结 第八章 常用实用类 String类 String对象 构造方法: 使用String类声明对象并创建对象 String s = new String("we are studen ...
- [linux基础学习]默认的目录介绍
以下用一个表格来罗列linux默认的目录或文件及其用途: 目录/文件 用途 来源 / /处于Linux文件系统树形结构的最顶端,它是Linux文件系统的入口,所有的目录.文件.设备都在/之下. - / ...
- Vi 的常用命令
1. vi 的三种工作模式 命令模式 打开文件首先进入命令模式, 是使用 vi 的入口; 通过命令对文件进行常规的编辑操作, 例如: 定位,翻页,复制,粘贴,删除等; 末行模式 执行保存,退出等操作, ...
- CSS冲突1 要关掉的css在项目内:【material-table】 中 checkbox 点击checkbox无法选中or取消,点击旁边才能选中or取消
CSS优先级: !important > 行内样式 > 内嵌样式|链接外部样式(哪个在后面哪个优先级大) id选择器 > class选择器 > 元素选择器 react中好像还不 ...
- git 常用文件目录介绍
生成的RSA公钥与密钥目录: C:\Users\***\.ssh 系统配置文件路径 C:\ProgramData\Git\ C:\Program Files\Git\mingw64\etc 全 ...
- lua相关库安装常见问题
一.先安装lua brew install lua 我本机的安装路径为:/usr/local/Cellar/lua/5.3.4_2 二.安装luarocks 下载luarocks的安装包: http: ...
- openresty跑定时任务配置、ngx.timer.every接口使用
openresty的定时任务是要跟worker绑定的.如果不绑定特定的worker,那么所有启动的woker都会去执行定时任务. 一般情况下默认绑定worker_id=0的,这样在nginx整个进程里 ...
- 如何在python项目中写出像Django中一样功能的settings
一 核心文件目录结构 二 实现代码 resdme: 在实现此功能主要用到的知识点及模块: 1.反射 3.内置方法dir # 全局配置 NAME = 'root' # 用户配置 NAME = 'pe ...