码迷,mamicode.com
首页 > 其他好文 > 详细

Honk's pool(二分模板题)

时间:2019-09-18 19:33:16      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:分时   ace   for   namespace   res   can   while   最大   二分   

题意:有n个水池,每个水池有a[i]单位水,有k次操作,每次操作将水量最多的水池减少一单位水,水量最少的水池增加一单位水,问最后水量最大的水池和水量最少的水池相差的水量。

思路:二分最后的最大水量和最小水量,特别的,模拟一下可以发现如果总水量sum%n==0,则最大值的下界和最小值的上界均为sum/n,若sum%n!=0,则最大值的下界为sum/n+1,最小值上界为sum/n。二分时注意选取区间是左闭右开还是左开右闭。

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
ll a[maxn];
ll n,k;
bool check1(ll p){
    ll res=0;
    for(int i=1;i<=n;i++)
        if(a[i]>p) res+=a[i]-p;
    if(res<=k) return 1;
    else return 0;
}
bool check2(ll p){
    ll res=0;
    for(int i=1;i<=n;i++)
        if(a[i]<p) res+=p-a[i];
    if(res<=k) return 1;
    else return 0;
}
int main(){
    while(~scanf("%lld%lld",&n,&k) ){
        ll sum=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        ll l,r,mid;//左开右闭区间
        r=1e9+9;
        if(sum%n==0)
            l=sum/n-1;
        else l=sum/n;
        while(r-l>1){
            mid=(r+l+1)/2;
            if(check1(mid))
                r=mid;
            else l=mid;
        }
        ll up=r;//>=k
        l=0;r=sum/n+1;//左闭右开
        while(r-l>1){
            mid=(r+l+1)/2;
            if(check2(mid))
                l=mid;
            else r=mid;
        }
        ll down=l;
        printf("%lld\n",up-down);
    }
}

Honk's pool(二分模板题)

标签:分时   ace   for   namespace   res   can   while   最大   二分   

原文地址:https://www.cnblogs.com/ucprer/p/11544522.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!