• C++ RMQ问题


    RMQ问题是区间求最值问题,就是求一个数组第i个到第j个中最大数或最小数的算法。

    这个算法有一些倍增思想,也有一些二分思想。具体是一个数组,m[i][j]表示从i开始往后数2的j次方个数的最大值或最小值是几。

    我们可以很明显的看出,m[i][j]=max(m[i][j-1],m[i+pow(2,j-1)][j-1]);这样就能求出所有i后2的j次方里最大的数了。

    但是有一个问题,(可能只有我不会。)如果让查找的区间长度不是2的次方怎么办?我也是想了20分钟。得到了结果,让中间重合一部分,凑成2个log(r-l+1)次方。就可以了。

    具体操作是max(l开始向后查看2的log(r-l+1)次方,r向前查看2的log(r-l+1)次方),或者min。这样每次运行都是2的次方,也没有多查找。

    有一个地方大家需要注意,要提前算,要提前算,要提前算!!!

    提前算好特别香,中间pow慢到死哎。

    正经代码来了:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<cstring>
    using namespace std;
    long long m[100005][20],md[100005][20],l,r,n,mid,d,x,s,sz[30]={1};
    int main()
    {
        cin>>n>>s;
        for(int i=1;i<=20;i++)
        {
        	sz[i]=sz[i-1]*2;
    	}
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&md[i][0]);
        }
        for(int j=1;j<=log2(n);j++)
        {
            for(int i=1;i+sz[j]-1<=n;i++)
            {
                md[i][j]=max(md[i][j-1],md[i+sz[j-1]][j-1]);
            }
        }
    	for(int i=0;i<s;i++)
    	{
    		scanf("%lld%lld",&l,&r);
    		mid=log2(r-l+1);
    		d=max(md[l][mid],md[r-sz[mid]+1][mid]);
    		printf("%lld
    ",d);
    	} 
        return 0;
    }

    这个代码对应洛谷P3865。

    应该是对的,大家懂了吗,自己去试试吧。

    对了,从今天开始我要把某谷春令营的作业以及算法仔细学习,然后用自己认为简单的方式来讲解,希望可以帮助到去比赛的同学。

  • 相关阅读:
    0 MATLAB的基本语法测试(7.20)
    eclipse(java)安装swing designer
    Request的用法
    requests模拟登陆的三种方式
    requests模块使用代理
    利用Python爬取翻译网站的翻译功能
    request发送带headers和带参数的请求
    爬虫的介绍和概念
    ROBOTS协议
    爬虫的流程
  • 原文地址:https://www.cnblogs.com/lichangjian/p/12418914.html
Copyright © 2020-2023  润新知