zoukankan      html  css  js  c++  java
  • [bzoj1492][NOI2007]Cash[CDQ分治;dp;斜率优化]

    首先,设f[x]表示x天能获得的A券最大值,有动规方程:

      $f[i]=max{f[j]*A[i]+f[j]*B[i]/R[j]}*R[i]/(R[i]*A[i]+B[i])$,

      设 $j<k$ ,$f[j]>f[k]$

      $Rightarrow (f[j]/R[j]-f[k]/R[k])/(f[j]-f[k]) leftarrow A[i]/B[i]$

      令$g[i]=f[i]/R[i]$,则有$(g[j]-g[k])/(f[j]-f[k]) leftarrow A[i]/B[i]$

      将每一天描述为一个点$(f[i],g[i])$可以在一个上凸壳上进行二分进行斜率优化。

      CDQ分治中按f[x]排序,分治时按id分割,这样用一个凸壳从左向右扫一遍,就可以更新整个区间的答案。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <cmath>
     7 #include <ctime>
     8 
     9 using namespace std;
    10 
    11 struct node
    12 {
    13     double    x,y,A,B,R,k; int    pos;
    14     bool    operator<(const node temp)const { return k>temp.k; }
    15 }c[110000],temp[110000];
    16 
    17 int    n,head,tail,H[110000];
    18 double    f[110000];
    19 
    20 const double    eps=1e-9;
    21 
    22 double    Calc(const int x,const int y)
    23 {
    24     if(fabs(c[x].x-c[y].x)<eps)return 1e100;
    25     return (c[x].y-c[y].y)/(c[x].x-c[y].x);
    26 }
    27 
    28 void    CDQ(const int l,const int r)
    29 {
    30     if(l==r)
    31     {
    32         f[l]=max(f[l],f[l-1]);
    33         c[l].y=f[l]/(c[l].R*c[l].A+c[l].B);c[l].x=c[l].y*c[l].R;
    34         return ;
    35     }
    36 
    37     int    i,mid=l+((r-l)>>1);
    38 
    39     int    l1=l,l2=mid+1;
    40     for(i=l;i<=r;++i)
    41     {
    42         if(c[i].pos<=mid)temp[l1++]=c[i];
    43         else    temp[l2++]=c[i];
    44     }
    45     for(i=l;i<=r;++i)c[i]=temp[i];
    46 
    47     CDQ(l,mid);
    48 
    49     tail=0,head=1;
    50     for(i=l;i<=mid;++i)
    51     {
    52         while(tail>1 && Calc(H[tail-1],H[tail])<Calc(H[tail],i))tail--;
    53         H[++tail]=i;
    54     }
    55     for(i=mid+1;i<=r;++i)
    56     {
    57         while(head<tail && Calc(H[head],H[head+1])>c[i].k)head++;
    58         f[c[i].pos]=max(f[c[i].pos],c[H[head]].x*c[i].A+c[H[head]].y*c[i].B);
    59     }
    60 
    61     CDQ(mid+1,r);
    62 
    63     l1=l;l2=mid+1;
    64     for(i=l;i<=r;++i)
    65     {
    66         if((c[l1].x<c[l2].x || (fabs(c[l1].x-c[l2].x)<eps && c[l1].y<c[l2].y+eps) || l2>r) && l1<=mid)
    67             temp[i]=c[l1++];
    68         else
    69             temp[i]=c[l2++];
    70     }
    71     for(i=l;i<=r;++i)c[i]=temp[i];
    72     return ;
    73 }
    74 
    75 int main()
    76 {
    77     scanf("%d%lf",&n,&f[0]);
    78     for(int i=1;i<=n;++i)
    79     {
    80         scanf("%lf%lf%lf",&c[i].A,&c[i].B,&c[i].R);
    81         c[i].k=-c[i].A/c[i].B;c[i].pos=i;
    82     }
    83 
    84     sort(c+1,c+n+1);
    85 
    86     CDQ(1,n);
    87 
    88     printf("%.3f
    ",f[n]);
    89 
    90     return 0;
    91 }
  • 相关阅读:
    Android直方图递增View
    分析实现Android自定义View之扇形图
    可折叠的ToolBar+抽屉菜单NavigationView+浮动按钮FloatButton
    走着官方的教程入门Material Design(一)
    AndroidStudio — Error:Failed to resolve: junit:junit:4.12错误解决
    Win10提示没有权限使用网络资源问题解决
    Android Socket连接PC出错问题及解决
    Android Studio —— 创建Menu菜单项
    Eclipse出现"Running Android Lint has encountered a problem"解决方案
    关于leal和mov
  • 原文地址:https://www.cnblogs.com/Gster/p/5090537.html
Copyright © 2011-2022 走看看