POJ 2796 Feel Good(单调栈)
题目链接:Feel Good
题意:给定长度为n的数字序列ai,定义某值为区间[l,r]内ai之和乘上区间[l,r]内最小的ai。求最大的该值。
题解:单调栈维护每个ai前面和后面第一个比它小的位置,对应题目中要求的值就为该区间之和乘上ai,从头往后遍历一遍。
数组:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 typedef long long ll; 8 const int N=2e5+10; 9 ll a[N],sum[N]; 10 int l[N],r[N],st[N]; 11 12 int main(){ 13 int n; 14 scanf("%d",&n); 15 for(int i=1;i<=n;i++){ 16 scanf("%lld",&a[i]); 17 sum[i]=sum[i-1]+a[i]; 18 } 19 int top=0; 20 for(int i=1;i<=n;i++){ 21 while(top>0&&a[i]<=a[st[top]]) top--; 22 l[i]=top==0?1:st[top]+1; 23 st[++top]=i; 24 } 25 top=0; 26 for(int i=n;i>=1;i--){ 27 while(top>0&&a[i]<=a[st[top]]) top--; 28 r[i]=top==0?n:st[top]-1; 29 st[++top]=i; 30 } 31 ll ans=-1; 32 int id=0; 33 for(int i=1;i<=n;i++){ 34 ll res=(sum[r[i]]-sum[l[i]-1])*a[i]; 35 if(res>ans) ans=res,id=i; 36 } 37 printf("%lld\n",ans); 38 printf("%d %d\n",l[id],r[id]); 39 return 0; 40 }
stack:
1 #include <stack> 2 #include <cstdio> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 typedef long long ll; 8 const int N=1e5+10; 9 10 stack <int> st; 11 int l[N],r[N],id; 12 ll a[N],sum[N],ans=-1; 13 14 int main(){ 15 int n; 16 scanf("%d",&n); 17 for(int i=1;i<=n;i++){ 18 scanf("%lld",&a[i]); 19 sum[i]=sum[i-1]+a[i]; 20 } 21 for(int i=1;i<=n;i++){ 22 while(st.size()&&a[st.top()]>=a[i]) st.pop(); 23 l[i]=(st.size()==0)?1:st.top()+1; 24 st.push(i); 25 } 26 while(st.size()) st.pop(); 27 for(int i=n;i>=1;i--){ 28 while(st.size()&&a[st.top()]>=a[i]) st.pop(); 29 r[i]=(st.size()==0)?n:st.top()-1; 30 st.push(i); 31 } 32 for(int i=1;i<=n;i++){ 33 ll res=(sum[r[i]]-sum[l[i]-1])*a[i]; 34 if(res>ans) ans=res,id=i; 35 } 36 printf("%lld\n",ans); 37 printf("%d %d\n",l[id],r[id]); 38 return 0; 39 }