热门标签 | 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



推荐阅读
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 在Kubernetes上部署JupyterHub的步骤和实验依赖
    本文介绍了在Kubernetes上部署JupyterHub的步骤和实验所需的依赖,包括安装Docker和K8s,使用kubeadm进行安装,以及更新下载的镜像等。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了指针的概念以及在函数调用时使用指针作为参数的情况。指针存放的是变量的地址,通过指针可以修改指针所指的变量的值。然而,如果想要修改指针的指向,就需要使用指针的引用。文章还通过一个简单的示例代码解释了指针的引用的使用方法,并思考了在修改指针的指向后,取指针的输出结果。 ... [详细]
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社区 版权所有