给N个矩形的端点坐标,求矩形覆盖面积和。

原理很简单,从左到右扫描,线段树记录的是纵向覆盖的长度。区间更新。因为坐标是实数而且很大,所以需要离散化。

WA+RE+CE+MLE+。。。一共错了二十多次。用了最蠢的办法,最后发现错在初始化的时候,构造函数参数我写成了int。。蠢哭。。。

和普通的线段树是不同的,因为此类题型中矩形左右两竖边的长度时相同的,而且每次都是先加一在减一,不会出现负数。而且最后用到的只有总长度。

AC代码:

#include <bits/stdc++.h>
#define clr(x,c) memset(x,c,sizeof(x)) using namespace std;
const int N = 20005; struct ScanLine {
double x;
double upY, downY;
int flag; // 入边1 出边-1
bool operator<(const ScanLine a) const {
return x < a.x;
}
ScanLine() {}
ScanLine(double x, double y1, double y2, int f) : x(x), upY(y1), downY(y2), flag(f) {}
} line[N]; double tr[N];
int cover[N];
double yy[N]; #define lson (o<<1)
#define rson (o<<1|1)
#define mid (l+r>>1)
int yl, yr, v;
void pushup(int o, int l, int r)
{
if (cover[o]) tr[o] = yy[r] - yy[l];
else if (l + 1 == r) tr[o] = 0; // 叶子
else tr[o] = tr[lson] + tr[rson];
} void update(int o, int l, int r)
{
if (yl > r || yr < l) return ;
if (yl <= l && yr >= r) {
cover[o] += v;
pushup(o, l, r);
return ;
}
if (l + 1 == r) return ; // 不包含的叶子节点要退出,否则死循环T^T
if (yl <= mid) update(lson, l, mid);
if (yr > mid) update(rson, mid, r); // 注意这里不是mid+1 因为mid~mid+1一段的距离也要算
pushup(o, l ,r);
} int main()
{
int n;
int cas = 0;
while (~scanf("%d", &n) && n) {
int cnt = 0;
double x1, y1, x2, y2;
for (int i = 0; i < n; ++i) {
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
line[++cnt] = ScanLine(x1, y2, y1, 1);
yy[cnt] = y1;
line[++cnt] = ScanLine(x2, y2, y1, -1);
yy[cnt] = y2;
}
sort(yy + 1, yy + cnt + 1);
sort(line + 1, line + cnt + 1);
int len = unique(yy + 1, yy + cnt + 1) - yy - 1;
clr(cover, 0);
clr(tr, 0);
double ans = 0;
for (int i = 1; i <= cnt; ++i) {
ans += tr[1] * (line[i].x - line[i - 1].x);
yl = lower_bound(yy+1, yy + len + 1, line[i].downY) - yy;
yr = lower_bound(yy+1, yy + len + 1, line[i].upY) - yy;
v = line[i].flag;
update(1, 1, len);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", ++cas, ans);
}
return 0;
}

还有一种方法,比较好理解,和平时的线段树比较像,就是对于每个区间求[l, r-1],算的时候右边加一,这样递归的时候就不用考虑叶子节点了。

#include <bits/stdc++.h>
#define clr(x,c) memset(x,c,sizeof(x))
using namespace std;
const int N = 20005; struct ScanLine {
double x;
double upY, downY;
int flag; // 入边1 出边-1
bool operator<(const ScanLine a) const {
return x < a.x;
}
ScanLine() {}
ScanLine(double x, double y1, double y2, int f) : x(x), upY(y1), downY(y2), flag(f) {}
} line[N]; double tr[N];
int cover[N];
double yy[N]; #define lson (o<<1)
#define rson (o<<1|1)
#define mid ((l+r)>>1)
int yl, yr, v; void pushup(int o, int l, int r)
{
if (cover[o] > 0) tr[o] = yy[r+1] - yy[l];
else if (l == r) tr[o] = 0;
else tr[o] = tr[lson] + tr[rson];
} void update(int o, int l, int r)
{
if (yl > r || yr < l) return ;
if (yl <= l && yr >= r) {
cover[o] += v;
pushup(o, l, r);
return ;
}
if (yl <= mid) update(lson, l, mid);
if (yr > mid) update(rson, mid + 1, r);
pushup(o, l ,r);
} int main()
{
int n;
int cas = 0;
while (~scanf("%d", &n) && n) {
int cnt = 0;
double x1, y1, x2, y2;
for (int i = 0; i < n; ++i) {
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
line[++cnt] = ScanLine(x1, y2, y1, 1);
yy[cnt] = y1;
line[++cnt] = ScanLine(x2, y2, y1, -1);
yy[cnt] = y2;
}
sort(yy + 1, yy + cnt + 1);
sort(line + 1, line + cnt + 1);
int len = unique(yy + 1, yy + cnt + 1) - yy - 1;
clr(cover, 0);
clr(tr, 0);
double ans = 0;
for (int i = 1; i <= cnt; ++i) {
ans += tr[1] * (line[i].x - line[i - 1].x);
yl = lower_bound(yy+1, yy+len+1, line[i].downY) - yy;
yr = lower_bound(yy+1, yy+len+1, line[i].upY) - yy - 1;
v = line[i].flag;
update(1, 1, len-1);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", ++cas, ans);
}
return 0;
}

HDU1542--Atlantis(扫描线)的更多相关文章

  1. [HDU1542]Atlantis(扫描线+线段树)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  2. hdu1542 Atlantis(矩阵面积的并)

    这个题算是我的第一个扫描线的题,扫描线算是一种思想吧,用到线段树+离散化.感觉高大上. 主要参考了这位大神的博客. http://www.cnblogs.com/kuangbin/archive/20 ...

  3. hdu1542 Atlantis 线段树--扫描线求面积并

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...

  4. hdu1542 Atlantis (线段树+扫描线+离散化)

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  5. HDU1542 Atlantis —— 求矩形面积并 线段树 + 扫描线 + 离散化

    题目链接:https://vjudge.net/problem/HDU-1542 There are several ancient Greek texts that contain descript ...

  6. HDU-1542 Atlantis(离散化+扫描线)

    题目大意:给n个矩形,可能重叠,求面积. 题目分析:线段树维护扫描线. 代码如下: # include<bits/stdc++.h> using namespace std; # defi ...

  7. Poj1151&HDU1542 Atlantis(扫描线+线段树)

    题意 给定\(n​\)个矩形\((x_1,y_1,x_2,y_2)​\),求这\(n​\)个矩形的面积并 题解 扫描线裸题,可以不用线段树维护,\(O(n^2)\)是允许的. #include < ...

  8. hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

    题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...

  9. [POJ1151][HDU1542]Atlantis(线段树,扫描线)

    英文题面,我就只放个传送门了. Solution  题意是算矩形面积并,这是扫描线算法能解决的经典问题. 算法的大致思想是,把每一个矩形拆成上边和下边(以下称作扫描线),每条扫描线有四个参数l,r,h ...

  10. hdu1542 Atlantis (线段树+矩阵面积并+离散化)

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...

随机推荐

  1. FolderBrowserDialog组件选择文件夹

    1.选择路径 this.folderBrowserDialog1.ShowDialog(); if (this.folderBrowserDialog1.ShowDialog() == DialogR ...

  2. js函数语法

    <script type="text/javascript">    //1 普通方法  /*   *  function 方法名(参数){   *   方法体   * ...

  3. C# - ref & out

    引用参数和值参数 值参数,是在函数中此变量的任何修改都不影响函数调用中指定的参数,除非把它当作返回值返回,经典例子,交换两个数,但是返回值只有一个. 此时可以用引用参数,函数处理的变量和函数调用中使用 ...

  4. Seven Python Tools All Data Scientists Should Know How to Use

    Seven Python Tools All Data Scientists Should Know How to Use If you’re an aspiring data scientist, ...

  5. 如何使用 Zend Expressive 建立 NASA 图片库?

    在本文中,我们将借助 NASA 天文图库 API,使用 Zend Expressive 建立图片库.最后的结果将显示在 AstroSplash 网站,该网站是为了文本特意搭建的.本文系 OneAPM ...

  6. 转:Linux Shell编程入门

    http://www.cnblogs.com/suyang/archive/2008/05/18/1201990.html 从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来 ...

  7. Vmware 8.00 文件共享ubuntu

    http://bolg.sinaapp.com/html/2012/1848.html 这是解决vm不能共享的解决方案. 今天学会的Linux命令: cp -i *** ~/tmp cd VMware ...

  8. [杂题]CSUOJ1274Balls and Boxes

    题目链接 题意:中文题 题意不多赘述 值得注意的是n<m 不必考虑n==m的情况 (m是盒子个数, n是每次选取的盒子个数, 不要弄反了!) 这题一看就是同余方程 每次选取n个盒子放球 也就是说 ...

  9. [线段树]HDOJ5091 Beam Cannon

    题意:给n, w, h  (1 <= N <= 10000,1 <= W <= 40000,1 <= H <= 40000) $w\times h$是可以射到的范围 ...

  10. Android 自定义seekbar中,thumb被覆盖掉一部分问题

    (图一)  (图二)    (图三) 做一个自定义的seekbar,更改其背景图片: <com.android.Progress android:id="@+id/focus_seek ...