您的位置:首页 > 其它

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

2015-05-05 18:16 633 查看
本题链接

本题 大意就是 给你一个数组 ,大小表示 花的高度 输入告诉你 花的个数,浇几天花(一天长一个单位)和浇花能覆盖花的个数,问你 浇完后高度最小值的最大情形。

虽然最近 刚学了二分 自认为 还是了解比较清楚,但是做这题开始没看出来是二分,惭愧。。。。

这题就是明显二分,在0~1e10范围内二分,看能满足这个题意的值。有个细节要注意,在模拟浇花那一个范围內花都会被 浇的时候,开始就想直接一个for(),将 存差值的b[i]数组依次减就好,多好理解啊,妈蛋 结果在cf的第20个测试数据TLE了,(cf真的很棒可以看后台测试数据和别人的代码)想想 也对 ,两个for,O(n^2)肯定超时啊,后来看了别人的题解,知道这里有一个 O(n)的解决办法,就是多一个数组c[i]存每次到哪里就不浇花,开始让x,存每次减去要交几次水的个数,再让x+c[i],就是这个点到底有没有被前面教的水覆盖到。

先上 原来明了但是TLE的代码

[code]#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代码

[code]#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;
}


写完这题,感觉贪心的思想几乎没有,还是考对二分的理解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: