单调栈
描述:求一个数组的某一个数,向左右两边延申的最大区间,比如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; }