HDU 6180 Schedule (贪心)

Description

给出\(n\)个加工任务的开始时间和结束时间,问最少要用多少台机器可以完成这些任务,同一台机器上的任务时间不能有重叠,但允许守尾相接。

Input

第一行给出用例组数\(T\),对于每组用例,第一行给出任务数量\(n\),接下来\(n\)行,每行给出两个整数,表示任务的开始时间和结束时间。\(1 \leqslant T \leqslant 100\)\(1 \leqslant n \leqslant 10^5\)

Output

对于每组用例,输出两个整数,分别表示最少用的机器台数和所有机器用的总时间。一台机器的用时为它最后的结束时间减它最开始启动的时间,中间不会停机。

Sample Input

1
3
1 3
4 6
2 5

Sample Output

2 8

Solution

经典的任务分配问题。对所有的\(2n\)个时间点统一排序,如果时间点相同,就优先结束点在前,开始点在后。具体的实现可以对每个时间点存一个\(pair\)\(first\)为时刻值,开始点的\(second\)\(1\),结束点的\(second\)\(-1\)

从前到后扫描\(2n\)个时间点,\(second\)的前缀和的最大值就是最少用的机器数量。

要求总用时,定于\(left[i]\)表示第\(i\)台机器的开始时间,\(right[i]\)表示第\(i\)台机器当前到的时间,\(left[i]\)在第一次用到\(i\)机器时记录,\(right[i]\)随扫描的进行不断更新,当扫描到一个结束点时,说明当前的机器要结束,先更新\(right[i]\)的值,计数器再减一。扫描结束后\(right\)数组中存储的就是每台机器最终的结束时间。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
typedef pair<int, int> pii;

pii a[2 * N];
int l[N], r[N];

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) 
        {
            int left, right;
            scanf("%d%d", &left, &right);
            a[2 * i - 1] = pii(left, 1);
            a[2 * i] = pii(right, -1);
        }
        sort(a + 1, a + 2 * n + 1);
        memset(l, -1, sizeof(l));
        memset(r, -1, sizeof(r));
        int num = 0, ans = 0;
        for (int i = 1; i <= 2 * n; i++)
        {
            if (a[i].second == 1)
            {
                num++;
                if (l[num] == -1) l[num] = r[num] = a[i].first;
                ans = max(ans, num);
            }
            else
            {
                r[num] = a[i].first;
                num--;
            }
        }
        ll sum = 0;
        for (int i = 1; i <= ans; i++) sum += r[i] - l[i];
        printf("%d %lld\n", ans, sum);
    }
    return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=6180

posted @ 2017-08-24 21:50  达达Mr_X  阅读(436)  评论(0编辑  收藏  举报