Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 192 additions & 4 deletions solution/3700-3799/3748.Count Stable Subarrays/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,32 +109,220 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3748.Co

<!-- solution:start -->

### 方法一
### 方法一: 分段计数

根据题目描述,稳定子数组的定义是不存在逆序对的子数组,即子数组中的元素是非降序排列的。因此,我们可以将数组划分为若干个非降序的段,用一个数组 $\text{seg}$ 来记录每个段的起始位置。同时,我们还需要一个前缀和数组 $\text{text{s}}$ 来记录每个段内稳定子数组的数量。

然后,对于每个查询 $[l, r]$,可能存在 $3$ 种情况:

1. 查询区间 $[l, r]$ 完全包含在某个段内,此时稳定子数组的数量可以直接通过公式计算得到,数量为 $\frac{(k + 1) \cdot k}{2}$,其中 $k = r - l + 1$。
2. 查询区间 $[l, r]$ 跨越了多个段,此时我们需要分别计算左侧不完整段、右侧不完整段和中间完整段的稳定子数组数量,然后将它们相加得到最终结果。

时间复杂度为 $O((n + q) \log n)$,其中 $n$ 是数组的长度,$q$ 是查询的数量。空间复杂度为 $O(n)$。

<!-- tabs:start -->

#### Python3

```python

class Solution:
def countStableSubarrays(
self, nums: List[int], queries: List[List[int]]
) -> List[int]:
s = [0]
l, n = 0, len(nums)
seg = []
for r, x in enumerate(nums):
if r == n - 1 or x > nums[r + 1]:
seg.append(l)
k = r - l + 1
s.append(s[-1] + (1 + k) * k // 2)
l = r + 1
ans = []
for l, r in queries:
i = bisect_right(seg, l)
j = bisect_right(seg, r) - 1
if i > j:
k = r - l + 1
ans.append((1 + k) * k // 2)
else:
a = seg[i] - l
b = r - seg[j] + 1
ans.append((1 + a) * a // 2 + s[j] - s[i] + (1 + b) * b // 2)
return ans
```

#### Java

```java

class Solution {
public long[] countStableSubarrays(int[] nums, int[][] queries) {
List<Integer> seg = new ArrayList<>();
List<Long> s = new ArrayList<>();
s.add(0L);

int l = 0;
int n = nums.length;
for (int r = 0; r < n; r++) {
if (r == n - 1 || nums[r] > nums[r + 1]) {
seg.add(l);
int k = r - l + 1;
s.add(s.getLast() + (long) k * (k + 1) / 2);
l = r + 1;
}
}

long[] ans = new long[queries.length];
for (int q = 0; q < queries.length; q++) {
int left = queries[q][0];
int right = queries[q][1];

int i = upperBound(seg, left);
int j = upperBound(seg, right) - 1;

if (i > j) {
int k = right - left + 1;
ans[q] = (long) k * (k + 1) / 2;
} else {
int a = seg.get(i) - left;
int b = right - seg.get(j) + 1;
ans[q] = (long) a * (a + 1) / 2 + s.get(j) - s.get(i) + (long) b * (b + 1) / 2;
}
}
return ans;
}

private int upperBound(List<Integer> list, int target) {
int l = 0, r = list.size();
while (l < r) {
int mid = (l + r) >> 1;
if (list.get(mid) > target) {
r = mid;
} else {
l = mid + 1;
}
}
return l;
}
}
```

#### C++

```cpp

class Solution {
public:
vector<long long> countStableSubarrays(vector<int>& nums, vector<vector<int>>& queries) {
int n = nums.size();
vector<int> seg;
vector<long long> s = {0};

int l = 0;
for (int r = 0; r < n; ++r) {
if (r == n - 1 || nums[r] > nums[r + 1]) {
seg.push_back(l);
long long k = r - l + 1;
s.push_back(s.back() + k * (k + 1) / 2);
l = r + 1;
}
}

vector<long long> ans;
for (auto& q : queries) {
int left = q[0], right = q[1];

int i = upper_bound(seg.begin(), seg.end(), left) - seg.begin();
int j = upper_bound(seg.begin(), seg.end(), right) - seg.begin() - 1;

if (i > j) {
long long k = right - left + 1;
ans.push_back(k * (k + 1) / 2);
} else {
long long a = seg[i] - left;
long long b = right - seg[j] + 1;
ans.push_back(a * (a + 1) / 2 + s[j] - s[i] + b * (b + 1) / 2);
}
}

return ans;
}
};
```

#### Go

```go
func countStableSubarrays(nums []int, queries [][]int) []int64 {
n := len(nums)
seg := []int{}
s := []int64{0}

l := 0
for r := 0; r < n; r++ {
if r == n-1 || nums[r] > nums[r+1] {
seg = append(seg, l)
k := int64(r - l + 1)
s = append(s, s[len(s)-1]+k*(k+1)/2)
l = r + 1
}
}

ans := make([]int64, len(queries))
for idx, q := range queries {
left, right := q[0], q[1]

i := sort.SearchInts(seg, left+1)
j := sort.SearchInts(seg, right+1) - 1

if i > j {
k := int64(right - left + 1)
ans[idx] = k * (k + 1) / 2
} else {
a := int64(seg[i] - left)
b := int64(right - seg[j] + 1)
ans[idx] = a*(a+1)/2 + s[j] - s[i] + b*(b+1)/2
}
}

return ans
}
```

#### TypeScript

```ts
function countStableSubarrays(nums: number[], queries: number[][]): number[] {
const n = nums.length;
const seg: number[] = [];
const s: number[] = [0];

let l = 0;
for (let r = 0; r < n; r++) {
if (r === n - 1 || nums[r] > nums[r + 1]) {
seg.push(l);
const k = r - l + 1;
s.push(s[s.length - 1] + (k * (k + 1)) / 2);
l = r + 1;
}
}

const ans: number[] = [];
for (const [left, right] of queries) {
const i = _.sortedIndex(seg, left + 1);
const j = _.sortedIndex(seg, right + 1) - 1;

if (i > j) {
const k = right - left + 1;
ans.push((k * (k + 1)) / 2);
} else {
const a = seg[i] - left;
const b = right - seg[j] + 1;
ans.push((a * (a + 1)) / 2 + s[j] - s[i] + (b * (b + 1)) / 2);
}
}

return ans;
}
```

<!-- tabs:end -->
Expand Down
Loading