【二分】C. Keshi Is Throwing a Party

102 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目链接:
codeforces.com/problemset/…

n个盆友,第i个盆友有i块钱,小明想尽可能邀请更多的人。第i个人高兴有个条件,比他钱多的不能超过 aia_i个人,钱少的不能超过 bib_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;
 }