单调栈Minimum Sum

Posted biu~跃哥冲冲冲

tags:

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

Minimum Sum

题目描述

One day, Snuke was given a permutation of length N , a 1 , a 2 , … , a N N, a_1,a_2,…,a_N N,a1,a2,,aN, from his friend.
Find the following:

Constraints
1 ≤ N ≤ 200 , 000 1≤N≤200,000 1N200,000
( a 1 , a 2 , … , a N a_1,a_2,…,a_N a1,a2,,aN) is a permutation of (1,2,…,N).

输入

The input is given from Standard Input in the following format:
N N N
a 1   a 2   …   a N a_1\\ a_2\\ …\\ a_N a1 a2  aN

输出

Print the answer.
Note that the answer may not fit into a 32-bit integer.

样例输入:

3
2 1 3

样例输出:

9

题目大意:其实就是计算给的那个式子,哈哈哈,为了方便起见,我拿题目所给样例模拟一下;

清晰的记得这道题当时用线段树给超时了,结果赛后搜博客加上和同学讨论许久我也还是不懂qwq,看到标记是单调栈,没整过呀,怎么搞,搜博客搜题解,看完后依然一脸懵逼,然后,就把他放那不管了,今天一个机遇又看了看单调栈,也不是太难理解,随后就又翻出这道题,写上一番提交后就A了,哈哈哈,还是很NICE的嘛!!!

解题思路:用单调栈找出每一个数的左边界和右边界,要想用到这个数,前提是它在这个区间内是最小的那个,不然的话就另有其数了,然后一个关键就是,怎样计算它的权重值:假如这个数是a[ i ],他的左边界为L,右边界为R,这里的L和R都是下标的表示,val=a[ i ]( i - L[ i ] )(R[ i ] - i ),据说是乘法原理,但这里我还是没整太明白,友友如若知晓的话可以联系博主,在此表示感谢啦!

AC代码:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
ll L[201010], R[201010], a[201010];
struct number 
    ll num, id;
st[201010];
inline ll read()
    ll  x = 0;
    bool f = 0;
    char ch = getchar();
    while (ch < '0' || '9' < ch)    f |= ch == '-', ch = getchar();
    while ('0' <= ch && ch <= '9')
        x = x * 10 + ch - '0', ch = getchar();
    return f ? -x : x;

int main()

    
    ll n, i;
    n = read();
    for (i = 1;i <= n;i++)
    
        a[i] = read();
        L[i] = 0;
        R[i] = n + 1;
    
    ll s = 0;
    for (i = 1;i <= n;i++)
    
        while (s && st[s].num >= a[i]) s--;
        if (s) L[i] = st[s].id;
        s++;
        st[s].num = a[i];
        st[s].id = i;
    
    s = 0;
    for (i = n;i >= 1;i--)
    
        while (s && st[s].num >= a[i]) s--;
        if (s) R[i] = st[s].id;
        s++;
        st[s].num = a[i];
        st[s].id = i;
    
    ll ans = 0;
    for (i = 1;i <= n;i++)
    
        ans += a[i] * (i - L[i]) * (R[i] - i);
    
    cout << ans << endl;
    return 0;

/*

2 1 3

*/


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

Minimum Sum(单调栈) AtCoder Grand Contest 005

Minimum Sum(单调栈) AtCoder Grand Contest 005

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

BZOJ4262Sum 单调栈+线段树

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

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