1. 程式人生 > >POJ 1151 HDU 1542 Atlantis(掃描線)

POJ 1151 HDU 1542 Atlantis(掃描線)

sizeof git poj oid file org val ber tee

題目大意就是:去一個地方探險,然後給你一些地圖描寫敘述這個地方,每一個描寫敘述是一個矩形的右下角和左上角。地圖有些地方是重疊的。所以讓你求出被描寫敘述的地方的總面積。

掃描線的第一道題,想了又想,嘯爺還給我講了講,最終有點理解了啊。

先說掃描線:書上說掃描線不是一個物體。而是一個概念。

在計算幾何中的作用類似於圖論中的bfs與dfs。所以還是須要多做題目來體會一下啊。

這道題目的做法是:離散化x坐標。然後依照y坐標的大小進行排序,每一條保存它的左邊界的位置與右邊界的位置。以及自身的高度。

還有就是假設是下邊初始為1。上邊初始為-1。

接下來就是掃描線了:依照y值排序後的數組,開始遍歷。

先二分查找它在離散數組中下表的位置。找到之後按他保存的邊界的標記。進行更新。這裏的區間更新用的是線段樹的維護。我們以離散化後數組建樹。

每一個節點保存它此時有多少個上界與下界的和,表示他是否存在矩形。

假設存在的話每一個節點中用sun數組保存這個矩形x值的差值(通過這個離散區間的下標,做減法就是離散的x的差值)。最後的時候乘上y的差值。

就是掃描到的矩陣的面積。

Atlantis
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 17207 Accepted:
6549

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 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
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <map>
#include <set>
#define eps 1e-12
///#define M 1000100
#define LL __int64
///#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)

using namespace std;

const int maxn = 5010;

struct node
{
    double l, r, h;
    int x;
} f[maxn];

double sum[maxn<<2];
int cnt[maxn];
double dc[maxn];

bool cmp(node a, node b)
{
    return a.h < b.h;
}

int Find(double x, double a[], int n)
{
    int l = 0;
    int r = n-1;
    while(l <= r)
    {
        int mid = (l+r)/2;
        if(a[mid] == x) return mid;
        if(a[mid] > x) r = mid-1;
        else l = mid+1;
    }
    return -1;

}

void Up(int l, int r, int site)
{
    if(cnt[site]) sum[site] = dc[r+1]-dc[l];
    else if(l == r) sum[site] = 0;
    else sum[site] = sum[site<<1]+sum[site<<1|1];
}

void Update(int l, int r, int L, int R, int d, int site)
{
    if(L <= l && r <= R)
    {
        cnt[site] += d;
        Up(l, r, site);
        return;
    }
    int mid = (l+r)>>1;
    if(L <= mid) Update(l, mid, L, R, d, site<<1);
    if(R > mid) Update(mid+1, r, L, R, d, site<<1|1);
    Up(l, r, site);
}

int main()
{
    int n;
    int Case = 1;
    while(cin >>n)
    {
        if(!n) break;
        double x1, y1, x2, y2;
        int m = 0;
        for(int i = 0; i < n; i++)
        {
            scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2);
            dc[m] = x1;
            f[m].l = x1;
            f[m].r = x2;
            f[m].h = y1;
            f[m++].x = 1;
            dc[m] = x2;
            f[m].l = x1;
            f[m].r = x2;
            f[m].h = y2;
            f[m++].x = -1;
        }
        sort(dc, dc+m);
        sort(f, f+m, cmp);
        int k = unique(dc, dc+m)-dc;
        memset(cnt, 0 , sizeof(cnt));
        memset(sum, 0 , sizeof(sum));
        double ans = 0;
        for(int i = 0; i < m-1; i++)
        {
            int l = Find(f[i].l, dc, k);
            int r = Find(f[i].r, dc, k)-1;
            if(l <= r) Update(0, k-1, l, r, f[i].x, 1);
            ans += sum[1]*(f[i+1].h-f[i].h);
        }
        printf("Test case #%d\n",Case++);
        printf("Total explored area: %.2f\n\n",ans);
    }
    return 0;
}


POJ 1151 HDU 1542 Atlantis(掃描線)