
题目描述
有一条无限长的数轴,原点在 0 处,沿着 x 轴 正 方向无限延伸。
给你一个二维数组 queries ,它包含两种操作:
- 操作类型 1 :
queries[i] = [1, x] 。在距离原点 x 处建一个障碍物。数据保证当操作执行的时候,位置 x 处 没有 任何障碍物。 - 操作类型 2 :
queries[i] = [2, x, sz] 。判断在数轴范围 [0, x] 内是否可以放置一个长度为 sz 的物块,这个物块需要 完全 放置在范围 [0, x] 内。如果物块与任何障碍物有重合,那么这个物块 不能 被放置,但物块可以与障碍物刚好接触。注意,你只是进行查询,并 不是 真的放置这个物块。每个查询都是相互独立的。
请你返回一个 boolean 数组results ,如果第 i 个操作类型 2 的操作你可以放置物块,那么 results[i] 为 true ,否则为 false 。
示例 1:
输入:queries = [[1,2],[2,3,3],[2,3,1],[2,2,2]]
输出:[false,true,true]
解释:

查询 0 ,在 x = 2 处放置一个障碍物。在 x = 3 之前任何大小不超过 2 的物块都可以被放置。
示例 2:
输入:queries = [[1,7],[2,7,6],[1,2],[2,7,5],[2,7,6]]
输出:[true,true,false]
解释:

- 查询 0 在
x = 7 处放置一个障碍物。在 x = 7 之前任何大小不超过 7 的物块都可以被放置。 - 查询 2 在
x = 2 处放置一个障碍物。现在,在 x = 7 之前任何大小不超过 5 的物块可以被放置,x = 2 之前任何大小不超过 2 的物块可以被放置。
提示:
1 <= queries.length <= 15 * 104 2 <= queries[i].length <= 3 1 <= queries[i][0] <= 2 1 <= x, sz <= min(5 * 104, 3 * queries.length) - 输入保证操作 1 中,
x 处不会有障碍物。 - 输入保证至少有一个操作类型 2 。
解法
方法一:树状数组 + 有序集合
思考
障碍只增不减,询问某前缀内能否放下长 \(sz\) 的块。在线对每个询问扫空隙是 \(O(q^2)\)。
倒序处理可把「插入障碍」变成「删除障碍」,删除只会使空隙变大。树状数组维护「以某坐标为右端的空隙」的前缀最大值。
先把全部障碍(加哨兵)放进有序集合并写入空隙,再倒序:询问时看 \(x\) 左侧最大空隙与尾巴 \(x-pre\);删除时把后继空隙更新为 \(nxt-pre\)。答案再反转回原序。
障碍物只会增加,因此可以离线倒序处理询问,将「加入障碍物」转化为「删除障碍物」。删除后相邻空隙只会变大,而树状数组可以高效维护前缀最大值。
我们先将所有障碍物放入有序集合,并在两端加入哨兵 \(0\) 和 \(m+1\)(\(m\) 为出现过的最大坐标)。对每一对相邻障碍物 \(x_1, x_2\),在树状数组的 \(x_2\) 位置更新空隙长度 \(x_2 - x_1\)。
然后倒序遍历询问:
- 类型 \(2\):找到不超过 \(x\) 的最后一个障碍物 \(pre\)。若 \([0, pre]\) 内的最大空隙或尾部落在 \((pre, x]\) 的空隙不小于 \(sz\),则可以放置物块。
- 类型 \(1\):删除障碍物 \(x\),并将后继 \(nxt\) 处的空隙更新为 \(nxt - pre\)。
时间复杂度 \(O(q \times \log m)\),空间复杂度 \(O(m)\)。其中 \(q\) 是询问数,\(m\) 是坐标的最大值。
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 | class BinaryIndexedTree:
def __init__(self, n: int):
self.n = n
self.c = [0] * (n + 1)
def update(self, x: int, v: int):
while x <= self.n:
self.c[x] = max(self.c[x], v)
x += x & -x
def query(self, x: int) -> int:
mx = 0
while x:
mx = max(mx, self.c[x])
x -= x & -x
return mx
class Solution:
def getResults(self, queries: List[List[int]]) -> List[bool]:
m = max(q[1] for q in queries)
sl = SortedList([0, m + 1])
for q in queries:
if q[0] == 1:
sl.add(q[1])
tree = BinaryIndexedTree(m + 1)
for x1, x2 in pairwise(sl):
tree.update(x2, x2 - x1)
ans = []
for q in reversed(queries):
x = q[1]
if q[0] == 1:
i = sl.index(x)
tree.update(sl[i + 1], sl[i + 1] - sl[i - 1])
sl.remove(x)
else:
i = sl.bisect_right(x)
pre = sl[i - 1]
ans.append(tree.query(pre) >= q[2] or x - pre >= q[2])
return ans[::-1]
|
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
64
65 | class BinaryIndexedTree {
private int n;
private int[] c;
public BinaryIndexedTree(int n) {
this.n = n;
c = new int[n + 1];
}
public void update(int x, int v) {
while (x <= n) {
c[x] = Math.max(c[x], v);
x += x & -x;
}
}
public int query(int x) {
int mx = 0;
while (x > 0) {
mx = Math.max(mx, c[x]);
x -= x & -x;
}
return mx;
}
}
class Solution {
public List<Boolean> getResults(int[][] queries) {
int m = 0;
for (int[] q : queries) {
m = Math.max(m, q[1]);
}
TreeSet<Integer> ts = new TreeSet<>();
ts.add(0);
ts.add(m + 1);
for (int[] q : queries) {
if (q[0] == 1) {
ts.add(q[1]);
}
}
BinaryIndexedTree tree = new BinaryIndexedTree(m + 1);
int pre = 0;
for (int x : ts) {
if (x > 0) {
tree.update(x, x - pre);
}
pre = x;
}
List<Boolean> ans = new ArrayList<>();
for (int i = queries.length - 1; i >= 0; --i) {
int[] q = queries[i];
int x = q[1];
if (q[0] == 1) {
int nxt = ts.higher(x);
tree.update(nxt, nxt - ts.lower(x));
ts.remove(x);
} else {
int p = ts.floor(x);
ans.add(tree.query(p) >= q[2] || x - p >= q[2]);
}
}
Collections.reverse(ans);
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
64
65 | class BinaryIndexedTree {
private:
int n;
vector<int> c;
public:
BinaryIndexedTree(int n) {
this->n = n;
c.resize(n + 1);
}
void update(int x, int v) {
while (x <= n) {
c[x] = max(c[x], v);
x += x & -x;
}
}
int query(int x) {
int mx = 0;
while (x > 0) {
mx = max(mx, c[x]);
x -= x & -x;
}
return mx;
}
};
class Solution {
public:
vector<bool> getResults(vector<vector<int>>& queries) {
int m = 0;
for (auto& q : queries) {
m = max(m, q[1]);
}
set<int> ts{0, m + 1};
for (auto& q : queries) {
if (q[0] == 1) {
ts.insert(q[1]);
}
}
BinaryIndexedTree tree(m + 1);
int pre = 0;
for (int x : ts) {
if (x) {
tree.update(x, x - pre);
}
pre = x;
}
vector<bool> ans;
for (int i = queries.size() - 1; i >= 0; --i) {
int x = queries[i][1];
if (queries[i][0] == 1) {
auto it = ts.find(x);
tree.update(*next(it), *next(it) - *prev(it));
ts.erase(it);
} else {
auto it = prev(ts.upper_bound(x));
ans.push_back(tree.query(*it) >= queries[i][2] || x - *it >= queries[i][2]);
}
}
ranges::reverse(ans);
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
64
65 | func getResults(queries [][]int) []bool {
m := 0
for _, q := range queries {
m = max(m, q[1])
}
st := redblacktree.New[int, struct{}]()
st.Put(0, struct{}{})
st.Put(m+1, struct{}{})
for _, q := range queries {
if q[0] == 1 {
st.Put(q[1], struct{}{})
}
}
tree := newBinaryIndexedTree(m + 1)
it := st.Iterator()
it.Next()
pre := it.Key()
for it.Next() {
x := it.Key()
tree.update(x, x-pre)
pre = x
}
ans := []bool{}
for i := len(queries) - 1; i >= 0; i-- {
q := queries[i]
x := q[1]
if q[0] == 1 {
nxt, _ := st.Ceiling(x + 1)
p, _ := st.Floor(x - 1)
st.Remove(x)
tree.update(nxt.Key, nxt.Key-p.Key)
} else {
node, _ := st.Floor(x)
p := node.Key
ans = append(ans, tree.query(p) >= q[2] || x-p >= q[2])
}
}
slices.Reverse(ans)
return ans
}
type binaryIndexedTree struct {
n int
c []int
}
func newBinaryIndexedTree(n int) *binaryIndexedTree {
return &binaryIndexedTree{n: n, c: make([]int, n+1)}
}
func (t *binaryIndexedTree) update(x, v int) {
for x <= t.n {
t.c[x] = max(t.c[x], v)
x += x & -x
}
}
func (t *binaryIndexedTree) query(x int) int {
mx := 0
for x > 0 {
mx = max(mx, t.c[x])
x -= x & -x
}
return mx
}
|