题意:

给定n个矩阵的左下角和右上角坐标,求矩阵面积并(矩阵总是正放的,即与x轴y轴都平行)

思路:

扫描线裸题

http://www.cnblogs.com/fenshen371/p/3214092.html

对于一个矩阵,我们仅仅关心他的上下底边。线段树维护的是当前有哪些区间是被线段覆盖的(即把线段都移动到x轴上,x轴被覆盖的长度是多少)

我们从上往下扫,则对于随意一条(如15,10)  我们会计算(20,13)-(15,10)之间的矩形面积

而对于(11,8),我们会计算(15,10)-(11,8)之间的矩形面积。

矩形面积= 底边长*高

1、显然这里的高就是(15,10)-(11,8) ; 更通俗的就是:line[i-1].y - line[i].y;

2、而底边长则是取决于从(11,8) 向上(不包含(11,8))有多长的区间被线段覆盖了,这个长度则是用线段树来维护。

3、而(11,8)这条线段对于线段树或者说 对区间是覆盖还是删除则取决于这条线段是上底边还是下底边(上底边则是覆盖,下底边则是删除)

对于线段树的建树也要注意一个要点:

平时建树的习惯是:

[1,4]

/ \

[1,2]    [3,4]

而我们用线段树维护的是x轴坐标,是连续的区间,假设这样建树则忽略掉了区间[2,3]

所以我们建成如此:

[1,4]

/ \

[1,2] [2,4]

即: build(l,mid,L(id)); build(mid,r,R(id)); mid不+1了

推断某区间是否为最底层区间时则写成 if(tree[id].l +1 == tree[id].r) ;

由于[1,1]这个区间对我们是没有意义的,即 l < r才是有长度的区间,才是有意义的。而最小的l < r 就是 l +1 = r 的情况。

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define N 205
#define L(x) (x<<1)
#define R(x) (x<<1|1)
int Mid(int a,int b){return (a+b)>>1;}
//这份代码是对y轴建树,从左到右扫
struct node{ //这个区间被c条线段覆盖了
int l, r;
int c; //用来记录重叠情况
double cnt, lf, rf;//离散点l相应的实际点lf cnt表示这个区间内存在的线段长度
}tree[N*4];
struct Line{
double x,y1,y2;
int f;
Line(double a=0.0,double b=0.0,double c=0.0, int d=0):x(a),y1(b),y2(c),f(d){}
}line[N*2];
bool cmp(Line a, Line b){return a.x<b.x;}
double y[N];
void build(int l, int r, int id){
tree[id].l = l, tree[id].r = r;
tree[id].cnt = tree[id].c = 0;
tree[id].lf = y[l]; tree[id].rf = y[r];
if(l+1==r)return ;
int mid = Mid(l,r);
build(l, mid, L(id));
build(mid,r,R(id));
}
void push_up(int id){
if(tree[id].c){
tree[id].cnt = tree[id].rf - tree[id].lf;
return ;
}
if(tree[id].l+1 == tree[id].r) tree[id].cnt = 0;
else tree[id].cnt = tree[L(id)].cnt + tree[R(id)].cnt;
}
void update(int id, Line e){
if(e.y1 == tree[id].lf && tree[id].rf == e.y2){
tree[id].c += e.f;
push_up(id); return ;
}
if(e.y2 <= tree[L(id)].rf)
update(L(id),e);
else if(tree[R(id)].lf <= e.y1)
update(R(id),e);
else {
Line tmp = e; tmp.y2 = tree[L(id)].rf; update(L(id),tmp);
tmp = e; tmp.y1 = tree[R(id)].lf; update(R(id),tmp);
}
push_up(id);
}
set<double>myset;
set<double>::iterator p;
int main(){
int i, j, n, Cas = 1;
double x1,x2,y1,y2;
while(scanf("%d",&n),n){
myset.clear();
int top = 1;
for(i = 1;i <= n; i++){
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
myset.insert(y1); myset.insert(y2);
Line E = Line(x1,y1,y2,1);
line[top++] = E;
Line E2= Line(x2,y1,y2,-1);
line[top++] = E2;
}
sort(line+1, line+top, cmp);
int siz = 1;
for(p=myset.begin(); p!=myset.end(); p++) y[siz++] = *p;
build(1, siz-1, 1);
update(1, line[1]);
double ans = 0;
for(i = 2; i < top; i++){
ans += tree[1].cnt * (line[i].x - line[i-1].x);
update(1, line[i]);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",Cas++,ans);
}
return 0;
}

POJ 1151 Atlantis 求矩阵面积并 扫描线 具体解释的更多相关文章

  1. POJ 1151 Atlantis(扫描线)

    题目原链接:http://poj.org/problem?id=1151 题目中文翻译: POJ 1151 Atlantis Time Limit: 1000MS   Memory Limit: 10 ...

  2. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  3. POJ 1151 Atlantis(经典的线段树扫描线,求矩阵面积并)

    求矩阵的面积并 采用的是区间更新 #include <iostream> #include <stdio.h> #include <string.h> #inclu ...

  4. POJ 1151 Atlantis 线段树+离散化+扫描线

    这次是求矩形面积并 /* Problem: 1151 User: 96655 Memory: 716K Time: 0MS Language: G++ Result: Accepted */ #inc ...

  5. POJ 1151 Atlantis(离散化)

    点我看题目 题意 : 就是给你n个矩形的最左下角和最右上角的点的坐标,然后将这n个矩形的面积求出来. 思路 : 离散化求矩形面积并.离散化具体介绍.将横纵坐标离散开来分别存,然后排序,也可以按照黑书上 ...

  6. Area - POJ 1654(求多边形面积)

    题目大意:从原点开始,1-4分别代表,向右下走,向右走,向右上走,向下走,5代表回到原点,6-9代表,向上走,向左下走,向左走,向左上走.求出最后的多边形面积. 分析:这个多边形面积很明显是不规则的, ...

  7. POJ 1151 Atlantis 矩形面积求交/线段树扫描线

    Atlantis 题目连接 http://poj.org/problem?id=1151 Description here are several ancient Greek texts that c ...

  8. hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]

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

  9. POJ 1151 Atlantis(线段树-扫描线,矩形面积并)

    题目链接:http://poj.org/problem?id=1151 题目大意:坐标轴上给你n个矩形, 问这n个矩形覆盖的面积 题目思路:矩形面积并. 代码如下: #include<stdio ...

随机推荐

  1. [C++]返回最值元素

    1 priority_queue C++中优先队列是一种特殊的队列,能够返回队列中优先级最大或者最小的元素,其内部是由堆实现的,个人认为这种方式使用更加直观. 1.1 返回vector中的最值元素 # ...

  2. python中round(四舍五入)的坑

    python中的round函数不能直接拿来四舍五入,一种替代方式是使用Decimal.quantize()函数. 具体内容待补. >>> round(2.675, 2) 2.67 可 ...

  3. mysqlsla 安装

    tar -zxvf mysqlsla-2.03.tar.gz cd mysqlsla-2.03 perl Makefile.PLmake && make install BEGIN f ...

  4. Singleton 多线程

    单例模式 何为单例模式,在GOF的<设计模式:可复用面向对象软件的基础>中是这样说的:保证一个类只有一个实例,并提供一个访问它的全局访问点.首先,需要保证一个类只有一个实例:在类中,要构造 ...

  5. 【LOJ】#2035. 「SDOI2016」征途

    题解 有人管它叫带权二分,有人管它叫dp凸优化,有人管它叫wqs二分-- 延伸出来还有zgl分治,xjp¥!%#!@#¥!# 当我没说 我们拆个式子,很容易发现所求的就是 \(m\sum_{i = 1 ...

  6. linux添加桌面快捷方式

    linux通过软件中心安装的程序快捷图标都放在/usr/share/applications/目录下.点选一个图标右键,选择复制到,目录选择桌面即可.    但是有一些软件自行安装后,在那个目录里没有 ...

  7. .NET Runtime version 2.0.50727.xxx 执行引擎错误。 (Fatal Execution Engine Error)

    如题问题困扰本人良久. 尝试VS2005.VS2008.VS2010均出现过次问题. 主要现象: 1. Window设计器会崩溃,直接挂掉.(当逐条注释掉一些静态构造函数内的代码是情况好转) 2. 发 ...

  8. 20169211《Linux内核原理与分析》 第九周作业

    一.Linux内核虚拟文件系统学习总结 Linux支持各种文件系统,Linux内核通过虚拟文件系统了对各种文件系统共性的进行抽象,并对外提供统一接口,从面向对象编程的角度来看,称为抽象文件系统更为合适 ...

  9. spring4声明式事务—02 xml配置方式

    1.配置普通的 controller,service ,dao 的bean. <!-- 配置 dao ,service --> <bean id="bookShopDao& ...

  10. python opencv3 窗口显示摄像头的帧

    git:https://github.com/linyi0604/Computer-Vision # coding:utf8 import cv2 """ 在窗口显示摄像 ...