【线段树】浅谈区间问题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

poj 2528 Mayor's posters(线段树区间覆盖、离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 49385   Accepted:...
  • aaaaacmer
  • aaaaacmer
  • 2015年07月28日 11:12
  • 704

zkw线段树详解

转载自:http://blog.csdn.net/qq_18455665/article/details/50989113 前言 首先说说出处:清华大学 张昆玮(zkw) - ppt 《统计的力...
  • keshuqi
  • keshuqi
  • 2016年08月14日 19:35
  • 4776

区间最值与线段树

区间最值问题: 有无序序列,求任意子区间段的最大值。 最常用的数据结构就是线段树。线段树是一种二叉搜索树,用分治的思想来解决,其中中间结果有点类似于动态规划的中间结果。我们用线段树可以快速地解决区间最...
  • ice110956
  • ice110956
  • 2013年09月26日 20:50
  • 1714

【codevs 3243】区间反转(线段树)

长天秋水共一色、叹孤鹜飞
  • reverie_mjp
  • reverie_mjp
  • 2016年09月07日 17:46
  • 731

线段树模板:点修改,区间修改

最近在看《算法竞赛入门经典训练指南》, 感觉以前的想法几乎完全是错的,模板并不一定能直接套。 最近在看线段树,才知道线段树每个节点的附加信息才是重头戏,因此完全套模板是不可行的。但是思想方法可以借鉴,...
  • qq_33929112
  • qq_33929112
  • 2016年10月10日 17:00
  • 502

线段树模板合集--单点替换,区间替换,区间增加3种情况

单点替换,单点增加,区间求最值,区间求和#include #include #include using namespace std; #define lson l , m , rt ...
  • qq547276542
  • qq547276542
  • 2016年05月30日 11:46
  • 3059

hihocoder 1078 线段树的区间修改 (线段树 区间更新 模板)

hihocoder 1078 线段树的区间修改 (线段树 区间更新 模板)
  • Tc_To_Top
  • Tc_To_Top
  • 2016年04月01日 13:11
  • 2123

code vs 3243 区间反转(线段树)

3243 区间翻转  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 钻石 Diamond 题解  ...
  • clover_hxy
  • clover_hxy
  • 2016年09月07日 17:07
  • 620

线段树?线段树!

引言: 人们自古都在寻找强大的数据结构,spaly被称作序列之王,维护序列基本上没有什么做不了的,然而天生不能可持久化的缺陷促使人们寻找更强的数据结构,因此诞生了无旋treap 线段树难道就没有翻身之...
  • orzGEOTCBRL
  • orzGEOTCBRL
  • 2016年07月13日 20:18
  • 2723

poj 2777(线段树+区间染色)

解题思路:这道题利用了线段树+位运算的思想,由于颜色的种类只有30种,所以int可以存下来,所以我们在线段树的节点里面加上status的状态信息,表示这段区间内的颜色信息,而且我们可以知道,父节点的s...
  • hexianhao
  • hexianhao
  • 2016年03月22日 21:53
  • 331
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【线段树】浅谈区间问题3
举报原因:
原因补充:

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