rmq

RMQ 区间最值问题

六月ゝ 毕业季﹏ 提交于 2020-01-14 01:01:50
今天学弟在群里直播讲课,讲了RMQ, 以前摸鱼太多这个题目并没看出来是啥 ,然后就去凑了个热闹。 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。 对于这个问题,区间最值,多次查询,我第一反应是线段树,也确实是线段树最值问题的基础模型,线段树博客其他文章中有,这里不单独拿出来了。 学弟讲这个题目,讲了3中方法暴力、动态规划,ST(Sparse Table) 暴力: 没什么好说 int RMQ(int A[], int mi, int ma) { int rt_max = -INF, rt_min = INF; for(int i=mi; i<=ma; i++) { rt_max = max(A[i], rt_max); rt_min = min(A[i], rt_min); } return {...}; } 动态规划: dp[i][j]维护为从i到j的最大值或最小值,状态转移方程即: dp[i][j]=max(dp[i][j-1],dp[j][j]); 这样在最开始将所有的值全部进行预处理,每次查询只要查询dp[i][j]的值,就能直接得到A[i]-A[j]的最大值和最小值: int dp[MX]

POJ 3264 Balanced Lineup (RMQ分析)

淺唱寂寞╮ 提交于 2020-01-08 04:35:04
链接: http://poj.org/problem?id=3264 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。 动态规划: 设data[i]是要求最大值的数列。dp[i][j]表示以第i个数开始,长度为2^j段的最大值。 若将该段从中间分开(因为是2^j,肯定能分成两段),得到的子序列为 i~2^(j-1)-1 和 i+2^(j-1)~i+2^j-1。。 写成方程的形式,即为: dp[i][j]= strcat ( dp[i][j-1] , dp[i+2^[j-1]][j-1] ) //strcat()为字符串连接函数 So....状态转移方程为: dp[i][j]= MAX ( dp[i][j-1] , dp[i+2^[j-1]][j-1] ) ; dp[i][0]为它本身 以下摘自: http://blog.csdn.net/niushuai666/article/details/7401403 代码为: void RMQ(int num) //预处理->O(nlogn) { for(int j = 1; j < 20; ++j) for(int i = 1; i <= num; ++i)

深度剖析如何实现事务消息

亡梦爱人 提交于 2020-01-06 23:26:16
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 这是一篇从去年写到今年的文章,希望大家会喜欢 1.背景 分布式事务一直是一个老生常谈的一个话题,在我的公众号下面下面已经写过很多篇分布式事务相关的文章了,但是依旧没有将其完全剖析。在之前的文章中我也多次提到我们可以使用消息队列来实现我们的分布式事务,但是大多都是一笔带过,很多读者都对这一块产生了很多疑问,希望读完这篇文章能让你理解如何用消息队列实现分布式事务。 当然首先要回顾一下我们的一些基本概念: CAP CAP定理,又被叫作布鲁尔定理。对于设计分布式系统来说(不仅仅是分布式事务)的架构师来说,CAP就是你的入门理论。 C (一致性):对某个指定的客户端来说,读操作能返回最新的写操作。对于数据分布在不同节点上的数据上来说,如果在某个节点更新了数据,那么在其他节点如果都能读取到这个最新的数据,那么就称为强一致,如果有某个节点没有读取到,那就是分布式不一致。 A (可用性):非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。可用性的两个关键一个是合理的时间,一个是合理的响应。合理的时间指的是请求不能无限被阻塞,应该在合理的时间给出返回。合理的响应指的是系统应该明确返回结果并且结果是正确的,这里的正确指的是比如应该返回50,而不是返回40。 P (分区容错性):当出现网络分区后,系统能够继续工作

POJ3264/RMQ

≯℡__Kan透↙ 提交于 2020-01-05 06:26:13
题目链接 /* 询问一段区间内的元素差值最大是多少,用RMQ维护一个最大值和一个最小值,相减即可。 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=50000+5; int h; int dpmax[maxn][18]; int dpmin[maxn][18]; int n,q; int k=0; int RMQ(int l,int r) { int k=0; while((1<<(k+1)<=(r-l+1))) k++; return max(dpmax[l][k],dpmax[r-(1<<k)+1][k])-min(dpmin[l][k],dpmin[r-(1<<k)+1][k]); } int main () { while(~scanf("%d%d",&n,&q)) { /* if(k) { memset(dpmax,0,sizeof(dpmax)); memset(dpmin,0,sizeof(dpmin)); } */ for(int i=0;i<n;i++) { scanf("%d",&h); dpmax[i][0]=h; dpmin[i][0]=h; } for(int k=1;(1<<k)<=n;k++) for(int i

动态规划求RMQ(区间最值问题Range Minimum/Maximum Query)

心已入冬 提交于 2020-01-05 04:14:42
求RMQ最简单的方法是遍历区间,时间复杂度O(n), 但是当查询次数很多的时候,时间效率并不高。可以用线段树把算法优化到O(logn) (在线段树中保存线段的 最值),不过sparse_table算法是较好的,用O(nlogn)的时间进行预处理,然后用O(1)时间进行查询。 预处理: 预处理使用DP的思想,f(i, j)表示[i, i+2^j - 1]区间中的最小值,我们可以开辟一个数组专门来保存f(i, j)的值。 例如,f(0, 0)表示[0,0]之间的最小值,就是num[0], f(0, 2)表示[0, 3]之间的最小值, f(2, 4)表示[2, 17]之间的最小值 注意, 因为f(i, j)可以由f(i, j - 1)和f(i+2^(j-1), j-1)导出, 而递推的初值(所有的f(i, 0) = i)都是已知的 所以我们可以采用自底向上的算法递推地给出所有符合条件的f(i, j)的值。 查询: 假设要查询从m到n这一段的最小值, 那么我们先求出一个最大的k, 使得k满足2^k <= (n - m + 1).于是我们就可以把[m, n]分成两个(部分重叠的)长度为2^k的区间: [m, m+2^k-1], [n-2^k+1, n];而我们之前已经求出了f(m, k)为[m, m+2^k-1]的最小值, f(n-2^k+1, k)为[n-2^k+1, n]的最小值,

rmq算法,利用倍增思想

非 Y 不嫁゛ 提交于 2020-01-05 04:00:36
RMQ问题ST算法 /* RMQ(Range Minimum/Maximum Query)问题: RMQ问题是求给定区间中的最值问题。当然,最简单的算法是O(n)的,但是对于查询次数很多(设置多大100万次),O(n)的算法效率不够。可以用线段树将算法优化到O(logn)(在线段树中保存线段的最值)。不过,Sparse_Table算法才是最好的:它可以在O(nlogn)的预处理以后实现O(1)的查询效率。下面把Sparse Table算法分成预处理和查询两部分来说明(以求最小值为例)。 预处理 : 预处理使用DP的思想,f(i, j)表示[i, i+2^j - 1]区间中的最小值,我们可以开辟一个数组专门来保存f(i, j)的值。 例如,f(0, 0)表示[0,0]之间的最小值,就是num[0], f(0, 2)表示[0, 3]之间的最小值, f(2, 4)表示[2, 17]之间的最小值 注意, 因为f(i, j)可以由f(i, j - 1)和f(i+2^(j-1), j-1)导出, 而递推的初值(所有的f(i, 0) = i)都是已知的 所以我们可以采用自底向上的算法递推地给出所有符合条件的f(i, j)的值。 查询 : 假设要查询从m到n这一段的最小值, 那么我们先求出一个最大的k, 使得k满足 2^k <= (n - m + 1). 于是我们就可以把[m, n]分成两个

RMQ问题ST算法

落花浮王杯 提交于 2020-01-05 03:58:12
http://www.cppblog.com/reiks/archive/2009/08/28/94629.aspx /* RMQ(Range Minimum/Maximum Query)问题: RMQ问题是求给定区间中的最值问题。当然,最简单的算法是O(n)的,但是对于查询次数很多(设置多大100万次),O(n)的算法效率不够。可以用线段树将算法优化到O(logn)(在线段树中保存线段的最值)。不过,Sparse_Table算法才是最好的:它可以在O(nlogn)的预处理以后实现O(1)的查询效率。下面把Sparse Table算法分成预处理和查询两部分来说明(以求最小值为例)。 预处理: 预处理使用DP的思想,f(i, j)表示[i, i+2^j - 1]区间中的最小值,我们可以开辟一个数组专门来保存f(i, j)的值。 例如,f(0, 0)表示[0,0]之间的最小值,就是num[0], f(0, 2)表示[0, 3]之间的最小值, f(2, 4)表示[2, 17]之间的最小值 注意, 因为f(i, j)可以由f(i, j - 1)和f(i+2^(j-1), j-1)导出, 而递推的初值(所有的f(i, 0) = i)都是已知的 所以我们可以采用自底向上的算法递推地给出所有符合条件的f(i, j)的值。 查询: 假设要查询从m到n这一段的最小值, 那么我们先求出一个最大的k,

POJ 3264 Balanced Lineup (RMQ分析)

依然范特西╮ 提交于 2020-01-05 03:04:38
链接: http://poj.org/problem?id=3264 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。 动态规划: 设data[i]是要求最大值的数列。dp[i][j]表示以第i个数开始,长度为2^j段的最大值。 若将该段从中间分开(因为是2^j,肯定能分成两段),得到的子序列为 i~2^(j-1)-1 和 i+2^(j-1)~i+2^j-1。。 写成方程的形式,即为: dp[i][j]= strcat ( dp[i][j-1] , dp[i+2^[j-1]][j-1] ) //strcat()为字符串连接函数 So....状态转移方程为: dp[i][j]= MAX ( dp[i][j-1] , dp[i+2^[j-1]][j-1] ) ; dp[i][0]为它本身 以下摘自: http://blog.csdn.net/niushuai666/article/details/7401403 代码为: void RMQ(int num) //预处理->O(nlogn) { for(int j = 1; j < 20; ++j) for(int i = 1; i <= num; ++i)

2D RMQ Range Tree

北慕城南 提交于 2019-12-24 12:16:16
问题 Hi I'm trying to implement a 2D range tree for rmq-ing, here's my code, i think it's not efficient enough, is there anything i can do for optimation. ls contain list of y sorted on every node rt contain a segment tree p.fi.fi contain x coordinate p.fi.se contain y coordinate p.se contain id of the point loc contain x node and y node for each id vector<pii> ls[400005]; vector<int> rt[400005]; pair<pii,int> p[100005]; vector<pii> loc[100005]; inline void merge(int id,vector<pii> &res,vector<pii

RMQ(ST算法)

廉价感情. 提交于 2019-12-18 17:36:29
RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列a,回答若干询问RMQ(A,i,j)(i, j<=n),返回数列a中下标在i,j之间的最小/大值。如果只有一次询问,那样只有一遍for就可以搞定,但是如果有许多次询问就无法在很快的时间处理出来。在这里介绍一个在线算法。所谓在线算法,是指用户每输入一个查询便马上处理一个查询。该算法一般用较长的时间做预处理,待信息充足以后便可以用较少的时间回答每个查询。ST(Sparse Table)算法是一个非常有名的在线处理RMQ问题的算法,它可以在O(nlogn)时间内进行预处理,然后在O(1)时间内回答每个查询。 步骤如下: 假设a数组为: 1, 3, 6, 7, 4, 2, 5 1.首先做预处理(以处理区间最小值为例) 设mn[i][j]表示从第i位开始连续2^j个数中的最小值。例如mn[2][1]为第2位数开始连续2个的数的最小值,即3, 6之间的最小值,即mn[2][1] = 3; 之后我们很容想到递推方程: mn[i][j] = min(mn[i][j - 1], mn[i + (1 << j - 1)][j - 1]) 附上伪代码: for(int j = 0; j < 20; j ++) for(int i = 1; i + (1 << j) <= n + 1; i