询问任意区间的min,max,gcd,lcm,sum,xor,or,and
给我们n个数,然后有m个询问,每个询问为L,R,询问区间[L,R]的最大最小值,最小公约数,最大公约数,和,异或,或,且
这些问题通通可以用RMQ的思想来解决。
以下用xor来作为例子
设dp[i][j]为以i开头的,长度为2^j的区间的所有值得异或
那么dp[i][j] = dp[i][j-1] xor dp[i+(1<<(j-1))][j-1]
这样,运用动态规划的思想,我们可以在nlogn的时间复杂度内算出以任意点开头的,长度为1,2,4,8...2^j 的区间的异或值。
那么询问任意区间的异或值时,只要将L->R之间的距离用二进制数来表示,那么只需要log(R-L+1)步就能求出所需的询问。
1 #include <stdio.h> 2 #include <string.h> 3 const int N = 100000 + 10; 4 int a[N]; 5 int dp[N][30]; 6 int n; 7 void init() 8 { 9 for(int i=1;i<=n;++i) 10 dp[i][0] = a[i]; 11 for(int j=1;(1<<j)<=n;++j) 12 { 13 for(int i=1;i+(1<<j)-1<=n;++i) 14 { 15 dp[i][j] = dp[i][j-1] ^ dp[i+(1<<(j-1))][j-1]; 16 } 17 } 18 } 19 20 int query(int L, int R) 21 { 22 int ans = 0; 23 int seg = R - L + 1; 24 int tmp = 1, i = 0; 25 while(seg) 26 { 27 if(seg&1) 28 { 29 ans ^= dp[L][i]; 30 L += tmp; 31 } 32 seg>>=1; 33 i++; 34 tmp = tmp * 2; 35 } 36 return ans; 37 } 38 int main() 39 { 40 while(scanf("%d",&n)!=EOF) 41 { 42 for(int i=1;i<=n;++i) 43 scanf("%d",&a[i]); 44 init(); 45 int m,L,R; 46 scanf("%d",&m); 47 while(m--) 48 { 49 scanf("%d%d",&L,&R); 50 printf("%d\n",query(L,R)); 51 } 52 } 53 return 0; 54 }
同理,以上所说的其他问题同样能够求解。
预处理的时间复杂度是O(nlogn), 每次询问是O(logn)