codeforces #305 547B B. Mike and Feet(单调栈)

来源:互联网 发布:域名dns未修改腾讯云 编辑:程序博客网 时间:2024/04/28 15:58

题目链接:

点击打开链接

题目大意:

给出一个序列,一个区间的值取这个区间中最小的数的值,那么不同长度区间的最大区间的值

题目分析:

首先我们可以考虑这么一条性质,也就是如果存在一个点作为当前区间的值,那么它向左向右能扩展的最大距离,就是它能支配的最大区间,而长度小于这个区间的区间它也能支配,那么它延展的距离内满足所有的值不大于它,这正好满足单调栈的性质。利用单调栈扫两边,栈内保持单调递增,然后每次找到比当前点小的最近的点,取做延展的最远距离,然后反向扫一遍,最后利用每个单点的值修改对应最大区间长度的最大值,长度小的区间最大值一定不小于长度大的区间,所以ans[i-1] = max ( ans[i] , ans[i-1] )递推以下,就是最终答案了,算是单调栈的模板题了

代码如下:

用了stl,1A,继续呐喊stl大法好

#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <stack>#define PII pair<int,int>#define x first#define id second#define MAX 200007using namespace std;int n;int a[MAX];int ans[MAX];int l[MAX],r[MAX];stack<PII> s;int main ( ){    while ( ~scanf ( "%d" , &n ) )    {        memset ( ans , 0 , sizeof ( ans ) );        for ( int i = 0 ; i < n ; i++ )            scanf ( "%d" , &a[i] );        //s.clear();        while ( !s.empty() ) s.pop();        l[0] = 0;        s.push( make_pair ( a[0] , 0 ) );        for ( int i = 1 ; i < n ; i++ )        {            while ( !s.empty() && s.top().x >= a[i] )                s.pop();            //cout << "YES : " << i  << endl;            if ( !s.empty() ) l[i] = s.top().id + 1;            else l[i] = 0;            s.push ( make_pair ( a[i] , i ) );        }        //cout << "YES" << endl;        //s.clear();        while ( !s.empty() ) s.pop();        r[n-1] = n-1;        s.push ( make_pair ( a[n-1] , n-1 ) );        for ( int i = n-2 ; i >= 0 ; i-- )        {            while ( !s.empty() && s.top().x >= a[i] )                s.pop();            if ( !s.empty() ) r[i] = s.top().id - 1;            else r[i] = n-1;            s.push ( make_pair ( a[i] , i ) );        }        for ( int i = 0 ; i < n ; i++ )            ans[r[i]-l[i]+1] = max ( a[i] , ans [r[i]-l[i]+1] );        for ( int i = n-1 ; i >= 1 ; i-- )            ans[i] = max ( ans[i] , ans[i+1] );        for ( int i = 1; i <= n ; i++ )            printf ( "%d " , ans[i] );        puts("");    }}


0 0