决策单调性 dp
决策单调性的一些优化技巧
- 对于判断决是否满足决策单调性,可以打个暴力验证一下
相邻层之间转移 - 分治
- 适用于形如
的二维 dp,转移为上层转移到下层,不在同一层转移,并且具有决策单调性 - 因为决策具有单调性,所以考虑分治,先求出 mid 的决策点,那么
的决策点为 ,对于 的决策点为 ,递归下去,每一层的复杂度就是
给定一个序列,希望分成
段,使得每一段的和平方的和最小
- 显然设
表示前 个数分成 段的最小值,然后分治就可以了
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;
}
- 有一类题目的直接贡献比较难算,但是仍然可以考虑暴力做法,因为分治树的结构是非常特殊的
- 还是考虑分治计算,区间数颜色直接用莫队来做,看起来很暴力,但是实际上每一层的复杂度仍然是
二分队列
- 方程类似于
- 考虑用一个单调队列维护目前的连续的最优决策点
- 因为满足决策单调性,所以对于相邻的两个决策点一定是
对于左区间更优, 对于右区间更优,设这个分割点为 ,那么队列中的值一定要满足 - 然后每次转移的时候将开头对于当前位置已经不够优的决策点弹走,可以通过二分快速判断,然后队头就是对于当前位置的最优决策点,然后将当前位置压入队尾并弹出不够优秀的尾部决策点
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探