Minimum Sum(单调栈) AtCoder Grand Contest 005

Posted zjj0624

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Minimum Sum(单调栈) AtCoder Grand Contest 005相关的知识,希望对你有一定的参考价值。

题意
给你一个由1~n的序列, a 1 , a 2 , a 3 . . . . . a n a_1,a_2,a_3.....a_n a1,a2,a3.....an,每个数字都只出现一次,没有重复,让你求由这个序列所有子序列的最小值的和.

思路
我们求出每一个点影响的最大的左右区间,然后用一点点组合数的知识来写.
求出每个点的左右区间用单调栈来实现.
注意要开LL.
代码

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define fi first
#define se second
#define pb push_back
#define me memset
const int N=2e5+10;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll a[N],le[N],ri[N];
int main()
{
    int n;
    cin>>n;
    for(int i=1 ; i<=n ; i++) cin>>a[i];
    stack<int>s;
    for(int i=1 ; i<=n ; i++)
    {
        while(!s.empty()&&a[s.top()]>a[i])
        {
            ri[s.top()]=i;
            s.pop();
        }
        s.push(i);
    }
    while(!s.empty())
    {
        ri[s.top()]=n+1;
        s.pop();
    }
    for(int i=n ; i>=1 ; i--)
    {
        while(!s.empty()&&a[s.top()]>a[i])
        {
            le[s.top()]=i;
            s.pop();
        }
        s.push(i);
    }
    while(!s.empty())
    {
        le[s.top()]=0;
        s.pop();
    }
    ll ans=0;
    for(int i=1 ; i<=n ; i++)
    {
        //cout<<i<<" "<<le[i]<<" "<<ri[i]<<endl;
        ans+=a[i]*(ri[i]-le[i]-1+(ri[i]-i-1)*(i-le[i]-1));
    }
    cout<<ans<<endl;
    return 0;
}

以上是关于Minimum Sum(单调栈) AtCoder Grand Contest 005的主要内容,如果未能解决你的问题,请参考以下文章

单调栈Minimum Sum

[Agc005D/At2060] Minimum Sum - 单调栈

TOJ 4244 Sum(单调栈区间极差)

BZOJ4262Sum 单调栈+线段树

洛谷P3503 [POI2010]KLO-Blocks 单调栈

bzoj 1660: [Usaco2006 Nov]Bad Hair Day 乱发节单调栈