点此看题面

大致题意: 设\(d(x,y)\)表示\(x\)子树内到\(x\)距离为\(y\)的点的个数,对于每个\(x\),求满足\(d(x,y)\)最大的最小的\(y\)。

暴力\(DP\)

首先让我们来思考如何暴力\(DP\)。

这应该还是比较简单的吧。

直接设\(f_{x,i}\)表示在\(x\)的子树内,到\(x\)的距离为\(i\)的点的个数

则不难推出转移方程:

\[f_{x,0}=1,f_{x,i}=\sum f_{son_x,i-1}
\]

但这样显然跑不过,要优化。

长链剖分

这是一道长链剖分优化\(DP\)的典型例题。

设\(len_x\)为\(x\)到叶节点的最长距离,则不难发现转移方程第二维\(i\)显然不可能超过\(len_x\)。

考虑使用指针(虽然我很不喜欢指针,但貌似这里必须用\(2333\)),对于每条长链顶点给它开一个长度为\(len_x\)的内存供它存储。

然后,对于每条长链的第\(i\)个元素\(t_i\),我们就用第\(i\)个位置作为\(f_{t_i,0}\)。

这样的好处就在于,对于一条长链,我们是可以直接让父节点从子节点那里继承答案的!

是不是非常神奇?

而对于非长儿子,我们暴力合并两条链。

由于每条链只会被合并一次,因此复杂度就达到了无比优秀的\(O(n)\)!

是不是很神奇?

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n,ee,lnk[N+5];struct edge {int to,nxt;}e[N<<1];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
#undef D
}F;
class LongChainDissection//长链剖分优化DP
{
private:
#define Assign(x) (f[x]=p,p+=len[x])//分配内存
#define F5(x,v) ((f[x][ans[x]]<f[x][v]||(f[x][ans[x]]==f[x][v]&&ans[x]>v))&&(ans[x]=v))//更新答案
int son[N+5],len[N+5],ans[N+5],*p,*f[N+5],_f[N+5];
I void dfs(CI x,CI lst)//DFS预处理长儿子与len数组
{
for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&
(dfs(e[i].to,x),len[e[i].to]>len[son[x]]&&(son[x]=e[i].to));
len[x]=len[son[x]]+1;
}
I void DP(CI x,CI lst)//DP
{
RI i,j;son[x]&&(f[son[x]]=f[x]+1,DP(son[x],x),ans[x]=ans[son[x]]+1);//优先处理长儿子,并继承答案
for(i=lnk[x];i;i=e[i].nxt) if(e[i].to^lst&&e[i].to^son[x])//枚举非长儿子
for(Assign(e[i].to),DP(e[i].to,x),j=1;j<=len[e[i].to];++j)//暴力合并
f[x][j]+=f[e[i].to][j-1],F5(x,j);f[x][0]=1,F5(x,0);
}
public:
I LongChainDissection() {p=_f;}I void Init() {dfs(1,0);}//初始化
I void Solve() {Assign(1),DP(1,0);for(RI i=1;i<=n;++i) F.writeln(ans[i]);}//DP并输出答案
}D;
int main()
{
RI i,x,y;for(F.read(n),i=1;i^n;++i) F.read(x,y),add(x,y),add(y,x);//读入+建边
return D.Init(),D.Solve(),F.clear(),0;//求解
}

【CF1009F】Dominant Indices(长链剖分优化DP)的更多相关文章

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

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

  2. CF1009F Dominant Indices 长链剖分

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

  3. 2019.01.19 bzoj3653: 谈笑风生(长链剖分优化dp)

    传送门 长链剖分优化dpdpdp水题. 题意简述:给一棵树,mmm次询问,每次给一个点aaa和一个值kkk,询问满足如下条件的三元组(a,b,c)(a,b,c)(a,b,c)的个数. a,b是c的祖先 ...

  4. 长链剖分优化dp三例题

    首先,重链剖分我们有所认识,在dsu on tree和数据结构维护链时我们都用过他的性质. 在这里,我们要介绍一种新的剖分方式,我们求出这个点到子树中的最长链长,这个链长最终从哪个儿子更新而来,那个儿 ...

  5. Codeforces 1009 F. Dominant Indices(长链剖分/树上启发式合并)

    F. Dominant Indices 题意: 给一颗无向树,根为1.对于每个节点,求其子树中,哪个距离下的节点数量最多.数量相同时,取较小的那个距离. 题目: 这类题一般的做法是树上的启发式合并,复 ...

  6. CF 1009 F Dominant Indices —— 长链剖分+指针

    题目:http://codeforces.com/contest/1009/problem/F 也可以用 dsu on tree 的做法,全局记录一个 dep,然后放进堆里,因为字典序要最小,所以再记 ...

  7. 2018.11.03 NOIP模拟 树(长链剖分优化dp)

    传送门 考虑直接推式子不用优化怎么做. 显然每一个二进制位分开计算贡献就行. 即记录fi,jf_{i,j}fi,j​表示距离iii这个点不超过jjj的点的每个二进制位的0/10/10/1个数. 但直接 ...

  8. BZOJ4543[POI2014]Hotel加强版——长链剖分+树形DP

    题意参见BZOJ3522 n<=100000 数据范围增强了,显然之前的转移方程不行了,那么不妨换一种. 因为不能枚举根来换根DP,那么我们描述的DP方程每个点要计算三个点都在这个点的子树内的方 ...

  9. 长链剖分优化树形DP总结

    长链剖分 规定若\(x\)为叶结点,则\(len[x]=1\). 否则定义\(preferredchild[x]\)(以下简称\(pc[x]\),称\(pc[x]\)为\(x\)的长儿子)为\(x\) ...

随机推荐

  1. Python 时间格式转换

    Python time, datetime模块常用方法 1.使用time模块,获取当前时间戳~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~import timetime.time( ...

  2. DB Intro - MongoDB User

    MongoDB 3.0 用户创建   摘要: MongoDB 3.0 安全权限访问控制,在添加用户上面3.0版本和之前的版本有很大的区别,这里就说明下3.0的添加用户的方法. 环境.测试: 在安装Mo ...

  3. (转)PowerHA完全手册(一,二,三)

    PowerHA完全手册(一) 原文:http://www.talkwithtrend.com/Article/39889-----PowerHA完全手册(一) http://www.talkwitht ...

  4. 阿冰教你一步一步做Android新闻客户端(二)两种异步线程加载图片的方法

    哈哈哈抱着没人看的心态随便写,直接上代码,各位看官看注释 一种Thread  一种AsyncTask 先不说用框架 public class ImageLoader { private ImageVi ...

  5. 【python爬虫】利用selenium和Chrome浏览器进行自动化网页搜索与浏览

    功能简介:利用利用selenium和Chrome浏览器,让其自动打开百度页面,并设置为每页显示50条,接着在百度的搜索框中输入selenium,进行查询.然后再打开的页面中选中“Selenium - ...

  6. 九度oj题目1027:欧拉回路

    题目1027:欧拉回路 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2844 解决:1432 题目描述:     欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条 ...

  7. 获取memcache中所有数据

    remap_table方法是用的一个框架写的: $gvs = $this->pageObj->get;是获取通过get方式传递过来的数据: $mem = $this->pageObj ...

  8. C# ADO.NET面向对象想法

    我认为的面向对象就是把各种问题拆分开来 逐一解决,  我想的是先是数据库,到底有什么, 然后新建一个类,类里面先是private的私有的,但是可以有无数个可以连接private的pubilc的属性 可 ...

  9. MySQL出现时区错误的解决方法

    目录 环境 问题 分析 解决方法 环境 windows10 MySQL 8.0.13 IDEA 问题 The server time zone value 'Öйú±ê׼ʱ¼ä' is unre ...

  10. Java操作Mongodb(转载)

    好文章,值得收藏 HelloWorld程序 学习任何程序的第一步,都是编写HelloWorld程序,我们也不例外,看下如何通过Java编写一个HelloWorld的程序. 首先,要通过Java操作Mo ...