HDU1542 扫描线(矩形面积并)

Atlantis

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


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
 

题意

  给出n个矩形的左下角和右上角的坐标,求矩形面积的并

解题思路

  离散化x轴,然后扫描线,具体实现看代码

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=200+10;
int cnt[maxn*4],n;//记录某个区间的下底边比上底边多的个数
double sum[maxn*4];//记录某个区间下底边比上底边多的个数总长度
double Hash[maxn];//对横坐标x离散化

struct node{
    double l,r,h;
    int f;
    node(){}
    node(double x1,double x2,double hh,int ff):l(x1),r(x2),h(hh),f(ff){}
    bool operator<(const node &a)const{
        return h<a.h;
    }
}s[maxn*4];

void init(){
    memset(sum,0,sizeof(sum));
    memset(cnt,0,sizeof(cnt));
}

void pushup(int x,int l,int r){
    if(cnt[x])   sum[x]=Hash[r+1]-Hash[l];//表示该区间整个线段长度可作为底边
    else if(l==r) sum[x]=0;//叶子结点区间长度为0,则底边长度为0
    else sum[x]=sum[x*2]+sum[x*2+1];
}

void update(int x,int L,int R,int f,int l,int r){
    if(L<=l&&r<=R){
        cnt[x]+=f;
        pushup(x,l,r);
        return ;
    }
    int mid=(l+r)/2;
    if(L<=mid)  update(x*2,L,R,f,l,mid);
    if(R>mid)   update(x*2+1,L,R,f,mid+1,r);
    pushup(x,l,r);
}

int main(){
    double x1,x2,y1,y2; int p=0;
    while(cin>>n&&n){
        init();int k=0;
        while(n--){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            if(x1>x2)   swap(x1,x2);
            if(y1>y2)   swap(y1,y2);
            Hash[k]=x1;
            s[k++]=node(x1,x2,y1,1);
            Hash[k]=x2;
            s[k++]=node(x1,x2,y2,-1);
        }
        sort(s,s+k);//把线段按高度h从小到大排序
        sort(Hash,Hash+k);//把x坐标从小到大排序

        int ans=unique(Hash,Hash+k)-Hash;//去重复端点
        double SUM=0;
        printf("Test case #%d
",++p);
        for(int i=0;i<k;i++){
            int l=lower_bound(Hash,Hash+ans,s[i].l)-Hash;
            int r=lower_bound(Hash,Hash+ans,s[i].r)-Hash;
            update(1,l,r-1,s[i].f,0,ans-1);//扫描线段更新可用底边长
            SUM+=sum[1]*(s[i+1].h-s[i].h);//新增加面积

        }
        printf("Total explored area: %.2f

",SUM);
    }
    return 0;
}
 
原文地址:https://www.cnblogs.com/weimeiyuer/p/9449365.html