#2569

Handling Sum Queries After Update

Hard
ArraySegment TreeSegment TreeLazy Propagation
LeetCode ↗

Approaches

Brute ForceOptimal
Complexity Comparison
Brute ForceOptimal Solution
Time
O(n²)
O(log n) per query
Space
O(1)
O(n)
💡

Intuition

Time O(log n) per querySpace O(n)

Using a lazy segment tree allows us to efficiently handle updates and queries in logarithmic time. This is crucial for large inputs where brute force would be too slow.

⚙️

Algorithm

4 steps
  1. 1Step 1: Build a lazy segment tree to manage the flips and updates efficiently.
  2. 2Step 2: For type 1 queries, mark the range for flipping in the segment tree.
  3. 3Step 3: For type 2 queries, propagate the updates through the segment tree to adjust nums2.
  4. 4Step 4: For type 3 queries, calculate the sum of nums2 using the segment tree.
solution.py59 lines
1class SegmentTree:
2    def __init__(self, n):
3        self.n = n
4        self.tree = [0] * (4 * n)
5        self.lazy = [0] * (4 * n)
6
7    def update(self, l, r, val, node=1, start=0, end=None):
8        if end is None:
9            end = self.n - 1
10        if self.lazy[node] != 0:
11            self.tree[node] ^= self.lazy[node]
12            if start != end:
13                self.lazy[node * 2] ^= self.lazy[node]
14                self.lazy[node * 2 + 1] ^= self.lazy[node]
15            self.lazy[node] = 0
16        if start > r or end < l:
17            return
18        if start >= l and end <= r:
19            self.tree[node] ^= val
20            if start != end:
21                self.lazy[node * 2] ^= val
22                self.lazy[node * 2 + 1] ^= val
23            return
24        mid = (start + end) // 2
25        self.update(l, r, val, node * 2, start, mid)
26        self.update(l, r, val, node * 2 + 1, mid + 1, end)
27        self.tree[node] = self.tree[node * 2] + self.tree[node * 2 + 1]
28
29    def query(self, idx, node=1, start=0, end=None):
30        if end is None:
31            end = self.n - 1
32        if self.lazy[node] != 0:
33            self.tree[node] ^= self.lazy[node]
34            if start != end:
35                self.lazy[node * 2] ^= self.lazy[node]
36                self.lazy[node * 2 + 1] ^= self.lazy[node]
37            self.lazy[node] = 0
38        if start == end:
39            return self.tree[node]
40        mid = (start + end) // 2
41        if idx <= mid:
42            return self.query(idx, node * 2, start, mid)
43        else:
44            return self.query(idx, node * 2 + 1, mid + 1, end)
45
46def handleQueries(nums1, nums2, queries):
47    n = len(nums1)
48    seg_tree = SegmentTree(n)
49    results = []
50    for query in queries:
51        if query[0] == 1:
52            seg_tree.update(query[1], query[2], 1)
53        elif query[0] == 2:
54            p = query[1]
55            for i in range(n):
56                nums2[i] += seg_tree.query(i) * p
57        elif query[0] == 3:
58            results.append(sum(nums2))
59    return results

Complexity note: The segment tree allows us to perform updates and queries in logarithmic time, making it efficient for large inputs.

  • 1Using a segment tree can significantly reduce the time complexity for range updates and queries.
  • 2Understanding lazy propagation in segment trees is crucial for optimizing updates.

Solutions and explanations are original Tejav content. Problem titles © LeetCode — use the LeetCode button above for the full problem statement.