题意:t个测试样例,每个测试样例有n个任务,给你起始时间、终止时间和任务量,每个任务必须在起始时间和终止时间之间完成(包括边界),现在要找出一个最小的每分钟处理的任务量,使得可以在规定时间内完成n个任务。
做法:二分,先用优先队列排序,先做已经开始且最早结束的,如果队列非空,判断当前的任务是否在规定的时间,如果不在,那么这个时间就不行。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
int n;
struct node{
int l,r,w;
bool operator <(const node &a)const{
return r>a.r;//最早结束的放前面
}
}e[10005];
priority_queue<node>sp;
bool cmp(node a,node b){
return a.l<b.l;
}
bool check(int mid){
int i=0,j=0;
while(!sp.empty())sp.pop();
while(1){
while(i<n&&e[i].l<=j)sp.push(e[i++]);//当前的任务到了开始时间 就加入队列
int now=mid;
while(now!=0&&!sp.empty()){//如果当前还能做任务且当前时间的队列非空 就继续做任务
node ita=sp.top();
sp.pop();
int m=min(now,ita.w);
now-=m;
ita.w-=m;
if(ita.w!=0)sp.push(ita);
}
j++;//时间加1
if(!sp.empty()&&sp.top().r<=j)return false;//如果队列非空且任务没有在规定的时间完成 当前答案不可行
if(sp.empty()&&i==n)return true;//如果在规定的时间完成了所有的任务 当前答案可行
}
}
int main(){
int t,i,sum;
scanf("%d",&t);
while(t--){
sum=0;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].w);
sum+=e[i].w;
}
sort(e,e+n,cmp);//排序 最早开始的放前面
int l=0,r=sum;
while(l<r){
int mid=(l+r)>>1;
if(check(mid)){
r=mid;
}
else l=mid+1;
}
cout<<l<<endl;
}
return 0;
}