POJ 1151 扫描线 线段树

Posted pkgunboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1151 扫描线 线段树相关的知识,希望对你有一定的参考价值。

题意:给定平面直角坐标系中的N个矩形,求它们的面积并。

题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序。记录所有的y坐标以后排序离散化。离散化之后线段树的第i个叶子节点储存的是y[i+1]-y[i].

这里的线段树用的是一个不用下传延迟标记的做法(仅限这一类题)。线段树的每一个节点维护length(这个节点的子节点覆盖的长度)和cnt(这个节点代表的线段[l,r]所覆盖的次数)。

任意一个区间都可以被线段树划分成O(logn)个子区间,我们把这些节点的cnt值加上1或减去1。

在修改任意一个节点的cnt时或者向上维护信息的时候,如果这个节点的cnt>0,则这个节点所代表的区间覆盖的长度是y[r+1]-y[l],否则是子节点的长度和。

代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
map<double,int> mp;
const int maxn=200010;
struct ST{
	int l,r,cnt;
	double length;
}t[4*maxn];
struct node{
	double x,y1,y2;
	int k;
	bool operator <(const node& rhs)const{
		return x<rhs.x;
	}
}a[maxn];
double b[maxn];
void build(int p,int l,int r){
	t[p].l=l,t[p].r=r;
	t[p].cnt=0;
	t[p].length=0;
	if(l==r){
		return;
	}
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
}
void maintain(int p){
	if(t[p].l==t[p].r)t[p].length=0;
	else t[p].length=t[p*2].length+t[p*2+1].length;
}
void change(int p,int l,int r,int k){
	if(l<=t[p].l&&r>=t[p].r){
		t[p].cnt+=k;
		if(t[p].cnt>0){
			t[p].length=b[t[p].r+1]-b[t[p].l];
		}
		else
			maintain(p);
		return;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(mid>=l)change(p*2,l,r,k);
	if(mid<r)change(p*2+1,l,r,k);
	if(t[p].cnt>0)t[p].length=b[t[p].r+1]-b[t[p].l];
	else maintain(p); 
}
int main(){
	int n,kase=0;
	double x1,x2,y1,y2;
	double ans=0;
	while(~scanf("%d",&n)&&n){
		ans=0;
		mp.clear();
		for(int i=1;i<=n;i++){
			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
			a[i]=(node){x1,y1,y2,1};
			a[i+n]=(node){x2,y1,y2,-1};
			b[i]=y1,b[i+n]=y2;
		}
		sort(a+1,a+1+2*n);
		sort(b+1,b+1+2*n);
		int m=unique(b+1,b+1+2*n)-(b+1);
		for(int i=1;i<=m;i++)
			mp[b[i]]=i;
		build(1,1,m-1);
		for(int i=1;i<2*n;i++){
			int l=mp[a[i].y1],r=mp[a[i].y2]-1;
			change(1,l,r,a[i].k);
			ans+=(a[i+1].x-a[i].x)*(t[1].length);
		}
		printf("Test case #%d
Total explored area: %.2f

",++kase,ans);
	}
	return 0;
} 

  

以上是关于POJ 1151 扫描线 线段树的主要内容,如果未能解决你的问题,请参考以下文章

poj1151 Atlantis——扫描线+线段树

POJ1151Atlantis(线段树,扫描线)

POJ 1151 扫描线 线段树

POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

POJ1151Atlantis 矩形面积并 扫描线 线段树