UVALive - 4254 Processor

题意:有n个任务,每个任务有三个参数,r,d,w,表示该任务必须在[r,d]之间执行,工作量是w,处理器执行速度可以变化,当执行速度是s的时候,一个工作量是w的任务需要需要的执行时间是w/s个工作单位,另外,任务不一定要连续的执行,可以分成若干块,求出处理器执行过程中最大速度的最小值,速度必须是整数


思路:最大值的最小值用二分处理,对于一个速度来说,我们可以考虑它在单位时间能做的事,定义两个变量,一个代表处理了的任务个数,一个代表当前的时间,我们没一个单位时间的递加,对于未处理或者未处理完的一个任务如果它的 l 的大小还小于当前的 j,那么我们就可以处理它,至于处理的先后顺序是按 r 从小到大,很容易贪心证明,那么对于一个任务我们每次都减去它所能处理的最大值,如果当前还有没有处理的任务且它的 r 值大于等于当前时间的话,那么这个速度是不行的,都处理的话,就可以了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 10005;

struct node{
    int l,r,w;
    bool operator <(const node &a)const {
        return r > a.r;
    }
}arr[MAXN];
int n,ans;
priority_queue<node> q;

bool cmp(node a,node b){
    return a.l < b.l;
}

bool check(int mid){
    int i = 0, j = 0;
    while (!q.empty())
        q.pop();
    while (1){
        while (i < n && arr[i].l <= j)
            q.push(arr[i++]);
        int now = mid;
        while (now != 0 && !q.empty()){
            node temp = q.top();
            q.pop();
            int m = min(now,temp.w);
            now -= m;
            temp.w -= m;
            if (temp.w != 0)
                q.push(temp);
        }
        j++;
        if (!q.empty() && q.top().r <= j)
            return false;
        if (q.empty() && i == n)
            return true;
    }
}

int main(){
    int t;
    scanf("%d",&t);
    while (t--){
        scanf("%d",&n);
        int sum = 0;
        for (int i = 0; i < n; i++){
            scanf("%d%d%d",&arr[i].l,&arr[i].r,&arr[i].w);
            sum += arr[i].w;
        }
        sort(arr,arr+n,cmp);
        int l = 0,r = sum;
        while (l <= r){
            int mid = (l+r)>>1;
            if (check(mid)){
                ans = mid;
                r = mid - 1;
            }
            else l = mid + 1;
        }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(UVALive - 4254 Processor)