publicclassSolution { publicintRangeSum(int[] nums, int n, int left, int right) { constint MODULO = 1000000007;
int sumsLength = n * (n + 1) / 2; int[] sums = newint[sumsLength]; int index = 0; for (int i = 0; i < n; i++) { int sum = 0; for (int j = i; j < n; j++) { sum += nums[j]; sums[index++] = sum; } }
Array.Sort(sums); int ans = 0; for (int i = left - 1; i < right; i++) { ans = (ans + sums[i]) % MODULO; }
classSolution { public: intrangeSum(vector<int>& nums, int n, int left, int right){ constint MODULO = 1000000007; int sumsLength = n * (n + 1) / 2; auto sums = vector <int> (sumsLength); int index = 0; for (int i = 0; i < n; i++) { int sum = 0; for (int j = i; j < n; j++) { sum += nums[j]; sums[index++] = sum; } } sort(sums.begin(), sums.end()); int ans = 0; for (int i = left - 1; i < right; i++) { ans = (ans + sums[i]) % MODULO; } return ans; } };
第二步考虑最小的 k 个子数组的和当中剩下的等于 num 的子数组的和,这些子数组的和之和等于 num} \times (k-\textit{count})。在第一步计算得到的 sum 的基础上令 sum}=\textit{sum}+\textit{num} \times (k-\textit{count}),则 sum 的值即为所有的子数组的和当中的最小的 k 个元素之和。
publicclassSolution { publicintRangeSum(int[] nums, int n, int left, int right) { constint MODULO = 1000000007; int[] prefixSums = newint[n + 1]; prefixSums[0] = 0; for (int i = 0; i < n; i++) { prefixSums[i + 1] = prefixSums[i] + nums[i]; }
int[] prefixPrefixSums = newint[n + 1]; prefixPrefixSums[0] = 0; for (int i = 0; i < n; i++) { prefixPrefixSums[i + 1] = prefixPrefixSums[i] + prefixSums[i + 1]; }
return (GetSum(prefixSums, prefixPrefixSums, n, right) - GetSum(prefixSums, prefixPrefixSums, n, left - 1)) % MODULO; }
publicintGetSum(int[] prefixSums, int[] prefixPrefixSums, int n, int k) { int num = GetKth(prefixSums, n, k); int sum = 0; int count = 0; for (int i = 0, j = 1; i < n; i++) { while (j <= n && prefixSums[j] - prefixSums[i] < num) { j++; }
publicintGetKth(int[] prefixSums, int n, int k) { int low = 0, high = prefixSums[n]; while (low < high) { int mid = (high - low) / 2 + low; int count = GetCount(prefixSums, n, mid); if (count < k) { low = mid + 1; } else { high = mid; } } return low; }
publicintGetCount(int[] prefixSums, int n, int x) { int count = 0; for (int i = 0, j = 1; i < n; i++) { while (j <= n && prefixSums[j] - prefixSums[i] <= x) { j++; }
intrangeSum(vector<int>& nums, int n, int left, int right){ vector<int> prefixSums = vector<int>(n + 1); prefixSums[0] = 0; for (int i = 0; i < n; i++) { prefixSums[i + 1] = prefixSums[i] + nums[i]; } vector<int> prefixPrefixSums = vector<int>(n + 1); prefixPrefixSums[0] = 0; for (int i = 0; i < n; i++) { prefixPrefixSums[i + 1] = prefixPrefixSums[i] + prefixSums[i + 1]; } return (getSum(prefixSums, prefixPrefixSums, n, right) - getSum(prefixSums, prefixPrefixSums, n, left - 1)) % MODULO; }
intgetSum(vector<int>& prefixSums, vector<int>& prefixPrefixSums, int n, int k){ int num = getKth(prefixSums, n, k); int sum = 0; int count = 0; for (int i = 0, j = 1; i < n; i++) { while (j <= n && prefixSums[j] - prefixSums[i] < num) { j++; } j--; sum += prefixPrefixSums[j] - prefixPrefixSums[i] - prefixSums[i] * (j - i); sum %= MODULO; count += j - i; } sum += num * (k - count); return sum; }
intgetKth(vector<int>& prefixSums, int n, int k){ int low = 0, high = prefixSums[n]; while (low < high) { int mid = (high - low) / 2 + low; int count = getCount(prefixSums, n, mid); if (count < k) { low = mid + 1; } else { high = mid; } } return low; }
intgetCount(vector<int>& prefixSums, int n, int x){ int count = 0; for (int i = 0, j = 1; i < n; i++) { while (j <= n && prefixSums[j] - prefixSums[i] <= x) { j++; } j--; count += j - i; } return count; } };