首页 > 其他分享 >斜率优化dp 学习笔记

斜率优化dp 学习笔记

时间:2023-06-17 09:44:53浏览次数:51  
标签:笔记 斜率 2as 最优 我们 dp 式子

斜率优化dp

引入

首先,我们考虑一种更简单的dp优化——单调队列优化。

比如,一个dp式形如:

\[dp_{i} = \min_{k \leq j \leq i} (dp_j+f_j+g_i) \]

我们发现,这个式子可以通过拆分(wgj:分离变量),变形成如下式子:

\[dp_{i} = \min_{k \leq j \leq i} (dp_j+f_j)+g_i \]

怎么样?我们发现,取最小值的这一项只与 \(j\) 有关,其余项只与 \(i\) 有关,那么我们可以想办法搞出 \(dp_j+f_j\) 的最小值,然后直接转移即可。我们发现,\(j\) 是在一个区间内的,那取最小值就转化为一个滑动窗口问题,使用单调队列即可。

总结一下,如果dp式中的元素可以分类,即一部分只与 \(i\) 有关,另一部分只与 \(j\) 有关,并且 \(j\) 有区间范围,区间单调右移,这样的dp就可以采用单调队列优化掉一层枚举。

但是,有时候,dp式子中的某一项既与 \(i\) 有关,又与 \(j\) 有关,例如以下dp式:

\[dp_i = \min_{0 \leq j < i}(dp_j+a_j+b_ic_j) \]

这时候你就完蛋了你就会痛苦的发现,单调队列不太行xwx。因为对于这个函数,我们很难直接找出最优决策点。

这时候,我们引入斜率优化。

斜率优化

Part 1:推式子

我们就题来谈 [APIO2010] 特别行动队

首先,这个题的dp式子很显然。我们设 \(s\) 为 \(x\) 的前缀和数组,\(dp_i\) 表示到第 \(i\) 个人,分组后的最大和,那么有:

\[dp_i = \max(dp_j+a(s_i-s_j)^2+b(s_i-s_j)+c) \]

然后,我们对它进行化简:

\[dp_i = \max (dp_j+as_j^2-bs_j-2as_is_j)+as_i^2+bs_i+c \]

关于 \(i\) 的部分,我们可以当作常量提出去,令这部分为 \(g_i\);剩下的部分中,一部分只与 \(j\) 有关,我们令这部分为 \(f_j\),这样,式子变为:

\[dp_i = \max(f_j-2as_is_j)+g_i \]

这时候,我们来看一下 \(\max\) 内部的部分。我们不妨设 \(f_1-2as_is_1 \leq f_2 -2as_is_2\),那么经过移项,有:

\[\frac{f_2-f_1}{s_2-s_1} \geq 2as_i \]

这样子,我们会发现一些内幕。如果平面直角坐标系中有两个点 \(A(s_1, f_1)\),\(B(s_2, f_2)\),那么上述式子等价于过 \(A\) 和 \(B\) 两点的直线的斜率。

Part 2:合法点集斜率单调性

我们总结一下上一个部分的结论:如果两个点连线的斜率不小于 \(2as_i\),那么前面这个点对应的 \(j\) 就不是最优决策点;反之,后者对应的 \(j\) 不是最优决策点。

我们考虑三个点的简化情况,假设 \(1\) 号点到 \(2\) 号点的斜率为 \(x\),\(2\) 号到 \(3\) 号点斜率为 \(y\),令 \(x<y\),\(k = 2as_i\):

pCQ0JT1.jpg

我们发现,\(2\) 号点一定不是最优决策点。因为它为最优点的充要条件是 \(y < k\) 并且 \(x \geq k\),而 \(x < y\)。

那么,我们就可以宣:\(2\) 号点你废了!抹(ma)走!

扩展一下:如果我们现在有很多个点,而这个点集中,如果存在三个横坐标递增的点,使得前两个点的斜率小于等于后两个点的斜率,那么可以删掉中间的点。

所以,如果我们处理出一个不可删点集的斜率数组(也就是最终要挑选出最优决策点的点集),那这个数组必然是单调递减的。

Part 3 找最优决策点

那这样,我们就可以二分来查找最优决策点。

其实,如果我们画图来看,会发现上述过程中,我们维护了一个凸壳;

pCQ0MSU.jpg

而找最优决策点,实际上就是令一条斜率为 \(k\) 的直线去切这个凸壳,切点即为最优决策点。

Part 4 代码实现

在这道题中,可以省略二分这一步。为什么呢?因为这道题的 \(k\) 是单调递减的,所以我们每次只需要把队头斜率斜率比 \(2as_i\) 大的弹走,留下的队头就是最优决策点。

至于在队尾加入元素,我们维护上凸包,每次比较队尾的两个元素的斜率和队尾与 \(i\) 点的斜率,如果后者大于前者,就弹队尾。

注意有些细节:求斜率必须要有两个点,所以要初始化队列头尾指针为 \(0\),这样当队列为空时,能保证队列中仍存在一个点。

#include<bits/stdc++.h>
#define LD long double
#define ll long long
using namespace std;
const int N = 1e6+100;

inline ll read(){
    ll x = 0, f = 1; char ch = getchar();
    while(ch<'0' || ch>'9'){
        if(ch == '-') f = -1;
        ch = getchar();
    }
    while(ch>='0'&& ch<='9'){
        x = x*10+ch-48;
        ch = getchar();
    }
    return x * f;
}
int n, L;
ll s[N];
ll a, b, c;
ll dp[N];
LD q[N];
int lq , rq;
LD getx(int x){
    return s[x];
}
LD gety(int x){
    return a*s[x]*s[x]-b*s[x]+dp[x];
}
LD getk(int x, int y){
    return (gety(y)-gety(x))/(getx(y)-getx(x));
}
int main(){
    scanf("%d", &n);
    scanf("%lld%lld%lld", &a, &b, &c);
    for(int i = 1; i<=n; ++i){
        s[i] = read();
        s[i]+=s[i-1];
    }
    for(int i = 1; i<=n; ++i){
        while(lq<rq&&2*s[i]*a<=getk(q[lq], q[lq+1])) lq++;
        int j = q[lq];
        dp[i] = dp[j]+a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c;
        while(lq<rq&&getk(q[rq-1], q[rq])<=getk(q[rq], i)) rq--;
        q[++rq] = i;
    }
    printf("%lld\n", dp[n]);
    return 0;
}

标签:笔记,斜率,2as,最优,我们,dp,式子
From: https://www.cnblogs.com/frostwood/p/17487064.html

相关文章

  • 日语语法学习笔记
    对应课程名词谓语句~だ只能接终助词或句号否定:~ではない疑问:~(か)~です对听话人礼貌否定:~ではありません疑问:~ですか~ですか、~ですか:前升后降~である正式场合对听话人礼貌:~であります~でございます敬语,郑重~は/が格助词は:强调主语が:强调宾语......
  • 【笔记】韦达定理的定义与证明
    前言已知,一元二次方程\(ax^2+bx+c=0\)\((a,b,c\in\mathbb{R},a\not=0)\)有如下求根公式:\[\Delta=b^2-4ac\]\[x_{1,2}=\frac{-b\pm\sqrt{\Delta}}{2a}\]当\(\Delta<0\)时,方程无实数根;当\(\Delta=0\)时,方程有两个相等的实数根(\(x_{1}=x_{2}\));当\(\D......
  • [学习笔记] 位运算
    〇、基础位运算与运算/AND语法:a&b。计算方法:按位计算AND。运算:1&1=1,1&0=0,0&1=0,0&0=0。或运算/OR语法:a|b。计算方法:按位计算OR。运算:1|1=1,1|0=1,0|1=1,0|0=0。异或运算/XOR语法:a^b。计算方法:按位计算XOR。运......
  • 算法学习笔记(25): 矩阵树定理
    矩阵树定理本文不作为教学向文章。比较好的文章参考:矩阵树-定理以及凯莱公式【学习笔记】矩阵树定理(Matrix-Tree)_繁凡さん的博客-CSDN博客矩阵树定理入土-ixRic的博客-洛谷博客对于无向图无向图中应该是矩阵树定理的常用场景。无向图的矩阵树定理讲的是:......
  • 【React工作记录一百零八】前端小知识点扫盲笔记记录9
    前言我是歌谣放弃很容易但是坚持一定很酷微信公众号关注前端小歌谣带你进入前端巅峰交流群今天继续对前端知识的小结如何截取字符串<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge">......
  • 【React工作记录一百零九】前端小知识点扫盲笔记记录10
    前言我是歌谣放弃很容易但是坚持一定很酷微信公众号关注前端小歌谣带你进入前端巅峰交流群今天继续对前端知识的小结对称数<!DOCTYPEhtml><htmllang="en"> <head> <metacharset="UTF-8"/> <metahttp-equiv="X-UA-Compatible"content="IE=edge"/>......
  • 学习笔记之Zookeeper内部原理解析
    1.1节点类型1.2Stat结构体(1)czxid-创建节点的事务zxid每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。(2)ctime-znode被创建的毫秒数(从19......
  • PAT甲级笔记
    第一次刷题笔记如果对数组进行sort排序:sort(a,a+n,cmp1);如果对vectorv或者字符串v进行sort排序:sort(v.begin(),v.end(),cmp1);辗转相除法求最大公约数:1 intgcd(inta,intb){2 returnb==0?a:gcd(b,a%b);3 }#definemax(a,b)a逗号后面不要加空......
  • 「学习笔记」组合数学
    本文部分内容来自\(\texttt{OI-Wiki}\)。加法&乘法原理加法原理完成一个工程可以有\(n\)类办法,\(a_i(1\lei\len)\)代表第\(i\)类方法的数目。那么完成这件事共有\(S=a_1+a_2+\cdots+a_n\)种不同的方法。乘法原理完成一个工程需要分\(n\)个步骤,\(a_i(1\le......
  • Wordpress:Briefly unavailable for scheduled maintenance. Check back in a minute.
    场景描述:在更新Wordpress版本从Version6.2.1升级到Version6.2.2时候,顺带点升级的插件太多了,突然就崩溃报错:Brieflyunavailableforscheduledmaintenance.Checkbackinaminute。 因为用的是Siteground建站,以为过会就好了,等了五分钟还是这样,所以进Siteground后台,文件管......