20、SQRT 分解
1、SQRT 分解介绍
2、区间查询图示
3、单元素更新图示
4、SQRT 分解实现
/**
* 通过 SQRT 分解解决
*/
@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]; // bStart 组
for (int i = bStart + 1; i < bEnd; i++) sum += blocks[i]; // [bStart + 1 ... bEnd - 1] 组
for (int i = bEnd * B; i <= r; i++) sum += data[i]; // bEnd 组
}
return sum;
}
}
5、通用 SQRT 分解
public interface Merger<E> {
E merge(E a, E b);
}
/**
* 通用 SQRT 分解
* 注意 merge 的元素可能为 null
* 注意并不是每一组的元素个数都为 B(更新操作)
* N / B, 第几组
* N % 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]); // bStart 组
for (int i = bStart + 1; i < bEnd; i++) res = merger.merge(res, blocks[i]); // [bStart + 1 ... bEnd - 1] 组
for (int i = bEnd * B; i <= r; i++) res = merger.merge(res, data[i]); // bEnd 组
}
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);
本文来自博客园,作者:lidongdongdong~,转载请注明原文链接:https://www.cnblogs.com/lidong422339/p/17315228.html