题意
对于第i个人的权值为i,一个人能被加入序列当且仅当,数列中大于i的数至多不超过ai,小于i的数至多不超过bi,问最多能选多少人
题解
很明显的二分答案,那么需要考虑的就是怎么写check了.直接上代码解释
bool check(int mid)//当前是否能够选取mid人
{
int cnt = 0;//当前已经选取了cnt人
for (int i = 1; i <= n; i++)
//有小到大枚举当前已经选了cnt人,
//那么要在加入一人就是cnt+1的位置且最后满足mid个人则序列一定为
//1...cnt cnt+1 ....mid,因为是从小到大枚举所以左边一定小于num[i],则只只要满足下面一个不等式即可加入数列中(比当前数小的个数为cnt,比当前数大的数为mid-(cnt+1))
if (a[i]>=mid-1-cnt && b[i]>=cnt) ++cnt;
return cnt >= mid;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N], b[N];
int n;
bool check(int mid)
{
int cnt = 0;
for (int i = 1; i <= n; i++)
if (a[i]>=mid-1-cnt && b[i]>=cnt) ++cnt;
return cnt >= mid;
}
void slove()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i] >> b[i];
}
int l = 0, r = n;
while (l < r)
{
int mid = (l + r+1) / 2;
if (check(mid))l = mid;
else r = mid - 1;
}
cout << l << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
slove();
}
}