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

版权声明:转载附上原文地址即可~欢迎各位神犇来虐~ https://blog.csdn.net/Icefox_zhx/article/details/79319008

首先我们发现如果第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;
}
展开阅读全文

没有更多推荐了,返回首页