Picture POJ - 1177

题目:

多个矩阵相交在一起,问新图形的周长是多少

题解:

参考题解

周长分为两部分:横线和竖线
横线计算方法:现在总区间被覆盖的长度和上一次总区间被覆盖的长度之差的绝对值
那么我们只需要从上往下,再从左往右扫描两次即可
但是这样需要两次,有没有更简化的方法:

现在我们打算一次自上而下的扫描把横线竖线都算出来
横线的算法和上面说的方法一样:现在这次总区间被覆盖的长度和上一次总区间被覆盖的长度之差的绝对值
我们用线段树来记录一些信息:

  1. l,r :该节点代表的线段的左右端点坐标
  2. len:这个区间被覆盖的长度(即计算时的有效长度)
  3. s:表示这个区间被覆盖率多次
  4. lc,rc:标记这个节点的左右两个端点是否被覆盖(0表示没有,1表示有)
  5. sum:表示这个区间有多少条不连续的线段

注意:这个sum涉及到了竖线的计算
若区间[0,10]被[1,2][4,5]覆盖,则num = 2

若区间[0,10]被[1,3][4,5]覆盖,则num = 1(两区间刚好连在一起)

若区间[0,10]被[1,5][2,6]覆盖,则num = 1(两区间连起来还是一段)
这样就可以计算竖线:
竖线的长度=【下一条即将被扫到的横线的高度 - 现在扫到的横线的高度】* 2 * num
乘2是因为每条线段有两个端点
有num个不相交的横线,向下划动h,不就形成长度为h的2 * num个竖线

代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ls i << 1
#define rs i << 1 | 1
#define m(i) ((tr[i].l + tr[i].r) >> 1)
typedef long long ll;
const int N= 5007;
const int X= 20007;
const int inf= 1 << 29;
struct Edge
{int l, r;int h;int f;bool operator<(const Edge& a) const{return h < a.h;}
} edge[N * 2];
struct tree
{int l, r;int len;int s;bool lc, rc; //表示这个节点代表的区间左右两个端点是否被覆盖int num; //这个区间有多少不连续到线段
} tr[X * 4];
void pushup(int i)
{if (tr[i].s) {tr[i].len= tr[i].r - tr[i].l + 1;tr[i].lc= tr[i].rc= 1;tr[i].num= 1;}else if (tr[i].l == tr[i].r) {tr[i].len= 0;tr[i].lc= tr[i].rc= 0;tr[i].num= 0;}else {tr[i].len= tr[ls].len + tr[rs].len;tr[i].lc= tr[ls].lc;tr[i].rc= tr[rs].rc;tr[i].num= tr[ls].num + tr[rs].num - (tr[ls].rc & tr[rs].lc);}
}
void build(int i, int l, int r)
{tr[i].l= l;tr[i].r= r;tr[i].s= tr[i].len= 0;tr[i].lc= tr[i].rc= tr[i].num= 0;if (l == r)return;int mid= m(i);build(ls, l, mid);build(rs, mid + 1, r);
}
void update(int i, int l, int r, int xx)
{if (l == tr[i].l && tr[i].r == r) {tr[i].s+= xx;pushup(i);return;}int mid= m(i);if (r <= mid)update(ls, l, r, xx);else if (l > mid)update(rs, l, r, xx);else {update(ls, l, mid, xx);update(rs, mid + 1, r, xx);}pushup(i);
}
int main()
{int n;while (scanf("%d", &n) != EOF) {int x1, x2, y1, y2, mx= -inf, mn= inf;int tot= 0;for (int i= 0; i < n; i++) {scanf("%d%d%d%d", &x1, &y1, &x2, &y2);mx= max(mx, max(x1, x2));mn= min(mn, min(x1, x2));Edge& t1= edge[tot];Edge& t2= edge[tot + 1];t1.l= t2.l= x1;t1.r= t2.r= x2;t1.h= y1;t1.f= 1;t2.h= y2;t2.f= -1;tot+= 2;}sort(edge, edge + tot);//数据小不用离散化int ans= 0;int last= 0;build(1, mn, mx - 1);for (int i= 0; i < tot; i++) {update(1, edge[i].l, edge[i].r - 1, edge[i].f);ans+= abs(tr[1].len - last);ans+= (edge[i + 1].h - edge[i].h) * 2 * tr[1].num;last= tr[1].len;}printf("%d\n", ans);}return 0;
}

Picture POJ - 1177(矩形周长并))相关推荐

  1. [洛谷P1856] [USACO5.5]矩形周长Picture

    洛谷题目链接:[USACO5.5]矩形周长Picture 题目背景 墙上贴着许多形状相同的海报.照片.它们的边都是水平和垂直的.每个矩形图片可能部分或全部的覆盖了其他图片.所有矩形合并后的边长称为周长 ...

  2. 【扫描线法】 poj 1177 hdu 1828

    可以看看这里: http://www.cnblogs.com/Booble/archive/2010/10/10/1847163.html 为了写扫描线, 大概写了有史以来最丑的线段树了. poj 1 ...

  3. 矩形面积和矩形周长并的模板——来自notonlysuccess

    矩形面积并 hdu1542 Atlantis 题意:矩形面积并 思路:浮点数先要离散化;然后把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用cnt表示该区间下边比上边多几个,sum代 ...

  4. 线段树扫描线求矩形周长详解

    线段树扫描线求矩形周长详解 原创 wucstdio 最后发布于2018-04-24 16:12:09 阅读数 841 收藏 发布于2018-04-24 16:12:09 版权声明:本文为博主原创文章, ...

  5. java继承类长方形面积_java_java用接口、多态、继承、类计算三角形和矩形周长及面积的方法,本文实例讲述了java用接口、多 - phpStudy...

    java用接口.多态.继承.类计算三角形和矩形周长及面积的方法 本文实例讲述了java用接口.多态.继承.类计算三角形和矩形周长及面积的方法.分享给大家供大家参考.具体如下: 定义接口规范: /** ...

  6. java继承求三角形圆形面积_java用接口、多态、继承、类计算三角形和矩形周长及面积的方法...

    本文实例讲述了java用接口.多态.继承.类计算三角形和矩形周长及面积的方法.分享给大家供大家参考.具体如下: 定义接口规范: /** * @author vvv * @date 2013-8-10 ...

  7. 定义一个矩形类(Rectangle),私有数据成员为矩形的长度( len)和宽度(wid),缺省构造函数置len和wid为0,有参构造函数置len和wid为对应形参的值,另外还包括求矩形周长、面积

    #include <iostream> using namespace std; class Rectangle {     private: double len,wid; //私有数据 ...

  8. POJ 1177 Picture [离散化+扫描线+线段树]

    http://poj.org/problem?id=1177 给若干矩形,求被覆盖的区域的周长. 将 y 坐标离散化后,按 x 坐标进行扫描.用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 ...

  9. 洛谷P1856 [USACO5.5]矩形周长Picture

    题目背景 墙上贴着许多形状相同的海报.照片.它们的边都是水平和垂直的.每个矩形图片可能部分或全部的覆盖了其他图片.所有矩形合并后的边长称为周长. 题目描述 编写一个程序计算周长. 如图1所示7个矩形. ...

最新文章

  1. net core 使用 rabbitmq
  2. Monitor Asynchronous Apex
  3. 《JavaScript高效图形编程(修订版)》——第2章 DHTML基础 2.1创建DHTML sprite
  4. 乐Phone:还原联想的联想
  5. 根据二叉树的先序和中序求后序遍历
  6. 16进制数组转字符串
  7. c ++查找字符串_C ++朋友功能| 查找输出程序| 套装1
  8. python-正则表达式1909
  9. Ubuntu下安装中文输入法
  10. SQL HAVING Clause
  11. airflow时区问题
  12. 基于CentOS7.2安装Kubernetes-v1.2
  13. 【Github使用感触之一】使多文件多版本变得简单
  14. 清除此计算机中wps云盘,教大家Win10系统删除WPS网盘的方法,爱纯净官网
  15. MBE风工作汇报PPT模板
  16. 奇异矩阵和非奇异矩阵 行列式矩阵简单理解 代数意义 几何意义 行列式的定义: 二阶行列式的几何意义: 三阶行列式的几何意义: 行列式化为对角形的几何解释: 二阶行列式乘积项的几何意
  17. 基于Java 生产者消费者模式(详细分析)
  18. 正态分布概率密度函数的推导
  19. 采用ODC改善软件质量:一个案例研究
  20. 利用python做薪酬管理_HRD告诉你,6个薪酬体系策略做好薪酬管理

热门文章

  1. 西游记里学化学,请收下我的膝盖~ | 今日最佳
  2. 每个人都应该学习编程,因为它会教你如何思考
  3. 编程从业五年的十四条经验,句句朴实
  4. 《自然》杂志:中国人越来越沉迷于对着一个叫“区块链”的东西胡言乱语
  5. 有了它,从此成为自带BGM的主角~
  6. feign和ajax,SpringCloud-feign 声明式服务调用
  7. c#语言输出字符串长度,根据宽度来决定显示的字符串长度(C#)
  8. sql年月日24小时制_Power Query 抓取气象台24小时降水量数据
  9. python获取历史双色球数据_你的梦想,我来买单!Python分析双色球中奖号码竟成功获取特等奖
  10. abap al设置单元格可编辑 oo_润乾报表美化设置 -- 样式