多路归并算法加二分查找(技能升级)

今天给大家写一篇关于蓝桥杯2023年的一道题:

归并排序是一种二分排序,这里介绍的是一种更为高级的归并, 多路归并是从多个有序序列中逐个抽取序列首元素最大值,全部抽取完成后得到一条有序序列 应用到该题上就是每个首项为ai公差为−bi的等差序列都为有序序列,而共有n条有序序列,其中利用多路归并抽取m个最大值即能组成最终序列前m个元素,显然该m个元素和最大

小蓝最近正在玩一款 RPG 游戏。他的角色一共有 N 个可以加攻击力的技能。其中第 i 个技能首次升级可以提升 Ai 点攻击力,以后每次升级增加的点数都会减少 Bi。(上取整)次之后,再升级该技能将不会改变攻击力。现在小蓝可以总计升级 M次技能,他可以任意选择升级的技能和次数。请你计算小蓝最多可以提高多少点攻击力?

输入格式

输入第一行包含两个整数 N 和 M。

以下 N 行每行包含两个整数 Ai 和 Bi。

输出格式

输出一行包含一个整数表示答案。

数据范围

输入样例:

复制代码
3 6
10 5
9 2
8 1

输出样例:

复制代码
47

优化思路:

纯暴力思路:

做等差数列的每一个值,然后排序去查找每一个数,直到第m个数字,判断前m个数字最大值是多少,这是简单粗暴的想法,比赛的时候可以直接去使用。这个的话,它的m最多有10yi个,首选项最大是10万,等差数列的项最小是1,这最坏情况下得几百个亿的次数,肯定不是现实。

优化

看到这种题首先得考虑二分查找,在这个题的话,就利用二分查找,在0到1e6的范围内去查找第m个数字x,这个x的话它一定 满足在等差数列的里面,(不一定是所有的等差数列,首项大于等于x,这样的才满足)然后去计算等差数列首项到x它减少的次数,这个满足向下取整在加1,记住这个就可以,论证(

)完了之后,去做计算所有的等差数列的减少次数和总和,这里需要注意的是它可能会有多个相同的x,这个需要单独减去一下,也就是代码的最后一步。

#多路归并加二分 复制代码
n,m = map(int,input().split())
a,b = [],[]
for i in range(n):
    i,j = map(int,input().split())
    a.append(i);b.append(j)
def check(mid):
    cnt = 0
    for i in range(len(a)):
        if a[i]>=mid:
            d = (a[i]-mid)//b[i] + 1
            cnt += d
    return cnt>=m
l,r = 0,int(1e6)
while l<r:
    mid = l+r+1 >> 1
    if check(mid):l = mid
    else:r = mid -1
res = 0
k = 0
for i in range(n):
    if a[i]>=l:
        d = (a[i]-l)//b[i] + 1
        k += d
        end = a[i]-(d-1)*b[i]
        res += (a[i]+end)*d//2
print(res-(k-m)*l)

总结

这种优化思路一般可能,直接想不到,所有先暴力跑一遍,然后在想办法去优化,多路归并一般想不到这个东西,但是完全可以从等差数列的数学角度来想到这个优化方案。

相关推荐
木心月转码ing17 分钟前
Hot100-Day10-T438T438找到字符串中所有字母异位词
算法
HelloReader1 小时前
Wi-Fi CSI 感知技术用无线信号“看见“室内的人
算法
颜酱4 小时前
二叉树分解问题思路解题模式
javascript·后端·算法
qianpeng8975 小时前
水声匹配场定位原理及实验
算法
董董灿是个攻城狮17 小时前
AI视觉连载8:传统 CV 之边缘检测
算法
AI软著研究员1 天前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish1 天前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱1 天前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
地平线开发者2 天前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮2 天前
大模型连载2:初步认识 tokenizer 的过程
算法