【题解】AT_abc388_e AtCoder Beginner Contest ABC388 E Simultaneous Kagamimochi

题目大意

题目传送门------原题面链接

建议阅读本次比赛 C 题题面。

有 N N N 块米糕,按大小升序排列,第 i i i 块米糕的大小为 A i A_i Ai。

现在定义"堆叠式米糕"如下:

  • 首先,选出两个米糕 A A A 和 B B B,设其大小分别为 a a a 和 b b b。
  • 如果 a ≤ b 2 a \le \frac{b}{2} a≤2b,那么 A A A 可以堆在 B B B 的上面,它们形成了一块"堆叠式米糕"。

现在,问最多同时组成多少块"堆叠式米糕"。

具体地,要找出一个尽可能大的非负整数 K K K 满足如下条件:

  • 所有米糕中,可以选择 2 ⋅ K 2 \cdot K 2⋅K 块形成 K K K 个"堆叠式米糕"。

思路

不会二分答案的读者推荐学习二分查找及贪心相关内容,本篇题解限于篇幅不再过多讲解。

看到这样套路化的问法,我们可以想到一种算法------二分答案。也就是说,我们要通过二分的方式,迅速地找到答案。

每一次,我们折半得到一个整数 m i d mid mid,然后使用一个基于贪心构造的函数来检查它是否满足题意。如果满足,我们把左边界设为 m i d mid mid,向右寻找更大的答案;如果不满足,那么更大的答案显然也不满足,所以我们把右边界设为 m i d − 1 mid - 1 mid−1,向左寻找合法答案。我们重复此过程直到答案值域缩小到一个数,此时这个数就是最终的答案。

接下来,让我们来看一看这个检查函数怎么写。首先,大家思考一个问题------较小的那个米糕要选哪些呢?显然,为了确保不会漏下任何可能,一定要选最小的那些!选择哪些米糕不重要,重要的是我们要贪心地判断该答案是否可行。然后思考较大的米糕------显然,小的较小米糕匹配小的较大米糕,未雨绸缪,以备后患,避免直接取最大的后面会没得选。还有一个小细节,我们要避免重复选择。这里实现方式不唯一,大家自行思考吧。

代码

Submission #61583414

自认为这个方法是代码较为简短,思路较为简单清晰的一个做法,时间复杂度 O ( n ⋅ l o g n ) O(n \cdot log n) O(n⋅logn)。如果各位大神有更优做法,欢迎在评论区提出或私信讨论!

相关推荐
Rabitebla41 分钟前
【C++】string 类:原理、踩坑与对象语义
linux·c语言·数据结构·c++·算法·github·学习方法
邪修king1 小时前
UE5 零基础入门第四弹:UMG UI 系统入门,从静态界面到逻辑联动
c++·ui·ue5
CN-Dust2 小时前
【C++】输入cin例题专题
java·c++·算法
智者知已应修善业9 小时前
【51单片机中的打飞机设计】2023-8-25
c++·经验分享·笔记·算法·51单片机
智者知已应修善业11 小时前
【51单片机按键调节占空比3位数码管显示】2023-8-24
c++·经验分享·笔记·算法·51单片机
徐某人..13 小时前
基于i.MX6ULL平台的智能网关系统开发
arm开发·c++·单片机·qt·物联网·学习·arm
无敌秋14 小时前
# C++ 简单工厂模式实战指南
c++·简单工厂模式
cany100014 小时前
C++ -- 模板的声明和定义
开发语言·c++
澈20714 小时前
深耕进阶 Day1:C 与 C++ 核心差异 + C++ 入门基石
c语言·开发语言·c++