CodeForces 460C--- Present(二分+贪心,还有个地方会TLE)

本题链接
本题 大意就是 给你一个数组 ,大小表示 花的高度 输入告诉你 花的个数,浇几天花(一天长一个单位)和浇花能覆盖花的个数,问你 浇完后高度最小值的最大情形。
虽然最近 刚学了二分 自认为 还是了解比较清楚,但是做这题开始没看出来是二分,惭愧。。。。
这题就是明显二分,在0~1e10范围内二分,看能满足这个题意的值。有个细节要注意,在模拟浇花那一个范围內花都会被 浇的时候,开始就想直接一个for(),将 存差值的b[i]数组依次减就好,多好理解啊,妈蛋 结果在cf的第20个测试数据TLE了,(cf真的很棒可以看后台测试数据和别人的代码)想想 也对 ,两个for,O(n^2)肯定超时啊,后来看了别人的题解,知道这里有一个 O(n)的解决办法,就是多一个数组c[i]存每次到哪里就不浇花,开始让x,存每次减去要交几次水的个数,再让x+c[i],就是这个点到底有没有被前面教的水覆盖到。
先上 原来明了但是TLE的代码

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long a[210000],b[210000];
int main()
{
    long long n,m,w;
    scanf("%I64d %I64d %I64d",&n,&m,&w);
    for(long long i=1;i<=n;i++)
      scanf("%I64d",&a[i]);
    long long low=0,mid,top=1e10,ans=-1;
    while(low<=top)
    {
         mid=(low+top)/2;
         memset(b,0,sizeof(b));
       for(long long i=1;i<=n;i++)
       {
         b[i]=max(mid-a[i],(long long)0);
       }
         long long d=m;
       for(long long i=1;i<=n;i++)
       {
          if(b[i]>0)
          {
             d-=b[i];
             if(d<0)
                break;

          long long c=b[i];
                for(long long j=i;j<i+w;j++)
               {
                 b[j]-=c;
               }
               b[i]=0;
          }
       }
       if(d<0)
       {
           top=mid-1;
       }
       else
       {
           ans=mid;
           low=mid+1;
       }
    }
    printf("%I64d\n",ans);
    return 0;
}

下面 是优化了浇水时覆盖一片花的AC代码

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
long long a[100010],b[100010],c[100010];//c是用来实现,浇水时一朵花覆盖到其他几朵的功能,具体实现看后面。
int main()
{
    long long n,m,w;
    scanf("%I64d %I64d %I64d",&n,&m,&w);
    for(long long i=1;i<=n;i++)
      scanf("%I64d",&a[i]);
    long long low=0,mid,top=1e10,ans=-1;
    while(low<=top)/=要有
    {
         mid=(low+top)/2;
       for(long long i=1;i<=n;i++)
       {
         b[i]=max(mid-a[i],(long long)0);
       }
       memset(c,0,sizeof(c));
       long long d=m,x=0;
       for(long long i=1;i<=n;i++)
       {
           x+=c[i];//判断这个点有没有被前面教的水覆盖到
           b[i]-=x;/处理之后的b[i]才是这个点面对前面教其他花后,自己有没有被浇到后的差值
           if(b[i]>0)
           {
             d-=b[i];
             if(d<0)
                break;

              x+=b[i];
              c[i+w]-=b[i];
              b[i]=0;
           }
       }
       if(d<0)
       {
           top=mid-1;
       }
       else
       {
           ans=mid;//存每一次中间值
           low=mid+1;
       }
    }
    printf("%I64d\n",ans);
    return 0;
}

写完这题,感觉贪心的思想几乎没有,还是考对二分的理解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值