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

原创 2016年05月30日 19:11:43

本文就来讲解一下什么是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;
}
版权声明:QwQ By 20150112 QwQ

相关文章推荐

【线段树】浅谈区间问题(2)

这篇博客就谈谈树状数组好了(RMQ弃坑了)。。。 树状数组是一个优美而且神奇的东西,写起来特别简单并且效率优于线段树。 那么进入正题,什么事树状数组呢?我们先来看一个函数lowbit(x)=x&(...

【线段树】浅谈区间问题(1)

文章将谈到如下内容1、线段树,O(n)-O(qlogn) online。 2、ST(Sparse Table),O(nlogn)-O(q) online。1.线段树利用二分的思想将所求区间进行二分,...

线段树(3)之区间合并(基础题)

提一下,博主的英语四级过了,就是这么6(虽然考了两回)       区间合并:这类题目会询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并,因为有可能合并之后连续最长...

【USACO 2008 Nov Gold】 3.Light Switching(lites 开关灯) 区间修改线段树

题意: n、m,n个灯,m次操作 两种操作 0: 这段区间全部状态取反,初始全部为0          1: 询问这段区间有几个灯是亮的。 裸线段树,弱爆了。 #include #...

团体程序设计天梯赛-练习集-L3-002. 堆栈(线段树-区间第k大)

题目链接其实可以套主席树求动态的区间第k大。但是这里规定了范围[1,100000] 我们可以建立一颗线段树,线段树的节点值表示在这个区间内数的出现次数的总和 比如区间为[2,2]的节点的值为2的出...

【区间DP】【二维线段树】【二维树状数组】2017.5.20 T3 deliver 题解

Problem 3 (deliver.pas/cpp/c) 【题目描述】 有一个军队正在编队。他们有n个人,编号1-n,编队结构如下: 1.一个军队有一个指挥官 2.编号小于他们指挥官编号的组...

SPOJ 1716 GSS3 Can you answer these queries III 线段树区间合并

传送门:SPOJ 1716 题意 求动态区间最大子段和 题解 线段树区间合并维护区间和, 左右连续最大字段和, 最大字段和 AC code:#include #include #include...
  • ADjky
  • ADjky
  • 2017-01-17 17:21
  • 110

POJ 2777 Count Color (线段树 区间覆盖染色问题)

题目链接POJ2777题目大意有一条长度为n(n≤\le10510^5)的数轴,有T(T≤\le30)种颜色,有m个操作(m≤\le10510^5),操作有以下两种:C a b c:把a与中间染成c色...

Codeforces 482B 线段树与离线区间加和问题

题目大意是说,请你构造一个长度为n的数列,满足给定的
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)