1 条题解
-
1
本题的关键在于如何考虑问题的可行性
首先,对于这样一个求解最大值的问题,我们发现决策的方向比较离散,即人数和我们每一步的决策似乎没什么关系,因而我们考虑二分答案,贪心验算即可
二分的部分可以略过了
贪心
此时的贪心有一个良好的性质可以利用:即小孩子已经按照钱的数目升序排列完成了,因此我们确定了答案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
- 上传者