C++ 算法:用二分查找找到最小工资满足员工期望快乐值
首先,我们可以先求出每个员工与其他员工的距离,即离他最近的发工资的员工的距离。
对于员工 i,我们可以维护一个数组 dist,dist[j]表示员工 i 和员工 j 之间的距离。初始时,我们可以将 dist 数组的所有元素初始化为无穷大,表示员工 i 与其他员工之间的距离尚未确定。
然后,我们可以遍历 m 名发工资的员工 b_1, b_2, ..., b_m,并更新 dist 数组。对于每个员工 b_i,我们将其与所有其他员工的距离更新为 min(dist[j], abs(b_i - j)),表示员工 b_i 与员工 j 的距离为 min(dist[j], abs(b_i - j))。
接下来,我们可以使用二分查找的方法来确定最小的工资 k。我们可以假设工资的上界为 max(a_1, a_2, ..., a_n),下界为 0,然后在这个范围内进行二分查找。
对于每个工资的候选值 mid,我们可以遍历所有员工,计算每个员工的快乐值增加量。对于员工 i,如果他的期望快乐值 a_i 大于等于当前工资候选值 mid,那么他的快乐值增加量为 k。否则,他的快乐值增加量为 max(0, k - dist[i])。
最后,如果所有员工的快乐值增加量之和大于等于 0,说明当前工资候选值 mid 可以满足所有员工的期望快乐值,我们可以将上界更新为 mid。否则,我们将下界更新为 mid + 1。
最终,当上界等于下界时,我们找到了最小的工资 k,使得所有员工的快乐值不低于他们的期望快乐值。
下面是使用 C++ 实现的代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
vector<int> b(m);
for (int i = 0; i < m; ++i) {
cin >> b[i];
}
vector<int> dist(n, INT_MAX);
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
dist[j] = min(dist[j], abs(b[i] - j));
}
}
int left = 0, right = *max_element(a.begin(), a.end());
while (left < right) {
int mid = left + (right - left) / 2;
int happiness = 0;
for (int i = 0; i < n; ++i) {
if (a[i] >= mid) {
happiness += mid;
} else {
happiness += max(0, mid - dist[i]);
}
}
if (happiness >= accumulate(a.begin(), a.end(), 0)) {
right = mid;
} else {
left = mid + 1;
}
}
cout << left << endl;
return 0;
}
在这个代码中,我们使用了二分查找的方法来确定最小的工资 k。时间复杂度为 O(n log M),其中 n 是员工数量,M 是员工期望快乐值的最大值。空间复杂度为 O(n),用于存储距离数组 dist。
注意,这个解法假设员工的编号是从 0 开始的,而不是从 1 开始的。如果从 1 开始编号,需要在代码中做相应的调整。
原文地址: https://www.cveoy.top/t/topic/qimA 著作权归作者所有。请勿转载和采集!