题目描述

给你一个数列,让你将这个数列分成若干段,使其每一段的和的\(a \times sum^2 + b \times sum + c\)的总和最大。

分析

算是一道斜率优化的入门题。
首先肯定是考虑\(O(n^2)\)的暴力DP。
定义状态\(f[i]\)表示最后一段的结尾是\(i\)的最大答案。
那么枚举j,得到转移方程为\(f[i]=max(f[i],f[j]+a\times (sum[i]-sum[j])^2+b\times(sum[i]-sum[j])+c\)
注意这里的转移方程不是\(sum[i]-sum[j-1]\)而是\(sum[i]-sum[j]\),因为j是属于前一段的,所以不能算j-1这一个格子。
40分蜜汁错误和全部剩下全部T飞。

#include <bits/stdc++.h>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define N 1000005
using namespace std;
template <typename T>
inline void read(T &x) {
    x = 0; T fl = 1;
    char ch = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-') fl = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    x *= fl;
}
ll sqr(ll x) {
    return x * x;
}
int n;
ll a, b, c;
ll x[N], sum[N], f[N];
int main() {
    read(n);
    read(a); read(b); read(c);
    for (int i = 1; i <= n; i ++)  {
        read(x[i]);
        sum[i] = sum[i - 1] + x[i];
    }
    for (int i = 1; i <= n; i ++)
        for (int j = 0; j < i; j ++)
            f[i] = max(f[i], f[j] + sqr(sum[i] - sum[j]) * a + (sum[i] - sum[j]) * b + c);
    printf("%lld\n", f[n]);
    return 0;
}

很显然这不是正解,那么我们就考虑优化DP。
考虑斜率优化。按照斜率优化的标准套路。
假设\(0<=k<j<i\)时,j的状态比k要优。。
那么很明显就得到了以下的式子,再将其化简:
\[f_j+a\times(sum_i-sum_j)^2+b\times(sum_i-sum_j)+c>=f_k+a\times a\times(sum_i-sum_j)^2+b\times(sum[i]-sum[j])+c\]
以下的所有操作都是初中内容。(可能会跳步,但是看得懂)
\[f_j-2asum_isum_j+asum_j^2-bsum_j>=f_k-2asum_isum_k+asum_k^2-bsum_k\]
\[\frac{(f_j+asum_j^2-bsum_j)-(f_k+asum_k^2-bsum_k)}{sum_j-sum_k}>=2sum_i\]
可以发现:左边单调递增,右边单调递减。那么维护斜率上凸包。

#include <bits/stdc++.h>
#define ll long long
#define ms(a, b) memset(a, b, sizeof(a))
#define inf 0x3f3f3f3f
#define N 1000005
#define db double
using namespace std;
template <typename T>
inline void read(T &x) {
    x = 0; T fl = 1;
    char ch = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-') fl = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    x *= fl;
}
ll sqr(ll x) {
    return x * x;
}
int n;
ll a, b, c;
ll x[N], sum[N], f[N];
int q[N];
ll get_x(int i) {
    return sum[i];
}
ll get_y(int i) {
    return f[i] + a * sqr(sum[i]) - b * sum[i];
}
db get_slope(int i, int j) {
    return (1.0 * (get_y(j) - get_y(i))) / (1.0 * (get_x(j) - get_x(i)));
}
int main() {
    read(n);
    read(a); read(b); read(c);
    for (int i = 1; i <= n; i ++)  {
        read(x[i]);
        sum[i] = sum[i - 1] + x[i];
    }
    int h = 0, t = 0;
    for (int i = 1; i <= n; i ++) {
        while (h < t && get_slope(q[h] , q[h + 1]) >= 2.0 * a * sum[i]) h ++;
        int j = q[h];
        f[i] = f[j] + a * sqr(sum[i] - sum[j]) + b * (sum[i] - sum[j]) + c;
        while (h < t && get_slope(q[t - 1], q[t]) <= get_slope(q[t], i)) t --;
        q[++ t] = i;
    }
    printf("%lld\n", f[n]);
    return 0;
}

[luogu3628][bzoj1911][APIO2010]特别行动队【动态规划+斜率优化DP】的更多相关文章

  1. BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 UPD(2018-04-01):用Latex重打了公式…… 题意概括 把一个整数序列划分成任意连续的段,使得划分出 ...

  2. 2018.09.07 bzoj1911: [Apio2010]特别行动队(斜率优化dp)

    传送门 斜率优化dp经典题. 题目中说的很清楚,设f[i]表示前i个数分配出的最大值. 那么有: f[i]=max(f[j]+A∗(sum[i]−sum[j])2+B∗(sum[i]−sum[j])+ ...

  3. [bzoj1911][Apio2010特别行动队] (动态规划+斜率优化)

    Description Input Output Sample Input - - Sample Output HINT Solution 斜率优化动态规划 首先易得出这样的一个朴素状态转移方程 f[ ...

  4. BZOJ1911 [Apio2010]特别行动队 【斜率优化】

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 5005  Solved: 2455 [Submit][Sta ...

  5. bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)

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

  6. P3628 [APIO2010]特别行动队(斜率优化dp)

    P3628 [APIO2010]特别行动队 设$s[i]$为战斗力前缀和 显然我们可以列出方程 $f[i]=f[j]+a*(s[i]-s[j])^{2}+b*(s[i]-s[j])+c$ $f[i]= ...

  7. 【BZOJ】1911: [Apio2010]特别行动队(斜率优化dp)

    题目 传送门:QWQ 分析 用$ dp[i] $ 表示前 i 个人组成的战斗力之和 然后显然$ dp[i]=Max (  dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum ...

  8. _bzoj1911 [Apio2010]特别行动队【斜率优化dp】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 裸的斜率优化dp. #include <cstdio> const int ...

  9. bzoj 1911: [Apio2010]特别行动队【斜率优化dp】

    仔细想想好像没学过斜率优化.. 很容易推出状态转移方程\( f[i]=max{f[j]+a(s[i]-s[j])^2+b(s[i]-s[j])+c} \) 然后考虑j的选取,如果选j优于选k,那么: ...

  10. 【BZOJ 1191】 [Apio2010]特别行动队 (斜率优化)

    dsy1911: [Apio2010]特别行动队 [题目描述] 有n个数,分成连续的若干段,每段的分数为a*x^2+b*x+c(a,b,c是给出的常数),其中x为该段的各个数的和.求如何分才能使得各个 ...

随机推荐

  1. static特别用法【静态导包】——Java包的静态导入

    面试我问你static关键字有哪些作用,如果你答出static修饰变量.修饰方法我会认为你合格,答出静态块,我会认为你不错,答出静态内部类我会认为你很好,答出静态导包我会对你很满意,因为能看出你非常热 ...

  2. 03-命令图片.doc

  3. 转:Flutter Decoration背景设定(边框、圆角、阴影、形状、渐变、背景图像等)

    1 继续关系: BoxDecoration:实现边框.圆角.阴影.形状.渐变.背景图像 ShapeDecoration:实现四个边分别指定颜色和宽度.底部线.矩形边色.圆形边色.体育场(竖向椭圆).  ...

  4. Python 爬虫 解析库的使用 --- XPath

    一.使用XPath XPath ,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言.它最初是用来搜寻XML文档的,但是它同样适用于HTML文档的搜索. 所 ...

  5. java学习之—队列

    /** * 队列 * Create by Administrator * 2018/6/11 0011 * 下午 3:27 **/ public class Queue { private int m ...

  6. jenkins中通过execute shell启动的进程会被杀死的问题

    在jenkins中配置自动更新部署项目时,如果采取用execute shell启动/关闭tomcat,会发现可以进行关闭tomcat, 但是无法启动tomcat,虽然构建会显示执行成功,但是查看进程, ...

  7. linux 挂载windows下目录,其它linux机器nfs的目录,自己dd的文件

    如有转载,不胜荣幸.http://www.cnblogs.com/aaron-agu/ 挂载window下共享的目录 //192.168.0.11/share /mnt 挂载其它linux机器下目录 ...

  8. String 常见的十种方法!

    public class ZiFuChuan { public static void main(String[] args) { ZiFuChuanFangFa f=new ZiFuChuanFan ...

  9. 去掉AMD锐龙和Intel Kaby Lake的不支持的硬件的提示

    Windows 7和Windows 8.1都不支持AMD Ryzen 锐龙系列和Intel最新的Kaby Lake系列,Windows Update 更新之后总是会提示“不支持的硬件(Unsuppor ...

  10. How to remove popup on boot on Windows 2003

    Administrative Tools\Manage Your Server\Add or remove a role\Add or Remove Programs Local Computer P ...