题目链接:https://vjudge.net/problem/POJ-2796
题意:求一个区间内的最小值乘以这个区间元素和的最大值
和poj2082的思路基本一样,对于区间内每个元素,都可以作为最小值。那么尽量往左右延伸到第一个比它小的数,记录下延伸之前的一个位置l[i]和r[i]。由此感觉单调栈本质的作用就是找出左边(右边)比当前数小(大)的第一个数,且复杂度为O(n)。这题坑点真多,一个是多组数据(又一次),一个是开ll,一开始前缀和数组忘了开ll光荣wa。还有一个是答案可能为0,所以最初令ans=-1
1 #include<iostream> 2 #include<algorithm> 3 #include<stack> 4 #define ll long long 5 using namespace std; 6 7 const int maxn=1000+10; 8 stack<int> st; 9 ll s[maxn]; 10 int a[maxn],l[maxn],r[maxn]; 11 int n,i,j; 12 13 void solve(){ 14 for (i=1;i<=n;i++){ 15 scanf("%d",&a[i]);s[i]=s[i-1]+a[i]; 16 } 17 a[0]=a[n+1]=-1; 18 st.push(1); 19 for (i=2;i<=n+1;i++){ 20 while (!st.empty()&&a[st.top()]>a[i]){ 21 r[st.top()]=i-1;st.pop(); 22 } 23 st.push(i); 24 } 25 while (!st.empty()) st.pop();st.push(n); 26 for (i=n-1;i>=0;i--){ 27 while (!st.empty()&&a[st.top()]>a[i]){ 28 l[st.top()]=i+1;st.pop(); 29 } 30 st.push(i); 31 } 32 ll ans=-1; 33 int ansl,ansr; 34 for (i=1;i<=n;i++){ 35 ll res=(s[r[i]]-s[l[i]-1])*a[i]; 36 if (res>ans){ 37 ans=res; 38 ansl=l[i];ansr=r[i]; 39 } 40 } 41 cout<<ans<<endl; 42 cout<<ansl<<' '<<ansr<<endl; 43 } 44 45 int main(){ 46 while (~scanf("%d",&n)){ 47 while (!st.empty()) st.pop(); 48 solve(); 49 } 50 return 0; 51 }