[关闭]
@Chilling 2017-02-16T17:52:41.000000Z 字数 2919 阅读 1109

POJ-2019: Cornfields(2维RMQ)

RMQ


链接:POJ-2019

Description

FJ has decided to grow his own corn hybrid in order to help the cows make the best possible milk. To that end, he's looking to build the cornfield on the flattest piece of land he can find.

FJ has, at great expense, surveyed his square farm of N x N hectares (1 <= N <= 250). Each hectare has an integer elevation (0 <= elevation <= 250) associated with it.

FJ will present your program with the elevations and a set of K (1 <= K <= 100,000) queries of the form "in this B x B submatrix, what is the maximum and minimum elevation?". The integer B (1 <= B <= N) is the size of one edge of the square cornfield and is a constant for every inquiry. Help FJ find the best place to put his cornfield.

Input

Sample Input

5 3 1
5 1 2 6 3
1 3 5 2 7
7 2 4 6 1
9 9 8 6 5
0 6 9 3 9
1 2

Sample Output

5

题意:输入n,b,q;表示一个n*n的数字矩形,q次询问以(a,b)为左上角的边长为b的正方形内数字最大值与最小值的差为多少。

分析:数据很水,可以暴力过……正解应该是二维线段树或者RMQ,不会二维线段树,二维RMQ也不会……
最开始把n*n的矩形摊开放到数组里,用普通的线段树进行b次查询每个宽度为b的区间里的最大最小值,然后超时了……比暴力还慢ORZ
这是从网上找了一个模板…


  1. #include<stdio.h>
  2. #include<algorithm>
  3. using namespace std;
  4. int mp[255][255];
  5. int dpmin[255][255][8][8]; //若起点为(0,0),2^8=256
  6. int dpmax[255][255][8][8];
  7. //二维RMQ,dp[x][y][i][j]
  8. //表示从(x,y)点到右下角为(x+2^i-1,y+2^j-1)矩形内最小值
  9. void RMQ(int n,int m) //n*m的矩阵
  10. {
  11. for(int i=0;(1<<i)<=n;i++)
  12. {
  13. for(int j=0;(1<<j)<=m;j++)
  14. {
  15. if(!i&&!j) continue;
  16. for(int r=1;r+(1<<i)-1<=n;r++)
  17. for(int c=1;c+(1<<j)-1<=m;c++)
  18. {
  19. if(!j)
  20. {
  21. dpmax[r][c][i][j]=max(dpmax[r][c][i-1][j],dpmax[r+(1<<(i-1))][c][i-1][j]);
  22. dpmin[r][c][i][j]=min(dpmin[r][c][i-1][j],dpmin[r+(1<<(i-1))][c][i-1][j]);
  23. }
  24. else
  25. {
  26. dpmax[r][c][i][j]=max(dpmax[r][c][i][j-1],dpmax[r][c+(1<<(j-1))][i][j-1]);
  27. dpmin[r][c][i][j]=min(dpmin[r][c][i][j-1],dpmin[r][c+(1<<(j-1))][i][j-1]);
  28. }
  29. }
  30. }
  31. }
  32. }
  33. int querymax(int lx,int ly,int rx,int ry)
  34. {
  35. int kx=0,ky=0;
  36. while(lx+(1<<(1+kx))-1<=rx) kx++;
  37. while(ly+(1<<(1+ky))-1<=ry) ky++;
  38. int m1=dpmax[lx][ly][kx][ky];
  39. int m2=dpmax[rx-(1<<kx)+1][ly][kx][ky];
  40. int m3=dpmax[lx][ry-(1<<ky)+1][kx][ky];
  41. int m4=dpmax[rx-(1<<kx)+1][ry-(1<<ky)+1][kx][ky];
  42. return max(max(m1,m2),max(m3,m4));
  43. }
  44. int querymin(int lx,int ly,int rx,int ry)
  45. {
  46. int kx=0,ky=0;
  47. while(lx+(1<<(1+kx))-1<=rx) kx++;
  48. while(ly+(1<<(1+ky))-1<=ry) ky++;
  49. int m1=dpmin[lx][ly][kx][ky];
  50. int m2=dpmin[rx-(1<<kx)+1][ly][kx][ky];
  51. int m3=dpmin[lx][ry-(1<<ky)+1][kx][ky];
  52. int m4=dpmin[rx-(1<<kx)+1][ry-(1<<ky)+1][kx][ky];
  53. return min(min(m1,m2),min(m3,m4));
  54. }
  55. int main()
  56. {
  57. int n,b,q;
  58. scanf("%d%d%d",&n,&b,&q);
  59. for(int i=1;i<=n;i++)
  60. for(int j=1;j<=n;j++)
  61. {
  62. scanf("%d",&mp[i][j]);
  63. dpmax[i][j][0][0]=mp[i][j];
  64. dpmin[i][j][0][0]=mp[i][j];
  65. }
  66. RMQ(n,n);
  67. while(q--)
  68. {
  69. int x,y;
  70. scanf("%d%d",&x,&y);
  71. printf("%d\n",querymax(x,y,x+b-1,y+b-1)-querymin(x,y,x+b-1,y+b-1));
  72. }
  73. return 0;
  74. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注