标签:
Description
Input
Output
Sample Input
2 10 10 20 20 15 15 25 25.5 0
Sample Output
Test case #1 Total explored area: 180.00
题目就是求所有矩形的并面积。
通过查阅知道了是扫描线,了解了扫描线的原理,用线段树手写了一下,结果PushUp函数写搓了。。看了AC的代码才知道了原因。
做法就是通过对纵坐标有序化,然后创建区间。
然后通过横向扫描过去,得到每段横向段的高度,乘以宽度就是面积了。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #define LL long long using namespace std; //线段树 //扫描线 const int maxn = 205; struct node { int lt, rt; double height; int num; }tree[4*maxn]; struct Line { double x; double y1, y2; bool isLeft; }line[maxn]; bool cmp(Line a, Line b) { return a.x < b.x; } double y[maxn]; //向上更新 void PushUp(int id) { if(tree[id].num > 0) { tree[id].height = y[tree[id].rt] - y[tree[id].lt]; return; } if(tree[id].lt+1 == tree[id].rt) tree[id].height = 0; else tree[id].height = tree[id<<1].height + tree[id<<1|1].height; } //建立线段树 void Build(int lt, int rt, int id) { tree[id].lt = lt; tree[id].rt = rt; tree[id].height = 0;//每段的初值,根据题目要求 tree[id].num = 0; if (lt+1 == rt) { //tree[id].val = 1; return; } int mid = (lt + rt) >> 1; Build(lt, mid, id<<1); Build(mid, rt, id<<1|1); //PushUp(id); } //寻找符合修改的区间通过判断num进行修改 void Updata(int id,Line p) { if(p.y1 <= y[tree[id].lt] && p.y2 >= y[tree[id].rt]) { if (p.isLeft > 0) tree[id].num++; else tree[id].num--; PushUp(id); return; } int mid = (tree[id].lt+tree[id].rt) >> 1; if (p.y1 < y[mid]) Updata(id<<1, p); if (p.y2 > y[mid]) Updata(id<<1|1, p); PushUp(id); } int n; void Input() { double x1, y1, x2, y2; int cnt = 1; for (int i = 0; i < n; ++i) { scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); y[cnt] = y1; y[cnt+1] = y2; line[cnt].x = x1; line[cnt].y1 = y1; line[cnt].y2 = y2; line[cnt].isLeft = true; line[cnt+1].x = x2; line[cnt+1].y1 = y1; line[cnt+1].y2 = y2; line[cnt+1].isLeft = false; cnt += 2; } sort(y+1, y+1+2*n); sort(line+1, line+1+2*n, cmp); Build(1, 2*n, 1); } double Work() { double ans = 0; Updata(1, line[1]); int len = 2*n; for (int i = 2; i <= len; ++i) { ans += (line[i].x-line[i-1].x) * tree[1].height; Updata(1, line[i]); } return ans; } int main() { //freopen("test.in", "r", stdin); int times = 1; while (scanf("%d", &n) != EOF && n) { Input(); double ans = Work(); printf("Test case #%d\n", times); printf("Total explored area: %.2lf\n\n", ans); times++; } return 0; }
ACM学习历程—POJ1151 Atlantis(扫描线 && 线段树)
标签:
原文地址:http://www.cnblogs.com/andyqsmart/p/4475579.html