• 解题:SDOI 2013 保护出题人


    题面

    首先是愉快的推式子

    $dp[i]=max(dp[i],frac{sum[i]-sum[j-1]}{x[i]+(i-j)*d})(1<=j<=i<=n)$(考虑有一只僵尸正好走到门前被打死,这样最优)

    然后发现这个玩意好像和平时的斜率优化不太一样,好像这个式子自己就是一个斜率,我们把它分成和$i$,$j$有关的两坨,这样清楚一点

    $dp[i]=max(dp[i],frac{(sum[i])-(sum[j-1])}{(x[i]+d*i)-(d*j)})$

    这样很清楚了,对于每个$i$我们就是在找$(sum[i],x[i]+d*i)$这个点向所有$1<=j<=i$连出的直线中的斜率的最大值,于是维护一个凸包并在上面二分即可

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=100005;
     6 const double eps=1e-7;
     7 int n,top,stk[N];
     8 double d,ans,sta[N],sum[N];
     9 inline double x(int p){return d*p;}
    10 inline double y(int p){return sum[p-1];}
    11 inline double s(int p,int q){return (y(q)-y(p))/(x(q)-x(p));}
    12 inline double X(int p){return sta[p]+d*p;}
    13 inline double Y(int p){return sum[p];}
    14 inline double S(int p,int q){return (Y(q)-y(p))/(X(q)-x(p));}
    15 int main()
    16 {
    17     scanf("%d%lf",&n,&d);
    18     for(int i=1;i<=n;i++)
    19         scanf("%lf%lf",&sum[i],&sta[i]),sum[i]+=sum[i-1];
    20     for(int i=1;i<=n;i++)
    21     {
    22         while(top>1&&s(stk[top-1],stk[top])>s(stk[top],i)) top--;
    23         stk[++top]=i;
    24         int l=1,r=top,tmp=0;
    25         while(l<=r)
    26         {
    27             int mid=(l+r)/2;
    28             if(S(stk[mid],i)>S(stk[mid-1],i)) l=mid+1,tmp=mid;
    29             else r=mid-1;
    30         }
    31         ans+=S(stk[tmp],i);
    32     }
    33     printf("%d",(int)(ans+0.5));
    34     return 0;
    35 }
    View Code
  • 相关阅读:
    Android Studio的代码没错,运行时logcat会出现红色语句解决方法
    541. Reverse String II
    Android Studio快速自动生成findViewById
    你真的了解android的layout_weight属性吗?
    572. Subtree of Another Tree
    441. Arranging Coins(可用二分搜索)
    67. Add Binary
    58. Length of Last Word
    724. Find Pivot Index
    我爱java系列--【加密算法的介绍】
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10006682.html
Copyright © 2020-2023  润新知