【题解】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\) 天。

有转移:

\[f_{i,0}=\max(f_{i,j})\\ f_{i,j}=\max(f_{i-1,j-1}-d+w(i,j))\\ w(i,j)=\sum_{k=1}^m[x_k=i\wedge j\ge y_k]v_k \]

2min finished bf. Let me try try. (


bf \(O(nkm)\)

好的,这显然是对的,现在考虑优化。

(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\) 天,剩余体力值最大。

转移的话,直接枚举最后一次连续区间:

\[f_{i}=\max(f_{i-1},f_{j}-(i-j-1)d+w(j+2,i))\\ w(i,j)=\sum_{k=1}^m[x_k-y_k+1\le i\le j\le x_k]v_k \]

这样状态数就舒服了不少。

\(\max\) 里面这一整坨用线段树维护就好。

具体地:

先把每个任务放在她的右端点。

  1. \([1,i]\) 区间 \(-d\)
  2. 然后对于右端点在 \(i\) 的每一个任务,我们对 \([x-y+1,x]\) 区间 \(+v\)
  3. 然后查询 \([i-k+1,i]\) 的区间最大值就行了。

注意到有且只有 \(j=x-y+1,i=x\),所以我们把 \(x-y-1\)\(x\) 离散化做一遍就行了。


好好生生的总结一下这道简单题:

思路是简单的,但是不算很自然,容易想歪的。难评,所以 dp 题还是要多见,力争一次想对。😭

posted @ 2024-09-23 16:39  CloudWings  阅读(12)  评论(0编辑  收藏  举报