POJ3264 RMQ问题

虽然早知道st(Sparse Table)算法,今天第一次动手写,事无巨细,姑且记录一下。

朴素的离线做法是进行n*n次的预处理,生成所有(i,j)对的最小值,保存起来,查询只需O(1)。

st做法则是借助二分的做法,进行n*log次预处理,生成所有(i,j)对的最小值,但这里j是对2的幂。

RMQ的st算法和树状数组都在一定场合替代线段树,只是st多占些内存,多些预处理,查询快,是典型的离线算法。

需要注意的是,st预处理时应该对无效的数据不计算,这样在VC下比都计算要快大约一倍(3s+->1.6s)。

这道题在C++下比G++下提交耗时要少得多。

 

#include <cstdio> #include <algorithm> using namespace std; //求出下一个2的幂对2的对数(幂2整数的天花板函数) int logclp2(int x) { if (x == 0) { return 0; } int y = 1, count = 0; while (y < x) { y = (y << 1); ++count; } return count; } //求出上一个2的幂对2的对数(幂2整数的地板函数) int logflp2(int x) { int y = (1 << 16), count = 16; while (y > x) { y >>= 1; --count; } return count; } int st_max[50000][17]; int st_min[50000][17]; int main() { int N, Q, i, j, k; int l, M, m; //freopen("c://input.txt", "rb", stdin); scanf("%d%d", &N, &Q); for (i = 0; i < N; ++i) { scanf("%d", &k); st_max[i][0] = k; st_min[i][0] = k; } //预处理 l = logclp2(N) + 1; for (j = 1; j < l; ++j) { k = (1 << (j - 1)); for (i = 0; i + k < N; ++i) //注意!冗余部分不要计算 { st_max[i][j] = max(st_max[i][j - 1], st_max[i + k][j - 1]); st_min[i][j] = min(st_min[i][j - 1], st_min[i + k][j - 1]); } } //接受查询 for (; Q; --Q) { scanf("%d%d", &i, &j); k = logflp2(j - i + 1); printf("%d/n", max(st_max[i - 1][k], st_max[j - (1 << k)][k]) - min(st_min[i - 1][k], st_min[j - (1 << k)][k])); } return 0; }

 

你可能感兴趣的:(c,算法,table)