bzoj5139 [Usaco2017 Dec]Greedy Gift Takers(二分答案+模拟)

本文介绍了一种通过二分查找确定在特定排列下无法获取礼物的牛的最小编号的方法。利用预处理找出每头牛可能停留的位置,并检查是否存在使得某些牛永远无法前进的死循环。若存在死循环,则采用二分法找到首头受影响的牛。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们发现如果第x头牛不能拿到礼物,则x之后的所有牛也不能拿到礼物。因此我们可以二分来找到这第一头不能拿到礼物的牛。满足什么条件的牛不能拿到礼物呢?我们预处理出每头牛拿到礼物之后会出现在哪里,如果在第x头牛之前的牛们形成了一个死循环,则第x头牛就永远也拿不到礼物了。怎么样会形成一个死循环呢?出现在前i个位置的牛有多于i头,则这i头牛就会一直卡在这前i个位置。因此我们模拟一下这个过程看有没有死循环出现就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,a[N],cnt[N];
inline bool jud(int mid){//判断mid是不是不能拿到礼物
    memset(cnt,0,sizeof(cnt));int sum=0;
    for(int i=1;i<mid;++i) cnt[a[i]]++;
    for(int i=1;i<mid;++i){
        sum+=cnt[i];if(sum>=i) return 1;
    }return 0;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();for(int i=1;i<=n;++i) a[i]=n-read();
    int l=1,r=n;//找第一个不能拿到礼物的牛
    while(l<=r){
        int mid=l+r>>1;
        if(jud(mid)) r=mid-1;else l=mid+1;
    }++r;printf("%d\n",n-r+1);
    return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值