题目
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
有N头牛,每头牛有个喝水时间,这段时间它将专用一个Stall 现在给出每头牛的喝水时间段,问至少要多少个Stall才能满足它们的要求
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
OUTPUT DETAILS:
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.
HINT
不妨试下这个数据,对于按结束点SORT,再GREEDY的做法 1 3 5 7 6 9 10 11 8 12 4 13 正确的输出应该是3
思路
首先看到这道题,第一想法居然是线段树。。。
把所有区间覆盖了之后求覆盖的最大值就行了。
于是,用线段树很 愉(jian) 快(nan) 的水过去了。
直到看到这句话:
。。。。。。。。。。。。。。。。。。
好吧,纯属眼瞎。。。
我们按起始点排序,用一个优先级队列(大根堆)维护结束点,然后拿新的牛跟结束时间最靠前的元素比一下,如果新的牛可以喝水,队首改为当新的牛的结束点,否则就直接往队列里新加入当前结束点,最后把队列的大小打出即可。
代码
- 解法1:线段树
//1、线段树
#include <bits/stdc++.h>
using namespace std;
const int M = 1010010;
struct node {
int l, r, w, f;
} t[4*M];
int a, b, n, aa[50010], bb[50010];
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1)+(x << 3)+(ch ^ 48);
ch = getchar();
}
return x*f;
}
void build(int k, int L, int R) {
t[k].l = L, t[k].r = R;
if (t[k].l == t[k].r) return ;
int m = (L + R) / 2;
build(k*2, L, m);
build(k*2+1, m+1, R);
}
inline void down(int k) {
t[k*2].f += t[k].f;
t[k*2+1].f += t[k].f;
t[k*2].w += t[k].f;
t[k*2+1].w += t[k].f;
t[k].f = 0;
}
void change_interval(int k) {
if (t[k].l >= a && t[k].r <= b) {
t[k].w++, t[k].f++;
return ;
}
if(t[k].f) down(k);
int m=(t[k].l+t[k].r)/2;
if (a <= m) change_interval(k*2);
if (b > m) change_interval(k*2+1);
t[k].w = max(t[k*2].w, t[k*2+1].w);
}
int main() {
ios::sync_with_stdio(false);
int m = read(), n = -10;
for (int i = 1; i <= m; i++)
aa[i] = read(), bb[i] = read(), n = max(bb[i], n);
build(1, 1, n);
for (int i = 1; i <= m; i++)
a = aa[i], b = bb[i], change_interval(1);
cout << t[1].w << endl;
return 0;
}
- 解法2:贪心
//2、贪心
#include <bits/stdc++.h>
using namespace std;
struct node {
int s, e;
} a[50010];
priority_queue <int, vector<int>,greater<int> > q;
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1)+(x << 3)+(ch ^ 48);
ch = getchar();
}
return x*f;
}
bool cmp(const node &a, const node &b) {
return a.s < b.s;
}
int main() {
ios::sync_with_stdio(false);
int n = read();
for (int i = 1; i <= n; i++)
a[i].s = read(), a[i].e = read();
sort(a+1, a+1+n, cmp);
for (int i = 1; i <= n; i++) {
if (q.size() == 0) {q.push(a[i].e); continue;}
if (q.top() < a[i].s) q.pop();
q.push(a[i].e);
}
cout << q.size() << endl;
return 0;
}