Skip to content

Commit 2dd77cb

Browse files
authored
Merge pull request #1142 from Aditi22Bansal/main
Solved leetcode problem 3161- Block Placement Queries
2 parents c222bbd + 637a2cb commit 2dd77cb

File tree

1 file changed

+253
-0
lines changed

1 file changed

+253
-0
lines changed
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
---
2+
id: fenwick-tree-solution
3+
level: Hard
4+
title: Fenwick Tree Solution
5+
sidebar_label: Fenwick Tree Solution
6+
tags:
7+
- Fenwick Tree
8+
- Data Structure
9+
- C++
10+
- Java
11+
- Python
12+
description: "This document provides solutions to a problem using the Fenwick Tree (Binary Indexed Tree) data structure, implemented in C++, Java, and Python."
13+
---
14+
15+
## Problem
16+
The problem requires efficiently processing a series of queries that involve updating and retrieving maximum values within a range. The solution uses the Fenwick Tree (Binary Indexed Tree) data structure to achieve this efficiently.
17+
18+
## Solution
19+
A Fenwick Tree is used to keep track of the maximum values in the range. Each query is processed in constant or logarithmic time, making the solution efficient for large inputs.
20+
21+
### Fenwick Tree Structure
22+
The Fenwick Tree is implemented with the following methods:
23+
- `update(int i, int val)`: Updates the tree with the value `val` at index `i`.
24+
- `get(int i)`: Retrieves the maximum value from the start to index `i`.
25+
26+
### Steps:
27+
1. **Initialization**: Initialize the Fenwick Tree and a sorted set to keep track of obstacles.
28+
2. **Update Queries**: Process update queries to add obstacles.
29+
3. **Compute Intervals**: Compute intervals between obstacles and update the tree.
30+
4. **Result Queries**: Process result queries to check if the interval length is sufficient.
31+
32+
## Code in Different Languages
33+
34+
### C++
35+
```cpp
36+
#include <iostream>
37+
#include <vector>
38+
#include <set>
39+
#include <algorithm>
40+
41+
using namespace std;
42+
43+
class FenwickTree {
44+
public:
45+
FenwickTree(int n) : vals(n + 1) {}
46+
47+
void update(int i, int val) {
48+
while (i < vals.size()) {
49+
vals[i] = max(vals[i], val);
50+
i += lowbit(i);
51+
}
52+
}
53+
54+
int get(int i) const {
55+
int res = 0;
56+
while (i > 0) {
57+
res = max(res, vals[i]);
58+
i -= lowbit(i);
59+
}
60+
return res;
61+
}
62+
63+
private:
64+
vector<int> vals;
65+
66+
static int lowbit(int i) {
67+
return i & -i;
68+
}
69+
};
70+
71+
class Solution {
72+
public:
73+
vector<bool> getResults(vector<vector<int>>& queries) {
74+
const int n = min(50000, static_cast<int>(queries.size()) * 3);
75+
vector<bool> ans;
76+
FenwickTree tree(n + 1);
77+
set<int> obstacles{0, n}; // sentinel values
78+
79+
for (const vector<int>& query : queries) {
80+
const int type = query[0];
81+
if (type == 1) {
82+
const int x = query[1];
83+
obstacles.insert(x);
84+
}
85+
}
86+
87+
for (auto it = obstacles.begin(); std::next(it) != obstacles.end(); ++it) {
88+
const int x1 = *it;
89+
const int x2 = *std::next(it);
90+
tree.update(x2, x2 - x1);
91+
}
92+
93+
for (int i = queries.size() - 1; i >= 0; --i) {
94+
const int type = queries[i][0];
95+
const int x = queries[i][1];
96+
if (type == 1) {
97+
const auto it = obstacles.find(x);
98+
if (next(it) != obstacles.end()) // x is not the last element.
99+
tree.update(*next(it), *next(it) - *prev(it));
100+
obstacles.erase(it);
101+
} else {
102+
const int sz = queries[i][2];
103+
const auto it = obstacles.upper_bound(x);
104+
const int prev = *std::prev(it);
105+
ans.push_back(tree.get(prev) >= sz || x - prev >= sz);
106+
}
107+
}
108+
109+
return {ans.rbegin(), ans.rend()};
110+
}
111+
};
112+
```
113+
### Java
114+
```java
115+
import java.util.*;
116+
117+
class FenwickTree {
118+
private int[] vals;
119+
120+
public FenwickTree(int n) {
121+
vals = new int[n + 1];
122+
}
123+
124+
public void update(int i, int val) {
125+
while (i < vals.length) {
126+
vals[i] = Math.max(vals[i], val);
127+
i += lowbit(i);
128+
}
129+
}
130+
131+
public int get(int i) {
132+
int res = 0;
133+
while (i > 0) {
134+
res = Math.max(res, vals[i]);
135+
i -= lowbit(i);
136+
}
137+
return res;
138+
}
139+
140+
private static int lowbit(int i) {
141+
return i & -i;
142+
}
143+
}
144+
145+
class Solution {
146+
public List<Boolean> getResults(int[][] queries) {
147+
final int n = Math.min(50000, queries.length * 3);
148+
List<Boolean> ans = new ArrayList<>();
149+
FenwickTree tree = new FenwickTree(n + 1);
150+
TreeSet<Integer> obstacles = new TreeSet<>(Arrays.asList(0, n)); // sentinel values
151+
152+
for (int[] query : queries) {
153+
final int type = query[0];
154+
if (type == 1) {
155+
final int x = query[1];
156+
obstacles.add(x);
157+
}
158+
}
159+
160+
Iterator<Integer> it = obstacles.iterator();
161+
int x1 = it.next();
162+
while (it.hasNext()) {
163+
final int x2 = it.next();
164+
tree.update(x2, x2 - x1);
165+
x1 = x2;
166+
}
167+
168+
for (int i = queries.length - 1; i >= 0; --i) {
169+
final int type = queries[i][0];
170+
final int x = queries[i][1];
171+
if (type == 1) {
172+
final Integer next = obstacles.higher(x);
173+
final Integer prev = obstacles.lower(x);
174+
if (next != null)
175+
tree.update(next, next - prev);
176+
obstacles.remove(x);
177+
} else {
178+
final int sz = queries[i][2];
179+
final int prev = obstacles.floor(x);
180+
ans.add(tree.get(prev) >= sz || x - prev >= sz);
181+
}
182+
}
183+
184+
Collections.reverse(ans);
185+
return ans;
186+
}
187+
}
188+
```
189+
### Python
190+
```python
191+
from sortedcontainers import SortedList
192+
from typing import List
193+
import itertools
194+
195+
class FenwickTree:
196+
def __init__(self, n: int):
197+
self.vals = [0] * (n + 1)
198+
199+
def update(self, i: int, val: int) -> None:
200+
while i < len(self.vals):
201+
self.vals[i] = max(self.vals[i], val)
202+
i += FenwickTree.lowtree(i)
203+
204+
def get(self, i: int) -> int:
205+
res = 0
206+
while i > 0:
207+
res = max(res, self.vals[i])
208+
i -= FenwickTree.lowtree(i)
209+
return res
210+
211+
@staticmethod
212+
def lowtree(i: int) -> int:
213+
return i & -i
214+
215+
class Solution:
216+
def getResults(self, queries: List[List[int]]) -> List[bool]:
217+
n = min(50000, len(queries) * 3)
218+
ans = []
219+
tree = FenwickTree(n + 1)
220+
obstacles = SortedList([0, n]) # sentinel values
221+
222+
for query in queries:
223+
type = query[0]
224+
if type == 1:
225+
x = query[1]
226+
obstacles.add(x)
227+
228+
for x1, x2 in itertools.pairwise(obstacles):
229+
tree.update(x2, x2 - x1)
230+
231+
for query in reversed(queries):
232+
type = query[0]
233+
x = query[1]
234+
if type == 1:
235+
i = obstacles.index(x)
236+
next = obstacles[i + 1]
237+
prev = obstacles[i - 1]
238+
obstacles.remove(x)
239+
tree.update(next, next - prev)
240+
else:
241+
sz = query[2]
242+
i = obstacles.bisect_right(x)
243+
prev = obstacles[i - 1]
244+
ans.append(tree.get(prev) >= sz or x - prev >= sz)
245+
246+
return ans[::-1]
247+
```
248+
249+
# Complexity Analysis
250+
## Time Complexity: $O(log N)$ for update and get methods.
251+
### Reason: Each update or get operation involves a logarithmic number of steps due to the nature of the Fenwick Tree.
252+
# Space Complexity: $O(N)$
253+
### Reason: We store values in the Fenwick Tree and maintain a sorted list of obstacles.

0 commit comments

Comments
 (0)