高橋和低橋 CSU - 1335
Time limit 1000 ms Memory limit 131072 kB
有個腦筋急轉彎是這樣的:有距離很近的一高一低兩座橋,兩次洪水之後高橋被淹了兩次,低橋卻只被淹了一次,爲什麼?答案是:因爲低橋太低了,第一次洪水退去之後水位依然在低橋之上,所以不算“淹了兩次”。舉例說明:
假定高橋和低橋的高度分別是5和2,初始水位爲1
第一次洪水:水位提高到6(兩個橋都被淹),退到2(高橋不再被淹,但低橋仍然被淹)
第二次洪水:水位提高到8(高橋又被淹了),退到3。
沒錯,文字遊戲。關鍵在於“又”的含義。如果某次洪水退去之後一座橋仍然被淹(即水位不小於橋的高度),那麼下次洪水來臨水位提高時不能算“又”淹一次。
輸入n座橋的高度以及第i次洪水的漲水水位ai和退水水位bi,統計有多少座橋至少被淹了k次。初始水位爲1,且每次洪水的漲水水位一定大於上次洪水的退水水位。
Input輸入文件最多包含25組測試數據。每組數據第一行爲三個整數n, m, k(1<=n,m,k<=105)。第二行爲n個整數hi(2<=hi<=108),即各個橋的高度。以下m行每行包含兩個整數ai和bi(1<=bi<ai<=108, ai>bi-1)。輸入文件不超過5MB。
Output對於每組數據,輸出至少被淹k次的橋的個數。
Sample Input2 2 2
2 5
6 2
8 3
5 3 2
2 3 4 5 6
5 3
4 2
5 2
Sample Output
Case 1: 1
Case 2: 3
題解:題意大概應該都知道,就不多說了,下面給出兩種解法……
1:二分法……
雖然洪水的的先後不可以排序,但橋的高度可以排序……
開兩個數組X和Y,X存橋的高度,Y存被淹的次數……
先說明下一個函數……
uppper_bound返回第一個大於a的座標
例如 int x[12]={0,2,4,4,4,5,5,5,6,7,7,8};
upper_bound(x,x+12,4)-x)=5;
upper_bound(x,x+12,-1)-x)=0;
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<string>
#include<math.h>
#include<map>
#include<queue>
#include<stack>
#define INF 0x3f3f3f3f
#define ll long long
#define For(i,a,b) for(int i=a;i<b;i++)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int x[100005],y[1000005]; // x 存橋的高度,y 存被淹的次數……
int main()
{
int n,m,k,s=0;
while(~scanf("%d%d%d",&n,&m,&k))
{
mem(y,0); // 次數初始化爲0
s++;
For(i,0,n)
scanf("%d",&x[i]);
sort(x,x+n);
int a,b,tb=1;
For(i,0,m)
{
scanf("%d%d",&a,&b);
int aa=upper_bound(x,x+n,a)-x; // 返回大於 a 的橋的座標
y[aa]--; // 因爲此橋大於a,所以淹不到,減1……
int bb=upper_bound(x,x+n,tb)-x; // tb 爲退潮後的水位,初始水位爲1,返回大於初始水位的橋的下標……
y[bb]++; // 因爲此橋大於上一次退潮水位,故這次它被淹了,加1……
tb=b; // 更新 退潮水位……
}
For(i,0,n) // 因爲橋的大小已排序,所以,只要前邊的被淹了,後面得一段橋也會被淹,
y[i+1]+=y[i]; // 所以讓y 自加……變成所有的洪水之後的次數
int ans=0;
For(i,0,n) // 計數……
{
if(y[i]>=k)
ans++;
}
printf("Case %d: %d\n",s,ans);
}
}