RMQ最大值最小值

时间:2022-07-08 15:13:50
#include<iostream>
#include
<cstdio>
#include
<cstring>
#include
<cmath>
using namespace std;
const int size = 100010;
int maxx[size][32],minn[size][32];
int n;
void init()
{
int k = log2(n);
for(int j = 1;j <= k;j ++)
{
for(int i = 1;i <= n;i ++)
{
maxx[i][j]
= max(maxx[i][j-1],maxx[i+(1<<j-1)][j-1]); //左边位运算优先级比较低,不用加括号
minn[i][j] = min(minn[i][j-1],minn[i+(1<<j-1)][j-1]); //这里[]内是[i+(1<<(j-1))],因为这个区间的另一部分是从上一部分末端开始。
}
}
}

int find(int l,int r)
{
int k = log2(r-l+1);
int maxans = max(maxx[l][k],maxx[r-(1<<k)+1][k]); //这两个区间可能有重复但是无关紧要,我要求的是最大和最小,就算重复也能求出最大和最小。
int minans = min(minn[l][k],minn[r-(1<<k)+1][k]); //同样,这个区间不会超过原区间的范围,因为分别从两个区间下手,考虑的最大化情况也是分别覆盖区间。
return (maxans - minans);
}

int main()
{
memset(minn,
60,sizeof(minn));
int q; scanf("%d%d",&n,&q);
for(int i = 1;i <= n;i ++)
{
scanf(
"%d",&maxx[i][0]);
minn[i][
0] = maxx[i][0];
}
init();
for(int i = 1;i <= q;i ++)
{
int a,b;
scanf(
"%d%d",&a,&b);
int ans = find(a,b);
printf(
"%d\n",ans);
}
return 0;
}