LOJ 6192 城市网络(树上倍增)
LOJ #6192. 「美团 CodeM 复赛」城市网络(链接)
一棵以 $ 1 $ 号节点为根的树,每个点有一个权值,有 $ q $ 个询问,每次从 $ x $ 点开始往某个祖先 $ y $ 走,初始有权值 $ c $ ,如果路径上遇到更大的权值,那么 $ c $ 改为那个权值,问会修改多少次。数据范围: $ n\leq 2\times 10^5 $
$ solution: $
首先因为本题没有修改操作,所以可以离线维护。然后我们发现如果我们在 $ x $ 处节点被修改权值,那么问题从这个节点开始就等效于:从 $ x $ 节点以其本身权值为初始权值向根节点走。然后此题还有另一个突破口:每一个节点,若以当前节点权值为初始权值,它向根节点走第一个会被修改的节点是确定的!这是倍增的标志!!!
结合上面两个性质,我们可以想出一种做法:用倍增数组 $ f[200005][19] $ 维护祖辈里比他大的节点(第一个比他大的,第二个,第四个,八个........)。如果我们初始权值为 $ v $ ,那么我们只要找到第一个比他大的节点(这个也可以用倍增完成),然后我们在这个节点开始用倍增,因为数组里记录都是比当前节点大的节点,所以我们只需将数组里所有深度小于终点的节点数记录下来即可!
至于预处理,首先我们虚拟一个根节点的父亲,权值无限大。然后更新某个节点处置时,找到父辈里第一个比他大的节点,用这个节点更新当前节点即可。具体寻找时:我们要从父亲节点出发,因为数组里记录的是比他大的节点,我们只需要看看那个节点的权值是否大于当前节点,小于等于才跳,最后得到的节点的父亲即为所求!
$ code: $
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define db double
#define rg register int
using namespace std;
int n,q;
int top;
int a[400005]; //节点权值
int dp[400005]; //节点深度
int f[300005][19]; //树上倍增
// f数组存的是祖辈里比他大的节点(第一个比他大的,第二个,第四个,八个........)
struct su{
int to,next;
}b[800005];
int tou[400005]; //链式前向星
inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
if(sign)return -res; else return res;
}
inline int get(int x,int v){ //找到去根节点的路径上第一个比他大的
if(a[x]>v)return x; //x是他父亲
for(rg i=18;i>=0;--i){
if(a[f[x][i]]<=v)x=f[x][i]; //只有都小于等于他才向上跳,倍增套路
}x=f[x][0]; return x; //小于等于才跳,那么下一个就是第一个比他大的
}
inline void dfs(int i,int fa){
dp[i]=dp[fa]+1; //深度
rg x=get(fa,a[i]); f[i][0]=x; //当前节点还没有值,从父亲开始找
for(rg j=0;j<18;++j)
f[i][j+1]=f[f[i][j]][j]; //用第一个比他大的节点更新倍增信息
for(rg j=tou[i];j;j=b[j].next)
if(b[j].to!=fa)dfs(b[j].to,i);
}
inline int ask(int x,int y,int v){
for(rg i=18;i>=0;--i)
if(a[f[x][i]]<=v)x=f[x][i]; //和get函数差不多,找到第一个比他大的
if(a[x]<=v)x=f[x][0]; //有可能初始节点就比v大
if(dp[x]<dp[y])return 0; //说明没有比他大的
rg res=1;
for(rg i=18;i>=0;--i){
if(dp[f[x][i]]>=dp[y])res+=1<<i,x=f[x][i]; //按照深度一点一点逼近
}return res;
}
int main(){
n=qr(); q=qr();
for(rg i=1;i<=n;++i) a[i]=qr();
for(rg i=1;i<n;++i){
rg x=qr(),y=qr();
b[++top].to=y; b[top].next=tou[x]; tou[x]=top; //居然不开c++11
b[++top].to=x; b[top].next=tou[y]; tou[y]=top; // o(一︿一+)o
} a[0]=1e9; dfs(1,0); //根节点的父亲要赋最大!!!
for(rg i=1;i<=q;++i){
rg x=qr(),y=qr(),z=qr();
printf("%d\n",ask(x,y,z));
}
return 0;
}
LOJ 6192 城市网络(树上倍增)的更多相关文章
- LOJ #6192. 「美团 CodeM 复赛」城市网络 (树上倍增)
#6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB 时间限制:500 ms 标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接 ...
- LibreOJ #6192. 「美团 CodeM 复赛」城市网络
#6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: sqc 提交提交记录统计讨论测试数据 题目描 ...
- (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树
题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...
- 美团 CodeM 复赛」城市网络
美团 CodeM 复赛」城市网络 内存限制:64 MiB时间限制:500 ms标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接的连通图),首都为 11 ...
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
- 【bzoj4568】[Scoi2016]幸运数字 树上倍增+高斯消元动态维护线性基
题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游 ...
- luogu1081 开车旅行 树上倍增
题目大意 小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市i 的海拔高度为Hi,城市i 和城市j 之间的距离 ...
- 『保卫王国 树上倍增dp』
保卫王国 Description Z 国有n座城市,n - 1条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻扎军队.驻扎军队需 ...
- 最近公共祖先算法LCA笔记(树上倍增法)
Update: 2019.7.15更新 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了 ...
随机推荐
- webpack前置知识2(JavaScript项目初始化)
所有的JavaScript项目都是在终端输入npm init -y进行项目初始化,如果要自定义项目规则,去掉 -y 参数. vscode终端快捷键ctrl+` 初始化 运行上述命令后,项目内会新建一个 ...
- 十三、RF中对json的解析
A.需要安装的库 1.RequestsLibrary,安装命令:pip2 install requests 2.HttpLibrary,安装命令:pip2 install robotframework ...
- 转 实例具体解释DJANGO的 SELECT_RELATED 和 PREFETCH_RELATED 函数对 QUERYSET 查询的优化(二)
https://blog.csdn.net/cugbabybear/article/details/38342793 这是本系列的第二篇,内容是 prefetch_related() 函数的用途.实现 ...
- 【flask】项目集成Sentry收集线上错误日志
flask集成sentry分为4个步骤: 首先在sentry官网注册1个账号 然后创建1个新的项目,这里我选择的是flask,这会得到一些关于sdk的使用说明 接下来创建一个简单的flask项目使用s ...
- 阶段3 1.Mybatis_07.Mybatis的连接池及事务_6 mybatis中的事务原理和自动提交设置
在实际的开发中,建议使用连接池的形式. JNDI的资料 H:\BaiDu\黑马传智JavaEE57期 2019最新基础+就业+在职加薪\讲义+笔记+资料\主流框架\31.会员版(2.0)-就业课(2. ...
- 系统分析与设计HW6
1. 使用 UML State Model建模 建模对象: 参考 Asg_RH 文档, 对 Reservation/Order 对象建模. 建模要求: 参考练习不能提供足够信息帮助你对订单对象建模,请 ...
- 系统分析与设计HW2
简答题 1. 简述瀑布模型.增量模型.螺旋模型(含原型方法)的优缺点. 瀑布模型 优点: 定义了软件开发基本流程与活动. 为项目提供了按阶段划分的检查点. 当前一阶段完成后,只需关注后续阶段. 缺点: ...
- 【Linux 应用编程】基础知识
错误提示 Linux 提供的系统调用API,通常会在失败的时候返回 -1.如果想获取更多更详细的报错信息,需要借助全局变量 errno 和 perror 函数: #include <stdio. ...
- docker windows下挂载目录和文件
我们利用docker启动项目的时候不能直接修改容器中的内容,只能在 run 的时候挂载到本地目录或者文件来进行修改. 例子:(路径可以忽略斜杠和反斜杠,我这边使用windows的路径没有报错.do ...
- Failure to find com.oracle:ojdbc6:jar:11.2.0.1.0
报错原因:oracle的ojdbc.jar是收费的,maven的中央仓库是没有的,需要下载到本地,然后打包进maven仓库 1.下载ojdbc6-11.2.0.1.0.jar包 http://cent ...