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\nTotal explored area: %.2f\n\n",++kase,ans);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/pkgunboat/p/9688471.html

时间: 2024-11-10 13:11:45

POJ 1151 扫描线 线段树的相关文章

POJ&#183;1151 Atlantis&#183;线段树求矩形面积并

题目在这:http://poj.org/problem?id=1151 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the is

POJ 1151 Atlantis( 线段树 + 扫描线 )

一维离散化, 扫描线扫另一维, 用线段树维护 POJ建议交C++...G++貌似double要用%f ? 反正同一份代码C++AC,G++WA ------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 109; struct Line { double p,

POJ 1151 Atlantis 线段树+离散化

题目链接:http://poj.org/problem?id=1151  http://acm.hdu.edu.cn/showproblem.php?pid=1542 题目大意:给你几个矩形的坐标,求他们的面积的并. 解题思路:可以参考http://www.cnblogs.com/kuangbin/archive/2011/08/16/2140544.html,实际上就是一个方向直接算出,另一个方向使用线段树维护已经覆盖的底边的长度.具体操作不算复杂:假想一条扫描下从下往上开始进行扫描,初始时候

poj 1151 Atlantis (线段树+扫描线+离散化)

Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18061   Accepted: 6873 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of

poj 1151 Atlantis (线段树+扫描线)

Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa

poj 1151 Atlantis (离散化 + 扫描线 + 线段树)

题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <cstdlib> 6 #include <algorithm> 7 #define LL __int64 8 #define lson l, mid, 2*rt

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> #include <algorithm> #define MAXN 110 #define LL ((rt<<1)+1) #define RR ((rt<<1)+2) using namespace std; int n; struct segment{ double l