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

题目链接:http://poj.org/problem?id=1151

折腾了一下午的题...

具体解释见代码注释。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=100005;
int n,num;
double y[maxn];

struct Line{//扫描线
	double x,y1,y2;
	int flag;
	inline bool operator <(const Line a) const{
		return x<a.x;
	}
}line[maxn];

void addLine(double x1,double y1,double x2,double y2){
	line[num].x=x1;
	line[num].y1=y1;
	line[num].y2=y2;
	line[num].flag=1;//表示矩形的左边
	y[num]=y1;//因为数据较大,将所有y坐标映射到y轴上,进行离散化
	num++;
	line[num].x=x2;
	line[num].y1=y1;
	line[num].y2=y2;
	line[num].flag=-1;//表示矩形的右边
	y[num]=y2;
	num++;
}

struct segmentTree{
	int l,r;
	double lf,rf;
	int cover;//标记是否被覆盖
	double len;//记录长度
}node[3*maxn];

void build(int rt,int l,int r){
	node[rt].l=l;
	node[rt].r=r;
	node[rt].lf=y[l];
	node[rt].rf=y[r];
	node[rt].cover=0;
	node[rt].len=0;
	if(l+1==r) return ;
	int mid=(l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid,r);
}

void callen(int rt){//计算长度
	if(node[rt].cover>0){//如果未覆盖,直接计算长度即可
		node[rt].len=node[rt].rf-node[rt].lf;
		return ;
	}
	if(node[rt].l+1==node[rt].r) {node[rt].len=0;}//如果被覆盖且是叶节点,长度置为0
	else node[rt].len=node[rt<<1].len+node[rt<<1|1].len;//非叶节点,从下往上更新
}

void Update(int rt,Line e){
	if(node[rt].lf==e.y1&&node[rt].rf==e.y2){
		node[rt].cover+=e.flag;
		callen(rt);
		return ;
	}
	if(e.y2<=node[rt<<1].rf) Update(rt<<1,e);
	else if(e.y1>=node[rt<<1|1].lf) Update(rt<<1|1,e);
	else{
		Line tmp1=e;
		tmp1.y2=node[rt<<1].rf;
		Update(rt<<1,tmp1);
		Line tmp2=e;
		tmp2.y1=node[rt<<1|1].lf;
		Update(rt<<1|1,tmp2);
	}
	callen(rt);
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
#endif
	int Cas=1;
	double x1,x2,y1,y2;
	while(~scanf("%d",&n)&&n){
		num=1;
		for(int i=0;i<n;i++){
			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
			addLine(x1,y1,x2,y2);
		}
		sort(line+1,line+num);
		sort(y+1,y+num);
		build(1,1,num-1);
		double ans=0;
		for(int i=2;i<num;i++){
			Update(1,line[i-1]);
			ans+=node[1].len*(line[i].x-line[i-1].x);
		}
		printf("Test case #%d\n",Cas++);
		printf("Total explored area: %.2f\n\n",ans);
	}
	return 0;
}




你可能感兴趣的:(poj 1151 Atlantis(线段树+离散化+扫描线))