2024牛客暑期多校训练营7 D.Interval Selection(异或哈希+双指针)

news/2024/9/18 12:33:34/ 标签: 哈希算法, 算法, 数据结构, c++

原题链接:D.Interval Selection


题目大意:


给你一个长度为 n n n 的数组 a a a,定义一个区间 [ l , r ] [l,r] [l,r] 内的连续子数组为好的,当且仅当这个子数组内的所有元素 a l , a l + 1 , . . . , a r a_{l},a_{l+1},...,a_{r} al,al+1,...,ar 在当前区间中恰好出现了 k k k 次。

例如数组 [ 1 , 1 , 2 , 3 , 2 , 3 , 1 ] [1,1,2,3,2,3,1] [1,1,2,3,2,3,1] k = 2 k=2 k=2 时,区间 [ 1 , 2 ] , [ 3 , 6 ] , [ 1 , 6 ] [1,2],[3,6],[1,6] [1,2],[3,6],[1,6] 这几个区间是好的,因为每个元素 a i a_{i} ai 都只出现了两次。而区间 [ 1 , 3 ] [1,3] [1,3] 不是好的,因为值 2 2 2 只出现了一次,同理区间 [ 1 , 7 ] [1,7] [1,7] 不是好的因为值 1 1 1 出现了三次。

问你这个数组有多少个区间是好的。

解题思路:


题解给出了线段树做法,没怎么看懂,这里给出一个更方便的异或哈希做法。

我们知道一个数字异或两次得到的值为 0 0 0,比如 3 ⊕ 3 = 0 3 \oplus3=0 33=0 1 ⊕ 7 ⊕ 7 = 0 1 \oplus 7 \oplus 7=0 177=0,但其实我们可以扩展这个性质到任意 k k k 位数异或为 0 0 0

比如当 k = 5 k=5 k=5 时,我们想要当且仅当 a i a_{i} ai 数量为 5 5 5 的倍数时异或起来为 0 0 0,且其他任意情况个 a a a 异或起来一定不为 0 0 0,我们可以做类似这样的操作。

我们知道一个数字异或两次可以归零,那么我们按照如下方法将每个 a i a_{i} ai 重新赋值。

原数组: [ a , a , a , a , a , a , a ] [a,a,a,a,a,a,a] [a,a,a,a,a,a,a] 7 7 7 a i a_{i} ai

我们随意构造一个长度为 k k k 的随机数列 B B B [ 1 , 9 , 3 , 6 , 8 ] [1,9,3,6,8] [1,9,3,6,8]

之后,按照 a 1 = 1 ⊕ 9 , a 2 = 9 ⊕ 3 , . . . , a 5 = 8 ⊕ 1 , a 6 = 1 ⊕ 9 , . . . a_{1}=1 \oplus 9,a_{2}=9 \oplus 3,...,a_{5}=8 \oplus 1,a_{6}=1 \oplus 9,... a1=19,a2=93,...,a5=81,a6=19,... 的循环顺序给对应的 a i a_{i} ai 赋值,于是我们发现了如下的情况:

修改后数组: [ 1 ⊕ 9 , 9 ⊕ 3 , 3 ⊕ 6 , 6 ⊕ 8 , 8 ⊕ 1 , 1 ⊕ 9 , 9 ⊕ 3 ] [1 \oplus 9,9 \oplus 3,3 \oplus 6,6 \oplus 8,8 \oplus 1,1 \oplus 9,9 \oplus 3] [19,93,36,68,81,19,93]

我们任选一个恰好包含了 k k k 的倍数个 a i a_{i} ai 的区间,例如区间 [ 2 , 6 ] , [ 3 , 7 ] [2,6],[3,7] [2,6],[3,7],那么我们异或的答案会为 0 0 0,而数量不为 k k k 的倍数的区间,比如 [ 1 , 2 ] , [ 4 , 4 ] [1,2],[4,4] [1,2],[4,4] 异或起来一定不为 0 0 0

可以发现,这样选取 k k k a i a_{i} ai 出来时,我们构造的数列 B B B 中的每个数字都参与了异或两次,不过这个数列要足够散乱以保证错误率达到一个极低的概率便可认为无错。

解决了 k k k 个异或为 0 0 0 的情况,假前缀异或和为 S S S,我们考虑答案如何取得。

显然我们可以枚举 r r r 的同时找到 l l l 使得 S [ r ] ⊕ S [ l − 1 ] = 0 S[r] \oplus S[l-1]=0 S[r]S[l1]=0 [ l , r ] [l,r] [l,r] 内不存在某个数字 a i a_{i} ai 的出现次数 c n t [ a i ] > k cnt[a_{i}]>k cnt[ai]>k

保证 [ l , r ] [l,r] [l,r] 内不存在某个数字 a i a_{i} ai 的出现次数 c n t [ a i ] > k cnt[a_{i}]>k cnt[ai]>k,其实只要保证我们双指针移动的同时保证 c n t [ a r ] ≤ k cnt[a_{r}] \leq k cnt[ar]k 即可保证区间内满足情况。

值得注意的是:
[ l , r ] [l,r] [l,r] 内存在 c n t [ a i ] < k cnt[a_{i}]<k cnt[ai]<k 的情况也可能存在答案,例如当 [ l , r ] [l,r] [l,r] 内形成的子数组为 k = 3 , [ 1 , 1 , 3 , 2 , 2 , 3 , 3 , 2 ] k=3,[1,1,3,2,2,3,3,2] k=3,[1,1,3,2,2,3,3,2] 时,即使 c n t 1 = 2 cnt_{1}=2 cnt1=2 也存在 [ 3 , 2 , 2 , 3 , 3 , 2 ] [3,2,2,3,3,2] [3,2,2,3,3,2] 这个子数组为答案,因此不会影响结果计算,只需要保证正确性即可。(显然)

比如数组: k = 2 , [ 2 , 1 , 1 , 2 , 1 , 2 ] k=2,[2,1,1,2,1,2] k=2,[2,1,1,2,1,2] k = 3 , [ 1 , 3 , 3 , 1 , 1 , 3 ] k=3,[1,3,3,1,1,3] k=3,[1,3,3,1,1,3] 是合法的,因为其修改后的数组的值异或为 0 0 0

但是值得注意的是当合法区间 [ l , r ] [l,r] [l,r] 形如: k = 2 , [ 1 , 1 , 2 , 2 , 3 , 3 ] k=2,[1,1,2,2,3,3] k=2,[1,1,2,2,3,3] 时,我们不能单纯让答案加 1 1 1,因为对于当前的 r r r 而言存在 3 3 3 l l l 使得 [ 1 , 1 , 2 , 2 , 3 , 3 ] , [ 2 , 2 , 3 , 3 ] , [ 3 , 3 ] [1,1,2,2,3,3],[2,2,3,3],[3,3] [1,1,2,2,3,3],[2,2,3,3],[3,3] 三个 S [ r ] ⊕ S [ l − 1 ] = 0 S[r] \oplus S[l-1]=0 S[r]S[l1]=0

即我们要进行找到区间 [ l − 1 , r − 1 ] [l-1,r-1] [l1,r1] 内有多少个下标等于 S [ r ] S[r] S[r] 的计数操作,注意是。

我们可以对 S [ r ] S[r] S[r] 开一个 v e c t o r vector vector 存下标,然后二分有多少个下标 j j j 满足 l − 1 ≤ j ≤ r − 1 l-1\leq j \leq r-1 l1jr1 即可。

构造和双指针二分用 m a p map map 辅助查询的时间复杂度均为单次操作 O ( log ⁡ n ) O(\log n) O(logn),注意一些细节即可通过。

时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn)

#include <bits/stdc++.h>
#include <chrono>
#include <random>
#include <ctime>using i64 = long long;
using u64 = unsigned long long;void solve() {//随机数生成器std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());int n, k;std::cin >> n >> k;std::vector<u64> A(n + 1);for (int i = 1; i <= n; ++i) {std::cin >> A[i];}i64 ans = 0;//特判 k = 1if (k == 1) {std::map<int, int> cnt;for (int l = 1, r = 1; r <= n; ++r) {++cnt[A[r]];while (cnt[A[r]] > 1) {--cnt[A[l++]];}ans += r - l + 1;}std::cout << ans << "\n";return;}//前缀异或和std::vector<u64> S(n + 1);//统计数字 a 的出现次数(获得循环位置)std::map<int, int> cnt;//数字 a 的哈希值std::map<int, std::vector<u64>> hash;for (int i = 1; i <= n; ++i) {auto& V = hash[A[i]];if (V.size() == 0) {V.emplace_back(rng());}u64 value = V.back();if (V.size() < k) {V.emplace_back(rng());value ^= V.back();} else {int p = cnt[A[i]] % k;value = V[p] ^ V[(p + 1) % k];}++cnt[A[i]];S[i] = S[i - 1] ^ value;//构建循环后的数组}//pos 记录 l - 1 <= 的 S[r]std::map<u64, std::vector<int>> pos;cnt.clear();pos[S[0]].emplace_back(0);for (int l = 1, r = 1; r <= n; ++r) {//保证 [l, r] 内所有数字 cnt[A[i]] <= k++cnt[A[r]];while (cnt[A[r]] > k) {--cnt[A[l++]];}//边移动 r 边加入 S[r] 下标则二分大于等于 l - 1 的即可pos[S[r]].emplace_back(r);auto& P = pos[S[r]];ans += P.end() - lower_bound(P.begin(), P.end(), l - 1) - 1;}std::cout << ans << "\n";
}signed main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t = 1;std::cin >> t;while (t--) {solve();}return 0;
}

http://www.ppmy.cn/news/1516401.html

相关文章

虚幻5|暴击攻击和释放技能,造成伤害

玩家数据的Actor组件制作&#xff1a;虚幻5|制作玩家血量&#xff0c;体力-CSDN博客 造成伤害时&#xff0c;显示暴击及暴击字体颜色和未暴击的字体颜色&#xff0c;还有释放技能连击 一.编辑暴击数据 1.打开之前创建的玩家数据Actor组件 创建一个浮点变量&#xff0c;命名…

Python实现贪心算法

目录 贪心算法简介贪心算法的基本思想贪心算法的应用场景活动选择问题 Python实现活动选择问题代码解释活动选择问题的解贪心算法的正确性分析贪心算法的其他应用贪心算法的局限性贪心算法的优化与变种总结 贪心算法简介 贪心算法&#xff08;Greedy Algorithm&#xff09;是一…

10天速通Tkinter库——Day7:主菜单及图鉴

本篇博客我将介绍Tkinter实践项目《植物杂交实验室》中的杂交实验室主菜单、基础植物图鉴、杂交植物图鉴、杂交植物更多信息四个页面的制作。 它们作为主窗口的子页面实例&#xff0c;除了继承主窗口的基础设置&#xff08;如图标、标题、尺寸等等&#xff09;、还可以使用主窗…

使用C++开发黑神话悟空类似3A如何避免内存泄漏

智能指针&#xff1a;使用C11或更高版本中的智能指针&#xff08;如std::unique_ptr、std::shared_ptr和std::weak_ptr&#xff09;来自动管理内存。这些智能指针在超出作用域时会自动释放它们所管理的内存。 RAII&#xff08;Resource Acquisition Is Initialization&#xf…

Java开发程序员职业发展路径

入行阶段&#xff1a;后端 3年 目标 在这一阶段&#xff0c;你将专注于后端开发&#xff0c;特别是Java编程语言及其相关技术栈。 主要任务和技能 掌握Java基础: 理解Java语言的核心概念&#xff0c;如OOP&#xff08;面向对象编程&#xff09;、数据结构、算法等。学习后端…

【Rust练习】10.元组

练习题来自&#xff1a;https://practice-zh.course.rs/compound-types/tuple.html 1 元组中的元素可以是不同的类型。元组的类型签名是 (T1, T2, …), 这里 T1, T2 是相对应的元组成员的类型. fn main() {let _t0: (u8,i16) (0, -1);// 元组的成员还可以是一个元组let _t1:…

相关性分析

斯皮尔曼、皮尔逊、肯德尔、点双列相关分析、偏相关分析、距离相关分析、双变量回归分析和互信息。 特性斯皮尔曼相关分析&#xff08;Spearman Correlation&#xff09;皮尔逊相关分析&#xff08;Pearson Correlation&#xff09;肯德尔相关分析&#xff08;Kendall’s Tau&…

华为OD题目 csv格式的数据 字符串 用C没写出来

这题对于嵌入式mcu的人来说&#xff0c;太难为了。不想解了&#xff0c;烂摆。有心情再说把。 将一个csv格式的数据文件中包含有单元格引用的内容替换为对应单元格内容的实际值。 Comma seprated values&#xff08;CSV&#xff09;逗号分隔值&#xff0c;csv格式的数据文件使用…

nodemon学习(一)简介、安装、配置、使用

nodemon用来监视node.js应用程序中的任何更改并自动重启服务,非常适合用在开发环境中。以前&#xff0c;我们开发一个node后端服务时&#xff0c;每次更改文件&#xff0c;均需重启一下&#xff0c;服务才能生效。这使我们的开发效率降低了很多。nodemon的出现&#xff0c;可以…

Catf1ag CTF Crypto(六)

前言 Catf1agCTF 是一个面向所有CTF&#xff08;Capture The Flag&#xff09;爱好者的综合训练平台&#xff0c;尤其适合新手学习和提升技能 。该平台由catf1ag团队打造&#xff0c;拥有超过200个原创题目&#xff0c;题目设计注重知识点的掌握&#xff0c;旨在帮助新手掌握C…

ffmpeg.exe命令行常见应用

基本转换&#xff1a; ffmpeg -i input.mp4 output.avi将input.mp4文件转换为output.avi文件。 提取音频&#xff1a; ffmpeg -i input.mp4 -vn output.mp3从input.mp4文件中提取音频并保存为output.mp3文件。 视频剪辑&#xff1a; ffmpeg -i input.mp4 -ss 00:00:30 -t 00:…

深入探讨Java多线程

我的主页&#xff1a;2的n次方_ 1. 多线程的概念 多线程是指在同一个程序中同时执行多个线程的技术。线程是操作系统能够独立调度和执行的最小单位。在Java中&#xff0c;线程由Thread类来表示&#xff0c;所有的线程都是通过这个类或其子类来创建和控制的。通过合理的多线…

codetop标签动态规划大全C++讲解(上)!!动态规划刷穿地心!!学吐了家人们o(╥﹏╥)o

主要供自己回顾学习&#xff0c;会持续更新&#xff0c;题源codetop动态规划近半年 1.零钱兑换2.零钱兑换II3.面试题08.11.硬币4.单词拆分5.最长递增子序列6.最长递增子序列的个数7.得到山形数组的最少删除次数8.最长公共子序列9.最长重复子数组10.最长等差数列11.最大子数组和…

Docker数据卷使用手册

目录 目标 前言 概念 官方文档 匿名卷&#xff08;Anonymous Volumes&#xff09; 简介 案例 命名卷&#xff08;Named Volumes&#xff09; 简介 案例 目标 掌握Volume命令通过演示案例&#xff0c;理解数据卷种类与各自的用途。 前言 我们在很多网上教程上可以看到…

前端宝典十:webpack性能优化最佳实践

Webpack 内置了很多功能。 通常你可用如下经验去判断如何配置 Webpack&#xff1a; 想让源文件加入到构建流程中去被 Webpack 控制&#xff0c;配置 entry&#xff1b;想自定义输出文件的位置和名称&#xff0c;配置 output&#xff1b;想自定义寻找依赖模块时的策略&#xff…

云计算day31

⼀、Docker 1、Docker介绍.pdf 1、Docker 是什么&#xff1f; Docker 是⼀个开源的应⽤容器引擎&#xff0c;可以实现虚拟化&#xff0c;完全采⽤“沙 盒”机制&#xff0c;容器之间不会存在任何接⼝。 Docker 通过 Linux Container&#xff08;容器&#xff09;技术将任意…

如何在Docker中部署Eureka Server:容器化微服务注册中心

在现代微服务架构中&#xff0c;服务注册和发现是至关重要的。Eureka Server 是一个由 Netflix 开发的开源服务注册和发现工具&#xff0c;它允许微服务实例在运行时动态地注册和查询其他服务。将 Eureka Server 部署在 Docker 中可以提高其可移植性和可维护性&#xff0c;同时…

Django 后端架构开发:手机与邮箱验证码接入、腾讯云短信SDK和网易邮箱

Django 后端架构开发&#xff1a;手机与邮箱验证码接入、腾讯云短信SDK和网易邮箱接入 &#x1f31f; 手机短信与邮箱短信验证码的应用场景 在现代应用中&#xff0c;短信和邮箱验证码是用户验证和安全管理的关键组成部分。它们广泛应用于注册、登录、找回密码等场景&#xf…

elasticsearch -- RestClient操作文档

RestClient操作文档 为了与索引库操作分离&#xff0c;我们再次参加一个测试类&#xff0c;做两件事情&#xff1a; 初始化RestHighLevelClient我们的酒店数据在数据库&#xff0c;需要利用IHotelService去查询&#xff0c;所以注入这个接口 package cn.itcast.hotel;import…

机器学习:opencv图像识别--图片专项

目录 前言 一、读取图片 1.安装opencv库 2.读取彩色图片 3.读取灰度图 二、RGB 1.RGB的概念 2.颜色通道&#xff1a; 3.图像表示 4.代码实现单通道图像 三、ROI 1.代码实现 四、图片打码 五、图片组合 六、图片缩放 总结 前言 OpenCV&#xff08;Open Source C…