hdu Atlantis (árbol de segmentos de línea: scanline)

Atlántida

Límite de tiempo: 2000/1000 MS (Java/Otros) Límite de memoria: 65536/32768 K (Java/Otros)
Total de envíos: 29151 Envíos aceptados: 11472


 

Descripción del problema
Hay varios textos griegos antiguos que contienen descripciones de la legendaria isla Atlántida. Algunos de estos textos incluso incluyen mapas de partes de la isla. Pero, lamentablemente, estos mapas describen diferentes regiones de la Atlántida. Tu amigo Bill tiene que saber el área total para la cual existen mapas. Usted (imprudentemente) se ofreció como voluntario para escribir un programa que calcule esta cantidad.
 

Aporte
El archivo de entrada consta de varios casos de prueba. Cada caso de prueba comienza con una línea que contiene un único número entero n (1<=n<=100) de mapas disponibles. Las n líneas siguientes describen un mapa cada una. Cada una de estas líneas contiene cuatro números x1;y1;x2;y2 (0<=x1<x2<=100000;0<=y1<y2<=100000), no necesariamente números enteros. Los valores (x1; y1) y (x2;y2) son las coordenadas de la parte superior izquierda resp. esquina inferior derecha del área mapeada.

El archivo de entrada termina con una línea que contiene un solo 0. No lo procese.
 

Producción
Para cada caso de prueba, su programa debe generar una sección. La primera línea de cada sección debe ser "Caso de prueba #k", donde k es el número del caso de prueba (comenzando con 1). El segundo debe ser “Área total explorada: a”, donde a es el área total explorada (es decir, el área de la unión de todos los rectángulos en este caso de prueba), impresa exactamente con dos dígitos a la derecha del punto decimal.

Genere una línea en blanco después de cada caso de prueba.
 

Entrada de muestra
 
  
2 10 10 20 20 15 15 25 25,5 0
 

Salida de muestra
 
  
Caso de prueba n.° 1 Área total explorada: 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;
}

Supongo que te gusta

Origin blog.csdn.net/zhi6fui/article/details/128535715
Recomendado
Clasificación