hdu1542-Atlantis 线段树+扫描线+离散化 求面积并

Atlantis

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 13435    Accepted Submission(s): 5582


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

题目大意:给你一些矩形,给你这些矩形的两个x坐标和两个y坐标,求这些矩形的面积的并。

解题思路:乍一看以为是计算几何的题目,在计算几何里有这一类的题目,是求两个多边形面积的并,是将两个多边形面积和减去两个多边形相交的面积,但是在这一道题解决不了,一个是数据规模不好处理,还有就是这里的多边形很多不好直接计算。所以我们这里就需要使用线段树的方法再加上计算几何里面的扫描线的方法来解决。

如图,我们将两个矩形分割成了三部分来求得面积,最后将面积相加就可以了,所以我们这里使用的是扫描线切割图形的方法。具体参看代码:

ac代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define lson L,M,lc
#define rson M+1,R,rc
#define lc po*2
#define rc po*2+1
using namespace std;
struct node
{
    double x,y1,y2;
    int state;
    	bool friend operator < (node X, node Y)
	{
		return X.x < Y.x;
		}
};
node b[210];
double h[210];
double d[210*4];//用来存储矩形的高度 
int co[210*4];//标记位 
int sum;
bool cmp(node a,node b)
{
    return a.x<b.x;
}
int find(double x)//用来确定位置,二分查找位置 
{
    int L=1,R=sum;
    int M;

    while(R>L)
    {
        M=(L+R)/2;

        if(fabs(h[M]-x)<0.000001)//因为是浮点数 ,防止精度问题 
            return M;

        if(h[M]<x)
            L=M+1;
        else
            R=M-1;
    }
    return L;
}
void pushUP(int L,int R,int po)//向上处理高度问题 
{
    if(co[po])
        d[po]=h[R+1]-h[L];
    else if(L==R)
        d[po]=0;
    else
        d[po]=d[lc]+d[rc];
}
void update(int ul,int ur,int ut,int L,int R,int po)//更新 
{
    if(ul<=L&&ur>=R)
    {
        co[po]+=ut;

        if(co[po]>0)
            d[po]=h[R+1]-h[L];
        else if(L==R)
            d[po]=0;
        else
            pushUP(L,R,po);

        return;
    }
    int M=(L+R)/2;
    if(ul<=M)
        update(ul,ur,ut,lson);
    if(ur>M)
        update(ul,ur,ut,rson);
    pushUP(L,R,po);
}
int main()
{
    int cas=0;
    int N;
    double x1,x2,y1,y2;
    double ans;
    for(cin>>N;N;cin>>N)
    {
        ans=0;
        sum=1;
        memset(h,0,sizeof(h));
        memset(co,0,sizeof(co));
        memset(d,0,sizeof(d));

        for(int i=1;i<=N;++i)
        {
            scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);

            b[i*2-1].x=x1;
            b[i*2-1].y1=y1;
            b[i*2-1].y2=y2;
            b[i*2-1].state=1;
            
            b[i*2].x=x2;
            b[i*2].y1=y1;
            b[i*2].y2=y2;
            b[i*2].state=-1;
            
            h[sum++]=y1;
            h[sum++]=y2;
        }
        sort(h+1,h+sum);//排序,方便后面处理 
        sort(b+1,b+2*N+1);
        int k=2;
        for(int i=2;i<sum;++i)//离散化,去重 
            if(h[i]!=h[i-1])
                h[k++]=h[i];
        sum=k-1;
        for(int i=1;i<=2*N;++i)
        {
            ans+=d[1]*(b[i].x-b[i-1].x);

            update(find(b[i].y1),find(b[i].y2)-1,b[i].state,1,sum-1,1);
        }
        ans+=d[1];
        printf("Test case #%d\nTotal explored area: %.2f\n\n",++cas,ans);
    }
    return 0;
}

题目链接:点击打开链接http://acm.hdu.edu.cn/showproblem.php?pid=1542

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值