您的位置:首页 > 其它

特别行动队 [APIO 2010]

2016-07-08 16:44 302 查看


分析 I Think

记 fi 表示前 i 个人的最大修正后的战斗力,依题意有 fi=max{fj+a∗(si−sj)2+b∗(si−sj)+c}=max{fj+a∗s2i+a∗s2j−2∗a∗si∗sj+b∗si−b∗sj+c}。设 a∗s2i+b∗si+c=r , fj+a∗s2j=y, sj=x ,2∗a∗si+b=k ,那么上式变成 fi=y−k∗x+r ,也就是 y=k∗x+fi−r 只是一条斜率一定的直线。就可以利用斜率优化将其优化至 O(n) 。

代码 Code

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

typedef long long LL;

const int Size = 1000047;

LL n;
LL a,b,c,tmp;
LL f[Size];
LL sum[Size];
int que[Size];
int H,T;

void read(LL &);
LL x(int,int);
LL y(int,int);

int main(){

read(n);
read(a);
read(b);
read(c);
for(int i=1;i<=n;++i){
read(tmp);
sum[i] = sum[i-1]+tmp;
}

f[0] = 0;
que[H=0] = 0;
T = 1;
for(int i=1;i<=n;++i){
while(H+1<T && y(que[H+1],que[H])>=x(que[H+1],que[H])*(b+2*a*sum[i]))
++H;
f[i] = f[que[H]]+a*(sum[i]-sum[que[H]])*(sum[i]-sum[que[H]])+b*(sum[i]-sum[que[H]])+c;
while(H+1<T && y(i,que[T-1])*x(que[T-1],que[T-2])>=y(que[T-1],que[T-2])*x(i,que[T-1]))
--T;
que[T++] = i;
}

printf("%lld",f
);

return 0;

}

void read(LL &_in){

_in = 0;
LL flag = 1;
char ch = getchar();

while(ch!='-' && (ch>'9'||ch<'0'))
ch = getchar();
if(ch == '-'){
flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9'){
_in = _in*10+ch-'0';
ch = getchar();
}

_in *= flag;

}

LL x(int i,int j){

return sum[i]-sum[j];

}

LL y(int i,int j){

return f[i]-f[j]+a*sum[i]*sum[i]-a*sum[j]*sum[j];

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  APIO