NOIP2023 T4 题解

T4

写出转移方程:fi 表示前 i 天且第 i 天必须跑的最大能量值。gi=maxj=1i{fj}。初值 f0=g0=0

对于转移方程,考虑枚举最后一段跑的段是从哪里开始的:fi=maxj=ik+1i(gj2+prize(j,i)(ji+1)×d)。其中 prize(j,i)[j,i] 跑获得的奖励。

注意如果 j=1 要特判。

这个转移方程是 O(n2m) 的。我们发现,每一个跑段的起终点一定是某个挑战的起终点,所以我们可以离散化。

(注意离散化后还要数组对应到原来坐标,注意离散化后的转移可能有两种:① 上一个离散点就在前一个 ② 上一个点不相邻

然后我们发现这玩意可以用线段树优化:线段树第 i 个结点,表示当前的决策点为 i 时的值。

具体而言:

for (ll i = 1, p = 1; i <= cur; i++) { 
	while (p < i && rev[i] - rev[p] + 1 > k) //p指向当前第一个在rev[i]-k+1之后的 
		p++;
	for (auto ch: chl[i])
		st.mdf(1, 1, st.sz + 1, 1, ch.l + 1, ch.v);
	ll tmp = (rev[i - 1] == rev[i] - 1 ? max(0ll, i - 2) : i - 1); //找到上一个决策点 
	st.mdf(1, 1, st.sz + 1, i, i + 1, g[tmp] + (rev[i] - 1) * d);
	
	f[i] = st.qry(1, 1, st.sz + 1, p, i + 1) - rev[i] * d;
	g[i] = max(g[i - 1], f[i]);
}

revi 是离散化后的原坐标。

now 右移一个,首先要枚举所有右端点是 now 的挑战,然后对 [lft,now] 进行区间加 prize

对位置 now 的决策设初值:g[now1/now2]+(rev[now]1)×d

f[i]=st.qry(p,i+1)rev[i]×d

为什么?我们把 f 的转移方程做变形:fi=max(g[j1]+prize(j,i)(ij+1)×d),其中 prize(j,i) 的累加用了线段树,而 (ij+1)×d=(j1)×di×d

所以我们在每个决策位置 j 都预先 +(j1)×d,算 fi 的时候只需要求 max 再减去就行了。

(有点像斜率优化:拆式子,费用提前计算)

还有,数据卡常。不能 map 离散化,要用 sort

posted @   FLY_lai  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示