决策单调性 dp

决策单调性的一些优化技巧

  • 对于判断决是否满足决策单调性,可以打个暴力验证一下

相邻层之间转移 - 分治

  • 适用于形如 O(nk) 的二维 dp,转移为上层转移到下层,不在同一层转移,并且具有决策单调性
  • 因为决策具有单调性,所以考虑分治,先求出 mid 的决策点,那么 1i<mid 的决策点为 [1,P],对于 mid<in 的决策点为 [P,n],递归下去,每一层的复杂度就是 O(nlogn)

LG P4072 [SDOI2016]征途

给定一个序列,希望分成 m 段,使得每一段的和平方的和最小

  • 显然设 dpi,j 表示前 i 个数分成 j 段的最小值,然后分治就可以了
inline void solve(int l,int r,int L,int R,int j) {
    if(l>r) return ;
    int mid=l+r>>1,p=0;
    FOR(i,L,min(R,mid-1)) {
        if(f[i][j-1]+(sum[mid]-sum[i])*(sum[mid]-sum[i])<f[mid][j]) p=i; 
        f[mid][j]=min(f[mid][j],f[i][j-1]+(sum[mid]-sum[i])*(sum[mid]-sum[i]));
    }
    solve(l,mid-1,L,p,j);solve(mid+1,r,p,R,j);
}
signed main() {
    n=read();m=read();
    FOR(i,1,n) FOR(j,1,m) f[i][j]=1e16;
    sum[0]=0;
    FOR(i,1,n) a[i]=read(),sum[i]=sum[i-1]+a[i],f[i][1]=sum[i]*sum[i];
    FOR(i,2,m) solve(1,n,1,n,i);   
    cout<<(m*f[n][m]-sum[n]*sum[n])<<endl;
    return 0;
}
  • 有一类题目的直接贡献比较难算,但是仍然可以考虑暴力做法,因为分治树的结构是非常特殊的

CF833B The Bakery

  • 还是考虑分治计算,区间数颜色直接用莫队来做,看起来很暴力,但是实际上每一层的复杂度仍然是 O(nlogn)

二分队列

  • 方程类似于 fi=minj=0i1fj+w(j,i)
  • 考虑用一个单调队列维护目前的连续的最优决策点
  • 因为满足决策单调性,所以对于相邻的两个决策点一定是 i 对于左区间更优,i+1 对于右区间更优,设这个分割点为 ki,i+1,那么队列中的值一定要满足 k1,2k2,3,...
  • 然后每次转移的时候将开头对于当前位置已经不够优的决策点弹走,可以通过二分快速判断,然后队头就是对于当前位置的最优决策点,然后将当前位置压入队尾并弹出不够优秀的尾部决策点
posted @   Kzos_017  阅读(90)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示