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
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll n,a[maxn],c;
ll up[maxn],upl[maxn],upr[maxn],down[maxn],downl[maxn],downr[maxn];
int main()
{
scanf("%lld",&n);
c=0;
for(ll i=0;i<n;i++)
{
scanf("%lld",&a[i]);
while(c!=0&&a[up[c-1]]>a[i])
{
upr[up[c-1]]=i;
c--;
}
if(c==0) upl[i]=0;
else upl[i]=up[c-1]+1;
up[c++]=i;
}
for(ll i=0;i<c;i++) upr[up[i]]=n;
c=0;
for(ll i=0;i<n;i++)
{
while(c!=0&&a[down[c-1]]<a[i])
{
downr[down[c-1]]=i;
c--;
}
if(c==0) downl[i]=0;
else downl[i]=down[c-1]+1;
down[c++]=i;
}
for(ll i=0;i<c;i++) downr[down[i]]=n;
ll ans=0;
for(ll i=0;i<n;i++)
{
ans-=(i-upl[i]+1)*(upr[i]-i)*a[i];
ans+=(i-downl[i]+1)*(downr[i]-i)*a[i];
}
printf("%lld",ans);
return 0;
}