「BZOJ3545」「ONTAK2010」Peaks
「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的更多相关文章
- 【BZOJ3551】【BZOJ3545】 【ONTAK2010】 Peaks (kruskal重构树+主席树)
Description 在\(Bytemountains\)有\(~n~\)座山峰,每座山峰有他的高度\(~h_i~\). 有些山峰之间有双向道路相连,共\(~m~\)条路径,每条路径有一个困难值 ...
- 众安「尊享e生」果真牛的不可一世么?
近日,具有互联网基因的.亏损大户(成立三年基本没盈利,今年二季度末亏损近4亿,你能指望它多厉害?).财产险公司—众安推出“尊享e生”中高端医疗保险(财险公司经营中高端医疗真的很厉害?真的是中高端医疗险 ...
- XCActionBar 「Xcode 中的 Alfred」
下载地址:https://github.com/pdcgomes/XCActionBar 基本命令: (1)「command+shift+8」或者双击「command」键可以打开「动作输入框窗口」 ( ...
- Git 执行 「fork 出来的仓库」和「最新版本的原仓库」内容同步更新
当我们在 GitHub 上 fork 出一个仓库后,如果原仓库更新了,此时怎样才能保证我们 fork 出来的仓库和原仓库内容一致呢?我们一般关注的是仓库的 master(主干分支)的内容,通过以下步骤 ...
- 【翻译】西川善司的「实验做出的游戏图形」「GUILTY GEAR Xrd -SIGN-」中实现的「纯卡通动画的实时3D图形」的秘密,后篇
http://www.4gamer.net/games/216/G021678/20140714079/ 连载第2回的本回, Arc System Works开发的格斗游戏「GUILTY G ...
- 翻译「C++ Rvalue References Explained」C++右值引用详解 Part1:概述
本文系对「C++ Rvalue References Explained」 该文的翻译,原文作者:Thomas Becker. 该文较详细的解释了C++11右值引用的作用和出现的意义,也同时被Scot ...
- 「Windows MFC 」「Edit Control」 控件
「Windows MFC 」「Edit Control」 控件
- 苹果搜索广告后台大揭秘,最全最细致详解,手把手设置教程「后附官方视频」-b
WWDC2016 搜索广告分会视频和 PPT 发布了,ASO100 带开发者第一时间了解 Search Ads 后台设置(文末有原声视频). 首先介绍一下搜索广告的模式和竞价规则 广告模式为 CPT( ...
- 被「李笑来老师」拉黑之「JavaScript微博自动转发的脚本」
故事的背景如下图,李笑来 老师于10月19日在 知乎Live 开设 一小时建立终生受用的阅读操作系统 的讲座,他老人家看到大家伙报名踊跃,便在微博上发起了一个 猜数量赢取iPhone7 的活动. 因为 ...
随机推荐
- jenkins配置基于角色的项目权限管理设置步骤
jenkins配置基于角色的项目权限管理设置步骤 本文链接:https://blog.csdn.net/russ44/article/details/52276222 由于jenkins默认的权限管理 ...
- 201871030132-熊文婷 实验二 个人项目―《D{0-1}KP问题》项目报告
项目 内容 课程班级博客链接 https://edu.cnblogs.com/campus/xbsf/2018CST 这个作业要求链接 https://www.cnblogs.com/nwnu-dai ...
- C++标准模板库(STL)——set常见用法详解
set的定义 set<typename> name; typename可以是任何基本类型,如int.double.char.结构体等,也可以是STL标准容器,如vector.set.que ...
- Java SSM框架理论知识
一.Spring理论知识 1.Spring 在ssm中起什么作用? Spring:轻量级框架 作用:Bean工厂,用来管理Bean的生命周期和框架集成. 两大核心:1.IOC/DI(控制反转/依赖注入 ...
- OpenFeign远程调用原理
之前对OpenFeign 了解到只用在接口上面打个注解,然后就可以通过内部调用去调用远程地址.研究完Feign生成对象以及代理对象的作用过程之后发现这个过程用到了Spring的好多东西,在之后的过程中 ...
- Linux系统命令login的翻译
LOGIN(1) 用户命令 LOGIN(1)名称 login - ...
- Java算法面试题(史上最强、持续更新、吐血推荐)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- Spring事务管理详解
事务概念回顾 什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行. 事物的特性(ACID): 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用 ...
- Python进程和线程实例详解
前言 进程是什么? 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需 ...
- CVPR2021|一个高效的金字塔切分注意力模块PSA
前言: 前面分享了一篇<继SE,CBAM后的一种新的注意力机制Coordinate Attention>,其出发点在于SE只引入了通道注意力,CBAM的空间注意力只考虑了局部区域的信息 ...