创建两个ST表,分别保存区间最大值和最小值,对于每次查询,找出最大值和最小值相减即可。
这题时间卡得比较死,如果写得不好可能还会TLE
#include <algorithm>
#include <cmath>
#include <cstdio>
const int N = 5e4 + 5;
using namespace std;
int n, m;
int h[N], lg2[N], p2[20], stmax[N][20], stmin[N][20];
void init()
{
//预处理log2(n)和2的次方
lg2[0] = 0;
for (int i = 0; i < 20; i++)
{
//这里减一后在查询时就不用加一了
p2[i] = pow(2, i) - 1;
int end = min((int)pow(2, i + 1), n);
for (int j = pow(2, i); j <= end; j++)
{
lg2[j] = i;
stmin[j][0] = stmax[j][0] = h[j];
}
}
for (int i = 1; i < 20; i++)
{
int len = pow(2, i - 1);
if (len * 2 > n) break;
for (int j = n - len * 2 + 1; j >= 1; j--)
{
stmax[j][i] = max(stmax[j][i - 1], stmax[j + len][i - 1]);
stmin[j][i] = min(stmin[j][i - 1], stmin[j + len][i - 1]);
}
}
}
inline int qmax(int l, int r) { return max(stmax[l][lg2[r - l]], stmax[r - p2[lg2[r - l]]][lg2[r - l]]); }
inline int qmin(int l, int r) { return min(stmin[l][lg2[r - l]], stmin[r - p2[lg2[r - l]]][lg2[r - l]]); }
int main()
{
int l, r;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &h[i]);
init();
while (m--)
{
scanf("%d%d", &l, &r);
printf("%d\n", qmax(l, r) - qmin(l, r));
}
return 0;
}