zoukankan      html  css  js  c++  java
  • 【洛谷P3628】特别行动队

    题目

    题目链接:https://www.luogu.com.cn/problem/P3628
    你有一支由 \(n\) 名预备役士兵组成的部队,士兵从 \(1\)\(n\) 编号,你要将他们拆分成若干特别行动队调入战场。出于默契的考虑,同一支特别行动队中队员的编号应该连续,即为形如 \((i, i + 1, \cdots i + k)\)的序列。所有的队员都应该属于且仅属于一支特别行动队。
    编号为 \(i\) 的士兵的初始战斗力为 \(x_i\) ,一支特别行动队的初始战斗力 \(X\) 为队内士兵初始战斗力之和,即 \(X = x_i + x_{i+1} + \cdots + x_{i+k}\)
    通过长期的观察,你总结出对于一支初始战斗力为 \(X\) 的特别行动队,其修正战斗力 \(X'= aX^2+bX+c\),其中 \(a,~b,~c\) 是已知的系数(\(a<0\))。 作为部队统帅,现在你要为这支部队进行编队,使得所有特别行动队的修正战斗力之和最大。试求出这个最大和。
    \(n\leq 10^6\)

    思路

    不记得从哪听说这道题不是很模板?但是感觉还是模板啊QWQ。
    \(f[i]\) 表示前 \(i\) 个人分好组的最大和。设 \(s[i]=\sum^{i}_{j=1}x[i]\),显然

    \[f[i]=\max(f[j]+a(s[i]-s[j])^2+b(s[i]-s[j])+c) \]

    展开,移项后得到

    \[f[j]+a·s[j]^2-b·s[j]=2a·s[i]·s[j]+f[i]-a·s[i]^2-b·s[i]+c \]

    那么可以看做一条斜率为 \(2a·s[i]\),截距为 \(f[i]-a·s[i]^2-b·s[i]+c\) 的直线,决策点为 \((s[j],f[j]+a·s[j]^2-b·s[j])\) 的平面直角坐标系。
    由于 \(a<0\),那么斜率满足单调递减,同时决策点的横坐标单调递增,所以单调队列维护上凸壳即可。
    时间复杂度 \(O(n)\)

    代码

    #include <cctype>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N=1000010;
    ll a,b,c,f[N],s[N],Y[N];
    int n,l,r,q[N];
    
    ll read()
    {
    	ll d=0,f=1; char ch=getchar();
    	while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
    	while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d*f;
    }
    
    double slope(int x,int y)
    {
    	return 1.0*(Y[y]-Y[x])/(s[y]-s[x]);
    }
    
    int main()
    {
    	n=read(); a=read(); b=read(); c=read();
    	for (int i=1;i<=n;i++)
    		s[i]=s[i-1]+read();
    	l=r=1;
    	for (int i=1;i<=n;i++)
    	{
    		for (int x=q[l],y=q[l+1];;x=q[l],y=q[l+1])
    			if (l<r && slope(x,y)>=2.0*a*s[i]) l++; 
    				else break;
    		int j=q[l];
    		f[i]=f[j]+a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c;
    		Y[i]=f[i]+a*s[i]*s[i]-b*s[i];
    		for (int x=q[r-1],y=q[r];;x=q[r-1],y=q[r])
    			if (l<r && slope(x,y)<=slope(y,i)) r--;
    				else break;
    		q[++r]=i;
    	}
    	printf("%lld",f[n]);
    	return 0;
    }
    
  • 相关阅读:
    php require与include的区别
    php页面消耗内存过大处理办法
    flex if(a is b){},flex if(a as b){} 意思
    thinkphp的配置文件修改后不起作用
    ThinkPHP 入口文件定义 3.0 输出两次解决办法
    JS中的Math.ceil和Math.floor函数
    ThinkPHP 配置问题
    Google 快照无法使用时,如何恢复
    首页被收录了,但是只显示网址,处理办法
    RED5 端口使用
  • 原文地址:https://www.cnblogs.com/stoorz/p/12567591.html
Copyright © 2011-2022 走看看