给你一个下标从 0 开始的正整数数组 heights
,其中 heights[i]
表示第 i
栋建筑的高度。
如果一个人在建筑 i
,且存在 i < j
的建筑 j
满足 heights[i] < heights[j]
,那么这个人可以移动到建筑 j
。
给你另外一个数组 queries
,其中 queries[i] = [ai, bi]
。第 i
个查询中,Alice 在建筑 ai
,Bob 在建筑 bi
。
请你能返回一个数组 ans
,其中 ans[i]
是第 i
个查询中,Alice 和 Bob 可以相遇的 最左边的建筑 。如果对于查询 i
,Alice 和 Bob 不能相遇,令 ans[i]
为 -1
。
示例 1:
```txt
输入:heights = [6,4,8,5,2,7], queries = [[0,1],[0,3],[2,4],[3,4],[2,2]]
输出:[2,5,-1,5,2]
解释:第一个查询中,Alice 和 Bob 可以移动到建筑 2 ,因为 heights[0] < heights[2] 且 heights[1] < heights[2] 。
第二个查询中,Alice 和 Bob 可以移动到建筑 5 ,因为 heights[0] < heights[5] 且 heights[3] < heights[5] 。
第三个查询中,Alice 无法与 Bob 相遇,因为 Alice 不能移动到任何其他建筑。
第四个查询中,Alice 和 Bob 可以移动到建筑 5 ,因为 heights[3] < heights[5] 且 heights[4] < heights[5] 。
第五个查询中,Alice 和 Bob 已经在同一栋建筑中。
对于 ans[i] != -1 ,ans[i] 是 Alice 和 Bob 可以相遇的建筑中最左边建筑的下标。
对于 ans[i] == -1 ,不存在 Alice 和 Bob 可以相遇的建筑。
```
示例 2:
```txt
输入:heights = [5,3,8,2,6,1,4,6], queries = [[0,7],[3,5],[5,2],[3,0],[1,6]]
输出:[7,6,-1,4,6]
解释:第一个查询中,Alice 可以直接移动到 Bob 的建筑,因为 heights[0] < heights[7] 。
第二个查询中,Alice 和 Bob 可以移动到建筑 6 ,因为 heights[3] < heights[6] 且 heights[5] < heights[6] 。
第三个查询中,Alice 无法与 Bob 相遇,因为 Bob 不能移动到任何其他建筑。
第四个查询中,Alice 和 Bob 可以移动到建筑 4 ,因为 heights[3] < heights[4] 且 heights[0] < heights[4] 。
第五个查询中,Alice 可以直接移动到 Bob 的建筑,因为 heights[1] < heights[6] 。
对于 ans[i] != -1 ,ans[i] 是 Alice 和 Bob 可以相遇的建筑中最左边建筑的下标。
对于 ans[i] == -1 ,不存在 Alice 和 Bob 可以相遇的建筑。
```
提示:
1 <= heights.length <= 5 * 10^4
1 <= heights[i] <= 10^9
1 <= queries.length <= 5 * 10^4
queries[i] = [ai, bi]
0 <= ai, bi <= heights.length - 1
找到 Alice 和 Bob 可以相遇的建筑
题目
给你一个下标从 0 开始的正整数数组 heights
,其中 heights[i]
表示第 i
栋建筑的高度。
如果一个人在建筑 i
,且存在 i < j
的建筑 j
满足 heights[i] < heights[j]
,那么这个人可以移动到建筑 j
。
给你另外一个数组 queries
,其中 queries[i] = [ai, bi]
。第 i
个查询中,Alice 在建筑 ai
,Bob 在建筑 bi
。
请你能返回一个数组 ans
,其中 ans[i]
是第 i
个查询中,Alice 和 Bob 可以相遇的 最左边的建筑 。如果对于查询 i
,Alice 和 Bob 不能相遇,令 ans[i]
为 -1
。
示例 1:
1 | 输入:heights = [6,4,8,5,2,7], queries = [[0,1],[0,3],[2,4],[3,4],[2,2]] |
示例 2:
1 | 输入:heights = [5,3,8,2,6,1,4,6], queries = [[0,7],[3,5],[5,2],[3,0],[1,6]] |
提示:
-
1 <= heights.length <= 5 * 10^4
-
1 <= heights[i] <= 10^9
-
1 <= queries.length <= 5 * 10^4
-
queries[i] = [ai, bi]
0 <= ai, bi <= heights.length - 1
题解
方法一:
思路
对于查询$[a,b]$不妨设$a\le b$,在$a=b$或$heights_a < heights_b$可以直接得到答案$b$
在除去这种特殊情况后,我们的问题变为了对于每个查询$[a,b]$,寻找最小$i$使得$b<i, heights_a \ge heights_i$
我们可以由小到大遍历$i$,找到所有查询中以$i$作为答案的查询。由于$i$是由小到大遍历的,所以对于每个查询找到的答案是最小的。
如何找到所有查询中以$i$作为答案的查询?只需要在所有右端点b小于i的查询中找到左端点a其值$heights_a < heights_i$的查询索引$idx$,得到答案$ans_{idx} = i$
维护一个$(heights_a, idx)$二元组的集合即可。能够高效查出最小值。可以用堆或平衡树等。
代码
1 | class Solution { |
方法二:
思路
对于查询$[a,b]$不妨设$a\le b$,在$a=b$或$heights_a < heights_b$可以直接得到答案$b$
在除去这种特殊情况后,我们的问题变为了对于每个查询$[a,b]$,寻找最小$i$使得$b < i, heights_a \ge heights_i$
线段树维护heights区间最小值。每次查询$heights[b…n-1]$中大于$heights_a$的最小下标。可以线段树上二叉搜索。
代码
1 |
|
方法三:
思路
二维偏序
对于查询$[a,b]$不妨设$a\le b$,在$a=b$或$heights_a < heights_b$可以直接得到答案$b$
在除去这种特殊情况后,我们的问题变为了对于每个查询$[a,b]$,寻找最小$i$使得$b < i, heights_a \ge heights_i$
考虑所有查询点$(heighs_a,b)$和数据点$(heights_i,i)$
为了保证查询点和数据点相同的情况下,查询点在数据点后面,并且能得到原查询的次序。对于第k次查询$[a_k, b_k]$,用三元组$(heighs_a,b,-k)$表示查询点,并用$(heighs_i, i, 1)$表示数据点。
将这些点的集合排序,按照第一关键字降序,第二关键字降序,第三关键字降序排序。
此时遍历点集合,对于当前点$(x,y,z)$,之前遍历过的点$(x’,y’,z’)$。$x\ge x’$。
如果当前z非0说明是查询点,我们只需要找到大于$z$的最小$z’$;
如果当前z为0说明是数据点,更新后缀$[y, \dots]$中的最小值为y。
树状数组可单点修改,求前缀最小值。可用树状数组维护$[1,N-y]$最小值。
代码
1 | class Solution { |