决策单调性优化
二分队列
反过来决策所对应的也是单调的。
设为决策为的最小。
队列里存有意义的决策。
DP过程:
- 求的决策,弹队头。
- 对尾弹掉不如的决策,更新的前驱的lim,把插进去。
方便可以写一个Search函数,查询两个决策对应状态集的分界点。
code:
点击查看代码
int Search(int x, int y) {
int l = y + 1, r = n, bst = y;
while(l <= r) {
int mid = (l + r) >> 1;
if(calc(mid, x) <= calc(mid, y)) {bst = mid; l = mid + 1;}
else r = mid - 1;
}
return bst;
}
Q[hd = tl = 1] = 0;
for(int i = 1; i <= n; i++) {
while(hd < tl && lim[hd] < i) hd++;
f[i] = calc(i, Q[hd]), pos[i] = Q[hd];
while(hd < tl && lim[tl - 1] > Search(Q[tl], i)) {tl--;}
lim[tl] = Search(Q[tl], i); Q[++tl] = i;
}
的四边形不等式
- 四边形不等式:满足交<并
- 满足四边形不等式则满足决策单调性:。
所以dp时的决策从变为了
复杂度:。因为长度为的由更新,长度为状态枚举决策点总复杂度为。因为,接着...
斜率优化
限制要求还是挺多的
先剔除无关紧要的常数项。
柿子含三个部分,只跟有关,只跟有关,与,都有关(如)。
此时把柿子化成一次函数(直线):形式。
-
:只跟有关
-
: ,骨肉相连中的部分
-
:同上的部分
-
:只跟有关
如目的是让最小,即直线的截距尽量小。
发现决策是若干个已经确定的节点,然后斜率也确定,即问题转化为了用固定斜率的直线去切节点使得截距最小。
画画图知道如果是截距最小队列维护下凸壳,否则上凸壳。
然后凸壳上连线的斜率从左往右是单增的,而所切的点往左连的边斜率,右连的斜率,感觉像一个分界处把。 -
必要前提是单增,这样才可维护凸包。
-
如果单增可以单调队列,否则就每次去二分啦,要带一个。
code
点击查看代码
Q[hd = tl = 1] = 0; dp[0] = 0;
for(int i = 1; i <= n; i++) {
while(hd < tl && Y(Q[hd + 1]) - Y(Q[hd]) <= K(i) * (X(Q[hd + 1]) - X(Q[hd]))) hd++;
int j = Q[hd]; dp[i] = dp[j] + _pw(a[i] - a[j]) + m;
while(hd < tl && (Y(i) - Y(Q[tl])) * (X(Q[tl]) - X(Q[tl - 1])) <= (Y(Q[tl]) - Y(Q[tl - 1])) * (X(i) - X(Q[tl]))) tl--;
Q[++tl] = i;
}
ps.我跳过多次的坑:求斜率除法要考虑精度,因此比较大小同乘分母可以直接整数比较大小,但是要注意不等式同乘负数要变号。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人