【面积并】 Atlantis

传送门

题意

多组测试样例,n表示矩形的个数,每个矩形用左上角和右下角来描述,输出这些矩形的面积并,

数据范围

\(\begin{array}{l}1 \leq n \leq 10000 \\ 0 \leq x_{1}<x_{2} \leq 100000 \\ 0 \leq y_{1}<y_{2} \leq 100000\end{array}\)

题解

一根扫描线从左到右或者从下到上扫描整个图形,在从左往右扫描的情况下,将每个矩形的始边和终边分别标记+1和-1,
线段树对于所有y离散化后的个数范围建树,其中维护两个信息,当前扫描线覆盖的线段的个数、当前扫描线覆盖的线段的长度
因为点是实数域的,所以接近无限,要对点离散化,用起点y1和终点(y2-1)来表示线段,线段树的结点标号就是离散后的下标。
有一个四元组\(( x_{1},y_{1},y_{2},+1)\)\((x_{2},y_{1},y_{2},-1)\)分别标记矩形开始的边和结束的边
不需要延迟标记,当前扫描线覆盖的长度都维护在根节点上。

Code

#include <bits/stdc++.h>
#define pb push_back
#define db double
using namespace std;
const int N = 100010;
int n;
struct Segment
{
	double x, y1, y2;
	int k;
	bool operator< (const Segment &t)const
	{
		return x < t.x;
	}
}seg[N * 2];
struct Node
{
	int l, r;
	int cnt;
	double len;
}tr[N * 8];

vector<double> ys;
int find(db y){
	return lower_bound(ys.begin(),ys.end(),y)-ys.begin();
}
void push_up(int u)
{
	if (tr[u].cnt) tr[u].len = ys[tr[u].r + 1] - ys[tr[u].l];//当前区间有覆盖,加上当前区间代表线段的长度
	else if (tr[u].l != tr[u].r)
	{
		tr[u].len = tr[u << 1].len + tr[u << 1 | 1].len;//将当前的总长度传递到根节点
	}
	else tr[u].len = 0;
}
void build(int u, int l, int r)
{
	tr[u] = {l, r, 0, 0};
	if (l != r)
	{
		int mid = l + r >> 1;
		build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
	}
}
void change(int u,int l,int r,int k){
	if(tr[u].l >= l && tr[u].r <= r){
		tr[u].cnt += k;
		push_up(u);
	}
	else {
		int mid = tr[u].l + tr[u].r >> 1;
		if( l <= mid ) change(u<<1,l,r,k);
		if(r>mid) change(u<<1|1,l,r,k);
		push_up(u);
	}
}
int main(){
	int T=1;
	while(cin>>n,n){
		ys.clear();
		for(int i=0,j=0;i<n;i++){
			double x1,y1,x2,y2;
			cin>>x1>>y1>>x2>>y2;
			ys.pb(y1);
			ys.pb(y2);
			seg[j++]={x1,y1,y2,1};
			seg[j++]={x2,y1,y2,-1};
		}
		sort(ys.begin(),ys.end());
		ys.erase(unique(ys.begin(),ys.end()),ys.end());
		sort(seg,seg+2*n);
		build(1,0,ys.size()-2);//线段个数比点的个数少1
		
		db res=0;
		for(int i=0;i<n*2;i++){
			if(i > 0) res += tr[1].len*(seg[i].x-seg[i-1].x);
			change(1,find(seg[i].y1),find(seg[i].y2)-1,seg[i].k);
		}
		printf("Test case #%d\n", T ++ );
		printf("Total explored area: %.2lf\n\n", res);
	}
}
posted @ 2020-09-20 15:37  Hyx'  阅读(193)  评论(0编辑  收藏  举报