【题目大意】:给出一些数,求出区间内最大值减去最小值的差值。
【解题思路】:经典的RMQ问题啊,用ST算法。&&还有线段树写法,改天写一下。
【ST算法】:
下面简单介绍一下ST算法:
•Sparse
Table(ST)算法是基于倍增思想设计的O(Nlog2N) –O(1)的在线算法
•算法记录从每个元素开始的连续的长度为2k的区间中元素的最小值,并以在常数时间内解决询问
•定义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对于长度为2k的区间的最大值,可以由两个长度为2k-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;
}