我们其实是很有必要把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 }
原文地址:https://www.cnblogs.com/aininot260/p/9379833.html
时间: 2024-10-25 15:11:45