您的位置:首页 > 其它

Codefores 460C-Present(二分+贪心)

2017-06-26 21:59 375 查看
在打哈尔滨理工大学个人训练赛做到的题目。

觉得挺不错的,挺锻炼思维的。

题目大意:给定n朵花,每朵花的高度不一样,还有m天,有一种神奇的水可以使相邻的w朵花每天长高1,每天只能浇一次,问最矮的花最后最高能多少。

遇到这种最矮的最高问题,应该很快想到二分才对,但是又没想到。

然后想到二分应该怎么继续呢。那肯定是判断每朵花能不能达到x,这时就应该从左往右扫了。因为是每一朵,而根据这个相邻w,前面的w-1朵具有特殊性,前w朵中的第i朵一定能享受到他前面花浇的水,而w往后的就享受不到i-w之前浇的水了,这里可以用前缀和记录浇的水。

另外需要判断天数是否大于m以及是否都能达到x

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
#include <stack>
#define fuck() (cout << "------------------------------" << endl)
using namespace std;
const int maxn = 100000 + 5;
const int inf = 0x3f3f3f3f;
long long a[maxn];
long long b[maxn];
int n,m,w;// n是多少朵花,m是剩余几天,w是一次能浇多长。
bool check(long long x)//x 最矮的高度
{
memset(b,0,sizeof(b));
long long time = 0;
long long sum = 0;
for(int i=0; i<n; i++)
{
if(i >= w) sum -= b[i-w];// 享受不到比他前m朵花少浇的水,应该是类似前缀和的味道。
if(x > a[i] + sum) // 达不到x
{
b[i] = x - sum - a[i];  //达到x还需要几天
sum += b[i];    // 少浇几天水
time += b[i];   //浇水次数总和
}
if(time > m)
return false;
}
return true;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&w)!=EOF && n)
{
for(int i=0; i<n; i++)
scanf("%lld",&a[i]);
long long  l = 1, r = 100000000000000, mid ;
long long ans = 0;
while(l <= r)
{
mid =  (l+r) >> 1;
if(check(mid))
{
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: