P1873 砍树

题目分析:

  • 答案区间[l,r] (l = min(a[i]),r = max(a[i]))
  • 找最优解:最高砍树高度
  • mid取(l + r + 1) >> 1,偏右

注意:

  • 二分出现死循环往往是mid写错了

代码如下:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>

using namespace std;

#define inf 0x3f3f3f3f
#define eps 1e-6
#define db double
#define ll long long
#define  mm(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define pb push_back
#define el endl
#define debug(x) cerr<<#x<<" = "<<x<<endl
#define fgx cerr<<"-------------------------"<<endl
#define shutio ios::sync_with_stdio(false),cin.tie(0)
#define  mk make_pair
#define lowbit(x) (x) & (-x)
#define fi first
#define se second

const int N = 1e6 + 10;

ll n,m;
ll a[N];
ll l,r;

bool check(ll x){
    ll s = 0;
    for(int i = 0; i < n; i ++ ){
        ll t = a[i] - x;
        if(t > 0) s += t;
    }
    return s>=m;    
}

int main() {
    shutio;
    cin >> n >> m;
    l = inf, r = -inf;
    for(int i = 0; i < n; i ++ ){
        cin >> a[i];
        l = min(l,a[i]),r = max(r,a[i]);        
    }
    while(l < r){
        ll mid = (l + r + 1) >> 1;
        if(check(mid)) l = mid;
        else r = mid - 1;
    }
    cout<<l;                    
    return 0;
}