APIO2010 特别行动队 & 斜率优化DP算法笔记
2015-07-07 13:18
274 查看
做完此题之后 自己应该算是真正理解了斜率优化DP
根据状态转移方程$f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j]$
可以变形为 $f[i]=max((a*sum[j]^2-b*sum[j])-(2a*sum[j]*sum[i]))+(a*sum[i]^2+b*sum[i]+c)$
我们可以把每个决策映射到平面上的一个点
其中坐标$x=(a*sum[j]^2-b*sum[j])$代表此决策的固定价值(与转移到哪无关)
坐标$y=(-2a*sum[j])$代表此决策的潜在价值(与转移到哪有关)
这样我们就可以开始用单调队列维护一个$x$递增 $y$递减的凸壳
------------------------------------------------------------------------
对于每次加入进来的一个新元素
我们先对队首的两个决策进行判断 若某决策现有价值不如后面的决策则将其删去
(因为维护的单调队列中的决策潜在价值是递增的)
然后更新新加的元素的最大值
再对新加元素与队尾的两个决策间进行判断
如果队尾第一个的决策在新加决策和前面所有决策所构成凸壳之内
那么这个决策永远不可能同时优于前一个决策和新加决策 所以就直接删掉就好了
最后将新加的决策加入单调队列
根据状态转移方程$f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j]$
可以变形为 $f[i]=max((a*sum[j]^2-b*sum[j])-(2a*sum[j]*sum[i]))+(a*sum[i]^2+b*sum[i]+c)$
我们可以把每个决策映射到平面上的一个点
其中坐标$x=(a*sum[j]^2-b*sum[j])$代表此决策的固定价值(与转移到哪无关)
坐标$y=(-2a*sum[j])$代表此决策的潜在价值(与转移到哪有关)
这样我们就可以开始用单调队列维护一个$x$递增 $y$递减的凸壳
------------------------------------------------------------------------
对于每次加入进来的一个新元素
我们先对队首的两个决策进行判断 若某决策现有价值不如后面的决策则将其删去
(因为维护的单调队列中的决策潜在价值是递增的)
然后更新新加的元素的最大值
再对新加元素与队尾的两个决策间进行判断
如果队尾第一个的决策在新加决策和前面所有决策所构成凸壳之内
那么这个决策永远不可能同时优于前一个决策和新加决策 所以就直接删掉就好了
最后将新加的决策加入单调队列
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #define rep(i,n) for(int i=1;i<=n;++i) #define imax(x,y) (x>y?x:y) #define imin(x,y) (x<y?x:y) using namespace std; const int N=1000010; int sum ,q ; long long f ; int n; long long a,b,c; long long solve(int x,int y) { return f[x]+a*(sum[y]-sum[x])*(sum[y]-sum[x])+b*(sum[y]-sum[x])+c; } long long solvex(int x) { return f[x]+a*sum[x]*sum[x]-b*sum[x]; } bool judge(int x,int y,int z) { long long tx=solvex(x),ty=solvex(y),tz=solvex(z); return (ty-tx)*(sum[z]-sum[x])<=(tz-tx)*(sum[y]-sum[x]);//约掉了-2a } int main() { scanf("%d",&n); scanf("%lld%lld%lld",&a,&b,&c); rep(i,n) { scanf("%d",&sum[i]); sum[i]+=sum[i-1]; } int ifront=1,itail=1; q[1]=0; rep(i,n) { while(ifront<itail&&solve(q[ifront],i)<=solve(q[ifront+1],i)) ++ifront; f[i]=solve(q[ifront],i); while(ifront<itail&&judge(q[itail-1],q[itail],i)) --itail; q[++itail]=i; } printf("%lld",f ); return 0; }
相关文章推荐
- TCP状态迁移,CLOSE_WAIT & FIN_WAIT2 的问题
- 中国“互联网+酒店”专题研究报告2015
- 我来了
- 阿里巴巴2016秋招内部推荐-B2B快速通道
- Maven最佳实践:版本管理
- 获取网卡信息
- 如何吸引流量,就一个字!
- 百度之星资格赛 J题 百度的新大厦
- SQL Server 快速获取表的行数
- 牙齿保健的小方法
- android中的Handler
- 百度之星资格赛 E题 C++ 与Java
- jboss相关error以及解决方案
- linux的gz解压缩
- 彻底卸载mysql的方法
- linux学习笔记 (十五)less命令
- invalid initialization of non-const reference of type与discards qualifiers
- PostgreSQL-9.1安装与配置详解
- C语言之基本算法15—前三位和后三位都是完全平方数的六位完全平方数
- dos批处理文件中使用vbs