有 n 台计算机,第 i 台计算机的运算能力为 vi 。
有一系列的任务被指派到各个计算机上,
第 i 个任务在 ai 时刻分配,
指定计算机编号为 bi, 耗时为 ci 且算力消耗为 di。
如果此任务成功分配,将立刻开始运行,
期间持续占用 bi 号计算机 di 的算力, 持续 ci 秒。
对于每次任务分配,如果计算机剩余的运算能力不足则输出 −1−1,
并取消这次分配,否则输出分配完这个任务后这台计算机的剩余运算能力。
1.把每一台电脑分开来去思考,每一台有一条属于自己的任务队列
2.在每个任务队列中,对于每个任务,有起始时间和结束时间,因为是把一个任务看作一个整体,结束时间可以作为弹出堆的判断条件,因为只有当后面的任务的开始大于这个的结束才会弹出,先完成先弹出先恢复
3.对于每一个任务,更新算力,如果此队列中存在任务的结束时间在我这个任务的开始时间之前,那么这个任务就相当于完成了,因为题目保证了a1<a2<...所以后面任务一定不会再受他影响,就可以把任务弹出,当前计算机算力恢复。(只有结束了才能恢复!)
4.对于在收回之前算力之后与需要的比较,如果可以满足,就把它加入队列,并且当前电脑算力要减去被占用的
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N=2e5+10;
typedef pair<int,int>PII;
PII task[N];
int w[N];
int n,m;
int a,b,c,d;
priority_queue<PII,vector<PII>,greater<PII>>mac[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>w[i];
}
for(int i=1;i<=m;i++)
{
cin>>a>>b>>c>>d;
while(!mac[b].empty()&&mac[b].top().first<=a)//完成时间在我开始之前,增加我的算力
{
w[b]+=mac[b].top().second;
mac[b].pop();
}
if(w[b]<d)
{
puts("-1");
}
else
{
mac[b].push({a+c,d});
w[b]-=d;
cout<<w[b]<<endl;
}
}
}
LITTLE TIPS:
用pair来存时间和占用算力,然后对它用优先队列,可以利用默认的对pair的first进行排序进行快速的小根堆排序