询问任意区间的min,max,gcd,lcm,sum,xor,or,and
2015-09-24 20:09
483 查看
给我们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)步就能求出所需的询问。
View Code
同理,以上所说的其他问题同样能够求解。
预处理的时间复杂度是O(nlogn), 每次询问是O(logn)
这些问题通通可以用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)步就能求出所需的询问。
#include <stdio.h> #include <string.h> const int N = 100000 + 10; int a ; int dp [30]; int n; void init() { for(int i=1;i<=n;++i) dp[i][0] = a[i]; for(int j=1;(1<<j)<=n;++j) { for(int i=1;i+(1<<j)-1<=n;++i) { dp[i][j] = dp[i][j-1] ^ dp[i+(1<<(j-1))][j-1]; } } } int query(int L, int R) { int ans = 0; int seg = R - L + 1; int tmp = 1, i = 0; while(seg) { if(seg&1) { ans ^= dp[L][i]; L += tmp; } seg>>=1; i++; tmp = tmp * 2; } return ans; } int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;++i) scanf("%d",&a[i]); init(); int m,L,R; scanf("%d",&m); while(m--) { scanf("%d%d",&L,&R); printf("%d\n",query(L,R)); } } return 0; }
View Code
同理,以上所说的其他问题同样能够求解。
预处理的时间复杂度是O(nlogn), 每次询问是O(logn)
相关文章推荐
- Java基础知识强化67:基本类型包装类之Integer直接赋值的面试题
- Swift 分类 结构体
- Linux命令操作
- 欢迎使用CSDN-markdown编辑器
- LeetCode----Longest Valid Parentheses
- poj3069(贪心)
- 白话经典算法系列之十四 腾讯2012年笔试题
- 地图的使用
- UEditor 编辑器跨域上传解决方法
- java学习之多线程1
- Redis 命令 - Strings
- Learning Spark - LIGHTNING-FAST DATA ANALYSIS 第三章 - (1)
- 数的长度 69 (数学+log的使用)
- 记/usr/bin/pt-stalk 的一个小bug
- 抓接口过程
- 用命令行管理s3
- PAT(甲级)1033
- @suppressWarnings("unchecked") java 中是什么意思 (一般放dao查询方法上)
- hdu 4006 第K大的数(优先队列)
- UVA - 455 Periodic Strings