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\n",Query(1, x1, x2, y1, y2));
147 }
148 }
149
150 return 0;
151 }