请容许我不理解一下为什么这题题解几乎全都是指针实现/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\) 数组,对空间复杂度似乎没啥影响(?)

#include<bits/stdc++.h>
#define il inline
using namespace std;
il int read()
{
int xr=0,F=1; char cr=getchar();
while(cr<'0'||cr>'9') {if(cr=='-') F=-1;cr=getchar();}
while(cr>='0'&&cr<='9')
xr=(xr<<3)+(xr<<1)+(cr^48),cr=getchar();
return xr*F;
}
const int N=1e6+5;
int n;
struct edge{
int nxt,to;
}e[N<<1];
int head[N],cnt;
void add(int u,int v){
e[++cnt]={head[u],v};head[u]=cnt;
}
int dep[N],son[N],dfn[N],tot;
void dfs1(int now,int fa)
{
for(int i=head[now];i;i=e[i].nxt)
{
int v=e[i].to;if(v==fa) continue;
dfs1(v,now);
if(dep[v]>dep[son[now]]) son[now]=v;
}
dep[now]=dep[son[now]]+1;
}
int f[N],ans[N];
void dfs2(int now,int fa)
{
dfn[now]=++tot;
f[dfn[now]]=1;
if(son[now])
{
dfs2(son[now],now);
if(f[dfn[son[now]]+ans[son[now]]]>1) ans[now]=ans[son[now]]+1;
}
for(int i=head[now];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==son[now]||v==fa) continue;
dfs2(v,now);
for(int j=1;j<=dep[v];j++)
{
f[dfn[now]+j]+=f[dfn[v]+j-1];
if(f[dfn[now]+j]>f[dfn[now]+ans[now]]||
f[dfn[now]+j]==f[dfn[now]+ans[now]]&&j<ans[now]) ans[now]=j;
}
}
}
int main()
{
n=read();
for(int i=1;i<n;i++)
{
int u=read(),v=read();
add(u,v),add(v,u);
}
dfs1(1,0),dfs2(1,0);
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}

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. Prometheus-3:一文详解promQL

    读前提示: 本文字数较多且紧凑,最好预留15min一次性看完,好营养,易吸收. promQL详解 Prometheus提供了内置的数据查询语言PromQL(全称为Prometheus Query La ...

  2. 一文了解 io.LimitedReader类型

    1. 引言 io.LimitedReader 提供了一个有限的读取功能,能够手动设置最多从数据源最多读取的字节数.本文我们将从 io.LimitedReader 的基本定义出发,讲述其基本使用和实现原 ...

  3. Federated Learning002

    联邦学习笔记--002 2022.11.26周六 今天学习了联邦学习中又一篇很经典的论文--Federated Machine Learning: Concept and Applications(联 ...

  4. Raw数据相关概念

    什么是"RAW"? 维基百科的字面解释是:原始图像文件包含从数码相机.扫描器或电影胶片扫描仪的图像传感器所处理数据.RAW文件包含创建一个可视图像所必须的相机传感器数据信息. 通俗 ...

  5. uniapp开发H5,分享链接到微信好友,显示标题和缩略图

    本文档介绍了如何在UniApp开发中实现将链接分享到微信好友,并确保在分享时显示标题和缩略图的方法. 背景 第一次用uniapp开发H5页面,发现分享给微信好友的链接,不显示标题和缩略图 步骤一:安装 ...

  6. quarkus依赖注入之七:生命周期回调

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇的知识点是bean的生命周期回调:在be ...

  7. [golang]获取本机IP

    前言 方便在内网环境中获取服务器本机IP,省了在脚本中过滤ip或ifconfig的结果. 如果内网中有nginx的话,通过nginx获取本机IP也很方便,可参考 借助nginx自动获取本机IP 示例代 ...

  8. 理解linux的CPU上下文切换

    前言 linux是一个多任务操作系统,它支持远大于CPU数量的任务同时运行.当然,这个同时运行不是真的同时运行,而是系统在很短的时间内轮流分配CPU资源,由于CPU的速度很快,所以给人一种同时运行的错 ...

  9. BUUCTF Reverse-[FlareOn6]Overlong-动态调试

    没有什么问题,直接进 三个函数,字符串也没啥特殊的 应该是个加密 返回上面分析 数据很大,你忍一下 也就是说它会找28位加密 然后我们接着分析 这个提示刚好28位 也就是说28位对应这个框 如果我们修 ...

  10. 在Windows下用VScode构造shell脚本的IDE

    在linux系统中,大家可以很轻松的开发.调试shell脚本.但是,对于不熟悉linux系统 的小白或者想在Windows下开发shell脚本的人来说,这就有点不友好了.本篇文章就 教大家,在Wind ...