您的位置:首页 > 其它

HDU 1542 Atlantis(矩形面积并,线段树+离散化+线扫描)

2017-08-01 17:45 471 查看
题目链接:点击打开链接

题意:矩形面积并
思路:由于数据较大,浮点数先要离散化;然后把矩形分成两类边,上边和下边,相关信息存到结构体中;对离散化后的横轴建线段树,然后对于每条边,自下而上扫描上去,每次扫描到的块为当前边与下一条边之间的块,sum代表区间内被覆盖的线段的长度总和,那么sum[1]就表示当前块 线段(横轴)的总长度,每次处理用sum[1] * 当前块height就是该块面积;这里线段树的一个结点并非是线段的一个端点,而是该端点和下一个端点间的线段,所以题目中r+1,r-1的地方要仔细琢磨。

对于cnt,要考虑仔细,每个区间,cnt均可叠加,表面上cnt表示该区间下边比上边多几个,实际update后,cnt已经表明了整个区间在当前块的线段分布,cnt不为零的区间,均有线段,sum也会不为零,算法正确性一目了然
// HDU 1542 Atlantis.cpp 运行/限制:0ms/1000ms
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAXN 500
#define lson l, m, root << 1
#define rson m + 1, r, root << 1 | 1
struct edge {
double lpoint, rpoint, height;
int flag;
edge(){}
edge(double a,double b,double c,int d):lpoint(a),rpoint(b),height(c),flag(d){}
bool operator <(const edge& b)const {
return this->height < b.height;
}
};
double point[MAXN];
int cnt[MAXN << 2];
double sum[MAXN << 2];
edge edges[MAXN];
int binarySearch(double num, int l, int r, double a[]) {
while (l <= r) {
int m = (l + r) >> 1;
if (fabs(num - a[m]) <= 1e-6) {
return m;
}
else if (num > a[m]) {
l = m + 1;
}
else {
r = m - 1;
}
}
return -1;
}
void pushUp(int root,int l,int r) {
if (cnt[root]) {
sum[root] = point[r + 1] - point[l];
}
else if (l == r) {
sum[root] = 0.0;
}
else {
sum[root] = sum[root << 1] + sum[root << 1 | 1];
}
}
void update(int le, int rig, int value, int l, int r, int root) {
if (le <= l && rig >= r) {
cnt[root] += value;
pushUp(root,l,r);
return;
}
int m = (l + r) >> 1;
if (le <= m) {
update(le, rig, value, lson);
}
if (rig > m) {
update(le, rig, value, rson);
}
pushUp(root,l,r);
}
int main(){
int n, count = 0;
double a, b, c, d;
while (scanf("%d", &n) != EOF && n) {
int m = 0;
for (int i = 0; i < n; i++) {
scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
point[m] = a;
edges[m++] = edge(a, c, b, 1);//下边
point[m] = c;
edges[m++] = edge(a, c, d, -1);//上边
}
sort(point, point + m);
sort(edges, edges + m);
int k = 1;
for (int i = 1; i < m; i++) {
if (point[i] != point[i - 1]) {
point[k++] = point[i];
}
}
memset(cnt, 0, sizeof(cnt));
memset(sum, 0, sizeof(sum));
double re = 0.0;
for (int i = 0; i < m - 1; i++) {
int l = binarySearch(edges[i].lpoint,0,k - 1,point);
int r = binarySearch(edges[i].rpoint,0,k - 1,point) - 1;
if (l <= r) {
update(l, r, edges[i].flag, 0, k - 1, 1);
}
re += sum[1] * (edges[i + 1].height - edges[i].height);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",++count,re);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: