本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目链接:
codeforces.com/problemset/…
n个盆友,第i个盆友有i块钱,小明想尽可能邀请更多的人。第i个人高兴有个条件,比他钱多的不能超过 个人,钱少的不能超过 个,求最多能邀请的人数。
可以发现对于人数有一个单调的性质,假设答案为ans,人数大于ans的情况必然不会满足,人数小于等于ans的必然满足条件。
基于单调性使用二分
二分主要是检验函数:
假设此时选择的人数为x
人标号 1 , 2 , 3 , 4 , 5 ,....,x
比其钱少的人数 0, 1, 2, 3, 4,....,x-1
比其钱多的人数x-1,x-2,x-3,x-4,x-5,..., 0
只要满足每个人的情况a[i]>=比其钱多的人数,b[i]>=比其钱少的人数,从前往后遍历即可。
最近准备转换一下代码风格,尽量减少全局变量的使用。尽量在一个函数内实现相应的功能。
所以本代码出现了lamda表达式内容。
二分方法是一种降低算法复杂度的有效的方法,主要是题目中存在一个有单调性的性质,这个性质或者特性需要自己去寻找,利用这个单调性对此进行二分,就可以快速找到答案。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
void solve()
{
int n;
cin>>n;
vector<int>a(n+1),b(n+1);
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
function<bool(int)> check = [&](int x)->bool
{
int cur = 0;
for(int i=1;i<=n;i++)
if(b[i]>=cur and a[i]>=x-1-cur and cur<=x-1) cur++;
if(cur>x-1) return true;
return false;
};
int l=0,r=n;
while(l<r)
{
int mid = l + r + 1 >> 1;
if(check(mid)) l = mid;
else r = mid - 1;
}
cout<<l<<endl;
}
int main()
{
int t;
// t = 1;
cin>>t;
while(t--) solve();
return 0;
}