二分+贪心。
二分答案,然后需要判断该速度时能否完成所有任务。每次优先去做结束时间早的任务。这样从1开始枚举每个时刻,如果该时刻是某任务的左端点就把它放进优先队列,然后每一秒优先去做结束时间早的任务。这里有个非常恶心的地方,如果你在这一秒内完成了这个任务,但是这一秒还没有结束,那么你可以把余下的时间去做另一个任务。用另一种角度阐述就是,如果某一秒速度v>某任务的工作量w,那么多出来的(v-w)这一块速度可以继续去干别的,直到这段速度全部用完或者没有任务可干。
判断的时候有两个地方,一是如果在某时刻队列中还存在结束时间比该时刻早的任务,那么这个速度肯定是小了。二是所有时间结束后队列非空,说明速度小了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define MOD 20071027
#define MAXN 20005
using namespace std;
int minn,maxn;
struct Task
{
int w,l,r;
Task(int a=0,int b=0,int c=0):w(a),l(b),r(c) {}
bool operator < (const Task &p) const
{
return r>p.r;
}
};
vector<Task> vec[MAXN];
void process(priority_queue<Task> &pq,int v)
{
if(!pq.empty())
{
Task t=pq.top();
pq.pop();
t.w-=v;
if(t.w>0) pq.push(t);
else
{
while(t.w<0&&!pq.empty())
{
Task tt=pq.top();
pq.pop();
tt.w+=t.w;
if(tt.w>0) pq.push(tt);
t.w=tt.w;
}
}
}
}
void Init()
{
for(int i=0; i<=20000; ++i)
vec[i].clear();
}
bool Judge(int v)
{
priority_queue<Task> pq;
for(int i=minn; i<=maxn; ++i)
{
if(!pq.empty()&&pq.top().r<=i) return false;
for(int j=0; j<vec[i].size(); ++j)
pq.push(vec[i][j]);
process(pq,v);
}
if(pq.empty()) return true;
else return false;
}
int Bsearch(int low,int high)
{
int mid=(low+high)>>1;
while(low<high)
{
if(Judge(mid)) high=mid;
else low=mid+1;
mid=(low+high)>>1;
}
return mid;
}
int main()
{
//freopen("shuju.txt","r",stdin);
// freopen("myout.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
minn=INF;
maxn=0;
Init();
int x,y,z;
for(int i=0; i<n; ++i)
{
scanf("%d%d%d",&x,&y,&z);
minn=min(minn,x);
maxn=max(maxn,y);
vec[x].push_back(Task(z,x,y));
}
int ans=Bsearch(1,1000);
printf("%d\n",ans);
}
return 0;
}