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 线段树合并的更多相关文章

  1. 【bzoj3545】[ONTAK2010]Peaks 线段树合并

    [bzoj3545][ONTAK2010]Peaks 2014年8月26日3,1512 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路 ...

  2. BZOJ.3545.[ONTAK2010]Peaks(线段树合并)

    题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...

  3. bzoj3545 Peaks 线段树合并

    离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #in ...

  4. 【线段树合并】bzoj3545: [ONTAK2010]Peaks

    1A还行 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问, ...

  5. [BZOJ3545] [ONTAK2010]Peaks(线段树合并 + 离散化)

    传送门 由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序. 每到一个询问的时候,将边权小于等于x的都合并起来再询问. .. 有重复元素的线段树合并的时间复杂度是nlog^2n # ...

  6. BZOJ3545 Peaks 离线处理+线段树合并

    题意: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...

  7. 线段树合并&&启发式合并笔记

    这俩东西听起来很高端,实际上很好写,应用也很多~ 线段树合并 线段树合并,顾名思义,就是建立一棵新的线段树保存原有的两颗线段树的信息. 考虑如何合并,对于一个结点,如果两颗线段树都有此位置的结点,则直 ...

  8. [XJOI NOI2015模拟题13] C 白黑树 【线段树合并】

    题目链接:XJOI - NOI2015-13 - C 题目分析 使用神奇的线段树合并在 O(nlogn) 的时间复杂度内解决这道题目. 对树上的每个点都建立一棵线段树,key是时间(即第几次操作),动 ...

  9. [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】

    题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...

随机推荐

  1. 在论坛中出现的比较难的sql问题:17(字符分拆2)

    原文:在论坛中出现的比较难的sql问题:17(字符分拆2) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必要记录下来 ...

  2. RuntimeError: Model class users.models.UserProfile doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

    Django启动的时候报错 File "/home/hehecat/PycharmProjects/MxShop/MxShop/urls.py", line 23, in from ...

  3. DotNet 使用阿里云媒体转码服务

    公司项目中一部分文件放到了阿里云 OSS 上,其中有些音频文件是 amr 类型的,在后期使用的时候比较麻烦,所以需要转换成 mp3 的文件,方便以后使用.本来想使用 ffmpeg 处理,但由于文件都存 ...

  4. Asp.netCore 是用的Socket 吗?

    Asp.netCore 是用的Socket 的krestrel 用的是Socket! public static IWebHostBuilder CreateDefaultBuilder(string ...

  5. R_基础_01

    R语言介绍:R是一种区分大小写的解释型语言.R中有多种数据类型,包括向量.矩阵.数据框(与数据集类似)以及列表(各种对象的集合),广泛用于数据统计. R的特点:一次交互式会话期间的所有数据对象都被保存 ...

  6. vue的交互

    交互     Vue做交互需要引入一个库:vue-resouce.js     get:      post     jsonp   <script src="vue.js" ...

  7. linux配置sftp简单过程

    首先疑惑是,  他需要的是上级的目录权限必须为root, 这点我有点不明白 环境是centos7.6 ssh 首先开整/etc/ssh/sshd_config # override default o ...

  8. 等保测评中与oracle有关的工作

    等保2.0包含硬件.存储.中间件.数据库各方面的安全规范,现把与Oracle数据库有关的内容整理如下,供参考: 一.安全计算环境 1.身份鉴别: a,应对登陆的用户进行身份标识和鉴别,身份标识具有唯一 ...

  9. Xcode11.1 踩坑备忘录

    Xcode11.1 踩坑备忘录(mac系统10.15) 1 .环信ChatDemo2.0报错 这是环信ChatDemo2.0报错 NSInteger numberOfBeforeSection = [ ...

  10. centos 7.6 配置VNC

    一.安装 1.  以root用户运行以下命令来安装vncserver; yum install tigervnc-server 2.  同样运行以下命令来安装vncviewer; yum instal ...