您的位置:首页 > 其它

bzoj1911 [Apio2010]特别行动队

2017-09-10 19:32 169 查看
题目

又是一道非常标准的斜率优化。

一开始还以为需要讨论a来判断是维护上凸包还是下凸包,233。又看了眼数据范围,a一定小于0,嗯,这就轻松多了。

for(int i=1;i<=n;i++)A[i]=read();
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+A[i];
for(int i=1;i<=n;i++)
for(int j=0;j<i;j++)
f[i]=max(f[i],f[j]+func(sum[i]-sum[j]));
cout<<f
;


n^2转移,再推一推公式,

斜率为

(double)(f[i]-f[j]+b*(sum[j]-sum[i])+a*(sum[i]sum[i]-sum[j]*sum[j]))/(double)(2*a(sum[i]-sum[j])),好长啊

#include<bits/stdc++.h>
#define LL long long
#define N 1000000
using namespace std;
LL n,a,b,c;
LL A[N+1],sum[N+1];
LL f[N+1],l,r,q[N+1];
inline char nc(
4000
)
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline LL read()
{
LL x=0,f=1;
char c=nc();
while((c<'0'||c>'9')&&c!='-')c=nc();
if(c=='-')f=-1,c=nc();
while(c<='9'&&c>='0')x=x*10+c-'0',c=nc();
return x*f;
}
LL func(LL x)
{
return a*x*x+b*x+c;
}
double slope(int i,int j)
{
return (double)(f[i]-f[j]+b*(sum[j]-sum[i])+a*(sum[i]*sum[i]-sum[j]*sum[j]))/(double)(2*a*(sum[i]-sum[j]));
}
int main()
{
n=read();
a=read(),b=read(),c=read();
for(int i=1;i<=n;i++)A[i]=read();
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+A[i];
//  for(int i=1;i<=n;i++)
//      for(int j=0;j<i;j++)
//          f[i]=max(f[i],f[j]+func(sum[i]-sum[j]));
//  cout<<f
;
l=1,r=0,q[++r]=0;
for(int i=1;i<=n;i++)
{
while(l<r&&slope(q[l+1],q[l])<=sum[i])l++;
int tmp=q[l];
f[i]=f[tmp]+a*(sum[i]-sum[tmp])*(sum[i]-sum[tmp])+b*(sum[i]-sum[tmp])+c;
while(l<r&&slope(i,q[r])<slope(q[r],q[r-1]))r--;
q[++r]=i;
}
cout<<f
;
return 0;
}


貌似还有一种斜率不是单调的,十分毒瘤,要用CDQ分治之类的,我还是不会233
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: