【题目大意】:给出一些数,求出区间内最大值减去最小值的差值。
【解题思路】:经典的RMQ问题啊,用ST算法。&&还有线段树写法,改天写一下。
【ST算法】:
下面简单介绍一下ST算法:
•
Sparse Table
(
ST
)算法是基于倍增思想设计的
O(Nlog
2
N)
–
O(1)
的在线算法
•
算法记录从每个元素开始的连续的长度为
2
k
的
区间中元素的最小值,并以在常数时间内解决
询问
•
定义
rmq[i][k]
为区间
[i,i+(2^k)-1]
的最值,也即表
示从
i
开始,长度为
2^k
的区间的最值
•对于查询RMQ(A,i,j),区间[i,j]的最值= max(rmq[i][k],rmq[j-(1<<k)+1][k]) ,其中2^k是最接近区间长度的2的幂,即k =log(b-a+1.0)/log(2.0);
•
如果我们事先计算了所有的
rmq[i][k]
,则由已经计算的
结果就可以在
O(1)
的时间内解决询问
l
对于长度为
2
k
的区间的最大值,可以由两个长度为
2
k-1
的区间的最大值得到
,
rmq[i][k] =
max( rmq[i][k-1] , rmq[i+2^(k-1)][k-1] )
【代码】:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
int n,m,x,y;
int a[50100];
int rmq_min[50100][16],rmq_max[50100][16];
void init_rmq(){
for(int i=1;i<=n;i++) { rmq_max[i][0]=rmq_min[i][0]=a[i]; }
for(int k=1;(1<<k)<=n;k++)
for(int i=1;(i+(1<<k)-1)<=n;i++){
rmq_max[i][k]=max(rmq_max[i][k-1],rmq_max[i+(1<<(k-1))][k-1]);
rmq_min[i][k]=min(rmq_min[i][k-1],rmq_min[i+(1<<(k-1))][k-1]);
}
}
int search_rmq(int l,int r){
int k=(int)(log(r-l+1.0)/log(2.0));
return max(rmq_max[l][k],rmq_max[r-(1<<k)+1][k])-min(rmq_min[l][k],rmq_min[r-(1<<k)+1][k]);
}
int main() {
memset(rmq_min,0,sizeof(rmq_min));
memset(rmq_max,0,sizeof(rmq_max));
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++) scanf("%d",&a[i]);
init_rmq();
for (int i=1; i<=m; i++){
scanf("%d%d",&x,&y);
printf("%d\n",search_rmq(x,y));
}
return 0;
}