题目链接:
题目大意:
给出一个序列,一个区间的值取这个区间中最小的数的值,那么不同长度区间的最大区间的值
题目分析:
首先我们可以考虑这么一条性质,也就是如果存在一个点作为当前区间的值,那么它向左向右能扩展的最大距离,就是它能支配的最大区间,而长度小于这个区间的区间它也能支配,那么它延展的距离内满足所有的值不大于它,这正好满足单调栈的性质。利用单调栈扫两边,栈内保持单调递增,然后每次找到比当前点小的最近的点,取做延展的最远距离,然后反向扫一遍,最后利用每个单点的值修改对应最大区间长度的最大值,长度小的区间最大值一定不小于长度大的区间,所以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 200007
using 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("");
}
}