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

来源:互联网 发布:uri malformed 解决js 编辑:程序博客网 时间:2024/05/17 06:17

本文就来讲解一下什么是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
原创粉丝点击