rmq

poj2452 Sticks Problem RMQ问题

Deadly 提交于 2020-02-12 11:06:24
题目大意说:给出一系列的木棒的长度,求出一个最大的区间[x,y],满足所有的len[k]>len[i] && len[k]<len[j] ,i<=k<=j。我看的题目分类说这个题目用RMQ,所有就用了RMQ实现,由于开始的时候我是枚举的所有的区间,所以肯定超时,后来改为从i找出以i开始的最大区间范围,然后在这个范围内求出最大值的下标j,那么j就是从i开始的所有>i且<j的最大区间,枚举采用二分,这样时间复杂度为O(nlogn). #include <iostream>#include <stdio.h>#include <cmath>const int N=50001;using namespace std;int m[N],large[N][17],smal[N][17];inline int get_max(int a,int b){ return a>b?a:b;}inline int get_min(int a,int b){ return a<b?a:b;}void initrmq(int n){ int i,j; for(i=0;i<n;i++) { large[i][0]=i; smal[i][0]=i; } for(j=1;(1<<j)<=n;j++) { for(i=0;i+(1<<j)-1 < n;i++) { if(m[large[i][j-1]] > m

RMQ学习笔记

老子叫甜甜 提交于 2020-01-30 01:03:40
一、RMQ: RMQ(Range Minimum/Maximun Query)指的是区间最值问题。即求多次查询区间最大值和最小值问题。一般常用的解决方法有: 1、暴力:O(n ^ 2); 2、ST表:预处理O(nlogn),单次查询O(1),空间O(nlogn); 3、线段树:预处理O(nlogn),单次查询O(logn),空间O(n); 二、接下来我将逐条讲述一下每一种算法(以最小值为例,最大值同理,暴力的算法我就直接跳过啦): 1、ST表: ST表基于倍增和DP的思想,用二维数组dp[i][j]记录从第i位开始,连续 2 j 2^j 2 j 位的最小值,这样,我们可以得出,dp[i][0] = a[i]。 这样dp的初值就有啦。那我们如何写dp的状态转移方程呢? 我们可以考录将 2 j 2^j 2 j 的区间分成两部分,每一部分的大小都是 2 j − 1 2^{j-1} 2 j − 1 , 即将[i , i + 2 j 2^j 2 j - 1]分成[i , i + 2 j − 1 2^{j-1} 2 j − 1 - 1]和[i + 2 j − 1 2^{j-1} 2 j − 1 , i + 2 j 2^j 2 j - 1]两部分。这样就可以得到状态转移方程dp[i][j] = min(dp[i][j-1] , dp[i + (1 << j - 1)][j-1];

浅谈RMQ实现LCA

风流意气都作罢 提交于 2020-01-28 07:52:10
求两个点的LCA一共有四种方法 Tarjan,倍增,RMQ还有树链剖分(我也不会) 今天我们来学习如何用RMQ来实现LCA 首先我们要知道什么是RMQ(区间最值) 推荐一篇大佬的博客: https://www.cnblogs.com/YSFAC/p/7189571.html 好了,现在大家都知道了什么是RMQ,那么我们来看一下什么是LCA LCA是树上两个点的最近公共祖先 举个例子: 在这个图中,4和5的最近公共祖先就是2 5和6的最近公共祖先就是1 然后我们来看如何快速的求出两个点的最近公共祖先 首先是求出每个点的深度 这个操作用一个DFS维护即可,每个店的深度是其父亲的深度加1 void dfs(int x,int fa){ for(int e=head[x];e;e=nxt[e]){ d[to[e]]=d[x]+1; dfs(to[e],x); } return ; } 然后是维护f数组 f数组储存的是每个点向上跳2^j步所到达的点,并且我们可以确定这个点是唯一的,因为是树 然后来看如何维护 我们可以用递推的方法来求,时间复杂度是(nlogn)的 对于f[i][j] 是从x往上跳2^j步 可以推导出相当于是从x往上跳2^j-1步,然后再跳2^j-1步 也就是相当于从x往上跳2^j-1步之后,从那个点在往上跳2^j-1步 由此得出了我们的递推式: f[i][j]=f[f[i]

[NOI2010]超级钢琴(贪心+RMQ+堆)

萝らか妹 提交于 2020-01-27 04:31:26
传送门 题意:有一个长为n的数列A,定义区间[l, r]的权值为 \(\sum_{i=l}^{r}a_i\) .选出k个不相同的区间,使得它们的权值和最大.并满足每个选出的区间长度∈[L, R]. 分析:最最最基本的,既然是要求区间和,就要想到前缀和.然后暴力做法是 \(n^2\) 枚举所有区间,把符合条件(区间长度的限制)的区间的区间和保存起来,然后排个序,输出前k个的和. 考虑这样一个问题,如果你已经知道了区间的右端点i,题目又限制了合法区间的长度∈[L,R],所以这个以i为右端点的区间的区间和就是 \(sum[i]-sum[j-1]\) 的值,其中i-j+1∈[L,R],即j∈[i+1-R,i+1-L].要使 \(sum[i]-sum[j-1]\) 的值最大,因为sum[i]的值是固定的了,所以sum[j-1]要最小.即我们要在区间[i+1-R,i+1-L]中找到一个j,使得sum[j-1]最小. 如果我们对于每一个右端点i都for循环[i+1-R,i+1-L],找到对应的左端点j,最坏情况下,时间复杂度还是 \(n^2\) .我们现在正在求解的问题是什么?在区间[i+1-R,i+1-L]找最小值,这不是RMQ问题么,那不就可以用ST求解么?然后本题中,我们为了方便,将RMQ(求区间最值)用于求区间最小值的下标,具体见代码实现. 接下来贪心地想我们每次都选最优的子段

RMQ问题(ST算法)

|▌冷眼眸甩不掉的悲伤 提交于 2020-01-24 00:28:26
RMQ是询问某个区间内的最大值或最小值的问题,ST算法可以求解RMQ问题.ST算法通常用在要 多次询问某一些区间的问题中,相比于线段树,它的程序实现更加简单,运行速度更快,它可以做到O(nlogn)的预处理,O(1)回答每个问题.使用ST算法的条件是没有修改操作,因此它适用于没有修改操作并且访问次数较多(10^6级别甚至更大)的情况. 1.预处理 ST算法的原理实际上是动态规划,首先要知道f数组的含义,f[i][j]中i表示左边端点,j表示2^j个长度, 因此f[i,j]表示的是区间为[i,i+2^j-1]这个范围内的最大值,也就是以a[i]为起点连续的2^j个数的最大值.由于元素个数为2^j个,所以从中间平均分成两部分,每一部分的个数都为2^(j-1);假设f[6][3]分为f[6][2]和f[10][2],如下图所示, 整个区间的最大值一定是左右两部分最大值的较大者,满足动态规划的最优化原理,分析得f数组的状态转移方程为f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1]). for(int j = 1;(1<<j) <= n;++j) //j枚举每一个可能出现的长度 for(int i = 1;i + (1<<j)-1 <= n;i++) //i枚举每一个区间的左端点 f[i][j] = max(f[i][j-1],f[i+(1<<(j-1))][j

RMQ 模板

随声附和 提交于 2020-01-16 20:33:56
RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为 n的数列A,回答若干次询问RMQ(i,j),返回数列A中下标在区间[i,j]中的最小/大值。 这个有很多算法:这里介绍一种比较高效的ST算法解决这个问题。ST(Sparse Table)算法可以 在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。 令dp(i,j)表示从 i 开始的,长度为 2^j 的一段中元素的最小值, 即可以递推出dp(i,j)=min(dp(i,j-1),dp(i+2^(j-1) , j-1))。 代码: void ST(int n) { for (int i = 1; i <= n; i++) dp[i][0] = A[i]; for (int j = 1; (1 << j) <= n; j++) { for (int i = 1; i + (1 << j) - 1 <= n; i++) { dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } } } int RMQ(int l, int r) { int k = 0; while ((1 << (k + 1)) <= r - l + 1) k++; return max(dp[l][k], dp[r -

RMQ之ST求区间最大值

浪子不回头ぞ 提交于 2020-01-16 20:33:00
题目链接: https://cn.vjudge.net/problem/HRBUST-1188 每一次按照二进制的方式进行更新,二维数组dp [i] [j],i表示下标,j表示从i 开始的往后移动2的j-1次方个数再-1. AC代码: 1 #include<iostream> 2 #include<cmath> 3 #include<stack> 4 #include<iomanip> 5 #include<queue> 6 #include<cstring> 7 #include<string> 8 #include<stdio.h> 9 #include<algorithm> 10 #include<vector> 11 using namespace std; 12 # define inf 0x3f3f3f3f 13 # define ll long long 14 const int maxn = 50000+100; 15 int dp[maxn][20]; 16 int n; 17 void RMQ() 18 { 19 for(int i=1; i<=20; i++) 20 { 21 for(int j=1; j<=n; j++) 22 { 23 if(j+(1<<i)-1<=n) 24 { 25 dp[j][i]=max(dp[j][i-1],dp[j+(1<<(i

rmq st算法求区间最值问题

主宰稳场 提交于 2020-01-16 20:32:25
st算法是解决区间最值问题比较有效的算法,把每一段查询区间分为两部分,用nlogn的预处理求出dp[i][j]从第i个数开始到i+2^j-1之间的最值,如果要查询[a,b]的最值,则可分为[a,a+2^k-1],[b-2^k+1,b-2^k+1+2^k-1]即[b-2^k+1,b]两个区间每次查询的时间为o(1)其中k=(int)(log(b-a+1)/log2)(换底公式) View Code 1 #define N 100005 2 int dp[N][18]; 3 int v[N]; 4 int max(int a,int b) 5 { 6 return a>b?a:b; 7 } 8 int rmq(int s,int e) 9 { 10 int k=(int)(log((e-s+1)*1.0)/log(2.0)); 11 return max(dp[s][k],dp[e-(1<<k)+1][k]); 12 } 13 int makrmq(int n) 14 { 15 int i,j; 16 for(i=1;i<=n;i++) 17 dp[i][0]=v[i]; 18 for(j=1;(1<<j)<=n;j++) 19 for(i=1;i+(1<<j)-1<=n;i++)//动态规划的思想求最值 20 dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1

RMQ求LCA

雨燕双飞 提交于 2020-01-16 20:31:13
题目链接 rmq求LCA,interesting。 一直没有学这玩意儿是因为CTSC的Day1T2,当时我打的树剖LCA 65分, gxb 打的rmq LCA 45分。。。 不过rmq理论复杂度还是小一点的,就学一下把。 RMQ求LCA 我们要用到三个数组 \(dfn[i]\) :第 \(i\) 个节点位置的时间戳 \(id[i][j]\) :在欧拉序中 \(i\) 到 \(i + 2^j - 1\) 这段区间内深度最小的节点编号 \(dep[i]\) :第 \(i\) 个节点的深度 实际上用到了一个性质: 对于任意两点的 \(LCA\) ,一定是它们欧拉序中两点之间的最小值 欧拉序是什么?就是把dfs中遍历到每一个一个节点(包括回溯时遍历到)加到一个序列里,最终得到的就是欧拉序 时空复杂度 设 \(T = 2 * n - 1\) 时间复杂度: 预处理: \(O(TlogT)\) 查询: \(O(1)\) 空间复杂度: 考虑欧拉序中有多少个点,首先每个点被访问到的时候会做出 \(1\) 的贡献 其次在遍历每条边时会多出 \(1\) 的共贡献 因此总空间复杂度为: \(O(T)\) // luogu-judger-enable-o2 #include<bits/stdc++.h> const int MAXN = 1e6 + 10; using namespace std;

RocketMQ(七)——Transaction Message(事务消息)

懵懂的女人 提交于 2020-01-16 14:19:01
分布式事务 通过MQ解决分布式事务的思路 1) 业务和消息生成耦合在一起 2) 业务和消息解耦 RocketMQ 中的事务消息 1) 目前RMQ3.2.6中事务消息的实现原理及存在的问题 2) 问题解决思路 本文介绍RocketMQ提供的第三种类型的消息——Transaction Message(事务消息)。在说事务消息之前,我们先来说说分布式事务的那些事! 分布式事务 什么是分布式事务,我的理解是一半事务。怎么说,比如有2个异构系统,A异构系统要做T1,B异构系统要做T2,要么都成功,要么都失败。 要知道异构系统,很显然,不在一个数据库实例上,它们往往分布在不同物理节点上,本地事务已经失效 2阶段提交 2阶段提交协议,Two-Phase Commit,是处理分布式事务的一种常见手段。2PC,存在2个重要角色:事务协调器(TC),事务执行者。 2PC,可以看到节点之间的通信次数太多了,时间很长!时间变长了,从而导致,事务锁定的资源时间也变长了,造成资源等待时间变长!在高并发场景下,存在严重的性能问题! 通过MQ解决分布式事务的思路 下面,我们来看看MQ在高并发场景下,是如何解决分布式事务的。 考虑生活中的场景: 我们去北京庆丰包子铺吃炒肝,先去营业员那里付款(Action1),拿到小票(Ticket),然后去取餐窗口排队拿炒肝(Action2)。思考2个问题:第一