题目大意就是:去一个地方探险,然后给你一些地图描写叙述这个地方,每一个描写叙述是一个矩形的右下角和左上角。地图有些地方是重叠的。所以让你求出被描写叙述的地方的总面积。
扫描线的第一道题,想了又想,啸爷还给我讲了讲,最终有点理解了啊。
先说扫描线:书上说扫描线不是一个物体。而是一个概念。
在计算几何中的作用类似于图论中的bfs与dfs。所以还是须要多做题目来体会一下啊。
这道题目的做法是:离散化x坐标。然后依照y坐标的大小进行排序,每一条保存它的左边界的位置与右边界的位置。以及自身的高度。
还有就是假设是下边初始为1。上边初始为-1。
接下来就是扫描线了:依照y值排序后的数组,開始遍历。
先二分查找它在离散数组中下表的位置。找到之后按他保存的边界的标记。进行更新。这里的区间更新用的是线段树的维护。我们以离散化后数组建树。
每一个节点保存它此时有多少个上界与下界的和,表示他是否存在矩形。
假设存在的话每一个节点中用sun数组保存这个矩形x值的差值(通过这个离散区间的下标,做减法就是离散的x的差值)。最后的时候乘上y的差值。
就是扫描到的矩阵的面积。
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 17207 | Accepted: 6549 |
Description
Input
The input file is terminated by a line containing a single 0. Don't process it.
Output
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
#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;
}