zoukankan      html  css  js  c++  java
  • 区间最值问题(RMQ):压位分块稀疏表

    区间最值问题(RMQ)也就是给定一个序列 $a[n]$, 多次询问 $min a[l:r]$(最大值同理)。

    稀疏表

    时间复杂度 $O(nlog n)-O(1)$

    空间复杂度 $O(nlog n)$

    编程难度 低

    设 $f(i, j)=min a[j:2^i+j]$, 递推预处理。

    $$f(i, j)=egin{cases}a_j,&i=0;\min{f(i-1, j), f(i-1, j+2^{i-1})},&1 le i le log_2n.end{cases}$$

    在最小值查询中,一个数被统计多次是没关系的。因此设 $t=leftlfloorlog_2(r-l) ight floor$, $min a[l:r]=min{f(t, l), f(t, r-2^t)}$.

    这里特别说一下,保存 $f(i, j)$ 的数组第一维用 $i$, 第二维用 $j$, 可以使递推时访存连续,减小时间常数。

    RMQ标准算法

    时间复杂度 $O(n)-O(1)$

    空间复杂度 $O(n)$

    编程难度 中等

    时空复杂度已达理论下界。可惜常数太大,在数据规模不大的时候有时表现还不如稀疏表。

    大致思路是,对序列建笛卡尔树,RMQ转成LCA; 对笛卡尔树求欧拉序,LCA转成相邻两项差值为 $pm 1$ 的约束RMQ问题。

    对于约束RMQ问题,每 $leftlfloorfrac{log_2 n}{2} ight floor$ 个分一块,整块询问用稀疏表,块内询问由于只有 $O(sqrt n)$ 种不相似的块,对于每种都可以递推预处理块内任一区间的 RMQ.

    压位分块稀疏表

    时间复杂度 $O(n(1+log n/mathrm w))-O(1)$

    空间复杂度 $O(n(1+log n/mathrm w))$

    编程难度 较低

    这东西是我校身经百战,见多识广的Lagoon队长告诉我的。我也不知道怎么称呼,就自作主张,把它叫做“压位分块稀疏表”吧。

    假设机器字长为 $ ewcommand{w}{mathrm w}w$, 通常 $w$ 取值为 $32$ 或 $64$.

    考虑一个暴力,询问按右端点排序,维护所有左端点对应区间的最小值,这是个单调栈就能解决的东西。查询的时候,最值点就是单调栈上不小于左端点的最左侧点。

    如果询问区间长度不超过 $w$, 那么只需要维护最近 $w$ 位是否属于单调栈。形式化地,我们维护一个 $w$ 比特非负整数 $S_r$, $r-i$ 在单调栈上,当且仅当 $S_r$ 的低第 $i$ 位为 $1$.

    计算 $S_r$ 只需要在 $S_{r-1} mathop{mathrm{lsh}} 1$ 的基础上,一边维护单调栈一边加删一些位。因为 $S_r$ 只占一个字长,随便保存,于是询问也根本不需要按右端点排序了。

    查询 $min a[l:r]$, 也就是求 $S_r$ 的低前 $r-l$ 位中,最高位 $1$ 的位置。通过位运算过滤掉太高的位上的 $1$, 然后调用 __builtin_clz(ll) (这是直接调CPU指令的)来查询最高位。

    给序列每 $mathrm w$ 个分一块,整块的部分用稀疏表查询,块内用上面这个压位暴力。

    模板题:洛谷3865【模板】ST表(区间最大值)代码链接

  • 相关阅读:
    DNS域名解析中A、AAAA、CNAME、MX、NS、TXT、SRV、SOA、PTR各项记录的作用
    HTTP数据包
    渗透——网络基础
    渗透——linux基础
    渗透——http协议基础
    渗透——CMS基础
    渗透测试流程
    渗透专用术语
    CodeFoeces GYM 101466A Gaby And Addition (字典树)
    关于Windows10内存随时间不断升高问题
  • 原文地址:https://www.cnblogs.com/nealchen/p/RMQ.html
Copyright © 2011-2022 走看看