首页 > 编程语言 >C++U4-第06课-二分答案

C++U4-第06课-二分答案

时间:2023-11-28 11:55:57浏览次数:31  
标签:二分 满足条件 06 边界 int U4 mid C++ ans

上节课作业解析

链接:https://pan.baidu.com/s/1QCDg1GXb5HhrpkPgomOCyg?pwd=s4b4
提取码:s4b4

二分答案学习目标

二分查找单调性意思

 二分答案单调性

 二分答案的思路

[【二分答案】砍树(简单版)]

枚举每一棵树,注意当锯片高度高于树的高度时砍的树木是 0。

#include <iostream>
using namespace std;

int a[1000009], n;
long long sum(int x) {
    long long s = 0;
    for (int i = 1; i <= n; i++) {
        s += max(0, a[i] - x);
    }
    return s;
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    int h;
    cin >> h;
    cout << sum(h);
    return 0;
}
View Code

 

 

[【二分答案】 砍树]

 

#include <iostream>
using namespace std;

int a[1000009], n, m; // 定义大小为1000009的整数数组a,变量n和m

// 判断是否满足条件
bool sum(int x) {
    long long s = 0;
    for (int i = 1; i <= n; i++) {
        s += max(0, a[i] - x); // 计算s,累加大于x的元素与x之差
    }
    return s >= m; // 返回是否满足目标值m
}

int main() {
    cin >> n >> m; // 输入n和m

    for (int i = 1; i <= n; i++) {
        cin >> a[i]; // 输入数组a的元素
    }

    int l = 0, r = 1e9, ans; // 初始化左边界l为0,右边界r为1e9(10^9),结果ans

    while (l <= r) {
        int mid = (l + r) >> 1; // 计算中间值mid,等于左右边界之和的一半

        if (sum(mid)) {
            ans = mid; // 如果满足条件,则更新结果ans为当前的mid
            l = mid + 1; // 更新左边界l为mid+1,继续在更大的数段中搜索
        }
        else {
            r = mid - 1; // 否则,更新右边界r为mid-1,继续在更小的数段中搜索
        }
    }

    cout << ans; // 输出结果ans
    return 0;
}

代码的具体思路如下:

声明一个大小为1000009的整数数组 a,以及变量 n 和 m。
定义函数 sum,用于判断是否满足条件。在函数内部,使用循环遍历数组 a,并累加大于 x 的元素与 x 之差,将结果保存在变量 s 中。最后,返回 s 是否大于等于目标值 m。
主函数开始,读取输入的整数 n 和 m,表示数组 a 的长度和目标值。
使用循环读取数组 a 的元素。
初始化左边界 l 为0,右边界 r 为1e9(即10^9),用于确定二分答案的搜索范围。
进行二分查找,当左边界小于等于右边界时,进行循环迭代。
在每次迭代中,计算中间值 mid,使用位运算 (l + r) >> 1 将左右边界之和除以2。
调用 sum(mid) 判断是否满足条件,如果满足,则更新结果 ans 为当前的 mid,并将左边界 l 更新为 mid + 1,继续在更大的数段中搜索。
如果不满足条件,则将右边界 r 更新为 mid - 1,继续在更小的数段中搜索。
当左边界大于右边界时,二分查找结束,得到满足条件的最优解 ans。
输出结果 ans。
返回0表示程序正常结束。
该代码使用二分答案的方法,在给定的范围内查找满足条件的最优解,并输出结果。通过调用 sum 函数来判断是否满足条件,根据返回值更新左右边界进行二分查找。最终得到的 ans 是满足条件的最优解。
View Code

 

 

[数列分段]

 

 【数列分段视频讲解,思路一样,代码有一点差别】 https://www.bilibili.com/video/BV1ye4y1D7Xs/?share_source=copy_web&vd_source=a7ac0c0928d95f5dba9f91d92ac06af8

 

#include <iostream>
using namespace std;

const int maxn = 1e5 + 10; // 定义常量maxn为1e5 + 10
int A[maxn], N, M; // 定义整数数组A,变量N和M

// 判断是否满足条件
bool check(int mid) {
    int section = 0; // 初始化区间个数section为0

    for (int i = 1; i <= N; i++) { // 循环遍历数组A的元素
        int j = i, sum = 0; // 定义变量j为i,sum为0
        section++; // 增加区间个数

        while (j <= N && sum + A[j] <= mid) { // 在当前区间内查找满足条件的子区间
            sum += A[j]; // 累加当前元素到sum
            j++; // 移动指针j
        }

        i = j - 1; // 更新指针i为j-1,跳过已经访问的元素
    }
    
    return section <= M; // 返回区间个数是否小于等于目标值M
}

int main() {
    cin >> N >> M; // 输入N和M

    int ma = 0; // 初始化最大元素ma为0

    for (int i = 1; i <= N; i++) { // 循环读取数组A的元素
        cin >> A[i];
        ma = max(ma, A[i]); // 更新最大元素ma
    }

    int l = ma, r = 1e9, ans; // 初始化左边界l为ma,右边界r为1e9(10^9),结果ans

    while (l <= r) { // 二分查找,当左边界小于等于右边界时进行循环
        int mid = (l + r) >> 1; // 计算中间值mid,等于左右边界之和的一半
        
        if (check(mid)) { // 如果满足条件,则更新右边界r为mid-1,并更新结果ans为当前的mid
            r = mid - 1;
            ans = mid;
        } else { // 否则,更新左边界l为mid+1
            l = mid + 1;
        }
    }

    cout << ans; // 输出结果ans
    return 0;
}

代码的具体思路如下:

声明一个大小为 maxn 的整数数组 A,以及变量 N 和 M。
定义函数 check,用于判断是否满足条件。在函数内部,使用两个指针 i 和 j 遍历数组 A,并同步累加元素到变量 sum 中。每次发现满足条件时,增加区间 section 的个数,并将指针 i 更新为 j-1,跳过已经访问的元素。最后返回区间个数是否小于等于目标值 M。
主函数开始,读取输入的整数 N 和 M,表示数组 A 的长度和目标值。
使用循环读取数组 A 的元素,并更新最大元素 ma。
初始化左边界 l 为 ma,右边界 r 为1e9(即10^9),用于确定二分答案的搜索范围。
进行二分查找,当左边界小于等于右边界时,进行循环迭代。
在每次迭代中,计算中间值 mid,使用位运算 (l + r) >> 1 将左右边界之和除以2。
调用 check(mid) 判断是否满足条件,如果满足,则将右边界 r 更新为 mid - 1,并更新结果 ans
View Code

 

本节课作业视频分享

链接:https://pan.baidu.com/s/1JLX8ZIGJFzoRtGASZIINsw?pwd=qzwj
提取码:qzwj

 

标签:二分,满足条件,06,边界,int,U4,mid,C++,ans
From: https://www.cnblogs.com/jayxuan/p/17861572.html

相关文章

  • C++ bool 类型
    @TOC一.bool类型在C++中,bool类型用于表示逻辑值,它只有两个可能的取值:true(真)和false(假)。bool类型常用于条件判断和布尔运算中。C++标准要求bool类型占用一个字节的内存空间。它的取值只能是true或false,并且可以通过关键词true和false直接赋值。下面是一些常见的使......
  • C++获取机器启动至今的时长和机器启动的时间戳
    根据当前时间戳与机器启动至今的时间长度相减,可以精确计算出机器启动时刻的时间戳epochtime代码#include<iostream>#include<stdio.h>#include<time.h>#include<chrono>intmain(){#ifdef__linux //linuxonly std::cout<<"===linuxonlytimeanalysis==......
  • C/C++ Zlib实现文件压缩与解压
    在软件开发和数据处理中,对数据进行高效的压缩和解压缩是一项重要的任务。这不仅有助于减小数据在网络传输和存储中的占用空间,还能提高系统的性能和响应速度。本文将介绍如何使用zlib库进行数据的压缩和解压缩,以及如何保存和读取压缩后的文件。zlib是一个开源的数据压缩库,旨在提......
  • C++ 十进制与十六进制转换
    文章作者:里海十进制与十六进制转换#include<iostream>#include<string>usingnamespacestd;//十进制整数转十六进制字符串stringDecimalToHex(longlongdecimal){stringhex="";while(decimal>0){intremainder=decimal%16;......
  • C++ 查找文本文件中字符串是否存在
    简介查找文本文件中字符串是否存在代码#include<iostream>#include<fstream>#include<vector>#include<string>usingnamespacestd;boolSearchString(stringfilePath,stringstrF){vector<string>lines;stringline;ifst......
  • C\C++ 使用RapidJSON库,轻松解析和生成JSON
    简介  RapidJSON是一个高效的C++JSON解析器和生成器。它专注于性能和易用性,使得处理JSON数据变得简单和快速。RapidJSON支持现代的JSON特性,如嵌套对象、数组、Unicode编码和注释。它的API简洁易用,可以轻松解析和生成JSON数据。无论你的项目需要处理大量的JSON数据,还是只需要解析......
  • C++ 字符串编码转换封装函数,UTF-8编码与本地编码互转
    简介字符串编码转换封装函数,UTF-8编码与本地编码互转。中文乱码的解决方法有时候我们会遇到乱码的字符串,比如:古文码可能是用GBK方式读取UTF-8编码的中文导致的,用下面的Utf8ToLocal(stringstr)函数转换一下就可以了。口字码可能是因为以UTF-8的方式读取GBK编码的中文导致的,用下面......
  • C++ 01.学习C++的意义-狄泰软件学院
    一些历史UNIX操作系统诞生之初是用汇编语言编写的随着UNIX系统的发展,汇编语言的开发效率成为瓶颈,所以需要一个新的语言替代汇编语言1971年通过对B语言改良,使其能直接产生机器代码,C语言诞生UNIX使用C语言重写,同时C语言在实践中不断升级完善。C语言的特点没有深思熟虑的设计过程残留......
  • C++ 修改文件创建时间、修改时间属性
    简介        修改文件创建时间、修改时间、大小等属性。        博客《C++获取文件创建时间、修改时间、大小等属性》分享后,好兄弟“古月”发来一段代码,说可以修改文件的创建时间等。测试了一下真可以,下面是运行效果和代码:代码#include<windows.h>#include<f......
  • C++ 使用Windows的API CreateDirectory 创建多层级文件夹
    简介使用Windows的API创建多层级文件夹效果代码#include<windows.h>#include<direct.h>#include<iostream>#include<string>#include<sstream>#include<vector>//创建多层级文件夹boolCreateDir(conststd::string&path){ std::......