TZOJ:8533
题目大意是每次位于队头的牛 i 拿到一个礼物,然后插入到从队尾数ci头牛之前的位置。询问最后一共有多少头牛是拿不到礼物的。
假设如果第i位能拿到礼物,i+1位拿不到礼物,那么i+1以及i+1之后的所有牛应该也都拿不到礼物,所以这个题目具有二分性,所以可以用二分去做。
那么我们该怎么check判断当前二分答案是否可行呢。如果定x为当前二分答案,也就是x是最后一头能拿到礼物的牛,计num为x之后的牛数量,也就是num=n-x。
那么在x-1位上的c【i】如果大于num,那么就会出现在x之前,如果小于num,就会在x之后,x就往前一位,知道x能到队头,就代表x是可以拿到礼物的,那么就返回true,否则就返回false。但是其实实际上x-1位上如果有出现插到x之前的位置上,x也有可能最后到达队头,那么我们就使x之前的c【i】排一个升序,然后按照上面的顺序使x逐渐往前移,如果c【1】<=num,就把num++,也就是c【1】这个值最后会到x之后,成为x之后的一个数字之一,一直到x-1之前,如果都可行,就返回true,否则就返回false。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N],b[N];
int check(int x)
{
for(int i=1;i<=x-1;i++)b[i]=a[i];
sort(b+1,b+x);
int num=n-x;
for(int i=1;i<=x-1;i++)
{
if(b[i]<=num)num++;
else return 0;
}
return 1;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int l=0,r=n+1;
while(l+1<r)
{
int mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
cout<<n-l<<endl;
}