标签:
Description
有个元素,可以将个元素分成多组,每组的元素编号必须是连续的.
设每组的为,则每组的价值公式为.
求最大价值和.
Input
输入由三行组成。
第一行包含一个整数,表示士兵的总数.
第二行包含三个整数,价值公式中各项的系数.
第三行包含个用空格分隔的整数.
Output
输出一个整数,表示最大价值和。
Sample Input
4
-1 10 -20
2 2 3 4
Sample Output
9
HINT
Solution
表示前个的最大价值和,
.
这样是的,显然过不了,所以考虑斜率优化.
当且时,
尽量将分离:
设,
则,
.
的前提条件是
.
整理得,.
令 ,
则队列中的元素满足
(若存在,因为是递增的,所以比优,即可以删去),
所以每次取元素时,将满足的出队(因为比优),然后取队首为.
#include<set> #include<cmath> #include<ctime> #include<queue> #include<stack> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define N 1000001 using namespace std; typedef long long ll; ll f[N],s[N],q[N],a,b,c,n,h,t; inline ll sqr(ll k){ return k*k; } inline ll y(ll k){ return a*sqr(s[k])+b*s[k]+c; } inline ll g(ll k){ return f[k]+a*sqr(s[k])-b*s[k]; } inline ll func(ll k){ return a*sqr(k)+b*k+c; } inline double cmp(ll p,ll q){ return (double)(g(q)-g(p))/(double)(s[q]-s[p]); } inline void init(){ scanf("%lld%lld%lld%lld",&n,&a,&b,&c); for(ll i=1;i<=n;i++){ scanf("%lld",&s[i]); s[i]+=s[i-1]; } for(ll i=1,k;i<=n;i++){ k=(a<<1)*s[i]; while(h<t&&cmp(q[h],q[h+1])>k) h++; f[i]=f[q[h]]+func(s[i]-s[q[h]]); while(h<t&&cmp(q[t],i)>cmp(q[t-1],q[t])) t--; q[++t]=i; } printf("%lld\n",f[n]); } int main(){ freopen("commando.in","r",stdin); freopen("commando.out","w",stdout); init(); fclose(stdin); fclose(stdout); return 0; }
标签:
原文地址:http://www.cnblogs.com/AireenYe/p/5934065.html