——以此博客来悼念我在\(QBXT\)懵逼的时光


\(rqy\; tql\) (日常%\(rqy\))


概念及用途

斜率优化是\(DP\)的一种较为常用的优化(据说在高中课本里稍有提及),它可以用于优化这样的一种\(DP\)式子
\[dp[i]=a[i]+\max(y_j-k_ix_j)\;\;\; j\in[1,i-1]\]

原理

以下均以上面的\(DP\)方程为例

如果我们将上式中的\((x_j,y_j)\)画到坐标系里,然后画一条斜率为\(k_i\)的直线,则这条直线为的方程为\(y=k_ix+(y_j-k_ix_j)\),所以\(y_j-k_ix_j\)这一部分就是该直线的截距。所以在\(k_i\)确定的情况下,我们要求一个最大值,即该直线的斜率最大,那就相当于要找直线从上向下平移,所碰到的第一个点,这时,它的截距是最大的。

如果我们把这样的点筛出来,就能大大优化时间复杂度。
gif示意图

最后筛出来的点就是图中最后出现的红色点

当两个点在候选队列里,此时再加进来一个点,如果是这样的一种情况:

那我们可以把中间的那个点删去,因为删去它不会影响我们的最优解,他的截距显然要更大一些

如果是这样的一种情况

则三个点暂时全部保留,因为在某些时刻,它们都可能成为最优解

实现方式

我们可以用双端队列来处理,删掉不优的,加进去暂时较优的。在这只发一下代码中比较重要的部分吧

bool check(int a,int b,int c){
    return (y(a)-y(c))*(x(b)-x(c))-(y(b)-y(c))*(x(a)-x(c))>=0;
}
/*
省略中间部分
*/
for(int i=1;i<=n;i++){
        while(h<t&&y(q[h])-k(i)*x(q[h])<y(q[h+1])-k(i)*x(q[h+1])) h++;
        dp[i]=(sum[i]-l)*(sum[i]-l)+y(q[h])-k(i)*x(q[h]);
        while(h<t&&check(q[t-1],q[t],i)) t--;
        q[++t]=i;
    }

代码中的\(x\)函数、\(y\)函数、\(k\)函数、\(check\)函数请按需要更改,模板差不多就是这样了

例题

HNOI2008 玩具装箱TOY

若果我们在输入时将所有的\(C_i\)和\(L+1\),原公式可以化为\((S-L)^2\)

用\(f_i\)表示前\(i\)个数的最小花费
\(f_i=min(f_j+(S_i-S_j-L)^2)\;\; 1 {<=}j{<=}i-1\)
\(f_i=min(f_j+(S_i-L)^2-2(S_i-L)S_j+S_j^2)\)
\(\;\;\;\;=(S_i-L)^2+min(y_j-k_ix_j)\)
\(y_j=f_j+S_j^2,k_i=2(S_i-L),x_j=S_j\)

所以我们就可用斜率优化来\(A\)掉这道题了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
int read(){
    int k=0,f=1; char c=getchar();
    for(;c<'0'||c>'9';c=getchar())
      if(c=='-') f=-1;
    for(;c>='0'&&c<='9';c=getchar())
      k=(k<<3)+(k<<1)+c-48;
    return k*f;
}
int n;
ll dp[50010],sum[50010],l;
inline ll x(int i){ return sum[i]; }
inline ll y(int i){ return dp[i]+sum[i]*sum[i]; }
inline ll k(int i){ return 2LL*(sum[i]-l); }
inline bool check(int a,int b,int c){
    return (y(a)-y(c))*(x(b)-x(c))-(y(b)-y(c))*(x(a)-x(c))>=0;
}
ll q[100010],h=1,t=1;
int main(){
    n=read(),l=read()+1;
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+read()+1;
    for(int i=1;i<=n;i++){
        while(h<t&&y(q[h])-k(i)*x(q[h])>=y(q[h+1])-k(i)*x(q[h+1])) h++;
        dp[i]=(sum[i]-l)*(sum[i]-l)+y(q[h])-k(i)*x(q[h]);
        while(h<t&&check(q[t-1],q[t],i)) t--;
        q[++t]=i;
    }
    cout<<dp[n];
    return 0;
}

DP玄学优化——斜率优化的更多相关文章

  1. 牛客多校第10场J Wood Processing 分治优化/斜率优化 DP

    题意:你有n块木头,每块木头有一个高h和宽w,你可以把高度相同的木头合并成一块木头.你可以选择一些木头消去它们的一部分,浪费的部分是 消去部分的高度 * 木头的宽度,问把n块木头变成恰好m块木头至少要 ...

  2. 【刷题笔记】DP优化-斜率优化

    斜率优化,是一种利用斜率的优化(废话) 关于数论:咕咕咕 部分内容参考自学长 如果有这样的一个状态转移方程: \[f[i]=\min\limits_{j=L_j}^{R_j}\{f[j]+val(j, ...

  3. 「DP 浅析」斜率优化

    #0.0 屑在前面 将结合经典例题 「HNOI2008」玩具装箱 以及 「NOI2007」货币兑换 进行讲解. #1.0 简述 #1.1 适用情况 斜率优化一般适用于状态转移方程如下的 DP \[f_ ...

  4. DP单调队列--斜率优化P3195

    题意:https://www.luogu.com.cn/problem/P3195 思路:https://www.luogu.com.cn/problemnew/solution/P3195 #def ...

  5. 【学习笔记】动态规划—斜率优化DP(超详细)

    [学习笔记]动态规划-斜率优化DP(超详细) [前言] 第一次写这么长的文章. 写完后感觉对斜优的理解又加深了一些. 斜优通常与决策单调性同时出现.可以说决策单调性是斜率优化的前提. 斜率优化 \(D ...

  6. 【BZOJ-1911】特别行动队 DP + 斜率优化

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3478  Solved: 1586[Submit][Statu ...

  7. [luogu3628][bzoj1911][APIO2010]特别行动队【动态规划+斜率优化DP】

    题目描述 给你一个数列,让你将这个数列分成若干段,使其每一段的和的\(a \times sum^2 + b \times sum + c\)的总和最大. 分析 算是一道斜率优化的入门题. 首先肯定是考 ...

  8. BZOJ 3437 小P的牧场(斜率优化DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3437 [题目大意] n个牧场排成一行,需要在某些牧场上面建立控制站, 每个牧场上只能建 ...

  9. HDOJ 1300 Pearls 斜率优化dp

    原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=1300 题意: 题目太长了..自己看吧 题解: 看懂题目,就会发现这是个傻逼dp题,斜率优化一下就好 代 ...

随机推荐

  1. Linux下新建一个站点

    Apache+nagix使用Lnmpa创建一个新的站点 我们在部署服务器的时候通常会遇到需要分域名和分应用部署,那么如何通过Apache+nagix创建一个新的站点服务呢 LNMPA这种架构有什么优势 ...

  2. 每次打开office 2013都提示配置进度,必须得等他下完然后重启,重启完了在打开,还是提示配置进度,怎么解决

    方法一: 我用下面的方法完美解决.在控制面板中1.删除旧版本2010 或者20032.删除激活程序3.重装2013激活程序done 方法二: 我把WPS卸载了就好了. 方法三: 我是按这个方法解决的, ...

  3. CodeForces754D【贪心】

    题意: 有n个区间,每个区间覆盖区间里一段数,求最大连续区间长度被覆盖k次,并输出选取的区间. 思路: 贪心: 感觉一开始肯定是要把区间按left从小到大排序的. 然后肯定是连续k个区间能够达到的重叠 ...

  4. KM算法萌新讲解篇

    KM算法   首先了解问题:也就是最大权值匹配: 二分图里,边带了权值,求整幅图里匹配最大/最小的权值 因为接触匈牙利算法的时候看的是找对象系列的博文,所以也自己写一发找对象的博文吧: 算法背景: 信 ...

  5. IT兄弟连 JavaWeb教程 JSP与Servlet的联系

    Servlet是使用Java Servlet接口(API)运行在Web服务器上的Java程序,其功能十分强大,它不但可以处理HTTP请求中的业务逻辑,而且还可以输出HTML代码来显示指定页面,而JSP ...

  6. ubuntu 安装 RPostgreSQL 库

    其实大家在Linux 的R 中安装其他库,完全可以使用R 自带的安装方式,只是这个 RPostgreSQL 库需要用到 postgresql 的lib 库与include 头文件,所以才有若干个步骤去 ...

  7. MyBatis源码解析(一)

    <!-- mybatis文件配置,扫描所有mapper文件 --><!--SqlSessionFactoryBean的初始化参数--> <bean id="sq ...

  8. C 语言实例 - 删除字符串中的特殊字符

    C 语言实例 - 删除字符串中的特殊字符 C 语言实例 C 语言实例 删除字符串中的除字母外的字符. 实例 #include<stdio.h> int main() { ]; int i, ...

  9. react native 安卓打包--mac环境,如果打包不成功可注意下my-release-key.keystore的位置关系(绝对路径)

    // my-release-key.keystore和my-key-alias都是可修改的名称 1.生成签名密钥(keytool -genkey -v -keystore my-release-key ...

  10. Markdown - 如何使用上标、下标

    解决方法 Markdown可以和HTML的语法兼容,可以通过HTML的上标和下标标签来实现效果: 标签 写法 效果 上标 2<sup>10</sup> 210 下标 H< ...