1、作用
查找区间最值(最大值和最小值)
时间复杂度为 O(nlogn)预处理
查询只需要 O(1)的复杂度
2、原理分析
初始化就是复杂度最高的,也是较难理解的
可以将 i~j 的一块区域分为左边和右边来求解
因为是求最值 不是和或差 所以是成立的
如图

3、数组的定义
所以
4、处理
我们可以枚举j,i来求出最值
当然不要忘了赋初值
循环j,i(不要越界)
1 2 3 4 5 6
   | int i, j; for(j = 1; j <= log2(n); j++) { 	for(i = 1; i + (1 << j) - 1 <= n; i ++) { 		f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); 	} }
   | 
 
5、代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
   | #include<bits/stdc++.h> using namespace std;
  const int maxn = 1e5 + 2; int n, v[maxn], m; int f[maxn][35];
  int read(); #define r1 read()
  void ST_prepare() { 	int i, j; 	for(j = 1; j <= log2(n); j++) { 		for(i = 1; i + (1 << j) - 1 <= n; i ++) { 			f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); 		} 	} } 
  int ST_ask(int st, int ed) { 	int mid = log2(ed - st + 1); 	return max(f[st][mid] , f[ed - (1 << mid) + 1][mid]); } int main() { 	int i, j, x, y; 	 	n = r1;m = r1; 	for(i = 1; i <= n; i ++) { 		v[i] = r1; 		f[i][0] = v[i]; 	} 	 	ST_prepare(); 	 	for(i = 1; i <= m; i ++) { 		x = r1; 		y = r1; 		printf("%d\n",ST_ask(x,y)); 	} 	 	return 0; }
  int read() { 	char c = getchar(); 	int x = 0,f = 1; 	for(; !isdigit(c); c = getchar()) if(c == '-') f = -1; 	for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); 	return f * x; }
   | 
 
有错请大佬纠正