「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. 第一个 Angular 应用程序

    node download https://nodejs.org/zh-cn/ 全局安装 npm install @angular/cli -g 指定版本 npm install @angular/c ...

  2. 车载智能HUD

    车载智能HUD 从 HUD 到行车记录仪再到后视镜,最近有不少团队都发布了自己的车载智能硬件. 什么是 HUD? HUD 全称抬头数字显示仪 (Heads Up Display),又叫平视显示系统,简 ...

  3. NVIDIA安倍架构

    NVIDIA安倍架构 NVIDIA Ampere ArchitectureNVIDIA The Heart of the World's Highest-Performing, Elastic Dat ...

  4. CEVA引入新的可配置传感器集线器DSP架构

    CEVA引入新的可配置传感器集线器DSP架构 CEVA introduces new configurable sensor hub DSP architecture 在一个将多个传感器设计成几乎所有 ...

  5. C++标准模板库(STL)——vector常见用法详解

    vector的定义 vector<typename> name; 相当于定义了一个一维数组name[SIZE],只不过其长度可以根据需要进行变化,比较节省空间,通俗来讲,vector就是& ...

  6. Task03:复杂一点的查询

    之前接触了sql基本的查询用法,接下来介绍一些相对复杂的用法. 3.1 视图 我们先来看一个查询语句 SELECT stu_name FROM view_students_info; 单从表面上看起来 ...

  7. 【读书笔记】《C语言 从入门到精通》(第三版)笔记

    C语言,上学的时候都没学好,没想到现在却靠它吃饭.因为对C语言还是比较熟悉,所以买这本书是用来当"字典"用的.所以下面的笔记不会有很基础的内容. 1.书籍介绍 2.结构体 3.[C ...

  8. NOIP模拟测试25「字符串·乌鸦喝水·所陀门王的宝藏(陀螺王)」

    字符串 题解 没看出catalan怎么办 dp打表啊! 考虑大力dp拿到30分好成绩!顺便收获一张表 打表发现$C_{n+m}^{m}-C_{n+m}^{m-1}$ 仔细观察然后发现其实就是之前的网格 ...

  9. Room-数据持久化存储(入门)

    @ 目录 一.简单使用 1.Entity 2.Dao 3.DataBase 4.使用 二.参数解析 1.Entity 2.Dao 3.查询方式 总结 # 前言 官方简介: Room 持久性库在 SQL ...

  10. es6快速入门 系列 - async

    其他章节请看: es6 快速入门 系列 async 前文我们已经知道 promise 是一种异步编程的选择.而 async 是一种用于执行异步任务更简单的语法. Tip:建议学完 Promise 在看 ...