【BZOJ-1911】特别行动队 DP + 斜率优化
2016-04-11 21:41
225 查看
1911: [Apio2010]特别行动队
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 3478 Solved: 1586
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4-1 10 -20
2 2 3 4
Sample Output
9HINT
Source
Solution
题意非常明显,将n个数划分成多段区间,使得总价值最大,每段区间的价值为$powersum=\sum power[i],ans=a*powersum^2+b*powersum+c$那么得出DP转移方程:$dp[i]=max(dp[j]+a*(pos[i]-pos[j])^2+b*(pos[i]-pos[j])+c)$
那么很显然不能AC,那么考虑优化一下时间
考虑斜率优化,对于转移到当前位置,最优解为$i$,如果满足任意$i<j$都有$i$更优那么就可以得到如下:
$(dp[j]-dp[i]+a*(pos[j]^2-pos[i]^2)+b*(pos[i]-pos[j]))/(2*a*(pos[j]-pos[i]))$那么维护一下即可
Code
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define maxn 1000100 int n,a,b,c; int po[maxn]; long long pos[maxn],dp[maxn]; int que[maxn],l,r; long long pf(long long x){return x*x;} double slope(int i,int j) { double fz=dp[j]-dp[i]+a*(pf(pos[j])-pf(pos[i]))+b*(pos[i]-pos[j]); double fm=(2*a*(pos[j]-pos[i])); return fz/fm; } int main() { n=read(); a=read(),b=read(),c=read(); for (int i=1; i<=n; i++) po[i]=read(),pos[i]=pos[i-1]+po[i]; for (int tmp,i=1; i<=n; i++) { while (l<r && slope(que[l],que[l+1])<pos[i]) l++; tmp=que[l]; dp[i]=dp[tmp]+a*pf(pos[i]-pos[tmp])+b*(pos[i]-pos[tmp])+c; while (l<r && slope(que[r-1],que[r])>slope(que[r],i)) r--; que[++r]=i; } printf("%lld\n",dp ); return 0; }
斜率优化好TAT..
相关文章推荐
- NFS
- 大数据时代的精准数据挖掘——使用R语言
- linux 下使用 tc 模拟网络延迟和丢包
- webservice 入门笔记五handler处理信息
- Hadoop 2.6.0集群的安装
- android照相、图片压缩
- 2016年大数据工程师必备的9项技能
- 算法--排序和查找
- 结对项目总结
- 商品管理数据表设计
- ios动画效果学习
- ios动画效果学习
- 数组对换位置
- Hdu oj 2066 一个人的旅行(floyd剪枝)
- Firemonkey 自定义Button的Style
- 2016年大数据工程师必备的9项技能
- 工厂三层结构环境的搭建
- 把Ubuntu用户目录下的目录名改成英文
- php循环生成的表单如何获得其各项值案例
- Whu 1604——Play Apple——————【博弈】