给你两个 下标从 0 开始 的整数数组 servers 和 tasks ,长度分别为 n 和 m 。servers[i] 是第 i 台服务器的 权重 ,而 tasks[j] 是处理第 j 项任务 所需要的时间(单位:秒)。
你正在运行一个仿真系统,在处理完所有任务后,该系统将会关闭。每台服务器只能同时处理一项任务。第 0 项任务在第 0 秒可以开始处理,相应地,第 j 项任务在第 j 秒可以开始处理。处理第 j 项任务时,你需要为它分配一台 权重最小 的空闲服务器。如果存在多台相同权重的空闲服务器,请选择 下标最小 的服务器。如果一台空闲服务器在第 t 秒分配到第 j 项任务,那么在 t + tasks[j] 时它将恢复空闲状态。
如果没有空闲服务器,则必须等待,直到出现一台空闲服务器,并 尽可能早 地处理剩余任务。 如果有多项任务等待分配,则按照 下标递增 的顺序完成分配。
如果同一时刻存在多台空闲服务器,可以同时将多项任务分别分配给它们。
构建长度为 m 的答案数组 ans ,其中 ans[j] 是第 j 项任务分配的服务器的下标。
返回答案数组 ans 。
示例 1:
输入:servers = [3,3,2], tasks = [1,2,3,2,1,2]
输出:[2,2,0,2,1,2]
解释:事件按时间顺序如下:
- 0 秒时,第 0 项任务加入到任务队列,使用第 2 台服务器处理到 1 秒。
- 1 秒时,第 2 台服务器空闲,第 1 项任务加入到任务队列,使用第 2 台服务器处理到 3 秒。
- 2 秒时,第 2 项任务加入到任务队列,使用第 0 台服务器处理到 5 秒。
- 3 秒时,第 2 台服务器空闲,第 3 项任务加入到任务队列,使用第 2 台服务器处理到 5 秒。
- 4 秒时,第 4 项任务加入到任务队列,使用第 1 台服务器处理到 5 秒。
- 5 秒时,所有服务器都空闲,第 5 项任务加入到任务队列,使用第 2 台服务器处理到 7 秒。
示例 2:
输入:servers = [5,1,4,3,2], tasks = [2,1,2,4,5,2,1]
输出:[1,4,1,4,1,3,2]
解释:事件按时间顺序如下:
- 0 秒时,第 0 项任务加入到任务队列,使用第 1 台服务器处理到 2 秒。
- 1 秒时,第 1 项任务加入到任务队列,使用第 4 台服务器处理到 2 秒。
- 2 秒时,第 1 台和第 4 台服务器空闲,第 2 项任务加入到任务队列,使用第 1 台服务器处理到 4 秒。
- 3 秒时,第 3 项任务加入到任务队列,使用第 4 台服务器处理到 7 秒。
- 4 秒时,第 1 台服务器空闲,第 4 项任务加入到任务队列,使用第 1 台服务器处理到 9 秒。
- 5 秒时,第 5 项任务加入到任务队列,使用第 3 台服务器处理到 7 秒。
- 6 秒时,第 6 项任务加入到任务队列,使用第 2 台服务器处理到 7 秒。
数据结构+模拟~
开两个优先队列即可,一个是空闲队列,一个是任务队列(PS:都是小根堆)~
空闲队列
f
r
e
e
free
free 存一个
p
a
i
r
(
x
,
y
)
pair(x,y)
pair(x,y),
x
x
x 为服务器权重,
y
y
y 为服务器编号~
任务队列
t
a
s
k
task
task 存一个
t
u
p
l
e
(
x
,
y
,
z
)
tuple(x,y,z)
tuple(x,y,z),
x
x
x 为任务完成后的时间,
y
y
y 为服务器权重,
z
z
z 为服务器编号~
此时我们维护一个当前时间
t
t
t,建立一个服务器编号到权重的映射数组
f
u
c
k
fuck
fuck,下面模拟一下过程:
- 假设当前遍历到任务 i i i
- 首先是释放任务队列中的服务器,令 [ a , b , c ] = w o r k . t o p ( ) [a,b,c]=work.top() [a,b,c]=work.top(),若 t ≥ a t\geq a t≥a 则证明该服务器已完成任务,将队头弹出,并将 p a i r ( f u c k [ c ] , [ c ] ) pair(fuck[c],[c]) pair(fuck[c],[c]) 存入空闲队列
- 然后判断空闲队列是否为空,不为空就取空闲队列的队头中的服务器,令 [ a , b ] = f r e e . t o p ( ) [a,b]=free.top() [a,b]=free.top(),弹出队头并将 t u p l e ( t a s k [ i ] + t , f u c k [ b ] , b ) tuple(task[i]+t,fuck[b],b) tuple(task[i]+t,fuck[b],b) 存入任务队列
- 若空闲队列为空,则取任务队列中的队头中的服务器,令 [ a , b , c ] = w o r k . t o p ( ) [a,b,c]=work.top() [a,b,c]=work.top(),弹出队头并将 t u p l e ( t a s k [ i ] + a , f u c k [ c ] , c ) tuple(task[i]+a,fuck[c],c) tuple(task[i]+a,fuck[c],c) 存入任务队列
- 实时更新时间 t t t
AC代码如下:
typedef tuple<int, int, int> T;
typedef pair<int, int> P;
class Solution {
public:
int fuck[200005];
public:
vector<int> assignTasks(vector<int> &servers, vector<int> &tasks) {
priority_queue<P, vector<P>, greater<>> free;
priority_queue<T, vector<T>, greater<>> work;
vector<int> ans;
vector<T> v;
int t;
for (int i = 0; i < servers.size(); i++) free.push(P(servers[i], i)), fuck[i] = servers[i];
for (int i = 0; i < tasks.size(); i++) {
t = max(t, i);
while (!work.empty()) {
auto[a, b, c]=work.top();
if (t >= a) {
free.push(P(fuck[c], c));
work.pop();
} else break;
}
if (!free.empty()) {
auto[a, b]=free.top();
free.pop();
ans.push_back(b);
work.push(T(tasks[i] + t, fuck[b], b));
} else {
auto[a, b, c]=work.top();
ans.push_back(c);
work.pop();
work.push(T(tasks[i] + a, fuck[c], c));
t = a;
}
}
return ans;
}
};