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

来源:互联网 发布:最好的java培训机构 编辑:程序博客网 时间:2024/05/16 08:57

题目链接:点击打开链接

题意:矩形面积
思路:由于数据较大,浮点数先要离散化;然后把矩形分成两类边,上边和下边,相关信息存到结构体中;对离散化后的横轴建线段树,然后对于每条边,自下而上扫描上去,每次扫描到的块为当前边与下一条边之间的块,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 | 1struct 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;}



阅读全文
1 0