Description
Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A…B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a reservation system to determine which stall each cow can be assigned for her milking time. Of course, no cow will share such a private moment with other cows.
Help FJ by determining:
The minimum number of stalls required in the barn so that each cow can have her private milking period
An assignment of cows to these stalls over time
Many answers are correct for each test dataset; a program will grade your answer.
Input
Line 1: A single integer, N
Lines 2…N+1: Line i+1 describes cow i’s milking interval with two space-separated integers.
Output
Line 1: The minimum number of stalls the barn must have.
Lines 2…N+1: Line i+1 describes the stall to which cow i will be assigned for her milking period.
Sample Input
5
1 10
2 4
3 6
5 8
4 7
Sample Output
4
1
2
3
2
4
Hint
Explanation of the sample:
Here’s a graphical schedule for this output:
Time 1 2 3 4 5 6 7 8 9 10
Stall 1 c1>>>>>>>>>>>>>>>>>>>>>>>>>>>
Stall 2 … c2>>>>>> c4>>>>>>>>> … …
Stall 3 … … c3>>>>>>>>> … … … …
Stall 4 … … … c5>>>>>>>>> … … …
Other outputs using the same number of stalls are possible. (该题目存在特殊判题)
题目大意:
每头奶牛拥有自己的挤奶区间,而它们又不愿意在同一个畜栏中(即两头奶牛的挤奶区间不能重合,端点重合也不允许),求最小畜栏数和每头牛吃的栏编号。
解题思路:
可以用贪心做,依据奶牛挤奶区间的开始时间排序。依次放奶牛,若所有畜栏都没空,那么就再造一个畜栏。
一开始写了个n^2 暴力统计,预想会超时,果真就超时了。。。
然后查看大佬们的思路发现可以用优先队列进行优化(结束时间早的畜栏优先度高),那么时间复杂度就降为O(nlogn)然后就可以过了
下面来探讨一下为什么结束时间早的畜栏优先度高:
1、如果现在要考虑的奶牛挤奶区间为New1,则能够选择的已有畜栏只有栏一;
2、如果现在要考虑的奶牛挤奶区间为New2,则三个已有畜栏都可以选择,此时选择任何一个都可以,因为已经依据奶牛挤奶区间的开始时间进行排序,所以接下来要考虑的区间左边界一定不大于New2的左边界,因此无论选择哪一个,三种情况下对于接下来的选择都是等价的。故而我们可以认为结束时间早的畜栏优先度高以方便讨论。
AC代码
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
struct node {
int x, y;
int t, myself;
bool operator < (const node &a) const {//优先队列,大顶堆,重载运算符以便强行输出最小
if (y == a.y) { return x > a.x; }
return y > a.y;
}
}list[50001];
priority_queue<node> que;
bool cmp1(node a, node b) {
if (a.x == b.x) { return a.y < b.y; }
return a.x < b.x;
};
bool cmp2(node a, node b) {
return a.myself < b.myself;
};
int main() {
int n;
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; i++) {
scanf("%d%d", &list[i].x, &list[i].y);
list[i].t = 0; list[i].myself = i;
}
sort(list + 1, list + 1 + n, cmp1);
int ans = 1;
list[1].t = ans;
que.push(list[1]);
for (int i = 2; i <= n; i++) {
if (list[i].x > que.top().y) {
list[i].t = que.top().t;
que.pop();
que.push(list[i]);
}
else {
ans++;
list[i].t = ans;
que.push(list[i]);
}
}
printf("%d\n", ans);
sort(list + 1, list + 1 + n, cmp2);
for (int i = 1; i <= n; i++) {
printf("%d\n", list[i].t);
}
}
return 0;
}