看神仙学长的博客学的:传送门html
它是解决区间最值问题的一种强有力的数据结构(雾我也不知道应不该该叫数据结构)ios
它能够作到O(nlogn)预处理,O(1)查询最值算法
把给定区间分红长度是2的幂次的小区间。先预处理出它们中的最小值是多少,而后用一种相似二分的思想由小区间到大区间比较两个区间的最小值。数组
倍增讲解数据结构
不会的数学公式就只能截图了,咕咕咕....spa
**好像仍是不太懂边界,我果真太菜了,咕咕咕.....,只能背了.net
1.f[i][j] : 记录给定序列中区间[i,i+pow(2,j)-1]中的最大值。 ps:f[i][0]=a[i]
2.bit[i] : bit[i]=pow(2,i)-----记录2的i次方 能够用位运算<<代替,不过必定要加(),不然就咕咕咕了
3.a[i] :输入的数组
4.LC:在生成st表时做为f[i][j]中j的循环上界。3d
设有一长度为5的a数组:a1,a2,a3,a4,a5
长度为1的区间[1,1],[2,2],[3,3],[4,4],[5,5]code
长度为2的区间[1,2],[2,3],[3,4],[4,5]htm
长度为4的区间[1,4],[2,5]
用f[i][j]表示:f[i][j]=[i,i+pow(2,j)-1]
长度为1的区间: f[1][0] <=>[1,1]
f[2][0] <=>[2,2]
长度为2的区间: f[1][1] <=>[1,2]
f[2][1] <=>[2,3]
f[1][2] <=>[1,4]
f[2][2] <=>[2,5]
f[i][j]=max(f[i][j-1],f[i+pow(2,j-1)][j-1]);
题目描述:给定一个长度为 N 的数列,和 M 次询问,求出每一次询问的区间内数字的最大值。
第一次提交:
检查了检查发现i和j写反了,咕咕咕
NM仍是TLE,lzt和我查了好长时间错误后,发现数组开大了,咕咕咕咕.....
真是活久见了数组大了居然能tle而不是mle
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<map> #include<string> #include<cstring> #define ll long long int #define MAXN 100001 using namespace std; const int maxn=999999999; const int minn=-999999999; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int f[MAXN][41],a,lc,n,m,p,len,l,r; int main() { n=read(),m=read(); for(int i=1;i<=n;++i) a=read(),f[i][0]=a; lc=(int)(log(n)/log(2)); for(int j=1;j<=lc;++j) { for(int i=1;i<=n-(1<<j)+1;i++) { f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); } } for(int i=1;i<=m;++i) { l=read(),r=read(); p=(int)(log(r-l+1)/log(2)); cout<<max(f[l][p],f[r-(1<<p)+1][p])<<'\n'; } return 0; }