P3628 [APIO2010]特别行动队
P3628 [APIO2010]特别行动队
本蒟蒻的第二道斜率优化的
首先还是写出一个
for(int i=1;i<=n;i++)
for(int j=0;j<i;j++)
dp[i]=max(dp[i],dp[j]+f(sum[i]-sum[j]));
其中
期望
怎么办?
斜率优化!
假设
把
移项得:
除过去搞一下:
然后就可以直接搞了。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 1000010
using namespace std;
int n;
long long a,b,c;
long long sum[MAXN],dp[MAXN];
int head,tail,que[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline long long f(long long x){
return a*x*x+b*x+c;
}
inline double slope(int x,int y){
return (double)((((dp[y]-dp[x])*1.0/(sum[y]-sum[x])-b)*1.0/a)+(sum[x]+sum[y])*1.0);
}
void work(){
head=1;tail=1;
for(int i=1;i<=n;i++){
while(head<tail&&slope(que[head],que[head+1])<=2.0*sum[i])head++;
dp[i]=f(sum[i]-sum[que[head]])+dp[que[head]];
while(head<tail&&slope(que[tail],i)<=slope(que[tail-1],que[tail]))tail--;
que[++tail]=i;
}
printf("%lld\n",dp[n]);
}
void init(){
n=read();a=read();b=read();c=read();
sum[0]=0;
for(int i=1;i<=n;i++){
int x=read();
sum[i]=sum[i-1]+x;
}
}
int main(){
init();
work();
return 0;
}