题解 | #魔导模块的效能迭代#

魔导模块的效能迭代

https://www.nowcoder.com/practice/e6a6c0b188a246829c10cf388ac3f73e

题目链接

魔导模块的效能迭代

题目描述

小红维护一个由 个魔导模块组成的系统,每个模块 的初始执行耗时为 ,性能下限为 。 小红有 天时间,每天可以挑选一个模块进行优化。若选中模块当前耗时为 ,优化后变为 ,但不能低于 。即优化后的新耗时为 。 求 天优化后,所有模块执行耗时之和的最小值。

解题思路

这是一个典型的贪心问题,可以使用**优先队列(大顶堆)**来解决。

  1. 贪心策略: 为了使最终的耗时总和最小,每天应该选择优化后能减少耗时最多的那个模块。 设模块当前耗时为 ,下限为 ,则优化一次减少的耗时为

  2. 算法流程

    • 计算所有模块初始耗时的总和
    • 将所有模块放入大顶堆中,堆的比较关键字为“单次优化可减少的耗时”。
    • 进行 次迭代:
      • 从堆顶取出减少耗时最多的模块。
      • 如果该模块优化后减少的耗时为 ,说明所有模块都已达到下限或无法再通过优化减少耗时,提前结束。
      • 更新 :减去该模块减少的耗时。
      • 更新该模块的当前耗时
      • 将更新后的模块重新放入堆中。
    • 最终输出
  3. 数值处理

    • 可以写成 (t + 1) / 2
    • 由于 较大,总和需使用 64 位整数。

代码

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>

using namespace std;

// 模块结构体,用于优先队列
struct Module {
    long long current_t;
    long long limit_b;
    
    // 计算当前优化一次能减少的耗时
    long long get_reduction() const {
        long long next_t = max(limit_b, (current_t + 1) / 2);
        return current_t - next_t;
    }
    
    // 大顶堆比较规则
    bool operator<(const Module& other) const {
        return get_reduction() < other.get_reduction();
    }
};

int main() {
    int n;
    long long k;
    cin >> n >> k;
    
    vector<long long> a(n), b(n);
    long long total_sum = 0;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        total_sum += a[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> b[i];
    }
    
    priority_queue<Module> pq;
    for (int i = 0; i < n; ++i) {
        pq.push({a[i], b[i]});
    }
    
    while (k > 0 && !pq.empty()) {
        Module top = pq.top();
        pq.pop();
        
        long long reduction = top.get_reduction();
        if (reduction <= 0) break; // 无法再进一步优化
        
        total_sum -= reduction;
        top.current_t = max(top.limit_b, (top.current_t + 1) / 2);
        pq.push(top);
        k--;
    }
    
    cout << total_sum << endl;
    
    return 0;
}
import java.util.*;

public class Main {
    static class Module implements Comparable<Module> {
        long currentT;
        long limitB;
        
        Module(long currentT, long limitB) {
            this.currentT = currentT;
            this.limitB = limitB;
        }
        
        long getReduction() {
            long nextT = Math.max(limitB, (currentT + 1) / 2);
            return currentT - nextT;
        }
        
        @Override
        public int compareTo(Module other) {
            return Long.compare(other.getReduction(), this.getReduction());
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long k = sc.nextLong();
        
        long[] a = new long[n];
        long totalSum = 0;
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextLong();
            totalSum += a[i];
        }
        
        long[] b = new long[n];
        for (int i = 0; i < n; i++) {
            b[i] = sc.nextLong();
        }
        
        PriorityQueue<Module> pq = new PriorityQueue<>();
        for (int i = 0; i < n; i++) {
            pq.add(new Module(a[i], b[i]));
        }
        
        while (k > 0 && !pq.isEmpty()) {
            Module top = pq.poll();
            long reduction = top.getReduction();
            if (reduction <= 0) break;
            
            totalSum -= reduction;
            top.currentT = Math.max(top.limitB, (top.currentT + 1) / 2);
            pq.add(top);
            k--;
        }
        
        System.out.println(totalSum);
    }
}
import heapq

def solve():
    # 读取输入
    line1 = input().split()
    n, k = int(line1[0]), int(line1[1])
    
    a_list = list(map(int, input().split()))
    b_list = list(map(int, input().split()))
    
    total_sum = sum(a_list)
    
    # Python 的 heapq 是小顶堆,存负值实现大顶堆
    # 堆元素:(-减少的耗时, 当前耗时, 下限)
    pq = []
    for i in range(n):
        reduction = a_list[i] - max(b_list[i], (a_list[i] + 1) // 2)
        if reduction > 0:
            heapq.heappush(pq, (-reduction, a_list[i], b_list[i]))
            
    while k > 0 and pq:
        neg_red, cur_t, limit_b = heapq.heappop(pq)
        reduction = -neg_red
        
        total_sum -= reduction
        k -= 1
        
        # 更新当前耗时
        new_t = max(limit_b, (cur_t + 1) // 2)
        # 计算下一次优化的减少量
        new_reduction = new_t - max(limit_b, (new_t + 1) // 2)
        if new_reduction > 0:
            heapq.heappush(pq, (-new_reduction, new_t, limit_b))
            
    print(total_sum)

solve()

算法及复杂度

  • 算法:贪心算法 + 优先队列(堆)。
  • 时间复杂度:。初始化堆需要 ,每次优化操作需要 ,最多进行 次。
  • 空间复杂度:。用于存储堆中的模块信息。
全部评论

相关推荐

牛客93169152...:可以发邮件,我停了三天没收到链接,发邮件问了一下,十分钟后就有了
点赞 评论 收藏
分享
03-12 15:35
嘉应学院 Python
快说谢谢牛牛精灵:说不定就是下一个寒武纪!
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务