zoukankan      html  css  js  c++  java
  • RMQ 区间最值查询 入门

    RMQ 区间最值查询 入门

    博客推荐

    讲解不错:https://blog.csdn.net/qq_41311604/article/details/79900893

    一些细节讲解:https://blog.csdn.net/xi__long/article/details/36933515

    总结

    RMQ(Range Minimum/Maximum Query)即区间最值查询。RMQ算法一般用较长时间做预处理,时间复杂度为O(nlogn),然后可以在O(1)的时间内处理每次查询。

    主要是来解决:给你一个数组 ,其中有N个数字,现在给你多次询问,给你区间[l,r],问你在这个区间内的最值为多少?

    我们设二维数组dp[i][j]表示从第i位开始连续 $$2^j$$个数中的最小值。例如dp[2][1]就表示从第二位数开始连续两个数的最小值(也就是从第二位数到第三位数的最小值),dp[i][0]就表示第i个数字本身。

    模板代码

    void rmq_init() //RMQ初始化
    {
        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)-1<=n; i++)
                dp[i][j]=min(dp[i][j-1], dp[i+(1<<j-1)][j-1]); //i + (1 << (j - 1))
        //左移操作符的优先级小于加号的优先级
    }
    
    //查询部分代码
    int rmq(int l, int r)
    {
        int k=log2(r-l+1);
        return min(dp[l][k], dp[r-(1<<k)+1][k]);
    }
    

    入门题目

    POJ 3264

    题意是说给你一系列的数,然后求给定区间上的最大值和最小值。

    就是个模板题了,线段树也可以,但是RMQ代码量更少。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<stack>
    #include<queue>
    #include<map>
    typedef long long ll;
    using namespace std;
    const double esp=1e-6;
    const int inf=0x3f3f3f3f;
    const int MAXN=5e4+7;
    int num[MAXN], madp[MAXN][20], midp[MAXN][20];
    int n, q;
    void init()
    {
    	for(int i=1; i<=n; i++)
    	{
    		madp[i][0]=num[i];
    		midp[i][0]=num[i];
    	}
    	for(int j=1; (1<<j) <=n; j++)
    		for(int i=1; i+(1<<j)-1<=n; i++)
    		{
    			madp[i][j]=max(madp[i][j-1], madp[i+(1<<j-1)][j-1]);
    			midp[i][j]=min(midp[i][j-1], midp[i+(1<<j-1)][j-1]);	
    		} 
    }
    int rmq_max(int l, int r)
    {
    	int k=log2(r-l+1);
    	return max(madp[l][k], madp[r-(1<<k)+1][k]);
    }
    int rmq_min(int l, int r)
    {
    	int k=log2(r-l+1);
    	return min(midp[l][k], midp[r-(1<<k)+1][k]);
    }
    int main()
    {
    	while(scanf("%d%d", &n, &q)!=EOF)
    	{
    		for(int i=1; i<=n; i++)
    		{
    			scanf("%d",&num[i]);
    		}
    		init();
    		int l, r;
    		for(int i=1; i<=q; i++)
    		{
    			scanf("%d%d",&l, &r);
    			printf("%d
    ", rmq_max(l, r)-rmq_min(l, r));
    		}
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    无法直接启动带有"类库输出类型"的项目解...
    基于.NET的免费开源的模板引擎---VTemplate(转)
    用户 'IIS APPPOOLDefaultAppPool' 登录失败。
    如何获得配置文件中,连接数据库的连接字符串
    如何获取数据库的链接字符串
    IIS运行.NET4.0配置
    Repeater用法
    asp.net三层架构详解
    C#本地时间转Unix时间
    C#Timer
  • 原文地址:https://www.cnblogs.com/alking1001/p/12309982.html
Copyright © 2011-2022 走看看