日志解析
其它编程语言题解点击跳转:华为OD机试双机位C卷:日志解析(C/C++/Java/Python/Go/JS)
2026华为OD机试双机位C卷 - 华为OD上机考试双机位C卷 200分题型
华为OD机试双机位C卷真题目录点击查看: 华为OD机试双机位C卷真题题库目录|机考题库 + 算法考点详解
题目描述
你是一个运维工程师,你同时负责n个系统的运维工作,已知每个系统每天会都从现场采集大量的现网运行日志(错误日志、接口日志等)下来生成一个日志文件,每个系统采集下来的日志文件大小均不相同。为了解析这些日志,你给每个系统配备了一台默认服务器进行日志解析,且此台服务器只能给本系统使用,由于所配置的服务器规则均相同,因为解析日志的速度也是相同的,即每秒钟可以解析defaultCnt条日志。
现在你发现解析的速度达不到预期,但你手头上还有一部分额外的资源可以使用,这些资源可以在任意时刻配置给任意一台服务器。但有个限制,那就是同一时刻只能配给其中一台服务器器,且服务器器是能整合全部额外资源,当然在下一秒钟即可配备给另外一台服务器。某一台服务器配备了额外资源以后,则每秒钟会增加解析extraCnt条日志,即每秒可解析(defaultCnt+extraCnt)条日志。
输入描述
输入一共2行
第一行为3个正整数n、defaultCnt、extraCnt,
第二行为n个正整数,a1,a2,...,an,分别表示每个系统采集的日志条目数
已知:1 ≤ n ≤ 1×10⁵,1 ≤ defaultCnt, extraCnt ≤ 100,1 ≤ ai ≤ 1000
输出描述
一个正整数,表示解析完成全部日志的最少时间。
用例1
输入
none
3 2 1
1 2 3
输出
none
1
说明
每个服务器每秒可解析2条日志,直接将额外的资源配备给第三台服务器器,则第三台服务器每秒可解析(2+1=3)条日志,则只需1秒即可解析完三个系统的全部日志。
用例2
输入
none
1 1 1
4
输出
none
2
题解
思路:二分
- 经典的二分题型,一般题目背景为
在...限制下..求最大/最小类问题可以考虑使用二分实现。 - 定义二分边界,下边界可直接设置为0
left = 0,至于上边界考虑数据边界,不使用加速情况下最大时间为right = (max(a) + defaultCnt - 1) / defaultCnt.注意上下取整。 - 接下来就是二分经典套路,枚举中间值(mid = (left + right)),判断在指定时间内是否可以完成所有日志收集,更新边界,直到
left == right结束,此时left就是最小结果。- 可以完成,更新上边界为
right = mid - 不可以完成,更新
left = mid + 1
- 可以完成,更新上边界为
- 判断是否可行采用贪心逻辑,题目中说明
同一时刻只能配给其中一台服务器器,这就转换为在时间T内,完成所有任务需要的加速次数是否 <= T. 对于每个日志文件需要的加速次数计算逻辑如下:每个日志默认自行可完成base = T * defaultCnt, 那么当a[i] > base是,需要加速次数为(a[i] - base + extraCnt - 1) / extraCnt. 累加所有任务加速次数,如果totalNeed <= T则能完成,反之则不能。
Code
c++
#include<iostream>
#include<vector>
#include<string>
#include <utility>
#include <sstream>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
int n, defaultCnt, extraCnt;
// 贪心判断
bool check(vector<int>&a , int time) {
// 总共需要加速时长
int totalNeed = 0;
int base = time * defaultCnt;
for (int i = 0; i < n; i++) {
if (a[i] > base) {
// 额外需要加速时间,向上取整
int need = (a[i] - base + extraCnt - 1) / extraCnt;
totalNeed += need;
if (totalNeed > time) {
return false;
}
}
}
return totalNeed <= time;
}
int main() {
cin >> n >> defaultCnt >> extraCnt;
vector<int> a(n);
int left = 0, right = 0;
for (int i = 0; i < n; i++) {
cin >> a[i];
// 向上取整,上边界确定为不采用加速原始需要的时间
right = max(right, (a[i] + defaultCnt -1) /defaultCnt);
}
// 二分
while (left < right) {
int mid = (left + right) >> 1;
if(check(a, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
cout << left;
return 0;
}