题目:有n个任务,每个任务有三个参数ri,di,wi,表示任务i必须在[ri, di]内执行完,现有一台处理器,处理器执行的速度可以变化,速度为s时,一个工作量为wi的任务执行的时间为w/s,任务不一定连续执行,现在要求求出处理器在执行过程中最大速度的最小值。
分析:首先一定是个二分,所以主要的地方在于check函数怎么写。假设某一时刻的速度为v,不难想到,如果贪心的选择结束时间距离当前时刻最近的任务执行(这里需要用到优先队列),一定是最优的,并且这样还可以避免浮点数运算。
ps:优先队列使用
代码如下:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#define db double
using namespace std;
const int maxn = 10000 + 10;
const int INF = (int)1e9;
struct node {
int l, r, w;
bool operator < (const node &a) const {
return r > a.r;
}
}A[maxn];
int n, mint, maxt;
priority_queue<node> Q;
bool cmp(node a, node b) {
return a.l < b.l || (a.l == b.l && a.r < b.r);
}
bool check(int var) {
while (!Q.empty()) Q.pop();
int pos = 0;
for (int tim = mint; tim < maxt; tim ++) {
while (pos < n && A[pos].l <= tim) Q.push(A[pos++]);
while (!Q.empty() && var) {
node tmp = Q.top(); Q.pop();
if (tmp.l < tim) {
tmp.l = tim;
Q.push(tmp);
continue;
}
if (tmp.r <= tim) return false;
if (tmp.w <= var) var -= tmp.w;
else {
tmp.w -= var;
Q.push(tmp);
break;
}
}
}
return Q.empty();
}
int main(){
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
int T; scanf("%d", &T);
while (T --) {
scanf("%d", &n);
int sumw = 0;
mint = INF, maxt = 0;
for (int i = 0; i < n; i ++) {
scanf("%d %d %d", &A[i].l, &A[i].r, &A[i].w);
sumw += A[i].w;
mint = min(mint, A[i].l);
maxt = max(maxt, A[i].r);
}
sort(A, A + n, cmp);
int L = 0, R = sumw, ans;
while (L <= R) {
int M = L + (R-L) / 2;
if (check(M)) {
ans = M;
R = M - 1;
} else L = M + 1;
}
printf("%d\n", ans);
}
return 0;
}