当前位置: 首页 > news >正文

二分答案 + P8800 [蓝桥杯 2022 国 B] 卡牌 - 题解

题解:卡牌问题

题目传送门:P8800 [蓝桥杯 2022 国 B] 卡牌

一、题目描述

小明有n种卡牌,每种卡牌有a_i张。他可以用m张空白牌制作任意卡牌,但第i种卡牌最多只能制作b_i张。问最多能凑出多少套"完整卡牌"(每套包含每种卡牌各一张)。

二、题目分析

这是一个典型的二分答案问题。我们需要找到最大的套数x,使得我们可以通过使用空白牌,让每种卡牌的数量都至少达到x张,且使用的空白牌总数不超过m张。

三、解题思路

  1. 二分搜索:我们可以在可能的套数范围内进行二分搜索,检查某个套数x是否可行。
  2. 可行性检查:对于每个候选的x,计算每种卡牌需要补充的数量(x - a_i),但要不超过b_i的限制,且总和不超过m。

四、算法讲解

算法采用二分答案策略:

  1. 排序:虽然题目没有明确要求,但将卡牌按现有数量排序可能有助于优化(但原代码中排序实际上不影响最终结果)。
  2. 二分框架:在可能的套数范围[0, max_a + m]内进行二分搜索。
  3. 检查函数:对于中间值mid,计算将所有卡牌补充到至少mid张所需空白牌数,检查是否满足条件。

以样例为例:

  • 输入:n=4, m=5, a=[1,2,3,4], b=[5,5,5,5]
  • 检查x=3:
    • 需要补充:2(1→3),1(2→3),0(3→3),0(4→3)
    • 总空白牌使用=3 ≤ 5,且每个补充不超过b_i限制
  • 检查x=4:
    • 需要补充:3(1→4),2(2→4),1(3→4),0(4→4)
    • 总空白牌使用=6 > 5,不可行
  • 因此最大可行套数是3

五、代码实现

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int n, m;
struct node {
    int a, b;
} arr[N];

// 排序函数,按现有卡牌数量升序排列
bool cmp(node c, node d) {
    return c.a < d.a;
}

// 检查是否能凑出x套牌
bool check(int x) {
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        int tem = x - arr[i].a;
        if (tem < 0)  // 现有牌已足够,不需要补充
            continue;
        else if (tem > arr[i].b)  // 需要补充的数量超过b_i限制
            return false;
        else {
            cnt += tem;  // 累加需要的空白牌数量
        }
    }
    return cnt <= m;  // 总空白牌使用量不超过m
}

void solve() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> arr[i].a;
    for (int i = 1; i <= n; i++)
        cin >> arr[i].b;
    sort(arr + 1, arr + 1 + n, cmp);  // 按现有数量排序
    
    // 二分查找最大可行套数
    int l = -1, r = 1e6;  // 初始范围设置
    while (l + 1 != r) {
        int mid = l + r >> 1;
        if (check(mid))
            l = mid;
        else
            r = mid;
    }
    cout << l;
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    solve();
    return 0;
}

六、重点细节

  1. 二分边界:初始左边界设为-1,右边界设为1e6,确保覆盖所有可能情况。
  2. 检查函数:必须同时满足两个条件:(1)每种卡牌补充不超过b_i限制;(2)总补充数不超过m。
  3. 排序:虽然排序不是必须的,但可能在某些优化策略中有用(尽管原代码中并未利用排序特性)。

七、复杂度分析

  1. 时间复杂度:O(n log(max_answer)),其中二分次数为log(max_answer),每次检查需要O(n)时间。
  2. 空间复杂度:O(n),用于存储卡牌信息。

八、总结

本题通过二分答案的方法高效地解决了最大套数问题。关键在于设计合理的检查函数来判断某个套数是否可行。算法的时间复杂度能够很好地处理题目给出的数据规模限制(n ≤ 2×10^5)。

这种二分答案的思路在解决"最大化最小值"或"最小化最大值"类问题时非常有效,是算法竞赛中的重要技巧。

相关文章:

  • 网络安全设备介绍:防火墙、堡垒机、入侵检测、入侵防御
  • UniApp集成极光推送详细教程
  • 多模态大语言模型arxiv论文略读(三)
  • Python - 爬虫-网页抓取数据-库urllib
  • 机器视觉之光源选型
  • 微服务的简单认识
  • JAVA:使用 Curator 进行 ZooKeeper 操作的技术指南
  • 算法基础_基础算法【高精度 + 前缀和 + 差分 + 双指针】
  • 标准化与归一化的区别
  • [python] next
  • 01-03手写持久层框架-JDBC问题与框架实现思路
  • NVIDIA工业设施数字孪生中的机器人模拟
  • 嵌入式仿真实验教学平台的核心优势再解析:对比Proteus的技术与教学价值突破
  • GCC RISCV 后端 -- 控制流(Control Flow)的一些理解
  • 【渗透测试】Vulnhub靶机-FSoft Challenges VM: 1-详细通关教程
  • IROS 2025将于杭州举办,开启中国机器人发展与国际交流新契机
  • 第2.6节 iOS生成全量和增量报告
  • 前沿技术有哪些改变生活
  • 最新企业ERP进销存管理系统源码 基于PHP+MySQL 含完整图文部署教程
  • java 启动jar将日志每天输入
  • 19个剧团15台演出,上海民营院团尝试文旅融合新探索
  • 长三角地区中华老字号品牌景气指数发布,哪些牌子是你熟悉的?
  • 纽约大学朗格尼医学中心的转型带来哪些启示?
  • 潘功胜:将创设科技创新债券风险分担工具
  • 老人刷老年卡乘车被要求站着?公交公司致歉:涉事司机停职
  • 今天全国铁路、公路进入返程高峰,这些路段时段通行压力大