zoukankan      html  css  js  c++  java
  • bzoj 1911 [Apio2010]特别行动队(斜率优化+DP)

    点击打开链接

    思路:

    斜率优化。
    设f[i]表示将前i个分组的最优值,则有转移方程式:
    f[i]=max{ f[j]+a*(s[i]-s[j])^2+b*(s[i]-s[j])+c }
    经过化简得到:f[i]=max{ (f[j]+a*s[j]^2-b*s[j])-2*a*s[i]*s[j] } + a*s[i]^2+b*s[i]+c
    单调队列维护上凸包即可。
    y[j] = (f[j]+a*s[j]^2-b*s[j])
    x[j] = s[j]
    min p = y[j]-2*a*s[i]*x[j] 因为a是负的 所以斜率为正 是上凸包


    now.x = s[j]
    now.y = y[i] = (f[i]+a*s[i]^2-b*s[i]) = {(f[j]+a*s[j]^2-b*s[j])-2*a*s[i]*s[j]+ a*s[i]^2+b*s[i]+c} + a*s[i]^2-b*s[i] = {(q[L].y)-2*a*s[i]*q[L].x} + 2*a*s[i]^2+c

    答案就是 q[R].y-a*s[n]*s[n]+b*s[n] 

    代码一:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define mem(a) memset(a,0,sizeof(a))
     5 #define mp(x,y) make_pair(x,y)
     6 const int INF = 0x3f3f3f3f;
     7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     8 inline ll read(){
     9     ll x=0,f=1;char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 //////////////////////////////////////////////////////////////////////////
    15 const int maxn = 1e6+10;
    16 
    17 struct node{
    18     ll x,y;
    19 }now,q[maxn];
    20 
    21 int n,x;
    22 ll a,b,c,s[maxn];
    23 
    24 ll cross(node A,node B,node C){
    25     return (B.x-A.x)*(C.y-A.y) - (C.x-A.x)*(B.y-A.y);
    26 }
    27 
    28 int main(){
    29     n=read();
    30     a=read(),b=read(),c=read();
    31     s[0] = 0;
    32     for(int i=1; i<=n; i++){
    33         x=read();
    34         s[i] = s[i-1]+x;
    35     }
    36 
    37     int L=0,R=0;
    38     for(int i=1; i<=n; i++){
    39         while(L<R && q[L+1].y-2*a*s[i]*q[L+1].x >= q[L].y-2*a*s[i]*q[L].x) L++;
    40         while(L<R && q[L].y-2*a*s[i]*q[L].x <= q[L+1].y-2*a*s[i]*q[L+1].x) L++;
    41         now.x = s[i];
    42         now.y = q[L].y-2*a*s[i]*q[L].x+2*a*s[i]*s[i]+c;    
    43         while(L<R && cross(q[R-1],now,q[R]) <= 0) R--; // 为什么now跑到中间去嘞?是上凸包
    44         q[++R] = now;
    45          
    46     }
    47 
    48     cout << q[R].y-a*s[n]*s[n]+b*s[n] << endl;
    49 
    50     return 0;
    51 }

    代码二:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define mem(a) memset(a,0,sizeof(a))
     5 #define mp(x,y) make_pair(x,y)
     6 const int INF = 0x3f3f3f3f;
     7 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     8 inline ll read(){
     9     ll x=0,f=1;char ch=getchar();
    10     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    11     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    12     return x*f;
    13 }
    14 //////////////////////////////////////////////////////////////////////////
    15 const int maxn = 1e6+10;
    16 
    17 int n,x,q[maxn];
    18 ll a,b,c,s[maxn],f[maxn];
    19 
    20 ll getup(int j,int k){
    21     return f[j]-f[k]+a*(s[j]*s[j]-s[k]*s[k])+b*(s[k]-s[j]);
    22 }
    23 
    24 ll getdown(int j,int k){
    25     return (s[j]-s[k]);
    26 }
    27 
    28 int main(){
    29     n=read();
    30     a=read(),b=read(),c=read();
    31     s[0] = 0;
    32     for(int i=1; i<=n; i++){
    33         x=read();
    34         s[i] = s[i-1]+x;
    35     }
    36 
    37     int L=0,R=0;
    38     for(int i=1; i<=n; i++){
    39         while(L<R && getup(q[L+1],q[L]) >= s[i]*2*a*getdown(q[L+1],q[L])) L++; // a是负的
    40         int j = q[L];
    41         f[i] = f[j] + a*(s[i]-s[j])*(s[i]-s[j]) + b*(s[i]-s[j]) + c;
    42         while(L<R && getup(i,q[R])*getdown(q[R],q[R-1]) >= getup(q[R],q[R-1])*getdown(i,q[R])) R--;
    43         q[++R] = i;    
    44     }
    45 
    46     cout << f[n] << endl;
    47 
    48     return 0;
    49 }
  • 相关阅读:
    JDBC的使用流程
    typescript vscode /bin/sh: ts-node: command not found
    小程序打开app场景
    设置获取cookie,setCookie,getCookie
    解决IOS微信页面回退不刷新问题
    百度小程序添加编译
    百度小程序审核不通过,基础库问题
    Charles Mac 破解安装和证书安装成功抓包单个域名是unknown
    xhrFields实现跨域访问
    Mac上启动nginx报错:nginx: [emerg] bind() to 0.0.0.0:80 failed (48: Address already in use)
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827706.html
Copyright © 2011-2022 走看看