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. Hibernate 系列教程7-双向一对一

    双向一对一 一对一主要用在 一个一方需要的信息比较少,比如注册的登录信息 另一个一方存储的信息比较多,比如注册之后用户填写的详细信息 实现方式常用的主要有2种: java模型都是一样,其中一个映射文件 ...

  2. eclipse的调试方法的简单介绍

    声明:本文不是自己 作为编程人员,程序的调试是一项基本功.在不使用IDE的时候,程序的调试多数是通过日志或者输入语句(System.out.println)的方式.可以把程序运行的轨迹或者程序运行过程 ...

  3. tiny210移植linux内核(3.0.8)杂项

    关于三星芯片nand内存分区文件: linux-3.0.8/drivers/mtd/nand/s3c_nand.c struct mtd_partition s3c_partition_info[] ...

  4. [转]intent 传递对象

    ---恢复内容开始--- Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[ ...

  5. JVM垃圾收集算法——分代收集算法

    分代收集算法(Generational Collection): 当前商业虚拟机的垃圾收集都采用"分代收集算法". 这种算法并没有什么新的思想,只是根据对象存活周期的不同将内存划分 ...

  6. java基本输入类型数据System.out.println()或System.out.print()

  7. cocos2d-x 3.x 橡皮擦功能

    1.HelloWorldScene.h cocos2d::DrawNode* _eraser; cocos2d::RenderTexture*_renderTexture; 2.HelloWorldS ...

  8. 学习笔记——建造者模式Builder

    构造者模式.外部场景如果需要一个汽车类,它不需要关心如何构造,它只需要告诉Director需要什么,就可以从Director获得. 如:CDirector(IBuilder* aBuilder); 场 ...

  9. Django - 模型表单(创建、更新、删除)

    urls.py # /music/alubm/add/ url(r'^album/add/$', views.AlbumCreate.as_view(), name="album-add&q ...

  10. Codeforces Round #349 (Div. 2) C. Reberland Linguistics (DP)

    C. Reberland Linguistics time limit per test 1 second memory limit per test 256 megabytes input stan ...