poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)
题意:给出n个矩形,每个矩形给左下 和 右上的坐标,求围成的周长的长度。
分析:
首先感谢大神的博客,最近做题经常看大神的博客:http://www.cnblogs.com/kuangbin/
沿x轴离散化。和之前的矩阵面积并有点像。
但是一定要去重,否则会错
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define LL __int64
#define lson l, mid, 2*rt
#define rson mid+1, r, 2*rt+1
const int maxn = +;
using namespace std;
int n, x[maxn];
struct node
{
int l, r, cnt;
int lf, rf;
int num, c; //num是分支的个数,即当前的x段有多少段,可以想象一段是对应两个竖边的。
bool lc, rc; //表示左端是否覆盖,和右端是否覆盖,用来判断x段是否练成一块了
}tr[maxn*];
struct Line
{
int y, x1, x2, f;
}line[maxn];
bool cmp(Line a, Line b)
{
return a.y < b.y;
}
void build(int l, int r, int rt)
{
tr[rt].l = l; tr[rt].r = r;
tr[rt].lf = x[l]; tr[rt].rf = x[r];
tr[rt].cnt = ; tr[rt].num = ;
tr[rt].c = ;
tr[rt].lc = tr[rt].rc = false;
if(tr[rt].l+ == tr[rt].r) return;
int mid = (l+r)/;
build(l, mid, *rt);
build(mid, r, *rt+);
}
void calen(int rt)
{
if(tr[rt].c>)
{
tr[rt].cnt = tr[rt].rf-tr[rt].lf;
tr[rt].num = ;
tr[rt].lc = tr[rt].rc = true; //这整个一块都覆盖了,左右端点自然也覆盖
return;
}
if(tr[rt].l+ == tr[rt].r)
{
tr[rt].cnt = tr[rt].num = ;
tr[rt].lc = tr[rt].rc = false;
}
else
{
tr[rt].cnt = tr[*rt].cnt+tr[*rt+].cnt;
tr[rt].lc = tr[*rt].lc; tr[rt].rc = tr[*rt+].rc;//自己这块没有覆盖,看一下子节点是否有覆盖
tr[rt].num = tr[*rt].num+tr[*rt+].num;
if(tr[*rt].rc && tr[*rt+].lc) tr[rt].num --; //如果当前这个节点的子节点左的右
//覆盖和右的左覆盖说明中间已经练成一片了,所以分支-1
}
}
void update(int rt, Line e)
{
if(tr[rt].lf==e.x1 && tr[rt].rf==e.x2)
{
tr[rt].c += e.f;
calen(rt);
return;
}
if(e.x2<=tr[*rt].rf) update(*rt, e);
else if(e.x1>=tr[*rt+].lf) update(*rt+, e);
else
{
Line tmp;
tmp = e;
tmp.x2 = tr[*rt].rf;
update(*rt, tmp);
tmp = e;
tmp.x1 = tr[*rt+].lf;
update(*rt+, tmp);
}
calen(rt);
}
int main()
{
int i, t, ans, pre;
int x1, x2, y1, y2;
while(~scanf("%d", &n))
{
t = ; ans = ; pre = ;
for(i = ; i < n; i++)
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
line[t].x1 = x1; line[t].x2 = x2;
line[t].y = y1; line[t].f = ;
x[t++] = x1;
line[t].x1 = x1; line[t].x2 = x2;
line[t].y = y2; line[t].f = -;
x[t++] = x2;
}
sort(x, x+t);
sort(line, line+t, cmp);
int y = unique(x, x+t)-x; //去重
build(, y-, ); for(i = ; i < t-; i++)
{
update(, line[i]);
ans += tr[].num**(line[i+].y-line[i].y); //竖线的长度
ans += abs(tr[].cnt-pre); //加上 新增的横线 或者 是减少的横线
pre = tr[].cnt;
}
update(, line[i]);
ans += abs(tr[].cnt-pre);
printf("%d\n", ans);
}
return ;
}
poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)的更多相关文章
- POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)
题目原网址:http://poj.org/problem?id=1177 题目中文翻译: 解题思路: 总体思路: 1.沿X轴离散化建树 2.按Y值从小到大排序平行与X轴的边,然后顺序处理 如果遇到矩形 ...
- poj 1177 --- Picture(线段树+扫描线 求矩形并的周长)
题目链接 Description A number of rectangular posters, photographs and other pictures of the same shape a ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...
- Picture POJ - 1177 (线段树-扫描线)
A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wa ...
- POJ 1177 Picture(线段树周长并)
描述 A number of rectangular posters, photographs and other pictures of the same shape are pasted on ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
随机推荐
- IIS7.5 HTTP 错误 500.19 - Internal Server Error 问题的解决方案
昨天在 windows 7 下用 IIS 7.5 运行一个以前用 .NET Framework 3.5 写的项目,发现总是出现 500.19 错误,如下: 百度了好久,没找到解决问题确切的答案,我也知 ...
- 不同的source control下配置DiffMerge
TFS: 1. 打开Option -> Source Control -> Visual Studio TFS -> Configure User Tools; 2. 添加 .*, ...
- 备份apt目录节省下载时间
备份与清理 * 备份快速设置已下载的部分软件包,以便重装系统再次使用,免去重新下载的时间 tar cizvf backup.tar.gz /var/cache/apt/archives ...
- linux 下载并安装Memcache服务器端
1.下载并安装Memcache服务器端 服务器端主要是安装memcache服务器端. 下载:http://www.danga.com/memcached/dist/memcached-1.2.2.ta ...
- SQL SERVER时间函数
本篇文章还是学习<程序员的SQL金典>内容的记录,此次将讲解的是SQL SERVER的时间函数. 本文只讲SQL SERVER支持的时间函数(其它数据库这里就不罗列了,想看更多的可以关注& ...
- 请求--拦截器--action经过
引用我这里想知道的是同名的多个参数,会被自动的放置在List或者数组中,我想知道是怎么实现的,因为取一个参数和取多个同名的参数是不同的方法: 一个是request.getParameter 一个是re ...
- Java学习第四篇:数组,排序,查找
一.数组 1.一维数组 (1).数组的定义 数据类型 数组名[]=new 数据类型[大小] public class Demo1 { public static void main(String[] ...
- 使用异步 I/O 大大提高应用程序的性能
使用异步 I/O 大大提高应用程序的性能 学习何时以及如何使用 POSIX AIO API Linux® 中最常用的输入/输出(I/O)模型是同步 I/O.在这个模型中,当请求发出之后,应用程序就会阻 ...
- prim求MST
PRIM==>>MST模板 #include <iostream> using namespace std; #define typec int #define V 3 con ...
- POJ2406 Power Strings KMP算法
给你一个串s,如果能找到一个子串a,连接n次变成它,就把这个串称为power string,即a^n=s,求最大的n. 用KMP来想,如果存在的话,那么我每次f[i]的时候退的步数应该是一样多的 譬 ...