华为OD机试 - 日志首次上报最多积分(Python/JS/C/C++ 2024 E卷 100分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

日志采集是运维系统的核心组件。日志是按行生成,每行记录做一条,由采集系统分批上报。

  • 如果上报太频繁,会对服务端造成压力;
  • 如果上报太晚,会降低用户的体验;
  • 如果一次上报的条数太多,会导致接口失败。

为此,项目组设计了如下的上报策略:

  1. 每成功上报一条日志,奖励1分;
  2. 每条日志延迟上报1秒,扣1分;
  3. 积累日志达到100条,必须立刻上报。

给出日志序列,根据该规则,计算首次上报能获得的最多积分数。

二、输入描述

按时序产生的日志条数 T1,T2,…Tn,其中 1 <= n <= 1000,0 <= Ti <= 100

三、输出描述

首次上报最多能获得的积分分数

四、测试用例

测试用例1:

1、输入

1 98 1

2、输出

98

3、说明

T1时刻上报得1分

T2时刻上报得98分

最大 T3时刻上报得0分

测试用例2:

1、输入

50 60 1

2、输出

50

3、说明

如果第1个时刻上报,获得积分50。如果第2个时刻上报,最多上报100条,前50条延迟上报1s,每条扣除1分,共获得积分为100-50=50

五、解题思路

1、问题分析

为了计算首次上报的最大积分数,我们需要考虑以下几种情况:

  1. 在积累的日志数未达到100条时,可以选择任何时刻进行上报。此时,选择一个最佳的上报时刻,使得积分最大化。
  2. 当积累的日志数达到或超过100条时,必须在该时刻进行上报。此时,需要计算在这个时刻上报前100条日志的积分。

2、具体步骤

  1. 记录每个时间点到达的日志数:使用一个列表记录每个时间点到达的日志数量及其到达时间。
  2. 遍历每个时间点:
    • 累积当前的日志数。
    • 如果累积的日志数达到或超过100条:
      • 必须在此时上报前100条日志。
      • 计算前100条日志的积分。
      • 更新最大积分数。
      • 结束遍历,因为首次上报已经完成。
    • 如果未达到100条,可以选择在此时上报:
      • 计算当前时刻上报所有已累积的日志的积分。
      • 更新最大积分数。
  3. 遍历结束后:
    • 如果日志总数未达到100条,可以选择在最后一个时刻上报所有日志,确保积分最大化。

六、Python算法源码

import sys
from collections import deque

def main():
    # 读取输入
    input_line = sys.stdin.read()
    tokens = input_line.strip().split()
    n = len(tokens)
    Ti_list = list(map(int, tokens))
    
    # 初始化队列,用于存储日志的到达时间和数量
    log_queue = deque()
    
    # 累积的日志数量
    accumulated_logs = 0
    
    # 累积的 ti 总和
    sum_ti_total = 0
    
    # 最大积分
    max_score = -float('inf')
    
    for t in range(1, n+1):
        Ti = Ti_list[t-1]
        if Ti > 0:
            log_queue.append((t, Ti))  # 添加到队列
        accumulated_logs += Ti
        sum_ti_total += Ti * t  # 更新总的 ti
        
        if accumulated_logs >= 100:
            # 需要强制上传前100条日志
            logs_needed = 100
            sum_ti_first100 = 0
            temp_queue = deque()
            for log in log_queue:
                ti, count = log
                if logs_needed >= count:
                    sum_ti_first100 += ti * count
                    logs_needed -= count
                else:
                    sum_ti_first100 += ti * logs_needed
                    temp_queue.append((ti, count - logs_needed))
                    logs_needed = 0
                    break
            # 计算积分
            score = sum_ti_first100 - 100 * (t -1)
            if score > max_score:
                max_score = score
            break  # 首次上传完成
        else:
            # 可以选择在此时上传所有累积的日志
            score = sum_ti_total - accumulated_logs * (t -1)
            if score > max_score:
                max_score = score
    
    # 如果所有时间点遍历完毕,且未达到100条日志
    if accumulated_logs < 100 and n >0:
        print(max_score)
    elif n ==0:
        print(0)
    else:
        print(max_score)

if __name__ == "__main__":
    main()

七、JavaScript算法源码

const readline = require('readline');

function OdTest() {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

    let input = '';

    rl.on('line', function(line) {
        input += line;
    });

    rl.on('close', function() {
        // 解析输入
        const tokens = input.trim().split(/\s+/).map(Number);
        const n = tokens.length;
        const Ti_list = tokens;
        
        // 初始化队列,用于存储日志的到达时间和数量
        const log_queue = [];
        
        // 累积的日志数量
        let accumulated_logs = 0;
        
        // 累积的 ti 总和
        let sum_ti_total = 0;
        
        // 最大积分
        let max_score = -Infinity;
        
        for (let t =1; t<=n; t++) {
            const Ti = Ti_list[t-1];
            if (Ti >0){
                log_queue.push({ti: t, count: Ti});
            }
            accumulated_logs += Ti;
            sum_ti_total += Ti * t;
            
            if (accumulated_logs >=100){
                // 需要强制上传前100条日志
                let logs_needed = 100;
                let sum_ti_first100 =0;
                const temp_queue = [];
                while (log_queue.length >0 && logs_needed >0){
                    const log = log_queue.shift();
                    if (log.count <= logs_needed){
                        sum_ti_first100 += log.ti * log.count;
                        logs_needed -= log.count;
                    } else {
                        sum_ti_first100 += log.ti * logs_needed;
                        log.count -= logs_needed;
                        temp_queue.push(log);
                        logs_needed =0;
                    }
                }
                // 将剩余的日志放回队列
                while (temp_queue.length >0){
                    log_queue.unshift(temp_queue.pop());
                }
                // 计算积分
                const score = sum_ti_first100 - 100 * (t -1);
                if (score > max_score){
                    max_score = score;
                }
                break; // 首次上传完成
            } else{
                // 可以选择在此时上传所有累积的日志
                const score = sum_ti_total - accumulated_logs * (t -1);
                if (score > max_score){
                    max_score = score;
                }
            }
        }
        
        // 如果所有时间点遍历完毕,且未达到100条日志
        if (accumulated_logs <100 && n >0){
            console.log(max_score);
        }
        else if (n ==0){
            console.log(0);
        }
        else{
            console.log(max_score);
        }
    });
}

OdTest();

八、C算法源码

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int ti;
    int count;
} LogEntry;

int main(){
    // 读取输入
    int Ti_list[1000];
    int n =0;
    while (scanf("%d", &Ti_list[n]) != EOF){
        n++;
        if(n >=1000){
            break;
        }
    }
    
    // 初始化队列
    LogEntry queue[1000];
    int front =0, rear=0;
    
    // 累积的日志数量
    int accumulated_logs =0;
    
    // 累积的 ti 总和
    long long sum_ti_total =0;
    
    // 最大积分
    long long max_score = -1000000000;
    
    for(int t=1; t<=n; t++){
        int Ti = Ti_list[t-1];
        if(Ti >0){
            queue[rear].ti = t;
            queue[rear].count = Ti;
            rear++;
        }
        accumulated_logs += Ti;
        sum_ti_total += (long long)Ti * t;
        
        if(accumulated_logs >=100){
            // 需要强制上传前100条日志
            int logs_needed =100;
            long long sum_ti_first100 =0;
            while(logs_needed >0 && front < rear){
                if(queue[front].count <= logs_needed){
                    sum_ti_first100 += (long long)queue[front].ti * queue[front].count;
                    logs_needed -= queue[front].count;
                    front++;
                }
                else{
                    sum_ti_first100 += (long long)queue[front].ti * logs_needed;
                    queue[front].count -= logs_needed;
                    logs_needed =0;
                }
            }
            // 计算积分
            long long score = sum_ti_first100 - 100 * (t -1);
            if(score > max_score){
                max_score = score;
            }
            break; // 首次上传完成
        }
        else{
            // 可以选择在此时上传所有累积的日志
            long long score = sum_ti_total - (long long)accumulated_logs * (t -1);
            if(score > max_score){
                max_score = score;
            }
        }
    }
    
    // 如果所有时间点遍历完毕,且未达到100条日志
    if(accumulated_logs <100 && n >0){
        printf("%lld\n", max_score);
    }
    else if(n ==0){
        printf("0\n");
    }
    else{
        printf("%lld\n", max_score);
    }
    
    return 0;
}

九、C++算法源码

#include <bits/stdc++.h>
using namespace std;

struct LogEntry {
    int ti;
    int count;
};

int main(){
    // 读取输入
    vector<int> Ti_list;
    int Ti;
    while(cin >> Ti){
        Ti_list.push_back(Ti);
    }
    int n = Ti_list.size();
    
    // 初始化队列
    deque<LogEntry> log_queue;
    
    // 累积的日志数量
    int accumulated_logs =0;
    
    // 累积的 ti 总和
    long long sum_ti_total =0;
    
    // 最大积分
    long long max_score = LLONG_MIN;
    
    for(int t=1; t<=n; t++){
        int current_Ti = Ti_list[t-1];
        if(current_Ti >0){
            log_queue.push_back(LogEntry{t, current_Ti});
        }
        accumulated_logs += current_Ti;
        sum_ti_total += (long long)current_Ti * t;
        
        if(accumulated_logs >=100){
            // 需要强制上传前100条日志
            int logs_needed =100;
            long long sum_ti_first100 =0;
            while(logs_needed >0 && !log_queue.empty()){
                if(log_queue.front().count <= logs_needed){
                    sum_ti_first100 += (long long)log_queue.front().ti * log_queue.front().count;
                    logs_needed -= log_queue.front().count;
                    log_queue.pop_front();
                }
                else{
                    sum_ti_first100 += (long long)log_queue.front().ti * logs_needed;
                    log_queue.front().count -= logs_needed;
                    logs_needed =0;
                }
            }
            // 计算积分
            long long score = sum_ti_first100 - 100LL * (t -1);
            if(score > max_score){
                max_score = score;
            }
            break; // 首次上传完成
        }
        else{
            // 可以选择在此时上传所有累积的日志
            long long score = sum_ti_total - (long long)accumulated_logs * (t -1);
            if(score > max_score){
                max_score = score;
            }
        }
    }
    
    // 如果所有时间点遍历完毕,且未达到100条日志
    if(accumulated_logs <100 && n >0){
        cout << max_score << endl;
    }
    else if(n ==0){
        cout << "0" << endl;
    }
    else{
        cout << max_score << endl;
    }
    
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值