poj2796 feel good 单调栈

题目链接: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 }
poj2796

 

posted @ 2020-05-29 20:11  coastal_taipan  阅读(148)  评论(0编辑  收藏  举报