BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

1911: [Apio2010]特别行动队

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 4142  Solved: 1964
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

4
-1 10 -20
2 2 3 4

Sample Output

9

HINT


f[i]=max{f[j]+...}

随便一化就好了

(a*(s[k]*s[k]-s[j]*s[j])+f[k]-f[j]+b*(s[j]-s[k])) / (2*a*(s[k]-s[j]))

最后是s[i]>=slope(j,k)时k优

s[]是单调的,用单调队列维护这个下凸壳

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e6+5,INF=1e9;
typedef long long ll;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}
int n,a,b,c;
ll s[N],f[N];
inline double slope(int j,int k){
    return  (double)(a*(s[k]*s[k]-s[j]*s[j])+f[k]-f[j]+b*(s[j]-s[k]))/(double)(2*a*(s[k]-s[j]));
}
int q[N],head,tail;
void dp(){
    head=tail=1;
    for(int i=1;i<=n;i++){
        while(head<tail&&slope(q[head],q[head+1])<=s[i]) head++;
        int j=q[head];
        f[i]=f[j]+a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c;//printf("f %lld %d\n",f[i],j);
        while(head<tail&&slope(q[tail-1],q[tail])>slope(q[tail],i)) tail--;
        q[++tail]=i;
    }
    printf("%lld",f[n]);
}
int main(){
    //freopen("in.txt","r",stdin);
    n=read();a=read();b=read();c=read();
    for(int i=1;i<=n;i++) s[i]=s[i-1]+read();
    dp();
}
时间: 2024-10-09 20:11:45

BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]的相关文章

【BZOJ1911】[Apio2010]特别行动队 斜率优化DP

想了好久啊.... 用了我感觉比较好写的一种(因为没写过维护凸包),另一种是维护凸包的做法,本质一样?推荐http://www.mamicode.com/info-detail-345781.html. 网上的大多数解法: DP:f[i]=max(f[j]+a*(sum[i]-sum[j])^2+b(sum[i]-sum[j])+c) 显然复杂度不对. 那么假设j>k且f[j]优于f[k] f[j]-f[k]+a*(sum[j]^2-sum[k]^2)-b*(sum[j]-sum[k])>2*

bzoj1911[Apio2010]特别行动队 斜率优化dp

1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 5057  Solved: 2492[Submit][Status][Discuss] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT dp[i]=dp[j]+a*x*x+b*x+cx=sum[i]-sum[j] 证明单调性假设对于i点 k<j且j的决策

[APIO2010]特别行动队 --- 斜率优化DP

[APIO2010]特别行动队 题面很直白,就不放了. 太套路了,做起来没点感觉了. \(dp(i)=dp(j)+a*(s(i)-s(j))^{2}+b*(s(i)-s(j))+c\) 直接推出一个斜率优化的式子上单调队列就好了 时间/空间复杂度:\(O(n)\) #include<cstdio> #define sid 1000500 #define ri register int #define ll long long #define dd double using namespace

APIO2010 特别行动队 &amp; 斜率优化DP入门讲解

做完此题之后 自己应该算是真正理解了斜率优化DP 根据状态转移方程f[i]=max(f[j]+ax^2+bx+c),x=sum[i]-sum[j] 可以变形为 f[i]=max((a*sum[j]^2-b*sum[j])-(2a*sum[j]*sum[i]))+(a*sum[i]^2+b*sum[i]+c) 我们可以把每个决策映射到平面上的一个点 其中x坐标为(a*sum[j]^2-b*sum[j])代表此决策的固定价值(与转移到哪无关) y坐标为-(2a*sum[j]) 代表此决策的潜在价值(

斜率优化专题4——bzoj 1911: [Apio2010] 特别行动队 题解

[原题] 1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 2134  Solved: 911 [Submit][Status] Description Input Output Sample Input 4 -1 10 -20 2 2 3 4 Sample Output 9 HINT [分析]只要跟着我前面的题目走,这道题真的是太水了.神马题解都不用参考,公式随便推. 易知方程是f[i]=max(f[j]+

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: [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: [Apio2010]特别行动队

1 #include<cstdio> 2 #include<iostream> 3 #define M 1000009 4 #define ll long long 5 using namespace std; 6 int n,zhan[M],h,t; 7 ll a,b,c,f[M],sum[M]; 8 double pai(int a1,int a2) 9 { 10 double ss=(f[a1]-f[a2])/(1.0*a*(sum[a2]-sum[a1])); 11 ret

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

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