ST算法是求解RMQ问题最有效的方法之一,核心思想是以nlogn的复杂度递推f(i, 2^j) = min( f(i, 2^(j-1)), f(i + 2^(j-1), 2^(j-1)) ),其中f(i,2*j)表示arr[i, i + 2*j - 1]这个区间内的最小值
由于本题区间是确知的,所以递推时可以使用滚动数组来实现
#include <stdio.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
int n, k;
int m[1000000], M[1000000];
int main()
{
int i, j, t;
/* input */
scanf("%d %d", &n, &k);
for(i = 0; i < n; ++i){
scanf("%d", &m[i]);
M[i] = m[i];
}
/* special judge */
if(k == 1){
printf("%d", m[0]);
for(i = 1; i < n; ++i) printf(" %d", m[i]);
putchar('\n');
printf("%d", m[0]);
for(i = 1; i < n; ++i) printf(" %d", m[i]);
return 0;
}
/* create sparse table with rolling array */
k = min(k, n);
for(j = 1; (t = j << 1) < k; j = t){
for(i = 0; i + t <= n; ++i){
m[i] = min(m[i], m[i + j]);
M[i] = max(M[i], M[i + j]);
}
}
/* print result */
j = k - j;
printf("%d", min(m[0], m[j]));
for(i = 1; i + k <= n; ++i) printf(" %d", min(m[i], m[i + j]));
putchar('\n');
printf("%d", max(M[0], M[j]));
for(i = 1; i + k <= n; ++i) printf(" %d", max(M[i], M[i + j]));
return 0;
}