CF868F Yet Another Minimization Problem

对于暴力dp的状态以及复杂度瓶颈就不再描述,假设前置内容大家都会了。
f[j][i]:前i个分了j组的最小费用。
记calc(l,r)表示:[l,r]分为一组的费用。
对于这个dp方程,我们可以得到一个性质,若:f[j][i]=f[j-1][p]+calc(p+1,i),f[j][ii]=f[j-1][pp]+calc(pp+1,ii),则i<=ii。(不会证明,只能说是多画点图后猜测的…,当然,也蛮显然的)
而这个就是决策单调性优化dp的标志了。
总而言之就是:由于刚刚猜测的式子,所以当我们做当前的f[j][ii]时,若之前的f[j][i]已经做过,并且f[j][i]是由f[j-1][p]转移而来的,那么我们只要从p开始,枚举pp就好了。这样可以在保证正确性的基础上,减去很多枚举步骤。
所以我们现在可以构思出一个大致框架:solve(l,r,ll,rr)表示要进行的dp区间为[l,r],dp[j][l…r]的值,均是由dp[j-1][ll…rr]转移而来的。
所以我们现在就可以随机在[l,r]内找一个值记为now好了,我们在转移f[j][now]时进行暴力枚举(不能暴力枚举多次,暴力枚举一次总行的吧),找出那个f[j-1][p]+calc(p+1,now)最小的p来,然后就可以分治下去了:solve(l,now-1,ll,p)和solve(now+1,r,p,rr)(这就是由刚刚的性质得来的)
而现在,为了实现复杂度的要求,我们就可以把这个[l,r]区间内的随机值,设为mid=l+r>>1,这样子就可以精确得使得递归层数为logn层,而对于每层的操作总和为n。需要分k段,所以复杂度就是:O(k nlogn)。
还有最后一个问题:calc(l,r)如何得到?且复杂度为什么?
利用类似莫队的双指针记录方法,可以在nlogn的时间内完成。
做完后发现,此类题与之前遇到过的整体二分有异曲同工之妙。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,nowl,nowr,ans;
int a[N],cnt[N],f[21][N]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值