poj 2019 Cornfields
分析
二维RMQ,maxn[i][j][a][b]表示以(i,j)为左上顶点,以(i+2^a-1,j+2^b-1)为右下顶点的矩形内的最大值,minn数组同理...
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #define N 260 5 #define M 9 6 using namespace std; 7 int maxn[N][N][M][M],minn[N][N][M][M]; 8 int n,b,k; 9 void init(){ 10 for(int a=0;(1<<a)<=n;a++) 11 for(int b=0;(1<<b)<=n;b++) 12 if(!(a==0&&b==0)) 13 for(int i=1;i+(1<<a)-1<=n;i++) 14 for(int j=1;j+(1<<b)-1<=n;j++){ 15 if(a==0){ 16 maxn[i][j][a][b]=max(maxn[i][j+(1<<(b-1))][a][b-1],maxn[i][j][a][b-1]); 17 minn[i][j][a][b]=min(minn[i][j+(1<<(b-1))][a][b-1],minn[i][j][a][b-1]); 18 } 19 else{ 20 maxn[i][j][a][b]=max(maxn[i+(1<<(a-1))][j][a-1][b],maxn[i][j][a-1][b]); 21 minn[i][j][a][b]=min(minn[i+(1<<(a-1))][j][a-1][b],minn[i][j][a-1][b]); 22 } 23 } 24 } 25 int query(int x1,int y1,int x2,int y2){ 26 int k1=0,k2=0; 27 while((1<<k1)<=(x2-x1+1))++k1;--k1; 28 while((1<<k2)<=(y2-y1+1))++k2;--k2; 29 int max1=max(maxn[x1][y1][k1][k2],maxn[x1][y2-(1<<k2)+1][k1][k2]); 30 int max2=max(maxn[x2-(1<<k1)+1][y2-(1<<k2)+1][k1][k2],maxn[x2-(1<<k1)+1][y1][k1][k2]); 31 int max3=max(max1,max2); 32 int min1=min(minn[x1][y1][k1][k2],minn[x1][y2-(1<<k2)+1][k1][k2]); 33 int min2=min(minn[x2-(1<<k1)+1][y2-(1<<k2)+1][k1][k2],minn[x2-(1<<k1)+1][y1][k1][k2]); 34 int min3=min(min1,min2); 35 return max3-min3; 36 } 37 int main(){ 38 while(~scanf("%d%d%d",&n,&b,&k)){ 39 for(int i=1;i<=n;i++) 40 for(int j=1;j<=n;j++){ 41 scanf("%d",&maxn[i][j][0][0]); 42 minn[i][j][0][0]=maxn[i][j][0][0]; 43 } 44 init(); 45 46 while(k--){ 47 int x,y; 48 scanf("%d%d",&x,&y); 49 printf("%d\n",query(x,y,x+b-1,y+b-1)); 50 } 51 } 52 return 0; 53 }