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])
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; }
相关文章推荐
- (四)MyBatis源码解析之SqlSession
- 文章标题
- IIS集群+分布式缓存
- 使用VC++6.0 MFC OLE操作Excel 进行简单的读写
- 常用日期处理方法工具类
- 浅析java的浅拷贝和深拷贝
- wordpress通过$wpdb获取一个分类下所有的文章
- 补作业:随机生成二元四则运算
- C++ 常用的字符串处理函数实现
- leetcode 31. Next Permutation
- 邮件审批工作流实现方案
- 创建属于你的SDK!
- windows下openGLES 3.0 配合 vs 环境搭建(二)
- ubuntu设置自定义程序开机启动(本文以tomcat为例)
- 如果不知道MySQL当前使用配置文件(my.cnf)的路径的解决方法
- Linux命令:ps / top
- 分数类中的运算符重载
- 分数类中的运算符重载
- 分数类中的运算符重载
- 分数类中的运算符重载