单调栈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 1≤N≤200,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