RMQ(st在线算法模板)

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;

#define M 100010
#define MAXN 500
#define MAXM 500
int dp[M][18];
/*
*一维RMQ ST算法
*构造RMQ数组 makermq(int n,int b[]) O(nlog(n))的算法复杂度
*dp[i][j] 表示从i到i+2^j -1中最小的一个值(从i开始持续2^j个数)
*dp[i][j]=min{dp[i][j-1],dp[i+2^(j-1)][j-1]}
*查询RMQ rmq(int s,int v)
*将s-v 分成两个2^k的区间
*即 k=(int)log2(s-v+1)
*查询结果应该为 min(dp[s][k],dp[v-2^k+1][k])
*/

void makermq(int n,int b[])
{
    int i,j;
    for(i=0;i<n;i++)
        dp[i][0]=b[i];
    for(j=1;(1<<j)<=n;j++)
        for(i=0;i+(1<<j)-1<n;i++)
            dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int s,int v)
{
    int k=(int)(log((v-s+1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v-(1<<k)+1][k]);
}

void makeRmqIndex(int n,int b[]) //返回最小值对应的下标
{
    int i,j;
    for(i=0;i<n;i++)
        dp[i][0]=i;
    for(j=1;(1<<j)<=n;j++)
        for(i=0;i+(1<<j)-1<n;i++)
            dp[i][j]=b[dp[i][j-1]] < b[dp[i+(1<<(j-1))][j-1]]? dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
}
int rmqIndex(int s,int v,int b[])
{
    int k=(int)(log((v-s+1)*1.0)/log(2.0));
    return b[dp[s][k]]<b[dp[v-(1<<k)+1][k]]? dp[s][k]:dp[v-(1<<k)+1][k];
}

int main()
{
    int a[]={3,4,5,7,8,9,0,3,4,5};
    //返回下标
    makeRmqIndex(sizeof(a)/sizeof(a[0]),a);
    cout<<rmqIndex(0,9,a)<<endl;
    cout<<rmqIndex(4,9,a)<<endl;
    //返回最小值
    makermq(sizeof(a)/sizeof(a[0]),a);
    cout<<rmq(0,9)<<endl;
    cout<<rmq(4,9)<<endl;
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-20 06:28:57

RMQ(st在线算法模板)的相关文章

LCA最近公共祖先 在线算法和离线算法 模板

原理讲解:http://dongxicheng.org/structure/lca-rmq/ 在线算法模板: /** LCA在线算法O(nlogn) 主函数调用: init(); tot=0,dir[1]=0; dfs(1,1); ST(2*n-1); int lca=LCA(u,v); */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #in

LCA最近公共祖先 ST+RMQ在线算法

对于这一类的问题有2中解决方法.第一种就是tarjan的离线算法,还有一中是基于ST算法的在线算法.复杂度都是O(n); 先介绍在线算法: 1) dfs: 对于图所示的树,我们从根节点1开始dfs,按照先序访问(不算完全的先序),那么它访问顺序就是1 -> 2 -> 4 -> 2 -> 5 -> 7 -> 5 -> 8 -> 5 -> 2 -> 1 -> 3 -> 1 然后用数组first存第一次访问到该点时的时间(也就是访问顺序里面

LCA在线算法ST算法

求LCA(最近公共祖先)的算法有好多,按在线和离线分为在线算法和离线算法. 离线算法有基于搜索的Tarjan算法较优,而在线算法则是基于dp的ST算法较优. 首先说一下ST算法. 这个算法是基于RMQ(区间最大最小值编号)的,不懂的可以这里学习一些 而求LCA就是把树通过深搜得到一个序列,然后转化为求区间的最小编号. 比如说给出这样一棵树. 我们通过深搜可以得到这样一个序列: 节点ver 1 3 1 2 5 7 5 6 5 2 4 2 1 (先右后左) 深度R 1 2 1 2 3 4 3 4 3

LCA(倍增在线算法) codevs 2370 小机房的树

codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力.已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计

LCA在线算法详解

LCA(最近公共祖先)的求法有多种,这里先介绍第一种:在线算法. 声明一下:下面的内容参考了http://www.cnblogs.com/scau20110726/archive/2013/05/26/3100812.html. 在线算法就是利用了DFS和RMQ两种算法,它先是预处理好所有情况,然后根据输入输出答案,在输入比较多的时候用比较好. 上面两张图介绍了在线算法的做法,要理解并不难,下面附上实现代码: 1 /******************************* 2 dfs实现代

hdu 3078(LCA的在线算法)

Network Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 847    Accepted Submission(s): 347 Problem Description The ALPC company is now working on his own network system, which is connecting all

hihocoder1069最近公共祖先&#183;三(LCA在线算法--DFS+RMQ-ST)

树上任意两点的最近祖先,必定就是这两个节点的最短路径上深度最小的那个点. 例如:下图中,节点7和5,其最短路径为7--4--1--5, 这条路径上深度最小的点为节点1,其深度为1.节点1即为节点7和5的LCA. 因此,要找到任意两个节点的LCA,只需要先找到上述最短路径,再找到最短路径中深度最小的点.而这下面所述LCA在线算法所做的事. LCA在线算法描述(以上图为例): 1.获得“最短路径”(并不是真正的一条路径,包含其他节点,但不影响算法的正确性) 采用DFS遍历整棵树,得到以下数据: (1

POJ 1273 Drainage Ditches(网络流dinic算法模板)

POJ 1273给出M条边,N个点,求源点1到汇点N的最大流量. 本文主要就是附上dinic的模板,供以后参考. #include <iostream> #include <stdio.h> #include <algorithm> #include <queue> #include <string.h> /* POJ 1273 dinic算法模板 边是有向的,而且存在重边,且这里重边不是取MAX,而是累加和 */ using namespace

最近公共祖先(LCA):离线&amp;在线算法

问题:求两个结点的最近公共祖先(即在树中的公共祖先中高度最低的祖先),下面介绍两种适用于不同场景的算法. Hiho15:离线Tarjan算法 基本思想 Tarjan算法适用于离线批量处理多个查询请求.基本思想是以深度优先搜索的顺序访问这颗树,给这棵树的结点染色,一开始所有结点都是白色的,而当第一次经过某个结点的时候,将它染成灰色,而当第二次经过这个结点的时候--也就是离开这棵子树的时候,将它染成黑色. 这样做的意义,举例说明,当我们深度优先搜索到A结点时,我们发现A结点和B结点是我们需要处理的一