【题解】Solution Set - NOIP2024集训Day36 dp 优化 - 状态设计
【题解】Solution Set - NOIP2024集训Day36 dp 优化 - 状态设计
https://www.becoder.com.cn/contest/5550
最后一题较难。
「NOIP2023」天天爱打卡
考虑 dp。
\(f_{i,j}\):前 \(i\) 天,到第 \(i\) 天为止连续打卡 \(j\) 天。
有转移:
2min finished bf. Let me try try. (
好的,这显然是对的,现在考虑优化。
(nearly FAKE
首先可以对 \(x\) 离散化,对每一个 \(x\) 的 \(y\) 排序之后,\(w\) 可以在 \(O(\log m)\) 计算,现在就是 \(O(km\log m)\) 的。
肯定这个 \(k\) 是不能要的。
上面这种状态根本没有优化前途(有点浪费时间。😥
(FAKE
还是先离散化。
重新定义状态:
\(f_{i}\):前 \(i\) 个任务剩下的最大体力值。
转移的时候,枚举一下当前这个天数的任务,完成了前多少个。均摊下来应该就对了。
13min
嘶,不太对。因为我们每次相当于钦定了一个极长区间打卡,问题就出在这个极长上面,因为有可能这个区间内会有其他的任务,所以代价不一定只有当前这个任务给定,故而并不能确定这个代价,也就不能确定这是极长区间是最优的了。
(稍微瞄了一眼题解(wtf,线段树?
好吧,那就返璞归真。
现在正片开始,我要重新理一下思路。
刚才 \(O(km\log m)\) 的做法的问题主要在于,始终还是没有脱离 \(k\),导致难以优化。
我们直接定义:
\(f_i\):前 \(i\) 天,剩余体力值最大。
转移的话,直接枚举最后一次连续区间:
这样状态数就舒服了不少。
\(\max\) 里面这一整坨用线段树维护就好。
具体地:
先把每个任务放在她的右端点。
- 先 \([1,i]\) 区间 \(-d\);
- 然后对于右端点在 \(i\) 的每一个任务,我们对 \([x-y+1,x]\) 区间 \(+v\)。
- 然后查询 \([i-k+1,i]\) 的区间最大值就行了。
注意到有且只有 \(j=x-y+1,i=x\),所以我们把 \(x-y-1\) 和 \(x\) 离散化做一遍就行了。
好好生生的总结一下这道简单题:
思路是简单的,但是不算很自然,容易想歪的。难评,所以 dp 题还是要多见,力争一次想对。😭