csu 1685: Entertainment Box【湖南省多校对抗赛3.6】multiset妙用

链接:点击读题

Description:

Input:

Output:


题意:给定N个任务,你可以最多同时一起进行K个任务,多进程嘛。然后每个任务都规定了开始时间和结束时间,求最多能够完成多少个任务。

思路:首先,对N个任务,按照结束时间进行区间排序。然后考虑将任务分配到哪一个进程中去处理,第i个进程处理完结束时间用S[i]表示,显然,如果某一个任务的开始时,所有进程都未空闲,此时,任务不能被执行。反正,任务就要被执行,如果这个时候又多个空闲的进程,那么分配到哪个进程中去呢?必然是刚刚结束任务的那个进程,而不是最先空闲的那个进程,因为这个情况下,空闲时间段是最大的。这里要理解理解。【我们WA好几次~~~~】这个时候,问题 就是在 所有进程S中查询 小于当前任务开始时间,并且最接近当前任务开始时间的进程。为了方便维护S的有序性,平衡二叉树!multiset的实现其实就是平衡二叉树!

贴一下代码。

#include <set>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int, int> PII;
const int maxn = 100000 + 5;
int n, k;
struct Interval{
    int _beg, _end;
    bool operator < (const Interval& e) const {
        return _end < e._end;
    }
};
Interval t[maxn];
int ans;
multiset<int> S;
multiset<int>::iterator it;
int main() {
//    freopen("input.txt", "r", stdin);
    while(~scanf("%d %d", &n, &k)) {
        for(int i = 0; i < n; i++) {
            scanf("%d %d", &t[i]._beg, & t[i]._end);
        }
        sort(t, t + n);
        ans = 0;
        S.clear();
        for(int i = 0; i < k; i++) {
            S.insert(0);
        }
        for(int i = 0; i < n; i++) {
            it = S.begin();
            if(t[i]._beg < *it) continue;
            else if(t[i]._beg == *it) {
                S.erase(it);
                S.insert(t[i]._end);
            }else {
                it = S.upper_bound(t[i]._beg);
                it--;
                S.erase(it);
                S.insert(t[i]._end);
            }
            ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}





你可能感兴趣的:(multiset,CSU)