当前位置: 首页 > news >正文

P5610 解题报告

P5610 解题报告

简要题意

一个长为 \(n\)非负整数序列 \(a\),支持以下两个操作:

  • 1 l r x:把区间 \([l,r]\) 中所有 \(x\) 的倍数除以 \(x\)
  • 2 l r:查询区间 \([l,r]\) 的和。

本题强制在线。

数据范围: \(1\leq n,m\leq 10^5\)\(0\leq a_i\leq 5\times 10^5\)\(1\leq x\leq 5\times 10^5\)\(1\leq l\leq r\leq n\)

时间限制:\(500\) ms。

分析

首先,我们考虑一个数至多被操作 \((\log V)\) 次,所以我们不需要关心操作部分的时间复杂度。因此我们只需要分析怎么找到需要被操作的数。

我们注意到:在 \([1,5\times 10 ^5]\) 内因数最多的个数为 \(200\)。所以我们开 \(5\times 10^5\) 个链表,然后我们就可以枚举一个数的所有因数,然后把 \(a_i\) 插入到每一个因数的链表中,我们就可以二分查找操作区间的左右端点,然后操作一个点的时候我们就判断这个点是否还是 \(x\) 的因数,如果不是,就把它删掉。删掉的操作可以使用并查集实现。询问操作就用常数最小的树状数组。

但是至此,我们还是做不了这题。我们还要做很多事情:

  • 首先,我们枚举一个数的因数这部分对每一个数做是 \(O(n \sqrt n)\) 的,这并不优秀。我们考虑枚举因数,然后枚举它的倍数,这个时间复杂度是调和级数,即 \(O(n \log n)\)

  • 其次,vector 实在太慢了。我们只好自己实现链表:开一个内存池,然后数据就用指针,赋值之后就可以当普通数组用了。但是注意,这个内存池不要开太大,不然会增大常数(指针移动的时间)。

于是,我们整理思路,总结一下步骤:

  • 开桶,然后预处理出每一个因数的出现次数,然后预留出每一个因数的链表空间;统计每一个数的因数个数并预留空间。

  • 然后预处理每一个数的因数,然后对每一个序列中的元素插入因数。

  • 在询问时,先二分出当前询问区间对应到当前链表上的区间,然后通过并查集实现访问下一项,每一次访问下一项时判断当前数是否还是当前数的倍数,不是就通过并查集删掉。

http://www.jsqmd.com/news/34538/

相关文章:

  • fcitx5里有趣的东西
  • 自定义MCP Server
  • 英语_错题集_25-11
  • Ai元人文随想:守护时光的印记
  • 浅谈模拟系列算法
  • 第三十六篇
  • Ai元人文随想:三值纠缠中的人文关怀
  • R语言实现多组样本两两t检验的完整教程
  • 实用指南:TensorFlow深度学习实战(40)——图神经网络(GNN)
  • 2023QDEZ男人八题赛后总结
  • 学习差的孩子,有必要用学习机吗?
  • CSP-S2023游记
  • 2025苏州驾驶证培训推荐榜:摩托车驾驶证培训、A2驾驶证培训、大车A1驾驶证培训、大车B2驾驶证培训,省心学车选这些
  • 2025佛山钢管厂家推荐榜:防腐钢管、大口径钢管、螺旋钢管工厂采购选型不踩坑
  • 不谈离散数学基本定理
  • 现代Linux网络命令简介
  • 深谈王书童变换
  • 众所周知,高中课内物理需要解微分方程
  • 语文诗歌赏析好题集萃(纯纯的学术向)
  • 11.7模拟赛
  • code first 常用命令
  • 动态规划学习/复习笔记
  • 系统设计与分布式算法实战指南
  • SDOI 2024游记兼退役游记
  • STM32G474单片机开发入门(六)定时器TIMER详解及实战含源码 - 教程
  • openEuler 22.03 LTS 在 VMware 虚拟机环境下的 CPU 与内存性能基准测试及分析
  • 某头部公募基金云原生转型实践:基于 KubeSphere 的多集群异构管理之路
  • 布谷鸟过滤器详解:从原理到Spring Boot实战
  • 让 Agentic AI 落地到“最后一公里”,GitHub Universe 25 新品解码
  • openEuler 云原生实战:部署高性能 Redis 集群与压测分析