1. 程式人生 > >51Nod 1279 扔盤子

51Nod 1279 扔盤子

有一口井,井的高度為N,每隔1個單位它的寬度有變化。現在從井口往下面扔圓盤,如果圓盤的寬度大於井在某個高度的寬度,則圓盤被卡住(恰好等於的話會下去)。

盤子有幾種命運:1、掉到井底。2、被卡住。3、落到別的盤子上方。

盤子的高度也是單位高度。給定井的寬度和每個盤子的寬度,求最終落到井內的盤子數量。

如圖井和盤子資訊如下:

井:5 6 4 3 6 2 3

盤子:2 3 5 2 4

最終有4個盤子落在井內。

收起

輸入

第1行:2個數N, M中間用空格分隔,N為井的深度,M為盤子的數量(1 <= N, M <= 50000)。
第2 - N + 1行,每行1個數,對應井的寬度Wi(1 <= Wi <= 10^9)。
第N + 2 - N + M + 1行,每行1個數,對應盤子的寬度Di(1 <= Di <= 10^9)

輸出

輸出最終落到井內的盤子數量。

輸入樣例

7 5
5
6
4
3
6
2
3
2
3
5
2
4

輸出樣例

4

 思路:

想了很久,發現了下面一層不管比上面一層大多少都不影響判定。所以如果出現下一層比上一層大的情況,則直接將下一層等於上一層。然後從上到下就形成了個遞減序列,這是從下往上遍歷,找第一個比盤大或等於盤子寬度的層,這層就是盤子的落腳點。因為上面的轉化後都比下面的大。

程式碼如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=50005;
int n,m;
int w[maxn];
int d[maxn];
int ans=0;
int main()
{
    scanf("%d%d",&n,&m);
    w[0]=0x3f3f3f3f;
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);
        if(w[i]>w[i-1])
        {
            w[i]=w[i-1];
        }
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&d[i]);
    }
    for (int i=n,j=1;i>=1;i--,j++)
    {
        while (w[i]<d[j]&&i>=1)
        {
            i--;
        }
        if(i>=1&&w[i]>=d[j])
        {
            ans++;
        }
    }
    printf("%d\n",ans);
    return 0;
}