1 条题解

  • 1
    @ 2023-11-12 15:51:38

    本题的关键在于如何考虑问题的可行性

    首先,对于这样一个求解最大值的问题,我们发现决策的方向比较离散,即人数和我们每一步的决策似乎没什么关系,因而我们考虑二分答案,贪心验算即可

    二分的部分可以略过了

    贪心

    此时的贪心有一个良好的性质可以利用:即小孩子已经按照钱的数目升序排列完成了,因此我们确定了答案num之后,依次考虑加入排队的小孩,很容易确定比他富有和穷的小孩人数

    考虑我们的答案序列,在二分确定答案为num的时候,我们对每个小孩依次考虑即可:对于第 i个小孩,如果他能包容前后的人数,他就能参加派对,反之则反

    这里贪心的重点在于已经排好序的小孩和可以被确定的前后人数,当然后者也是考虑二分的重要依据之一(因为二分的num正好满足了对于快速计算前后人数的需求)

    代码

    #include<bits/stdc++.h>
    #define int long long
    #define inf 0x3f3f3f3f3f3f3f3f
    #define For(i,a,b) for(int i=(a);i<=(b);i++)
    #define foR(i,a,b) for(itn i=(a);i>=(b);i--)
    using namespace std;
    const int N=2e5+5;
    int n,a[N],b[N];
    inline void init() {
    	cin>>n;
    	For(i,1,n) scanf("%lld%lld",&a[i],&b[i]);
    	return;
    }
    inline bool check(int num) {
    	int now=1;//表示当前正在检查答案序列中的第now个位置
    	For(i,1,n) if(a[i]>=num-now&&b[i]>=now-1) {
    		++now;
    		if(now>num) return true;//注意中途退出,不然容易Runtime Error
    	}//如果这位同学足够宽宏大量 
    	return now>num;
    }
    inline void solve() {
    	int l=0,r=n+1,mid,ans=-1;
    	while(l<=r) {
    		mid=l+r>>1;
    		if(check(mid)) l=mid+1,ans=mid;
    		else r=mid-1;
    	}
    	printf("%lld\n",ans);
    	return;
    }
    signed main() {
    	int T;
    	cin>>T;
    	while(T--) {
    		init();
    		solve();
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    8
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    8
    已通过
    2
    上传者