[学习笔记]ST表
前言:某次模擬賽T1被二維ST坑了。于是決心總結下。
?
ST表:O(常數)查詢靜態(tài)區(qū)間最值。
思想:利用倍增預處理。然后拼湊。
一維ST表:
f[i][j]表示,[i,i+(1<<j)-1]的區(qū)間最值。
lg[i]表示,log2i
#include<bits/stdc++.h> using namespace std; const int N=100000+10; int n,m; int a[N]; int f[N][30]; int lg[N]; int main() {scanf("%d%d",&n,&m);int t;for(int i=1;i<=n;i++) scanf("%d",&t),f[i][0]=t;for(int i=1;i<=n;i++) lg[i]=(i>>lg[i-1]+1)?lg[i-1]+1:lg[i-1];for(int j=1;(1<<j)<=n;j++)for(int i=1;(i+(1<<j)-1)<=n;i++){f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);}int l,r;for(int i=1;i<=m;i++){scanf("%d%d",&l,&r);int len=lg[r-l+1];printf("%d\n",max(f[l][len],f[r-(1<<len)+1][len]));}return 0; }?
二維ST表:
類似處理二維前綴和。
先求出每行單獨的,然后再把行并起來。
f[i][j][k][l]表示,行[i,i+(1<<k)-1]與列[j,j+(1<<l)-1]圍成的矩形的數的最值。
lg[i]同上。
#include<bits/stdc++.h> #define ri register int #define numb (ch^'0') using namespace std; typedef long long ll; const int N=303; void rd(int &x){x=0;char ch;while(!isdigit(ch=getchar()));for(x=numb;isdigit(ch=getchar());x=(x<<1)+(x<<3)+numb); } int a[N][N]; int f[N][N][12][12]; int n,m,q; int lg[N]; inline int Max(const int &a,const int &b){return a>b?a:b; } int main(){scanf("%d%d",&n,&m);int now=1,id=0;for(ri i=1;i<=max(n,m);++i){if(i==now) lg[i]=id,now*=2,++id;else lg[i]=lg[i-1];}for(ri i=1;i<=n;++i){for(ri j=1;j<=m;++j){rd(a[i][j]);f[i][j][0][0]=a[i][j];}}for(ri l=1;l<=10;++l){for(ri i=1;i<=n;++i){for(ri j=1;j+(1<<l)-1<=m;++j){f[i][j][0][l]=Max(f[i][j][0][l-1],f[i][j+(1<<(l-1))][0][l-1]);}}}for(ri k=1;k<=10;++k){for(ri l=0;l<=10;++l)for(ri i=1;i+(1<<k)-1<=n;++i){for(ri j=1;j+(1<<l)-1<=m;++j){f[i][j][k][l]=Max(f[i][j][k-1][l],f[i+(1<<(k-1))][j][k-1][l]);}}}scanf("%d",&q);int x1,x2,y1,y2;while(q--){rd(x1);rd(y1);rd(x2);rd(y2);int l1=x2-x1+1;int l2=y2-y1+1;int g1=lg[l1],g2=lg[l2];//cout<<g1<<" "<<l1<<" "<<g2<<" "<<l2<<endl;int ans=0;ans=Max(ans,f[x1][y1][g1][g2]);//cout<<ans<<endl;ans=Max(ans,f[x1][y2-(1<<g2)+1][g1][g2]);//cout<<ans<<endl;ans=Max(ans,f[x2-(1<<g1)+1][y1][g1][g2]);//cout<<ans<<endl;ans=Max(ans,f[x2-(1<<g1)+1][y2-(1<<g2)+1][g1][g2]);printf("%d\n",ans);}return 0; }?
?
樹上ST表
O(logn)查詢樹上兩點鏈之間的最值。logn因為要找LCA
處理方法類比倍增LCA。跳LCA的時候順便求出。
?
?
?
基于倍增思想的預處理。O(常數)查詢。
用于卡常數還是不錯的。
轉載于:https://www.cnblogs.com/Miracevin/p/9856967.html
總結
- 上一篇: Python 正则表达式(分组)
- 下一篇: git上的分支命名规范