Minimax Tree 树上放min和max得到最大数和最小数 贪心+树形DP
题目
Minimax Tree(https://ac.nowcoder.com/acm/problem/128164)
题目大意
一棵有根树,它由从1到n的n个顶点组成,根顶点的数目是1。这棵树有x片叶子
(根不被认为是叶子)。树的每一片叶子上都写着一个整数。
Bob有n-x个贴纸,其中有k个被标为min,有n-x-k被标为max。
Bob决定将贴纸放在树的内部顶点上,每个内部顶点上都有一个贴纸。
一旦他把所有的贴纸贴在树上,Bob想用以下方式计算树的每个顶点v的函数f:
如果v是叶,f(v)等于用v写的整数。
如果v有“min”标签,f(v)等于f(u)的最小值,其中u是v的任何子节点。
如果v有“max”标签,f(v)等于f(u)的最大值,其中u是v的任何子节点。
Bob还不知道如何在树上放置标签,但是他对根顶点f的值感兴趣。给出树和标签,帮助鲍勃计算f(1)的最小值和最大值!
输入描述:
第一行包含两个空格分隔的整数n和k(2≤ n ≤ 10^5,0≤ k≤ n)。第二行包含n - 1空格分隔整数p2, p3, …, pn(1≤ pi≤ n)。数字pi表示编号为i的顶点的父节点。第三行包含n个空格分隔的整数a1, a2, …, an(0≤ ai ≤ 10^9)。如果顶点i是叶,那么ai是写在该顶点上的数字。否则ai等于0。
保证给定的图是一棵树。保证k + l ≤ n。
输出描述:
在单行输出中,两个整数用空格隔开f(1)的最小值和最大值。
思路
如果我们有k个min,求min时,在深度k的范围,所有的节点都是我们可以控制的节点。
因为我们可以直接连一条链到它,得到它的值。对于k层外的节点只能放max了。可以怎么不把min放在k层外是最优的。
这个思路有一个没有考虑到的点。例如
1这个节点放max和min没有影响。所以dfs的时候只有一个子树时,dfs层数不能增加。
求max是一样的做法。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
vector<vector<int> > G(100005);
int a[100005];
int f[100005], d[100005];
int ans;
vector<int> v;
//k:贴纸的数量 d:层数 pos:求min还是max
void dfs(int u, int k, int d, int pos) {
if(d==k+1) {
v.push_back(u);
return;
}
if(a[u]) {
if(!pos) ans=min(ans, a[u]);
else ans=max(ans, a[u]);
}
for(auto x: G[u]){
if(G[u].size()==1) dfs(x, k, d, pos);
else dfs(x, k, d+1, pos);
}
}
//对深度为k的子节点树形DP
void dfs2(int u, int pos) {
for(auto x: G[u]) {
dfs2(x, pos);
if(!pos) f[u]=max(f[u], f[x]);
else f[u]=min(f[u], f[x]);
}
if(a[u]) f[u]=a[u];
}
int main() {
int n, k;
scanf("%d%d", &n, &k);
for(int i=2; i<=n; i++) {
int x;
scanf("%d", &x);
G[x].push_back(i);
d[x]++;
}
int siz=0;
for(int i=1; i<=n; i++) {
scanf("%d", &a[i]);
if(d[i]==0){
siz++;
}
}
ans=0x3f3f3f3f;
dfs(1, k, 1, 0);
for(auto x: v) {
dfs2(x, 0);
ans=min(ans, f[x]);
}
printf("%d ", ans);
ans=0;
v.clear();
memset(f, 0x3f, sizeof(f));
dfs(1, n-k-siz, 1, 1);
for(auto x: v) {
dfs2(x, 1);
ans=max(ans, f[x]);
}
printf("%d\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了