codeforces #262 DIV2 C题Present(二分+贪心)

时间:2022-12-30 09:58:17

题目地址:http://codeforces.com/contest/460/problem/C

这个题是用二分枚举最小值,然后判断能否在规定的次数内使得所有的数都达到这个值。判断的时候要用贪心的方法判断,从左往右遍历,这时候需要让每次浇花的范围尽量向右。所以当到达一个不得不浇花的地方时,要继续占用所需要的浇花次数。当浇花次数不够用的时候,就说明无法达到。

在我的代码中,c数组是记录当前到了该点的时候浇花范围的最右界,表示到了这个地方的时候少了多少次覆盖。y就代表当前这个数被多少个浇花范围覆盖。x是指还剩余的浇花次数。

忘了初始化。。二分很明显不好调试。。调了将近20分钟才发现忘了对C数组初始化。。。sad。。。。

代码如下:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <algorithm>
#include <queue>
using namespace std;
#define LL __int64
LL a[110000], b[110000], c[110000];
int main()
{
LL n, m, i, w, ans, x, y;
scanf("%I64d%I64d%I64d",&n,&m,&w);
for(i=0;i<n;i++)
{
scanf("%I64d",&a[i]);
}
memset(c,0,sizeof(c));
LL low=1, high=1e10, mid;
while(low<=high)
{
mid=(high+low)/2;
//printf("%I64d\n",mid);
x=m;
y=0;
memset(c,0,sizeof(c));
int flag=0;
for(i=0;i<n;i++)
{
b[i]=mid-a[i];
if(b[i]<0)
b[i]=0;
}
for(i=0;i<n;i++)
{
y+=c[i];
b[i]-=y;
if(b[i]>0)
{
if(x-b[i]<0)
{
flag=1;
break;
}
else
{
x-=b[i];
y+=b[i];
if(i+w<n)
c[i+w]-=b[i];
}
}
}
//printf("%I64d %d\n",mid, flag);
if(flag)
{
high=mid-1;
}
else
{
ans=mid;
low=mid+1;
}
//printf("%I64d\n",ans);
}
printf("%I64d\n",ans);
return 0;
}