内容来自刘宇波老师算法与数据结构体系课
1、SQRT 分解介绍

2、区间查询图示

3、单元素更新图示

4、SQRT 分解实现
307 - 区域和检索 - 数组可修改
| |
| |
| |
| @SuppressWarnings("all") |
| public class NumArray { |
| |
| private int[] data; |
| private int[] blocks; |
| private int N; |
| private int B; |
| private int Bn; |
| |
| public NumArray(int[] nums) { |
| N = nums.length; |
| if (N == 0) return; |
| |
| B = (int) Math.sqrt(N); |
| Bn = N / B + (N % B != 0 ? 1 : 0); |
| |
| data = Arrays.copyOf(nums, N); |
| blocks = new int[Bn]; |
| for (int i = 0; i < N; i++) blocks[i / B] += data[i]; |
| } |
| |
| public void update(int index, int val) { |
| if (index < 0 || index >= N) return; |
| int diff = val - data[index]; |
| data[index] = val; |
| blocks[index / B] += diff; |
| } |
| |
| public int sumRange(int l, int r) { |
| if (l < 0 || l >= N || r < 0 || r >= N || l > r) return 0; |
| |
| int sum = 0; |
| int bStart = l / B; |
| int bEnd = r / B; |
| |
| if (Math.abs(bStart - bEnd) <= 1) { |
| for (int i = l; i <= r; i++) sum += data[i]; |
| } else { |
| for (int i = l; i < (bStart + 1) * B; i++) sum += data[i]; |
| for (int i = bStart + 1; i < bEnd; i++) sum += blocks[i]; |
| for (int i = bEnd * B; i <= r; i++) sum += data[i]; |
| } |
| |
| return sum; |
| } |
| } |
5、通用 SQRT 分解
| public interface Merger<E> { |
| |
| E merge(E a, E b); |
| |
| } |
| |
| |
| |
| |
| |
| |
| |
| public class SQRTDecomposition<E> { |
| |
| private E[] data; |
| private E[] blocks; |
| private int N; |
| private int B; |
| private int Bn; |
| private Merger<E> merger; |
| |
| public SQRTDecomposition(E[] arr, Merger<E> merger) { |
| if (arr.length == 0) return; |
| this.merger = merger; |
| |
| N = arr.length; |
| B = (int) Math.sqrt(N); |
| Bn = N / B + (N % B != 0 ? 1 : 0); |
| |
| data = Arrays.copyOf(arr, N); |
| blocks = (E[]) new Object[Bn]; |
| buildBlocks(); |
| } |
| |
| private void buildBlocks() { |
| for (int i = 0; i < N; i++) { |
| if (i % B == 0) blocks[i / B] = data[i]; |
| else blocks[i / B] = merger.merge(blocks[i / B], data[i]); |
| } |
| } |
| |
| public void update(int index, E val) { |
| if (index < 0 || index >= N) return; |
| data[index] = val; |
| |
| int b = index / B; |
| blocks[b] = data[b * B]; |
| for (int i = b * B + 1; i < Math.min((b + 1) * B, N); i++) blocks[b] = merger.merge(blocks[b], data[i]); |
| } |
| |
| public E query(int l, int r) { |
| if (l < 0 || l >= N || r < 0 || r >= N || l > r) return null; |
| |
| int bStart = l / B; |
| int bEnd = r / B; |
| |
| E res = data[l]; |
| if (Math.abs(bStart - bEnd) <= 1) { |
| for (int i = l + 1; i <= r; i++) res = merger.merge(res, data[i]); |
| } else { |
| for (int i = l + 1; i < (bStart + 1) * B; i++) res = merger.merge(res, data[i]); |
| for (int i = bStart + 1; i < bEnd; i++) res = merger.merge(res, blocks[i]); |
| for (int i = bEnd * B; i <= r; i++) res = merger.merge(res, data[i]); |
| } |
| |
| return res; |
| } |
| } |
| Integer[] nums = {-2, 0, 3, -5, 2, -1}; |
| SQRTDecomposition<Integer> sumSQRT = new SQRTDecomposition<>(nums, Integer::sum); |
| SQRTDecomposition<Integer> maxSQRT = new SQRTDecomposition<>(nums, Math::max); |
| SQRTDecomposition<Integer> minSQRT = new SQRTDecomposition<>(nums, Math::min); |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步