51NOD 1279 扔盘子(二分 + 思维)

传送门

有一口井,井的高度为N,每隔1个单位它的宽度有变化。现在从井口往下面扔圆盘,如果圆盘的宽度大于井在某个高度的宽度,则圆盘被卡住(恰好等于的话会下去)。

盘子有几种命运:1、掉到井底。2、被卡住。3、落到别的盘子上方。

盘子的高度也是单位高度。给定井的宽度和每个盘子的宽度,求最终落到井内的盘子数量。

如图井和盘子信息如下:

井:5 6 4 3 6 2 3

盘子:2 3 5 2 4

最终有4个盘子落在井内。

本题由 @javaman 翻译。

Input

第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)

Output

输出最终落到井内的盘子数量。

Input示例

7 5

5

6

4

3

6

2

3

2

3

5

2

4

Output示例

4

解题思路:

我们首先考虑一下这个井,这个井第 i 层的宽度应该跟它前面的 i-1层的宽度有关系,第 i 层的宽度能够允许盘子通过的最大宽度应该是前 i 层的最小宽度,否则就会被卡住,那么现在井的宽度就变成了一个有序的序列(这个很关键),现在我们就是求这个盘子每次到达什么地方,也就是在这个有序的序列中第一个 >= 盘子的宽度的地方,然后就让这个位置加+1,下次再从这个位置+1开始到最后查找,也就是二分查找。具体详见代码:

My Code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int MAXN = 50000+5;
const int INF = 1e9+100;
int W[MAXN], D[MAXN];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        W[n+1] = INF;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&W[n-i]);
            W[n-i] = min(W[n-i+1],W[n-i]);
        }
        for(int i=0; i<m; i++)
            scanf("%d",&D[i]);
        int ans = 0, tp = 1;
        for(int i=0; i<m; i++)
        {
            int tmp = lower_bound(W+tp, W+n+1, D[i])-W;
            if(tmp == n+1)
                break;
            tp = tmp+1;
            ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}
时间: 2024-10-05 16:24:07

51NOD 1279 扔盘子(二分 + 思维)的相关文章

51nod 1279 扔盘子

题目链接在这儿 如果上面一层窄,下面再宽也没用. 那么可以根据输入获得一个单调的栈,这个栈是经过选择的.比如输入例子的5 6 4 3 6 2 3,将变成5 5 3 3 3 2 2 .最后一层为栈顶,接着来一个盘子判断栈顶(亦即坑底部)能否容纳,不可则出栈再判断,可则认为放置这个盘子入这层,这层消失.统计一下放置了多少次即可. #include <bits/stdc++.h> using namespace std; const int maxN = 1e5 + 5; int N, M, S;

1279 扔盘子(51nod)

题目链接 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1279 这道题要求的就是当顶被封之前有多少盘被扔下去= =当顶被封住时 即使下面的盘子再小也不能扔下去 我们用a[]保存井的宽度,数组b[]来保存盘子的大小 首先盘子j要是能到达第i米,则需要满足min(a[0~i])>=b[j]; 所以我们只需保存最小值便可 1 #include<stdio.h> 2 #include<string.h>

1279 扔盘子

思路:先将井口处理成递增的序列,然后再二分每个盘子插入的位置. 1 #include <iostream> 2 #include <queue> 3 #include <stack> 4 #include <cstdio> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <bitset> 9 #include <algori

51 nod 1279 扔盘子

有一口井,井的高度为N,每隔1个单位它的宽度有变化.现在从井口往下面扔圆盘,如果圆盘的宽度大于井在某个高度的宽度,则圆盘被卡住(恰好等于的话会下去). 盘子有几种命运:1.掉到井底.2.被卡住.3.落到别的盘子上方. 盘子的高度也是单位高度.给定井的宽度和每个盘子的宽度,求最终落到井内的盘子数量. 如图井和盘子信息如下: 井:5 6 4 3 6 2 3 盘子:2 3 5 2 4 最终有4个盘子落在井内. Input 第1行:2个数N, M中间用空格分隔,N为井的深度,M为盘子的数量(1 <= N

51nod 1279 单调栈

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1279 1279 扔盘子 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 有一口井,井的高度为N,每隔1个单位它的宽度有变化.现在从井口往下面扔圆盘,如果圆盘的宽度大于井在某个高度的宽度,则圆盘被卡住(恰好等于的话会下去). 盘子有几种命运:1.掉到井底.2.被卡住.3.落到别的盘子上方. 盘子

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

POJ 3579 Median 二分+思维

POJ 3579 Median 二分+思维 题意 给你一些数,然后求这些数相互之间差的绝对值,然后绝对值排序,找到中间那个数. 解题思路 我反正一直开始是没有想到这个题竟然可以用二分来做.━━( ̄ー ̄*|||━━. 二分枚举答案,假设枚举值为mid,然后就是在排好序的序列中对每一个num[i]找到在i之后,有多少个大于num[i]+mid的数的个数(数列里的值比num[i]+mid大,说明该值与num[i]作差形成的新数列里的数比中位数mid大),用lower_bound计算所有差值比mid大于

51nod 扔盘子

题目传送门 这道题一开始写了n方的算法 果不其然 它T了 所以就想想o(n)的算法 写不出来 就像sbzhq学习了一下 这道题啊 要维护一下从深度1到n每一段的最小值以及他的位置 然后就暴力搞一搞就okay 啦!!! #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int inf=1e9+7; int read(){ int ans=0,f=1,c=get

51nod 1105---二分套二分

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1105 题意a序列和b序列,ab序列是 a和b两两组合,问你ab中第k大是多少.. 这题是个二分套二分,是个二分好题..为什么好呢,因为这个二分容易写残疾啊...(总之就是我太弱了 接下来分析一下这个题的解法和要注意的地方. 一个显然的方法就是二分答案了,然后判断mid是第几大就可以了.. 但是,仔细一想?咦..会不会二分的答案其实不是ab数组里面的呢?会不会ab里面有很