zoukankan      html  css  js  c++  java
  • 600.奶牛的仰望

    AcWing题目传送门
    洛谷题目传送门

    一、题目描述

    约翰有(N)头奶牛,编号为(1)(N)

    现在这(N)头奶牛按编号从小到大的顺序站成了一排,其中奶牛 (i) 的身高为(H_i)

    现在,每头奶牛都向它的右侧望向那些编号较大的奶牛,对于奶牛 (i) 如果存在一头奶牛 (j) 满足 (i<j) 并且 (H_i<H_j),那么我们称奶牛 (i) 需要仰视奶牛 (j)

    请你求出每头奶牛的最近仰视对象。

    输入格式
    第一行包含整数(N)

    接下来(N)行,每行包含一个整数(H_i),其中第 (i) 行的数为编号为 (i) 的奶牛的高度。

    输出格式
    (N) 行,每行输出一个整数,其中第 (i) 行的输出整数表示编号为 (i) 的奶牛的最近仰视对象的编号,如果不存在仰视对象,则输出(0)

    数据范围
    (1≤N≤10^5)
    (1≤H_i≤10^6)

    输入样例:

    6 
    3  2  6  1  1  2 
    

    输出样例

    3 3 0 6 6 0 
    

    二、解题思路

    结论:找出离自己最近比自己大(或小)的,用单调栈。

    最朴素的办法就是暴力,遍历每一个奶牛,然后向它右边遍历所有其它奶牛,找出离自己最近并且高于自己的奶牛。

    这么做性能并不是很高,比如 ([1,2,2,2,2,2,2,3,3,3,3,3,3]),这样的测试数据,第一个(2)的那个,需要向右找(6)个数字才能找到比自己大的;而第二个(2),则需要向右找(5)个数字才能找到比自己大的。

    想要性能好,该怎么办呢?我们需要知道为什么朴素作法慢,它到底哪里可提速呢?

    很明显,上面的办法中有大量的重复运算,比如明明知道第(2)个位置和第(3)个位置一样,结果,还是傻傻的每次去重新开始找,能不慢吗?

    单调栈的思路是这样的:
    1)设计一个栈,让每个奶牛都带着“我需仰望哪位?”的问题进入栈,一旦有牛能回答这个问题,它就出栈。

    2)每个奶牛进栈之前,都与与它最近的已入栈奶牛对比身高,如果它比离它近的高,那么它就是栈顶奶牛的答案:“你需仰望大爷我!”,栈顶的知道答案后,就退出了栈。

    3)反复执行上面的过程,把栈顶的奶牛都处理掉,直到栈为空或者栈顶奶牛的高度大于要入栈的奶牛,再把当前的奶牛入栈,因为它自己也想知道答案。

    其实单调栈就是解决了两个问题“比你高”,“离你近”。

    比你高是靠与栈顶元素对比来的,离你近是因为栈本身的性质。

    三、数组模拟栈法

    #include <bits/stdc++.h>
    
    //奶牛的仰望
    //https://www.cnblogs.com/littlehb/p/15247842.html
    using namespace std;
    const int N = 101000;
    
    int n;    //多少只奶牛
    int a[N]; //每只奶牛的身高
    int s[N]; //谁仰望谁
    
    //用数组模拟栈,每一个栈内的元素,都是需要找到“比自己高度大的,离自己最近”的奶牛。
    int stk[N]; //内容:序号
    int tt;     //指针,默认是0
    
    
    int main() {
        //优化不可少
        ios::sync_with_stdio(false);
        //读入
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        //奶牛一个个进来,判断新进来的是不是已有奶牛仰望的对象
        for (int i = 1; i <= n; i++) {
            //栈内有奶牛,且身高大于栈顶的奶牛
            while (tt && a[i] > a[stk[tt]]) {
                s[stk[tt]] = i;//仰视对象
                tt--;//出栈
            }
            stk[++tt] = i;//加入栈中,等待找到需它仰视的奶牛。
        }
        for (int i = 1; i <= n; i++) cout << s[i] << endl;//输出即可
        return 0;
    }
    

    四、STL栈法

    #include <bits/stdc++.h>
    
    //奶牛的仰望
    //https://www.cnblogs.com/littlehb/p/15247842.html
    using namespace std;
    const int N = 101000;
    
    int n;    //多少只奶牛
    int a[N]; //每只奶牛的身高
    int s[N]; //谁仰望谁
    stack<int> stk;
    
    int main() {
        //优化不可少
        ios::sync_with_stdio(false);
        //读入
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        //奶牛一个个进来,判断新进来的是不是已有奶牛仰望的对象
        for (int i = 1; i <= n; i++) {
            //栈内有奶牛,且身高大于栈顶的奶牛
            while (stk.size() && a[i] > a[stk.top()]) {
                s[stk.top()] = i;//仰视对象
                stk.pop();//找到了仰望对象,就不再需要继续找了
            }
            stk.push(i);//加入栈中,等待找到需它仰视的奶牛。
        }
        for (int i = 1; i <= n; i++) cout << s[i] << endl;//输出即可
        return 0;
    }
    
  • 相关阅读:
    78. Subsets
    93. Restore IP Addresses
    71. Simplify Path
    82. Remove Duplicates from Sorted List II
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    312. Burst Balloons
    程序员社交平台
    APP Store开发指南
    iOS框架搭建(MVC,自定义TabBar)--微博搭建为例
  • 原文地址:https://www.cnblogs.com/littlehb/p/15247842.html
Copyright © 2011-2022 走看看