C. Keshi Is Throwing a Party(二分)
题目:C. Keshi Is Throwing a Party
题目链接:https://codeforces.com/contest/1610/problem/C
题意:有n个人,编号1 – n,第i个人有i块钱。给出两个长度为n的数组a和b(下标从1 - n)。现在要选人,对于选出来的每个人i,要满足:
- 比i钱多的人数小于等于a[i].
- 比i钱少的人数小于等于b[i]。
求最多可以选出多少个人。
输入描述:
第一行输入测试用例个数t。(1 <= t <= 1e4)。
每个测试用例第一行输入人数n。(1 <= n <= 2e5)。
接下来输入n行,每行两个整数,第i行输入a[i]和b[i]。(0 <= ai, bi < n)。
题目保证所有测试用例n的总和小于等于2e5。
输出描述:
对于每个测试用例,输出最多能选出的人数。
样例输入:
1
3
1 2
2 1
1 1
样例输出:
2
样例解释:可以选择第一个人和第二个人。如果全选,那比第1个人钱多的人数为2 > a[1],不满足条件。当然还可以选择【1】,【2】,【3】,【1,3】,【2,3】。所以最多可选择2个人。
题目分析:对于答案ans,【1,ans】是满足条件的,【ans + 1, n】是不满足条件的。故可以使用二分求解问题。
解题步骤:
- 确定二分的范围。二分下界是1,因为选择1个人时,比他钱多的人和比他钱少的人都为0,一定满足条件。二分上界是n,最多就是n个人。
- check函数:对于传入的mid,定义t = 0,表示当前选择的人有t个。从前往后遍历n个人,对于第i个人,如果比i钱少的人数t(前面选的人钱一定比i少)小于等于b[i]且比i钱多的人数mid – t – 1(总共要选mid个,当前t个 + 第i个1个,后面就还要选mid – t – 1个)小于等于a[i],那么我们就可以选择第i个人。此时t 加1,最后判断t是否大于等于mid即可。
AC代码:
#include<iostream>
using namespace std;
const int N = 2e5 + 10;
int a[N], b[N], n;
bool check(int mid){
int t = 0;
for(int i = 1;i <= n;i++){
if((mid - t - 1) <= a[i] && t <= b[i]) t++;
}
if(t >= mid) return true;
return false;
}
void solve(){
scanf("%d", &n);
for(int i = 1;i <= n;i++) scanf("%d %d", &a[i], &b[i]);
int l = 1, r = n, ans;
while(l <= r){
int mid = (l + r) >> 1;
if(check(mid)){
ans = mid;
l = mid + 1;
}
else r = mid - 1;
}
printf("%d\n", ans);
}
int main(void){
int t;
scanf("%d", &t);
while(t--) solve();
return 0;
}
时间复杂度:O(nlogn),二分执行logn次,每次check函数从前往后遍历n次。
空间复杂度:O(n)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具