首页 > 代码库 > 关于st表的推导
关于st表的推导
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+7; int st[maxn][32]; int a[maxn],n; void init(){ int i,j; //st[i][j]表示i到i+2^j-1区间的最小值 //先预处理区间长度为1的 for(i=0;i<n;++i) st[i][0]=a[i]; for(i=0;i<n;++i){ for(j=1;i+2^(j)-1<n;++j){ //i~i+2^(j-1)-1 //i+2^(j-1)~i+2^(j-1)+2^(j-1)-1=>i+2^j-1; //一定要发现这个显然的事实就是 //2^(j-1)+2^(j-1)=2^j; st[i][j]=min(s[i][j-1],s[i+2^(j-1)][j-1]); } } } int queryMin(int l,int r){ int len=r-1+1; int index=log(len); //st[l][index] l~l+2^(index)-1 //2^(index)<=(r-l+1); l+2^(index)-1<=r //r-(l+2^(index)-1)>=0 还差多少元素没放进来 //x+LEN=l+2^(index)-1+(r-(l+2^(index)-1)); //x+2^(index)-1=r;//区间长度固定。。起点是多少才能正好跑到r,列一个简单的方程才能解决 //x=r+1-(2^(index)); return min(st[l][index],st[r+1-(2^(index))][index]); } int main(){ while(~scanf("%d",&n)){ int i,q,l,r; for(i=0;i<n;++i){ scanf("%d",a+i); } init(); scanf("%d",&q); for(i=0;i<q;++i){ scanf("%d%d",&l,&r); printf("%d\n",query(l,r)); } } return 0; }
上面这个^符号代表幂次。。而c++里只有异或。。这就是为什么这是一个伪代码的意思
先来一个终极伪代码
推导过程如上。。
下面给一个真正的的代码
#include <bits/stdc++.h> using namespace std; const int maxn=1e6+7; int st[maxn][32]; int a[maxn],n; void init(){ int i,j; //st[i][j]表示i到i+2^j-1区间的最小值 //先预处理区间长度为1的 for(i=0;i<n;++i) st[i][0]=a[i]; for(i=0;i<n;++i){ for(j=1;i+(1<<j)-1<n;++j){//这里有一个优化。。本来是小于32的。。问题规模较小是只是相当于一个常数的优化 //i~i+2^(j-1)-1 //i+2^(j-1)~i+2^(j-1)+2^(j-1)-1=>i+2^j-1; //一定要发现这个显然的事实就是 //2^(j-1)+2^(j-1)=2^j; st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } } int queryMin(int l,int r){ int k=log(r-l+1); //st[l][index] l~l+2^(index)-1 //2^(index)<=(r-l+1); l+2^(index)-1<=r //r-(l+2^(index)-1)>=0 还差多少元素没放进来 //x+LEN=l+2^(index)-1+(r-(l+2^(index)-1)); //x+2^(index)-1=r;//区间长度固定。。起点是多少才能正好跑到r,列一个简单的方程才能解决 //x=r+1-(2^(index)); return min(st[l][k],st[r+1-(1<<k)][k]); } int main(){ while(~scanf("%d",&n)){ int i,q,l,r; for(i=0;i<n;++i){ scanf("%d",a+i); } init(); scanf("%d",&q); for(i=0;i<q;++i){ scanf("%d%d",&l,&r); printf("%d\n",queryMin(l-1,r-1)); } } return 0; }
还有一个对于新手来说理解的坑。。那就是int x=log(val)实际上是对log的值向下取整。。这一点非常重要
只有这个成立我们注释里的推导才会成立。。另外有一些没用的推导。。但是我没有删掉。。这是因为想记录一下我全部的思考过程
关于st表的推导
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。