关闭

【线段树】浅谈区间问题3

标签: RMQ算法
181人阅读 评论(0) 收藏 举报
分类:

本文就来讲解一下什么是RMQ吧……

RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ问题是指求区间最值的问题。

RMQ运用的是倍增的思想
比如说已知数组[a]: 3 5 2 4 7 6
开一个F二维数组,F[i][j]表示从第i个数开始,共j^2个数中的最值。

来讲讲RMQ代码的实现

1.构建F数组
有点像dp,但又不完全是。i,j是枚举的,我们假设我们要求F[i][j]并且之前的所有数组已经被求出了。
那么F[i][j]={ F[i][j-1] || F[i+j^2][j-1] }
为什么呢?就是将所求区间分为前后俩个部分来实现,很容易懂对吧。

2.查询
查询(i,j)区间内的最值
那么设k为区间在F数组中的中点
k=log(j-i+1)/log(2)
ans={ F[i][k]||F[j-k^2+1][k] }
跟上面求F数组极其相似,将所需区间分为俩半,然后合并

分析 时间代价 O(logn*n 构造F + q 查询q次 )
优点:时间代价远小于线段树
缺点:不支持修改

上一道躶题

【问题描述】
每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连续的牛来进行比赛. 但是为了避免水平悬殊,牛的身高不应该相差太大. John 准备了Q (1 <= Q <= 180,000) 个可能的牛的选择和所有牛的身高 (1 <= 身高 <= 1,000,000). 他想知道每一组里面最高和最低的牛的身高差别. 注意: 在最大数据上, 输入和输出将占用大部分运行时间.

【问题分析】
RMQ维护最大最小俩个域即可

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int N=50001;
const int logN=17;
int n,q;    int h[N],Fmax[N][logN],Fmin[N][logN];
int readin()
{
    int x=0,f=1;  char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void read()
{
    int i;
    n=readin(); q=readin();
    for (i=1;i<=n;i++)
        h[i]=readin();
    return;
}
void RMQ()
{
    int i,j;
    for (i=1;i<=n;i++)
    {   
        Fmax[i][0]=h[i];
        Fmin[i][0]=h[i];
    }
    for (j=1;j<=logN;j++)
        for (i=1;i<=n;i++)
            if (i+(i<<j)-1<=n)
            {   
                Fmax[i][j]=max(Fmax[i][j-1],Fmax[i+(1<<(j-1))][j-1]);
                Fmin[i][j]=min(Fmin[i][j-1],Fmin[i+(1<<(j-1))][j-1]);
            }
    return;
}
void query(int a,int b)
{
    int k=log(b-a+1)/log(2);
    int mmin,mmax;
    mmin=min(Fmin[a][k],Fmin[b-(1<<k)+1][k]);
    mmax=max(Fmax[a][k],Fmax[b-(1<<k)+1][k]);
    printf("%d\n",mmax-mmin);
    return;
}
void work()
{
    int i,a,b;
    for (i=1;i<=q;i++)
    {
        a=readin(); b=readin();
        query(a,b);
    }
    return;
}
int main()
{
    read();
    RMQ();
    work();
    return 0;
}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:9687次
    • 积分:475
    • 等级:
    • 排名:千里之外
    • 原创:37篇
    • 转载:0篇
    • 译文:0篇
    • 评论:19条
    膜拜同班神犇
    心灵砒霜
    搞OI又有什么用呢,好像你能搞好什么的。
    不要轻易放弃,再耽误个一俩年什么的。
    坚持总会有结果的,一个月胖十斤。
    算法和数据结构你是学不完的。
    QwQ

    如果不是被I64d卡了 我是********
    所以rp++喽
    最新评论