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 城市网络(树上倍增)的更多相关文章

  1. LOJ #6192. 「美团 CodeM 复赛」城市网络 (树上倍增)

    #6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB 时间限制:500 ms 标准输入输出   题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接 ...

  2. LibreOJ #6192. 「美团 CodeM 复赛」城市网络

    #6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: sqc 提交提交记录统计讨论测试数据   题目描 ...

  3. (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树

    题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...

  4. 美团 CodeM 复赛」城市网络

    美团 CodeM 复赛」城市网络 内存限制:64 MiB时间限制:500 ms标准输入输出 题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接的连通图),首都为 11 ...

  5. NOIP2013 货车运输 (最大生成树+树上倍增LCA)

    死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...

  6. 【bzoj4568】[Scoi2016]幸运数字 树上倍增+高斯消元动态维护线性基

    题目描述 A 国共有 n 座城市,这些城市由 n-1 条道路相连,使得任意两座城市可以互达,且路径唯一.每座城市都有一个幸运数字,以纪念碑的形式矗立在这座城市的正中心,作为城市的象征.一些旅行者希望游 ...

  7. luogu1081 开车旅行 树上倍增

    题目大意 小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市i 的海拔高度为Hi,城市i 和城市j 之间的距离 ...

  8. 『保卫王国 树上倍增dp』

    保卫王国 Description Z 国有n座城市,n - 1条双向道路,每条双向道路连接两座城市,且任意两座城市 都能通过若干条道路相互到达. Z 国的国防部长小 Z 要在城市中驻扎军队.驻扎军队需 ...

  9. 最近公共祖先算法LCA笔记(树上倍增法)

    Update: 2019.7.15更新 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了 ...

随机推荐

  1. Linux清空文本内容

    测试文件:test.txt 第一种: $> test.txt 第二种: $echo "" > test.txt 第三种: $cat /dev/null > tes ...

  2. Oracle数据库用户的密码过期问题处理

    SQL> select username, user_id, account_status,expiry_date, profile from dba_users where username ...

  3. JQuery插件 aos.js

    简介: aos.js是一款效果超赞的页面滚动元素动画jQuery动画库插件.该动画库可以在页面滚动时提供28种不同的元素动画效果,以及多种easing效果.在页面往回滚动时,元素会恢复到原来的状态. ...

  4. db4o这个对象数据库有很多优点,但为什么不是很火? 大家有没有用过db4o的?

    没有主键的概念(因为对象的内存地址,或者引用就能标志一个对象了).因而外界想指向一个具体的对象就比较困难(比如本页的url里的1079505). 激活/保存层次的问题.获取一个对象,它的字段引用了其它 ...

  5. JVM监控工具之JProfiler

    一.简介 JProfiler是一款Java的性能监控工具.可以查看当前应用的对象.对象引用.内存.CPU使用情况,线程运行情况(阻塞.等待等),同时可以查找哪个对象占用的内存比较多.哪个对象占用CPU ...

  6. Chrome 浏览器添加跨域支持

    开发前端本地项目时,涉及到与后端服务器的通信联调,在使用 ajax 时由于浏览器的安全策略不允许跨域.一种方式是本地搭建转发服务器,今天又 GET 到一种更直接的方式,在 Chrome 浏览器开启时添 ...

  7. jenkins中通过Publish Over SSH将项目部署到远程机器上

    Publish Over SSH插件使用在使用Publish Over SSH之前,需要制作SSH私钥.机器间做免密登录配置.假设机器A,ip为192.168.AA.AAA,机器B: 192.168. ...

  8. nginx+memcached缓存图片

    1.nginx的配置如下: location ^~ /images/ {     set $memcached_key  "$uri"; #用URI作为key去memcached中 ...

  9. Python3 字符编码到底是个什么鬼

    首先ASCII码是美国人自己给自己用的,只针对英文及一系列符号,凭想象预留了编码位置,不料有个东方大国文字过于复杂,预留根本不够,所以这个大国重新搞了个编码gb2312.gbk等,结果就是全世界各国都 ...

  10. netcore 使用redis session 分布式共享

    首先准备redis服务器(docker 和redis3.0内置的哨兵进行高可用设置) 网站配置Redis作为存储session的介质(配置文件这些略).然后可以了解一下MachineKey这个东西.( ...