zoukankan      html  css  js  c++  java
  • bzoj1911[Apio2010]特别行动队 斜率优化dp

    1911: [Apio2010]特别行动队

    Time Limit: 4 Sec  Memory Limit: 64 MB
    Submit: 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+c
    x=sum[i]-sum[j]

    证明单调性
    假设对于i点 k<j且j的决策比k优
    dp[j]+a*(sum[i]-sum[j])*(sum[i]-sum[j])+b*(sum[i]-sum[j])+c>=dp[k]+a*(sum[i]-sum[k])*(sum[i]-sum[k])+b*(sum[i]-sum[k])+c
    化简得 dp[j]+a*sum[j]*sum[j]-2*a*sum[i]*sum[j]-b*sum[j]>=dp[k]+a*sum[k]*sum[k]-2*a*sum[i]*sum[k]-b*sum[k]

    要证明单调性 需证明下面的式子
    dp[j]+a*(sum[t]-sum[j])*(sum[t]-sum[j])+b*(sum[t]-sum[j])+c>=dp[k]+a*(sum[t]-sum[k])*(sum[t]-sum[k])+b*(sum[t]-sum[k])+c
    化简得dp[j]+a*sum[j]*sum[j]-2*a*sum[t]*sum[j]-b*sum[j]>=dp[k]+a*sum[k]*sum[k]-2*a*sum[t]*sum[k]-b*sum[k]

    设t>i 显然sum[t]>=sum[i] 设sum[t]=sum[i]+v
    代入sum[t]得 dp[j]+a*sum[j]*sum[j]-2*a*sum[i]*sum[j]-b*sum[j]+v*sum[j]>=dp[k]+a*sum[k]*sum[k]-2*a*sum[i]*sum[k]-b*sum[k]+v*sum[k]
    因为j>k 所以sum[j]>=k 上式成立,决策单调性得证
    证毕

    可以写出斜率式
    dp[j]+a*sum[j]^2-2*a*sum[i]*sum[j]-b*sum[j]>=dp[k]+a*sum[k]^2-2*a*sum[i]*sum[k]-b*sum[k] 且j>k
    => dp[j]-dp[k]+a*sum[j]^2-a*sum[k]^2+b*sum[k]-b*sum[j]>=sum[i]*2*a*(sum[j]-sum[k])
    => (dp[j]-dp[k]+a*sum[j]^2-a*sum[k]^2+b*sum[k]-b*sum[j])/(2*a*(sum[j]-sum[k]))>=sum[i]

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<queue>
     5 #include<cmath>
     6 #include<vector>
     7 #include<cstdlib>
     8 #include<iostream>
     9 #define ll long long
    10 #define inf 2147483647
    11 #define N 1000005
    12 using namespace std;
    13 ll dp[N],sum[N];
    14 int a,b,c,q[N];
    15 ll pw(ll x){return x*x;}ll S(int j,int k){return 2*a*(sum[j]-sum[k]);}
    16 ll G(int j,int k){return dp[j]-dp[k]+a*pw(sum[j])-a*pw(sum[k])+b*sum[k]-b*sum[j];}
    17 double slope(int j,int k){return (double)G(j,k)/S(j,k);}
    18 
    19 int main(){
    20     int n;
    21     scanf("%d",&n);
    22     scanf("%d%d%d",&a,&b,&c);
    23     for(int i=1;i<=n;i++){
    24         int x;
    25         scanf("%d",&x);
    26         sum[i]=sum[i-1]+x;
    27     }
    28     int h=1,t=2;
    29     for(int i=1;i<=n;i++){
    30         while(h+1<t&&slope(q[h],q[h+1])<=sum[i])h++;
    31         int j=q[h],x=sum[i]-sum[j];
    32         dp[i]=dp[j]+a*pw(x)+b*x+c;
    33         while(h+1<t&&slope(i,q[t-1])<=slope(q[t-1],q[t-2]))t--;
    34         q[t++]=i;
    35     }
    36     printf("%lld",dp[n]);
    37     return 0;
    38 }
  • 相关阅读:
    MacOS Sierra允许运行任何来源的程序
    Windows Server2008 R2中的角色
    Linux根目录解析
    Linux安装配置SVN服务器
    Linux6.x修改出eth0网卡的解决方法
    如何利用mount命令挂载另一台服务器上的目录
    Arcgis水文分析-Dem提取集水区
    前端布局之Flex布局
    其实我就是想好好的写写代码(一个伪程序猿的独白)
    WebApi关于配置全局返回Json数据格式时间以及命名小写
  • 原文地址:https://www.cnblogs.com/wsy01/p/8124910.html
Copyright © 2011-2022 走看看