参照了http://www.cppblog.com/abilitytao/archive/2010/07/21/120927.html求矩阵的周长的线段树方法
题目大意:给出几组矩阵左上和右下的坐标,求出这些矩阵的覆盖面积
解题思路:线段树求,
由于题目的坐标是小数,而且范围大,所以我们先要离散化,用坐标来进行线段树
即让线段按照x坐标的大小从小到大排列,y坐标按照从小到大排列去掉重复的值
然后通过一个扫描线来求扫描线覆盖的y的长度。
线段的扫描按照x的大小从小到大扫描,求出当前扫描线覆盖的矩阵竖线的长度,然后乘以下条线段的跨度,则为这个区域矩阵覆盖的面积
扫描线的描述可以看下面这个人的讲解,非常详细
http://www.cnblogs.com/Booble/archive/2010/10/10/1847163.html
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 110;
struct node
{
double sum, len;
int l, r, cover;
node()
{
sum = len = 0.0;
l = r = cover = 0;
}
};
struct line
{
double x, y1, y2;
bool inout;
bool operator <(const line &b) const
{
return x < b.x;
}
};
node nodes[maxn * 10];
line lines[maxn * 2];
int n, cnt;
double index[maxn * 2];
void build(int l, int r, int dex);
void insert(int l, int r, int dex);
void del(int l, int r, int dex);
int getIndex(double x);
void getLen(int nu);
int main()
{
int t = 1;
while(true)
{
double x1, x2, y1, y2;
scanf("%d", &n);
if(n == 0)
break;
cnt = 0;
for(int i = 0; i < n; i++)
{
scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
lines[2 * i].x = x1;
lines[2 * i + 1].x = x2;
lines[2 * i].y1 = lines[2 * i + 1].y1 = y1;
lines[2 * i].y2 = lines[2 * i + 1].y2 = y2;
lines[2 * i].inout = true;
lines[2 * i + 1].inout = false;
index[2 * i] = y1;
index[2 * i + 1] = y2;
}
sort(lines, lines + 2 * n);
sort(index, index + 2 * n);
for(int i = 1; i < 2 * n; i++)
{
if(index[i] != index[i-1])
index[cnt++] = index[i-1];
}
index[cnt++] = index[2 * n - 1];
build(0, cnt - 1, 1);
double ans = 0;
for(int i = 0; i < 2 * n - 1; i++)
{
if(lines[i].inout)
insert(getIndex(lines[i].y1), getIndex(lines[i].y2), 1);
else
del(getIndex(lines[i].y1), getIndex(lines[i].y2), 1);
ans += nodes[1].sum * (lines[i+1].x - lines[i].x);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", t++, ans);
}
return 0;
}
int getIndex(double x)
{
return lower_bound(index, index + cnt, x) - index;
}
void build(int l, int r, int dex)
{
nodes[dex].l = l;
nodes[dex].r = r;
nodes[dex].len = index[r] - index[l];
nodes[dex].sum = 0;
nodes[dex].cover = 0;
if(r - l > 1)
{
int mid = (r + l) >> 1;
build(l, mid, 2 * dex);
build(mid, r, 2 * dex + 1);
}
}
void insert(int l, int r, int dex)
{
if(nodes[dex].l == l && nodes[dex].r == r)
nodes[dex].cover++;
else
{
int mid = (nodes[dex].l + nodes[dex].r) >> 1;
if(r <= mid)
insert(l, r, 2 * dex);
else if(l >= mid)
insert(l, r, 2 * dex + 1);
else
{
insert(l, mid, 2 * dex);
insert(mid, r, 2 * dex + 1);
}
}
getLen(dex);
}
void del(int l, int r, int dex)
{
if(nodes[dex].l == l && nodes[dex].r == r)
nodes[dex].cover--;
else
{
int mid = (nodes[dex].l + nodes[dex].r) >> 1;
if(r <= mid)
del(l, r, 2 * dex);
else if(l >= mid)
del(l, r, 2 * dex + 1);
else
{
del(l, mid, 2 * dex);
del(mid, r, 2 * dex + 1);
}
}
getLen(dex);
}
void getLen(int nu)
{
if(nodes[nu].cover > 0)
nodes[nu].sum = nodes[nu].len;
else if(nodes[nu].r - nodes[nu].l > 1)
nodes[nu].sum = nodes[2 * nu].sum + nodes[2 * nu + 1].sum;
else
nodes[nu].sum = 0;
}