二分+贪心。
二分答案,然后需要判断该速度时能否完成所有任务。每次优先去做结束时间早的任务。这样从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; }