码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-04-11 22:23:47      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:

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..

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

标签:

原文地址:http://www.cnblogs.com/DaD3zZ-Beyonder/p/5380297.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!