HDU1828线段树(扫描线)
Picture |
| Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) |
| Total Submission(s): 12 Accepted Submission(s): 10 |
|
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 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 |
|
Sample Output
228 |
|
Source
IOI 1998
|
题意:
给出n个矩形的右下和左上角的坐标,问这n个矩形组成的图形的边长
代码:
参考博客
http://blog.csdn.net/u013480600/article/details/22548393
http://blog.csdn.net/u012860063/article/details/43163949
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=;
int cnt[maxn*],segnum[maxn*],sum[maxn*],pre[maxn*],suf[maxn*];
struct node{
int l,r,h,d;
node(){}
node(int a,int b,int c,int d):l(a),r(b),h(c),d(d){}
bool operator < (node&p){
if(h==p.h) return d>p.d;
return h<p.h;
}
}nodes[maxn];
void pushup(int l,int r,int rt){
if(cnt[rt]){//是下底边
segnum[rt]=;
pre[rt]=suf[rt]=;
sum[rt]=r-l+;
}
else if(l==r)//是叶子
segnum[rt]=sum[rt]=pre[rt]=suf[rt]=;
else{
segnum[rt]=segnum[rt<<]+segnum[rt<<|];
if(suf[rt<<]&&pre[rt<<|]) segnum[rt]-=;//有竖边重合
sum[rt]=sum[rt<<]+sum[rt<<|];
pre[rt]=pre[rt<<];//用两个儿子的两头更新父亲的两头
suf[rt]=suf[rt<<|];
}
}
void build(int l,int r,int rt){//本题中可以不用build递归,直接memset数组就行
cnt[rt]=;suf[rt]=;pre[rt]=;segnum[rt]=;sum[rt]=;
if(l==r) return;
int m=(l+r)>>;
build(l,m,rt<<);
build(m+,r,rt<<|);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&R>=r){
cnt[rt]+=c;
pushup(l,r,rt);
return;
}
int m=(l+r)>>;
if(L<=m) update(L,R,c,l,m,rt<<);
if(R>m) update(L,R,c,m+,r,rt<<|);
pushup(l,r,rt);
}
int main()
{
int t,x1,x2,y1,y2;
while(scanf("%d",&t)==){
int lbd=-,rbd=,m=;
while(t--){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
lbd=min(lbd,x1);
rbd=max(rbd,x2);
nodes[m++]=node(x1,x2,y1,);
nodes[m++]=node(x1,x2,y2,-);
}
build(lbd,rbd-,);
sort(nodes,nodes+m);
int ans=,last=;
for(int i=;i<m;i++){
if(nodes[i].l<=nodes[i].r-) //这个判断要有!
update(nodes[i].l,nodes[i].r-,nodes[i].d,lbd,rbd-,);
ans+=abs(sum[]-last);//算横向边
last=sum[];//更新前一个边
if(i!=m-)//算纵向边
ans+=segnum[]*(nodes[i+].h-nodes[i].h);
}
printf("%d\n",ans);
}
return ;
}
HDU1828线段树(扫描线)的更多相关文章
- hdu1828(线段树+扫描线)
又知道了线段树的一种用法,除了单点更新,区间更新,还有这种在一段线段上标号但不往下推. 真是神奇 hdu1828 #include <iostream> #include <stdi ...
- hdu1828 线段树扫描线求矩形面积的周长
题意: 给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路: 线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...
- hdu1828 Picture(线段树+扫描线+矩形周长)
看这篇博客前可以看一下扫描线求面积:线段树扫描线(一.Atlantis HDU - 1542(覆盖面积) 二.覆盖的面积 HDU - 1255(重叠两次的面积)) 解法一·:两次扫描线 如图我们可以 ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))
扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)
题目链接:http://codeforces.com/contest/522/problem/D 题目大意: 给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...
- 【POJ-2482】Stars in your window 线段树 + 扫描线
Stars in Your Window Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11706 Accepted: ...
- HDU 4419 Colourful Rectangle --离散化+线段树扫描线
题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
- BZOJ-3228 棋盘控制 线段树+扫描线+鬼畜毒瘤
3228: [Sdoi2008]棋盘控制 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 23 Solved: 9 [Submit][Status][D ...
随机推荐
- [Clr via C#读书笔记]Cp11事件
Cp11事件 类型之所以提供事件通知功能,是因为类型维护了一个已登记方法的列表,事件发生后,类型将通知列表登记的所有方法: 事件模型建立在委托的基础上.委托是调用回调方法的一种类型安全的方式. 设计事 ...
- geth账户密码
xiaocong geth账户密码 123 {d6abe909013d8da914ae2a08c9b58e7b76601b39} 账户密码 123456 0x4A7F15104F54dB3214D2F ...
- Thunder团队第五周 - Scrum会议7
Scrum会议7 小组名称:Thunder 项目名称:i阅app Scrum Master:苗威 工作照片: 参会成员: 王航:http://www.cnblogs.com/wangh013/ 李传康 ...
- 20145214实验二 Java面向对象程序设计
20145214实验二 Java面向对象程序设计 初步掌握单元测试和TDD 三种代码 伪代码 `百分制转五分制:` `如果成绩小于60,转成"不及格"` `如果成绩在60与70之间 ...
- c# 计算两个时间的时间差
//计算2个日期之间的天数差 DateTime dt1 = Convert.ToDateTime("2007-8-1"); DateTime dt2 = Convert.ToDat ...
- 如何进行Linux Kernel 开发
转自:http://www.cppblog.com/flyonok/archive/2011/04/15/144316.html 如何进行Linux Kernel 开发? (Take 3) 译者序:这 ...
- Sitemesh小记
一.前言 因参与公司框架改造,接触到了Sitemesh这个用于网页布局和修饰的框架,因之前没有接触过(汗颜),但是发现其小巧好用,便以此文记之~ 二.正文 Sitemesh有什么作用呢?我相信很多人在 ...
- Tomcat 7优化配置
Tomcat 的优化不像其它软件那样,简简单单的修改几个参数就可以了,它的优化主要有三方面,分为系统优化,Tomcat 本身的优化,Java 虚拟机(JVM)调优.系统优化就不在介绍了,接下来就详细的 ...
- 第69天:jQuery入口函数
一.jQuery入口函数 1.$(document).ready(function(){}); 2.$(function(){}); 二.事件处理程序 1.事件源 Js方式:document.get ...
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...

