(实际上是 2024.9.14 写的)
本来以为是考 DS 的。()
T1
题目里给的那个性质可能是来干扰的。
异或上右移一位的数,其实就是除了第一位(最左边的),算贡献的时候都要看这一位异或前一位是不是 1。于是随便线性 DP,状态里记一下当前位填 0 还是 1 就行了。
DP 数组 状态的第一维 可以不要,省空间。
T2
板子。
ST 表、线段树、猫树等应该都可。我写的线段树。
当然如果用 ST 表的话应该也能算是 DP。
(其实用线段树或者猫树似乎也都算 DP 吧?)
T3
神秘。但是看题面又感觉有点点经典。
要求最后每个房间有 0 或 4 或 7 个人。
先想了下有没有什么贪心的结论,发现自己不会贪心,但是人的移动要“就近”。
发现一个显然的结论——可以把人的移动看成 人一个房间一个房间地移动。于是考虑 DP,从前往后看每个房间,只把前面房间里的人往后移,后面房间里的人往前移就相当于前面向后面移负数个人。直觉感觉这样直接用负数是对的,想了一下好像确实是对的。
于是设 \(f _ { i , j }\) 表示处理了前 \(i\) 个房间,前面的房间(\(1\) 到 \((i - 1)\))都满足了要求,\(i\) 房间有 \(j\)(可以为负数)人,此时的最小代价之和(最小移动步数之和)。枚举房间 \((i - 1)\) 最终要剩几个人来转移。
发现 \(j\) 的范围好像很大,而且有些 \(f _ {i, j}\) 用不到(无法被走到)。于是用 unordered_map 来记 \(f\)。滚动数组滚掉第一维。
现在还是过不了。考虑剪枝。
这些内容可能不对:如果一个位置有 \(\geq 14\) 个人,那么就一定可以把其中 \(7\) 个放在之前的房间里,让这 \(7\) 个人继续往后走一定是不优的。如果一个位置有 \(\leq - 14\) 个人,那么也是这样的,因为这相当于 从右往左走,和 从左往右走 在这一点上是一样的。
于是就考虑如果 \(- 14 \leq j \leq 14\) 才要 \(f _ {i, j}\) 这个状态。这样就能过了。
实际上都这样了可能就不用 unordered_map 了。但是我是直接在 unordered_map 版本上改的(现在 AC 了),没试过不用 unordered_map。
这个做法(用负数)我大概是从高精度减法里悟到的。
[题解做法类似。但是它记的是从上一个房间到这个房间的人数(也可以为负),更为优秀。(\(j\) 似乎是 \(- 7\)(包含)到 \(7\)(包含)的)。](??)
T4
注意仔细审题:一个人如果装饰,装饰的是一个长度不超过 \(x\) 的区间,且 \(p\) 在这个区间中。
数据范围比较奇怪,发现可以 \(O(nm)\)。
那么对于每个人,对于所有他能装饰的区间,在右端点上考虑左端点的范围。
题目是显然的区间分割类 DP。设 \(f _ i\) 表示处理了 \(1\) ~ \(i\) 位置的最大价值和。
对每个点,枚举每个人的每个可装饰区间,记当前的可装饰区间为 \([j + 1, i]\),转移方程为:
\(f _ i = \max ( f _ j + (i - j) * y )\)
考虑优化。把 \((i - j) * y\) 拆成 \(i * y - j * y\)。求 \(f _ j - j * y\) 的最大值即可。用 \(m\) 棵线段树来优化(因为有 \(m\) 个 \(y\))。
时间好像是 \(O(nm\log n)\)。
但是这个做法还没过,不知道为什么。
题解的[单调队列](?)做法时间复杂度好像更优。还没学。
总结(经验教训)
- 如果不会优化某个 DP 就拆 DP 式子,把与 \(i\)(当前点)相关的和与 \(j\)(从 \(j\) 转移来)相关的分开,可能就能优化了。(T4)
- 要学会从学过的东西里来迁移。(T3)
- DP 也可以剪枝(不要一定不优的状态)。(T3)
2024.9.14
标签:map,13,14,2024.9,房间,unordered,DP From: https://www.cnblogs.com/huangkxQwQ/p/18414738