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 }