这道题受到了以前做过的一道题目的影响,有n节课,每节课都有一个开始结束时间,求出一天中最多可以上多少节课,使得任意两节课时间不冲突。这道题目是按照结束时间递增的时间排序。
刚开始碰到这道题我就有感觉和以前那道题差不多,毕竟对于每一个stall,都是尽量的使得里面的区间最多。所以我就按照结束时间排序了。
但是这道题目怎么写呢?按照贪心的思想,我们肯定是想要每一个stall都是尽量满的,这样一来,使用的stall就会更少。所以假如现在已经有了n个stall,我们在考虑一个区间。我们该把这个区间放到哪个stall中去呢?还是我们要新增一个stall来放置这个区间?
为了使得空间尽量的不浪费,我们选择n个stall中剩余空间最大的那个来装置这个区间,如果可以装的下,就装在这里。如果装不下,那么其他的也装不下,我们就新增一个stall来安置这个区间。
但是这样一想,我们刚才按照结束时间排序的策略就不太合适了,我们想要所有区间排列的尽量紧密,那么我们应该先考虑左端点小的区间,这样才能结合的更紧密。也就是我们一开始要按照左端点递增来排序。
#include <map>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define MAX_N 50005
using namespace std;
struct data
{
int l, r;
int id;
bool operator < (const data& b) const
{
return l < b.l;
}
};
data dat[MAX_N];
typedef pair<int, int> pii;//每个stall最后一个区间的结束时间,这个stall的编号
priority_queue<pii, vector<pii>, greater<pii> > stalls;
int main()
{
//freopen("in.txt", "r", stdin);
int N;
int stall_id[MAX_N];//保存每个区间所在stall的编号
while (scanf("%d", &N) != EOF)
{
for (int i = 1; i <= N; i++)
{
scanf("%d%d", &dat[i].l, &dat[i].r);
dat[i].id = i;
}
sort(dat + 1, dat + N + 1);
int cnt = 1;
stalls.push(pii(dat[1].r, cnt));
stall_id[dat[1].id] = cnt;
for (int i = 2; i <= N; i++)
{
int ok = 0;
if (!stalls.empty())
{
pii t = stalls.top();
if (t.first < dat[i].l)
{
t.first = dat[i].r;
stalls.pop();
stalls.push(pii(t));
stall_id[dat[i].id] = t.second;
ok = 1;
}
}
if (!ok)
{
cnt++;
stalls.push(pii(dat[i].r, cnt));
stall_id[dat[i].id] = cnt;
}
}
printf("%d\n", cnt);
for (int i = 1; i <= N; i++)
printf("%d\n", stall_id[i]);
}
return 0;
}