poj2019(二维线段树)

点击打开题目链接


大致题意:给定一个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);
		}
	}

}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值