YunYan

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

两种思路:

1 单调栈:维护一个单调非递减栈,当栈为空或者当前元素大于等于栈顶元素时就入栈,当前元素小于栈顶元素时就出栈,出栈的同时计算当前值,当前值所包含的区间范围为从当前栈顶元素到当前元素i的距离加上栈顶元素到第二个栈顶元素的距离。

code:

  

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1E5+7;
ll arr[N];
int main(){
    ll n;
    while(cin>>n,n){
        ll ans=0;
        stack<ll >st;
        for(ll i=1;i<=n;i++) cin>>arr[i];
        arr[n+1]=0;
        for(ll i=1;i<=n+1;i++){
            if(st.empty()||arr[st.top()]<=arr[i]) st.push(i);
            else {
                ll c=st.top();
                while(st.size()&&arr[c]>arr[i]){
                    st.pop();
                    if(st.empty()) ans=max(ans,arr[c]*(i-1));
                    else {
                        ans=max(ans,(i-st.top()-1)*arr[c]);
                        c=st.top();
                    }
                }
                st.push(i);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

2 dp

  维护两个数组left和right,left[i]表示元素i向大于当前元素向左的最大连续延伸。right[i]同理。

     转移方式:j=left[j]-1,j=right[j]+1。然后遍历每个元素ans=max(ans,(right[i]-left[i]+1)*arr[i]) 

  code:

  

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1E5+7;
ll arr[N];
ll left1[N];
ll right1[N];
int  main(){
    ll n;
    while(scanf("%lld",&n)!=EOF&&n){
        for(ll i=1;i<=n;i++){
            scanf("%lld",&arr[i]);
            left1[i]=right1[i]=i;
        }
        for(ll i=1;i<=n;i++){
            ll j=i;
            while(j>=1&&arr[i]<=arr[j]) j=left1[j]-1;
            left1[i]=j+1;
        }
        for (ll i=n-1; i>=1; i--) {
            ll j=i;
            while (j<=n && arr[i]<=arr[j])  j=right1[j]+1;
            right1[i]=j-1;
        }
        ll ans=0;
        for(ll i=1;i<=n;i++){
            ans=max(ans,(right1[i]-left1[i]+1)*arr[i]);
        }printf("%lld\n",ans);
    }
    return 0;
}

 

         

posted on 2020-03-22 16:08  Target--fly  阅读(139)  评论(0编辑  收藏  举报