CodeForces 548D Mike and Feet (单调栈)

http://codeforces.com/contest/548/problem/D

Mike and Feet

Mike is the president of country What-The-Fatherland. There are n bears living in this country besides Mike. All of them are standing in a line and they are numbered from 1 to n from left to right. i-th bear is exactly ai feet high.

CodeForces 548D Mike and Feet (单调栈)_第1张图片

A group of bears is a non-empty contiguous segment of the line. The size of a group is the number of bears in that group. The strengthof a group is the minimum height of the bear in that group.

Mike is a curious to know for each x such that 1 ≤ x ≤ n the maximum strength among all groups of size x.

Input

The first line of input contains integer n (1 ≤ n ≤ 2 × 105), the number of bears.

The second line contains n integers separated by space, a1, a2, ..., an (1 ≤ ai ≤ 109), heights of bears.

Output

Print n integers in one line. For each x from 1 to n, print the maximum strength among all groups of size x.

Sample test(s)
input
10
1 2 3 4 5 4 3 2 1 6
output
6 4 4 3 3 2 2 1 1 1 

单调栈与单调队列很相似。首先栈是后进先出的,单调性指的是严格的递增或者递减。

单调栈有以下两个性质:

1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。

2、越靠近栈顶的元素越后进栈。

单调栈与单调队列不同的地方在于栈只能在栈顶操作,因此一般在应用单调栈的地方不限定它的大小,否则会造成元素无法进栈。

元素进栈过程:对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。对于单调递减栈,则每次弹出的是大于e或者等于e的元素。

一个单调递增栈的例子:

进栈元素分别为3,4,2,6,4,5,2,3

3进栈:(3)

3出栈,4进栈:(4)

2进栈:(4,2)

2出栈,4出栈,6进栈:(6)

4进栈:(6,4)

4出栈,5进栈:(6,5)

2进栈:(6,5,2)

2出栈,3进栈:(6,5,3)

以上左端为栈底,右端为栈顶。

题意:
给出n个数,这n个数在区间长度为i(1~n)的时候可以分割成一些区间,这每个区间都会有一个最小值,在同样长度的这些区间的最小值中,输出最大值
 
 
思路:
使用单调栈,保持栈内的数的单调递增性
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <queue>
#include <stack>
#include <vector>
#include <map>

using namespace std;
typedef long long LL;

#define N 351100
#define INF 0x3f3f3f3f
#define PI acos (-1.0)
#define EPS 1e-8
#define met(a, b) memset (a, b, sizeof (a))

struct node
{
    int L, num;
}S;

stack <node> sta;
int a[N], ans[N];

int main ()
{
    int n;

    while (scanf ("%d", &n) != EOF)
    {
        met (a, 0);
        met (ans, 0);

        for (int i=0; i<n; i++)
            scanf ("%d", &a[i]);

        for (int i=0; i<=n; i++)
        {
            int len = 0;//连续区间的长度  

            while (!sta.empty ())
            {
                S = sta.top ();

                if (S.num < a[i]) break;//新入栈的元素比栈顶元素要小,那么对于这个连续区间而言,
                //这个比新入栈的元素就没有用了,可以出栈  

                int lr = S.L + len;//出栈的同时获得其长度  

                ans[lr] = max (ans[lr], S.num);//ans记录lr区间的时候的最大值

                len += S.L;
                sta.pop ();
            }
            sta.push((node){len+1, a[i]});
        }

        for (int i=n; i>=1; i--)
            ans[i] = max (ans[i], ans[i+1]);//因为上面只更新了一部分的点,所以现在要对那些没有更新的点也更新  

        for (int i=1; i<n; i++)
            printf ("%d ", ans[i]);
        printf ("%d\n", ans[n]);
    }
    return 0;
}


你可能感兴趣的:(CodeForces 548D Mike and Feet (单调栈))