您的位置:首页 > 其它

hdu 3507 斜率dp

2017-10-01 16:39 274 查看
传送门

设dp[i]表示输出前i个的最小费用,那么有如下的DP方程:

dp[i]= min{ dp[j]+(sum[i]-sum[j])^2 +M }  0<j<i

其中 sum[i]表示数字的前i项和。

#include<bits/stdc++.h>
using namespace std;

#define ll long long
#define mp make_pair
const int maxn = 5e5+10;

ll dp[maxn];

typedef pair <ll, ll> Line;
#define k first
#define b second
struct ConvexHull
{
Line stk[maxn];
int l, r;
void init(){ l = r = 0; }
//sz r - l [l,r)

bool cover(Line &a, Line &b, Line &c)
{
// line a and b cover line c
return (a.k - b.k) * (b.b - c.b) >= (b.b - a.b) * (c.k - b.k);
// >= 下凸包 求最小值
// <= 上凸包 求最大值
}

void add(Line p)
{
while(r - l > 1 && cover(p,stk[r-2],stk[r-1]))r--;
stk[r++] = p;
}

ll calc(ll x, Line l){ return l.k * x + l.b; }

ll ask(ll x)
{
while(r - l > 1 && calc(x,stk[l+1]) <= calc(x,stk[l]))l++;
return calc(x,stk[l]);
}
}hull;

#undef k
#undef b

ll sq(ll x){ return x*x; }

ll v[maxn];
ll sum[maxn];
int n,m;
int T;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
ll ans=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&v[i]);
sum[i]=sum[i-1]+v[i];
}
hull.init();
hull.add(mp(0,0));
for(int _=1;_<=n;_++)
{
dp[_]=sq(sum[_])+m+hull.ask(sum[_]);//常数
hull.add( mp(-2ll*sum[_],sq(sum[_])+dp[_]));//k b
}
printf("%lld\n",dp
);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: