直接DP就好了,求两个数组: left,right,分别表示
left[i] :比i小的左端点,(注意,为避免相等时重复统计,计左不计右)
class Solution {
private static final int MOD = 1000000007;
private void debug(int [] pri) {
for(int i=0,n = pri.length; i< n ; i++)System.out.print(pri[i]+" ");
System.out.println();
}
public int sumSubarrayMins(int[] A) {
int n = A.length;
int[] left = new int[n];
int[] right = new int[n];
left[0] =-1;
for(int i=1 ; i<n ; ++i){
if(A[i-1] <= A[i])left[i] = i-1;
else{
int now = i-1;
while (now !=-1 &&A[now] > A[i] ) {//算左不算右,避免重复统计
now = left[now];
}
left[i] = now;
}
}
right[n -1] = n;
for(int i=n -2 ; i >=0 ; --i){
if(A[i+1]< A[i])right[i] = i+1;
else{
int now = i+1;
while (now != n && A[now] >= A[i]) {
now = right[now];
}
right[i] = now;
}
}
// debug(left);
// debug(right);
long ans = 0;
for(int i=0 ; i<n ; ++i){
ans += (long)A[i]*(right[i] - i)*(i - left[i]);
ans %=MOD;
}
return (int)ans;
}
}