首页 > 编程语言 >二分算法习题汇总

二分算法习题汇总

时间:2023-10-29 21:45:09浏览次数:29  
标签:二分 le int 汇总 mid long 青蛙 习题 include

一、复制书稿

题目描述

现在要把 \(m\) 本有顺序的书分给 \(k\) 个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。

现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。

输入格式

第一行两个整数 \(m,k\)。

第二行 \(m\) 个整数,第 \(i\) 个整数表示第 \(i\) 本书的页数。

输出格式

共1行:分配给抄写员的页数的最大值

样例 #1

样例输入 #1

9 3
1 2 3 4 5 6 7 8 9

样例输出 #1

17

提示

\(1\le k \le m \le 500\)。

代码实现

#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 向一所小学捐赠了一些青蛙,这些青蛙一共有 \(M\) 种品种,每只青蛙都属于一种品种。

老师需要把所有的青蛙分给 \(N\) 个孩子。每个孩子得到的所有青蛙都必须属于相同的品种,而且可以有一些孩子一只青蛙也没得到。

我们把怄火值定义为得到青蛙最多的孩子得到的青蛙数量。请你帮助老师分青蛙,使得怄火值最小

例如,如果有 \(4\) 只红品种的青蛙(\(\texttt{RRRR}\))和 \(7\) 个蓝品种的青蛙(\(\texttt{BBBBBBB}\)),要分给 \(5\) 个孩子,

那么我们可以这样划分:\(\texttt{RR}\),\(\texttt{RR}\),\(\texttt{BB}\),\(\texttt{BB}\),\(\texttt{BBB}\)。这样分的怄火值为 \(3\),是最小的。

输入格式

第一行两个正整数,\(N,M\),含义如题目所示。

第二行 \(M\) 个整数,表示第 \(M\) 个品种的青蛙有几只,保证每个品种的青蛙的数量都在 \([1,10^9]\) 中。

输出格式

一行一个整数,表示最小的怄火值。

样例 #1

样例输入 #1

7 4
1 2 3 4

样例输出 #1

2

提示

对于 \(20\%\) 的数据,保证 \(1 \le M \le 10\)。

对于另外 \(30\%\) 的数据,保证 \(1\le M\le 1000\),\(1\le N\le 10000\)。

对于 \(100\%\) 的数据,保证 \(1 \le M \le 3 \times 10^5\),\(1 \le N \le 10^9\),\(M \le N\)。

代码实现

#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;
}

三、平均数

题目描述

给一个长度为 \(n\) 的数列,我们需要找出该数列的一个子串,使得子串平均数最大化,并且子串长度 \(\ge m\)。

输入格式

第一行两个整数 \(n\) 和 \(m\)。

接下来 \(n\) 行,每行一个整数 \(a_i\),表示序列第 \(i\) 个数字。

输出格式

一个整数,表示最大平均数的 \(1000\) 倍,如果末尾有小数,直接舍去,不要用四舍五入求整。

样例 #1

样例输入 #1

10 6
6
4
2
10
3
8
5
9
4
1

样例输出 #1

6500

提示

数据规模与约定

  • 对于 \(60\%\) 的数据,保证 \(m\le n\le 10^4\);
  • 对于 \(100\%\) 的数据,保证 \(1 \leq m\le n\le 10^5\),\(0\le a_i\le2000\)。

代码实现

#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;
}

标签:二分,le,int,汇总,mid,long,青蛙,习题,include
From: https://www.cnblogs.com/hsy2093/p/17796564.html

相关文章

  • C语言二分查找法新手
    如果有一天我们想通过输入一个数去查找这个数在数组的下标。我们应该怎么去实现呢?首先我们肯定要创建一个数组组,我们知道数组的数组是从零开始的,首先呢,我们要了解二分查找法可以在百度里面查到。二分查找也称折半查找,它是一种效率较高的查找方法。但是,折半查找要求线性表必须采......
  • 系统集成易混淆知识点汇总-成本基准、项目预算
    概念:(1)成本基准:成本基准是经过高级管理层批准的、按时间段分配的项目预算,但不包括管理储备。(2)项目预算:项目预算是在成本基准的基础上增加管理储备而得到的,是项目的总预算。区别:成本基准中不包含管理储备但包含应急储备,项目预算则是包含管理储备的项目总预算。......
  • 系统集成易混淆知识点汇总-完工预算、完工估算
    概念:(1)完工预算(BAC):完工预算是在编制项目计划时确定的,完成整个项目所需的总成本。(2)完工估算(EAC):完工估算是在项目执行过程中的某个时间点,根据项目的绩效情况,所估计的完成整个项目所需的总成本。区别:(1)完工预算一经确定,通常不进行修改,如需修改,必须经过变更控制流程,由变更控制委员会......
  • 系统集成易混淆知识点汇总-参数估算、类比估算、三点估算、自下而上估算
    概念:(1)参数估算:参数估算是一种基于历史数据和项目参数,使用某种算法来计算成本或工期的估算技术。利用历时数据之间的统计关系和其他变量,来估算诸如成本、预算和持续时间等活动参数。(2)类比估算:类比估算是指以过去类似项目的参数值或规模指标为基础,来估算当前项目的同类参数或指标......
  • 系统集成易混淆知识点汇总-应急储备、管理储备
    概念:(1)应急储备:应急储备是用来应对可预测风险(已知-未知风险:可预见其发生-不可预见其发生后果的风险)的应急时间或应急费用。(2)管理储备:管理储备是用来应对不可预测风险(未知-未知风险:不可预见其发生-不可预见其发生后果的风险)的应急时间或应急费用。区别:(1)应急储备用来应对可预测风......
  • 系统集成易混淆知识点汇总-质量保证、质量控制
    概念:(1)质量保证一般是每隔一定时间(例如,每个阶段末)进行的,主要通过系统的质量审计和过程分析来保证项目的质量(产品/系统/服务的质量保证;管理过程的质量保证)。也就说质量保证是按质量管理计划正确地做。(2)质量控制是实时监控项目的具体结果,以判断它们是否符合相关质量标准,制订有效方......
  • 系统集成易混淆知识点汇总-WBS、RBS、OBS
    概念:(1)WBS:WBS是工作分解结构,是以可交付成果为导向的工作层次分解,其分解的对象是项目团队为实现项目目标、提交所需可交付成果而实施的工作。(2)RBS:RBS是资源分解结构,是资源依类别和类型的层级展现,类别:人力、设备、材料和用品;类型:技能水平、等级水平等。(3)OBS:OBS是组织分解结构,与工......
  • 系统集成易混淆知识点汇总-虚拟团队、集中办公
    概念:(1)虚拟团队:虚拟团队是指在大多数时间并不面对面集中办公,而是通过互联网技术来分散办公的团队。(2)集中办公:集中办公是指把主要团队成员安排在同一物理地点工作,以便加强团队建设,提高团队绩效。集中办公可以是临时或永久的。区别:(1)物理空间不同。虚拟团队的团队成员分散在不同的......
  • 系统集成易混淆知识点汇总-风险规避、风险转移
    概念:(1)风险规避:风险规避是指通过改变项目计划,把项目目标与某个威胁隔离开来,使项目目标【完全】不受该威胁的影响。(2)风险转移:风险转移是指通过签署风险转移合同,把某个或某些【单个项目】风险转移给第三方承担,或者把【整体项目】风险转移给第三方承担。区别:(1)规避是要使项目彻底不......
  • 系统集成易混淆知识点汇总-风险减轻、风险接受
    概念:(1)风险减轻:风险减轻是指采取措施【降低消极】风险发生的概率或后果。(2)风险接受:风险接受是指不主动应对风险,而是被动地等风险发生后再采取措施去应急,或者仅准备一些【应急储备】用于风险发生后的应急。区别:(1)风险减轻仅适用于消极风险,而【风险接受】既可用于【消极风险】,也可......