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. 201421123042 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰 ...

  2. [JCIP笔记] (二)当我们谈线程安全时,我们在谈论什么

    总听组里几个大神说起线程安全问题.本来对"线程安全"这个定义拿捏得就不是很准,更令人困惑的是,大神们用这个词指代的对象不仅抽象而且千变万化.比如,我们的架构师昨天说: " ...

  3. PAT1048. Find Coins(01背包问题动态规划解法)

    问题描述: Eva loves to collect coins from all over the universe, including some other planets like Mars. ...

  4. android 运行时异常捕获

    1,将运行时异常捕获并存到手机SD卡上 可以直接使用logcat 命令Runtime.getRuntime().exec("logcat -f "+ file.getAbsolut ...

  5. SQL Server 实现递归查询

    基础数据/表结构                 Sql 语句 ;With cte(id,pid,TName)As ( Select id,pid,TName Union All Select B.i ...

  6. MSIL实用指南-生成if...else...语句

    if...else...语句是非常重要的选择语句,它的生成一般需要ILGenerator的DefineLabel方法和MarkLabel方法,以及Brtrue_S和Br_S指令. 一.DefineLa ...

  7. Groovy入门(2-2)Groovy的eclipse插件安装

    1.安装eclipse插件 启动eclipse,点击help -> Install New Software... 在弹出的窗口中点击:Add... Groovy插件的地址:http://dis ...

  8. spring cloud eureka显示ip

    eureka.instance.preferIpAddress=trueeureka.instance.instance-id=${spring.cloud.client.ipAddress}:${s ...

  9. awk、变量、运算符、if多分支

    awk.变量.运算符.if多分支 awk: 语法 awk [options] 'commands' files option -F 定义字段分隔符,默认的分隔符是连续的空格或制表符 使用option中 ...

  10. Vue项目结构说明

    简单介绍目录结构 http://blog.csdn.net/u013778905/article/details/53864289 (别人家的链接,留给我自己看的)