[USACO06FEB] Stall Reservations 贪心

[USACO06FEB] Stall Reservations 贪心

\(n\)头牛,每头牛占用时间区间\([l_i,r_i]\),一个牛棚每个时间点只能被一头牛占用,问最少新建多少个牛棚,并且每头牛在哪个牛棚里?

比较巧的\(O(n)\)扫一遍做法,用一个小跟堆维护所有牛棚最后一个牛占用的时间(即\(r_i\)),贪心的想,如果最先结束的那个牛棚都不能满足当前牛,那么我们只能新开一个牛棚,并继续维护小根堆;如果那个牛棚满足,那么这个牛就去那个牛棚,更新当前牛棚最后占用时间。

#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
inline int read(){
    char ch=getchar();int s=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') s=s*10+(ch^'0'), ch=getchar();
    return s;
}
struct nod{
    int cnt,last;
    const bool operator < (const nod &a) const{
        return last>a.last; // 小根堆
    }
    nod(int cnt, int last):cnt(cnt),last(last){}
};
#define MAXN 50005
struct nod2{
    int l,r,id;
    const bool operator < (const nod2 &a) const{
        if(l==a.l) return r<a.r;
        return l<a.l;
    }
} a[MAXN];
int ans[MAXN];
priority_queue<nod> q;
int n;
int sum=0;
int main(){
    n=read();
    for(int i=1;i<=n;++i) a[i].id=i,a[i].l=read(),a[i].r=read();
    sort(a+1, a+1+n);
    q.push(nod(1, a[1].r));
    ans[a[1].id]=1;
    ++sum;
    for(int i=2;i<=n;++i){
        nod cur=q.top();
        if(cur.last>=a[i].l){
            ++sum; // 新开牛棚
            ans[a[i].id]=sum;
            q.push(nod(sum, a[i].r));
        }else{
            q.pop(); // 更新牛棚最后结束时间
            ans[a[i].id]=cur.cnt;
            q.push(nod(cur.cnt, a[i].r));
        }
    }
    printf("%d\n", sum);
    for(int i=1;i<=n;++i) printf("%d\n", ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/santiego/p/11837680.html