POJ1151矩形面积并

题意: n个矩形面积并。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {
	public static void main(String[] args) {
		new POJ1151().run();
	}
}

class POJ1151 {

	void run() {
		Scanner cin = new Scanner(new BufferedInputStream(System.in));
		PrintWriter cout = new PrintWriter(new BufferedOutputStream(System.out));
		int Case = 0;
		int n;
		while ((n = cin.nextInt()) != 0) {
			Line[] lines = new Line[2 * n];
			List<Double> xs = new ArrayList<Double>();

			for (int i = 0; i < n; i++) {
				double x1 = cin.nextDouble(), y1 = cin.nextDouble();
				double x2 = cin.nextDouble(), y2 = cin.nextDouble();
				lines[i * 2] = new Line(x1, x2, y1, 1);
				lines[i * 2 + 1] = new Line(x1, x2, y2, -1);
				xs.add(x1);
				xs.add(x2);
			}

			h = new Hash(xs);
			int limit = h.length() - 1;
			build(1, 0, limit);

			double res = 0;
			Arrays.sort(lines);
			for (int i = 0; i < 2 * n - 1; i++) {
				int l = h.idx(lines[i].left_x);
				int r = h.idx(lines[i].right_x) - 1;
				update(l, r, lines[i].f, 1, 0, limit);
				res += len[1] * (lines[i + 1].y - lines[i].y);
			}
			if(Case != 0) cout.println();
			cout.printf("Test case #%d\n", ++Case);
			cout.printf("Total explored area: %.2f\n", res);
		}
		cout.flush();
	}

	void build(int t, int l, int r) {
		left[t] = l;
		right[t] = r;
		len[t] = 0;
		cnt[t] = 0;
		if (l == r)
			return;
		int mid = (l + r) >> 1;
		build(t << 1, l, mid);
		build(t << 1 | 1, mid + 1, r);
	}

	void up(int t) {
		if (cnt[t] != 0)
			len[t] = h.value(right[t] + 1) - h.value(left[t]);
		else if (left[t] == right[t])
			len[t] = 0;
		else
			len[t] = len[t << 1] + len[t << 1 | 1];
	}

	void update(int al, int ar, int c, int t, int l, int r) {
		if (al <= l && r <= ar) {
			cnt[t] += c;
			up(t);
			return;
		}
		int mid = (l + r) >> 1;
		if (al <= mid)
			update(al, ar, c, t << 1, l, mid);
		if (ar > mid)
			update(al, ar, c, t << 1 | 1, mid + 1, r);
		up(t);
	}

	Hash h;

	final int N = 208;
	int[] left = new int[N << 2];
	int[] right = new int[N << 2];
	int[] cnt = new int[N << 2];
	double[] len = new double[N << 2];
}

class Line implements Comparable<Line> {
	double left_x;
	double right_x;
	double y;
	int f;

	Line(double left_x, double right_x, double y, int f) {
		this.left_x = left_x;
		this.right_x = right_x;
		this.y = y;
		this.f = f;
	}

	@Override
	public int compareTo(Line other) {
		return Double.compare(y, other.y);
	}
}

class Hash {
	Hash(List<Double> array) {
		Set<Double> treeSet = new TreeSet<Double>();
		for (double d : array)
			treeSet.add(d);
		this.array = new double[treeSet.size()];
		size = 0;
		for (double d : treeSet)
			this.array[size++] = d;
	}

	int length() {
		return size;
	}

	int idx(double key) {
		return Arrays.binarySearch(array, key);
	}

	double value(int idx) {
		return array[idx];
	}

	int size;
	double[] array;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值