用ST算法(ST表) 求解RMQ(区间最值)问题

//poj 3264

//O(n log(n) )

//只能用于静态数据,并且只能求区间最大或者最小,动态数据的话用线段树吧。

//实质是二进制的增倍

//单独此算法运用场合不多见。LCA可用到ST。

//挺简单的,但是看了2个多小时才能自己写出来&写对,学习的时候不知道自己有没有在思考,好笨,我哭了。

//详解见https://blog.csdn.net/a_bright_ch/article/details/81062039

 1 #include
 2 #include
 3 #include
 4 #include
 5 using namespace std;
 6 
 7 const int MAXN = 5e4+5;
 8 
 9 int n, m; // n个数 m次查询
10 int a[MAXN];
11 int maxn[MAXN][32];// f[i][j] 表示从第i位起的 2^j 个数中的最大值 区间[i, i+(1<
12 int minn[MAXN][32];
13 
14 void ST() {
15     for(int i = 1; i <= n; ++i) maxn[i][0] = minn[i][0] = a[i];
16     int m = (int)log2(n*1.0)/log2(2*1.0);
17     for(int j = 1; j <= m; ++j) {
18         for(int i = 1; i+(1<1 <= n; ++i) {
19             maxn[i][j] = max(maxn[i][j-1], maxn[i+(1<<(j-1))][j-1]);
20             minn[i][j] = min(minn[i][j-1], minn[i+(1<<(j-1))][j-1]);
21         }
22     }
23 }
24 
25 int query(int l, int r) {
26     int k = log2(r-l+1)/log2(2);
27     return max(maxn[l][k], maxn[r-(1<1][k]) - min(minn[l][k], minn[r-(1<1][k]);
28 }
29 
30 int main() {
31     scanf("%d%d", &n, &m);
32     for(int i = 1; i <= n; ++i) {
33         scanf("%d", &a[i]);
34     }
35     ST();
36     int l, r;
37     for(int i = 0; i != m; ++i) {
38         scanf("%d%d", &l, &r);
39         printf("%d\n", query(l, r));
40     }
41     return 0;
42 }

你可能感兴趣的:(用ST算法(ST表) 求解RMQ(区间最值)问题)