首页 > 其他分享 >O(n)-O(1) RMQ

O(n)-O(1) RMQ

时间:2024-08-20 11:16:58浏览次数:7  
标签:RMQ log 询问 预处理 复杂度 最大值

这貌似是一个很神奇的新科技。

由乃救爷爷

给你一个长为 \(n\) 的序列,你需要回答 \(q\) 次询问

每次询问给出 \(l,r\),求 \(\max\limits_{i=l}^ra_i\)。

其中,\(n,m\le 2\times 10^7\)

看起来好像是一个比较模板的 RMQ,事实也确实如此

不过一般解决 RMQ 的方法都无法在正确的时间复杂度内解决这个问题,例如线段树:预处理 \(O(n\log n)\),单次询问 \(O(\log n)\),无论预处理还是解决询问都会超时。再比如 ST 表:预处理 \(O(n\log n)\),单次询问 \(O(1)\),预处理也会超时。

这里就要讲一讲一个很强的东西了:基于整数状压的线性 RMQ。

前置:

  1. ST 表(必须会)
  2. 状态压缩(必须会)
  3. 分块(因为比较简单不强求)
  4. 单调栈(因为比较简单不强求)

算法介绍

首先,一个降低常数的办法是,先分块(假设块长为 \(B\)),记录每个块的最大值,然后把每个块当成一个元素,重新构成一个序列 \(b\),在这个序列上建立 ST 表。

对于一次询问 \(l,r\),假设 \(l\) 属于 \(p\) 块,\(r\) 属于 \(q\) 块。

  • 如果 \(p\ne q\):那么 \([l,r]\) 内的最大值即为 \(b_{p+1\sim q-1}\) 的最大值与剩余两边部分的最大值,求解的时间复杂度为 \(O(\frac{n}{B}\log{\frac{n}{B}})\)。

  • 如果 \(p=q\):那么直接在块内暴力查找,时间复杂度 \(O(B)\)。

此时的时间复杂度足以通过本题,但依然没有到达线性的要求,我们进行进一步强化。

假设 \(B=\log n\),对序列 \(a\) 分块后,再建立 ST 表的时间复杂度为 \(O(\frac{n}{\log n}\log{\frac{n}{\log n}})\approx O(n)\)。然后我们在记录每个块内前后缀最大值(时间复杂度 \(O(n)\))。依然假设对于一次询问 \(l,r\),\(l\) 属于 \(p\) 块,\(r\) 属于 \(q\) 块。

  • 如果 \(p\ne q\):则询问可以拆成“后缀 + 大区间 + 前缀”的模式,可以 \(O(1)\) 求解。

  • 如果 \(p=q\):此时就比较难绷了,好像依然需要暴力查找。

首先有一个性质,就是 \(B\) 很小,不超过 \(30\)(因为 \(B=\log n\))。

假设我们现在确定了右边界 \(r\),但是未确定左边界 \(l\)。此时有哪些候选项可能成为 \([l,r]\) 区间内的最大值?显然,候选项有多个,假设分别为 \(p_1,p_2,\dots p_k\)。思考每个 \(p_i\) 都需要满足的条件。

显然,对于任意 \(i<j\),如果 \(a_i<a_j\),则 \(a_i\) 一定不可能成为区间 \([l,r]\) 最大值。假设存在区间 \([l,r]\) 的最大值为 \(a_i\),那么显然可以用 \(a_j\) 代替 \(a_i\)。原因很简单:如果区间 \([l,r]\) 包含 \(i\),则其一定也包含 \(j\)。但是对于 \(i<j,a_i>a_j\)。\(a_j\) 依然可能成为区间最大值(可能存在 \(i<l\le j\) 的情况)。

我们维护一个单调栈,使得栈底到栈顶单调递减,每把一个数入栈,就进行一次状态压缩,为在栈中的数对应的位置为 \(1\),反之为 \(0\)。假设当前将 \(r\) 入栈,则把状态压缩后的结果储存在 \(val_r\) 中,\(val_r\) 中所有为 \(1\) 的位置即为可能成为 \([l,r]\) 最大值的候选项(\(l\le r\))。

对于查询 \([l,r]\) 中的最大值,我们取出 \(val_r\),此时小于 \(l\) 的位置的候选项均不合法,排除不合法候选项后,取出当前最靠后的一个 \(1\),即为区间 \([l,r]\) 的最大值,他满足其到 \(r\) 中的任意数都小于它,它到 \(l\) 中的任意数都不大于他。

因为要状态压缩,所有必须要求区间长度很小,而因为块长 \(B\le 30\),所以很适合对每个块进行一遍上述过程,预处理 \(O(n)\),查询 \(O(1)\)。

综上,对于任意情况,我们都可以做到趋近于线性求出区间最大值。还有一个小技巧是:将快长直接赋值 \(64\)。方便各种运算,时间复杂度也不会很劣,甚至跑的更快。

都是我口胡的,赶紧写代码。

标签:RMQ,log,询问,预处理,复杂度,最大值
From: https://www.cnblogs.com/zuoqingyuan/p/18369101

相关文章

  • P6109 [Ynoi2009] rprmq1 题解
    Description有一个\(n\timesn\)的矩阵\(a\),初始全是\(0\),有\(m\)次修改操作和\(q\)次查询操作,先进行所有修改操作,然后进行所有查询操作。一次修改操作会给出\(l_1,l_2,r_1,r_2,x\),代表把所有满足\(l_1\lei\ler_1\)且\(l_2\lej\ler_2\)的\(a_{i,j}\)元......
  • ST表 RMQ问题(区间最大/最小值查询)
    #include<iostream>#include<cstring>#include<algorithm>#include<cmath>usingnamespacestd;intf[100005][22];intmain(){intn,m;scanf("%d%d",&n,&m);for(inti=1;i<=n;i++)scanf("%d"......
  • O(1) 修改的 RMQ
    前天uq里有人问这个。单点修改区间\(min\),能不能做到修改\(O(1)\)查询\(O(\sqrtn)\)。后来和@critno私下讨论了一会,得到了\(O(1)\)修改\(O(n^{\epsilon})\)查询的算法,并进行了简化版的实现。算法本质是操作序列分块。先考虑一个朴素算法。原序列不动,跑RMQ。......
  • 数据结构——RMQ(ST表)问题
    数据结构——RMQ(ST表)问题问题描述对于序列\(A[1\dotsn]\),有\(m\)组询问\(\langlel,r\rangle\),求\(\max_{i=l}^rA_i\)。我们下面使用\(\mathcalO(A)\sim\mathcalO(B)\)表示预处理\(\mathcalO(A)\),单次询问\(\mathcalO(B)\)的时间复杂度。线段树解法时间复杂度......
  • RMQ 部分代码
    inta[50001];intf1[50001][20],f2[50001][20];inlinevoidwork1(){ for(inti=1;i<=n;i++) f1[i][0]=a[i]; for(intj=1;(1<<j)<=n;j++) for(inti=1;i+(1<<j)-1<=n;i++) f1[i][j]=max(f1[i][j-1],f1[......
  • 线段树--RMQ
    这是带上lazy标记的线段树板子inta[N];intls(intp){returnp<<1;}intrs(intp){returnp<<1|1;}classSegmentTree{public: inttree[N<<2|1],tag[N<<2|1]; inlinevoidpush_up(intp){ tree[p]=tree[ls(p)]+tree[rs(p)]; } in......
  • RMQ问题的各种解法
    RMQ问题:给定一个序列,并有一些询问,每次询问一个区间的最大值或最小值。下面以区间最大值为例进行讲解,设序列长度为\(N\),有\(M\)次查询。1单调队列前提条件每个查询的区间互相不包含、离线、不能进行修改、不能在序列中增加元素。思路将所有查询按左端点排序(如果不保......
  • 2024.4.5 RMQ补题
    P2048[NOI2010]超级钢琴前缀和处理连续子段的和弦,然后rmq求最大值运用堆存储最优答案每次取出堆头统计一次后,除掉统计点再分成两段加入即可,共k次#include<bits/stdc++.h>#definemaxn500010#defineINF0x3f3f3f3f#defineintlonglongusingnamespacestd;int......
  • 51nod1174 区间中最大的数RMQ
    给出一个有n个数的序列,下标0~n-1,有Q次查询,每次询问区间[l,r]的最大值。如果有修改,可以考虑线段树,这里只有静态查询,可以用ST表,预处理时间O(nlogn),单次查询时间O(1)。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definerep(i,a,b)for(inti=a;i<=b;i......
  • RMQ
    这里会记一些不那么基础的RMQ算法,同时也会向外拓展到增量法规建笛卡尔树之类的东西。首先是基础的RMQ,静态可以用ST表做到\(O(n\logn)-O(1)\),动态可以用线段树做到\(O(n)-O(\logn)\),当然还有一些奇技淫巧可以用ST表维护特殊的动态RMQ。现在来看不基础的。询问区间定......