您的位置:首页 > 其它

HDU 3507 PrintArticle (单调队列优化)

2016-06-02 17:01 288 查看
题意:给出一个数列C,一个数字M,将数列分成若干段,每段的代价为(设这段的数字为k个):



dp[i]=min(dp[j]+(sum[i]-sum[j])*(sum[i]-sum[j])+M)

若j1<j2且j2比j1优

dp[j1]+sum[i]^2+sum[j1]^2-2*sum[i]*sum[j1]+M>dp[j2]+sum[i]^2+sum[j2]^2-2*sum[i]*sum[j2]

dp[j1]-dp[j2]+sum[j1]^2-sum[j2]^2>2*sum[i]*(sum[j1]-sum[j2])

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
int dp[500005],sum[500005],n,m,q[500005];
int getup(int j,int k){
return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];
}
int getdown(int x,int y){
return 2*(sum[x]-sum[y]);
}
int getdp(int i,int j){
return dp[j]+m+(sum[i]-sum[j])*(sum[i]-sum[j]);
}
int main(){
while (scanf("%d%d",&n,&m)==2){
for (int i=1;i<=n;i++){
scanf("%d",&sum[i]);
}
dp[0]=sum[0]=0;
for (int i=1;i<=n;i++)
sum[i]+=sum[i-1];
int h=0,t=0;
q[t++]=0;
for (int i=1;i<=n;i++){
while (h+1<t&&getup(q[h+1],q[h])<=sum[i]*getdown(q[h+1],q[h])) h++;
dp[i]=getdp(i,q[h]);
while (h+1<t&&getup(i,q[t-1])*getdown(q[t-1],q[t-2])<=getup(q[t-1],q[t-2])*getdown(i,q[t-1])) t--;
q[t++]=i;
}
printf("%d\n",dp
);}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: