二分答案-----Present

原题链接: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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值