高橋和低橋 CSU - 1335

高橋和低橋     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 Input
2 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);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章