NC20806 区区区间间间
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;
}
NC20806 区区区间间间的更多相关文章
- 牛客网 223C 区区区间间间(单调栈)
题目链接:区区区间间间 题意:给出长度为n的数字序列ai,定义区间(l,r)的价值为, 请你计算出. 题解:单调栈求ai左边和右边第一个比它小的位置,需要减去ai的个数为$(R_i-i+1)*(i-L ...
- NowCoder--牛可乐发红包脱单ACM赛C_区区区间间间
题目链接:C_区区区间间间 思路:算贡献,求出每个数为当前最大值时所在的区间个数,和每个数为最小值的区间个数 和这个题有点类似 搭配食用效果更佳 点击这里 #include<bits/stdc+ ...
- 牛客ACM赛 C 区区区间间间
链接 C 区区区间间间 给定长度为\(n\)序列,求\[\sum_{i=1}^{n} \sum_{j=i}^{n} max-min\] 其中\(max\),\(min\)为区间最大,最小值,\(n\l ...
- 牛客网 牛可乐发红包脱单ACM赛 C题 区区区间间间
[题解] 我想到了两种解法. 一种是扫描线+线段树+单调栈. 另一种方法是O(n)的,比较巧妙. 考虑每个数在哪些区间可以作为最小数.最长的区间就是它向左右走,直到有数字比它小,这个可以用单调栈维护. ...
- [nowcoderACM_223C][区区区间间间]
题目链接 思路 考虑用单调栈,栈顶为最大元素.当得到一个新值得时候,将这个值宇栈顶比较.因为栈顶是前面的最大元素.所以只要当前元素比栈顶大,那么肯定比前面的都大.只要将这个元素乘上前面的个数就行了. ...
- TZOJ 5694 区间和II(树状数组区间加区间和)
描述 给定n个整数,有两个操作: (1)给某个区间中的每个数增加一个值: (2)查询某个区间的和. 输入 第一行包括两个正整数n和q(1<=n, q<=100000),分别为序列的长度和操 ...
- LibreOJ 6280 数列分块入门 4(分块区间加区间求和)
题解:分块的区间求和比起线段树来说实在是太好写了(当然,复杂度也高)但这也是没办法的事情嘛.总之50000的数据跑了75ms左右还是挺优越的. 比起单点询问来说,区间询问和也没有复杂多少,多开一个su ...
- LibreOJ 6283 数列分块入门 7(区间加区间乘区间求和)
题解:这道题要打一个乘标记一个加标记,两个标记的优先级是乘法高,所以在乘的时候要将加标记同时乘上一个c,当然,对于每个非完整块一定要记得暴力重构整个块,把加标记和乘标记都初始化. 代码如下: #inc ...
- 使用IBM SVC构建vSphere存储间集群
使用IBM SVC构建vSphere存储间集群 本文目的 本文描述利用IBM SVC来构建Vsphere 存储间集群 解决方案 什么是vMSC? vShpere存储间集群是一个针对VmwarevSpe ...
随机推荐
- acwing刷题-放养又没有完全放养
题目 一个鲜为人知的事实是,奶牛拥有自己的文字:「牛文」. 牛文由 26 个字母 a 到 z 组成,但是当奶牛说牛文时,可能与我们所熟悉的 abcdefghijklmnopqrstuvwxyz 不同, ...
- 2021.08.01 P3377 左偏树模板
2021.08.01 P3377 左偏树模板 P3377 [模板]左偏树(可并堆) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<iostream> ...
- XCTF练习题---MISC---如来十三掌
XCTF练习题---MISC---如来十三掌 flag:flag{bdscjhbkzmnfrdhbvckijndskvbkjdsab} 解题步骤: 1.观察题目,下载附件进行查看 2.打开附件,压根看 ...
- ViewFlipper 简单应用
AdvserView.java package com.earen.viewflipper; import android.content.Context; import android.graphi ...
- 测试必会 Docker 实战(一):掌握高频命令,夯实内功基础
在 Dokcer 横空出世之前,应用打包一直是大部分研发团队的痛点.在工作中,面对多种服务,多个服务器,以及多种环境,如果还继续用传统的方式打包部署,会浪费大量时间精力. 在 Docker 出现后,它 ...
- spring 拦截器流程 HandlerInterceptor AsyncHandlerInterceptor HandlerInterceptorAdapter
HandlerInterceptor源码 3种方法: preHandle:拦截于请求刚进入时,进行判断,需要boolean返回值,如果返回true将继续执行,如果返回false,将不进行执行.一般用于 ...
- Blazor Hybrid / MAUI 简介和实战
1. Blazor Blazor 是一个使用 .NET 生成交互式客户端 Web UI 的框架: 使用 C# 代替 JavaScript 来创建信息丰富的交互式 UI. 共享使用 .NET 编写的服务 ...
- WSL2+Docker+IDEA一站式开发调试
WSL2+Docker+IDEA一站式开发调试 前言 我们知道,Docker是一个容器引擎:对于开发者来说,使用Dokcer容器部署各种开发需要的中间件(比如myql.redis)会非常简单方便: ...
- 521. Longest Uncommon Subsequence I - LeetCode
Question 521. Longest Uncommon Subsequence I Solution 题目大意:给两个字符串,找出非共同子串的最大长度 思路:字符串相等就返回-1,不等就返回长度 ...
- Spring 源码(17)Spring Bean的创建过程(8)Bean的初始化
知识回顾 Bean的创建过程会经历getBean,doGetBean,createBean,doCreateBean,然后Bean的创建又会经历实例化,属性填充,初始化. 在实例化createInst ...