题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=119
题目分析:
这道题用的RMQ算法(range maximum/minimum query)
。这里做了几点优化。
1)定义dpMax和dpMin时,为什么17写在前面,因为内存中数据是按行连续的存的,所以初始化dpMax[0]和dpMin[0]相关数据时,可以直接用memcpy。
2)所有的求2的方幂的操作都是用的位运算,这样会比较快。在求比一个数小的最大的二的方幂,也就是这个数的最左边的1,没有用库函数。还没有研究过到底哪个快,但感觉用库函数可能不会比这个方式快吧?
#include<stdio.h> #include<string.h> const int N = 100001; int arr[N]; //因为10^5约等于2^16.6 int dpMax[17][N]; int dpMin[17][N]; int GetBit(unsigned int x) {//最高位的1的位置 int count = -1; while(x) { x >>= 1; ++count; } return count; } inline int max(const int a, const int b) { return a > b ? a : b; } inline int min(const int a, const int b) { return a < b ? a : b; } void RMQ(int n) { int k = GetBit(n); memcpy(&dpMax[0][1], &arr[1], n * sizeof(int)); memcpy(&dpMin[0][1], &arr[1], n * sizeof(int)); for(int j = 1; j <= k; ++j)//步长 { for(int i = 1; i <= n; ++i) { if(i + (1 << j) - 1 <= n) { dpMax[j][i] = max(dpMax[j - 1][i], dpMax[j - 1][i + (1 << (j - 1))]); dpMin[j][i] = min(dpMin[j - 1][i], dpMin[j - 1][i + (1 << (j - 1))]); } } } } int main() { int n,m,i; int a,b; int k,Max,Min; while(scanf("%d %d", &n, &m) != EOF) { for(i = 1; i <= n; ++i) scanf("%d", &arr[i]); RMQ(n); for(i = 0; i < m; ++i) { scanf("%d %d", &a, &b); k = GetBit(b - a + 1); Max = max(dpMax[k][a], dpMax[k][b - (1 << k) + 1]); Min = min(dpMin[k][a], dpMin[k][b - (1 << k) + 1]); printf("%d\n", Max - Min); } } return 0; }