题目描述
数组 arr
中 大于 前面和后面相邻元素的元素被称为 峰值 元素。
给你一个整数数组 nums
和一个二维整数数组 queries
。
你需要处理以下两种类型的操作:
queries[i] = [1, li, ri]
,求出子数组 nums[li..ri]
中 峰值 元素的数目。
queries[i] = [2, indexi, vali]
,将 nums[indexi]
变为 vali
。
请你返回一个数组 answer
,它依次包含每一个第一种操作的答案。
注意:
- 子数组中 第一个 和 最后一个 元素都 不是 峰值元素。
示例 1:
输入:nums = [3,1,4,2,5], queries = [[2,3,4],[1,0,4]]
输出:[0]
解释:
第一个操作:我们将 nums[3]
变为 4 ,nums
变为 [3,1,4,4,5]
。
第二个操作:[3,1,4,4,5]
中峰值元素的数目为 0 。
示例 2:
输入:nums = [4,1,4,2,1,5], queries = [[2,2,4],[1,0,2],[1,0,4]]
输出:[0,1]
解释:
第一个操作:nums[2]
变为 4 ,它已经是 4 了,所以保持不变。
第二个操作:[4,1,4]
中峰值元素的数目为 0 。
第三个操作:第二个 4 是 [4,1,4,2,1]
中的峰值元素。
提示:
3 <= nums.length <= 105
1 <= nums[i] <= 105
1 <= queries.length <= 105
queries[i][0] == 1
或者 queries[i][0] == 2
- 对于所有的
i
,都有:
queries[i][0] == 1
:0 <= queries[i][1] <= queries[i][2] <= nums.length - 1
queries[i][0] == 2
:0 <= queries[i][1] <= nums.length - 1
, 1 <= queries[i][2] <= 105
解法
方法一:树状数组
根据题目描述,对于 $0 < i < n - 1$,如果满足 $nums[i - 1] < nums[i]$ 且 $nums[i] > nums[i + 1]$,我们可以将 $nums[i]$ 视为 $1$,否则视为 $0$。这样,对于操作 $1$,即查询子数组 $nums[l..r]$ 中的峰值元素个数,相当于查询区间 $[l + 1, r - 1]$ 中 $1$ 的个数。我们可以使用树状数组来维护区间 $[1, n - 1]$ 中 $1$ 的个数。
而对于操作 $1$,即把 $nums[idx]$ 更新为 $val$,只会影响到 $idx - 1$, $idx$, $idx + 1$ 这三个位置的值,因此我们只需要更新这三个位置即可。具体地,我们可以先把这三个位置的峰值元素去掉,然后更新 $nums[idx]$ 的值,最后再把这三个位置的峰值元素加回来。
时间复杂度 $O((n + q) \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 和 $q$ 分别是数组 nums
的长度和查询数组 queries
的长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 | class BinaryIndexedTree:
__slots__ = "n", "c"
def __init__(self, n: int):
self.n = n
self.c = [0] * (n + 1)
def update(self, x: int, delta: int) -> None:
while x <= self.n:
self.c[x] += delta
x += x & -x
def query(self, x: int) -> int:
s = 0
while x:
s += self.c[x]
x -= x & -x
return s
class Solution:
def countOfPeaks(self, nums: List[int], queries: List[List[int]]) -> List[int]:
def update(i: int, val: int):
if i <= 0 or i >= n - 1:
return
if nums[i - 1] < nums[i] and nums[i] > nums[i + 1]:
tree.update(i, val)
n = len(nums)
tree = BinaryIndexedTree(n - 1)
for i in range(1, n - 1):
update(i, 1)
ans = []
for q in queries:
if q[0] == 1:
l, r = q[1] + 1, q[2] - 1
ans.append(0 if l > r else tree.query(r) - tree.query(l - 1))
else:
idx, val = q[1:]
for i in range(idx - 1, idx + 2):
update(i, -1)
nums[idx] = val
for i in range(idx - 1, idx + 2):
update(i, 1)
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 | class BinaryIndexedTree {
private int n;
private int[] c;
public BinaryIndexedTree(int n) {
this.n = n;
this.c = new int[n + 1];
}
public void update(int x, int delta) {
for (; x <= n; x += x & -x) {
c[x] += delta;
}
}
public int query(int x) {
int s = 0;
for (; x > 0; x -= x & -x) {
s += c[x];
}
return s;
}
}
class Solution {
private BinaryIndexedTree tree;
private int[] nums;
public List<Integer> countOfPeaks(int[] nums, int[][] queries) {
int n = nums.length;
this.nums = nums;
tree = new BinaryIndexedTree(n - 1);
for (int i = 1; i < n - 1; ++i) {
update(i, 1);
}
List<Integer> ans = new ArrayList<>();
for (var q : queries) {
if (q[0] == 1) {
int l = q[1] + 1, r = q[2] - 1;
ans.add(l > r ? 0 : tree.query(r) - tree.query(l - 1));
} else {
int idx = q[1], val = q[2];
for (int i = idx - 1; i <= idx + 1; ++i) {
update(i, -1);
}
nums[idx] = val;
for (int i = idx - 1; i <= idx + 1; ++i) {
update(i, 1);
}
}
}
return ans;
}
private void update(int i, int val) {
if (i <= 0 || i >= nums.length - 1) {
return;
}
if (nums[i - 1] < nums[i] && nums[i] > nums[i + 1]) {
tree.update(i, val);
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 | class BinaryIndexedTree {
private:
int n;
vector<int> c;
public:
BinaryIndexedTree(int n)
: n(n)
, c(n + 1) {}
void update(int x, int delta) {
for (; x <= n; x += x & -x) {
c[x] += delta;
}
}
int query(int x) {
int s = 0;
for (; x > 0; x -= x & -x) {
s += c[x];
}
return s;
}
};
class Solution {
public:
vector<int> countOfPeaks(vector<int>& nums, vector<vector<int>>& queries) {
int n = nums.size();
BinaryIndexedTree tree(n - 1);
auto update = [&](int i, int val) {
if (i <= 0 || i >= n - 1) {
return;
}
if (nums[i - 1] < nums[i] && nums[i] > nums[i + 1]) {
tree.update(i, val);
}
};
for (int i = 1; i < n - 1; ++i) {
update(i, 1);
}
vector<int> ans;
for (auto& q : queries) {
if (q[0] == 1) {
int l = q[1] + 1, r = q[2] - 1;
ans.push_back(l > r ? 0 : tree.query(r) - tree.query(l - 1));
} else {
int idx = q[1], val = q[2];
for (int i = idx - 1; i <= idx + 1; ++i) {
update(i, -1);
}
nums[idx] = val;
for (int i = idx - 1; i <= idx + 1; ++i) {
update(i, 1);
}
}
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 | type BinaryIndexedTree struct {
n int
c []int
}
func NewBinaryIndexedTree(n int) *BinaryIndexedTree {
return &BinaryIndexedTree{n: n, c: make([]int, n+1)}
}
func (bit *BinaryIndexedTree) update(x, delta int) {
for ; x <= bit.n; x += x & -x {
bit.c[x] += delta
}
}
func (bit *BinaryIndexedTree) query(x int) int {
s := 0
for ; x > 0; x -= x & -x {
s += bit.c[x]
}
return s
}
func countOfPeaks(nums []int, queries [][]int) (ans []int) {
n := len(nums)
tree := NewBinaryIndexedTree(n - 1)
update := func(i, val int) {
if i <= 0 || i >= n-1 {
return
}
if nums[i-1] < nums[i] && nums[i] > nums[i+1] {
tree.update(i, val)
}
}
for i := 1; i < n-1; i++ {
update(i, 1)
}
for _, q := range queries {
if q[0] == 1 {
l, r := q[1]+1, q[2]-1
t := 0
if l <= r {
t = tree.query(r) - tree.query(l-1)
}
ans = append(ans, t)
} else {
idx, val := q[1], q[2]
for i := idx - 1; i <= idx+1; i++ {
update(i, -1)
}
nums[idx] = val
for i := idx - 1; i <= idx+1; i++ {
update(i, 1)
}
}
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 | class BinaryIndexedTree {
private n: number;
private c: number[];
constructor(n: number) {
this.n = n;
this.c = Array(n + 1).fill(0);
}
update(x: number, delta: number): void {
for (; x <= this.n; x += x & -x) {
this.c[x] += delta;
}
}
query(x: number): number {
let s = 0;
for (; x > 0; x -= x & -x) {
s += this.c[x];
}
return s;
}
}
function countOfPeaks(nums: number[], queries: number[][]): number[] {
const n = nums.length;
const tree = new BinaryIndexedTree(n - 1);
const update = (i: number, val: number): void => {
if (i <= 0 || i >= n - 1) {
return;
}
if (nums[i - 1] < nums[i] && nums[i] > nums[i + 1]) {
tree.update(i, val);
}
};
for (let i = 1; i < n - 1; ++i) {
update(i, 1);
}
const ans: number[] = [];
for (const q of queries) {
if (q[0] === 1) {
const [l, r] = [q[1] + 1, q[2] - 1];
ans.push(l > r ? 0 : tree.query(r) - tree.query(l - 1));
} else {
const [idx, val] = [q[1], q[2]];
for (let i = idx - 1; i <= idx + 1; ++i) {
update(i, -1);
}
nums[idx] = val;
for (let i = idx - 1; i <= idx + 1; ++i) {
update(i, 1);
}
}
}
return ans;
}
|