CODEVS2744 养鱼喂妹子 - 二分+贪心

传送门

思路:加上能够养活x个妹子,那么必定能养活<x个妹子,满足单调性,可以二分。

我们二分能够养活的最大的妹子数量。对于当前已经符合check函数的mid,ans一定在[mid,r]的区间内,

因此采用 mid=(l+r+1)>>1;if(check(mid)) l=mid;else r=mid-1; 最终答案为 l-1。

关于check函数,我们用一种类似均分纸牌的做法:遍历每个城镇,若当前城镇缺鱼,就向右边要;注意,若当前城镇多鱼,你能给右边不就给吗。。。

最后看下最后一个城镇是否缺鱼。

tips:二分边界要搞好,可以直接[0,+inf],毕竟人家是O(logn)。

AC Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100000+10;
typedef long long ll;
ll pos[N],a[N],b[N];
int n;
bool check(ll mid){
    for(int i=1;i<=n;i++) b[i]-=mid;
    for(int i=1;i<n;i++){
        if(b[i]<0) b[i+1]-=abs(b[i])+abs(pos[i+1]-pos[i]);
        else if(b[i]>pos[i+1]-pos[i]) b[i+1]+=b[i]-(pos[i+1]-pos[i]);
    }
    return b[n]>=0; 
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld%lld",&pos[i],&a[i]);
    }
    ll l=0,r=1<<30;//!!
    while(l<r){
        memcpy(b,a,sizeof(a));
        ll mid=(l+r+1)>>1;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    printf("%lld",l);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Loi-Brilliant/p/9419933.html
今日推荐