package class47; import java.util.ArrayList; import java.util.Arrays; import java.util.List; // 利用只支持单点增加 + 范围查询的动态开点线段树(累加和),解决leetcode 315 public class Problem_0315_CountOfSmallerNumbersAfterSelf { public static class Node { public int sum; public Node left; public Node right; } public static class DynamicSegmentTree { public Node root; public int size; public DynamicSegmentTree(int max) { root = new Node(); size = max; } public void add(int i, int v) { add(root, 1, size, i, v); } private void add(Node c, int l, int r, int i, int v) { if (l == r) { c.sum += v; } else { int mid = (l + r) / 2; if (i <= mid) { if (c.left == null) { c.left = new Node(); } add(c.left, l, mid, i, v); } else { if (c.right == null) { c.right = new Node(); } add(c.right, mid + 1, r, i, v); } c.sum = (c.left != null ? c.left.sum : 0) + (c.right != null ? c.right.sum : 0); } } public int query(int s, int e) { return query(root, 1, size, s, e); } private int query(Node c, int l, int r, int s, int e) { if (c == null) { return 0; } if (s <= l && r <= e) { return c.sum; } int mid = (l + r) / 2; if (e <= mid) { return query(c.left, l, mid, s, e); } else if (s > mid) { return query(c.right, mid + 1, r, s, e); } else { return query(c.left, l, mid, s, e) + query(c.right, mid + 1, r, s, e); } } } public static List countSmaller(int[] nums) { List ans = new ArrayList<>(); if (nums == null || nums.length == 0) { return ans; } int n = nums.length; for (int i = 0; i < n; i++) { ans.add(0); } int[][] arr = new int[n][]; for (int i = 0; i < n; i++) { arr[i] = new int[] { nums[i], i }; } Arrays.sort(arr, (a, b) -> (a[0] - b[0])); DynamicSegmentTree dst = new DynamicSegmentTree(n); for (int[] num : arr) { ans.set(num[1], dst.query(num[1] + 1, n)); dst.add(num[1] + 1, 1); } return ans; } }