有m个任务tasks和n个服务器,第 0 项任务在第 0 秒可以开始处理,相应地,第 j 项任务在第 j 秒可以开始处理。
处理第 j 项任务时,你需要为它分配一台 权重最小 的空闲服务器。
如果存在多台相同权重的空闲服务器,请选择 下标最小 的服务器。
如果一台空闲服务器在第 t 秒分配到第 j 项任务,那么在 t + tasks[j] 时它将恢复空闲状态。
如果没有空闲服务器,则必须等待,直到出现一台空闲服务器,并 尽可能早 地处 理剩余任务。
如果有多项任务等待分配,则按照 下标递增 的顺序完成分配。
输入:servers = [3,3,2], tasks = [1,2,3,2,1,2]
输出:[2,2,0,2,1,2]
1 <= n, m <= 2 * 105
思路:用一个堆来做的时候,就发现很难模拟没有空闲服务器时,当前这个任务放到哪里,所以这里需要两个堆,
一个是存储空闲服务器 q1,一个存非空闲服务器q2,每次都在做任务的时候,都去非空闲服务器q2里看看有没有空闲的可以拿出来放到q1
执行任务都从q1拿服务器执行,这样就将二维操作变成了一维(只从q1拿服务器执行)
class Solution {
public:
struct S1 {
int id, w, free_at;
bool operator<(const S1& s) const {
if (w == s.w) {
return id > s.id;
}
return w > s.w;
}
};
struct S2 {
int id, w, free_at;
bool operator<(const S2& s) const {
if (free_at != s.free_at) {
return free_at > s.free_at;
} else if (w != s.w) {
return w > s.w;
} else {
return id > s.id;
}
}
};
vector<int> assignTasks(vector<int>& servers, vector<int>& tasks) {
int m = tasks.size();
vector<int> ans(m);
priority_queue<S1> q1; //空闲
priority_queue<S2> q2; //非空闲
for (int i = 0; i < servers.size(); i++) {
q1.push({i, servers[i], 0});
}
for (int i = 0; i < m; i++) {
while (!q2.empty() && q2.top().free_at <= i) { //将q2中可以执行当前任务的服务器放到q1排序
S2 s = q2.top(); q2.pop();
q1.push({s.id, s.w});
}
if (!q1.empty()) { //如果有空闲服务器
S1 s = q1.top(); q1.pop();
ans[i] = s.id;
q2.push({s.id, s.w, i + tasks[i]});
} else { //如果没有空闲服务器,则取出最早执行完任务的非空闲服务器,充当空闲服务器来执行任务
S2 s = q2.top(); q2.pop();
ans[i] = s.id;
q2.push({s.id, s.w, s.free_at + tasks[i]});
}
}
return ans;
}
};