BZOJ 3156: 防御准备 斜率优化DP

3156: 防御准备

Description

Input

第一行为一个整数N表示战线的总长度。

第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。

Output

共一个整数,表示最小的战线花费值。

Sample Input

10
2 3 1 5 4 5 6 3 1 2

Sample Output

18

HINT

1<=N<=10^6,1<=Ai<=10^9

题解:

  斜率优化DP;

  首先将数组倒置

  设定dp[i] 为前i的点的最优答案

  易得

    dp[i] = min{dp[j]+(i-j-1)*(i-j)/2}+a[i]; 1<=j<i;

  

  注意最后答案dp[n+1]

  

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e6+20,inf = 2e9, mod = 1e9+7;
typedef long long ll;

ll dp[N];
ll n,a[N],b[N];
double getsum(ll k,ll j)
{
    return (double)((dp[k]-dp[j]) + (double)(k*k+k-j*j-j)/2.0)/(double)(k-j);
}
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&b[i]);
    }
    for(int i=1;i<=n;i++)
    {
        a[i]=b[n-i+1];
    }
    deque<int > q;
    dp[1] = a[1];
    q.push_back(1);
    for(int i=2;i<=n+1;i++)
    {
        int now=q.front();q.pop_front();
        while(!q.empty()&&getsum(q.front(),now)<i) now=q.front(),q.pop_front();
        q.push_front(now);
        dp[i] = dp[now] + (ll)(i-now-1)*(ll)(i-now)/2 + a[i];
        now = q.back();q.pop_back();
        while(!q.empty()&&getsum(i,now)<getsum(now,q.back())) now=q.back(),q.pop_back();
        q.push_back(now);
        q.push_back(i);
    }
    printf("%lld\n",dp[n+1]);

    return 0;
}
时间: 2024-10-27 07:33:51

BZOJ 3156: 防御准备 斜率优化DP的相关文章

[BZOJ3156]防御准备 斜率优化DP

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3156 裸的斜率优化,记一下以后复习用吧. 要直接dp很明显应该要倒着dp,很不爽,先把它倒过来. 令$sum[j]=\sum_{i=1}^ji$,于是我们首先推出这样一个方程$$f[i]=min\{f[j]+sum[i-1]-sum[j]-(i-j-1)*j+a[i]\}$$ 这样dp复杂度是$O(n^{2})$的,考虑斜率优化. 设$k>j$,且$k$优于$j$,则有$$f[k]+su

BZOJ - 1010【斜率优化DP】

1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 9961  Solved: 4056[Submit][Status][Discuss] Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压 缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过 压缩后变成一维长度为Ci.为了方便整理

【BZOJ3156】防御准备 斜率优化DP

老规矩,方程什么都在注释里面. 呃,其实写斜率优化不妨像我这么写,先把会TLE的裸dp交一遍,T了以后就把方程去掉(long long)这种类型转化神马的粘到注释里面,然后j放一边,i放一边,都有的放到i的一边,然后列出yxkb,然后最大上凸,最小下凹,简单分析,不对再改,然后来俩点判断判断叉积神马的,然后一遍ac. 嘲讽一下:某同学POJ一道题调了一天至今还没过..代码风格啊... 不会斜率优化的往我博客分类里其它博客翻. #include <cstdio> #include <cst

斜率优化专题3——bzoj 3156 防御准备 题解

[原题] 3156: 防御准备 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 198  Solved: 107 [Submit][Status] Description Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战线花费值. Sample Input 10 2 3 1 5 4 5 6 3 1 2 Sample Output 18 HINT

bzoj 3156 防御准备(斜率DP)

3156: 防御准备 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 837  Solved: 395[Submit][Status][Discuss] Description Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Output 共一个整数,表示最小的战线花费值. Sample Input 10 2 3 1 5 4 5 6 3 1 2 Sample Output 18 HIN

[bzoj 1911][Apio 2010]特别行动队(斜率优化DP)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(Si-Sj)+c} 0<j<i 简化一下方程,我们知道对于一次项,最后结果肯定是b*Sn 所以可以写成f[i]=max{f[j]+a*(Si-Sj)^2+c} 0<j<i 我们不妨设0<x<y<i,且x比y优 即f[x]+a*(Si-Sx)^2+c>f[y]+a*

bzoj 3437 斜率优化DP

写题解之前首先要感谢妹子. 比较容易的斜率DP,设sum[i]=Σb[j],sum_[i]=Σb[j]*j,w[i]为第i个建立,前i个的代价. 那么就可以转移了. 备注:还是要感谢妹子. /************************************************************** Problem: 3437 User: BLADEVIL Language: C++ Result: Accepted Time:3404 ms Memory:39872 kb **

BZOJ 1096 [ZJOI2007]仓库建设 斜率优化dp

1096: [ZJOI2007]仓库建设 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚. 由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天,L公司的总裁L先生接到气象部门的电话,被告知三天之后将有一场

BZOJ 1096 ZJOI2007 仓库设计 斜率优化dp

太高兴了,这是我第一次自己独立思考的斜率优化dp,从头到尾都是自己想的.(相信自己,能行的,不过也做了40分钟了). 这道题目还好吧! 看到之后第一反应是想设从工厂0运到工厂i 总共需要 tot[i] 的费用, 用 p[i] 表示从山顶到工厂 i 总共的产品数, 再用 x[i] 表示从工厂0到工厂 i 的距离, 那么状态转移方程就是 f[i] = min{f[j] + tot[i] - tot[j] - p[j] * (x[i] - x[j] ) + c[i] } ,很明显由于数据有 n <=