BZOJ 1911: [Apio2010]特别行动队 斜率优化dp-程序员宅基地

技术标签: php  数据结构与算法  

1911: [Apio2010]特别行动队

题目连接:

http://www.lydsy.com/JudgeOnline/problem.php?id=1911

Description

有n个数,然后你需要把这n个数分成若干段,每段的权值是a*sum*sum+b*sum+c

问你怎么切,使得权值和最大

sum表示该区间的权值和

Input

三行 n,a,b,c 然后n个数,表示每个数的权值

Output

答案

Sample Input

4

-1 10 -20

2 2 3 4

Sample Output

9

数据范围n,b,c为1e6,a为5

Hint

题意

题解:

斜率优化dp

n^2 dp很显然,dp[i] = max(dp[j]+w[i][j])

这个模式比较显然的是斜率优化dp的模式

方程,假设i>j,且i优于j,则可以化为 dp[i]-dp[j]+a*(sum[i]*sum[i]-sum[j]*sum[j])+b*(sum[j]-sum[i]) / 2*a*(sum[i]-sum[j]) <sum[i]

然后斜率优化dp跑一波就好了

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int n;
long long a,b,c;
long long x;
long long sum[maxn];
long long dp[maxn];
double slope(int i,int j)
{
    double up = dp[i]-dp[j]+a*(sum[i]*sum[i]-sum[j]*sum[j])+b*(sum[j]-sum[i]);
    double down = 2*a*(sum[i]-sum[j]);
    return up/down;
}
int l,r,q[maxn];
int main()
{
    scanf("%d",&n);
    scanf("%lld%lld%lld",&a,&b,&c);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&x);
        sum[i]=sum[i-1]+x;
    }
    for(int i=1;i<=n;i++)
    {
        while(l<r&&slope(q[l+1],q[l])<sum[i])l++;
        int now = q[l];
        dp[i]=dp[now]+a*(sum[i]-sum[now])*(sum[i]-sum[now])+b*(sum[i]-sum[now])+c;
        while(l<r&&slope(q[r],q[r-1])>slope(i,q[r]))r--;
        q[++r]=i;
    }
    printf("%lld\n",dp[n]);
}

转载于:https://www.cnblogs.com/qscqesze/p/5179656.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30340775/article/details/96244681

智能推荐

将一个文件夹内的所有文件名包括子目录的文件名遍历出来PHP_一个包里的所有文件名列表-程序员宅基地

<?phpfunction my_dir($dir) { $files = array(); if(@$handle = opendir($dir)) { //注意这里要加一个@,不然会有warning错误提示:) while(($file = readdir($handle)) !== false) { if($file != "...._一个包里的所有文件名列表

VSCode中创建自己的模板(vue初学模板,node初学模板)_vscode node模板-程序员宅基地

17:36生成自定义模板File ???? Prefereces ???? User Snippets出现如图界面(红色是我已经创建的模板),点击蓝色创建自己的模板输入你模板的名字test 就是我的模板名,根据绿色注释部分 “Example”可以以此类推自定义自己的模板以一个 node 初学简单的模板为例回车后生成如下所示代码:{"c..._vscode node模板

【Endnote】如何在参考文献前加编号 (1.2.3.等 或 [1] [2] [3]等)_endnote参考文献[1][2][3]如何标注-程序员宅基地

步骤如下:1. Edit菜单下的Output Styles,点击Edit “XXX”(XXX为你要编辑的endnote模板)12. 选择 左侧的Bibliography 下的“Layout”,注意右侧的“Start reference with:”2若是空白,则表明你的文献前没有序号。选择如下设置(二选一)并保存。(1)在文献前加入编号 1. 2. 3.等。在“Star..._endnote参考文献[1][2][3]如何标注

PJSIP2.7 Android版本编译及构建pjsua2和pjsua_pjsua2 java编译-程序员宅基地

本人使用的环境:Ubuntu14.0.4 (DigitalOcean 虚拟主机,笔者使用移动宽带选择Singapore节点80ms 左右延迟,推荐链接https://m.do.co/c/1399118d3ab5) 笔者按照PJSIP Android版本的官方编译说明操作,遇到了部分问题。特别是如Android SDK 依赖问题,按照说明(https://developer.android._pjsua2 java编译

java不区分大小写的map集合-程序员宅基地

1.一个项目经过多人开发,有时传值就会不注意大小写,导致常用方法必须传两遍,传一遍大写,传一遍小写,字段一多就会很麻烦,为了节省时间,可以使用下面的集合:CaseInsensitiveMap—不区分大小写的无序map;LinkedCaseInsensitiveMap—不区分大小写的有序map;例如:import org.apache.commons.collections.map..._不区分大小写的map

283. Move Zeroes-程序员宅基地

题目描述(简单难度)将所有的 0 移动到末尾,并且保持其他数字的相对顺序不变。解法一我的第一反应是利用两个指针,一个指针指向开头,一个指针指向末尾非零元素,然后从开头指针遍历,如果遇到 0 就和末尾指向的元素相交换,末尾指针向前移动到非零元素。这就保证末尾指针后边元素全部是 0,当首尾指针相遇的时候结束。但是上边的想法会使得其他数字的相对顺序改变了,我们可以逆转一下思路。不是将0 放到末尾,而是将所有非零元素放到开头,这样就保证末尾剩下的都是 0 了。同样利用双指针,指针 i 用于遍历数组,指

随便推点

八数码(哈希表判重)-程序员宅基地

#include<iostream>#include<cstring>#include<stack>#include<cstdio>using namespace std;const int maxn=1000000;//状态最大不超过9!,这里设置大一点int dx[]={-1,1,0,0...

Logstash配置——变量的使用-程序员宅基地

前置条件:Linux Logstash 5.5.0(其他版本请查阅一下文档) 使用logstash把日志从文件输出到文件,根据输入文件的路径,确定输出文件的文件名。配置如下: input { stdin{} file { path => "/tmp/a..._logstash 变量

面向对象详讲(上)_面对对象景区门票-程序员宅基地

面向对象上篇*## 1.类与对象1.1看一个养猫猫问题1.2 java语言是面向对象的计算机语言的发展向接近人的思维方式演变(能编写功能更多软件):汇编语言 [面向机器] 有助记符 load return …c语言 [面向过程] 函数=> 完成功能java语言 [面向对象] 类与对象 => 编写更加复杂,大型软件 汇编语言(汇编 不会编,不会编汇编)=> 驱动程序1.3类与对象的关系示意图1.4 快速入门-面向对象的方式解决养猫问_面对对象景区门票

linux 下检查java jar包 程序是否正常 shell-程序员宅基地

echo "服务正常"else echo "服务异常"fi _linux 如何检查jar是否损坏

FFmpeg FFmpeg的使用及常用参数-程序员宅基地

FFmpeg的使用及常用参数一.下载:官网:http://ffmpeg.org/二.demo: 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 string srcFileName = @"F:\资料\Demo\...