Skip to content

Commit fc9d827

Browse files
committed
git
1 parent 3fd1a85 commit fc9d827

File tree

3 files changed

+186
-0
lines changed

3 files changed

+186
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
class Solution {
2+
public:
3+
vector<int> pathExistenceQueries(int n, vector<int>& nums, int maxDiff,
4+
vector<vector<int>>& queries) {
5+
vector<int> ans;
6+
vector<int> sortedNums;
7+
vector<int> indexMap(n);
8+
vector<pair<int, int>> sortedNumAndIndexes;
9+
10+
for (int i = 0; i < n; ++i)
11+
sortedNumAndIndexes.emplace_back(nums[i], i);
12+
13+
ranges::sort(sortedNumAndIndexes);
14+
15+
for (int i = 0; i < n; ++i) {
16+
const auto& [num, sortedIndex] = sortedNumAndIndexes[i];
17+
sortedNums.push_back(num);
18+
indexMap[sortedIndex] = i;
19+
}
20+
21+
const int maxLevel = std::bit_width(static_cast<unsigned>(n)) + 1;
22+
// jump[i][j] := the index of the j-th ancestor of i
23+
vector<vector<int>> jump(n, vector<int>(maxLevel));
24+
25+
int right = 0;
26+
for (int i = 0; i < n; ++i) {
27+
while (right + 1 < n && sortedNums[right + 1] - sortedNums[i] <= maxDiff)
28+
++right;
29+
jump[i][0] = right;
30+
}
31+
32+
for (int level = 1; level < maxLevel; ++level)
33+
for (int i = 0; i < n; ++i) {
34+
const int prevJump = jump[i][level - 1];
35+
jump[i][level] = jump[prevJump][level - 1];
36+
}
37+
38+
for (const vector<int>& query : queries) {
39+
const int u = query[0];
40+
const int v = query[1];
41+
const int uIndex = indexMap[u];
42+
const int vIndex = indexMap[v];
43+
const int start = min(uIndex, vIndex);
44+
const int end = max(uIndex, vIndex);
45+
const int res = minJumps(jump, start, end, maxLevel - 1);
46+
ans.push_back(res == INT_MAX ? -1 : res);
47+
}
48+
49+
return ans;
50+
}
51+
52+
private:
53+
// Returns the minimum number of jumps from `start` to `end` using binary
54+
// lifting.
55+
int minJumps(const vector<vector<int>>& jump, int start, int end, int level) {
56+
if (start == end)
57+
return 0;
58+
if (jump[start][0] >= end)
59+
return 1;
60+
if (jump[start][level] < end)
61+
return INT_MAX;
62+
int j = level;
63+
for (; j >= 0; --j)
64+
if (jump[start][j] < end)
65+
break;
66+
return (1 << j) + minJumps(jump, jump[start][j], end, j);
67+
}
68+
};
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
class Solution {
2+
public int[] pathExistenceQueries(int n, int[] nums, int maxDiff, int[][] queries) {
3+
int[] ans = new int[queries.length];
4+
int[] indexMap = new int[n];
5+
int[] sortedNums = new int[n];
6+
Pair<Integer, Integer>[] sortedNumAndIndexes = new Pair[n];
7+
8+
for (int i = 0; i < n; ++i)
9+
sortedNumAndIndexes[i] = new Pair<>(nums[i], i);
10+
11+
Arrays.sort(sortedNumAndIndexes, Comparator.comparingInt(Pair::getKey));
12+
13+
for (int i = 0; i < n; ++i) {
14+
final int num = sortedNumAndIndexes[i].getKey();
15+
final int sortedIndex = sortedNumAndIndexes[i].getValue();
16+
sortedNums[i] = num;
17+
indexMap[sortedIndex] = i;
18+
}
19+
20+
final int maxLevel = Integer.SIZE - Integer.numberOfLeadingZeros(n) + 1;
21+
// jump[i][j] := the index of the j-th ancestor of i
22+
int[][] jump = new int[n][maxLevel];
23+
24+
int right = 0;
25+
for (int i = 0; i < n; ++i) {
26+
while (right + 1 < n && sortedNums[right + 1] - sortedNums[i] <= maxDiff)
27+
++right;
28+
jump[i][0] = right;
29+
}
30+
31+
for (int level = 1; level < maxLevel; ++level)
32+
for (int i = 0; i < n; ++i) {
33+
final int prevJump = jump[i][level - 1];
34+
jump[i][level] = jump[prevJump][level - 1];
35+
}
36+
37+
for (int i = 0; i < queries.length; ++i) {
38+
final int u = queries[i][0];
39+
final int v = queries[i][1];
40+
final int uIndex = indexMap[u];
41+
final int vIndex = indexMap[v];
42+
final int start = Math.min(uIndex, vIndex);
43+
final int end = Math.max(uIndex, vIndex);
44+
final int res = minJumps(jump, start, end, maxLevel - 1);
45+
ans[i] = res == Integer.MAX_VALUE ? -1 : res;
46+
}
47+
48+
return ans;
49+
}
50+
51+
// Returns the minimum number of jumps from `start` to `end` using binary
52+
// lifting.
53+
private int minJumps(int[][] jump, int start, int end, int level) {
54+
if (start == end)
55+
return 0;
56+
if (jump[start][0] >= end)
57+
return 1;
58+
if (jump[start][level] < end)
59+
return Integer.MAX_VALUE;
60+
int j = level;
61+
for (; j >= 0; --j)
62+
if (jump[start][j] < end)
63+
break;
64+
return (1 << j) + minJumps(jump, jump[start][j], end, j);
65+
}
66+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
class Solution:
2+
def pathExistenceQueries(
3+
self,
4+
n: int,
5+
nums: list[int],
6+
maxDiff: int,
7+
queries: list[list[int]],
8+
) -> list[int]:
9+
sortedNumAndIndexes = sorted((num, i) for i, num in enumerate(nums))
10+
sortedNums = [num for num, _ in sortedNumAndIndexes]
11+
indexMap = {originalIndex: sortedIndex for sortedIndex,
12+
(_, originalIndex) in enumerate(sortedNumAndIndexes)}
13+
maxLevel = n.bit_length() + 1
14+
# jump[i][j] is the index of the j-th ancestor of i
15+
jump = [[0] * maxLevel for _ in range(n)]
16+
17+
right = 0
18+
for i in range(n):
19+
while right + 1 < n and sortedNums[right + 1] - sortedNums[i] <= maxDiff:
20+
right += 1
21+
jump[i][0] = right
22+
23+
for level in range(1, maxLevel):
24+
for i in range(n):
25+
prevJump = jump[i][level - 1]
26+
jump[i][level] = jump[prevJump][level - 1]
27+
28+
def minJumps(start: int, end: int, level: int) -> int:
29+
"""
30+
Returns the minimum number of jumps from `start` to `end` using binary
31+
lifting.
32+
"""
33+
if start == end:
34+
return 0
35+
if jump[start][0] >= end:
36+
return 1
37+
if jump[start][level] < end:
38+
return math.inf
39+
for j in range(level, -1, -1):
40+
if jump[start][j] < end:
41+
break
42+
return (1 << j) + minJumps(jump[start][j], end, j)
43+
44+
def minDist(u: int, v: int) -> int:
45+
uIndex = indexMap[u]
46+
vIndex = indexMap[v]
47+
start = min(uIndex, vIndex)
48+
end = max(uIndex, vIndex)
49+
res = minJumps(start, end, maxLevel - 1)
50+
return res if res < math.inf else -1
51+
52+
return [minDist(u, v) for u, v in queries]

0 commit comments

Comments
 (0)