#C0E10. 华为OD机试E卷 - 日志采集系统/日志首次上报最多积分
华为OD机试E卷 - 日志采集系统/日志首次上报最多积分
https://blog.csdn.net/banxia_frontend/article/details/141604543
最新华为OD机试
题目描述
日志采集是运维系统的的核心组件。日志是按行生成,每行记做一条,由采集系统分批上报。
- 如果上报太频繁,会对服务端造成压力;
- 如果上报太晚,会降低用户的体验;
- 如果一次上报的条数太多,会导致超时失败。
为此,项目组设计了如下的上报策略:
- 每成功上报一条日志,奖励1分
- 每条日志每延迟上报1秒,扣1分
- 积累日志达到100条,必须立即上报
给出日志序列,根据该规则,计算首次上报能获得的最多积分数。
输入描述
按时序产生的日志条数 T1,T2…Tn,其中 1<=n<=1000,0<=Ti<=100
输出描述
首次上报最多能获得的积分数
示例1
输入
1 98 1
输出
98
说明
T1 时刻上报得 1 分 T2 时刻上报得98分,最大 T3 时刻上报得 0 分
示例2
输入
50 60 1
输出
50
说明
如果第1个时刻上报,获得积分50。如果第2个时刻上报,最多上报100条,前50条延迟上报1s,每条扣除1分,共获得积分为 100-50=50
示例3
输入
3 7 40 10 60
输出
37
说明
T1时刻上报得3分
T2时刻上报得7分
T3时刻上报得37分,最大
T4时刻上报得-3分
T5时刻上报,因为已经超了100条限制,所以只能上报100条,得-23分
解题思路
上报策略:
- 积分奖励:每成功上报一条日志,可以获得 1 分。
- 延迟扣分:每条日志每延迟 1 秒上报,会扣除 1 分。
- 强制上报:当积累的日志数量达到 100 条时,必须立即上报,无法再继续等待更多日志。
例子解析
-
输入:
1 98 1
,输出:98
- 在第1时刻,上报1条日志,获得1分。
- 在第2时刻,累计生成99条日志(1+98),上报这99条日志,获得99 -1 = 98分(因为第1条日志延迟1秒扣1分,其余98条按时上报不扣分)。
- 在第3时刻,累计生成100条日志(99+1),必须立即上报,获得100 -2 - 98= 0分。
- 最大积分出现在第2时刻,为98分。
-
输入:
50 60 1
,输出:50
- 在第1时刻,上报50条日志,获得50分。
- 在第2时刻,累计生成110条日志(50+60),强制上报100条。前50条日志延迟1秒,每条扣1分,最终得分为50分(100 - 50)。
-
输入:
3 7 40 10 60
,输出:37
- 在第3时刻上报,当前为40条,加上前两秒的,总共50条,上报得50分,但是T2的 7条超时了1秒,减7分,T1的3条超时了2秒,减6分,最后得37分。
Java
import java.util.Scanner;
public class LogCollection {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 读取输入的日志序列
String input = in.nextLine();
// 将日志序列按空格分割成数组
String[] logs = input.split(" ");
int totalCount = 0; // 总日志条数
int maxScore = 0; // 最大积分数
for (int i = 0; i < logs.length; i++) {
int logCount = Integer.valueOf(logs[i]); // 当前时间点的日志条数
if (logCount == 0) {
continue; // 如果当前时间点没有日志条数,则跳过
}
totalCount += logCount; // 更新总日志条数
int score = 0; // 当前时间点的积分数
for (int j = 0; j <= i; j++) {
if (totalCount > 100 && i == j) {
// 如果总日志条数超过100,并且当前时间点是最后一个时间点
score += logCount - (totalCount - 100); // 计算得分
} else {
score += Integer.valueOf(logs[j]) - (i - j) * Integer.valueOf(logs[j]); // 计算得分
}
}
if (score > maxScore) {
maxScore = score; // 更新最大积分数
}
if (totalCount >= 100) {
break; // 如果总日志条数达到100条以上,则退出循环
}
}
System.out.println(maxScore); // 输出最大积分数
}
}
Python
import sys
# 读取输入的日志序列
input = sys.stdin.readline().strip()
# 将日志序列按空格分割成数组
logs = input.split(" ")
totalCount = 0 # 总日志条数
maxScore = 0 # 最大积分数
for i in range(len(logs)):
logCount = int(logs[i]) # 当前时间点的日志条数
if logCount == 0:
continue # 如果当前时间点没有日志条数,则跳过
totalCount += logCount # 更新总日志条数
score = 0 # 当前时间点的积分数
for j in range(i+1):
if totalCount > 100 and i == j:
# 如果总日志条数超过100,并且当前时间点是最后一个时间点
score += logCount - (totalCount - 100) # 计算得分
else:
score += int(logs[j]) - (i - j) * int(logs[j]) # 计算得分
if score > maxScore:
maxScore = score # 更新最大积分数
if totalCount >= 100:
break # 如果总日志条数达到100条以上,则退出循环
print(maxScore) # 输出最大积分数
JavaScript
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', function (input) {
var logs = input.split(" ");
var totalCount = 0; // 总日志条数
var maxScore = 0; // 最大积分数
for (var i = 0; i < logs.length; i++) {
var logCount = parseInt(logs[i]); // 当前时间点的日志条数
if (logCount === 0) {
continue; // 如果当前时间点没有日志条数,则跳过
}
totalCount += logCount; // 更新总日志条数
var score = 0; // 当前时间点的积分数
for (var j = 0; j <= i; j++) {
if (totalCount > 100 && i === j) {
// 如果总日志条数超过100,并且当前时间点是最后一个时间点
score += logCount - (totalCount - 100); // 计算得分
} else {
score += parseInt(logs[j]) - (i - j) * parseInt(logs[j]); // 计算得分
}
}
if (score > maxScore) {
maxScore = score; // 更新最大积分数
}
if (totalCount >= 100) {
break; // 如果总日志条数达到100条以上,则退出循环
}
}
console.log(maxScore); // 输出最大积分数
rl.close();
});
C++
#include <iostream> // 包含输入输出流库
#include <vector> // 包含向量容器库
using namespace std;
int main() {
string input;
getline(cin, input); // 从标准输入读取整行数据
vector<string> logs; // 用于存储日志条数的字符串向量
string temp = ""; // 临时字符串变量,用于逐字符拼接日志条数
for (int i = 0; i < input.length(); i++) { // 遍历输入的每一个字符
if (input[i] == ' ') { // 遇到空格时,表示一个日志条数的结束
logs.push_back(temp); // 将当前拼接的字符串加入日志向量
temp = ""; // 重置临时字符串变量
} else {
temp += input[i]; // 拼接字符
}
}
logs.push_back(temp); // 将最后一个日志条数加入日志向量
int totalCount = 0; // 累计日志总条数
int maxScore = 0; // 记录最大积分数
for (int i = 0; i < logs.size(); i++) { // 遍历每个时间点的日志
int logCount = stoi(logs[i]); // 将当前日志条数从字符串转换为整数
if (logCount == 0) { // 如果当前时间点日志条数为0,跳过该时间点
continue;
}
totalCount += logCount; // 累加日志总条数
int score = 0; // 当前时间点的积分
for (int j = 0; j <= i; j++) { // 计算当前时间点的积分
if (totalCount > 100 && i == j) { // 如果总日志条数超过100且当前为最后一个时间点
score += logCount - (totalCount - 100); // 计算积分,考虑超出100条的部分
} else {
score += stoi(logs[j]) - (i - j) * stoi(logs[j]); // 正常积分计算,考虑延迟扣分
}
}
if (score > maxScore) { // 更新最大积分数
maxScore = score;
}
if (totalCount >= 100) { // 如果总日志条数达到或超过100,提前结束循环
break;
}
}
cout << maxScore << endl; // 输出最大积分数
return 0;
}
C语言
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char input[1000]; // 定义一个字符数组用于存储输入
fgets(input, 1000, stdin); // 从标准输入读取一行数据
char logs[100][10]; // 定义一个二维字符数组存储日志条数,每条日志最长为10个字符
int logCount = 0; // 日志条数计数器
char *token = strtok(input, " "); // 使用空格分割输入字符串,获取第一个日志条数
while (token != NULL) { // 逐个分割字符串,直到没有更多的分割部分
strcpy(logs[logCount], token); // 将当前日志条数复制到日志数组中
logCount++; // 增加日志条数计数
token = strtok(NULL, " "); // 获取下一个日志条数
}
int totalCount = 0; // 累积日志总条数
int maxScore = 0; // 记录最大积分数
for (int i = 0; i < logCount; i++) { // 遍历每个时间点的日志
int logNum = atoi(logs[i]); // 将当前日志条数从字符串转换为整数
if (logNum == 0) { // 如果当前时间点日志条数为0,跳过该时间点
continue;
}
totalCount += logNum; // 累加日志总条数
int score = 0; // 当前时间点的积分
for (int j = 0; j <= i; j++) { // 计算当前时间点的积分
int logAtJ = atoi(logs[j]); // 将日志条数从字符串转换为整数
if (totalCount > 100 && i == j) { // 如果总日志条数超过100且当前为最后一个时间点
score += logNum - (totalCount - 100); // 计算积分,考虑超出100条的部分
} else {
score += logAtJ - (i - j) * logAtJ; // 正常积分计算,考虑延迟扣分
}
}
if (score > maxScore) { // 更新最大积分数
maxScore = score;
}
if (totalCount >= 100) { // 如果总日志条数达到或超过100,提前结束循环
break;
}
}
printf("%d\n", maxScore); // 输出最大积分数
return 0;
}