poj1151 Atlantis
这题的意思是,给你一些长方形, 要你求出他们覆盖的总面积。 给你的点只有200个, 所以, 一般的运行速度都是足够的。 不要被下面的数字所影响。我这题是用到了 映射的方法, 其实更简单的应该是二分查找就够了。通过对y轴进行建线段树。 当然要先进行排序,和去重。 然后对X 轴进行排序。 每次当前的X轴点和前一个X轴点相减再乘以当前Y轴的所有区间的和。对了, 要用C++ 提交, 我用G++ 提交无限wa。 不知道为什么。
View Code
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define maxn 1000
using namespace std;
struct node
{
int left, right;
int flag;
double value;
}map[maxn];
//我把题目想难了,只有200个点而已 只要用二分查找就可以了, 不必要进行映射, 增加了编码的难度,
struct mir
{
int point;
double value;
}mirror[maxn];
bool operator < (struct mir a, struct mir b)
{
return a.value < b.value ? true:false;
}
struct mirx
{
int left, right;
int flag;
double x;
}mirrorx[maxn];
bool operator < (struct mirx a, struct mirx b)
{
return a.x < b.x? true:false;
}
void build(int left, int right, int side)
{
map[side].left = left;
map[side].right = right;
map[side].value = 0.0;
map[side].flag = 0;
if (left + 1 == right)
{
return;
}
int mid = (left + right) >> 1;
build(left, mid, side << 1);
build(mid, right, side << 1 | 1);
return;
}
void insert(int left, int right, int flag, int side)
{
if (left > map[side].right || right < map[side].left)
{
return;
}
if (left <= map[side].left && right >= map[side].right)// 当区间在这里的时候, 直接判断
{
map[side].flag += flag;//在这里标记
if (map[side].flag > 0)//当标记大于0 的时候, 说明整个区间都是被覆盖的
{
map[side].value = mirror[map[side].right].value - mirror[map[side].left].value;
}
else
{
if (map[side].left + 1 < map[side].right)//标记为0 的时候, 如果不是跟节点要左右子树加到上面来
{
map[side].value = map[side << 1].value + map[side << 1 | 1].value;
}
else
{
map[side].value = 0;
}
}
return;
}
int mid = (map[side].left + map[side].right) >> 1;
if (right <= mid)
{
insert(left, right, flag, side << 1);
}
else if (left >= mid)
{
insert(left, right, flag, side << 1 | 1);
}
else
{
insert(left, mid, flag, side << 1);
insert(mid, right, flag, side << 1 | 1);
}
if (map[side].flag == 0)// 当自身标记为零的时候, 要让value 值为左右子树的和
{
map[side].value = map[side << 1].value + map[side << 1 | 1].value;
}
return;
}
void inline swap(int &a, int &b)
{
a ^= b ^= a ^= b;
}
void mirrx_init(int k)
{
mirrorx[k].left = 0;
mirrorx[k].right = 0;
}
void print(int n, int count)
{
double x1, y1, x2, y2;
int k = 0;
for (int i = 1; i <= n;i ++)
{
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
mirror[++k].value = y1;
mirrorx[k].x = x1;
mirror[k].point = k;
mirrorx[k].flag = 1;
mirrx_init(k);
mirror[++k].value = y2;
mirrorx[k].x = x2;
mirrorx[k].flag = -1;
mirror[k].point = k - 1;
mirrx_init(k);
}
sort(mirror + 1, mirror + 2 * n + 1);//对y轴进行排序
//下面是对y 对 x 轴的映射, 并对y进行去重
mirrorx[mirror[1].point].left = 1;
mirrorx[mirror[1].point + 1].left = 1;
k = 1;
for (int i = 2; i <= n * 2; i ++)
{
if (mirror[i].value != mirror[k].value)
{
mirror[++k] = mirror[i];
}
if (mirrorx[mirror[i].point].left == 0)
{
mirrorx[mirror[i].point].left = k;
mirrorx[mirror[i].point + 1].left = k;
}
else
{
mirrorx[mirror[i].point].right = k;
mirrorx[mirror[i].point + 1].right = k;
}
}
for (int i = 1; i <= k; i ++)
{
if (mirrorx[i].left > mirrorx[i].right)
{
swap(mirrorx[i].left, mirrorx[i].right);
}
}
sort(mirrorx + 1, mirrorx + 1 + n * 2);//对x 轴进行排序
build(1, k, 1);
double left = 0, sum = 0;
insert(mirrorx[1].left, mirrorx[1].right, 1, 1);
left = mirrorx[1].x;
for (int i = 2; i <= 2 * n; i++)
{
sum += (mirrorx[i].x - left) * map[1].value;
left = mirrorx[i].x;
insert(mirrorx[i].left, mirrorx[i].right, mirrorx[i].flag, 1);
}
printf("Test case #%d\n", count);
printf("Total explored area: %.2lf\n\n", sum);
return;
}
int main()
{
int n;
int count = 1;
while (scanf("%d", &n) != EOF)
{
if (n == 0)
{
break;
}
print(n, count);
count ++;
}
return 0;
}