NC20806 区区区间间间
题目
题目描述
给出长度为n的序列a,其中第i个元素为 \(a_i\),定义区间(l,r)的价值为
\(v_{l,r} = max(a_i - a_j | l \leqslant i,j\leqslant r)\)
请你计算出 \(\sum_{l = 1}^n \sum_{r = l + 1}^n v_{l,r}\)
输入描述
第一行输入数据组数T
对于每组数据,第一行为一个整数n,表示序列长度
接下来一行有n个数,表示序列内的元素
输出描述
对于每组数据,输出一个整数表示答案
示例1
输入
3
3
4 2 3
5
1 8 4 3 9
20
2 8 15 1 10 5 19 19 3 5 6 6 2 8 2 12 16 3 8 17
输出
5
57
2712
说明
对于一组测试数据的解释:
区间[1, 2]的贡献为:4 - 2 = 2
区间[1, 3]的贡献为:4 - 2 = 2
区间[2, 3]的贡献为:3 - 2 = 1
2 + 1 + 2 = 5.
备注
\(T \leqslant 20,n\leqslant 10^5, 0 \leqslant a_i \leqslant 10^5\)
不保证数据随机生成!
题解
知识点:单调栈。
\(\sum_{l = 1}^n \sum_{r = l + 1}^n v_{l,r} = \sum_{l = 1}^n \sum_{r = l + 1}^n (max_{l,r} - min_{l,r})\) ,即所有子区间最大值之和减去所有子区间最小值之和。枚举端点用单调队列维护最小最大值,复杂度是 \(O(n^2)\)。换一个角度考虑,把每个元素当作最大/最小值,看看能维持左右多长,再将端点数相乘即可,这里用单调栈维护最邻近大于/小于。
细节上注意,以最大值为例,如果两个相同的元素,!s1.empty() && a[s1.top()] <= a[i] 都用小于等于作为弹出条件,那么这两个元素的扩展区间是完全相同的,从而左侧元素的右侧扩展和右侧元素的左侧扩展会有重复,因此保留一侧扩展而另一侧到小于等于就停,即 !s2.empty() && a[s2.top()] < a[i] 。
并且长度为 \(1\) 的区间不能算入其中,因此区间总数是 \((r[i] - i + 1) * (i - l[i] + 1) - 1\) ,但是由于长度为一的区间在最大值减去最小值过程会被消去,因此不减一也行。
这里有个小技巧,找最邻近大于时,即最小值扩展距离,可以将原数组取相反数,此时最小的会变成最大的,可以用最大值的方式求取,最后答案取相反数即可。
时间复杂度 \(O(n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int n;
int a[100007], l[100007], r[100007];
ll calc() {
stack<int> s1, s2;
for (int i = 0;i < n;i++) {
while (!s1.empty() && a[s1.top()] <= a[i]) s1.pop();
l[i] = s1.empty() ? 0 : s1.top() + 1;
s1.push(i);
}
for (int i = n - 1;i >= 0;i--) {
while (!s2.empty() && a[s2.top()] < a[i]) s2.pop();///防止相等元素重复计算
r[i] = s2.empty() ? n - 1 : s2.top() - 1;
s2.push(i);
}
ll sum = 0;
for (int i = 0;i < n;i++)
sum += (1LL * (r[i] - i + 1) * (i - l[i] + 1) - 1) * a[i];
return sum;
}
bool solve() {
cin >> n;
for (int i = 0;i < n;i++) cin >> a[i];
ll mx = calc();
for (int i = 0;i < n;i++) a[i] = -a[i];///取相反数,最小值变最大值可以用同一种操作
ll mn = -calc();
cout << mx - mn << '\n';
return true;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
if (!solve()) cout << -1 << '\n';
}
return 0;
}
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16438643.html

浙公网安备 33010602011771号