「High Cry」Solution

简述题意

给定长度为 n n n 的数组 n n n,求出有多少个区间满足区间或大于区间最大值。

  • n ≤ 2 × 1 0 5 n \le 2 \times 10^5 n2×105

思路

从区间入手肯定不好做,考虑从最大值入手。

注意到一个区间,其肯定有一个最大值 a i a_i ai,因此统计区间个数就等价于统计对于 i ∈ [ 1 , n ] i \in [1,n] i[1,n],有多少个区间 [ l , r ] [l,r] [l,r] 满足 l ≤ i ≤ r l \le i \le r lir 且最大值等于 a i a_i ai 且区间或大于 a i a_i ai。注意到一个区间有多个最大值,因此钦定一个区间的最大值为最靠左的那一个。

区间最大值显然满足单调性,所以可以通过 ST \text{ST} ST 表加二分对每一个 i i i 预处理出 q l i , q r i ql_i,qr_i qli,qri,其含义为对于 ∀ l ∈ [ q l i , i ] , r ∈ [ i , q r i ] \forall l \in [ql_i,i],r\in[i,qr_i] l[qli,i],r[i,qri] [ l , r ] [l,r] [l,r] 的最大值为 a i a_i ai

接下来考虑区间或的限制。我们知道对于一个区间的或,很容易通过前缀数组 l o g ( n ) log(n) log(n) 求得,且在某个端点固定的情况下,随着另一个端点的延伸一定单调不降,因此也可以二分解决。对于每一个 i i i,不妨求出 l i , r i ( l i ≤ i , r i ≥ i ) l_i,r_i(l_i \le i,r_i\ge i) li,ri(lii,rii) ,其中 l i l_i li 表示离 i i i 最近且满足 [ l i , i ] [l_i,i] [li,i] 的区间或大于最大值的点,同理 r i r_i ri 表示离 i i i 最近且满足 [ i , r i ] [i,r_i] [i,ri] 的区间或大于最大值的点。那么对于一个区间 [ x , y ] [x,y] [x,y],如果其满足 x ∈ [ q l i , l i ] , y ∈ [ i , q r i ] x \in [ql_i,l_i],y \in [i,qr_i] x[qli,li]y[i,qri] 或者 x ∈ [ q l i , i ] , y ∈ [ r i , q r i ] x \in [ql_i,i],y\in[r_i,qr_i] x[qli,i],y[ri,qri],那么 [ x , y ] [x,y] [x,y] 就为题目所求的区间。

假设我们已求得 q l i , q r i , l i , r i ql_i,qr_i,l_i,r_i qli,qri,li,ri,那么某个 i ∈ [ 1 , n ] i \in [1,n] i[1,n] 对答案的贡献即为:
满足 x ∈ [ q l i , l i ] , y ∈ [ i , q r i ] x \in [ql_i,l_i],y \in [i,qr_i] x[qli,li]y[i,qri] 的区间个数 + + + 满足 x ∈ [ q l i , i ] , y ∈ [ r i , q r i ] x \in [ql_i,i],y\in[r_i,qr_i] x[qli,i],y[ri,qri] 的区间个数 - 满足 x ∈ [ q l i , l i ] , y ∈ [ r i , q r i ] x \in [ql_i,l_i],y \in [r_i,qr_i] x[qli,li]y[ri,qri] 的区间个数。推导基于容斥原理,且近乎显然。

代码

一道没太多细节的题,但是记得特殊处理 q l i ql_i qli q r i qr_i qri l i l_i li r i r_i ri 不存在的情况,且注意二分边界。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 2e5 + 5;
int n , pre[MAXN][31] , Max[MAXN][21] , a[MAXN] , ql[MAXN] , qr[MAXN] , ans;
vector<int> idx[MAXN];
int GetMax(int l , int r) {int s = log2(r - l + 1);return max(Max[l][s] , Max[r - (1 << s) + 1][s]);
}
bool check(int l , int r , int pos) {for (int v : idx[pos]) {if (pre[r][v] - pre[l - 1][v] > 0) return 1;}return 0;
}
int Findl(int pos) {int l = ql[pos] , r = pos;while(l < r) {int mid = l + r + 1 >> 1;if (check(mid , pos , pos)) l = mid;else r = mid - 1;}if (!check(l , pos , pos)) return -1;return l;
}
int Findr(int pos) {int l = pos , r = qr[pos];while(l < r) {int mid = l + r >> 1;if (check(pos , mid , pos)) r = mid;else l = mid + 1;}if (!check(pos , l , pos)) return -1;return l;
}
signed main() {ios::sync_with_stdio(false);cin.tie(nullptr) , cout.tie(nullptr);cin >> n;for (int i = 1 ; i <= n ; i ++) cin >> a[i] , Max[i][0] = a[i];for (int i = 1 ; i <= n ; i ++) {for (int j = 0 ; j <= 30 ; j ++) {if ((1 << j) & a[i]) pre[i][j] = pre[i - 1][j] + 1;else pre[i][j] = pre[i - 1][j] , idx[i].push_back(j);}}for (int j = 1 ; j <= 20 ; j ++) {for (int i = 1 ; i + (1 << j) - 1 <= n ; i ++) {Max[i][j] = max(Max[i][j - 1] , Max[i + (1 << j - 1)][j - 1]);}}a[0] = a[n + 1] = 0x3f3f3f3f;for (int i = 1 ; i <= n ; i ++) {if (a[i - 1] >= a[i] && a[i + 1] > a[i]) continue;int l = 1 , r = i - 1;while(l < r) {int mid = l + r >> 1;if (GetMax(mid , i - 1) < a[i]) r = mid;else l = mid + 1;}if (GetMax(l , i - 1) < a[i]) ql[i] = l;else ql[i] = i;l = i , r = n;while(l < r) {int mid = l + r + 1 >> 1;if (GetMax(i , mid) <= a[i]) l = mid;else r = mid - 1;}qr[i] = l;}for (int i = 1 ; i <= n ; i ++) {if (a[i - 1] >= a[i] && a[i + 1] > a[i]) continue;int l = Findl(i) , r = Findr(i);if (l == -1 && r == -1) continue;if (l == -1) ans += (i - ql[i] + 1) * (qr[i] - r + 1);else if (r == -1) ans += (l - ql[i] + 1) * (qr[i] - i + 1);else ans += (l - ql[i] + 1) * (qr[i] - i + 1) + (i - ql[i] + 1) * (qr[i] - r + 1) - (l - ql[i] + 1) * (qr[i] - r + 1);}cout << ans;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【rust简单工具理解】

1.map方法 map这个闭包的本质就是映射 let numbers vec![1, 2, 3, 4, 5]; let numbers_f64: Vec<f64> numbers.into_iter().map(|&x| x as f64).collect(); println!("{:?}", numbers_f64); // 输出: [1.0, 2.0, 3.0, 4.0, 5.0]2.and_then and_then …

锦瑟香也MYLOVE:音质与颜值俱佳,入坑HiFi的热门好物!

当下尽管无线耳机大行其道&#xff0c;但有线耳机依旧保有其独特的魅力&#xff0c;特别是在音质表现上&#xff0c;它们拥有无线耳机难以企及的优势。如果对音质要求很高的话&#xff0c;口袋里还是少不了一副有线耳机。国产品牌中就有许多性价比高的有线耳机&#xff0c;它们…

Django admin后台添加自定义菜单和功能页面

django admin是根据注册的模型来动态生成菜单&#xff0c;从这个思路出发&#xff0c;如果想添加自定义菜单&#xff0c;那就创建一个空模型并且注册。步骤如下&#xff1a; 1、创建空模型&#xff1a; class ResetSVNAuthFileModel(models.Model):"""仅用来显…

学习 Rust 的第五天:了解程序的基本控制流程

大家好呀 欢迎来到这个学习 Rust 的 30 天系列的第五天&#xff0c;今天我们将深入了解 Rust 中的控制流。 控制流&#xff0c;顾名思义&#xff0c;根据条件来 控制程序的流程。 If 表达式 当你想要在满足条件时执行一段代码块时&#xff0c;可以使用 if 表达式。 示例 …

菜鸟Java基础教程 9.Java 循环结构

Java 循环结构 - for, while 及 do…while Java循环结构 Java 循环结构 - for, while 及 do...while1. while 循环实例Test.java 文件代码&#xff1a; 2. do…while 循环实例Test.java 文件代码&#xff1a; 3. for循环实例Test.java 文件代码&#xff1a; 4. Java 增强 for 循…

数据类型判断的方法

一、typeof 使用方法如下&#xff1a; typeof operand typeof(operand)operand表示要返回类型的对象或基本类型的表达式 &#xff0c;typeof运算符返回一个字符串&#xff0c;表示操作数的类型。 typeof 666 // number typeof 666 // string typeof undefined // undefined …

《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制伊甸火山3D网格曲面图

11.4.2小节我们使用3D曲面图可视化分析伊甸火山数据&#xff0c;本小节我们采用3D网格曲面图可视化分析伊甸火山数据&#xff0c;以展示其地形&#xff0c;具体示例代码如下。 购书地址&#xff1a;https://item.jd.com/14102657.html

Django数据导出与导入问题

执行: python manage.py loaddata data.json 的常见错误: * 1. UnicodeDecodeError: utf-8 codec cant decode byte 0xff in position 0: invalid start byte* 2. raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",...django.core.serializer…

css animation 动画详细学习

学习 CSS 动画是一个深入且富有创造性的过程&#xff0c;它允许开发者创建出引人入胜且交互性强的网页效果。以下是对 CSS 动画学习的一些总结和要点&#xff1a; 1. 关键帧动画&#xff08;keyframes&#xff09; 使用 keyframes 规则定义动画的整个过程。在 keyframes 中&a…

聚道云软件连接器助力企业实现滴滴出差报销自动化

一、客户介绍 某机械有限公司是一家在机械设备制造领域拥有深厚底蕴和卓越实力的企业。自公司成立以来&#xff0c;该公司始终秉承创新、务实、高效的发展理念&#xff0c;专注于机械设备的研发、生产和销售。经过多年的发展&#xff0c;公司已成为国内机械行业的佼佼者&#…

c++自制小游戏:c++人生重开模拟器(修仙版)

现在已经停止更新了&#xff0c;最新版8.5&#xff0c;主页的所有下载链接都没用了&#xff0c;新旧版的人生重开模拟器都在这&#xff1a; 密码4b3i 注&#xff1a;版本较新的基于GCC-4.9.2环境下运行的&#xff0c;旧版基于GCC版本更低&#xff0c;但多少不知道了 祝你游玩…

【抽代复习笔记】12-群(六):群与运算表、群与同态的一些关系

关于运算表的一些性质&#xff1a; 假设G是一个有限集合&#xff0c;o是定义在G上的映射&#xff0c;则 ①群公理1成立&#xff1c;&#xff1d;&#xff1e;运算表中所有元素都属于G&#xff1b; ②交换律成立&#xff1c;&#xff1d;&#xff1e;运算表中的元素关于主对角…

比例微积分算法

比例微积分&#xff08;Proportional-Integral-Derivative&#xff0c;简称PID&#xff09;算法是一种常用的控制算法&#xff0c;它用于计算控制器的输出&#xff0c;以使得系统的输出能够尽可能地跟踪期望的目标值。PID控制器基于系统的误差&#xff08;目标值与当前值的差&a…

RocketMQ异步消息发送失败重试DEMO

producer.setRetryTimesWhenSendAsyncFailed(3); 都知道通过设置&#xff0c;尝试是在MQClientAPIImpl 中完成 其重试是通过MQClientAPIImpl的onExceptionImpl方法来实现&#xff0c;它会先判断重试次数&#xff0c;然后重新调用sendMessageAsync方法进行重试&#xff0c;调用…

并查集的进一步优化

并查集是一种用于处理不相交集合的数据结构。它支持两种操作&#xff1a;查找&#xff08;Find&#xff09;和合&#xff08;Union&#xff09;。 查找操作用于确定某个元素属于哪个子集&#xff0c;而合并操作则用于将两个子集合并为一个集合。本文将介绍并查集的进一步优化方…

新手必看!嵌入式STM32-PID

本文目录 一、知识点1. 位置式pid&#xff08;1&#xff09;公式&#xff08;2&#xff09;代码 2. 串级PID简易代码 一、知识点 1. 位置式pid &#xff08;1&#xff09;公式 &#xff08;2&#xff09;代码 pid.c typedef struct PID {float Kp; // Proportion…

高效编程工具 JetBrains CLion 2024 中文激活 mac/win

在追求编程高效与精准的道路上&#xff0c;JetBrains CLion 2024 for Mac无疑是您的最佳伙伴。这款专为Mac用户打造的C/C集成开发环境&#xff0c;凭借其强大的功能和出色的性能&#xff0c;赢得了广大开发者的青睐。 CLion 2024拥有智能的代码编辑器和强大的代码分析工具&…

vue 数据类型转换

在Vue中进行数据类型转换有多种方式&#xff0c;具体取决于你希望实现的转换类型和场景。 以下是一些常见的数据类型转换示例&#xff1a; 字符串转数字&#xff1a; let str "42"; let num Number(str); console.log(num); // 42数字转字符串&#xff1a; let…

关于java数据样品以及转换

关于集合 List<String> List<String> list duoMapper.selectName(); [ "alice1", "alice2", "alice3", "alice4", "alice5", "alice6", "alice7", "alice8",…

pycharm已有项目增加pipenv

pycharm已有项目增加pipenv 第一步 第一步 python base 需要安装pipenv pip install pipenv在设置&#xff0c;project 之后 会自动查找项目下的pipfile 和pipfile.lock 进行pip配置 如果网络较慢&#xff0c;可以修复pipfile下的url 为国内的pip源 [[source]] name "…