POJ 3264 Balanced Lineup ST算法
2015-12-18 09:45
295 查看
ST算法即是sparse table算法,就是稀疏表的意思,就是利用二分法来划分一个表,划分为2的次方段,之后利用这个st表计算查询结果,能够使得预处理时间O(nlgn),而查询时间为O(1) ;
那么有人会有疑问。既然查询时间是O(1)。那么为什么这个算法非常多时候并不比线段树快多少。甚至根本没有快过呢?
由于事实上查询时间为O(log(range)), range为查询区间的大小,由于要找到range二进制的最高位数,能够使用floor(log(range))的数学方法查找这个数。只是也是须要lg(rang)的时间效率。由于range不算太大。故此这点时间效率能够觉得是O(1).只是这就解析了为什么这个算法的查询时间不比线段树快多少。由于线段树的查询时间就是log(range)。
网上非常少人指出指点,一般都是笼统地说查询时间是O(1), 好像也不少人为此感到疑惑,故此解析下。
只是也能够这么说算法本身的查询时间效率是O(1)。而实际运行起来却是 O(logn)。或者说理论上的时间效率是O(1),实际时间效率是O(logn)。
预计这就是为什么非常多大牛的博客或者一些书本上也是写这个算法的查询效率是O(1)了。
说究竟就是一个数学方法计算。
详细能够參考topcoder或者參考这个大牛的吧:http://blog.csdn.net/v_july_v/article/details/18312089
本算法的优势就是代码量会比线段树省点。
掌握了当中的数学原理之后,这个算法还是非常好写的。
只是有线段树的存在,那么这个算法好像也不是不可缺少的。
那么有人会有疑问。既然查询时间是O(1)。那么为什么这个算法非常多时候并不比线段树快多少。甚至根本没有快过呢?
由于事实上查询时间为O(log(range)), range为查询区间的大小,由于要找到range二进制的最高位数,能够使用floor(log(range))的数学方法查找这个数。只是也是须要lg(rang)的时间效率。由于range不算太大。故此这点时间效率能够觉得是O(1).只是这就解析了为什么这个算法的查询时间不比线段树快多少。由于线段树的查询时间就是log(range)。
网上非常少人指出指点,一般都是笼统地说查询时间是O(1), 好像也不少人为此感到疑惑,故此解析下。
只是也能够这么说算法本身的查询时间效率是O(1)。而实际运行起来却是 O(logn)。或者说理论上的时间效率是O(1),实际时间效率是O(logn)。
预计这就是为什么非常多大牛的博客或者一些书本上也是写这个算法的查询效率是O(1)了。
说究竟就是一个数学方法计算。
详细能够參考topcoder或者參考这个大牛的吧:http://blog.csdn.net/v_july_v/article/details/18312089
本算法的优势就是代码量会比线段树省点。
掌握了当中的数学原理之后,这个算法还是非常好写的。
只是有线段树的存在,那么这个算法好像也不是不可缺少的。
#include <cstdio> #include <algorithm> const int MAX_N = 50001; const int L = 17;//16;//(int)log(MAX_N) / log(2) + 1; int N, Q, A, B; int maxArr[MAX_N][L], minArr[MAX_N][L]; void initRMQ_ST() { for (int j = 1; j < L; j++) for (int i = 1; i <= N; i++) { if (i - 1 + (1<<j) <= N) { maxArr[i][j]=max(maxArr[i][j-1], maxArr[i+(1<<(j-1))][j-1]); minArr[i][j]=min(minArr[i][j-1], minArr[i+(1<<(j-1))][j-1]); } else break;//能够break掉 } } inline int query(int low, int up) { int range = up - low + 1; int r = 0; while ((1<<(r+1)) <= range) r++; int maxV = max(maxArr[low][r], maxArr[up-(1<<r)+1][r]); int minV = min(minArr[low][r], minArr[up-(1<<r)+1][r]); return maxV - minV; } int main() { while (scanf("%d %d", &N, &Q) != EOF) { for (int i = 1; i <= N; i++) { scanf("%d", &maxArr[i][0]); minArr[i][0] = maxArr[i][0]; } initRMQ_ST(); while (Q--) { scanf("%d %d", &A, &B); printf("%d\n", query(A, B)); } } return 0; }
相关文章推荐
- ReactiveCocoa源码拆分解析(一)
- 如何禁用Eclipse的Validating
- 第三个Sprint团队贡献分
- 理解SVM的三层境界-支持向量机通俗导论
- poj--2955--Brackets(区间dp)
- OS 10.11 cocoaPod 使用,详细教程
- mongodb查询
- 03 Prefix Sums
- VMware Workstation 11 中 Ubuntu 14.04 的 VMware Tools 问题 : 共享文件夹
- 理解内核initcall
- java、javac -version不一致(java编译及运行环境不一致)的环境变量设置问题解决
- 兼容ie8以下的圆角头像制作方法
- android开发游记:DrawerLayout 实现抽屉效果的导航菜单
- poj--2955--Brackets(区间dp)
- 电商平台稳定性的保证 分布式压力测试
- Android之Intent
- 迭代器失效
- Android实用的任务管理器—tractor
- linux文件权限以及权限修改命令
- NGINX 配置Thinkphp