今天怕是石乐志。。。。
题目:UVA-1422
题目大意:给你n个任务,每个任务要在【l,r】的时间内完成w个工作量,注意坑点*就是这个任务可以分段完成,就是先完成一部分再在另外一个时间完成另一部分*,那么这题肯定是贪心,将完成时间靠前的先考虑,然后二分工作速度,就是每分钟做多少个工作量,然后枚举每一秒,在每一秒内,找到任务开始时间在这时间里的那些任务,优先做那些结束时间早的任务,所以要用优先队列维护。。。。
优先队列石乐志,一直不知道优先队列用结构体的时候要加重载函数,,
struct node
{
int l,r,s;
// bool operator < (const node & a) const {
// return r > a.r;
//}
bool operator<(const node &a)const
{
return r>a.r;//这里的意思就是r越小的在优先队列里越优先,别被>号误解
}
}p[10000+10];
代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int n,max_;
struct node
{
int l,r,s;
// bool operator < (const node & a) const {
// return r > a.r;
//}
bool operator<(const node &a)const
{
return r>a.r;
}
}p[10000+10];
priority_queue<node>w;
bool cmp(node x,node y)
{
if(x.l==y.l)
return x.r<y.r;
return x.l<y.l;
}
int judge(int mid)
{
priority_queue<node>q;
//queue<node>q;
int cnt=0;
for(int i=1;i<=max_;i++)//枚举每一秒直到某个任务的最大结束时间
{
while(p[cnt].l<i&&cnt<n)//把那些可以开始做的任务加入队列
q.push(p[cnt++]);
int res=mid;//res代表这一秒可以做的任务量
while(res!=0&&!q.empty())
{
//node now=q.front();
node now=q.top();
q.pop();
if(now.r<i)//如果这个任务的结束时间小于现在,但是它还在队列里,说明这个任务永远完成不了了,说明这个工作速度不行,可以返回了。
return 0;
if(now.s>res)//如果这个任务量大于这一秒可以做的量,那么还需要把这个任务加入队列,此时这一秒可以做的量都没了,都贡献给了这个任务
{
now.s-=res;
res=0;
q.push(now);
}
else//如果这个任务量小于这一秒可以做的量,那说明这个任务完成了,就不需要再加入队列了,但是这一秒可以做的量还有剩余,再拿去给别的任务用
{
res-=now.s;
}
}
}
if(cnt==n&&q.empty())//检查是否所有任务都被访问到了并且队列里没有任务了
return 1;
else
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
//int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>p[i].l>>p[i].r>>p[i].s;
max_=max(max_,p[i].r);
//w.push(p[i]);
}
// while(!w.empty())
// {
// node u=w.top();
// w.pop();
// cout<<u.l<<" "<<u.r<<" "<<u.s<<endl;
// }
sort(p,p+n,cmp);
int l=0,r=100000,mid;
while(l<r)
{
mid=(l+r)/2;
if(judge(mid))
r=mid;
else
l=mid+1;
//cout<<"l="<<l<<" "<<"r="<<r<<endl;
}
cout<<l<<endl;
}
return 0;
}