rmq

dfs序+RMQ求LCA详解

删除回忆录丶 提交于 2019-11-26 20:36:45
首先安利自己 倍增求LCA的博客 ,前置 (算不上) 知识在此。 LCA有3种求法:倍增求lca(上面qwq),树链剖分求lca( 什么时候会了树链剖分再说。 ),还有,标题。 是的你也来和我一起学习这个了qwq。 开始吧。 众所周知,每当你dfs时,你都能产生一棵dfs树,可以根据你的dfs序来构建。 such as( 丑陋的画风 ): 一个dfs的顺序。 以这个为例: 那么我们写出他的遍历顺序: 假如我们要求3,8(wtf?)的LCA, 那么我们首先写出他的bfs序: 123432565217871。 然后留意一下我们要求的两个数的位置。 12 3 4 3 2565217 8 71。 我们发现这样一个事情 : 两个数的LCA,一定在前一个数最后一次出现的位置(在bfs序中)。 感性 证明 : 对于前一个数最后一次出现的位置,他的意义就是 当前节点的子树已经遍历完了,并且正在进行回溯 !( 拍桌,划重点! )。 也就是说,他要回溯到他的祖先了,而它的祖先同样也是后一个节点的祖先,一定在后一个节点遍历前,前一个节点回溯后。 前一个节点<lca<后一个节点。 证毕。 那么,我们只要找到dfs遍历顺序中的 “前一个数最后一次出现的位置,后一个数第一次出现的位置”,这个区间取出区间最小值,即是两个节点的lca。 或许有人会说:为什么最小值一定是lca呢? 又需要证明了。

【RMQ】一点感悟

谁说我不能喝 提交于 2019-11-26 17:08:45
RMQ算法全称为(Range Minimum/Maximum Query)【区间最值】 主要是这两种算法解决区间最值问题:线段树和稀疏表(Sparse Table) ST算法是解决RMQ(区间最值)问题,它能在O(nlogn)的时间预处理,然后O(1)回答。 其原理是倍增,f[i][j]表示从i位起的2^j个数中的最大数,即[i,i+2^j-1]中的最大值,从其定义中可以看出来 思想是动态规划 设二维数组dp[i][j]表示从第i位开始连续j个数中的最小值。 求 dp[i][j] 的时候把它分成两部分, 第一部分是 从 i到 i+2^(j-1)-1 , 第二部分从2^(j-1)到2^(j) , 得到转移方程: dp[i][j] = min(dp [i][j - 1], dp [i + (1 << j - 1)][j - 1]) 意思很明显,就是前半段和后半段的最大值, [i ,2^(j-1)-1], [2^(j-1),j] 的最大值. void init() { for(int i=1;i<=N;i++) dp[i][0]=arr[i]; for(int j=1;(1<<j)<=N;j++) for(int i=1;i+(1<<j)<=N+1;i++) dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]); } 查询的时候 取k=⌊log2( r

线段树浅析——RMQ问题

喜欢而已 提交于 2019-11-26 16:49:19
在OI路上你有没有遇到过这种情况—— 在一道你 只会打暴力 不会的题的题解上这样写着:我们可以用线段树维护。 机房的dalao说 这道是线段树模板题 我不知道你们遇没遇到过 反正我是经常这样,所以有了这篇博文。 讲起来我上篇关于01背包的博客没人看欸 算是以此篇博客记录一下我学习线段树的心得吧—— 好 以上都是废话 接下来我们开始正题 首先我们先介绍一个著名问题—— RMQ(Range Minimum/Maximum Query)问题 RMQ问题是指我们给定了一个序列,我们每次给定一个区间,查询这个区间中最大/最小的值的问题 (某位dalao:我们可以直接写暴力) 我们首先通过这位dalao的暴力来写一下代码: 来源: https://www.cnblogs.com/dixiao/p/11291291.html

POJ3264_Balanced Lineup(区间最值查询)

ぐ巨炮叔叔 提交于 2019-11-25 23:24:42
题意: 求给定区间内的最大值和最小值之差 思路: RMQ #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #pragma comment(linker, "/STACK:102400000,102400000") typedef long long LL; const int INF = 0x3f3f3f3f; const int maxn = 50000+5; using namespace std; int n,m, A[maxn]; int maxval[maxn][20], minval[maxn][20]; void RMQ_ST(){ for(int i = 1; i <= n; ++i) maxval[i][0] = minval[i][0] = A[i]; for(int i = 1; i <= (int)(log(n*1.0)/log(2.0)); ++i){ for(int j = 1; j + (1<<i) - 1 <= n; ++j){ maxval[j][i] = max(maxval[j][i-1], maxval[j + (1<<(i-1))][i-1]); minval[j][i] = min(minval[j][i-1], minval[j +