• [BZOJ1911][Apio2010]特别行动队


    [BZOJ1911][Apio2010]特别行动队

    试题描述

    输入

    输出

    输入示例

    4
    -1 10 -20
    2 2 3 4

    输出示例

    9

    数据规模及约定

    题解

    DP,令 f(i) 表示前 i 个士兵可以达到的最大修正后的战斗力,则有 f(i) = max{ f(j) + d(j+1 ~ i) | 0 < j < i },其中d(i ~ j)表示第 i 个士兵到第 j 个士兵组成一队修正之后的战斗力。展开之后得到

    f(i) - a·Si2 - b·Si - c = f(j) + a·Sj2 - b·Sj - 2·a·Si · Sj

    发现蓝色部分只与i相关,黄色部分只与j相关,绿色部分随 i 的增加是单调递减的,橙色部分只与j相关,把它们依次换元成b, y, k, x,得到

    b = y - k · x,变形得 y = kx + b,斜率k单调递增,我们要求的是b的最大值,所以维护所有(x, y)点构成的上凸壳即可。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *tail;
    inline char Getchar() {
        if(Head == tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
    
    #define maxn 1000010
    #define LL long long
    int n, a, b, c, S[maxn], q[maxn], l, r;
    LL f[maxn];
    
    double slop(int i, int j) {
    	double yi = i ? f[i] + (double)a * S[i] * S[i] - (double)b * S[i] : 0.0, yj = f[j] + (double)a * S[j] * S[j] - (double)b * S[j];
    	double xi = i ? S[i] : 0, xj = S[j];
    	return (yi - yj) / (xi - xj);
    }
    
    int main() {
    	n = read(); a = read(); b = read(); c = read();
    	for(int i = 1; i <= n; i++) S[i] = S[i-1] + read();
    	
    	f[0] = 0;
    	l = r = 1; q[1] = 0;
    	for(int i = 1; i <= n; i++) {
    		while(l < r && slop(q[l], q[l+1]) > 2.0 * a * S[i]) l++;
    		int j = q[l];
    		f[i] = f[j] + (LL)a * S[j] * S[j] - (LL)b * S[j] - 2ll * a * S[i] * S[j] + (LL)a * S[i] * S[i] + (LL)b * S[i] + c;
    		while(l < r && slop(q[r], i) >= slop(q[r-1], q[r])) r--;
    		q[++r] = i;
    	}
    	
    	printf("%lld
    ", f[n]);
    	
    	return 0;
    }
    
  • 相关阅读:
    在win2003中发布部署vs2010b2写的mvc2网站
    安装blender2.5Alpha0
    Win7下虚拟机个人使用小结:Virtual PC,VMware和VirtualBox
    ASP.NET AJAX Control Toolkit Beta 0911 发布[再增两控件]
    Camtasia 6录屏时鼠标闪烁问题解决
    为XNA制做安装程序(四)WIX Toolset 3.0 for Visual Studio 2008
    Oracle EM 12c
    无题
    从徐汇到虹口
    近况
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5414479.html
Copyright © 2020-2023  润新知