【题解】Solution Set - NOIP2024集训Day21 DP常⻅模型2「背包」

【题解】Solution Set - NOIP2024集训Day21 DP常⻅模型2「背包」

https://www.becoder.com.cn/contest/5505


「BZOJ4987」Tree

答案显然是一个连通块,否则不优。

我们在每个连通块深度最小的点统计答案。

树上依赖背包就行。

fi,j,0/1 从当前根 i 开始,是否要回到当前根节点。

fi,j,2 从当前子树任意根节点开始,任意节点结束。

2 的转移不能写成钦定必须经过 i 的了:https://www.becoder.com.cn/submission/2594787


「雅礼集训 2018 Day10」贪玩蓝月

插入元素 O(p) 是好做的。


删除元素的话,如果只有一端,我们直接记录每个版本,然后回退就行。

所以,我们考虑把这个双段队列拆分成两个栈,这样就好处理了。

问题是如果一个栈空了,需要从另一个栈的底部借一个过来,怎么办?

我们直接把非空的那个栈从中间剖开,两边暴力重算,这样时间复杂度是对的。

Why?

考虑势能分析。

定义势能函数 h() 为两个栈的大小之差的绝对值。

每次加入元素最多会使 h() 加一。

而每次暴力重构会让 h()0。所以时间复杂度是均摊下来就是插入次数 * p。


现在我们 dp 值维护好了,问题在于查询,我们需要合并两个 dp 值。

显然可以 max+ 卷积合并,然后 O(p) 查询(但是这玩意没有凸性,不能闵可夫斯基和

考虑枚举一个栈内的 dp 值 dpi,在另一个栈区间查询 [li,ri] 的 dp 最大值,因为要取模所以其实就是两个滑动窗口。两种处理方式:

  1. 单调队列。分成两个区间分开处理;
  2. st 表。这样修改的时候带个 log

「SDOI2017」苹果树

如果没有 thk,那么就是一个裸的树上依赖背包。

一个结论:最深的那个点一定是叶子节点。否则往下走一定更优。

我们不妨去枚举枚举这个叶子节点,现在我们能选取的个数就是 k。同时整棵树被分成了两个部分,一部分是先序遍历在其前面的,另一部分是后序遍历在其前面的。

我们分别按先/后序遍历,预处理出这个两个多重背包的前缀。

自己的思路大体是对了,但是还有很多细节,具体可以参见 Soluiotn

代码里面的 g 计算的范围是先序遍历在 i 前面和 i 这条链上的点。f 是后序遍历在 i 前面的点。

关于单调队列优化多重背包。

(我不会所以来口胡一下。

先把朴素的 O(mcnti) 转移拿出来:

fi,j=maxk=0cnti{fi1,jk×wi+k×vi}

但是这道题 wi=1 我们可以很聪明的把式子改写成:

fi,j=maxk=0cnti{fi1,jk(jk)×vi}+j×vi

这样就变成真正的单调队列的板板了。如果 wi 任意的话,jk×wi 不再连续,所以就不能用这种比较巧妙的东西,得改循环顺序,具体参见 OI-Wiki

「BZOJ3425 Poi2013」Polarization

由于每条边至少贡献一次(就这条边两旁的两个点),同时我们可以每层让边反向构造出这组方案。

所以第一问最小值就是边数 n1


现在算最大值。

有两个结论:

  1. 如果我们钦定了一个根,那么她的
posted @   CloudWings  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示