返回顶部
大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

Print Article HDU - 3507

一道斜率dp入门题

Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate this degree.
One day Zero want to print an article which has N words, and each word i has a cost Ci to be printed. Also, Zero know that print k words in one line will cost

M is a const number.
Now Zero want to know the minimum cost in order to arrange the article perfectly.

InputThere are many test cases. For each test case, There are two numbers N and M in the first line (0 ≤ n ≤ 500000, 0 ≤ M ≤ 1000). Then, there are N numbers in the next 2 to N + 1 lines. Input are terminated by EOF.OutputA single number, meaning the mininum cost to print the article.Sample Input
5 5
5
9
5
7
5
Sample Output
230

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1e6+10;

int n,tail,head,q[maxn],m;

ll f[maxn],sum[maxn];

double g(int k2,int k1) {
    return double(f[k1]-f[k2]+sum[k1]*sum[k1]-sum[k2]*sum[k2])/double(2*sum[k1]-2*sum[k2]);
}

int main() {
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++) {
            scanf("%lld",&sum[i]);sum[i]+=sum[i-1];
            if(sum[i]==sum[i-1]) i--,n--;//不加会错。。
        }
        head=tail=1;f[0]=0;
        for(int i=1;i<=n;i++) {
            int k1=q[head],k2=q[head+1];
            while(head<tail&&g(k1,k2)<=sum[i]) 
            head++,k1=q[head],k2=q[head+1];
            f[i]=f[k1]+(sum[i]-sum[k1])*(sum[i]-sum[k1])+m;
            while(head<tail&&g(q[tail-1],q[tail])>=g(q[tail],i)) tail--;
            q[++tail]=i;
        }
        printf("%lld\n",f[n]);
    }
    return 0;
}

 

posted @ 2019-04-26 15:13  plysc  阅读(156)  评论(0编辑  收藏  举报