HDU-1542 Atlantis(离散化+扫描线)

题目大意:给n个矩形,可能重叠,求面积。

题目分析:线段树维护扫描线。

 

代码如下:

# include<bits/stdc++.h>
using namespace std;
# define LL long long
# define mid (l+(r-l)/2)

const int N=100000;

struct Segment
{
	double x1,x2,y;
	bool buttom;
};
Segment seg[(N<<1)+5];
struct Node
{
	double m;	///被覆盖的长度
	int c;	///被完全覆盖的次数
};
Node tr[N*4+5];
double x[N*2+5];
map<double,int>mp;

bool comp(const Segment &s1,const Segment &s2)
{
	return s1.y<s2.y;
}

void build(int rt,int l,int r)
{
	tr[rt].m=0.0;
	tr[rt].c=0;
	if(l==r) return ;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
}

void updateHere(int rt,int l,int r)
{
	if(tr[rt].c>0)
		tr[rt].m=x[r]-x[l-1];
	else if(l==r)
		tr[rt].m=0;
	else tr[rt].m=tr[rt<<1].m+tr[rt<<1|1].m;
}

void update(int rt,int l,int r,int L,int R,int val)
{
	if(L<=l&&r<=R){
		tr[rt].c+=val;
		updateHere(rt,l,r);
	}else{
		if(L<=mid) update(rt<<1,l,mid,L,R,val);
		if(R>mid) update(rt<<1|1,mid+1,r,L,R,val);
		updateHere(rt,l,r);
	}
}

int main()
{
	int n;
	int cas=0;
	while(~scanf("%d",&n)&&n)
	{
		double x1,y1,x2,y2;
		for(int i=0;i<n;++i){
			cin>>x1>>y1>>x2>>y2;
			seg[i<<1].x1=x1,seg[i<<1].x2=x2;
			seg[i<<1].y=y1;
			seg[i<<1].buttom=true;
			seg[i<<1|1].x1=x1,seg[i<<1|1].x2=x2;
			seg[i<<1|1].y=y2;
			seg[i<<1|1].buttom=false;
			x[i<<1]=x1;
			x[i<<1|1]=x2;
		}
		n<<=1;
		sort(seg,seg+n,comp);
		sort(x,x+n);
		int len=unique(x,x+n)-x;
		for(int i=0;i<len;++i)
			mp[x[i]]=i;
		build(1,1,len-1);
		seg[2*n].y=seg[2*n-1].y;
		double ans=0;
		for(int i=0;i<n;++i){
			int l=mp[seg[i].x1];
			int r=mp[seg[i].x2];
			if(seg[i].buttom)
				update(1,1,len-1,l+1,r,1);
			else update(1,1,len-1,l+1,r,-1);
			ans+=tr[1].m*(seg[i+1].y-seg[i].y);
		}
		printf("Test case #%d\n",++cas);
		printf("Total explored area: %.2lf\n\n",ans);
	}
	return 0;
}

  

posted @ 2016-08-03 16:25  20143605  阅读(130)  评论(0编辑  收藏  举报