题目描述

给你一个数列,让你将这个数列分成若干段,使其每一段的和的\(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. 文本文档中各字母出现次数汇总(java)

    package 字母频率统计; import java.io.*; public class Inputfile { public static void main(String args[]) { ...

  2. CentOS 6.5 手动rpm包安装gcc、g++

    摘自:https://blog.csdn.net/lichen_net/article/details/70211204 mount CentOS的安装光盘,然后先后安装 rpm -ivh ppl-0 ...

  3. PHP的优化建议(仅借鉴)

    转载: https://www.awaimai.com/1050.html 1 字符串 1.1 少用正则表达式 能用PHP内部字符串操作函数的情况下,尽量用他们,不要用正则表达式, 因为其效率高于正则 ...

  4. 重启iis命令

    iisreset

  5. Some beautiful Progress Bars in WPF

    1.Better WPF Circular Progress Bar 2.Bending the WPF ProgressBar 3.A CIRCULAR PROGRESSBAR STYLE USIN ...

  6. 关于 ajax

    1.type 提交类型 get /post 2.async 默认true 异步 3.cache 默认 true 读取缓存 false不读取缓存  会在请求后面 添加一个时间戳 https://www. ...

  7. kibana——es的批量操作

    一·_mget: 1.创建的索引如下: 2.批量查询: #查询两个 GET _mget { "docs":[ { "_index":"testdb&q ...

  8. linux下更改MySQL数据库存储路径

    参考地址:1.https://blog.csdn.net/ArnoBM/article/details/83008212 2.http://www.cnblogs.com/lyongde/p/3725 ...

  9. VS2017设置背景主题

    一.VS2017设置背景主题 1.下载并安装Color Theme Editor for Visual Studio 2017和MoeIDE (图中红圈中的两个插件,工具-扩展和更新-联机-右上角搜索 ...

  10. PHPStorm 配置命名空间

    文件-设置-Directories 选中:application     点击顶部:Sources,右侧会出现 Source Floders 配置项 点击:p进行设置 输入app\