N个整数组成的数组,定义子数组a[i]…a[j]的宽度为:max(a[i]…a[j]) - min(a[i]…a[j]),求所有子数组的宽度和。
输入
第1行:1个数N,表示数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数,表示数组中的元素(1 <= A[i] <= 50000)
输出
输出所有子数组的宽度和。
输入样例
5
1
2
3
4
5
输出样例
20
使用单调栈处理出以a[i]为最小值和最大值的左右边界
答案为:sum : (i - Lmax[i]) * (Rmax[i] - i) * a[i] - (i - Lmin[i]) * (Rmin[i] - i) * a[i]

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn];
int Lmin[maxn], Rmin[maxn];
int Lmax[maxn], Rmax[maxn];
stack<int> s;
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	a[0] = 0; a[n + 1] = 0;
	for (int i = 1; i <= n + 1; i++) {
		while (!s.empty() && a[s.top()] >= a[i]) {
			Rmin[s.top()] = i;
			s.pop();
		}
		s.push(i);
	}
	while (!s.empty()) s.pop();
	for (int i = n; i >= 0; i--) {
		while (!s.empty() && a[s.top()] > a[i]) {
			Lmin[s.top()] = i;
			s.pop();
		}
		s.push(i);
	}
	a[0] = 1e9; a[n + 1] = 1e9;
	while (!s.empty()) s.pop();
	for (int i = 1; i <= n + 1; i++) {
		while (!s.empty() && a[s.top()] <= a[i]) {
			Rmax[s.top()] = i;
			s.pop();
		}
		s.push(i);
	}
	while (!s.empty()) s.pop();
	for (int i = n; i >= 0; i--) {
		while (!s.empty() && a[s.top()] < a[i]) {
			Lmax[s.top()] = i;
			s.pop();
		}
		s.push(i);
	}
	long long ans = 0;
	for (int i = 1; i <= n; i++) {
		ans += 1LL * (i - Lmax[i]) * (Rmax[i] - i) * a[i];
		ans -= 1LL * (i - Lmin[i]) * (Rmin[i] - i) * a[i];
	}
	cout << ans << endl;
	return 0;
}