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

今天给大家写一篇关于蓝桥杯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)

总结

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

相关推荐
zero_one_Machel2 分钟前
leetcode73矩阵置零
算法·leetcode·矩阵
青椒大仙KI1133 分钟前
24/9/19 算法笔记 kaggle BankChurn数据分类
笔记·算法·分类
^^为欢几何^^37 分钟前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
豆浩宇37 分钟前
Halcon OCR检测 免训练版
c++·人工智能·opencv·算法·计算机视觉·ocr
浅念同学1 小时前
算法.图论-并查集上
java·算法·图论
何不遗憾呢1 小时前
每日刷题(算法)
算法
立志成为coding大牛的菜鸟.1 小时前
力扣1143-最长公共子序列(Java详细题解)
java·算法·leetcode
鱼跃鹰飞1 小时前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先
liangbm31 小时前
数学建模笔记——动态规划
笔记·python·算法·数学建模·动态规划·背包问题·优化问题
潮汐退涨月冷风霜1 小时前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习