CF1845E

原题

翻译

首先我们容易发现如果给每个球一个编号,他的相对位置是不变的

于是我们不妨把原问题转化为一个常为k严格递增的序列bi表示这k的球的位置

我们发现如果递推操作次数显然不记录序列的状态的话是比较难办的。于是我们考虑正难则反,考虑对于一个序列ci,判断他能不能让bi通过操作k次得到

容易发现如果想得到ci,要满足以下条件:

  • |b|=|c|,表示序列bici的长度相等
  • i=1k|bici|k,表示最少操作次数k
  • (ki=1k|bici|)mod2=0,表示剩下的操作通过来回移动一个小球来消耗掉

于是我们按照序列顺序dp,设dpi,j,s表示前i个位置放j个小球,此时操作次数为s的方案数

容易得到递推式:

dpi,j,s=dpi1,j,s+dpi1,j1,s|ibj|

其中前半部分表示第i个位置不选小球的贡献,后半部分则表示i个位置选小球的贡献

这样的复杂度是O(n2k),据说加上一个滚动数组后卡常也能过,但从理论上这个复杂度我们是不满意的。我们考虑优化这个dp


方法1:

关于不降序列对应位置距离之和,有经典套路:在每个间隔处统计答案。 我们设fc,i表示对于序列bici的前数值i的部分的bi的个数和ci的个数差几个(也可以理解成前i个位置原先小球个数-操作后小球个数),其中差可以为负。

容易发现对于一个已知序列ci,其变为bi最小操作次数为i=1n|fc,i|

而优化dp的过程通常需要以下两种条件:

  • 考虑特殊条件
  • 去除多余状态

如果细心可以发现题目有一个隐含条件,即|fc,ifc,i1|{0,1}

假设存在一个序列ci|fc,i|足够大,则|fc,i|可以构造成形如1,2,3,...,fc,i的等差数列的形式

根据等差数列求和公式,容易得到序列ci变为bi的最小操作次数为O(fc,i2)

但根据题目要求,最小操作次数应该O(k),所以|fc,i|O(k)

于是我们考虑把|fc,i|带入dp式子中代替j项定义

dpi,j,s表示前i个位置中原先球的个数-操作后小球个数=j,最小操作次数=s的方案数

容易得到递推式:

dpi,j,s=dpi1,j[ai==1],sj+dpi1,j[ai==1]+1,sj

最终复杂度O(nkk)


方法2:

仔细一想上面的方法,可以发现我们优化后的dp式子相对与原先的dp式子记录的状态数完全没有改变,且我们并没有优化转移,所以说明原先的dp式子加一点小优化复杂度也是不变的

我们同样用一种更感性的方法证明上面的问题

我们考虑如果[1,x]内全是球,我们想把这些球都移走,则我们需要的最小操作次数是i=1xi=O(x2),但我们要求最多操作O(k),则xO(k)

于是我们可以求出dp转移时j的范围[preik,prei+k],其中prei表示操作前的前i个位置的球的个数

同样得到最终复杂度O(nkk)

posted @   FOX_konata  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示