#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 210;
double len[maxn<<2]; // 区间被覆盖的长度
int cover[maxn<<2]; // 区间被覆盖次数
double yy[maxn]; // 用于存储y坐标
map<double, int> m; // 用于对y坐标离散化
struct Line
{
double y1, y2, x;
int flag; // 1表示矩形的左竖边,-1表示矩形的右竖边
}line[maxn];
bool cmp(Line a, Line b)
{
if (a.x != b.x)
return a.x < b.x;
return a.flag > b.flag; // 有重边时,将左竖边排在前面
}
void build(int l, int r, int rt)
{
len[rt] = cover[rt] = 0;
if (l + 1 == r) return ;
int m = (l + r) >> 1;
build(l, m, rt << 1);
build(m, r, rt << 1 | 1);
}
void pushUp(int l, int r, int rt)
{
if (cover[rt])
len[rt] = yy[r] - yy[l];
else
{
if (l + 1 == r)
len[rt] = 0;
else len[rt] = len[rt<<1] + len[rt<<1|1];
}
}
void update(int L, int R, int flag, int l, int r, int rt)
{
if (L <= l && R >= r)
{
cover[rt] += flag;
pushUp(l, r, rt);
return ;
}
if (l + 1 == r) return ;
int m = (l + r) >> 1;
if (L < m) update(L, R, flag, l, m, rt << 1);
if (R > m) update(L, R, flag, m, r, rt << 1 | 1);
pushUp(l, r, rt);
}
int main()
{
int n, cas = 0;
while (scanf("%d", &n), n)
{
double x1, y1, x2, y2;
for (int i = 0; i < n; ++i)
{
scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
line[2*i].x = x1;
line[2*i].y1 = y1;
line[2*i].y2 = y2;
line[2*i].flag = 1;
yy[2*i] = y1;
line[2*i+1].x = x2;
line[2*i+1].y1 = y1;
line[2*i+1].y2 = y2;
line[2*i+1].flag = -1;
yy[2*i+1] = y2;
}
sort(yy, yy + n * 2);
sort(line, line + n * 2, cmp);
int idx = 1;
for (int i = 1; i < n * 2; ++i)
{
if (yy[i] != yy[idx-1])
yy[idx++] = yy[i];
}
for (int i = 0; i < idx; ++i)
m[yy[i]] = i;
build(0, idx - 1, 1);
double ret = 0;
for (int i = 0; i < n * 2 - 1; ++i)
{
int l = m[line[i].y1];
int r = m[line[i].y2];
int flag = line[i].flag;
update(l, r, flag, 0, idx - 1, 1);
ret += len[1] * (line[i+1].x - line[i].x);
}
printf("Test case #%d\n", ++cas);
printf("Total explored area: %.2lf\n\n", ret);
}
return 0;
}
hdu1542 Atlantis (线段树+扫描线)
最新推荐文章于 2021-01-19 22:05:01 发布