原题链接:https://codeforc.es/problemset/problem/460/C
题目大意:
小海狸是一个初级程序员,所以信息学是他最喜欢的科目。很快他的信息学老师就要过生日了,小海狸决定为她准备一份礼物。他在窗台上种了一排花,并开始等待它们生长。然而,过了一段时间,海狸发现这些花不再生长。海狸认为赠送小花是不礼貌的行为。于是他决定想出一些解决办法。
离生日还剩m天。此刻第i朵花的高度(假设这一排的花从左到右编号为1到n)等于ai。在剩下的m天中的每一天,海狸可以采取特殊的浇水方式,给w朵相邻的花浇水(他一天只能做一次)。在这一天,每朵浇灌的花都会增长一个高度单位。海狸希望最小的花的高度最终能尽可能大。他能得到的最小的花的最大高度是多少?
输入
第一行包含隔开空间的整数n、m和w(1≤w≤n≤105;1≤m≤105)。第二行包含空格分隔的整数a1, a2, ..., an (1 ≤ ai ≤ 109)。
输出
打印一个整数 - 最小的花的最大最终高度。
Examples
Input
6 2 3 2 2 2 2 1 1
Output
2
Input
2 5 1 5 8
Output
9
这个题我当时脑子wa 了,还以为是线段树的题,现在想想,找最小最大的值,先想的应该是二分
但是暴力的话是 N*N 会超时,所以想 nlogn ,那当然就是二分了
二分模板如下(每个人的模板不同,找一个适合自己的,记住他就行了)
// 范围是 [L,R]
int l = L-1 ,r = R+1;
while(l+1 != r)
{
int mid=(l+r)>>1;
if(pan(mid))
{
l=mid;
}
else r=mid;
}
cout<<l<<endl;//自己选择是要哪个
cout<<r<<endl;
最小的答案是所有a[i]中最小的那个
最大的答案是最小的a[i] + m;
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define int long long
#define endl "\n"
const int N = 2e5+5; //这里一定要开二倍空间,因为下面的 b[i+w] 会超过 N,当然你也可以加一个i+w的判断
int a[N],b[N];
int n,m,w;
bool pan(int x)
{
memset(b,0,sizeof(b));
int ans=0;
for(int i=1; i<=n; i++)
{
b[i]+=b[i-1];
int k=a[i]+b[i];
if(k<x)
{
b[i]+=(x-k);
b[i+w]-=(x-k);
ans+=(x-k);
}
if(ans>m) return false;
}
return true;
}
signed main()
{
int l=inf,r=0,mid=0;
cin>>n>>m>>w;
for(int i=1; i<=n; i++) cin>>a[i],l=min(l,a[i]);// 左边界
r=l+m;//右边界
l--,r++;
while(l+1!=r)
{
mid=(l+r)>>1;
// cout<<"l== "<<l<<" r== "<<r<<" mid== "<<mid<<endl;
if(pan(mid))
{
l=mid;
} else r=mid;
}
cout<<l<<endl;
return 0;
}