luogu-P3262题解
简要题意
有一棵不超过十层的满二叉树,需要对每个节点进行染色。每个叶子节点会对其颜色相同的祖先节点产生贡献且黑白贡献不同。求最大贡献。
题解
首先我会暴力!我如果直接暴力枚举每个节点的颜色,复杂度就是
不用说都知道是因为我们在枚举的时候重复枚举了很多相同的状态,这时我们应该单独考虑贡献。对于一个点,它的贡献应该只与其祖先节点有关,而我们暴力是去枚举了其他无关的节点。所以我们就可以设计一个
转移其实就是合并两个子树的信息,所以直接预处理出叶子节点的答案,然后跑一遍
代码
inline void upd(int &x, int y){x = x > y ? x : y;}
void dfs(int u, int sta, int dep){
if(dep == n)return(void)(f[u][0] = c[u - lim][sta][0], f[u][1] = c[u - lim][sta][1]);
for(int i = 0; i <= qp[dep]; ++i)f[ls][i] = f[rs][i] = 0;
dfs(ls, sta, dep + 1); dfs(rs, sta, dep + 1);
for(int i = 0; i <= qp[dep]; ++i)for(int j = 0; j <= qp[dep]; ++j)upd(f[u][i + j], f[ls][i] + f[rs][j]);
for(int i = 0; i <= qp[dep]; ++i)f[ls][i] = f[rs][i] = 0;
dfs(ls, sta + qp[dep], dep + 1), dfs(rs, sta + qp[dep], dep + 1);
for(int i = 0; i <= qp[dep]; ++i)for(int j = 0; j <= qp[dep]; ++j)upd(f[u][i + j], f[ls][i] + f[rs][j]);
}
signed main(){
n = rd(), m = rd(); lim = 1 << n - 1;
for(int i = 0; i < lim; ++i)for(int j = 0; j < n - 1; ++j)v[i][j][1] = rd();
for(int i = 0; i < lim; ++i)for(int j = 0; j < n - 1; ++j)v[i][j][0] = rd();
qp[n - 1] = 1; for(int i = n - 2; ~ i; --i)qp[i] = qp[i + 1] << 1;
for(int i = 0; i < lim; ++i)for(int j = 0; j < lim; ++j)
for(int k = 0, bit = i; k < n - 1; ++k, bit >>= 1)c[j][i][bit & 1] += v[j][k][bit & 1];
dfs(1, 0, 1); int ans = 0;
for(int i = 0; i <= m; ++i)upd(ans, f[1][i]);
wt(ans);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律