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;
}
 

 

發佈了84 篇原創文章 · 獲贊 9 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章