Picture

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

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

代码如下

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
#define fuck(x) cout<<"["<<x<<"]";
#define FIN freopen("input.txt","r",stdin);
#define FOUT freopen("output.txt","w+",stdout);
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int maxn = 1e5+;
struct node1{
int l,r;
int cover;
int len;
int lbt,rbt;
int segnum;
}st[maxn<<];
struct node2{
int x,y1,y2;
int flag;
}edge[maxn];
int Y[maxn];
void build(int root,int l,int r){
st[root].l=l;
st[root].r=r;
st[root].cover=st[root].len=;
st[root].lbt=st[root].rbt=;
st[root].segnum=;
if(r-l==) return;
int mid=(l+r+)/;
build(root<<,l,mid);
build(root<<|,mid,r);
} void update(int root){
if(st[root].cover>){
st[root].len=Y[st[root].r]-Y[st[root].l];
st[root].lbt=st[root].rbt=;
st[root].segnum=;
}else if(st[root].r-st[root].l==){
st[root].len=;
st[root].lbt=st[root].rbt=;
st[root].segnum=;
}else{
st[root].len=st[root<<].len+st[root<<|].len;
st[root].lbt=st[root<<].lbt;
st[root].rbt=st[root<<|].rbt;
st[root].segnum=st[root<<].segnum+st[root<<|].segnum-st[root<<].rbt*st[root<<|].lbt;
}
}
void update(int root,int val,int y1,int y2){
if(y1<=Y[st[root].l]&&Y[st[root].r]<=y2){
st[root].cover+=val;
}else{
int mid=(st[root].l+st[root].r+)/;
if(y1<Y[mid]) update(root<<,val,y1,y2);
if(y2>Y[mid]) update(root<<|,val,y1,y2);
}
update(root);
}
bool cmp(node2 a,node2 b){
if(a.x==b.x) return a.y1<b.y1;
return a.x<b.x;
}
int main(){
#ifndef ONLINE_JUDGE
FIN
#endif int n;
while(scanf("%d",&n) !=EOF){
if(n==) printf("0\n");
int x1,x2,y1,y2;
for(int i=;i<n;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
edge[i<<].x=x1;
edge[i<<].y1=y1;
edge[i<<].y2=y2;
edge[i<<].flag=;
Y[i<<]=y1;
edge[i<<|].x=x2;
edge[i<<|].y1=y1;
edge[i<<|].y2=y2;
edge[i<<|].flag=-;
Y[i<<|]=y2;
}
sort(Y,Y+*n);
sort(edge,edge+*n,cmp);
int cnt=;
for(int i=;i<*n;i++){
if(Y[i]!=Y[i+]) Y[cnt++]=Y[i];
}
Y[cnt++]=Y[*n-];
build(,,cnt-);
int ans=;
int lastlen=;
for(int i=;i<*n-;i++){
update(,edge[i].flag,edge[i].y1,edge[i].y2);
ans+=*st[].segnum*(edge[i+].x-edge[i].x);
ans+=abs(st[].len-lastlen);
lastlen=st[].len;
}
ans+=(edge[*n-].y2-edge[*n-].y1);
printf("%d\n",ans);
}
return ;
}

HDU1828 Picture 线段树+扫描线模板题的更多相关文章

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

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

  2. Zeratul的完美区间(线段树||RMQ模板题)

    原题大意:原题链接 给定元素无重复数组,查询给定区间内元素是否连续 解体思路:由于无重复元素,所以如果区间内元素连续,则该区间内的最大值和最小值之差应该等于区间长度(r-l) 解法一:线段树(模板题) ...

  3. POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)

    题目原网址:http://poj.org/problem?id=1177 题目中文翻译: 解题思路: 总体思路: 1.沿X轴离散化建树 2.按Y值从小到大排序平行与X轴的边,然后顺序处理 如果遇到矩形 ...

  4. poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)

    题目链接 题意:给出n个矩形,每个矩形给左下 和 右上的坐标,求围成的周长的长度. 分析: 首先感谢大神的博客,最近做题经常看大神的博客:http://www.cnblogs.com/kuangbin ...

  5. poj 1177 --- Picture(线段树+扫描线 求矩形并的周长)

    题目链接 Description A number of rectangular posters, photographs and other pictures of the same shape a ...

  6. HDU 1828 Picture (线段树:扫描线周长)

    依然是扫描线,只不过是求所有矩形覆盖之后形成的图形的周长. 容易发现,扫描线中的某一条横边对答案的贡献. 其实就是 加上/去掉这条边之前的答案 和 加上/去掉这条边之后的答案 之差的绝对值 然后横着竖 ...

  7. Luogu1856 [USACO5.5]矩形周长Picture (线段树扫描线)

    对于横轴,加上与上一次扫描的差值:对于竖轴,加上高度差与区间内不相交线段\(*2\)的积: 难点在pushdown,注意维护覆盖关系.再就注意负数 #include <iostream> ...

  8. HDU 1828 Picture (线段树+扫描线)(周长并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 给你n个矩形,让你求出总的周长. 类似面积并,面积并是扫描一次,周长并是扫描了两次,x轴一次,y ...

  9. 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))

    扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...

随机推荐

  1. A*与IDA*的奇妙之旅

    因为A*卡了一天QAQ 那么,A*是什么呢? A* A*是对于bfs的优化,启发式搜索. 例如下图: 不错,在这张图上,小人去找电脑,用bfs的话: 黄色就是bfs的搜索范围...不要问我为什么选黄色 ...

  2. nodejs环境变量配置

    步骤 创建文件夹:安装包 配置环境变量: export NODE_HOME=/root/安装包/node-v7.6.0-linux-x64 export PATH=$NODE_HOME/bin:$PA ...

  3. 20145202 《网络对抗技术》 PC平台逆向破解

    20145202 <网络对抗技术> PC平台逆向破解 准备工作 先将环境设置为:堆栈可执行.地址随机化关闭 参考http://git.oschina.net/wildlinux/NetSe ...

  4. C#的特性Attribute

    一.什么是特性 特性是用于在运行时传递程序中各种元素(比如类.方法.结构.枚举.组件等)的行为信息的声明性标签,这个标签可以有多个.您可以通过使用特性向程序添加声明性信息.一个声明性标签是通过放置在它 ...

  5. 长沙Uber优步司机奖励政策(3月28日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  6. idea 常用设置

    1.修改为Eclipse快捷键 File -> Settings -> Keymap => Keymaps改为 Eclipse copy   2.显示行号: File -> S ...

  7. HI2115软件开发板V150版本AT+NSOST指令

    1. 在HI2115里面,由于内存空间比较大,所以支持UDP发送指令AT+NSOST的分包 ret = sendto(socket, seq_num, data_string, length, msg ...

  8. C++学习005-循环

    C++在循环方面,感觉个C没有身边么区别 while循环 for循环 do while循环 其实 使用Goto也可以写个循环 编写环境vs2015 1. while循环 int main() { in ...

  9. Django数据模型--字段详解

    一.字段 1.CharField: 字段数据类型为字符串 class Test(models.Model): test = models.CharField(max_length=) 2.Intege ...

  10. liunx运维必备150个基础命令

    经过上次的面试,总结了一下的linux系统常用命令: 命令 功能说明 线上查询及帮助命令(2个) man 查看命令帮助,命令的词典,更复杂的还有info,但不常用. help 查看Linux内置命令的 ...