【BZOJ-1911】特别行动队 DP + 斜率优化

1911: [Apio2010]特别行动队

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 3478  Solved: 1586
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

4
-1 10 -20
2 2 3 4

Sample Output

9

HINT

Source

Solution

题意非常明显,将n个数划分成多段区间,使得总价值最大,每段区间的价值为$powersum=\sum power[i],ans=a*powersum^2+b*powersum+c$

那么得出DP转移方程:$dp[i]=max(dp[j]+a*(pos[i]-pos[j])^2+b*(pos[i]-pos[j])+c)$

那么很显然不能AC,那么考虑优化一下时间

考虑斜率优化,对于转移到当前位置,最优解为$i$,如果满足任意$i<j$都有$i$更优那么就可以得到如下:

$(dp[j]-dp[i]+a*(pos[j]^2-pos[i]^2)+b*(pos[i]-pos[j]))/(2*a*(pos[j]-pos[i]))$那么维护一下即可

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();}
    while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}
#define maxn 1000100
int n,a,b,c; int po[maxn]; long long pos[maxn],dp[maxn];
int que[maxn],l,r;
long long pf(long long x){return x*x;}
double slope(int i,int j)
{
    double fz=dp[j]-dp[i]+a*(pf(pos[j])-pf(pos[i]))+b*(pos[i]-pos[j]);
    double fm=(2*a*(pos[j]-pos[i]));
    return fz/fm;
}
int main()
{
    n=read(); a=read(),b=read(),c=read();
    for (int i=1; i<=n; i++) po[i]=read(),pos[i]=pos[i-1]+po[i];
    for (int tmp,i=1; i<=n; i++)
        {
            while (l<r && slope(que[l],que[l+1])<pos[i]) l++;
            tmp=que[l];
            dp[i]=dp[tmp]+a*pf(pos[i]-pos[tmp])+b*(pos[i]-pos[tmp])+c;
            while (l<r && slope(que[r-1],que[r])>slope(que[r],i)) r--;
            que[++r]=i;
        }
    printf("%lld\n",dp[n]);
    return 0;
}

斜率优化好TAT..

时间: 2024-12-17 09:17:46

【BZOJ-1911】特别行动队 DP + 斜率优化的相关文章

BZOJ 1911: [Apio2010]特别行动队( dp + 斜率优化 )

sum为战斗力的前缀和 dp(x) = max( dp(p)+A*(sumx-sump)2+B*(sumx-sump)+C )(0≤p<x) 然后斜率优化...懒得写下去了... -------------------------------------------------------------------------------- #include<bits/stdc++.h> using namespace std; typedef long long ll; const in

[bzoj 1911][Apio 2010]特别行动队(斜率优化DP)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(Si-Sj)+c} 0<j<i 简化一下方程,我们知道对于一次项,最后结果肯定是b*Sn 所以可以写成f[i]=max{f[j]+a*(Si-Sj)^2+c} 0<j<i 我们不妨设0<x<y<i,且x比y优 即f[x]+a*(Si-Sx)^2+c>f[y]+a*

bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3191  Solved: 1450[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT Source [思路] 斜率优化. 设f[i]表示将前i个分组的最优值,则有转移方程式: f[i]=max{ f[j]

BZOJ 1911 特别行动队(斜率优化DP)

应该可以看出这是个很normal的斜率优化式子.推出公式搞一搞即可. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set>

【斜率DP】BZOJ 1911:特别行动队

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3006  Solved: 1360[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT 很容易写出斜率式什么的就不说了.. 不开long long见祖宗.. 1 #include<cstdio> 2 #i

BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化

欢迎访问~原文出处--博客园-zhouzhendong&AK 去博客园看该题解 题目传送门 题意概括 把一个整数序列划分成任意连续的段,使得划分出来的每一段的价值和最大. 对于某一段,价值的计算公式为 V=ax^2+bx+c,其中 x 为当前段的数值和. 题解 这题是博主大蒟蒻的第一道斜率优化DP题-- C++:while (1) 懵逼++; Pascal:while (true) do inc(懵逼); 本题首先一看就是 DP 题. 但是一看 1<=n<=1000000,-5<

BZOJ 1911 特别行动队

另一个版本的斜率优化...这个要好理解一些. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 1000050 using namespace std; struct pnt { long long x,y; }p[maxn]; long long n,a,b,c,s[maxn],dp[maxn],q[maxn],l,r; long l

BZOJ 1096: [ZJOI2007]仓库建设( dp + 斜率优化 )

dp(v) = min(dp(p)+cost(p,v))+C(v) 设sum(v) = ∑pi(1≤i≤v), cnt(v) = ∑pi*xi(1≤i≤v), 则cost(p,v) = x(v)*(sum(v)-sum(p)) - (cnt(v)-cnt(p)) 假设dp(v)由dp(i)转移比dp(j)转移优(i>j), 那么  dp(i)+cost(i,v) < dp(j)+cost(j,v) 即 dp(i)+x(v)*(sum(v)-sum(i))-(cnt(v)-cnt(i)) <

【BZOJ1911】【Apio2010】特别行动队,斜率优化DP裸题(斜率有单调性)

题解: 首先裸dp方程为: F(x)=a*x*x+b*x+c;  sum为前缀和 f[i]=f[j]+F(sum[i]-sum[j]); 然后拆开后把带j的放一边,带i的放一边,形成y=kx+b的形式,使y和x都含j不含i,k和b都含i不含j. 得:f[j]+asum[j]*sum[j]-b*sum[j]=2*a*sum[i]*sum[j]+f[i]-a*sum[i]*sum[i]-b*sum[i]-c; 然后有:y=kx+b; y=f[j]+asum[j]*sum[j]-b*sum[j]; x