首页 > 其他分享 >【CF1009F Dominant Indices】(长链剖分)

【CF1009F Dominant Indices】(长链剖分)

时间:2023-03-17 11:11:44浏览次数:50  
标签:tmp 长链 Dominant int son dep ans Indices 节点

原题链接

题意

给定一棵以 \(1\) 为根,\(n\) 个节点的树。设 \(d(u,x)\) 为 \(u\) 子树中到 \(u\) 距离为 \(x\) 的节点数。

对于每个点,求一个最小的 \(k\),使得 \(d(u,k)\) 最大。

\(1 \leq n \leq 10^6\)。

思路

考虑朴素的 dp 转移,即:

\[d_{u,x}=\sum_{v \in son_u} d_{v,x-1} \]

时间复杂度为 \(O(n^2)\),利用线段树合并或树上启发式合并的方法可以优化到 \(O(n \log n)\),这里主要介绍一种长链剖分优化的方式。

长链剖分,即设定 \(u\) 的重儿子 \(v\) :满足子树 \(v\) 中存在深度最大的节点的儿子。那么对于每一个顶点节点,从它前往深度最深的节点的路径就是一条重链。

image

可以证明,这样划分满足任意一个节点到根节点的路径被不超过 \(O(\sqrt{n})\) 条重链覆盖。

回到本题中,对于一个节点 \(u\),注意到当它只有一个儿子 \(v\) 的时候,信息可以直接转移过来。考虑对状态定义进行优化,设 \(f_{u,x}\) 为,与 \(u\) 子树中最深的那个节点的深度差为 \(x\) 的节点个数。那么每次就可以直接继承重儿子的信息。

而对于其余的轻儿子,即其他重链的顶点节点,直接暴力枚举深度合并答案。由于每条重链最多只会被合并一次,所以时间复杂度为 \(O(n)\)

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e6+10;
vector<int>f[N];
int n,dep[N],son[N],ans[N],h[N],idx;
struct edge{int v,nex;}e[N<<1];
void add(int u,int v){e[++idx]=edge{v,h[u]};h[u]=idx;}
void dfs(int u,int fa)
{
	for(int i=h[u];i;i=e[i].nex)
	{
		int v=e[i].v;if(v==fa) continue;dfs(v,u);
		if(!son[u]||dep[v]>dep[son[u]]) son[u]=v,dep[u]=dep[v]+1;
	}
}
void solve(int u,int fa)
{
	if(!son[u]) return f[u].push_back(1),ans[u]=0,void();solve(son[u],u);
	swap(f[u],f[son[u]]),ans[u]=ans[son[u]];f[u].push_back(1);//vector swap为O(1) 
	if(f[u][ans[u]]==1) ans[u]=dep[u];//特判一条链的情况 
	for(int i=h[u];i;i=e[i].nex)
	{
		int v=e[i].v;if(v==fa||v==son[u]) continue;solve(v,u);
		for(int j=dep[v];j>=0;j--)
		{
			int tmp=dep[u]-(dep[v]-j+1);f[u][tmp]+=f[v][j];
			if(f[u][tmp]>f[u][ans[u]]||f[u][tmp]==f[u][ans[u]]&&tmp>ans[u]) ans[u]=tmp;
		}
	}
}
int main()
{
	scanf("%d",&n);for(int u,v,i=1;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);dfs(1,0);solve(1,0);
	for(int i=1;i<=n;i++) printf("%d\n",dep[i]-ans[i]);
	return 0;
}

标签:tmp,长链,Dominant,int,son,dep,ans,Indices,节点
From: https://www.cnblogs.com/ListenSnow/p/17225970.html

相关文章

  • 关于java对接物联网设备自定义协议的安全性,以及长链接场景下需要注意的事项
    目前从事于物联网行业。共享充电宝。负责通讯相关。当前设备在线量约50W台。记录一下走得弯路。方便大家借鉴。文笔不太好,希望大家轻喷。本文主要是从以下几个方......
  • 长链剖分优化
    概述长链剖分通过对DP状态的复用,有效地降低某些状态具备显著继承性的treedp(多为与当前子树深度有关的dp状态)的转移复杂度。也可以说这是把本质不同的dp状态......
  • 报错 Shape of passed values is (8, 51), indices imply (6, 51)
    在做concat操作的时候,出现了这样的错误:Shapeofpassedvaluesis(8,51),indicesimply(6,51)经过检查是因为数据前面使用过append,index是不一样的;在concat的时候是......
  • RuntimeError: Input, output and indices must be on the current device 问题
    RuntimeError:Input,outputandindicesmustbeonthecurrentdevice做项目时遇到这个问题明明就已经加了这条语句,使其运行在我设置好的设备上了。为何会报错呢?......
  • 长链剖分
    现在的情况是正在找一些比较轻量化的题单来写。长链剖分。我们知道树的链剖分有三个,重剖,长剖,还有一个不是很正统的实链剖分。重链剖分就是每次找子树最大的一个当做重儿......
  • 长链剖分
    概述长链剖分通过把树剖成尽量长的多个链,高效地解决...我也不知道解决啥(长剖优化DP的东西在DP优化那边)。毕竟这个东西,不具备启发式分裂的复杂度。不过其还是有一......
  • 关于长链剖分的数组实现 | CF1009F Dominant Indices
    请容许我不理解一下为什么这题题解几乎全都是指针实现/kk其实长链剖分是可以直接用数组来写的。考虑朴素DP。设\(f_{u,i}\)表示以点\(u\)为根的子树中与点\(u\)距......
  • BZOJ 3252 攻略(长链剖分模板 链的常用性质 贪心)
    BZOJ3252攻略​ 给定一棵带边权的树,选择k个叶子结点,使这些叶子结点与根节点相连,形成k条路径。输出被路径覆盖的所有边的边权和的最大值(同一条边若被重复覆盖只算一......
  • 【LGR125D】【JRKSJ R5】Concvssion(多项式,长链剖分)
    Sub1:\(a_i=(i+1)\bmodn\)即图只有一个环。设\(g_u\)表示原来\(u\)上有多少个点,\(f_u=u\)表示\(u\)的点权。那么对于某个\(k\in[1,n]\),\(ans_k=\sum_{u}g_uf_......
  • 【十二省联考2019】希望(容斥,换根DP,长链剖分,懒标记)
    暴力的想法是考虑钦定每个点作为到达点并统计贡献,但显然这样会算重。注意到会算重的到达点一定构成了一个连通块,这是一个很好的性质,方便了我们容斥:我们直接用点的贡献减去......