HDU1542线段树扫描线求矩形面积

Atlantis

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


 

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

怎样扫描?

如图,按高度将横向的线排序,再从下至上的扫描,横向的直线将图形分解成不同颜色的矩形,每次加矩形的面积。

 怎样利用线段树?

线段树来维护每条直线上的有效线段,扫到一条边如果是下边的话加入到线段树中,如果是上边就从线段树中删除。

表示扫描线进入矩形中,这个矩形的下边就是有效线段。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <map>
#include <vector>
#include <string.h>
#include <string>
#include <queue>
#include <set>
using namespace std;
//ios_base::sync_with_stdio(false);
//#include <bits/stdc++.h>
typedef long long ll;
const int N = 110;
struct Edge {
    double l, r; //这条线的左右端点横坐标
    double h; //这条线纵坐标
    int f;    //这条线是矩形的上边还是下边
    Edge() {}
    Edge(double l,double r,double h,int f):l(l),r(r),h(h),f(f) {}

}e[N<<1];
bool cmp(Edge a, Edge b)
{
    return a.h < b.h;
}
struct Node {
    int l, r; //横坐标的区间,是横坐标的下标
    int s; //该节点被覆盖的情况(是否完全被覆盖)
    double len; //该区间被覆盖的总长度
}q[N<<3];//每个矩形有两个横坐标所以需要2*4N的节点
#define ls i<<1
#define rs i<<1|1
#define m(i) ((q[i].l+q[i].r)>>1)
double x[2*N];
void build(int i, int l, int r)
{
    q[i].r = r, q[i].l = l;
    q[i].s = 0, q[i].len = 0;
    if(l == r) return;
    int mid = m(i);
    build(ls, l, mid);
    build(rs, mid+1, r);
}
void pushup(int i)
{
    if(q[i].s) //非零,已经被整段覆盖
    {
        q[i].len = x[q[i].r+1] - x[q[i].l]; //左闭右开解决区间缺失问题
    }
    else if(q[i].l == q[i].r) //这是一个点不是线段
    {
        q[i].len = 0;
    }
    else
    {
        q[i].len = q[ls].len + q[rs].len;
    }
}
void update(int i, int l, int r, int xx)
{
    if(q[i].l == l && q[i].r == r)
    {
        q[i].s += xx;
        pushup(i);
        return;
    }
    int mid = m(i);
    if(r <= mid) update(ls, l, r, xx);
    else if(l > mid) update(rs, l, r, xx);
    else
    {
        update(ls, l, mid, xx);
        update(rs, mid+1, r, xx);
    }
    pushup(i);
}
int main()
{
    int n, cas = 0;
    while(scanf("%d", &n)==1 && n)
    {
        int tot = 0;
        for(int i = 0; i < n; i++)
        {
            double x1, x2, y1, y2;
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            e[tot] = Edge(x1, x2, y1, 1);
            e[tot+1] = Edge(x1, x2, y2, -1);
            x[tot] = x1;
            x[tot+1] = x2;
            tot += 2;
        }
        sort(e,e+tot,cmp);
        //离散化坐标
        sort(x,x+tot);
        //去重
        int k = unique(x, x + tot) - x;
        build(1, 0, k-1);
        double ans = 0.0;
        for(int i = 0; i < tot; i++)
        {
            int l = lower_bound(x, x+k, e[i].l) - x;
            int r = lower_bound(x, x+k, e[i].r) - x -1;
            update(1, l, r, e[i].f);
            ans += (e[i+1].h - e[i].h)*q[1].len;
        }
        printf("Test case #%d\n",++cas);
        printf("Total explored area: %.2f\n\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/QiHang_QiHang/article/details/81135465