zoukankan      html  css  js  c++  java
  • 【bzoj1911】 Apio2010—特别行动队

    http://www.lydsy.com/JudgeOnline/problem.php?id=1911 (题目链接)

    题意

      给出一个序列,将序列分成连续的几段,每段的价值为a*s*s+b*s+c,其中a,b,c为给定常数,s为这一段中所有数之和。求最大价值和。

    Solution

      斜率优化。

      dp方程:$${f[i]=max(f[j]+a*(s[i]-s[j])^2+b*(s[i]-s[j])+c)}$$

      其中${s[i]}$为前缀和,${f[i]}$表示从1~i的最大价值。

      斜率式:$${s[i]*(2*a*s[j])+f[i]=(f[j]-b*s[j]+a*s[j]^2)+a*s[i]^2+b*s[i]+c}$$

      所以决策${j}$映射到平面直角坐标系上就是:${(2*a*s[j],f[j]-b*s[j]+a*s[j]^2)}$。斜率:${s[i]}$为正且单增;横坐标${2*a*s[j]}$单减(${a}$小于0,${s[j]}$单增),所以单调队列里面的点长成这样:

    细节

      开long long。

    代码

    // bzoj1911
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf 1e18
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=1000010;
    LL f[maxn],s[maxn],a,b,c;
    int n,q[maxn];
    
    double slope(int i,int j) {
    	return (double)((f[i]-b*s[i]+a*s[i]*s[i])-(f[j]-b*s[j]+a*s[j]*s[j]))/(double)((2*a*s[i])-(2*a*s[j]));
    }
    int main() {
    	scanf("%d",&n);
    	scanf("%lld%lld%lld",&a,&b,&c);
    	for (int i=1;i<=n;i++) scanf("%lld",&s[i]),s[i]+=s[i-1];
    	int l=1,r=1;q[1]=0;
    	for (int i=1;i<=n;i++) {
    		while (l<r && slope(q[l],q[l+1])<=s[i]) l++;
    		f[i]=f[q[l]]+a*(s[i]-s[q[l]])*(s[i]-s[q[l]])+b*(s[i]-s[q[l]])+c;
    		while (l<r && slope(q[r-1],q[r])>slope(q[r],i)) r--;
    		q[++r]=i;
    	}
    	printf("%lld",f[n]);
    	return 0;
    }
    

      

  • 相关阅读:
    Xshell远程连接工具
    Linux系列之常用命令整理笔录
    板卡
    禅道Bug等级划分标准
    CPU与GPU的区别
    PICT用例组合工具简介与使用教程
    alpha测试和beta测试的区别
    性能基础知识学习之八---loadrunner中run-time setting常用功能
    性能基础知识学习之七---loadrunner压测
    性能基础知识学习之六---socket接口测试
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6013532.html
Copyright © 2011-2022 走看看