Picture

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

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

First

/*
hdu 1828 线段树扫描线(周长) 给你一些矩阵,有部分or全部重叠.求最终图形的周长 对于x轴的边,矩阵的下边标为1,矩阵的上边标为-1.每次插入后用当前覆盖面积
减去上一次的覆盖面积(即新增长度),扫描过一个矩阵的上边后便能消除下边的
影响。
对x,y轴分别扫描一次即可 最开始没考虑重边的问题,结果C++ AC(G++ WR)
然后更改后G++才过 - - 2
0 0 1 1
1 0 2 1 2
0 0 1 1
0 1 1 2 hhh-2016-03-26 16:35:21
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
#define lson (i<<1)
#define rson ((i<<1)|1)
typedef long long ll;
const int maxn = 20050;
int a[maxn];
struct node
{
int l,r;
int sum,len;
int mid()
{
return (l+r)>>1;
}
} tree[maxn*5]; void push_up(int i)
{
if(tree[i].sum)
tree[i].len = (tree[i].r-tree[i].l+1);
else if(tree[i].l == tree[i].r)
tree[i].len = 0;
else
tree[i].len = tree[lson].len+tree[rson].len;
} void build(int i,int l,int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].sum = 0;
tree[i].len = 0;
if(l == r)
return ; int mid = tree[i].mid();
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
} void push_down(int i)
{
// if(tree[i].sum)
// {
// tree[lson].sum += tree[i].sum;
// tree[rson].sum += tree[i].sum;
// tree[lson].len = tree[lson].r-tree[lson].l;
// tree[rson].len = tree[rson].r-tree[rson].l;
// }
} void Insert(int i,int l,int r,int val)
{
if(tree[i].l >= l && tree[i].r <=r )
{
tree[i].sum += val;
push_up(i);
return ;
}
int mid = tree[i].mid();
push_down(i);
if(l <= mid)
Insert(lson,l,r,val);
if(r > mid)
Insert(rson,l,r,val);
push_up(i);
} struct edge
{
int l,r;
int va,high;
};
edge tx[maxn*2];
edge ty[maxn*2]; bool cmp(edge a,edge b)
{
if(a.high != b.high)
return a.high < b.high;
else //如果有重边则要先插入在删除
return a.va > b.va;
} int main()
{
int n;
while(scanf("%d",&n) != EOF)
{
int x1,x2,y1,y2;
int tox = 0,lx=0x3f3f3f3f,rx=0;
int toy = 0,ly=0x3f3f3f3f,ry=0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
lx = min(x1,lx),rx = max(rx,x2);
ly = min(y1,ly),ry = max(ry,y2);
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1;
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1;
ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x1,ty[toy++].va=1;
ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x2,ty[toy++].va=-1;
}
sort(tx,tx+tox,cmp);
sort(ty,ty+toy,cmp);
int ans=0,prelen = 0;
build(1,lx,rx-1);
for(int i = 0; i < tox; i++)
{
Insert(1,tx[i].l,tx[i].r-1,tx[i].va);
ans += abs(tree[1].len-prelen);
prelen = tree[1].len;
}
//cout << ans <<endl;
build(1,ly,ry-1);
prelen = 0;
for(int i = 0; i < toy; i++)
{
Insert(1,ty[i].l,ty[i].r-1,ty[i].va);
ans += abs(tree[1].len-prelen);
prelen = tree[1].len;
}
cout << ans <<endl;
}
return 0;
}

  

Second

/*
hdu 1828 线段树扫描(周长)2 在向上扫描的过程中我们可以计算出平行于x轴的长度
然后在两条线之间我们只需要计算出有多少条竖线便能得带这两条线之间平行于
y轴的长度。
用ls和rs来表示当前节点左右端点是否被覆盖
在处理竖线数量时,注意合并带来的影响,假设lson.rs和rson.ls都存在值的话
说明存在重叠的部分 hhh-2016-03-26 17:58:50
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <functional>
using namespace std;
#define lson (i<<1)
#define rson ((i<<1)|1)
typedef long long ll;
const int maxn = 20050;
int a[maxn];
struct node
{
int l,r;
int sum,len;
int num,ls,rs;
int mid()
{
return (l+r)>>1;
}
} tree[maxn*5]; void push_up(int i)
{
if(tree[i].sum)
{
tree[i].len = (tree[i].r-tree[i].l+1);
tree[i].ls = tree[i].rs = 1;
tree[i].num = 1;
}
else if(tree[i].l == tree[i].r)
{
tree[i].len= 0;
tree[i].num=tree[i].rs=tree[i].ls=0;
}
else
{
tree[i].len = tree[lson].len+tree[rson].len;
tree[i].ls = tree[lson].ls;
tree[i].rs = tree[rson].rs;
tree[i].num = tree[lson].num+tree[rson].num;
tree[i].num -= (tree[lson].rs&tree[rson].ls);
//减去重叠的部分
}
} void build(int i,int l,int r)
{
tree[i].l = l;
tree[i].r = r;
tree[i].sum = tree[i].len = 0;
tree[i].ls = tree[i].rs = tree[i].num = 0;
if(l == r)
return ; int mid = tree[i].mid();
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
} void push_down(int i)
{ } void Insert(int i,int l,int r,int val)
{
if(tree[i].l >= l && tree[i].r <=r )
{
tree[i].sum += val;
push_up(i);
return ;
}
int mid = tree[i].mid();
push_down(i);
if(l <= mid)
Insert(lson,l,r,val);
if(r > mid)
Insert(rson,l,r,val);
push_up(i);
} struct edge
{
int l,r;
int va,high,id;
};
edge tx[maxn*2]; bool cmp(edge a,edge b)
{
if(a.high != b.high)
return a.high < b.high;
else
return a.va > b.va;
} int main()
{
int n;
while(scanf("%d",&n) != EOF)
{
int x1,x2,y1,y2;
int tox = 0,lx=0x3f3f3f3f,rx=0;
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
lx = min(x1,lx),rx = max(rx,x2);
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1;
tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1;
}
sort(tx,tx+tox,cmp);
int ans=0,prelen = 0;
build(1,lx,rx-1);
//tx[tox] = tx[tox+1];
for(int i = 0; i < tox; i++)
{
Insert(1,tx[i].l,tx[i].r-1,tx[i].va);
ans += abs(tree[1].len-prelen);
if(i != tox-1)
ans += (tx[i+1].high-tx[i].high)*tree[1].num*2;
prelen = tree[1].len;
}
cout << ans <<endl;
}
return 0;
}

  

hdu 1828 线段树扫描线(周长)的更多相关文章

  1. HDU 1828 线段树+扫描线(计算矩形周长并)

    题意:给你n个矩形,然后矩形有可能重叠,要你求周长 思路:首先碰到这种矩形在数轴上那么第一反应应该想到的是扫描线, 做周长我们有两种方法 第一种,我们可以分开两部分求,第一遍求x轴上的贡献,第二遍求y ...

  2. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  3. hdu 5091(线段树+扫描线)

    上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...

  4. HDU 5107 线段树扫描线

    给出N个点(x,y).每一个点有一个高度h 给出M次询问.问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对全部的点和询 ...

  5. hdu 1542 线段树+扫描线 学习

    学习扫描线ing... 玄学的东西... 扫描线其实就是用一条假想的线去扫描一堆矩形,借以求出他们的面积或周长(这一篇是面积,下一篇是周长) 扫描线求面积的主要思想就是对一个二维的矩形的某一维上建立一 ...

  6. hdu 1255(线段树 扫描线) 覆盖的面积

    http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所 ...

  7. HDU 5091 线段树扫描线

    给出N个点.和一个w*h的矩形 给出N个点的坐标,求该矩形最多能够覆盖多少个点 对每一个点point(x.y)右边生成相应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍.遇到点则用 ...

  8. hdu 4419 线段树 扫描线 离散化 矩形面积

    //离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...

  9. hdu 3265 线段树扫描线(拆分矩形)

    题意:        给你n个矩形,每个矩形上都有一个矩形的空洞,所有的矩形都是平行于x,y轴的,最后问所有矩形的覆盖面积是多少. 思路:       是典型的矩形覆盖问题,只不过每个矩形上多了一个矩 ...

随机推荐

  1. Flask-uploads 简单使用

    pip install flask-uploads#先导入次此处需要用到的库: from flask_uploads import UploadSet, IMAGES, configure_uploa ...

  2. System V IPC 之信号量

    本文继<System V IPC 之共享内存>之后接着介绍 System V IPC 的信号量编程.在开始正式的内容前让我们先概要的了解一下 Linux 中信号量的分类. 信号量的分类 在 ...

  3. a标签传递参数

    a标签传递参数 单个参数:参数名称前面跟   ? <a href="localhost:8080/arguments?id=1">单个参数</a> 多个参数 ...

  4. V7000存储数据恢复_底层结构原理拆解及Mdisk磁盘掉线数据恢复方法

    Storwize V7000(也就是我们常说的V7000)是新推出的一款中端存储系统,这款系统的定位虽然在中端,但是Storwize V7000提供有存储管理功能,这一功能以前只有高端存储才拥有(例如 ...

  5. Spring Cache扩展:注解失效时间+主动刷新缓存(二)

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  6. ( 转 ) 聊一聊C#的Equals()和GetHashCode()方法

    聊一聊C#的Equals()和GetHashCode()方法   博客创建一年多,还是第一次写博文,有什么不对的地方还请多多指教. 关于这次写的内容可以说是老生长谈,百度一搜一大堆.大神可自行绕路. ...

  7. SSH 配置

    ssh免密通用配置 Host * Port 1234 User root #ProxyCommand nc -X 5 -x 127.0.0.1:1081 %h %p #5 socks5, 4 sock ...

  8. 使用 slf4j抽象日志层 和 其他日志实现对接

    前言 如果你正在提供一个开源的Java-jar,那么让你的项目仅依赖slf4j-api然后让你的用户在他们开发和运营环境中选择任意的日志实现绝对是个好想法,.作为终端用户,他们可以快速地从上面提到的日 ...

  9. Java设计模式(八)Proxy代理模式

    一.场景描述 代理在生活中并不少见,租房子需要找中介,打官司需要找律师,很多事情我们需要找专业人士代理我们做,另一方面,中介和律师也代理了房东.法律程序与我们打交道. 当然,设计模式中的代理与广义的代 ...

  10. Java中如何实现j并发更新数据库同一条数据

    分情况来说:普通单应用并发.多应用或多台服务器并发 情况一:普通单应用并发 使用关键字synchronized就可实现. 情况二:多应用或多台服务器并发 因多个应用之间并非同一个jvm(应用)内,因此 ...