POJ2019:二維ST算法解決靜態方陣最值問題
阿新 • • 發佈:2018-07-28
指數 rmq 方便 解決 最大值和最小值 st算法 完整 lse 正方
我們其實是很有必要把ST算法拓展到二維的,因為二維的RMQ問題還是不少的
int N,B,K; int mm[505]; int val[maxn][maxn]; int dpmin[maxn][maxn][8][8]; int dpmax[maxn][maxn][8][8];
這裏的N是方陣的長寬,此處是正方形題目,然後mm是預處理出來的,方便計算指數
dpmin和dpmax就是預處理數組了
然後看一下開局預處理:
void initRMQ(int n,int m) { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) dpmin[i][j][0][0]=dpmax[i][j][0][0]=val[i][j]; for(int ii=0;ii<=mm[n];ii++) for(int jj=0;jj<=mm[m];jj++) if(ii+jj) for(int i=1;i+(1<<ii)-1<=n;i++) for(int j=1;j+(1<<jj)-1<=m;j++) { if(ii) { dpmin[i][j][ii][jj] = min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]); dpmax[i][j][ii][jj] = max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]); } else { dpmin[i][j][ii][jj] = min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]); dpmax[i][j][ii][jj]= max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]); } } }
我們看預處理的時候還是比較明朗的,當然別忘了在主函數把mm初始化好
mm[0]=-1; for(int i=1;i<=500;i++) mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
然後就是求最大值和最小值的函數了,這裏,一定要仔細地去寫,很容易寫錯:
int rmq1(int x1,int y1,int x2,int y2) //max { int k1=mm[x2-x1+1]; int k2=mm[y2-y1+1]; x2=x2-(1<<k1)+1; y2=y2-(1<<k2)+1; return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2])); } int rmq2(int x1,int y1,int x2,int y2) { int k1=mm[x2-x1+1]; int k2=mm[y2-y1+1]; x2=x2-(1<<k1)+1; y2=y2-(1<<k2)+1; return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2])); }
這個式子確實很長的
最後給出題目完整的實現:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=255; 5 int N,B,K; 6 int mm[505]; 7 int val[maxn][maxn]; 8 int dpmin[maxn][maxn][8][8]; 9 int dpmax[maxn][maxn][8][8]; 10 void initRMQ(int n,int m) 11 { 12 for(int i=1;i<=n;i++) 13 for(int j=1;j<=m;j++) 14 dpmin[i][j][0][0]=dpmax[i][j][0][0]=val[i][j]; 15 for(int ii=0;ii<=mm[n];ii++) 16 for(int jj=0;jj<=mm[m];jj++) 17 if(ii+jj) 18 for(int i=1;i+(1<<ii)-1<=n;i++) 19 for(int j=1;j+(1<<jj)-1<=m;j++) 20 { 21 if(ii) 22 { 23 dpmin[i][j][ii][jj] = min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]); 24 dpmax[i][j][ii][jj] = max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]); 25 } 26 else 27 { 28 dpmin[i][j][ii][jj] = min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]); 29 dpmax[i][j][ii][jj] = max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]); 30 } 31 } 32 } 33 int rmq1(int x1,int y1,int x2,int y2) //max 34 { 35 int k1=mm[x2-x1+1]; 36 int k2=mm[y2-y1+1]; 37 x2=x2-(1<<k1)+1; 38 y2=y2-(1<<k2)+1; 39 return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2])); 40 } 41 int rmq2(int x1,int y1,int x2,int y2) 42 { 43 int k1=mm[x2-x1+1]; 44 int k2=mm[y2-y1+1]; 45 x2=x2-(1<<k1)+1; 46 y2=y2-(1<<k2)+1; 47 return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2])); 48 } 49 int main() 50 { 51 mm[0]=-1; 52 for(int i=1;i<=500;i++) 53 mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; 54 while(scanf("%d%d%d",&N,&B,&K)==3) 55 { 56 for(int i=1;i<=N;i++) 57 for(int j=1;j<=N;j++) 58 scanf("%d",&val[i][j]); 59 initRMQ(N,N); 60 int x,y; 61 while(K--) 62 { 63 scanf("%d%d",&x,&y); 64 printf("%d\n",rmq1(x,y,x+B-1,y+B-1)-rmq2(x,y,x+B-1,y+B-1)); 65 } 66 } 67 return 0; 68 }
POJ2019:二維ST算法解決靜態方陣最值問題