大致题意:给定一个n*n矩阵以及k个查询。每个查询中给出两个数x,y,则该查询询问以第x行第y列为左上角的b*b
矩阵中元素最大值与最小值之差。
思路:二维问题简单化,可先考虑一维的情形,即考虑区间内元素最大最小值问题。这个可以用RMQ解决,当然,
写线段树也可以,这道题我就直接以线段树为基础了。主要的式子就是maxval[o]=max(maxval[o*2],maxval[o*2+1]),
然后二维相对一维,差不多就数组多了一维,参数,边界等稍微复杂点。这道就当成自己二维线段树模板题啦~~~
代码如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
class Reader {
static BufferedReader reader;
static StringTokenizer tokenizer;
static void init(InputStream input) {
reader = new BufferedReader(new InputStreamReader(input));
tokenizer = new StringTokenizer("");
}
static String next() throws IOException {
while (!tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
static int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
class Num {
int max, min;
public Num(int max, int min) {
super();
this.max = max;
this.min = min;
}
public Num() {
super();
// TODO Auto-generated constructor stub
}
}
public class Main {
/**
* @param args
*/
static int n, b, k, x, y;
static int val[][];
static int max[][], min[][];
private static void btree1(int o, int l, int r) {
if (l == r) {
btree2(o, l, r, 1, 1, n);
return;
}
int mid = (l + r) / 2;
btree1(o * 2, l, mid);
btree1(o * 2 + 1, mid + 1, r);
btree2(o, l, r, 1, 1, n);
}
private static int getmax(int a, int b) {
return a > b ? a : b;
}
private static int getmin(int a, int b) {
return a < b ? a : b;
}
private static void btree2(int xo, int xl, int xr, int o, int l, int r) {
if (l == r) {
if (xl == xr) {
max[xo][o] = val[xl][l];
min[xo][o] = val[xr][l];
} else {
max[xo][o] = getmax(max[xo * 2][o], max[xo * 2 + 1][o]);
min[xo][o] = getmin(min[xo * 2][o], min[xo * 2 + 1][o]);
}
return;
}
int mid = (l + r) / 2;
btree2(xo, xl, xr, o * 2, l, mid);
btree2(xo, xl, xr, o * 2 + 1, mid + 1, r);
max[xo][o] = getmax(max[xo][o * 2], max[xo][o * 2 + 1]);
min[xo][o] = getmin(min[xo][o * 2], min[xo][o * 2 + 1]);
}
private static Num query1(int o, int l, int r) {
if ((l >= x) && (r <= x + b - 1))
return query2(o, l, r, 1, 1, n);
int mid = (l + r) / 2;
Num num1, num2;
num1 = new Num(0, Integer.MAX_VALUE);
if (mid >= x)
num1 = query1(o * 2, l, mid);
if (mid < x + b - 1) {
num2 = query1(o * 2 + 1, mid + 1, r);
num1.max = getmax(num1.max, num2.max);
num1.min = getmin(num1.min, num2.min);
}
return num1;
}
private static Num query2(int xo, int xl, int xr, int o, int l, int r) {
if ((l >= y) && (r <= y + b - 1)) {
return new Num(max[xo][o], min[xo][o]);
}
int mid = (l + r) / 2;
Num num1, num2;
num1 = new Num(0, Integer.MAX_VALUE);
if (mid >= y)
num1 = query2(xo, xl, xr, o * 2, l, mid);
if (mid < y + b - 1) {
num2 = query2(xo, xl, xr, o * 2 + 1, mid + 1, r);
num1.max = getmax(num1.max, num2.max);
num1.min = getmin(num1.min, num2.min);
}
return num1;
}
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
Reader.init(System.in);
n = Reader.nextInt();
b = Reader.nextInt();
k = Reader.nextInt();
val = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
val[i][j] = Reader.nextInt();
max = new int[4 * n + 1][4 * n + 1];
min = new int[4 * n + 1][4 * n + 1];
btree1(1, 1, n);
for (int i = 1; i <= k; i++) {
x = Reader.nextInt();
y = Reader.nextInt();
System.out.println(query1(1, 1, n).max - query1(1, 1, n).min);
}
}
}