[USACO06FEB]Stall Reservations S(构造)

题目描述:

约翰的N(l<N< 50000)头奶牛实在是太难伺候了,她们甚至有自己独特的产奶时段.当 然对于某一头奶牛,她每天的产奶时段是固定的,为时间段A到B包括时间段A和时间段B.显然,约翰必须开发一个调控系统来决定每头奶牛应该被安排到哪个牛棚去挤 奶,因为奶牛们显然不希望在挤奶时被其它奶牛看见.

约翰希望你帮他计算一下:如果要满足奶牛们的要求,并且每天每头奶牛都要被挤过奶,至少需要多少牛棚 •每头牛应该在哪个牛棚被挤奶。如果有多种答案,你只需任意一种即可。

题解:

网上很多人都是用贪心,我这里给出一种另类做法。

显然牛棚是有一个上限的,也就是n。

我们先假设有n个牛棚。把奶牛的开始和结束时间都放到一个数组并打上不同的标记,把他们按时间排序(时间相同的开始时间要在结束时间前)。

首先刚开始这n个牛棚都是空闲的。

遇到一个开始时间空闲牛棚数就减一,遇到一个结束时间空闲牛棚数就加一。

我们找出在每次操作后空闲牛棚的最小值,显然这些牛棚从未被用过,是不需要的,要用的就是剩下的牛棚。

我们知道了最小的牛棚数构造就很简单了。

我们先把所有空闲的牛棚放进一个队列里,每次要用就从队列里去一个,每次用完就放回队列里。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 50010;
int n;
int a[N], b[N];
struct node{
    int t, f, id;
}p[N << 1];
int top;
int lim, mi, num;
int ans[N];
queue<int> q;
bool cmp(node x, node y) {
    if (x.t == y.t) return x.f > y.f;
    return x.t < y.t;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &a[i], &b[i]);
        p[++top] = node{a[i], 1, i};
        p[++top] = node{b[i], 0, i};
    }
    sort(p + 1, p + 1 + top, cmp);
    mi = lim = n;
    for (int i = 1; i <= top; i++) {
        if (p[i].f == 1) {
            lim--;
        } else {
            lim++;
        }
        mi = min(mi, lim);
    }
    num = lim - mi;
    printf("%d\n", num);
    for (int i = 1; i <= num; i++) q.push(i);
    for (int i = 1; i <= top; i++) {
        if (p[i].f == 1) {
            ans[p[i].id] = q.front();
            q.pop();
        } else {
            q.push(ans[p[i].id]);
        }
    }
    for (int i = 1; i <= n; i++) {
        printf("%d", ans[i]);
        putchar('\n');
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zcr-blog/p/12718381.html