区间最值ST算法

题目描述

给出一大串数字(编号为1到N),给定M个询问,每次询问两个数字A,B,要求A到B这段区间内的最大数。

输入输出格式

输入格式:

一个整数N表示数字的个数,接下来一行为N个数。第三行读入一个M,接下来M行,每行都有两个整数A,B。

输出格式:

输出共M行,每行输出一个数。

输入输出样例

输入样例#1:

6
34 1 8 123 3 2
4
1 2
1 5
3 4
2 3

输出样例#1:

34
123
123
8

说明

对于30%的数据,1<=N<=10000,1<=M<=100

对于100%的数据,1<=N<=200000,1<=M<=10000.

sparse table

f[i][j]表示从i向前走2^j步之间的最小值

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
int a[400000],f[400000][30];
int n,m;
int max(int a,int b){
    if(a>b) return a;
    return b;
}
void init(){
    for(int i=1;i<=n;++i) f[i][0]=a[i];
    for(int j=1;j<=30;++j)
     for(int i=(1<<j);i<=n;++i)
      f[i][j]=max(f[i][j-1],f[i-(1<<(j-1))][j-1]);//预处理,RMQ
}
int query(int l,int r){
    int x=log(r-l+1)/log(2);
    return max(f[r][x],f[l+(1<<x)-1][x]);//将区间分成两二进制数段
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    init();
    scanf("%d",&m);
    for(int i=1;i<=m;++i){
        int l,r;
        scanf("%d %d",&l,&r);
        printf("%d\n",query(l,r));
    }
    return 0;
}
时间: 2024-08-06 07:58:35

区间最值ST算法的相关文章

51NOD1174 区间最大数 &amp;&amp; RMQ问题(ST算法)

RMQ问题(区间最值问题Range Minimum/Maximum Query) ST算法 RMQ(Range Minimum/Maximum Query),即区间最值查询,是指这样一个问题:对于长度为n的数列a,回答若干询问RMQ(A,i,j)(i, j<=n),返回数列a中下标在i,j之间的最小/大值.如果只有一次询问,那样只有一遍for就可以搞定,但是如果有许多次询问就无法在很快的时间处理出来.在这里介绍一个在线算法.所谓在线算法,是指用户每输入一个查询便马上处理一个查询.该算法一般用较长

poj--3264Balanced Lineup+ST算法求区间最大最小值

题目链接:点击进入 其实这种动态查询区间最大最小值的题目,解法是有很多的,像是线段树和树状数组都是可以做的.ST算法效率和上面两种是一样的,但是编码更为简单. ST算法是一种利用了递推思想进行计算的算法,令dp(i,j)表示从i开始长度为2^j的一段元素中的最小值,则dp(i,j)=min(dp(i,j-1),dp(i+2^(j-1),j-1)).这是求区间最小值的递归关系,其实求区间最大值也是一样的. 代码如下: #include<iostream> #include<cstring&

D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input standard input output standard output An array of positive integers a1,?a2,?...,?an is given. Let us consider its arbitrary subarray al,?al?+?1...,?ar, where 1?

RMQ(模板 ST 区间最值,频繁的间隔时间)

PS: 介绍:http://blog.csdn.net/liang5630/article/details/7917702 RMQ算法.是一个高速求区间最值的离线算法,预处理时间复杂度O(n*log(n)).查询O(1).所以是一个非常高速的算法,当然这个问题用线段树相同可以解决. 1.求区间的最大值和最小值! 代码例如以下: #include <cstdio> #include <cstring> #include <cmath> #include <iostr

算法模板——线段树3(区间覆盖值+区间求和)

实现功能——1:区间覆盖值:2:区间求和 相比直接的区间加,这个要注重顺序,因为操作有顺序之分.所以这里面的tag应该有个pushup操作(本程序中的ext) 1 var 2 i,j,k,l,m,n,a1,a2,a3,a4:longint; 3 a,b,d:array[0..100000] of longint; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end;

算法模板——线段树4(区间加+区间乘+区间覆盖值+区间求和)

实现功能——1:区间加法 2:区间乘法 3:区间覆盖值 4:区间求和 这是个四种常见线段树功能的集合版哦...么么哒(其实只要协调好三种tag的关系并不算太难——前提是想明白了线段树的工作模式) 代码长度几经修改后也大为缩水 还有!!!——通过BZOJ1798反复的尝试,我的出来一个重要结论——尽量减少pushup操作的不必要使用次数,对于程序提速有明显的效果!!! 1 type vet=record 2 a0,a1:longint; 3 end; 4 var 5 i,j,k,l,m,n,a1,

POJ2019:二维ST算法解决静态方阵最值问题

我们其实是很有必要把ST算法拓展到二维的,因为二维的RMQ问题还是不少的 int N,B,K; int mm[505]; int val[maxn][maxn]; int dpmin[maxn][maxn][8][8]; int dpmax[maxn][maxn][8][8]; 这里的N是方阵的长宽,此处是正方形题目,然后mm是预处理出来的,方便计算指数 dpmin和dpmax就是预处理数组了 然后看一下开局预处理: void initRMQ(int n,int m) { for(int i=1

RMQ问题——ST算法

什么是RMQ.ST:RMQ(Range Minimum/Maximum Query)问题,即求区间的最值.可以写一个线段树来实现,但是每次查询的时间复杂度为O(log n),若查询次数过多则可能超时.ST算法是一种离线算法,经过O(nlogn)的预处理后,可以在O(1)的时间复杂度内进行查询,缺点是无法对数据做出修改. 算法实现: 初始化:用dp实现初始化.a[]为原始数据数组f,[i][j]表示从i向后的2j个数字中的最值.显然f[i][0]=a[i]; 我们将f[i][j]分为两段,一段为a

树状数组求区间最值

树状数组求区间最值 树状数组(Binary Index Tree)利用二进制的一些性质巧妙的划分区间,是一种编程,时间和空间上都十分理想的求区间和的算法,同样我们可以利用树状数组优美的区间划分方法来求一个序列的最值 约定以 num[]  表示原数组, 以 idx[] 表示索引数组, Lowbit(x)=x&(-x) 树状数组求和时通过构造数组 idx[] 使 idx[k]=sum(num[tk]), tk [k-Lowbit(k)+1,k], 使用同样的方法构造最值索引数组: 以最大值为例, 先