特别行动队题解

特别行动队题解

刷水题什么的最愉快了。
题意十分明了,就是选出一种分配方案将士兵分为若干组,使修正后的战斗力最大。
我们先可以写出暴力dp转移:
\(f[n]\)为将前\(i\)个士兵分组,且第\(i\)个士兵为最后一组最后一个的最大战斗力。
\(f[i]=max_{j=1}^{j
时间复杂度:\(O(n^3)\)
设前缀和\(sum[i]=\sum_{j=1}^{j<=i}x[j]\)
则化为:\(f[i]=max_{j=1}^{j
最后斜率优化一下:
拆开平方,移项:
\(f[i]-a*sum[i]*sum[i]-b*sum[i]-c+2*sum[i]*sum[j]=f[j]+a*sum[j]*sum[j]-b*sum[j]\)
其中:
\(\bullet y=f[j]+a*sum[j]*sum[j]-b*sum[j]\)
\(\bullet k=2*sum[i]\)
\(\bullet x=sum[j]\)
\(\bullet b=f[i]-a*sum[i]*sum[i]-b*sum[i]-c\)
\(\therefore f[i]=y-kx+a*sum[i]*sum[i]+b*sum[i]+c\)
特别行动队题解_第1张图片
代码:

#include
#define ll long long 
using namespace std;
const int N=1000006;
int n,head=1,tail=1;
ll f[N],sum[N],ans=0,a,b,c,t;
struct point{ll x,y;}tmp,q[N];
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T; 
}
bool check(point u,point v,int z){return v.y-u.y>=2*a*sum[z]*(v.x-u.x);}
bool check2(point u,point v,point z){return (v.y-u.y)*(z.x-v.x)<=(z.y-v.y)*(v.x-u.x);}
int main(){
    n=read(),a=read(),b=read(),c=read();
    q[tail].x=0,q[tail].y=0;
    for(int i=1;i<=n;++i){
        t=read(),sum[i]=sum[i-1]+t;
        while(head

你可能感兴趣的:(特别行动队题解)