单调栈

描述:求一个数组的某一个数,向左右两边延申的最大区间,比如1276453.对于4可以向左延申到7,向右延申到5,也就是4在这个区间内是最小值。

适用:对于一个数组,如果对于全部区间去求解,需要n*(n-1)/2个区间,所以问题的复杂度至少是N的平方,如果换一个角度,所有的区间都是以某一个数字作为最小值的,所以只要求出一个数代表一个区间,就可以转换为O(n)的复杂度。

#include<stdio.h>
#include<math.h>
#include<iostream>
#include<stack>
using namespace std;
const int maxn=100010;
long long a[100010];
int l[100010],r[100010],n,ansl,ansr,top;

long long  sum[100010]={0},ans=-1;

int main(){
int i,j;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
l[i]=r[i]=i;
} 
a[0]=a[n+1]=-1;

stack<int>s;   
for(i=1;i<=n+1;i++){
while(!s.empty()&&a[i]<=a[s.top()]  ){//a[i]<栈顶,出栈 
 r[s.top()] =i-1;//找出栈顶元素的下标右端点 
 s.pop();
}  
if(!s.empty())l[i]=s.top()+1;  
else l[i]=1;
   s.push(i);

} 

long long tmp;
for(i=1;i<=n;i++){

tmp=(sum[r[i]]-sum[l[i]-1])*a[i];
if(tmp>=ans){
ans=tmp;
ansl=l[i];
ansr=r[i];
} 
}
printf("%lld\n", ans);
  printf("%d %d\n", ansl, ansr);
return 0;
}

 

posted on 2018-08-19 15:00  mdumpling  阅读(144)  评论(0编辑  收藏  举报

导航