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

LeetCode 每日一题笔记 日期:2026.04.09 题目:3655.区间乘法查询后的异或二

LeetCode 每日一题笔记

0. 前言

  • 日期:2026.04.09
  • 题目:3655.区间乘法查询后的异或二
  • 难度:困难
  • 标签:数组 根号分治 乘法差分 快速幂

1. 题目理解

问题描述
给你一个长度为 n 的整数数组 nums 和一个大小为 q 的二维整数数组 queries,其中 queries[i] = [li, ri, ki, vi]。
对于每个查询,需要按以下步骤依次执行操作:
设定 idx = li。
当 idx <= ri 时:
更新:nums[idx] = (nums[idx] * vi) % (10^9 + 7)。
将 idx += ki。
在处理完所有查询后,返回数组 nums 中所有元素的按位异或结果。

示例

输入: nums = [1,1,1], queries = [[0,2,1,4]]
输出: 4
解释:
唯一的查询 [0, 2, 1, 4] 将下标 0 到下标 2 的每个元素乘以 4。
数组从 [1, 1, 1] 变为 [4, 4, 4]。
所有元素的异或为 4 ^ 4 ^ 4 = 4。

2. 解题思路

核心观察

  • 直接暴力处理所有查询时间复杂度过高,需根据步长 k 的大小分治处理;
  • 步长 k 较小时(如 k < √q),查询覆盖的元素多但同余类集中,适合用乘法差分 + 逆元批量处理;
  • 步长 k 较大时(如 k ≥ √q),单次查询覆盖的元素少,直接暴力更高效;
  • 模运算下乘法的逆操作需用快速幂求逆元(费马小定理,因 MOD=1e9+7 是质数);
  • 阈值取 √q 可平衡两类操作的时间复杂度。

算法步骤

  1. 确定分块阈值:B = √q + 1,将查询按步长 k 分为小步长(k < B)和大步长(k ≥ B);
  2. 分组存储小步长查询:将 k < B 的查询按 k 分组;
  3. 处理大步长查询:直接暴力遍历,对每个符合条件的元素乘 vi 取模;
  4. 处理小步长查询
    • 对每个小 k,再按l % k分为同余类(步长 k 时,起始位置模 k 相同的元素在同一序列);
    • 对每个同余类,若仅一个查询则直接暴力,否则用乘法差分数组
      • 左端点位置乘 v;
      • 右端点下一位乘 v 的逆元;
    • 计算前缀积,将结果应用到原数组;
  5. 计算最终异或:遍历数组,所有元素异或得到结果。

3. 代码实现

classSolution{privatestaticfinalintMOD=1_000_000_007;publicintxorAfterQueries(int[]nums,int[][]queries){intn=nums.length;intB=(int)Math.sqrt(queries.length)+1;List<int[]>[]groups=newArrayList[B];Arrays.setAll(groups,_->newArrayList<>());for(int[]q:queries){intl=q[0],r=q[1],k=q[2],v=q[3];if(k<B){groups[k].add(newint[]{l,r,v});}else{for(inti=l;i<=r;i+=k){nums[i]=(int)((long)nums[i]*v%MOD);}}}int[]diff=newint[n+1];for(intk=1;k<B;k++){List<int[]>g=groups[k];if(g.isEmpty()){continue;}List<int[]>[]buckets=newArrayList[k];Arrays.setAll(buckets,_->newArrayList<>());for(int[]t:g){buckets[t[0]%k].add(t);}for(intstart=0;start<k;start++){List<int[]>bucket=buckets[start];if(bucket.isEmpty()){continue;}if(bucket.size()==1){int[]t=bucket.get(0);intl=t[0],r=t[1];longv=t[2];for(inti=l;i<=r;i+=k){nums[i]=(int)((long)nums[i]*v%MOD);}continue;}intm=(n-start-1)/k+1;Arrays.fill(diff,0,m,1);for(int[]t:bucket){intl=t[0];longv=t[2];diff[l/k]=(int)((long)diff[l/k]*v%MOD);intr=(t[1]-start)/k+1;if(r<m){diff[r]=(int)((long)diff[r]*pow(v,MOD-2)%MOD);}}longmulD=1;for(inti=0;i<m;i++){mulD=mulD*diff[i]%MOD;intj=start+i*k;nums[j]=(int)((long)nums[j]*mulD%MOD);}}}intans=0;for(intx:nums){ans^=x;}returnans;}privatelongpow(longx,intn){longres=1;for(;n>0;n/=2){if(n%2>0){res=res*x%MOD;}x=x*x%MOD;}returnres;}}

4. 代码优化说明

优化点1:全局复用差分数组

仅创建一个全局差分数组diff,每次处理小步长查询时重置前 m 位为 1,避免重复创建数组,极致节省内存。

优化点2:同余类单查询直接暴力

当某个同余类的查询数仅为 1 时,跳过乘法差分的复杂逻辑,直接暴力处理,减少差分开销。

优化点3:快速幂求逆元

利用费马小定理,通过快速幂计算v^(MOD-2) % MOD得到 v 的模逆元,高效实现乘法差分的“撤销”操作。

优化点4:分块阈值平衡

阈值取√q + 1,将小步长和大步长的时间复杂度均控制在可接受范围,避免单一策略的极端情况。

5. 复杂度分析

  • 时间复杂度O(qq+nq)O(q\sqrt{q} + n\sqrt{q})O(qq+nq)

    • 大步长查询:每个查询处理元素数为O(n/k)O(n/k)O(n/k),因k>qk > \sqrt{q}k>q,总操作数为O(qq)O(q\sqrt{q})O(qq)
    • 小步长查询:最多q\sqrt{q}q个不同 k,每个 k 处理同余类的时间为O(n)O(n)O(n),总操作数为O(nq)O(n\sqrt{q})O(nq)
    • 快速幂求逆元:单次为O(log⁡MOD)O(\log MOD)O(logMOD),可忽略。
  • 空间复杂度O(n+q)O(n + \sqrt{q})O(n+q)

    • 差分数组:O(n)O(n)O(n)
    • 分组存储:最多q\sqrt{q}q个组,总空间为O(q)O(q)O(q)但分块后实际为O(q)O(\sqrt{q})O(q)量级。

6. 总结

  • 核心思路是根号分治:根据步长 k 的大小选择不同策略,平衡时间复杂度;
  • 关键技巧:小步长用乘法差分 + 逆元批量处理,大步长直接暴力;
  • 模运算下的乘法区间更新,需结合逆元实现差分的“区间乘”效果;
  • 本题是分治思想在数组操作中的经典应用,重点考察对时间复杂度的平衡能力。

关键点回顾

  1. 根号分治的阈值取q\sqrt{q}q,平衡两类操作;
  2. 小步长按同余类分组,乘法差分结合逆元实现区间乘;
  3. 大步长直接暴力,因单次查询覆盖元素少;
  4. 最终结果为所有元素的异或,需在所有查询处理完后计算。
http://www.jsqmd.com/news/675398/

相关文章:

  • 2026 论文神器榜:10 款 AI 工具让本科写作告别熬夜爆肝
  • vulhub系列-76-02-Breakout(超详细)
  • CSS如何快速获取网页上的标准色值_借助开发者工具的取色器和色彩格式转换功能
  • AI Coding的效能传导:从个体提速到组织进化
  • burpsuite-基础一
  • unity mcp接入 实现一句话生成游戏!
  • SEER‘S EYE 预言家之眼实战:集成至Dify平台构建AI Agent应用
  • Linux命令:ss
  • 从零开始:Spring Boot + MyBatis 搭建后端接口完整教程
  • Linux---信号
  • 线性代数与矩阵运算:AI世界的数学基石——从SVD到特征值分解的实战解析
  • 基于Simulink的轴向磁通电机多物理场耦合仿真​
  • NativeScript APP 开发备忘
  • GitHub 上的 CI/CD 怎么用?从 GitHub Actions 到一条可上线的流水线
  • 学Simulink——基于Simulink的电机参数在线辨识与自适应控制​
  • 我第一次做 OData 后端服务时,真正绊住我的,不是代码,而是 Cloud Foundry 里的这些基础坑
  • yolov8模型训练MOT20数据集 行人多目标跟踪计数数据集的训练及应用 如何根据mot20数据集 来实现行人目标识别,行人追踪,行人的计数
  • Linux命令:ifconfig
  • 在 Word 中,一个公式就能看出你会不会高效排版
  • LumiPixel Canvas Quest与其他开源模型的对比评测
  • 双链表详解
  • Qianfan-OCR入门指南:如何扩展自定义解析模式(如专利权利要求提取)
  • [力扣 105]二叉树前中后序遍历精讲:原理、实现与二叉树还原
  • 如何让全面战争MOD开发从繁琐变得优雅:RPFM的现代化解决方案
  • OpenClaw Web 界面集成教程|通过网页与你的 AI 智能体对话
  • iFakeLocation:你的iOS虚拟定位终极指南,三分钟学会位置模拟
  • 终极免费开源字体Bebas Neue:如何解决现代设计的标题字体难题
  • 电力设备类输电线路覆冰检测数据集 json格式 2千张
  • 智慧课堂学生专注度分析:基于cv_resnet101_face-detection_cvpr22papermogface 的试点研究
  • RexUniNLU模型安全部署指南:权限控制与数据加密