求出每个子区间的最大值减最小值的和
可以化成求出每个子区间的最大值的和减去每个子区间最小值的和
又可以看成求每个数作为最大值能左右延伸多远,就直接用这个数乘以这个区间能组成多少个子区间(分区间是否跨过这个数来计数)
然后这个问题就可以用单调栈来解决了

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
typedef long long ll;
ll le[N],ri[N];
ll a[N];
int t,n;
ll solve(){
   
    memset(le,0,sizeof(le));
    memset(ri,0,sizeof(ri));
    stack<int> s,t;
    for(int i=1;i<=n;i++){
   
        while(s.size()>0 && a[i]>=a[s.top()]){
   
            s.pop();
        }
        if(s.size()==0){
   
            le[i]=1;
        }
        else{
   
            le[i]=s.top()+1;
        }
        s.push(i);
    }
    for(int i=n;i>=1;i--){
   
        while(t.size()>0 && a[i]>a[t.top()]){
   
            t.pop();
        }
        if(t.size()==0){
   
            ri[i]=n;
        }
        else{
   
            ri[i]=t.top()-1;
        }
        t.push(i);
    }
    ll ans=0;
    for(int i=1;i<=n;i++){
   
        //a[i]直接乘以以a[i]作为最大值的区间个数,分跨过a[i]和没跨过a[i]两种
        ans+=a[i]*(ri[i]-le[i]+(ri[i]-i)*(i-le[i]));
    }
    for(int i=1;i<=n;i++){
   
        printf("%lld ",le[i]);
    }
    printf("\n");
    return ans;
}
int main(void){
   
    scanf("%d",&t);
    while(t--){
   
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
   
            scanf("%lld",&a[i]);
        }
        ll ans=solve();
        for(int i=1;i<=n;i++){
   
            a[i]=-a[i];
        }
        ans+=solve();
        printf("%lld\n",ans);
    }
    return 0;
}