2940. 找到 Alice 和 Bob 可以相遇的建筑

Powered by:NEFU AB-IN

Link

文章目录

  • [2940. 找到 Alice 和 Bob 可以相遇的建筑](#2940. 找到 Alice 和 Bob 可以相遇的建筑)

2940. 找到 Alice 和 Bob 可以相遇的建筑

题意

给你一个下标从 0 开始的正整数数组 heights ,其中 heightsi 表示第 i 栋建筑的高度。

如果一个人在建筑 i ,且存在 i < j 的建筑 j 满足 heightsi < heightsj ,那么这个人可以移动到建筑 j 。

给你另外一个数组 queries ,其中 queriesi = ai, bi 。第 i 个查询中,Alice 在建筑 ai ,Bob 在建筑 bi 。

请你能返回一个数组 ans ,其中 ansi 是第 i 个查询中,Alice 和 Bob 可以相遇的 最左边的建筑 。如果对于查询 i ,Alice 和 Bob 不能相遇,令 ansi 为 -1 。

思路

题意就是找两个点,坐标大的点的下标(包括自己)的右边,哪个值比这两个点的最大值大,找出这个值的下标,并返回最靠左的

  1. st表 + 二分

    问题相当于计算区间 b+1,n−1 中第一个大于 v=heightsa 的高度的位置,那么二分区间即可,二分判断这个区间的最大值是否大于v

    线段树此题TLE,无在线操作的,就不用线段树解决RMQ问题

  2. 离线 + 最小堆

    离线的意思,就是把询问分组,不按照输入的顺序一个个回答,按自己定义的顺序回答

    整理好询问后,从左到右遍历建筑,如果发现当前 idx 建筑高度 > 之前需要回答的一个询问的建筑高度,那么这个询问的答案就是 idx

    需要一个最小堆去维护这些询问,每次取出最小的 heightsi,去和 heightsidx 比较

    如果 heightsi< heightsidx 就立刻回答(答案就是 idx)# 否则就不再回答(因为最小堆中其余元素都是 >= 堆顶的)

    还需要在堆中记录询问的编号

代码

python 复制代码
'''
Author: NEFU AB-IN
Date: 2024-08-10 17:31:58
FilePath: \LeetCode\2940\2940.py
LastEditTime: 2024-08-10 18:19:01
'''
# 3.8.19 import
import random
from collections import Counter, defaultdict, deque
from datetime import datetime, timedelta
from functools import lru_cache, reduce
from heapq import heapify, heappop, heappush, nlargest, nsmallest
from itertools import combinations, compress, permutations, starmap, tee
from math import ceil, comb, fabs, floor, gcd, hypot, log, perm, sqrt
from string import ascii_lowercase, ascii_uppercase
from sys import exit, setrecursionlimit, stdin
from typing import Any, Callable, Dict, List, Optional, Tuple, TypeVar, Union

# Constants
TYPE = TypeVar('TYPE')
N = int(2e5 + 10)
M = int(20)
INF = int(1e12)
OFFSET = int(100)
MOD = int(1e9 + 7)

# Set recursion limit
setrecursionlimit(int(2e9))


class Arr:
    array = staticmethod(lambda x=0, size=N: [x() if callable(x) else x for _ in range(size)])
    array2d = staticmethod(lambda x=0, rows=N, cols=M: [Arr.array(x, cols) for _ in range(rows)])
    graph = staticmethod(lambda size=N: [[] for _ in range(size)])


class Math:
    max = staticmethod(lambda a, b: a if a > b else b)
    min = staticmethod(lambda a, b: a if a < b else b)


class IO:
    input = staticmethod(lambda: stdin.readline().rstrip("\r\n"))
    read = staticmethod(lambda: map(int, IO.input().split()))
    read_list = staticmethod(lambda: list(IO.read()))


class Std:
    class SparseTable:
        def __init__(self, data: list, func=lambda x, y: x | y):
            """Initialize the Sparse Table with the given data and function."""
            self.func = func
            self.st = [list(data)]
            i, n = 1, len(self.st[0])
            while 2 * i <= n:
                pre = self.st[-1]
                self.st.append([func(pre[j], pre[j + i]) for j in range(n - 2 * i + 1)])
                i <<= 1

        def query(self, begin: int, end: int):
            """Query the combined result over the interval [begin, end]."""
            lg = (end - begin + 1).bit_length() - 1
            return self.func(self.st[lg][begin], self.st[lg][end - (1 << lg) + 1])

# --------------------------------------------------------------- Division line ------------------------------------------------------------------


class Solution:
    def leftmostBuildingQueries(self, heights: List[int], queries: List[List[int]]) -> List[int]:
        n = len(heights)
        st = Std.SparseTable(heights, Math.max)

        ans = []
        for a, b in queries:
            if a > b:
                a, b = b, a
            if a == b or heights[b] > heights[a]:
                ans.append(b)
                continue

            val = Math.max(heights[a], heights[b])
            l, r = b, n - 1
            while l < r:
                mid = l + r >> 1
                if st.query(b, mid) > val:
                    r = mid
                else:
                    l = mid + 1
            ans.append(r if heights[r] > val else -1)
        return ans
python 复制代码
class Solution:
    def leftmostBuildingQueries(self, heights: List[int], queries: List[List[int]]) -> List[int]:
        ans = [-1] * len(queries)
        qs = [[] for _ in heights]
        for i, (a, b) in enumerate(queries):
            if a > b:
                a, b = b, a  # 保证 a <= b
            if a == b or heights[a] < heights[b]:
                ans[i] = b  # a 直接跳到 b
            else:
                qs[b].append((heights[a], i))  # 离线询问

        h = []
        for i, x in enumerate(heights):
            while h and h[0][0] < x:
                # 堆顶的 heights[a] 可以跳到 heights[i]
                ans[heappop(h)[1]] = i
            for q in qs[i]:
                heappush(h, q)  # 后面再回答
        return ans
相关推荐
GuWenyue2 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
我叫洋洋4 小时前
C ++ [ hello world ]
c语言·c++·算法
奋发向前wcx5 小时前
y1,y2总复习笔记5 2026.7.19
数据结构·笔记·算法
战族狼魂8 小时前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
李剑一8 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH8 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
中达瑞和-高光谱·多光谱9 小时前
1nm到8nm光谱分辨率,你的应用该选哪款光谱相机?
算法·高光谱·高光谱相机
香辣牛肉饭10 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
旖-旎10 小时前
LeetCode 279:完全平方数(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题