二分算法习题汇总
二分算法习题汇总
一、复制书稿
题目描述
现在要把
现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。
输入格式
第一行两个整数
第二行
输出格式
共1行:分配给抄写员的页数的最大值
样例 #1
样例输入 #1
9 3
1 2 3 4 5 6 7 8 9
样例输出 #1
17
提示
代码实现
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <algorithm>
#include <cstring>
using namespace std;
int M, K;
int page[505];
//判别答案合法性
bool check(int num){
int group = 1, rest = num;
for(int i = 0; i < M; i++){
//如果这个人当前可以抄的上限页数大于当前这本书书的页数,就交给他抄,不用新增人。
if(rest >= page[i]) rest -= page[i];
//如果这个人抄不了这本书,就要再来一个人,并且更新他的上限页数。
else{
group ++;
rest = num - page[i];
if(rest < 0)
return false;
}
}
//group表示最少需要多少个人
return group <= K;
}
int main(){
cin >> M >> K;
int sum = 0;
int l = 0, r, mid;
for(int i = 0; i < M; i++){
cin >> page[i];
sum += page[i];
}
r = sum;
while(l < r){
mid = (l + r) >> 1;
//如果mid合法,则在左区间寻找答案
if(check(mid))
r = mid;
else
l = mid + 1;
}
cout << l << endl;
}
二、 青蛙(frog)
题目描述
小 L 向一所小学捐赠了一些青蛙,这些青蛙一共有
老师需要把所有的青蛙分给
我们把怄火值定义为得到青蛙最多的孩子得到的青蛙数量。请你帮助老师分青蛙,使得怄火值最小。
例如,如果有
那么我们可以这样划分:
输入格式
第一行两个正整数,
第二行
输出格式
一行一个整数,表示最小的怄火值。
样例 #1
样例输入 #1
7 4
1 2 3 4
样例输出 #1
2
提示
对于
对于另外
对于
代码实现
#include <stdio.h>
#include <iostream>
using namespace std;
int a[300005];
int n, m;
bool check(int mid){
int cnt = 0;
for(int i = 1; i <= m; i++){
if(a[i] % mid == 0) cnt += (a[i]/mid);
else cnt += (a[i]/mid+1);
if(cnt > n) return false;
}
return true;
}
int main() {
int maxx = 0;
cin >> n >> m;
for(int i = 1; i <= m; i++){
cin >> a[i];
maxx = max(maxx, a[i]);
}
int l = 1, r = maxx;
while(l < r){
int mid = (l+r) / 2;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << r << endl;
}
三、平均数
题目描述
给一个长度为
输入格式
第一行两个整数
接下来
输出格式
一个整数,表示最大平均数的
样例 #1
样例输入 #1
10 6
6
4
2
10
3
8
5
9
4
1
样例输出 #1
6500
提示
数据规模与约定
- 对于
的数据,保证 ; - 对于
的数据,保证 , 。
代码实现
#include <stdio.h>
#include <iostream>
using namespace std;
long long a[100005], sum[100005];
long long n, m, maxx = 0;
bool check(long long mid){
long long minn = 1e15;
for(int i = 1; i <= n; i++){
sum[i] = sum[i-1] + a[i] - mid;
if(i >= m){
//可能为一个负值
minn = min(minn, sum[i-m]);
if(sum[i] >= minn) return true;
}
}
return false;
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
a[i] *= 10000;
if(maxx < a[i]) maxx = a[i];
}
long long l = 0, r = maxx, mid;
while(l < r){
mid = (l+r+1) / 2;
if(check(mid)) l = mid;
else r = mid-1;
}
cout << l / 10 << endl;
return 0;
}
四、查询(query)
题目描述
青蛙老师有三个长度为
给定一个正整数
但是他不会做,于是将问题交给你了。
输入格式
第一行一个正整数
第二行
第三行
第四行
接下来一行,一个正整数
输出格式
一行一个整数表示答案。
样例#1
样例输入#1
5
1 3 6 4 1
3 8 9 2 6
5 6 5 3 2
10
样例输出#1
16
数据范围
对于
对于另外
对于另外
对于另外
对于
代码实现
//query.cpp
#include <stdio.h>
#include <iostream>
#include <algorithm>
typedef long long ll;
using namespace std;
ll a[100005], b[100005], c[100005];
ll n, k;
bool check(ll x){
ll cnt = 0;
//当固定i时,有多少个c满足乘积结果小于x的情况
for(int i = 1; i <= n; i++){
ll l = 0, r = n;
while(l < r){
ll mid = (l + r + 1) / 2;
if(a[i] + b[i] * c[mid] >= x) r = mid-1;
else l = mid;
}
cnt += l;
}
if(cnt >= k) return true;
else return false;
}
int main(){
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
for(int i = 1; i <= n; i++) cin >> c[i];
cin >> k;
sort(c+1, c+n+1);
ll l = 0, r = 1e19;
//固定i,找对应的j
while(l < r){
ll mid = (l + r + 1) / 2;
//check合法证明序列中有k个数或大于k个数小于mid,所以mid应该往更小的地方找
if(check(mid)) r = mid - 1;
//否则要往大了找
else l = mid;
}
cout << r << endl;
return 0;
}
本文作者:hsy2093
本文链接:https://www.cnblogs.com/hsy2093/p/17796564.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步