1 /* 2 题意:POJ2796 给定一个长度为n的数组,求sum(a[i])*min(a[i)最大的一段区间。 3 思路:枚举每个a[i],求最左边和最右边的距离。利用单调栈求左右区间 4 时间:2018.07.17 5 */ 6 // #include <bits/stdc++.h> 7 #include <cstdio> 8 #include <iostream> 9 using namespace std; 10 11 typedef long long LL; 12 const int MAXN=100005; 13 const LL MOD7 = 1e9+7; 14 15 int a[MAXN]; 16 int n; 17 LL sum[MAXN]; 18 int L[MAXN]; 19 int R[MAXN]; 20 int Stack[MAXN]; 21 int top; 22 23 void printStack() 24 { 25 for (int i=0;i<top;++i) printf("%d ",Stack[i]);printf("\n"); 26 } 27 28 void init() 29 { 30 top=0; 31 for (int i=1;i<=n;++i) 32 { 33 while (top && a[Stack[top-1]]>=a[i]) --top; 34 // printf("%d: ",i); 35 // printStack(); 36 if (!top) L[i]=1; 37 else L[i]=Stack[top-1]+1; 38 Stack[top++]=i; 39 } 40 top=0; 41 for (int i=n;i>=1;--i) 42 { 43 while (top && a[Stack[top-1]]>a[i]) --top; 44 if (!top) R[i]=n; 45 else R[i] = Stack[top-1]-1; 46 Stack[top++]=i; 47 } 48 // for (int i=1;i<=n;++i) printf("L[%d]=%d\tR[%d]=%d\n",i,L[i],i,R[i]); 49 } 50 51 int main() 52 { 53 #ifndef ONLINE_JUDGE 54 freopen("test.txt","r",stdin); 55 #endif // ONLINE_JUDGE 56 scanf("%d",&n); 57 for (int i=1;i<=n;++i) 58 { 59 scanf("%d",&a[i]); 60 sum[i]=sum[i-1]+a[i]; 61 } 62 init(); 63 LL ans=-1; 64 int l,r; 65 for (int i=1;i<=n;++i) 66 { 67 LL tmp = (LL)a[i]*(sum[R[i]]-sum[L[i]-1]); 68 if (tmp>ans) 69 { 70 ans = tmp; 71 l=L[i]; 72 r=R[i]; 73 } 74 } 75 printf("%lld\n",ans); 76 printf("%d %d\n",l,r); 77 return 0; 78 }
原文:https://www.cnblogs.com/LeeSongt/p/9326323.html