题目

初始有一个点 1,每次新加入点 \(2\sim n+1\),给这条边染上新的颜色,

并且一种颜色只能出现在一条路径上,使得每个点到根节点的路径上颜色种类数尽量少

每次询问输出每个点到根节点路径上颜色种类最大值

\(n\leq 10^6\)


分析

考虑到 \(x\) 只与其中一个子节点的边颜色相同,如果存在两个子节点的边颜色相同,

那么 \(x\) 到根节点就不能填这种颜色,反而不如 \(x\) 到根节点填这种颜色的颜色种类数

设 \(dp[x]\) 表示 \(x\) 的子树的结点到 \(x\) 的路径上颜色种类数的最大值。

那么选择其中一个子节点 \(dp\) 值最大的,设其为 \(fi[x]\),次大值为 \(se[x]\)

如果 \(x\) 连 \(fi[x]\) 所在的子节点,那么其它子节点的答案会加一,连其它节点 \(fi[x]+1\) 代价更大一定不优。

所以 \(dp[x]=\max\{fi[x],se[x]+1\}\),然后每次答案就是 \(fi[1]\),(\(dp[1]\) 默认有一个父亲不是真正的颜色种类)

如果还未更新,\(dp[x]=\max\{fi[x],se[x]+1\}\),那么 \(x\) 到根节点的路径也不会受影响,直接退出。

这样看似时间复杂度仍然是 \(O(n^2)\),其实不然,

考虑到一种染色就是轻重链剖分之后重链染同一种颜色,那么颜色种类数为 \(O(\log n)\)

这显然是上界,那么时间复杂度为 \(O(n\log n)\)

感觉这道题出得好妙啊,不仅用到了轻重链剖分的性质,还结合了树形dp。(dp可菜了QAQ


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=1000011;
int n,fa[N],fi[N],se[N],dp[N];
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int max(int a,int b){return a>b?a:b;}
int main(){
n=iut()+1,dp[1]=1;
for (int i=2;i<=n;++i){
fa[i]=iut(),dp[i]=1;
for (int x=i;fa[x];){
if (fi[fa[x]]<dp[x]) se[fa[x]]=fi[fa[x]],fi[fa[x]]=dp[x];
else if (se[fa[x]]<dp[x]) se[fa[x]]=dp[x];
int now=max(fi[fa[x]],se[fa[x]]+1);
if (dp[fa[x]]==now) break;
dp[fa[x]]=now,x=fa[x];
}
print(fi[1]),putchar(32);
}
return 0;
}

#树形dp,树链剖分#CF442D Adam and Tree的更多相关文章

  1. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  2. 6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

    LINK:Decompose 看起来很难 实际上也很难 考验选手的dp 树链剖分 矩阵乘法的能力. 容易列出dp方程 暴力dp 期望得分28. 对于链的情况 容易发现dp方程可以转矩阵乘法 然后利用线 ...

  3. BZOJ4712洪水——动态DP+树链剖分+线段树

    题目描述 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开了创造模式,然后飞到 山顶放了格水.于是小A面前出现了一个瀑布.作为平民的小A只好老实巴交地爬山堵水.那么 ...

  4. [2016北京集训试题7]thr-[树形dp+树链剖分+启发式合并]

    Description Solution 神仙操作orz. 首先看数据范围,显然不可能是O(n2)的.(即绝对不是枚举那么简单的),我们考虑dp. 定义f(x,k)为以x为根的子树中与x距离为k的节点 ...

  5. 【BZOJ3522】【BZOJ4543】【POI2014】Hotel 树形DP 长链剖分 启发式合并

    题目大意 ​ 给你一棵树,求有多少个组点满足\(x\neq y,x\neq z,y\neq z,dist_{x,y}=dist_{x,z}=dist_{y,z}\) ​ \(1\leq n\leq 1 ...

  6. 5210: 最大连通子块和 动态DP 树链剖分

    国际惯例的题面:这题......最大连通子块和显然可以DP,加上修改显然就是动态DP了......考虑正常情况下怎么DP:我们令a[i]表示选择i及i的子树中的一些点,最大连通子块和;b[i]表示在i ...

  7. (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。

    Problem Description   Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...

  8. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  9. 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp

    题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...

  10. 【bzoj4712】洪水 树链剖分+线段树维护树形动态dp

    题目描述 给出一棵树,点有点权.多次增加某个点的点权,并在某一棵子树中询问:选出若干个节点,使得每个叶子节点到根节点的路径上至少有一个节点被选择,求选出的点的点权和的最小值. 输入 输入文件第一行包含 ...

随机推荐

  1. win32 - 将控制台输出重定向到txt文本上

    这里需要两个app. parent.cpp #include <Windows.h> #include <stdio.h> int main() { SECURITY_ATTR ...

  2. pikachu php反序列化漏洞

    原理 php中serialize(),unserialize()这两个函数. 序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象: class S{ p ...

  3. Windows Docker Destop修改默认镜像文件位置

    0.首先关闭docker destop. 1.通过Everything或者资源管理器找到以.vhdx结尾的文件所在的位置,这些就是docker镜像路径 2.我的路径:C:\Users\Administ ...

  4. 谈谈在incubator-dolphinscheduler 中为啥不能及时看到python任务输出的print日志

    一.incubator-dolphinscheduler 中如何获取shell类型的节点或者python类型的节点任务的日志 1.在org.apache.dolphinscheduler.server ...

  5. ArrayList继承了AbstractList为何还要实现List接口

    ArrayList继承了AbstractList为何还要实现List接口? 相关的问题: Vector既然继承了AbstractList为啥还要实现List接口 HashMap继承了AbstractM ...

  6. Java 从键盘读入学生成绩 找出最高分 并输出学生等级成绩 * 成绩>=最高分-10 等级为’A‘ * 成绩>=最高分-20 等级为’B‘ * 成绩>=最高分-30 等级为'C' * 其余 等级为’D‘

    1 /* 2 * 从键盘读入学生成绩 找出最高分 并输出学生等级成绩 3 * 成绩>=最高分-10 等级为'A' 4 * 成绩>=最高分-20 等级为'B' 5 * 成绩>=最高分- ...

  7. Java 在三个数字中找出最大值

    1 int aa1 = 11000000; 2 int aa2 = 20000; 3 int aa3 = 6000; 4 5 //第一种 6 int max = (aa1 > aa2)? aa1 ...

  8. [学习笔记]在Linux中使用源码编译的方式安装Nginx

    ​准备工作 准备nginx源码包: http://nginx.org/en/download.html 准备相关的依赖包以及环境: gzip 模块需要 zlib 库  http://www.zlib. ...

  9. MindSpore自定义算子中的张量维度问题

    技术背景 在前面的几篇博客中,我们介绍了MindSpore框架下使用CUDA来定义本地算子的基本方法,以及配合反向传播函数的使用,这里主要探讨一下MindSpore框架对于CUDA本地算子的输入输出的 ...

  10. linux-debian-把用户加入root组

    使用vim进入 /etc/sudoers   打开这个文件(或者 vi)也行 修改数据: 敲击键盘上个的  i 就可以键入字符了, 在root = ALL(ALL:ALL) ALL  的下面敲击 用户 ...