Peaks 线段树合并
Peaks 线段树合并
\(n\)个带权值\(h_i\)山峰,有\(m\)条山峰间双向道路,\(q\)组询问,问从\(v_i\)开始只经过\(h_i\le x\)的路径所能到达的山峰中第\(k\)高的山峰,如果无解输出\(-1\)
线段树合并好题。吊打主席树、Kruskal重构树的典范
首先发现可以离线,我们将所有询问按\(x\)排序,随着询问再去加边,这样可以去掉路径上\(h_i\le x\)这一条件使问题极大简化。
然后从\(v_i\)开始能经过的所有山峰可以看做联通块,于是我们愉快地用并查集维护,用权值线段树查询第\(k\)大,合并联通块时合并权值线段树即可。很像[HNOI2012]永无乡。
另外注意此题是查询第\(k\)大,不是第\(k\)小。
#include <cstdio>
#include <algorithm>
#define MAXN 100010
#define MAXM 500005
using namespace std;
int n,m,q;
inline int read(){
char ch=getchar();int s=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+ch-'0', ch=getchar();
return s;
}
int h[MAXN],h_sort[MAXN],rnk[MAXN];
struct nod{
int u,v,val;
} edge[MAXM];
bool cmp_nod(const nod &a, const nod &b){
return a.val<b.val;
}
struct question{
int v,x,k;
int id;
} qs[MAXM];
bool cmp_qs(const question &a, const question &b){
return a.x<b.x;
}
int res[MAXM];
int fa[MAXN];
int get_fa(int x){
if(fa[x]==x) return x;
return fa[x]=get_fa(fa[x]);
}
#define MAXT MAXN*20
int rot[MAXN],tot,s;
int tre[MAXT],sl[MAXT],sr[MAXT];
void change(int &x, int l, int r, int pos){
if(x==0) x=++tot;
tre[x]+=1;
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) change(sl[x], l, mid, pos);
else change(sr[x], mid+1, r, pos);
}
int query(int x, int l, int r, int k){
if(x==0||tre[x]<k) return 0; // 如果不存在则返回0
if(l==r) return l;
int mid=(l+r)>>1;
if(tre[sr[x]]>=k) return query(sr[x], mid+1, r, k); // 找第k大所以先找右儿子
else return query(sl[x], l, mid, k-tre[sr[x]]);
}
int merge(int a, int b, int l, int r){
if(a==0||b==0) return a+b;
if(l==r){
tre[a]+=tre[b];
return a;
}
int mid=(l+r)>>1;
sl[a]=merge(sl[a], sl[b], l, mid);
sr[a]=merge(sr[a], sr[b], mid+1, r);
tre[a]=tre[sl[a]]+tre[sr[a]]; // 记得合并后更新
return a;
}
void merge_edge(int x){
int fa1=get_fa(edge[x].u),fa2=get_fa(edge[x].v);
if(fa1==fa2) return; // 如果已经都联通了则不需要合并线段树了
fa[fa2]=fa1;
rot[fa1]=merge(rot[fa1], rot[fa2], 1, s);
}
int main(){
n=read(),m=read(),q=read();
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=1;i<=n;++i) h_sort[i]=h[i]=read();
sort(h_sort+1, h_sort+1+n);
s=unique(h_sort+1, h_sort+1+n)-(h_sort+1);
for(int i=1;i<=n;++i){
rnk[i]=lower_bound(h_sort+1, h_sort+1+s, h[i])-h_sort; // 离散化
change(rot[i], 1, s, rnk[i]);
}
for(int i=1;i<=m;++i) edge[i].u=read(),edge[i].v=read(),edge[i].val=read();
sort(edge+1, edge+1+m, cmp_nod);
for(int i=1;i<=q;++i) qs[i].v=read(),qs[i].x=read(),qs[i].k=read(),qs[i].id=i;
sort(qs+1, qs+1+q, cmp_qs);
int pos=1;
for(int i=1;i<=q;++i){
int x=qs[i].x,v=qs[i].v,k=qs[i].k;
while(pos<=m&&edge[pos].val<=x) merge_edge(pos),++pos; // 把小于等于x的边加入
int ans=query(rot[get_fa(v)], 1, s, k);
if(ans==0) res[qs[i].id]=-1;
else res[qs[i].id]=h_sort[ans]; // 最后答案不是下标而是对应的值
}
for(int i=1;i<=q;++i) printf("%d\n", res[i]);
return 0;
}
Peaks 线段树合并的更多相关文章
- 【bzoj3545】[ONTAK2010]Peaks 线段树合并
[bzoj3545][ONTAK2010]Peaks 2014年8月26日3,1512 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路 ...
- BZOJ.3545.[ONTAK2010]Peaks(线段树合并)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...
- bzoj3545 Peaks 线段树合并
离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #in ...
- 【线段树合并】bzoj3545: [ONTAK2010]Peaks
1A还行 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问, ...
- [BZOJ3545] [ONTAK2010]Peaks(线段树合并 + 离散化)
传送门 由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序. 每到一个询问的时候,将边权小于等于x的都合并起来再询问. .. 有重复元素的线段树合并的时间复杂度是nlog^2n # ...
- BZOJ3545 Peaks 离线处理+线段树合并
题意: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...
- 线段树合并&&启发式合并笔记
这俩东西听起来很高端,实际上很好写,应用也很多~ 线段树合并 线段树合并,顾名思义,就是建立一棵新的线段树保存原有的两颗线段树的信息. 考虑如何合并,对于一个结点,如果两颗线段树都有此位置的结点,则直 ...
- [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】
题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...
随机推荐
- 从其他数据库迁移到MySQL及MySQL特点
从其他数据库迁移到MySQL Oracle,SQL Server迁移到MySQL 一些变化 不再使用存储过程.视图.定时作业 表结构变更,如采用自增id做主键,以及其他语法变更 业务SQL改造,不使用 ...
- Python学习路线2019升级版(课程大纲+视频教程+网盘资源下载)
2019最新Python全栈+人工智能学习路线升级版 全面涵盖前端.后端.爬虫.数据挖掘.人工智能等课程(课程大纲+视频教程+网盘资源下载)! 学习路线四大亮点: 1.人工智能三大主流框架全覆盖 2. ...
- Java基础IO类之数据流
DataInputStream: 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本java数据类型.应用程序可以使用数据输出流 写入稍后由数据输入流读取的数据.DataInputStrea ...
- ALV报表——抓取工单长文
ABAP抓取工单长文 运行效果: 代码: *&---------------------------------------------------------------------* *& ...
- SAS学习笔记54 RTF文件格式
Style RTF Control Word Example Code Italicize \i title '\i italicized title'; Underline \ul title '\ ...
- win10 idea springboot上传镜像到远程docker服务器
1. 开启2375端口,供外部访问docker vim /usr/lib/systemd/system/docker.service 修改ExecStart为下面一行内容 #ExecStart=/us ...
- Django-cms show_menu参数解释
当页面结构设置(/admin/cms/page)如下: - Home (level=0) - About Us (level=1) - About Company Services (level=2) ...
- jQuery的显示和隐藏
在 jQuery 中可以使用 hide() 和 show() 方法来隐藏和显示 HTML 元素,以及使用 toggle() 方法能够切换 hide() 和 show() 方法. 隐藏例子: <! ...
- vue滚动分页加载以及监听事件处理
<template> <div class="bodyContainer"> <div class="allContent" id ...
- docker 推送镜像到阿里云
1. 登录阿里云Docker Registry $ sudo docker login --username=www.18860363800@hotmail.com registry.cn-beiji ...