zoukankan      html  css  js  c++  java
  • 单调栈

    单调栈的定义:

    元素顺序始终保持单调性(递增、递减)的栈。
    (递增单调栈和递减单调栈的区别仅限于单调顺序不同,故以下为了方便讲解,默认提到的单调栈都为严格递增单调栈。)

    维护方法:

    压入新元素 (x) 时,将 (x) 与栈顶元素比较,若 (x) 小于等于栈顶元素,则将栈顶元素弹出,再与新的栈顶元素比较,直到 (x) 大于栈顶元素。


    举例:

    有一组数7,8,9,2,10,13,将这6个数从左往右压入严格递增单调栈:
    1、压入7,此时栈为空,无栈顶元素,操作完成后栈内元素为:{7};
    2、压入8,此时栈顶元素为7,7<8,故可以直接压入,操作完成后栈内元素为:{7、8};
    3、压入9,此时栈顶元素为8,8<9,故可以直接压入,操作完成后栈内元素为:{7、8、9};
    4、压入2,此时栈顶元素为9,9>2,故需要弹出栈顶元素9;同理,弹出8、7。此时栈为空,可以压入2,操作完成后栈内元素为:{2};
    5、压入10,此时栈顶元素为2,2<10,故可以直接压入,操作完成后栈内元素为:{2、10};
    6、压入13,此时栈顶元素为10,10<13,故可以直接压入,操作完成后栈内元素为:{2、10、13};
    7、清空栈内元素;

    使用单调栈时,一般是在弹出元素的过程中进行统计操作(即x小于等于栈顶元素的情况);


    例题:

    Largest Rectangle in a Histogram

    题目大意:给定 (n) 个高为 (a_1、a_2、...、a_n) 的柱子,求该柱状图中,可勾勒出的最大的矩形面积。

    思路:选择某个柱子 (i) ,将 (i) 向两边拓展,若碰到比 (a_i) 高的柱子就接着拓展,若碰到比 (a_i) 小的柱子就停止拓展。
    直接暴力做的时间复杂度是 (O(n^2)) ,但可以使用单调栈优化。
    考虑向一个递增单调栈中按 (i) 从小到大的顺序压入 (i) ,设栈顶元素为 (top) ,若 (a_i < a_top) ,则在弹出 (top) 的同时,将答案 (ans)(top) 向左右拓展可得的最大面积取 (Max),并更新第 (i) 根柱子向左端能拓展到的最远处。
    (i) 根柱子向最左端拓展的最远处可以在压入 (i) 之前弹出 (top) 的过程中更新,而最右端则应在弹出 (i) 的时候被更新。

    代码:

    #include <assert.h>
    #include <ctype.h>
    #include <errno.h>
    #include <float.h>
    #include <fstream>
    #include <iomanip>
    #include <iostream>
    #include <limits.h>
    #include <locale.h>
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <wchar.h>
    #include <wctype.h>
    #include <algorithm>
    #include <bitset>
    #include <cctype>
    #include <cerrno>
    #include <clocale>
    #include <cmath>
    #include <complex>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <deque>
    #include <exception>
    #include <fstream>
    #include <functional>
    #include <limits>
    #include <list>
    #include <map>
    #include <iomanip>
    #include <ios>
    #include <iosfwd>
    #include <iostream>
    #include <istream>
    #include <ostream>
    #include <queue>
    #include <set>
    #include <sstream>
    #include <stack>
    #include <stdexcept>
    #include <streambuf>
    #include <string>
    #include <utility>
    #include <vector>
    #include <cwchar>
    #include <cwctype>
    #define int long long
    using namespace std;
    const int N = 8e4 + 5;
    int n, ans, cnt, a[N], stck[N];
    signed main () {
    	scanf ("%lld", &n);
    	for (int i = 1; i <= n; i ++)
    		scanf ("%lld", &a[i]);
    	for (int i = 1; i <= n; i ++) {
    		while (cnt && a[stck[cnt]] <= a[i]) {
    			ans += i - stck[cnt] - 1;
    			cnt --;
    		}
    		stck[++ cnt] = i;
    	}
    	for (int i = 1; i <= cnt; i ++)
    		ans += n - stck[i];
    	printf ("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    107. Binary Tree Level Order Traversal II
    108. Convert Sorted Array to Binary Search Tree
    111. Minimum Depth of Binary Tree
    49. Group Anagrams
    使用MALTAB标定实践记录
    442. Find All Duplicates in an Array
    522. Longest Uncommon Subsequence II
    354. Russian Doll Envelopes
    opencv 小任务3 灰度直方图
    opencv 小任务2 灰度
  • 原文地址:https://www.cnblogs.com/HarryHuang2004/p/13197446.html
Copyright © 2011-2022 走看看