「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. .Net Core自实现CLR异步编程模式(Asynchronous programming patterns)

    最近在看一个线程框架,对.Net的异步编程模型很感兴趣,所以在这里实现CLR定义的异步编程模型,在CLR里有三种异步模式如下,如果不了解的可以详细看MSDN 文档Asynchronous progra ...

  2. (转)修改python默认排序方式

    在Java中,自定义类可以通过继承comparable接口,重写compareTo方法来使用内置sort()函数来对自定义对象排序,我就在想Python中有没有类似的操作. 首先随便写个自定义类,比如 ...

  3. CVPR2020论文解析:视觉算法加速

    CVPR2020论文解析:视觉算法加速 GPU-Accelerated Mobile Multi-view Style Transfer 论文链接:https://arxiv.org/pdf/2003 ...

  4. 硬件delay评估表

    硬件delay评估表 硬件延时评估表用于快速评估一个模型在特定硬件环境和推理引擎上的推理速度. Bw 主要用于定义PaddleSlim支持的硬件延时评估表的格式. 概述 硬件延时评估表中存放着所有可能 ...

  5. AlexeyAB DarkNet YOLOv3框架解析与应用实践(一)

    AlexeyAB DarkNet YOLOv3框架解析与应用实践(一) Darknet:  C语言中的开源神经网络 Darknet是一个用C和CUDA编写的开源神经网络框架.它速度快,易于安装,支持C ...

  6. CUDA 7 Stream流简化并发性

    CUDA 7 Stream流简化并发性 异构计算是指高效地使用系统中的所有处理器,包括 CPU 和 GPU .为此,应用程序必须在多个处理器上并发执行函数. CUDA 应用程序通过在 streams  ...

  7. TensorRT IRNNv2Layer

    TensorRT IRNNv2Layer IRNNv2Layer层实现递归层,如递归神经网络(RNN).门控递归单元(GRU)和长短期记忆(LSTM).支持的类型有RNN.GRU和LSTM.它执行一个 ...

  8. 【C++】map容器的用法

    检测map容器是否为空: 1 #include <iostream> 2 #include<map> 3 #include<string> 4 using name ...

  9. Git操作文档

    Git 操作文档 Git 是一个十分流行的版本控制系统,Git 和 SVN 区别在于,SVN使用增量文件系统,存储每次提交之间的差异.而 git 使用全量文件系统,存储每次提交的文件的全部内容(sna ...

  10. 终于明白为什么要加 final 关键字了

    在开发过程中,由于习惯的原因,我们可能对某种编程语言的一些特性习以为常,特别是只用一种语言作为日常开发的情况.但是当你使用超过一种语言进行开发的时候就会发现,虽然都是高级语言,但是它们之间很多特性都是 ...