zoukankan      html  css  js  c++  java
  • 扔盘子(思维)

    有一口井,井的高度为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输出最终落到井内的盘子数量。Sample Input

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

    Sample Output

    4

    刚开始想的是用两个队列来维护,但是.......后来用两个数组来存放盘子和井的宽度由于用到了两重循环结果TLE了

    #include<bits/stdc++.h>
    #define maxn 50010
    using namespace std;
    
    int main()
    {
    	int n,m;
    	int i,j;
    	int flag;
    	int logo;
    	int a[maxn],b[maxn]; 
    	scanf("%d%d",&n,&m);
    	a[0] = 0;
    	for(i=1; i<=n; i++)
    	{
    		scanf("%d",&a[i]);
    	}
    	for(i=0; i<m; i++)
    	{
    		scanf("%d",&b[i]);
    	}
    	flag = n; 	
    	for(j=0; j<m; j++)
    	{
    		logo = 1;
    		for(i=0; i<flag; i++)
    		{
    			if(b[j] > a[i])
    			{
    				flag = i;
    				logo = 0;
    			}
    		}
    		if(logo == 1)
    			flag--;
    		if(flag == 0)
    		{
    			printf("%d
    ",j);
    			break;
    		}
    	}
    	
    	return 0;
    }
    

      

    然后看了大神的博客发现时间复杂度可以简化到O(n),具体的方法就是让井的下层宽度小于或者等于上层宽度,然后从上往下以此比较

    #include<bits/stdc++.h>
    #include<string.h> 
    #define maxn 50010
    using namespace std;
    
    int main()
    {
    	int n,m;
    	int i,j;
    	int flag;
    	int a[maxn],b[maxn]; 
    	scanf("%d%d",&n,&m);
    	for(i=1; i<=n; i++)
    	{
    		scanf("%d",&a[i]);
    		if(i >= 2)
    			a[i] = min(a[i],a[i-1]);
    	}
    	flag = 0;
    	for(j=0; j<m; j++)
    	{
    		scanf("%d",&b[j]);
    		while(a[n] < b[j])
    			n--;
    		if(n > 0)
    		{
    			flag++;
    			n--;			
    		}
    	}
    	printf("%d
    ",flag);
    	return 0;
    }
    

      

    用栈的方法来解

    #include<stdio.h>
    #include<string.h>
    #include<stack>
    const int M = 50005;
    
    using namespace std;
    
    int main()
    {
        int n, m;
        int i, j, k;
        int well[M], plate[M], a[M];
        int ans = 0;
    
        stack<int> s;
    
        scanf("%d %d", &n, &m);
    
        for( i = 0; i < n; i++ )
        {
            scanf("%d", &well[i]);
        }
    
        for( i = 0; i < m; i++ )
        {
            scanf("%d", &plate[i]);
        }
    
        s.push(well[0]);
    
        for( i = 1; i < n; i++ )
        {
            if(well[i] > well[i-1])
            {
                well[i] = well[i-1];
            }
    
            s.push(well[i]);
        }
    
        for( i = 0; i < m; i++ )
        {
            while(!s.empty())
            {
                if(s.top() >= plate[i])
                {
                    ans++;
                    s.pop();
                    break;
                }
    
                else
                    s.pop();
            }
        }
    
        printf("%d", ans);
    
        return 0;
    
    }
    View Code

    温故而知新

      

    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    42 最大子数组Ⅱ
    笔试之const问题
    笔试中sizeof求字节数的问题
    40 用栈实现队列
    38 搜索二维矩阵Ⅱ
    25.Remove Nth Node From End of List(删除链表的倒数第n个节点)
    29.最小的K个数
    28.数组中出现次数超过一半的数字
    27.字符串的排列
    26.二叉搜索树与双向链表
  • 原文地址:https://www.cnblogs.com/h-hkai/p/7617015.html
Copyright © 2011-2022 走看看