hdu Atlantis (線分ツリー: スキャンライン)

アトランティス

時間制限: 2000/1000 MS (Java/その他) メモリ制限: 65536/32768 K (Java/その他)
総提出数: 29151 受け入れられた提出物: 11472


 

問題の説明
伝説の島アトランティスについての記述を含む古代ギリシャの文書がいくつかあります。これらのテキストには、島の一部の地図も含まれているものもあります。しかし残念ながら、これらの地図はアトランティスのさまざまな地域を説明しています。あなたの友人のビルは、地図が存在する総面積を知っている必要があります。あなたは(愚かにも)この量を計算するプログラムを書くことを志願しました。
 

入力
入力ファイルは複数のテスト ケースで構成されます。各テスト ケースは、使用可能なマップの単一の整数 n (1<=n<=100) を含む行で始まります。次の n 行は、それぞれ 1 つのマップを説明します。これらの各行には 4 つの数値 x1;y1;x2;y2 (0<=x1<x2<=100000;0<=y1<y2<=100000) が含まれていますが、整数である必要はありません。値 (x1; y1) および (x2;y2) は、それぞれ左上の座標です。マップされたエリアの右下隅。

入力ファイルは 0 を 1 つ含む行で終了します。処理しないでください。
 

出力
テスト ケースごとに、プログラムは 1 つのセクションを出力する必要があります。各セクションの最初の行は「テスト ケース #k」でなければなりません。ここで、k はテスト ケースの番号 (1 から始まります) です。2 番目の値は「合計探索面積: a」でなければなりません。ここで、a は合計探索面積 (つまり、このテスト ケースのすべての長方形の和分の面積) であり、小数点以下 2 桁まで正確に出力されます。

各テスト ケースの後に空行を出力します。
 

サンプル入力
 
  
2 10 10 20 20 15 15 25 25.5 0
 

サンプル出力
 
  
テスト ケース #1 総探索面積: 180.00
#include<bits/stdc++.h>
using namespace std;
int ls(int p) { return p << 1; }
int rs(int p) { return p << 1 | 1; }
const int N = 20005;
int Tag[N];
double length[N];
double xx[N];
struct ScanLine {
	double y;
	double right_x, left_x;
	int inout;
	ScanLine(){}
	ScanLine(double y,double x2,double x1,int io):
		y(y),right_x(x2),left_x(x1),inout(io){}
}line[N];
bool cmp(ScanLine& a, ScanLine& b) { return a.y < b.y; } //小到大

void pushup(int p, int pl, int pr) {
	if (Tag[p]) length[p] = xx[pr] - xx[pl];

	else if (pl + 1 == pr) length[p] = 0;
	else length[p] = length[ls(p)] + length[rs(p)];
}

void update(int L, int R, int io, int p, int pl, int pr) {
	if (L <= pl && pr <= R) {
		Tag[p] += io;
		pushup(p, pl, pr);
		return;
	}

	if (pl + 1 == pr) return;
	int mid = (pl + pr) >> 1;
	if (L <= mid) update(L, R, io, ls(p), pl, mid);
	if (R > mid) update(L, R, io, rs(p), mid, pr);
	pushup(p, pl, pr);
}

int main() {
	int n, t = 0;
	while (scanf("%d", &n), n) {
		int cnt = 0; //边的数量,包含入边和出边
		while (n--) {
			double x1, x2, y1, y2;
			scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
			line[++cnt] = ScanLine(y1, x2, x1, 1);
			xx[cnt] = x1;
			line[++cnt] = ScanLine(y2, x2, x1, -1);
			xx[cnt] = x2;
		}
		sort(xx + 1, xx + cnt + 1);
		sort(line + 1, line + cnt + 1, cmp);
		int num = unique(xx + 1, xx + cnt + 1) - (xx + 1); //删为的个数 ,返回个数

		memset(Tag, 0, sizeof(Tag));
		memset(length, 0, sizeof(length));
		double ans = 0;
		for (int i = 1; i <= cnt; ++i) {
			int L, R;
			ans += length[1] * (line[i].y - line[i - 1].y);

			L = lower_bound(xx + 1, xx + num + 1, line[i].left_x) - xx;
			R = lower_bound(xx + 1, xx + num + 1, line[i].right_x) - xx;
			update(L, R, line[i].inout, 1, 1, num);
		}
		printf("Test case #%d\nTotal explored area: %.2f\n\n", ++t, ans);
		
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/zhi6fui/article/details/128535715
おすすめ