P1569 -- 喝水

时间限制:2000MS      内存限制:131072KB

状态:Accepted      标签:    无   无   无

Description

GH的N个妹子要喝水,喝水有个时间从A时刻开始到B时刻结束。求最少需要多少个水龙头供水(GH的妹子都用水龙头喝水。。。。。。。。。。)

Input Format

输入第一行一个数N,接下来N行每行一对A,B。

Output Format

输出一个数为答案。

Sample Input

5
1 10
2 4
3 6
5 8
4 7

Sample Output

4

Hint

对于10%的数据N<=10

对于100%的数据N<=2000000,A,B<=15000000

本题输入文件不超过35M,建议开启输入优化。

 

题解

      这道题是区间覆盖的问题。不难看出只要区间不相交的所有区间都可以公用一个水龙头。我们可以用“差分“来解决这个问题。对于区间[A,B],差分数组Q[A]++, Q[B + 1]--。不难看出,这样一直做下去,会先把[A,B],[B + 1, C]这样的区间合并在一起。最后遍历差分数组,用Cnt += Q[i], Ans = Max(Ans, Cnt)。答案即Ans。之所以要取一个Max,因为右端点会减一,且会和左端点加一把不相交的区间只算一次,Cnt最大的时候表示的即答案。

 

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define SIZE 15000010
 4 #define INF 210000000
 5 using namespace std;
 6 
 7 char B[1<<15],*S=B,*T=B;char getc(){
 8     return S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++;
 9 }
10 #define isd(c) (c>='0'&&c<='9')
11 int aa,bb;char ch;int Scan(){
12     while(ch=getc(),!isd(ch)&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
13     while(ch=getc(),isd(ch))aa=aa*10+ch-'0';return bb?aa:-aa;
14 }
15 
16 int N;
17 int L = INF, R;
18 int Left, Right;
19 int Q[SIZE];
20 int Cnt, Ans;
21 
22 int Min(int A, int B) {
23     return A < B ? A : B;
24 }
25 
26 int Max(int A, int B) {
27     return A > B ? A : B;
28 }
29 
30 int main() {
31     N = Scan();
32     for (int i = 1; i <= N; ++i) {
33         Left = Scan(); Right = Scan();
34         L = Min(Left, L);
35         R = Max(Right, R);
36         ++Q[Left];
37         --Q[Right + 1];
38     }
39     for (int i = L; i <= R + 1; ++i) Cnt += Q[i], Ans = Max(Ans, Cnt);
40     printf("%d\n", Ans); 
41 }