Problem Description
  A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter.

  Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.

The corresponding boundary is the whole set of line segments drawn in Figure 2.

  The vertices of all rectangles have integer coordinates.

 
  题目就是求矩形并的周长和。
  这个题其实和求矩形的面积和没有什么区别,线段树维护的是覆盖区间的总长度,然后扫描线是从左到右扫描,每次计算一个竖边的时候,这一次区间覆盖长度减去上一次区间覆盖长度的绝对值就是变化量,要加到ans上。
  然后就是计算横边的时候有点麻烦,可以再从下到上扫描一遍,从新弄一个线段树。
  不过根据那个杭电大神的做法,是同时再维护三个线段树,分别表示区间内线段端点的个数,区间内左边界是否被覆盖,右边界是否被覆盖,后两个线段树是用来辅助计算前面那个的。然后x的差值乘上线段的个数就是横边的了。
  不过这里要注意先计算还是先更新的问题,横边要先计算,然后更新,然后竖边计算。
 
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm> #define lc po*2
#define rc po*2+1
#define lson L,M,lc
#define rson M+1,R,rc using namespace std; const int maxn=; struct BIAN
{
int x,y1,y2;
short state;
}; BIAN bian[];
bool vis[maxn];
int BIT[maxn*];
int COL[maxn*]; bool lBIT[maxn*],rBIT[maxn*];
int coubian[maxn*]; void pushUP(int L,int R,int po)
{
if(COL[po])
{
BIT[po]=R-L+;
lBIT[po]=rBIT[po]=;
coubian[po]=;
}
else if(L==R)
{
BIT[po]=;
lBIT[po]=rBIT[po]=;
coubian[po]=;
}
else
{
BIT[po]=BIT[lc]+BIT[rc];
lBIT[po]=lBIT[lc];
rBIT[po]=rBIT[rc];
coubian[po]=coubian[lc]+coubian[rc]; if(lBIT[rc]&&rBIT[lc])
coubian[po]-=;
}
} void update(int ul,int ur,int ut,int L,int R,int po)
{
if(ul<=L&&ur>=R)
{
COL[po]+=ut;
pushUP(L,R,po); return;
} int M=(L+R)/; if(ul<=M)
update(ul,ur,ut,lson);
if(ur>M)
update(ul,ur,ut,rson); pushUP(L,R,po);
} bool cmp(BIAN a,BIAN b)
{
return a.x<b.x;
} int main()
{
int N;
int x1,x2,y1,y2;
int ans,last; while(~scanf("%d",&N))
{
ans=;
last=;
memset(COL,,sizeof(COL));
memset(BIT,,sizeof(BIT));
memset(vis,,sizeof(vis));
memset(lBIT,,sizeof(lBIT));
memset(rBIT,,sizeof(rBIT));
memset(coubian,,sizeof(coubian)); for(int i=;i<=N;++i)
{
scanf("%d %d %d %d",&x1,&y1,&x2,&y2); bian[i*-].x=x1;
bian[i*-].y1=y1+;
bian[i*-].y2=y2+;
bian[i*-].state=; bian[i*].x=x2;
bian[i*].y1=y1+;
bian[i*].y2=y2+;
bian[i*].state=-;
} sort(bian+,bian+*N+,cmp); for(int i=;i<=*N;++i)
{
ans+=coubian[]*(bian[i].x-bian[i-].x); update(bian[i].y1,bian[i].y2-,bian[i].state,,,); ans+=abs(BIT[]-last);
last=BIT[];
} printf("%d\n",ans);
} return ;
}

(中等) HDU 1828 Picture,扫描线。的更多相关文章

  1. 51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)

    1206 Picture  题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 给出平面上的N个矩形(矩形的边平行于X轴 ...

  2. HDU 1828 Picture(长方形的周长和)

    HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4 ...

  3. HDU 1828 Picture(线段树扫描线求周长)

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  4. HDU 1828“Picture”(线段树+扫描线求矩形周长并)

    传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...

  5. hdu 1828 Picture(线段树 || 普通hash标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others)    Mem ...

  6. HDU 1828 Picture (线段树+扫描线)(周长并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 给你n个矩形,让你求出总的周长. 类似面积并,面积并是扫描一次,周长并是扫描了两次,x轴一次,y ...

  7. POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

    求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...

  8. hdu 1828 Picture(线段树扫描线矩形周长并)

    线段树扫描线矩形周长并 #include <iostream> #include <cstdio> #include <algorithm> #include &l ...

  9. hdu 1828 Picture(线段树,扫描线)

    A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wa ...

随机推荐

  1. UVA - 10635 最长公共子序列

    input n,p,q 2<=n<=250 1<=p,q<=n*n 1 a1 a2 a3 ... ap 1<ai<n*n,ai!=aj 1 b1 b2 b3 ... ...

  2. c++模板两个数的加法

    1.最简单的情况: template<class T> T Add(const T& a, const T& b) { return a + b; } 缺点是不能够处理不同 ...

  3. MongoDB和Redis区别

    简介 MongoDB更类似Mysql,支持字段索引.游标操作,其优势在于查询功能比较强大,擅长查询JSON数据,能存储海量数据,但是不支持事务. Mysql在大数据量时效率显著下降,MongoDB更多 ...

  4. AI 人工智能 探索 (三)

    三类子弹的设计 using UnityEngine; using System.Collections; public class AI : AssembleModel { private Hasht ...

  5. java 文件字节输入流

    Example10_4.java import java.io.*; public class Example10_4 { public static void main(String args[]) ...

  6. 河南多校联合训练 F 不是匹配

    描述  有N个人,N个活动, 每个人只会对2个或者3个活动感兴趣,  每个活动也只有两个人或者两个活动对它兴趣,每个人参加一个  感兴趣的活动需要一天 ,且当天该活动被参加时,其他的人不能参加  如果 ...

  7. Mysql笔记3数据库基本操作

    1 创建数据库 create database 数据名称 default character set 编码; 2查看常用的编码校验规则 mysql> show character set; 3删 ...

  8. VirtualBox中CentOS通过Host-Only方式实现虚拟机主机互相访问、共享上网

    VirtualBox常用的网络配置如下: 连接方式 主机访问虚拟机 虚拟机访问主机 虚拟机访问虚拟机 虚拟机访问外网 说明 网络地址转换(NAT) 不支持 支持 不支持 支持 默认连接方式,虚拟IP, ...

  9. Junit单元测试的简单使用(主要是在spring框架下的项目)

    首先是解释什么是单元测试,单元测试是指对于一个大型项目里,对于单一模块或者单一接口的测试. 然后解释为什么要写单元测试,首先对于一个大型的项目,如果你每次都要重启一遍服务器调页面或者接口的bug,那就 ...

  10. Safari WebApp 模拟 原声APP禁止打开新窗口JS代码

    if(("standalone" in window.navigator) && window.navigator.standalone) { var noddy, ...