问题
https://vjudge.net/problem/UVA-1422
分析
最大最小值,使用二分法.因为一个任务可以分开成多个片段,所以先按照到达时间从小到大排序然后再加入优先队列。
注意:区间是左开右闭区间,然后速度是x,一天可以处理多个任务,不是只能处理一个,所以要递推相减。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn=10000+5,Inf=0x3f3f3f3f;
struct Task{
int r,d,w;
bool operator < (const Task &rhs) const {
return d>rhs.d;
}
};
Task task[maxn];
bool cmp (const Task &lhs,const Task &rhs) {
return lhs.r<rhs.r;
}
int n,kase=0,r,d,w;
bool check(int x){
priority_queue<Task> q;
for(int d=1,i=0;d<20001;++d){
while(i<n && task[i].r==d){
q.push(task[i]);
++i;
}
if(q.empty()){
if(i==n) break;
else continue;
}
int tot=x;
while(!q.empty() && tot>0){
Task temp=q.top();
q.pop();
if(d>=temp.d && temp.w>0) return false;
if(d<temp.d){
if(temp.w<=tot){
tot-=temp.w;
temp.w=0;
}else {
temp.w-=tot;
q.push(temp);
tot=0;
}
}
}
}
return q.empty();
}
int main(void){
scanf("%d",&kase);
while(kase--){
scanf("%d",&n);
int left=0,right=10000000;
for(int i=0;i<n;++i){
scanf("%d%d%d",&r,&d,&w);
task[i]=Task{r,d,w};
}
sort(task,task+n,cmp);
while(left<right){
int mid=(left+right)/2;
if(check(mid)) right=mid;
else left=mid+1;
}
printf("%d\n",left);
}
}