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. 【深度学习】深入理解ReLU(Rectifie Linear Units)激活函数

    论文参考:Deep Sparse Rectifier Neural Networks (很有趣的一篇paper) Part 0:传统激活函数.脑神经元激活频率研究.稀疏激活性 0.1  一般激活函数有 ...

  2. Xdebug的优点!php代码开发

    可以跟踪函数,知道那个函数出错,之前只是输出一点调试信息,只是哪一行错了,并且是白色 如果是死循环,debug会对死循环判断一百次的循环,并且会给出每一次循环的时间,内存,和函数名,位置.根据时间可以 ...

  3. CentOS 7 使用yum安装出现错误

    CentOS 7 使用yum安装软件出现错误: Loaded plugins: fastestmirror 此错误信息可能是因为DNS配置错误,可以通过更改配置文件来解决: 1. 使用vi打开DNS的 ...

  4. 深度学习之 mnist 手写数字识别

    深度学习之 mnist 手写数字识别 开始学习深度学习,先来一个手写数字的程序 import numpy as np import os import codecs import torch from ...

  5. 阿里云API网关(16)客户端请求的https支持

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  6. Docker学习笔记 - Docker的远程访问

    学习内容: 配置客户端与守护进程的远程访问 服务端配置-H选项: 使服务端支持远程被访问 客户端使用-H选项: 使客户端访问远程服务端 本地环境DOCKER_HOST设置客户端访问的默认服务端地址 准 ...

  7. Spark入门(1-2)Spark的特点、生态系统和技术架构

    一.Spark的特点 Spark特性 Spark通过在数据处理过程中成本更低的洗牌(Shuffle)方式,将MapReduce提升到一个更高的层次.利用内存数据存储和接近实时的处理能力,Spark比其 ...

  8. spring-boot 使用Aop通知打印控制器请求报文和返回报文

    一.简介 开发过程中我们往往需要写许多例如: @GetMapping("/id/get") public Result getById( String id) throws Exc ...

  9. mysql 千万级数据查询效率实践,分析 mysql查询优化实践--本文只做了一部分,仅供参考

    数据量, 1300万的表加上112万的表 注意: 本文只做了部分优化,并不全面,仅供参考, 欢迎指点.   请移步tim查看,因为写的时候在tim写的,粘贴过来截图有问题,就直接上链接了. https ...

  10. Lua中table的实现-《Lua设计与实现》

    本文来自<Lua设计与实现>的阅读笔记,推荐Lua学习者可以购买一本,深入浅出讲解lua的设计和实现原理,很赞,哈哈   Lua中对于表的设计,是基于数组和散列表,和其他语言不同,对于数组 ...