RMQ o(nlogn) o(1)

#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;
#define maxn 100000

int a[maxn];
int n;
int d[maxn][20];

void RMQ_init()
{
    for(int i=1; i<=n; i++)
        d[i][0] = a[i];

    for(int j=1; (1<<j)<=n; j++)
        for(int i=1; i+j-1<=n; i++)
        {
            d[i][j] = min(d[i][j-1], d[i+(1<<(j-1))][j-1]);
        }
}

int RMQ(int L, int R)
{
    int k = (int)(log((double)R-L+1)/log(2.0));
    return min(d[L][k], d[R-(1<<k)+1][k]);
}

int main()
{
    cin>>n;
    for(int i=1; i<=n; i++)
        cin>>a[i];
    RMQ_init();
    int q;
    cin>>q;
    int l, r;
    while(q--)
    {
        cin>>l>>r;
        cout<<RMQ(l, r)<<endl;
    }
    return 0;
}

/*

10
1 6 5 4 8 7 5 4 3 3
100
*/

时间: 2024-10-23 11:37:12

RMQ o(nlogn) o(1)的相关文章

【BZOJ3879】SvT 后缀树+虚树

转载请注明出处谢谢:http://blog.csdn.net/vmurder/article/details/42806431 SVT什么意思? suffix virtual tree. 没有错!后缀虚树 好了,下面发一段以前的文字. 话说其实后缀数组分治能写,当时想shei了. Vn: 啊,水题. 一看到"后缀"和这数据范围,肯定后缀数组.后缀自动机.后缀树走起! 然后我们可以轻松构造出来一个后缀树,然后每次询问树形DP随便乱搞就能过了.但是这个时候显然会TLE,所以我们可以尝试利用

hdu5381 The sum of gcd]莫队算法

题意:http://acm.hdu.edu.cn/showproblem.php?pid=5381 思路:这个题属于没有修改的区间查询问题,可以用莫队算法来做.首先预处理出每个点以它为起点向左和向右连续一段的gcd发生变化的每个位置,不难发现对每个点A[i],这样的位置最多logA[i]个,这可以利用ST表用nlognlogA[i]的时间预处理,然后用二分+RMQ在nlogn的时间内得到.然后就是区间变化为1时的转移了,不难发现区间变化为1时,变化的答案仅仅是以变化的那一个点作为左端点或右端点的

HDU_6194 后缀数组+RMQ

好绝望的..想了五个多小时,最后还是没A...赛后看了下后缀数组瞬间就有了思路...不过因为太菜,想了将近两个小时才吧这个题干掉. 首先,应当认为,后缀数组的定义是,某字符串S的所有后缀按照字典序有小到大的顺序排列(使用下标表示后缀).因为具体过程没太看懂,但是参见刘汝佳蓝书<算法竞赛黑暗圣典>可以得到一个聪明的NLOGN的神器算法.不过这个不太重要. 之后还可以通过他在LCP问题中提到的RANK,height数组相关算法,处理出来height数组,之后其他的可以扔掉. <黑暗圣典>

RMQ模板

附上一个详细的大佬的讲解  http://blog.csdn.net/niushuai666/article/details/6624672 RMQ模板(NYOJ 119) #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <vector> #include <algorithm> #include <cmath>

POJ 3264 RMQ裸题

POJ 3264 题意:n个数,问a[i]与a[j]间最大值与最小值之差. 总结:看了博客,记下了模板,但有些地方还是不太理解. #include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #

RMQ问题——ST算法

什么是RMQ.ST:RMQ(Range Minimum/Maximum Query)问题,即求区间的最值.可以写一个线段树来实现,但是每次查询的时间复杂度为O(log n),若查询次数过多则可能超时.ST算法是一种离线算法,经过O(nlogn)的预处理后,可以在O(1)的时间复杂度内进行查询,缺点是无法对数据做出修改. 算法实现: 初始化:用dp实现初始化.a[]为原始数据数组f,[i][j]表示从i向后的2j个数字中的最值.显然f[i][0]=a[i]; 我们将f[i][j]分为两段,一段为a

BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )

二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) --------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cctype> using namespace std; typedef long long

RMQ区间求最值

RMQ用于区间快速查找最值,适用于期间数值无更改的情况.其预处理的复杂度为O(nlogn),查询的时间复杂度为O(1),对比于线段树的预处理O(nlogn),查询O(logn)来说,在某些情况下有着其独到的优势. RMQ原理就是在原来的数组上跑一个dp,我们以查询最大值为例,它的状态定义是这样的: dp[ i ][ j ]:下标从i开始,长度为2^j的区间的最大值.显然dp[ i ][ 0 ]就是下标是i的那个数字本身. 下面给出其转移方程: dp[ i ][ j ] = max( dp[ i

POJ2452---Sticks Problem(单调栈+RMQ,方法不够优秀)

Description Xuanxuan has n sticks of different length. One day, she puts all her sticks in a line, represented by S1, S2, S3, -Sn. After measuring the length of each stick Sk (1 <= k <= n), she finds that for some sticks Si and Sj (1<= i < j &