「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. TVM量化小结手册

    TVM量化小结手册 文章目录 Offical References TVM quantization roadmap INT8 quantization proposal Quantization S ...

  2. 将TVM集成到PyTorch上

    将TVM集成到PyTorch上 随着TVM不断展示出对深度学习执行效率的改进,很明显PyTorch将从直接利用编译器堆栈中受益.PyTorch的主要宗旨是提供无缝且强大的集成,而这不会妨碍用户.为此, ...

  3. Spring Cloud系列(七):消息总线

    在上一篇中,当一个配置中心的客户端启动之后,它所引用的值就无法改变了,但是Spring Cloud 提供了一种手段去解决了这个问题--Spring Cloud Bus. 一.Spring Cloud ...

  4. iSCSI网络磁盘

    一.fdisk 划分 分区 [root@server0 ~]# lsblk [root@server0 ~]# fdisk /dev/vdb 三个主分区 , 分别2个G大小 两个逻辑分区 , 分别1个 ...

  5. 一文带你了解.Net互斥锁

    本文主要讲解.Net基于Threading.Mutex实现互斥锁 基础互斥锁实现 基础概念:和自旋锁一样,操作系统提供的互斥锁内部有一个数值表示锁是否已经被获取,不同的是当获取锁失败的时候,它不会反复 ...

  6. Redis 5种数据结构及对应使用场景

    本文案例收录在 https://github.com/chengxy-nds/Springboot-Notebook 也当过面试官,面试过不少应聘者,因为是我自己招人自己用,所以我不会看应聘者造火箭的 ...

  7. SpringBoot(1)-新手入门(详细教程+理解)

    前话:很多人刚学java没多久就开始学springboot,毕竟springboot屏蔽了很多框架的配置,导致搭建一个项目变得比以前简单很多.但建议还是先把基础的框架都熟悉一遍,再用springboo ...

  8. 【VBA】延时函数

    延时函数(单位秒),例如延时0.5秒 1 Sub 延时() 2 delay (0.5) 3 Debug.Print "延时0.5秒" 4 End Sub 5 6 Sub delay ...

  9. 学习响应式编程 Reactor (1) - 响应式编程

    响应式编程 命令式编程(Imperative Programing),是一种描述计算机所需做出的行为的编程范式.详细的命令机器怎么(How)去处理以达到想要的结果(What). 声明式编程(Decla ...

  10. LuatOS | 全新在线模拟器,随时随地发挥创意

    LuatOS --运行在嵌入式硬件的实时操作系统,开启全新物联网生态. 聚焦嵌入式应用生态,内置功能可支持绝大多数物联网应用场景.深度整合Lua语言,只需少量内存和Flash空间就能运行.不局限于合宙 ...