Picture

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3310    Accepted Submission(s): 1723

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.

 
Input
Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.

0 <= number of rectangles < 5000 
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Please process to the end of file.

 
Output
Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.
 
Sample Input
7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16
 
Sample Output
228
 
Source
 
题目意思:
给n个矩形,求并后的总周长
 
思路:
矩形周长并,很经典的扫描线题目。周长=水平线+竖直线。
求水平线的长度时,每插入一条线段后总长度减去插入线段之前的总长度即为增长的长度,最终即得出水平线的长度。
求竖直线的长度时,每插入一条线段后“裸露”出的点的个数乘上后一线段高度和这一线段的高度差,即得出竖直线长度。
 
 
代码:
 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <set>
using namespace std; #define N 5005
#define ll root<<1
#define rr root<<1|1
#define mid (a[root].l+a[root].r)/2 int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
int abs(int x,int y){return x<?-x:x;} struct node{
int l, r;
int sum;
int ysum;
int val;
bool lv, rv;
}a[N*]; struct Line{
int x1, x2, y;
int val;
Line(){}
Line(int a,int b,int c,int d){
x1=a;
x2=b;
y=c;
val=d;
}
}line[N*]; bool cmp(Line a,Line b){
return a.y<b.y;
}
int n, m;
int xx[N*]; int b_s(int key){
int l=, r=m;
while(l<=r){
int mm=(l+r)/;
if(xx[mm]==key) return mm;
else if(xx[mm]>key) r=mm-;
else if(xx[mm]<key) l=mm+;
}
} void build(int l,int r,int root){
a[root].l=l;
a[root].r=r;
a[root].ysum=a[root].sum=a[root].val=;
a[root].lv=a[root].rv=false;
if(l==r) return;
build(l,mid,ll);
build(mid+,r,rr);
} void up(int root){
if(a[root].val){
a[root].sum=xx[a[root].r+]-xx[a[root].l];
a[root].lv=a[root].rv=true;
a[root].ysum=;
}
else if(a[root].l==a[root].r) {
a[root].lv=a[root].rv=false;
a[root].ysum=a[root].sum=;
}
else{
a[root].sum=a[ll].sum+a[rr].sum;
a[root].lv=a[ll].lv;
a[root].rv=a[rr].rv;
a[root].ysum=a[ll].ysum+a[rr].ysum;
if(a[rr].lv&&a[ll].rv) a[root].ysum-=;
}
} void update(int l,int r,int val,int root){
if(a[root].l==l&&a[root].r==r){
a[root].val+=val;
up(root);
return;
}
if(l>=a[rr].l) update(l,r,val,rr);
else if(r<=a[ll].r) update(l,r,val,ll);
else{
update(l,mid,val,ll);
update(mid+,r,val,rr);
}
up(root);
} main()
{
int i, j, k;
int x1, y1, x2, y2;
int kase=;
while(scanf("%d",&n)==&&n){
m=;k=;
for(i=;i<n;i++){
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
line[k++]=Line(x1,x2,y1,);
line[k++]=Line(x1,x2,y2,-);
xx[m++]=x1;xx[m++]=x2;
}
sort(xx+,xx+m);
m=unique(xx+,xx+m)-xx-;
sort(line,line+k,cmp);
build(,m,);
int ans=;
int pre=;
for(i=;i<k-;i++){
update(b_s(line[i].x1),b_s(line[i].x2)-,line[i].val,);
ans+=abs(a[].sum-pre)+(line[i+].y-line[i].y)*a[].ysum;
pre=a[].sum;
}
update(b_s(line[k-].x1),b_s(line[k-].x2)-,line[k-].val,);
ans+=abs(a[].sum-pre);
printf("%d\n",ans);
}
}

HDU 1828 扫描线(矩形周长并)的更多相关文章

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

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

  2. 扫描线矩形周长的并 POJ1177

    //扫描线矩形周长的并 POJ1177 // 我是按x轴 #include <iostream> #include <cstdio> #include <cstdlib& ...

  3. hdu1828 Picture(线段树+扫描线+矩形周长)

    看这篇博客前可以看一下扫描线求面积:线段树扫描线(一.Atlantis HDU - 1542(覆盖面积) 二.覆盖的面积 HDU - 1255(重叠两次的面积))  解法一·:两次扫描线 如图我们可以 ...

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

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

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

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

  6. HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)

    做这道题之前,建议先做POJ 1151  Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...

  7. hdu 1828 线段树扫描线(周长)

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

  8. HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...

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

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

随机推荐

  1. 【转载】C++异常机制的学习

    参考了这篇文章:http://blog.chinaunix.net/uid-24517549-id-4079174.html 关于线程 进程和线程的概念相信各位看官早已耳熟能详.在这里,我只想带大家回 ...

  2. Service 与 Thread 的区别

    很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下. 1). Thread:Thre ...

  3. nginx系统真正有效的图片防盗链完整设置详解

    原文:http://www.wufangbo.com/nginx-fang-dao-lian/ 关于nginx防盗链的方法网上有很多教程,都可以用,但是我发现很多教程并不完整,所做的防盗链并不是真正的 ...

  4. java实现数据库连接池

    package com.kyo.connection; import java.sql.Connection; import java.sql.DatabaseMetaData; import jav ...

  5. OpenGL的几何变换3之内观察全景图

    继续上一篇文章的例子:OpenGL的几何变换2之内观察立方体 上一篇是通过绘图方式得到的立方体,没有贴图,这次加上纹理贴图. 通过纹理贴图有两种方案: 1.图片分割化,即是把一张完整的全景图片(就是支 ...

  6. SAP MM常用表

    EBAN 采购申请 MM模块EBAN_采购申请 EBKN 采购申请帐户设置 MM模块EBKN_采购申请帐户设置 EBUB 有关物料的运输请求的索引 MM模块EBUB_有关物料的运输请求的索引 EINA ...

  7. C语言中随机数相关问题

    用C语言产生随机数重要用到rand函数.srand函数.及宏RAND_MAX(32767),它们均在stdlib.h中进行了声明. int rand(void);//生成一个随机数 voidsrand ...

  8. [redis] windwos下安装和使用redis

    一篇很好的入门学习文章:Redis学习 Redis是一种nosql数据库,在开发中常用做缓存. 1.下载地址: 低版本下载地址:https://github.com/dmajkic/redis/dow ...

  9. XPath语法 在C#中使用XPath示例 【转http://www.cnblogs.com/yukaizhao/archive/2011/07/25/xpath.html】非常详细的文章

    XPath语法 在C#中使用XPath示例   XPath可以快速定位到Xml中的节点或者属性.XPath语法很简单,但是强大够用,它也是使用xslt的基础知识. 示例Xml: <?xml ve ...

  10. Qt之QThread(深入理解)

    简述 为了让程序尽快响应用户操作,在开发应用程序时经常会使用到线程.对于耗时操作如果不使用线程,UI界面将会长时间处于停滞状态,这种情况是用户非常不愿意看到的,我们可以用线程来解决这个问题. 前面,已 ...