Copy class Solution {
private static class TreeNode {
int start, end, sum;
TreeNode left, right;
TreeNode(int start, int end, int sum, TreeNode left, TreeNode right) {
this.start = start;
this.end = end;
this.sum = sum;
this.left = left;
this.right = right;
}
}
// 这利用10001而不用10000是为了避免query时候对于0会出现负数
private final int OFFSET = 10001;
private TreeNode root;
private TreeNode construct(int[] arr, int start, int end) {
if (start == end) {
return new TreeNode(start, start, arr[start], null, null);
}
int mid = (start + end) / 2;
TreeNode left = construct(arr, start, mid);
TreeNode right = construct(arr, mid + 1, end);
return new TreeNode(start, end, left.sum + right.sum, left, right);
}
// update的时候需要注意不是替换当前val,而是需要加上,因为需要处理重复数字
private void update(TreeNode root, int index, int val) {
if (root.start == root.end && root.start == index) {
root.sum += val;
return;
}
int mid = (root.start + root.end) / 2;
if (index <= mid) update(root.left, index, val);
else update(root.right, index, val);
root.sum = root.left.sum + root.right.sum;
}
private int query(TreeNode root, int start, int end) {
if (root.start == start && root.end == end) {
return root.sum;
}
int mid = (root.start + root.end) / 2;
if (end <= mid) {
return query(root.left, start, end);
} else if (start > mid) {
return query(root.right, start, end);
} else {
return query(root.left, start, mid) + query(root.right, mid + 1, end);
}
}
public List<Integer> countSmaller(int[] nums) {
// 本来是-1e4到1e4范围,向右移动1e4 OFFSET
int[] arr = new int[20002];
// 先新建一个全部为0的线段树
this.root = construct(arr, 0, arr.length - 1);
int MIN = 0;
List<Integer> res = new ArrayList<>();
// 从右往左,先query所有小于当前num的个数,然后加入当前num,这样就只会考虑到num右边的数字
for (int i = nums.length - 1; i >= 0; --i) {
res.add(query(this.root, MIN, nums[i] - 1 + OFFSET));
update(this.root, nums[i] + OFFSET, 1);
}
Collections.reverse(res);
return res;
}
}