NC20806 区区区间间间
题目
题目描述
给出长度为n的序列a,其中第i个元素为 ,定义区间(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.
备注
不保证数据随机生成!
题解
知识点:单调栈。
,即所有子区间最大值之和减去所有子区间最小值之和。枚举端点用单调队列维护最小最大值,复杂度是 。换一个角度考虑,把每个元素当作最大/最小值,看看能维持左右多长,再将端点数相乘即可,这里用单调栈维护最邻近大于/小于。
细节上注意,以最大值为例,如果两个相同的元素,!s1.empty() && a[s1.top()] <= a[i]
都用小于等于作为弹出条件,那么这两个元素的扩展区间是完全相同的,从而左侧元素的右侧扩展和右侧元素的左侧扩展会有重复,因此保留一侧扩展而另一侧到小于等于就停,即 !s2.empty() && a[s2.top()] < a[i]
。
并且长度为 的区间不能算入其中,因此区间总数是 ,但是由于长度为一的区间在最大值减去最小值过程会被消去,因此不减一也行。
这里有个小技巧,找最邻近大于时,即最小值扩展距离,可以将原数组取相反数,此时最小的会变成最大的,可以用最大值的方式求取,最后答案取相反数即可。
时间复杂度
空间复杂度
代码
#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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧