您的位置:首页 > 其它

BZOJ 1911 [APIO2010]特别行动队

2017-08-14 19:42 253 查看
题目描述



因为是从别人博客里斜率优化分类一栏找的题目,所以…这题被我秒了。

显然先预处理前缀和s(i)=∑ik=1xi

设d(i)为将前i个士兵分组的最大修正后战斗力。

d(i)===max{ d(j)+a(s(i)−s(j))2+b(s(i)−s(j))+c }max{ d(j)+a×s(i)2−2a×s(i)s(j)+a×s(j)2+b×s(i)−b×s(j)+c }max{ d(j)−2a×s(i)s(j)+a×s(j)2−b×s(j) }+a×s(i)2+b×s(i)+c



KiXjBiYj====2a×s(i)s(j)d(i)−a×s(i)2−b×s(i)−cd(j)+a×s(j)2−b×s(j)

直线解析式为KiXj+Bi=Yj其中斜率Ki单减,Xj单增。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#define k(A) (2*a*s[A])
#define x(A) s[A]
#define b(A) (d[A]-a*s[A]*s[A]-b*s[A]-c)
#define y(A) (d[A]+a*s[A]*s[A]-b*s[A])
using namespace std;
const int maxn=1000010;
long long d[maxn],s[maxn];
int q[maxn],n,a,b,c;
double slope(int i,int j){
return 1.0*(y(i)-y(j))/(x(i)-x(j));
}
int main(){
cin>>n>>a>>b>>c;
s[0]=q[0]=d[0]=0;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
s[i]=s[i-1]+x;
}
int head=0,tail=0;
for(int i=1;i<=n;i++){
while(head<tail&&slope(q[head],q[head+1])>k(i)) head++;
d[i]=-(k(i)*x(q[head])-y(q[head])-a*s[i]*s[i]-b*s[i]-c);
while(head<tail&&slope(q[tail-1],q[tail])<=slope(q[tail],i)) tail--;
q[++tail]=i;
}
cout<<d
<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: