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
| class RangeModule {
TreeMap<Integer, Integer> ranges = new TreeMap<>(); // {l=r}
public void addRange(int left, int right) {
Integer ll = ranges.floorKey(left); // 左侧区间的左端点 ll <= left
Integer rl = ranges.floorKey(right); // 右侧区间的左端点 rl <= right
// [ll, lr) 和 [left, right) 区间重叠 ll <= left <= lr (ll < lr)
if (ll != null && ranges.get(ll) >= left) left = ll;
// [left, right) 和 [rl, rr) 区间重叠 rl <= right <= rr (rl < rr)
if (rl != null && ranges.get(rl) >= right) right = ranges.get(rl);
// 将 [left, right) 向两端扩充为合并后的区间
ranges.put(left, right);
// 迭代器删除被 [left, right) 包含的区间
var it = ranges.keySet().iterator();
while (it.hasNext()) {
int l = it.next();
int r = ranges.get(l);
if (left < l && r <= right) it.remove();
}
}
public boolean queryRange(int left, int right) {
Integer ll = ranges.floorKey(left); // 左侧区间的左端点 ll <= left
// 若 ll <= left < right <= lr,则返回 true
return ll == null ? false : right <= ranges.get(ll);
}
public void removeRange(int left, int right) {
Integer ll = ranges.lowerKey(left); // 左侧区间的左端点 ll < left
Integer rl = ranges.lowerKey(right); // 右侧区间的左端点 rl < right
if (ll != null) {
int lr = ranges.get(ll);
if (lr > right) { // 分割区间 ll < left < right < lr
ranges.put(ll, left);
ranges.put(right, lr);
} else if (lr > left) { // 分割区间 ll < left < lr <= right
ranges.put(ll, left);
}
}
if (rl != null) {
int rr = ranges.get(rl);
// 若 rl < left,则 rl == ll,之前已经分割
if (rr > right) { // 分割区间 left <= rl < right < rr
ranges.put(rl, right); // 减小区间,便于删除
ranges.put(right, rr);
}
}
// 迭代器删除被 [left, right) 包含的区间
var it = ranges.keySet().iterator();
while (it.hasNext()) {
int l = it.next();
int r = ranges.get(l);
if (left <= l && r <= right)
it.remove();
}
}
}
|