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

Atlantis

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 9032    Accepted Submission(s): 3873

Problem 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 Bill has to know the
total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

Input

The input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0<=x1<x2<=100000;0<=y1<y2<=100000),
not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.

The input file is terminated by a line containing a single 0. Don’t process it.

Output

For each test case, your program should output one section. The first line of each section must be “Test case #k”, where k is the number of the test case (starting with 1). The second one must be “Total explored area: a”, where a is the total explored area
(i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.

Output a blank line after each test case.

Sample Input

2
10 10 20 20
15 15 25 25.5
0

Sample Output

Test case #1
Total explored area: 180.00 

Source

Mid-Central European Regional Contest 2000

Recommend

linle   |   We have carefully selected several similar problems for you:  1828 1255 1540 2795 1823

Statistic | Submit | Discuss | Note

第一次做线段树+扫描线+离散化..当然是不会做的 甚至都没听说过

所以百度+查资料+看了n久 终于有了一点眉目。。

离散化是程序设计中一个非常常用的技巧,它可以有效的降低时间复杂度。其基本思想就是在众多可能的情况中“只考虑我需要用的值”。离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。要掌握这个思想,必须从大量的题目中理解此方法的特点。

在这里先按照x大小排序。(10,15,20,25)这样的话我们就知道矩形的长,然后就该求宽了。知道宽面积

不就是手到擒来嘛。至于求宽就是把y坐标离散化,然后开始建树,扫描求宽了。记得一次加入一个y坐标,其实

就是一个y=?的一条线、每添加两条线计算一次面积(如果添加1 2 3次计算两次面积求和),然后求和

这就是本题例题的四个扫描线。。第一次是标号为1的左边,第二次面积为红色,第三次为绿色,第四次就是蓝色

#include <stdio.h>
#include <algorithm>
using namespace std;
struct node1
{
	double x,y1,y2,flag;//flag表示该边是入边还是出边
}c[205];
struct node2
{
	double left,right,len,s;//s标记这条边是否完全覆盖
	int l,r;
}d[205*4];
double y[205];//所有y坐标
bool cmp(node1 a,node1 b)
{
	return a.x<b.x;
}
void build(int root,int l,int r)
{
	d[root].l=l;
	d[root].r=r;
	d[root].left=y[l];
	d[root].right=y[r];
	d[root].len=0;
	d[root].s=0;
	if(l+1==r)
	return ;
	int mid=(l+r)/2;
	build(root*2,l,mid);
	build(root*2+1,mid,r);//不是mid+1,比如只有(10,15,20三个y坐标,应该出现三个范围(10 20)(10 15)(15 20))而不是(10 20)(10 15)
}
void cal(int root)
{
	if(d[root].s>0)非0 完全覆盖
	d[root].len=d[root].right-d[root].left;
	else if(d[root].r-d[root].l==1)
	d[root].len=0;
	else
	d[root].len=d[root*2].len+d[root*2+1].len;
}
void update(int root,node1 x)
{
	if(d[root].left==x.y1&&d[root].right==x.y2)
	{
		d[root].s+=x.flag;
		cal(root);
		return ;
	}
	if(x.y1>=d[root*2].right) update(root*2+1,x);
	else if(x.y2<=d[root*2+1].left) update(root*2,x);
	else
	{
		node1 temp;
		temp=x;
		temp.y2=d[root*2].right;
		update(root*2,temp);
		temp=x;
		temp.y1=d[root*2+1].left;
		update(root*2+1,temp);
	}
	cal(root);
	return ;
}
int main()
{
	int n,ncase=1;
	while(scanf("%d",&n)&&n)
	{
		int t=1;
		for(int i=0;i<n;i++)
		{
			double x1,y1,x2,y2;
			scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
			c[t].x=x1,c[t].y1=y1,c[t].y2=y2,c[t].flag=1,y[t++]=y1;//入边<span style="white-space:pre">		</span>
			c[t].x=x2,c[t].y1=y1,c[t].y2=y2,c[t].flag=-1,y[t++]=y2;//出边
		}
		sort(c+1,c+t,cmp);
		sort(y+1,y+t);
		build(1,1,t-1);
		update(1,c[1]);
		double sum=0;
		for(int i=2;i<t;i++)
		{
			sum+=(c[i].x-c[i-1].x)*d[1].len;
			update(1,c[i]);
		}
		printf("Test case #%d\nTotal explored area: %.2lf\n\n",ncase++,sum);
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 20:28:50

hdu1542 Atlantis (线段树+扫描线+离散化)的相关文章

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

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8998    Accepted Submission(s): 3856 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

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

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <

hdu 1542 Atlantis(线段树&amp;扫描线&amp;面积并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6386    Accepted Submission(s): 2814 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

hdu 1542 Atlantis (线段树+扫描线)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 18559    Accepted Submission(s): 7523 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11551    Accepted Submission(s): 4906 Problem Description There are several ancient Greek texts that contain descriptions of the fabled

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,

HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化一下,数据大小就缩小了,那么之后只需要线段树单点更新就好了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <map> 5 #include <algor