请容许我不理解一下为什么这题题解几乎全都是指针实现/kk

其实长链剖分是可以直接用数组来写的。

考虑朴素 DP。设 \(f_{u,i}\) 表示以点 \(u\) 为根的子树中与点 \(u\) 距离为 \(i\) 的点的个数。

则转移方程为:

\[f_{u,i}=\sum\limits_{v\in son_u} f_{v,i-1}
\]

答案为:

\[ans_u=\max\{f_{u,i}\}
\]

转移方程以深度为下标,可以使用长链剖分优化。

在重链剖分时,我们定义一个节点的重儿子为 \(siz\) 最大的儿子,而长链剖分时则是把能到达深度最深的点作为重儿子。

这样,每次我们先对于 \(u\) 的重儿子 DP,那么点 \(u\) 可以直接继承 \(son_u\) 的 DP 值,再暴力合并其它轻儿子。

对于每个点,只会在它所在长链的顶端被暴力合并一次,时间复杂度为 \(O(n)\)。

观察到 \(f_v\) 在继承过来的时候是需要向后错一位的,这导致我们需要用一些特殊方法来存储 DP 值。

这里提供一种数组实现的思路。

对于 DP 数组 \(f\),我们把 \(f_{u,i}\) 映射到下标 \(dfn_u+i\) 的位置上。由于每次我们先遍历 \(son_u\),那么得到 \(dfn_{son_u}=dfn_u+1\)。

也就是说,\(f_{v,0}\) 和 \(f_{u,1}\) 映射的位置相同,恰好向后错了一位。

由于需要保证空间复杂度 \(O(n)\),在每求完一个点的 DP 值后统计该点的答案。

这个写法只是把一个指针数组换成了 \(dfn\) 数组,对空间复杂度似乎没啥影响(?)

  1. #include<bits/stdc++.h>
  2. #define il inline
  3. using namespace std;
  4. il int read()
  5. {
  6. int xr=0,F=1; char cr=getchar();
  7. while(cr<'0'||cr>'9') {if(cr=='-') F=-1;cr=getchar();}
  8. while(cr>='0'&&cr<='9')
  9. xr=(xr<<3)+(xr<<1)+(cr^48),cr=getchar();
  10. return xr*F;
  11. }
  12. const int N=1e6+5;
  13. int n;
  14. struct edge{
  15. int nxt,to;
  16. }e[N<<1];
  17. int head[N],cnt;
  18. void add(int u,int v){
  19. e[++cnt]={head[u],v};head[u]=cnt;
  20. }
  21. int dep[N],son[N],dfn[N],tot;
  22. void dfs1(int now,int fa)
  23. {
  24. for(int i=head[now];i;i=e[i].nxt)
  25. {
  26. int v=e[i].to;if(v==fa) continue;
  27. dfs1(v,now);
  28. if(dep[v]>dep[son[now]]) son[now]=v;
  29. }
  30. dep[now]=dep[son[now]]+1;
  31. }
  32. int f[N],ans[N];
  33. void dfs2(int now,int fa)
  34. {
  35. dfn[now]=++tot;
  36. f[dfn[now]]=1;
  37. if(son[now])
  38. {
  39. dfs2(son[now],now);
  40. if(f[dfn[son[now]]+ans[son[now]]]>1) ans[now]=ans[son[now]]+1;
  41. }
  42. for(int i=head[now];i;i=e[i].nxt)
  43. {
  44. int v=e[i].to;
  45. if(v==son[now]||v==fa) continue;
  46. dfs2(v,now);
  47. for(int j=1;j<=dep[v];j++)
  48. {
  49. f[dfn[now]+j]+=f[dfn[v]+j-1];
  50. if(f[dfn[now]+j]>f[dfn[now]+ans[now]]||
  51. f[dfn[now]+j]==f[dfn[now]+ans[now]]&&j<ans[now]) ans[now]=j;
  52. }
  53. }
  54. }
  55. int main()
  56. {
  57. n=read();
  58. for(int i=1;i<n;i++)
  59. {
  60. int u=read(),v=read();
  61. add(u,v),add(v,u);
  62. }
  63. dfs1(1,0),dfs2(1,0);
  64. for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
  65. return 0;
  66. }

upd:感觉这么搞局限性还是很大。指针还是该学学的。/kk

关于长链剖分的数组实现 | CF1009F Dominant Indices的更多相关文章

  1. 【CF1009F】Dominant Indices(长链剖分)

    [CF1009F]Dominant Indices(长链剖分) 题面 洛谷 CF 翻译: 给定一棵\(n\)个点,以\(1\)号点为根的有根树. 对于每个点,回答在它子树中, 假设距离它为\(d\)的 ...

  2. BZOJ.3653.谈笑风生(长链剖分/线段树合并/树状数组)

    BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. ...

  3. 【CF1009F】Dominant Indices(长链剖分优化DP)

    点此看题面 大致题意: 设\(d(x,y)\)表示\(x\)子树内到\(x\)距离为\(y\)的点的个数,对于每个\(x\),求满足\(d(x,y)\)最大的最小的\(y\). 暴力\(DP\) 首先 ...

  4. CF1009F Dominant Indices——长链剖分优化DP

    原题链接 \(EDU\)出一道长链剖分优化\(dp\)裸题? 简化版题意 问你每个点的子树中与它距离为多少的点的数量最多,如果有多解,最小化距离 思路 方法1. 用\(dsu\ on\ tree\)做 ...

  5. (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机

    真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机

  6. 【CF1009F】 Dominant Indices (长链剖分+DP)

    题目链接 \(O(n^2)\)的\(DP\)很容易想,\(f[u][i]\)表示在\(u\)的子树中距离\(u\)为\(i\)的点的个数,则\(f[u][i]=\sum f[v][i-1]\) 长链剖 ...

  7. CF1009F Dominant Indices(树上DSU/长链剖分)

    题目大意: 就是给你一棵以1为根的树,询问每一个节点的子树内节点数最多的深度(相对于这个子树根而言)若有多解,输出最小的. 解题思路: 这道题用树链剖分,两种思路: 1.树上DSU 首先想一下最暴力的 ...

  8. CF1009F Dominant Indices 长链剖分

    题目传送门 https://codeforces.com/contest/1009/problem/F 题解 长链剖分的板子吧. 令 \(dp[x][i]\) 表示 \(x\) 的子树中的深度为 \( ...

  9. LOJ3053 十二省联考2019 希望 容斥、树形DP、长链剖分

    传送门 官方题解其实讲的挺清楚了,就是锅有点多-- 一些有启发性的部分分 L=N 一个经典(反正我是不会)的容斥:最后的答案=对于每个点能够以它作为集合点的方案数-对于每条边能够以其两个端点作为集合点 ...

  10. 2018牛客网暑假ACM多校训练赛(第七场)I Tree Subset Diameter 动态规划 长链剖分 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round7-I.html 题目传送门 -  https://www.n ...

随机推荐

  1. 支持typecho博客的黑白模式纪念日插件

    插件说明 一个可以在指定日期让你的网站变成黑白模式的纪念日插件,以此来缅怀那些逝去的生命.我使用typecho博客系统,handsome主体,该插件完美适配. 设置效果 插件开启前,页面为彩色: 效果 ...

  2. 如何将Maven项目快速改造成一个java web项目(方式二)

    原始的maven项目,使用IDEA打开后,目录结构如下所示 删除pom.xml文件,删除resource目录,将java目录下的代码放到项目根目录下, 将webapp目录放到项目根目录下.如下图所示 ...

  3. 关于win11没有gpedit.msc(本地组策略管理)的解决方案

    转载自 https://blog.csdn.net/Xingchen0101/article/details/128943201 在本地部署一个bat文件 里面粘贴以下文本 pushd "% ...

  4. linux内核编译基础知识储备 --- 过渡篇(四)

    文章目录 一. 一种makefile中定义函数的方式 二. makefile之if函数 三. MAKE变量 四. $(quiet) 4.1 quiet = 空 与 quiet=quiet_ 的区别 4 ...

  5. 【技术积累】Java中的常用类【一】

    Math类 Math类是Java中的一个数学工具类,提供了一系列常用的数学方法.下面是Math类的常用方法及其案例: abs() 返回一个数的绝对值. int num = -10; int absNu ...

  6. Selenium+2Captcha 自动化+验证码识别实战

    本文深入探讨了使用Selenium库进行网页自动化操作,并结合2Captcha服务实现ReCAPTCHA验证码的破解.内容涵盖Selenium的基础知识.验证码的分类.2Captcha服务的使用,以及 ...

  7. 【分享】如何才能简洁高效不失优雅的爆破ZIP文件?

    0x01 前言 在CTF比赛中,压缩包密码的爆破一直是一个热门话题.在这个过程中,简洁高效的方法是至关重要的.本文将介绍一些实用的技巧和工具,帮助您高效地爆破ZIP文件密码,而不失优雅.我们将探讨一些 ...

  8. quarkus数据库篇之四:本地缓存

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<quarkus数据库篇> ...

  9. [Lua][Love Engine] 打砖块游戏实现过程与知识点

    本文旨在根据LOVE2D官方文档和教程实现打砖块的游戏,记录部分实现过程和重要知识点 目标摧毁所有砖块 玩家控制球拍左右滑动反弹小球 小球摧毁砖块 小球保持在屏幕内 小球碰到屏幕底部,GAME OVE ...

  10. 开源Word文字替换小工具更新 增加文档页眉和页脚替换功能

    ITGeeker技术奇客发布的开源Word文字替换小工具更新到v1.0.1.0版本啦,现已支持Office Word文档页眉和页脚的替换. 同时ITGeeker技术奇客修复了v1.0.0.0版本因替换 ...