二维线段树之矩形树 _求解矩阵和问题

Posted daybreaking

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二维线段树之矩形树 _求解矩阵和问题相关的知识,希望对你有一定的参考价值。

  1 //zoj 2859
  2 // 二维线段树之矩形树  求解矩阵和问题
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <cstring>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <queue>
  9 #include <stack>
 10 #include <deque>
 11 #include <map>
 12 #include <iostream>
 13 using namespace std;
 14 typedef long long LL;
 15 const double pi = acos(-1.0);
 16 const double e = exp(1);
 17 //const int MAXN =2e5+10;
 18 //const int N = 200010 * 4;
 19 #define INT_MAX (1 << 30) - 1
 20 
 21 const int maxn = 300 * 300 * 1.5;
 22 
 23 struct node {
 24     short x1, x2, y1, y2;
 25     int min;
 26     int ch[4];
 27 };
 28 node tree[maxn];
 29 
 30 int con[301][301];
 31 int n, tol;
 32 
 33 void build(int x1, int x2, int y1, int y2)
 34 {
 35     int i;
 36     int k = ++tol;
 37     tree[k].x1 = x1, tree[k].x2 = x2;
 38     tree[k].y1 = y1, tree[k].y2 = y2;
 39     tree[k].min = 0;
 40 
 41     if(x1 == x2 && y1 == y2)
 42     {
 43         tree[k].min = con[x1][y1];
 44         memset(tree[k].ch, 0, sizeof(tree[k].ch));
 45         return ;
 46     }
 47 
 48     int midx = (x1 + x2) >> 1;
 49     int midy = (y1 + y2) >> 1;
 50 
 51     tree[k].ch[0] = tol + 1;
 52     build(x1, midx, y1, midy); //左下
 53     
 54     if(midx + 1 <= x2 && midy + 1 <= y2) //右上
 55     {
 56         tree[k].ch[1] = tol + 1;
 57         build(midx + 1, x2, midy + 1, y2);
 58     }
 59     else
 60     {
 61         tree[k].ch[1] = 0;
 62     }
 63 
 64     if(midy + 1 <= y2)  //左上
 65     {
 66         tree[k].ch[2] = tol + 1;
 67         build(x1, midx, midy + 1, y2);
 68     }
 69     else
 70     {
 71         tree[k].ch[2] = 0;
 72     }
 73     
 74 
 75     if(midx + 1 <= x2)  //右下
 76     {
 77         tree[k].ch[3] = tol + 1;
 78         build(midx + 1, x2, y1, midy);
 79     }
 80     else
 81     {
 82         tree[k].ch[3] = 0;
 83     }
 84 
 85 
 86     tree[k].min = tree[ tree[k].ch[0] ].min;
 87 
 88     for(i = 1; i < 4; i++)
 89     {
 90         if(tree[k].ch[i])
 91         {
 92             tree[k].min = min(tree[k].min, tree[ tree[k].ch[i] ].min);
 93         }
 94     }
 95     
 96 }
 97 
 98 bool judge(int k, int x1, int x2, int y1, int y2)
 99 {
100     if(x1 > tree[k].x2 || x2 < tree[k].x1 || y1 > tree[k].y2 || y2 < tree[k].y1)
101         return false;
102     return true;
103 }
104 
105 int Query(int k, int x1, int x2, int y1, int y2)
106 {
107     if(judge(k, x1, x2, y1, y2) == false)
108         return INT_MAX;
109     if(x1 <= tree[k].x1 && x2 >= tree[k].x2 && y1 <= tree[k].y1 && y2 >= tree[k].y2)
110     {
111         return tree[k].min;
112     }
113 
114     int minx = Query(tree[k].ch[0], x1, x2, y1, y2);
115     for(int i = 1; i < 4; i++)
116     {
117         minx = min(minx, Query(tree[k].ch[i], x1, x2, y1, y2));
118     }
119     return minx;
120 }
121 
122 
123 
124 int main()
125 {
126     int i, j, n, size, t;
127     int x1, y1, x2, y2;
128     scanf("%d", &t);
129     while (t--)
130     {
131         //memset(T,0,sizeof(T));
132         tol = 0;
133         scanf("%d", &size);
134         for (i = 1; i <= size; i++)
135         {
136             for (j = 1; j <= size; j++)
137             {
138                 scanf("%d", &con[i][j]);
139             }
140         }
141         build(1, size, 1, size);
142         scanf("%d", &n);
143         while (n--)
144         {
145             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
146             printf("%d
",Query(1, x1, x2, y1, y2));
147         }
148     }
149 
150     return 0;
151 }

 

以上是关于二维线段树之矩形树 _求解矩阵和问题的主要内容,如果未能解决你的问题,请参考以下文章

hdu 1542 线段树之扫描线之面积并

UVa 11297 Census (二维线段树)

[hdu-6638]Snowy Smile 线段树维护 带修改的区间最大字段和 最大子矩阵 2019多校6

USACO Overplanting ( 线段树扫描线 )

HDU6638 Snowy Smile (线段树+二维最大子段和)

[POJ2155] Matrix(二维线段树,树套树)