美团2017年CodeM大赛-初赛B轮 黑白树 (树形dp)

大意: 给定树, 初始每个点全为白色, 点$i$有权值$k_i$, 表示选择$i$后, 所有距离$i$小于$k_i$的祖先(包括i)会变为黑色, 求最少选多少个点能使所有点变为黑色.

链上情况的话, 直接从链头开始做一次线性dp就行了, 但是显然不能拓展到树上情况.

正解是从叶子往上贪心划分, 若当前点$x$为白色, 则从$x$子树内选择一个$y$, 满足$k[y]-dis(x,y)$最大, 这个显然可以用树形dp在O(n)时间求出.

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, P2 = 998244353, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int rd() {int x=0;char p=getchar();while(p<‘0‘||p>‘9‘)p=getchar();while(p>=‘0‘&&p<=‘9‘)x=x*10+p-‘0‘,p=getchar();return x;}
//head

const int N = 1e6+10;
int n, ans, fa[N], k[N];
vector<int> g[N];

int dfs(int x) {
	int d = 0;
	for (int y:g[x]) d=max(d,dfs(y));
	k[fa[x]] = max(k[fa[x]], k[x]-1);
	if (d>0) return d-1;
	return ++ans, k[x]-1;
}

int main() {
	scanf("%d", &n);
	REP(i,2,n) {
		scanf("%d", fa+i);
		g[fa[i]].pb(i);
	}
	REP(i,1,n) scanf("%d", k+i);
	dfs(1);
	printf("%d\n", ans);
}

原文地址:https://www.cnblogs.com/uid001/p/10925278.html

时间: 2024-10-04 21:46:29

美团2017年CodeM大赛-初赛B轮 黑白树 (树形dp)的相关文章

CodeM美团点评编程大赛初赛B轮 黑白树【DFS深搜+暴力】

[编程题] 黑白树 时间限制:1秒 空间限制:32768K 一棵n个点的有根树,1号点为根,相邻的两个节点之间的距离为1.树上每个节点i对应一个值k[i].每个点都有一个颜色,初始的时候所有点都是白色的. 你需要通过一系列操作使得最终每个点变成黑色.每次操作需要选择一个节点i,i必须是白色的,然后i到根的链上(包括节点i与根)所有与节点i距离小于k[i]的点都会变黑,已经是黑的点保持为黑.问最少使用几次操作能把整棵树变黑. 输入描述: 第一行一个整数n (1 ≤ n ≤ 10^5) 接下来n-1

2014第六届华为编程大赛初赛第一轮

/*********************************************************************** 1.投票问题 输入若干候选人,以及投票,格式如下,输出(按输入候选人输入顺序)候选人以及得票,以及 无效票数. Input: addCandidate xx1 addCandidate xx2 addCandidate xx3 addCandidate xx4 addCandidate xx5 addCandidate xx6 vote xx2 vot

【CodeM初赛B轮】F 期望DP

[CodeM初赛B轮]F 题目大意:有n个景点,m条无向边,经过每条边的时间需要的时间是l,在每个景点游览花费的时间是t,游览完每个景点可以获得的满意度是h.你的总时间为k,起初你等概率的选择游览一个景点,然后每次等概率的前往一个相邻的景点游览,当你剩余时间不够游览一个相邻的景点时就结束游览.问所获得的满意度的期望值.(本题强行询问两次~) n<=100,总时间<=500 题解:显然的期望DP啊,不过本题的细节比较多,我这里只说一些细节吧~ 用f[i][j]表示游览完景点i,还剩时间j,所获得

CodeM美团点评编程大赛初赛A轮

因为语文太差弃赛,第一个追及问题看不懂我就弃赛了.打进复赛确实挺难的,补一下题,锻炼下就行了. 身体训练 时间限制:1秒 空间限制:32768K 美团外卖的配送员用变速跑的方式进行身体训练.他们训练的方式是:n个人排成一列跑步,前后两人之间相隔 u 米,每个人正常速度均为 v 米/秒.当某个配送员排在最后的时候,他需要以当时自己的最高速度往前跑,直到超过排头的人 u 米,然后降回到原始速度 v 米/秒.每个人最初的最高速度为c[i] 米/秒,每轮衰减d[i] 米/秒,也就是说,如果i是第j个跑的

BC 2015年百度之星程序设计大赛 - 初赛(1)(KPI-主席树)

KPI Accepts: 517 Submissions: 2185 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的KPI是由当前管道内请求的重要值的中间值来计算.现在给你

HDU 6122 今夕何夕 【数学公式】 (2017&quot;百度之星&quot;程序设计大赛 - 初赛(A))

今夕何夕 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1295    Accepted Submission(s): 455 Problem Description 今天是2017年8月6日,农历闰六月十五. 小度独自凭栏,望着一轮圆月,发出了"今夕何夕,见此良人"的寂寞感慨. 为了排遣郁结,它决定思考一个数学问题:接下来最

2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)

题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展gcd, 不是用逆元吗.. 网上还有别人的解释,没看懂,贴一下: (a / b) % m = ( a % (m*b)) / b 笔者注:鉴于ACM题目特别喜欢M=1000000007,为质数: 当gcd(b,m) = 1, 有性质: (a/b)%m = (a*b^-1)%m, 其中b^-1是b模m的逆

2014年百度之星程序设计大赛 - 初赛(第二轮)

1001 暴力 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 100100; int ll[maxn], rr[maxn]; struct node { int x, y, bj; }e[maxn]; int main() { int cas = 1; int T; scanf("%d", &T);

2014年百度之星程序设计大赛 - 初赛(第二轮)Chess

题目描述:小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘上的走法遵循十字路线.也就是说,如果"王"当前在(x,y)点,小度在下一步可以移动到(x+1, y), (x-1, y), (x, y+1), (x, y-1), (x+2, y), (x-2, y), (x, y+2), (x, y-2) 这八个点中的任意一个. 小度觉得每次都是小良赢,没意思.为了难倒小良,他想出