热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【题解】LuoguP1600天天爱跑步LCA+树上差分

真NOIpday1T2众所周知noip按难度顺序出题感谢洛谷题解greenlcat提供思路及写法写调写题解共计一整个晚上2.5个小时对我今天晚自习啥都没干分步解决这个题Step1:

真·NOIp day1 T2

众所周知noip按难度顺序出题

感谢洛谷题解@greenlcat 提供思路及写法

写+调+写题解 共计一整个晚上2.5个小时对我今天晚自习啥都没干

分步解决这个题

Step 1 :倍增LCA

本身这题码量就不小,还写树剖LCA,我这个菜鸡调不出来的

倍增求LCA好像没什么可写的,基本操作

1 int n,m,cnt,deep[maxn],fa[maxn][25],w[maxn],head[maxn];
2 struct edge{
3 int nxt,to;
4 }e[maxn*2];
5 inline void add(int from,int to){
6 e[++cnt].to=to;e[cnt].nxt=head[from];head[from]=cnt;
7 }
8 void dfs1(int x){
9 for(int i&#61;1;(1<){
10 fa[x][i]&#61;fa[fa[x][i-1]][i-1];
11 }
12 for(int i&#61;head[x];i;i&#61;e[i].nxt){
13 int y&#61;e[i].to;
14 if(y&#61;&#61;fa[x][0])continue;
15 fa[y][0]&#61;x;
16 deep[y]&#61;deep[x]&#43;1;
17 dfs1(y);
18 }
19 }
20 int lca(int x,int y){
21 if(x&#61;&#61;y)return x;
22 if(deep[x]<deep[y])swap(x,y);
23 int k&#61;log(deep[x]-deep[y])/log(2);
24 for(int i&#61;k;i>&#61;0;i--){
25 if(deep[fa[x][i]]>&#61;deep[y]){
26 x&#61;fa[x][i];
27 }
28 if(x&#61;&#61;y)return x;
29 }
30 k&#61;log(deep[x])/log(2);
31 for(int i&#61;k;i>&#61;0;i--){
32 if(fa[x][i]!&#61;fa[y][i]){
33 x&#61;fa[x][i];y&#61;fa[y][i];
34 }
35 }
36 return fa[x][0];
37 }
38 int main(){
39 n&#61;read();m&#61;read();
40 for(int i&#61;1;i){
41 int u,v;u&#61;read();v&#61;read();
42 add(u,v);add(v,u);
43 }
44 deep[1]&#61;1;fa[1][0]&#61;1;dfs1(1);
45 for(int i&#61;1;i<&#61;n;i&#43;&#43;){
46 w[i]&#61;read();
47 }
48 return 0;
49 }

part one

 

Step 2 :分析转化

发现模拟每个玩家的复杂度爆炸&#xff0c;分着不行就考虑整体处理

改为枚举每个观察员&#xff0c;看哪些节点对观察员有贡献&#xff08;可被观察到&#xff09;

而枚举观察员可以转化成dfs整棵树&#xff0c;O(n)可以接受

考虑对于一个观察员x&#xff0c;如果他在一条$s_i$到$t_i$的路径上

1.如果x在$s_i$到LCA上

当$s_i$满足$deep[{s_i}]&#61;w[x]&#43;deep[x]$时&#xff0c;$s_i$对x有1的贡献

2.如果x在$t_i$到LCA上

当$t_i$满足$dis[{s_i},{t_i}]-deep[{t_i}]&#61;w[x]-deep[x]$时&#xff0c;$t_i$对x有1的贡献

所以我们发现&#xff0c;能够对x有贡献的$s_i$或$t_i$都在以x为根的子树上

 

Step 3 :统计贡献

code&#xff08;注释都在代码里了&#xff09;

1 struct edge{
2 int nxt,to;
3 }e1[maxn*2],e2[maxn*2];
4 inline void add1(int from,int to){
5 e1[&#43;&#43;cnt1].to&#61;to;e1[cnt1].nxt&#61;h1[from];h1[from]&#61;cnt1;
6 }
7 inline void add2(int from,int to){
8 e2[&#43;&#43;cnt2].to&#61;to;e2[cnt2].nxt&#61;h2[from];h2[from]&#61;cnt2;
9 }
10 int b1[maxn*2],b2[maxn*2],js[maxn],dis[maxn];
11 int s[maxn],l[maxn],t[maxn],ans[maxn];
12 void dfs2(int x){
13 int t1&#61;b1[w[x]&#43;deep[x]],t2&#61;b2[w[x]-deep[x]&#43;maxn];
14 //递归前先读桶里的数值&#xff0c;t1是上行桶里的值&#xff0c;t2是下行桶的值
15 for(int i&#61;head[x];i;i&#61;e[i].nxt){ //递归子树
16 int y&#61;e[i].to;
17 if(y&#61;&#61;fa[x][0])continue;
18 dfs2(y);
19 }
20 b1[deep[x]]&#43;&#61;js[x];
21 //上行过程中&#xff0c;当前点作为路径起点产生贡献&#xff0c;入桶
22 for(int i&#61;h1[x];i;i&#61;e1[i].nxt){
23 //下行过程中&#xff0c;当前点作为路径终点产生贡献&#xff0c;入桶
24 int y&#61;e1[i].to;
25 b2[dis[y]-deep[t[y]]&#43;maxn]&#43;&#43;;
26 }
27 ans[x]&#43;&#61;b1[w[x]&#43;deep[x]]-t1&#43;b2[w[x]-deep[x]&#43;maxn]-t2;
28 //计算上、下行桶内差值&#xff0c;累加到ans[x]里面
29 for(int i&#61;h2[x];i;i&#61;e2[i].nxt){
30 //回溯前清除以此结点为LCA的起点和终点在桶内产生的贡献&#xff0c;它们已经无效了
31 int y&#61;e2[i].to;
32 b1[deep[s[y]]]--;
33 b2[dis[y]-deep[t[y]]&#43;maxn]--;
34 }
35 }
36 int main(){
37 for(int i&#61;1;i<&#61;m;i&#43;&#43;){
38 s[i]&#61;read();t[i]&#61;read();
39 int lcaa&#61;lca(s[i],t[i]); //求LCA
40 dis[i]&#61;deep[s[i]]&#43;deep[t[i]]-2*deep[lcaa];
41 js[s[i]]&#43;&#43;;//统计以s[i]为起点路径的条数
42 add1(t[i],i);//第i条路径加入到以t[i]为终点的路径集合中
43 add2(lcaa,i);//把每条路径归到对应的LCA集合中
44 if(deep[lcaa]&#43;w[lcaa]&#61;&#61;deep[s[i]]){
45 //如果路径起点或终点刚好为LCA且LCA处是可观察到运动员的,答案--
46 ans[lcaa]--;
47 }
48 }
49 dfs2(1);
50 for(int i&#61;1;i<&#61;n;i&#43;&#43;){
51 printf("%lld ",ans[i]);
52 }
53 return 0;
54 }

part two

 

完整高清无注释code

1 #include
2 using namespace std;
3 namespace gengyf{
4 #define ll long long
5 #define int long long
6 const int maxn&#61;3e5&#43;10;
7 inline int read(){
8 int x&#61;0,f&#61;1;
9 char c&#61;getchar();
10 while(c<&#39;0&#39;||c>&#39;9&#39;){if(c&#61;&#61;&#39;-&#39;)f&#61;-1;c&#61;getchar();}
11 while(c>&#61;&#39;0&#39;&&c<&#61;&#39;9&#39;){x&#61;(x*10)&#43;c-&#39;0&#39;;c&#61;getchar();}
12 return x*f;
13 }
14 int n,m,cnt,deep[maxn],fa[maxn][25],w[maxn],head[maxn];
15 int h1[maxn],h2[maxn],cnt1,cnt2;
16 struct edge{
17 int nxt,to;
18 }e[maxn*2],e1[maxn*2],e2[maxn*2];
19 inline void add(int from,int to){
20 e[&#43;&#43;cnt].to&#61;to;e[cnt].nxt&#61;head[from];head[from]&#61;cnt;
21 }
22 inline void add1(int from,int to){
23 e1[&#43;&#43;cnt1].to&#61;to;e1[cnt1].nxt&#61;h1[from];h1[from]&#61;cnt1;
24 }
25 inline void add2(int from,int to){
26 e2[&#43;&#43;cnt2].to&#61;to;e2[cnt2].nxt&#61;h2[from];h2[from]&#61;cnt2;
27 }
28 void dfs1(int x){
29 for(int i&#61;1;(1<){
30 fa[x][i]&#61;fa[fa[x][i-1]][i-1];
31 }
32 for(int i&#61;head[x];i;i&#61;e[i].nxt){
33 int y&#61;e[i].to;
34 if(y&#61;&#61;fa[x][0])continue;
35 fa[y][0]&#61;x;
36 deep[y]&#61;deep[x]&#43;1;
37 dfs1(y);
38 }
39 }
40 int lca(int x,int y){
41 if(x&#61;&#61;y)return x;
42 if(deep[x]<deep[y])swap(x,y);
43 int k&#61;log(deep[x]-deep[y])/log(2);
44 for(int i&#61;k;i>&#61;0;i--){
45 if(deep[fa[x][i]]>&#61;deep[y]){
46 x&#61;fa[x][i];
47 }
48 if(x&#61;&#61;y)return x;
49 }
50 k&#61;log(deep[x])/log(2);
51 for(int i&#61;k;i>&#61;0;i--){
52 if(fa[x][i]!&#61;fa[y][i]){
53 x&#61;fa[x][i];y&#61;fa[y][i];
54 }
55 }
56 return fa[x][0];
57 }
58 int b1[maxn*2],b2[maxn*2],js[maxn],dis[maxn];
59 int s[maxn],l[maxn],t[maxn],ans[maxn];
60 void dfs2(int x){
61 int t1&#61;b1[w[x]&#43;deep[x]],t2&#61;b2[w[x]-deep[x]&#43;maxn];
62 for(int i&#61;head[x];i;i&#61;e[i].nxt){
63 int y&#61;e[i].to;
64 if(y&#61;&#61;fa[x][0])continue;
65 dfs2(y);
66 }
67 b1[deep[x]]&#43;&#61;js[x];
68 for(int i&#61;h1[x];i;i&#61;e1[i].nxt){
69 int y&#61;e1[i].to;
70 b2[dis[y]-deep[t[y]]&#43;maxn]&#43;&#43;;
71 }
72 ans[x]&#43;&#61;b1[w[x]&#43;deep[x]]-t1&#43;b2[w[x]-deep[x]&#43;maxn]-t2;
73 for(int i&#61;h2[x];i;i&#61;e2[i].nxt){
74 int y&#61;e2[i].to;
75 b1[deep[s[y]]]--;
76 b2[dis[y]-deep[t[y]]&#43;maxn]--;
77 }
78 }
79 int main(){
80 n&#61;read();m&#61;read();
81 for(int i&#61;1;i){
82 int u,v;u&#61;read();v&#61;read();
83 add(u,v);add(v,u);
84 }
85 deep[1]&#61;1;fa[1][0]&#61;1;dfs1(1);
86 for(int i&#61;1;i<&#61;n;i&#43;&#43;){
87 w[i]&#61;read();
88 }
89 for(int i&#61;1;i<&#61;m;i&#43;&#43;){
90 s[i]&#61;read();t[i]&#61;read();
91 int lcaa&#61;lca(s[i],t[i]);
92 dis[i]&#61;deep[s[i]]&#43;deep[t[i]]-2*deep[lcaa];
93 js[s[i]]&#43;&#43;;
94 add1(t[i],i);add2(lcaa,i);
95 if(deep[lcaa]&#43;w[lcaa]&#61;&#61;deep[s[i]]){
96 ans[lcaa]--;
97 }
98 }
99 dfs2(1);
100 for(int i&#61;1;i<&#61;n;i&#43;&#43;){
101 printf("%lld ",ans[i]);
102 }
103 return 0;
104 }
105 }
106 signed main(){
107 gengyf::main();
108 return 0;
109 }

View Code

 

完结撒花花

转:https://www.cnblogs.com/gengyf/p/11600205.html



推荐阅读
  • 题目《BZOJ2654: Tree》的时间限制为30秒,内存限制为512MB。该问题通过结合二分查找和Kruskal算法,提供了一种高效的优化解决方案。具体而言,利用二分查找缩小解的范围,再通过Kruskal算法构建最小生成树,从而在复杂度上实现了显著的优化。此方法不仅提高了算法的效率,还确保了在大规模数据集上的稳定性能。 ... [详细]
  • 三角测量计算三维坐标的代码_双目三维重建——层次化重建思考
    双目三维重建——层次化重建思考FesianXu2020.7.22atANTFINANCIALintern前言本文是笔者阅读[1]第10章内容的笔记,本文从宏观的角度阐 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • 本文介绍了几种常用的图像相似度对比方法,包括直方图方法、图像模板匹配、PSNR峰值信噪比、SSIM结构相似性和感知哈希算法。每种方法都有其优缺点,适用于不同的应用场景。 ... [详细]
  • 本文介绍如何使用线段树解决洛谷 P1531 我讨厌它问题,重点在于单点更新和区间查询最大值。 ... [详细]
  • 最详尽的4K技术科普
    什么是4K?4K是一个分辨率的范畴,即40962160的像素分辨率,一般用于专业设备居多,目前家庭用的设备,如 ... [详细]
  • 本文详细介绍了如何在Unity中实现一个简单的广告牌着色器,帮助开发者更好地理解和应用这一技术。 ... [详细]
  • 命令模式是一种行为设计模式,它将请求封装成一个独立的对象,从而允许你参数化不同的请求、队列请求或者记录请求日志。本文将详细介绍命令模式的基本概念、组件及其在实际场景中的应用。 ... [详细]
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 利用python爬取豆瓣电影Top250的相关信息,包括电影详情链接,图片链接,影片中文名,影片外国名,评分,评价数,概况,导演,主演,年份,地区,类别这12项内容,然后将爬取的信息写入Exce ... [详细]
  • 微软推出Windows Terminal Preview v0.10
    微软近期发布了Windows Terminal Preview v0.10,用户可以在微软商店或GitHub上获取这一更新。该版本在2月份发布的v0.9基础上,新增了鼠标输入和复制Pane等功能。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在Delphi7下要制作系统托盘,只能制作一个比较简单的系统托盘,因为ShellAPI文件定义的TNotifyIconData结构体是比较早的版本。定义如下:1234 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 文章目录Golang定时器Timer和Tickertime.Timertime.NewTimer()实例time.AfterFunctime.Tickertime.NewTicke ... [详细]
author-avatar
逆夏_Pretty
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有