题意
传送门 NC 20806
题解
∑ l = 1 n ∑ r = l + 1 n m a x ( a i − a j ∣ l ≤ i , j ≤ r ) = ∑ l = 1 n ∑ r = l + 1 n m a x ( a i ∣ l ≤ i ≤ r ) − ∑ l = 1 n ∑ r = l + 1 n m i n ( a j ∣ l ≤ j ≤ r ) \sum\limits_{l=1}^{n}\sum\limits_{r=l+1}^{n}max(a_i-a_j|l\leq i,j \leq r) = \sum\limits_{l=1}^{n}\sum\limits_{r=l+1}^{n}max(a_i|l\leq i\leq r)-\sum\limits_{l=1}^{n}\sum\limits_{r=l+1}^{n}min(a_j|l\leq j \leq r) l=1∑nr=l+1∑nmax(ai−aj∣l≤i,j≤r)=l=1∑nr=l+1∑nmax(ai∣l≤i≤r)−l=1∑nr=l+1∑nmin(aj∣l≤j≤r)
单调递减栈维护栈中某个元素至靠近栈底的相邻元素区间的最大值,对于每一个位置 i i i,统计以其为右闭合边界的所有 i − 1 i-1 i−1 个区间的最大值之和;对于最小值,取相反数后处理同理。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 100005
int n, t;
int s[maxn], q[maxn];
ll calc()
{
q[0] = -1;
ll r = 0, sum = 0, res = 0;
for (int i = 0; i < n; i++)
{
while (r > 0 && s[q[r]] <= s[i])
{
sum -= (ll)s[q[r]] * (q[r] - q[r - 1]);
--r;
}
q[++r] = i;
sum += (ll)s[q[r]] * (q[r] - q[r - 1]);
res += sum;
}
return res;
}
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", s + i);
ll res = calc();
for (int i = 0; i < n; i++) s[i] = -s[i];
res += calc();
printf("%lld\n", res);
}
return 0;
}