POJ 1151 Atlantis 离散化 + 扫描线 + 线段树

本文介绍了一种利用线段树和扫描线算法解决给定矩形面积计算的问题,并通过离散化处理实现了数据的有效管理。通过输入一系列矩形坐标,程序能够准确计算并输出所有矩形的总面积。

来源:http://poj.org/problem?id=1151

题意:给一些矩形,求这些矩形的面积。

思路:线段树 + 扫描线的题目,因为数据 是double,所以要离散化。

代码:

#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 110;
struct line{
	double x1,x2,y;
	int flag;
}LL[N * 4];
struct rec{
	double x1,y1,x2,y2;
}rr[N * 4];
struct tree{
	int lp,rp,cur;
	double len;
	int getmid(){
	   return (lp + rp) / 2;
	}
}tt[8 * N];
double xx[4*N];
double ep = 1e-6;
bool cmp(line a,line b){
	return a.y > b.y;
}
void built_tree(int lp,int rp,int pos){
	tt[pos].lp = lp;
	tt[pos].rp = rp;
	tt[pos].cur = 0;
	tt[pos].len = 0;
	if(lp + 1 == rp)
		return;
	int mid = tt[pos].getmid();
	built_tree(lp,mid,pos * 2);
	built_tree(mid,rp,pos * 2 + 1);
}
void updatelen(int pos){
	if(tt[pos].cur > 0){
		tt[pos].len = xx[tt[pos].rp - 1] - xx[tt[pos].lp - 1];
	}
	else{
	   if(tt[pos].lp + 1 == tt[pos].rp)
		   tt[pos].len = 0.0;
	   else
		   tt[pos].len = tt[pos*2+1].len + tt[pos*2].len;
	}
}
void update(int pos,line temp){
	if(xx[tt[pos].lp - 1] == temp.x1 && xx[tt[pos].rp - 1] == temp.x2){
	   tt[pos].cur += temp.flag;
	   updatelen(pos);
	   return;
	}
	if(tt[pos].lp + 1 == tt[pos].rp)
		return;
	int mid = tt[pos].getmid();
	if(temp.x2 - xx[mid - 1] <= ep){
	   update(pos*2,temp);
	}
	else if(temp.x1 - xx[mid - 1] >= ep)
		update(pos*2+1,temp);
	else{
       line p = temp; 
	   p.x2 = xx[mid - 1];  
	   update(pos*2,p);
       p = temp; 
	   p.x1 = xx[mid - 1];
	   update(pos*2+1,p);
	}
	updatelen(pos);
}
int main(){
	//freopen("1.txt","r",stdin);
	int ca = 1,n;
	while(scanf("%d",&n) && n){
		int cnt = 0;
		for(int i = 0; i < n; ++i){
		   scanf("%lf%lf%lf%lf",&rr[i].x1,&rr[i].y1,&rr[i].x2,&rr[i].y2);
		   LL[cnt].x1 = rr[i].x1; LL[cnt].x2 = rr[i].x2; 
		   LL[cnt].y = rr[i].y2;  LL[cnt].flag = 1;
		   xx[cnt] = rr[i].x1;
		   cnt++;
		   LL[cnt].x1 = rr[i].x1; LL[cnt].x2 = rr[i].x2;
		   LL[cnt].y = rr[i].y1;  LL[cnt].flag = -1;
		   xx[cnt] = rr[i].x2;
		   cnt++;
		}
		sort(LL,LL + cnt,cmp);
		sort(xx,xx+cnt);
		int len = unique(xx,xx+cnt) - xx;
		built_tree(1,len ,1);
		double ans = 0.0;
		update(1,LL[0]);
		for(int i = 1; i < cnt; ++i){
		   ans += ( LL[i - 1].y - LL[i].y ) * tt[1].len;
		   update(1,LL[i]);
		}
		printf("Test case #%d\n",ca++);
		printf("Total explored area: %.2lf\n\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值