「BZOJ3545」「ONTAK2010」Peaks

题目传送门

题目大意:

给定一个 \(n\) 个点,\(m\) 条边的带点权边权无向图,有 \(q\) 次询问,每次询问从 \(v\) 点出发,经过边权 \(\le x\) 的边能够经过的第 \(k\) 大点权,若不足 \(k\) 个输出 \(-1\)。


离线似乎可以使用类似于「HNOI2010」永无乡的线段树合并/平衡树启发式合并解法。

我们在这里只讨论在线做法。

首先考虑如何处理边权 \(\le x\) 这一条件,显然,我们在最小生成树上走是最优的。

所以我们可以考虑将边权从小到大排序,构建一棵Kruskal重构树,这样我们在查询的时候就只需要在这颗重构树上倍增即可求出我们需要的特殊点。

什么是Kruskal重构树?

就是使用Kruskal算法求最小生成树,当每次合并两个连通块的时候,新建一个节点作为两个连通块的父亲,让这条边的边权作为这个新点的点权,这样最后会形成一棵二叉树的结构,而这棵树有这样一个性质:非叶点权从下到上递增

所以我们在上面才可以倍增求解。

然后考虑后一个条件:第 \(k\) 大点权。

我们发现,这实际上就是让我们在以特殊点为根的子树的叶节点中求出第 \(k\) 大点权,这个利用在 \(\texttt{DFS}\) 序上建立可持久化线段树就可以轻松解决。

至此,本题完结。

注意一些细节以及空间优化、常数优化。

贴代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
char buf[1<<24],*p1=buf,*p2=buf;
char getch(){
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++;
}
int read(){
int num=0;char ch=getch();
while(!isdigit(ch)) ch=getch();
while(isdigit(ch)) num=num*10+ch-'0',ch=getch();
return num;
}
int a[maxn],b[maxn];
struct cc{
int u,v,w;
bool operator<(const cc &h)const{
return w<h.w;
}
}e[maxn*5];
int num=0;
int rt[maxn],ls[maxn*20],rs[maxn*20],sum[maxn*20],cnt;
void update(int &u,int &pos,int l,int r,int &t){
u=++cnt;
ls[u]=ls[pos],rs[u]=rs[pos],sum[u]=sum[pos]+1;
if(l==r) return ;
int mid=(l+r)>>1;
if(t<=mid) update(ls[u],ls[pos],l,mid,t);
else update(rs[u],rs[pos],mid+1,r,t);
}
int query(int &ll,int &rr,int l,int r,int k){
if(sum[rr]<k) return 0;
if(l==r) return l;
int x=sum[rs[rr]]-sum[rs[ll]];
int mid=(l+r)>>1;
if(k<=x) return query(rs[ll],rs[rr],mid+1,r,k);
else return query(ls[ll],ls[rr],l,mid,k-x);
}//主席树部分
int f[maxn][20],mx[maxn][20];
int ch[maxn][2],tot;
int fa[maxn];
int getfa(int t){
return fa[t]==t?t:fa[t]=getfa(fa[t]);
}
int dfn[maxn],tim;
int siz[maxn];
int n,m,q;
void dfs(int &u){
dfn[u]=++tim,siz[u]=1;
if(u<=n) update(rt[dfn[u]],rt[dfn[u]-1],1,num,a[u]);//实点
else rt[dfn[u]]=rt[dfn[u]-1];//虚点
for(int i=0;i<=1;++i){
int v=ch[u][i];
if(!v) continue;
f[v][0]=u,mx[v][0]=a[u];
dfs(v);siz[u]+=siz[v];
}
}
inline void solve(int &x,int &d){
for(int i=18;i>=0;--i){
if(f[x][i]&&mx[x][i]<=d) x=f[x][i];
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
n=read(),m=read(),q=read();
for(int i=1;i<=n;++i){
b[i]=read(),a[i]=b[i];
fa[i]=i;
}
b[0]=-1;
for(int i=1;i<=m;++i){
int a=read(),b=read(),c=read();
e[i]=(cc){a,b,c};
}
tot=n;
sort(e+1,e+m+1);
for(int i=1;i<=m;++i){
int fu=getfa(e[i].u),fv=getfa(e[i].v);
if(fu==fv) continue;
++tot;fa[tot]=fa[fu]=fa[fv]=tot;
b[tot]=a[tot]=e[i].w;
ch[tot][0]=fv,ch[tot][1]=fu;
}
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;++i)
a[i]=lower_bound(b+1,b+num+1,a[i])-b;//离散化
dfs(tot);
for(int j=1;j<=18;++j){
for(int i=1;i<=tot;++i){
f[i][j]=f[f[i][j-1]][j-1];
mx[i][j]=max(mx[i][j-1],mx[f[i][j-1]][j-1]);
}
}//倍增预处理
for(int i=1;i<=q;++i){
int aa=read(),bb=read(),cc=read();
solve(aa,bb);
cout<<b[query(rt[dfn[aa]-1],rt[dfn[aa]+siz[aa]-1],1,num,cc)]<<'\n';
}
return 0;
}

「BZOJ3545」「ONTAK2010」Peaks的更多相关文章

  1. 【BZOJ3551】【BZOJ3545】 【ONTAK2010】 Peaks (kruskal重构树+主席树)

    Description ​ 在\(Bytemountains\)有\(~n~\)座山峰,每座山峰有他的高度\(~h_i~\). 有些山峰之间有双向道路相连,共\(~m~\)条路径,每条路径有一个困难值 ...

  2. 众安「尊享e生」果真牛的不可一世么?

    近日,具有互联网基因的.亏损大户(成立三年基本没盈利,今年二季度末亏损近4亿,你能指望它多厉害?).财产险公司—众安推出“尊享e生”中高端医疗保险(财险公司经营中高端医疗真的很厉害?真的是中高端医疗险 ...

  3. XCActionBar 「Xcode 中的 Alfred」

    下载地址:https://github.com/pdcgomes/XCActionBar 基本命令: (1)「command+shift+8」或者双击「command」键可以打开「动作输入框窗口」 ( ...

  4. Git 执行 「fork 出来的仓库」和「最新版本的原仓库」内容同步更新

    当我们在 GitHub 上 fork 出一个仓库后,如果原仓库更新了,此时怎样才能保证我们 fork 出来的仓库和原仓库内容一致呢?我们一般关注的是仓库的 master(主干分支)的内容,通过以下步骤 ...

  5. 【翻译】西川善司的「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密,后篇

    http://www.4gamer.net/games/216/G021678/20140714079/     连载第2回的本回,  Arc System Works开发的格斗游戏「GUILTY G ...

  6. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part1:概述

    本文系对「C++ Rvalue References Explained」 该文的翻译,原文作者:Thomas Becker. 该文较详细的解释了C++11右值引用的作用和出现的意义,也同时被Scot ...

  7. 「Windows MFC 」「Edit Control」 控件

    「Windows MFC 」「Edit Control」 控件

  8. 苹果搜索广告后台大揭秘,最全最细致详解,手把手设置教程「后附官方视频」-b

    WWDC2016 搜索广告分会视频和 PPT 发布了,ASO100 带开发者第一时间了解 Search Ads 后台设置(文末有原声视频). 首先介绍一下搜索广告的模式和竞价规则 广告模式为 CPT( ...

  9. 被「李笑来老师」拉黑之「JavaScript微博自动转发的脚本」

    故事的背景如下图,李笑来 老师于10月19日在 知乎Live 开设 一小时建立终生受用的阅读操作系统 的讲座,他老人家看到大家伙报名踊跃,便在微博上发起了一个 猜数量赢取iPhone7 的活动. 因为 ...

随机推荐

  1. 达梦数据库产品支持技术学习分享_Week1

    本周主要从以下几个方面进行本人对达梦数据库学习的分享,学习进度和学习情况因人而异,仅供参考. 一.达梦数据库的体系架构 二.达梦数据库的安装 三.达梦数据库的数据类型 四.达梦数据库的DDL.DML. ...

  2. ELK技术栈之-Logstash详解

    ELK技术栈之-Logstash详解   前言 在第九章节中,我们已经安装好Logstash组件了,并且启动实例测试它的数据输入和输出,但是用的是最简单的控制台标准输入和标准输出,那这节我们就来深入的 ...

  3. h264和h265多维度区别

    h264和h265多维度区别 1.  概述 h265旨在在有限带宽下传输更高质量的网络视频,仅需原先的一半带宽即可播放相同质量的视频,很多朋友不知道h264和h265如何区别,下面让我们一起来了解一下 ...

  4. IaaS、PaaS 和 SaaS:云服务模型概述

    IaaS.PaaS 和 SaaS:云服务模型概述 为您的组织选择合适的云服务模型,可以帮助您充分利用预算和 IT 资源. 基础设施即服务 (IaaS).平台即服务 (PaaS) 以及软件即服务 (Sa ...

  5. 运用iGuard防御ADS权限维持

    权限维持是一门庞大的学问,当攻击者在入侵服务器获得主机权限后,往往会想尽办法隐藏其入侵途径以维持权限.权限维持的一般手段包括构造文件包含漏洞.构造远程任意代码执行漏洞.构造SQL注入点.利用系统自启动 ...

  6. python应用_读取Excel数据【二】_二次封装之函数式封装

    目的:想要把对Excel文件读取做成一个通用的函数式封装,便于后续简单调用,隔离复杂性. 未二次封装前原代码: #coding=gbkimport osimport xlrdcurrent_path= ...

  7. 谁能干掉了if else

    很多人觉得自己写的是业务代码,按照逻辑写下去,再把公用的方法抽出来复用就可以了,设计模式根本就没必要用,更没必要学. 一开始的时候,我也是这么想,直到我遇到... 举个例子 我们先看一个普通的下单拦截 ...

  8. Linux命令大全之查看登陆用户信息

    1,w +回车 2.who +回车 3.last+回车 4.lastlog+回车

  9. 使用 vite 构建一个表情选择插件

    初始化 Vite 基于原生 ES 模块提供了丰富的内建功能,开箱即用.同时,插件足够简单,它不需要任何运行时依赖,只需要安装 vite (用于开发与构建)和 sass (用于开发环境编译 .scss ...

  10. UBoot的编译与烧写

    每当我们学习任何编译语言之前,第一节课都是介绍我们要学习的是什么,以及编译语言和工具,最后写一个小程序编译并运行就算入门,也就是所谓的"Hello, world!".这里也不例外, ...