zoukankan      html  css  js  c++  java
  • 特别行动队

    https://loj.ac/problem/10190

    题目描述

      有(n)个士兵,每个士兵有一定的战斗力,分为若干支特别行动队,每支行动队内的士兵编号连续,令(x=sum x_i),那么这支特别行动队的战斗力为(ax^2+bx+c),求最大战斗力。

    思路

      考虑用(f[i])表示前(i)个人能到达的战斗力,那么方程比较简单,就是把(k+1sim j)分为一组

    [f[i]=min{f[j]+a(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c} ]

      我们尝试把这个式子化为与(j)相关的一次函数

    [f[j]+a*sum[j]^2=(2*a*sum[i]+b)*sum[j]-a*sum[i]^2-b*sum[i]-c ]

      对于这个式子我们显然可以用斜率优化优化为(O(N))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=1e6+10;
    
    ll read()
    {
    	ll res=0,w=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    	return res*w;
    }
    
    ll a,b,c,sum[N],f[N],q[N];
    ll Y(ll x){return f[x]+a*sum[x]*sum[x];}
    ll K(ll x){return 2*a*sum[x]+b;}
    ll X(ll x){return sum[x];}
    int main()
    {
    	ll n=read();
    	a=read(),b=read(),c=read();
    	for(ll i=1;i<=n;i++)
    		sum[i]=sum[i-1]+read();
    	ll l=0,r=0;
    	for(ll i=1;i<=n;i++)
    	{
    		while(l<r&&(Y(q[l+1])-Y(q[l]))>=K(i)*(X(q[l+1])-X(q[l])))l++;
    		ll x=sum[i]-sum[q[l]];
    		f[i]=f[q[l]]+a*x*x+b*x+c;
    		while(l<r&&(Y(q[r])-Y(q[r-1]))*(X(i)-X(q[r]))<=(Y(i)-Y(q[r]))*(X(q[r])-X(q[r-1])))r--;
    		q[++r]=i;
    	}
    	printf("%lld",f[n]);
    }
    
  • 相关阅读:
    分享一份Java架构师学习资料,2019年最新整理!
    Spring Boot 最核心的 25 个注解,都是干货!
    推荐一款接口 API 设计神器!
    题库
    杂乱的知识点
    mysql查询疯狂41例
    mysql你问我答
    可能出现的面试题
    SQLALchemy
    基于蓝图的完整的Flask项目
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11853495.html
Copyright © 2011-2022 走看看