zoukankan      html  css  js  c++  java
  • BZOJ 1911 特别行动队 (斜率优化)

    $ BZOJ~1911~*~ $ 特别行动队: (斜率优化)



    $ solution: $

    感觉这道题目还是比较常规的,首先我们很容易想到DP,因为题目里面说了选出的人都是连续的,这意味着我们可以从前往后DP。我们直接设 (f[i]) 表示前 (i) 在分组之后的战斗力之和(因为题目没有明确要求分几组,所以我们省去这一维度)。然后转移也比较常规,我们枚举前面的某一个人 (k) 作为这一组人的左端点(右端点就是第 (i) 个人)。这题数据范围很大,我们也不用着急,现将式子列出来,如果转移不能优化再另寻他法。(事实上这种没有性质的DP,优化只能靠转移方程)

    转移方程:

    $ F[i]=F[k]+a imes (S[i]-S[k])^2+b imes(S[i]-S[k])+c $

    把这个式子拆开你就会看到一个与 (i,k) 都有关的乘积项,这是斜率优化的标志:

    $ F[i] = F[k] + a imes S[i]^2 - 2a imes S[i] imes S[k] + a imes S[k]^2+b imes S[i] - b imes S[k] + c $

    然后我们将同一类的项移动到一起,化为斜率优化的标准式:

    $ F[k] + a imes S[k]^2 - b imes S[k] = + 2a imes S[i] imes S[k] + F[i] -a imes S[i]^2 - b imes S[i] - c $

    然后我们将 乘积项(2a imes S[i] imes S[k]) 里面有关于 (k)(S[k]) 作为横坐标(自变量) ,然后等式右边有关 (k) 的项 (F[k] + a imes S[k]^2 - b imes S[k]) 作为纵坐标(应变量)。然后我们要 (F[i]) 最大,其实就是让截距 (F[i] -a imes S[i]^2 - b imes S[i] - c) 最大。于是直接斜率优化即可。



    $ code: $

    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    
    #define ll long long
    #define db double
    #define rg register int
    
    using namespace std;
    
    int n;
    ll a,b,c;
    int s[1000005];
    int q[1000005];
    ll g[1000005];
    ll f[1000005];
    
    inline int qr(){
    	register char ch; register bool sign=0; rg res=0;
    	while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    	while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    	if(sign)return -res; else return res;
    }
    
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	n=qr(); a=qr(); b=qr(); c=qr(); rg l=1,r=0;
    	for(rg i=1;i<=n;++i) s[i]=s[i-1]+qr();
    	for(rg i=1;i<=n;++i){  q[++r]=i-1;
    		while(l<r&&g[q[l+1]]-g[q[l]]>=2*a*s[i]*(s[q[l+1]]-s[q[l]]))++l;
    		rg x=s[i]-s[q[l]];
    		f[i]=f[q[l]]+a*x*x+b*x+c;
    		g[i]=f[i]+a*s[i]*s[i]-b*s[i];
    		while(l<r&&(g[q[r]]-g[q[r-1]])*(s[i]-s[q[r]])<=(g[i]-g[q[r]])*(s[q[r]]-s[q[r-1]]))--r;
    	}printf("%lld
    ",f[n]);
    	return 0;
    }
    
    
  • 相关阅读:
    383. Ransom Note
    598. Range Addition II
    453. Minimum Moves to Equal Array Elements
    492. Construct the Rectangle
    171. Excel Sheet Column Number
    697. Degree of an Array
    665. Nondecreasing Array
    视频网站使用H265编码能提高视频清晰度吗?
    现阶段的语音视频通话SDK需要解决哪些问题?
    企业远程高清会议平台视频会议系统在手机端使用的必备要求有哪些?
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/11213565.html
Copyright © 2011-2022 走看看