题目链接

题意:给出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 (线段树 扫描线 离散化 矩形周长并)的更多相关文章

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

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

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

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

  3. HDU 1828“Picture”(线段树+扫描线求矩形周长并)

    传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...

  4. POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]

    题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...

  5. HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...

  6. hdu 4419 线段树 扫描线 离散化 矩形面积

    //离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...

  7. Picture POJ - 1177 (线段树-扫描线)

    A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wa ...

  8. POJ 1177 Picture(线段树周长并)

      描述 A number of rectangular posters, photographs and other pictures of the same shape are pasted on ...

  9. hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

随机推荐

  1. JPA学习---第六节:大数据字段映射与字段延迟加载

    1.大数据字段所需的注解 @Lob ,例如: @Lobprivate String info; 在mysql中映射产生的字段的类型是longtext:在oracle中是  CLOB @Lobpriva ...

  2. Error: Most middleware (like bodyParser) ...

    运行NodeJS时出现如下错误: Error: Most middleware (like bodyParser) is no longer bundled with Express and must ...

  3. Regex.Match 方法

    Regex.Match 方法 在输入字符串中搜索正则表达式的匹配项,并将精确结果作为单个 Match 对象返回. 重载列表      (1) 在指定的输入字符串中搜索 Regex 构造函数中指定的正则 ...

  4. [转载]关于安装Android Studio的一些问题的解决方法

    最近在研究Android编程,在Android Studio安装和使用时遇到了麻烦,从园子里找到了<关于安装Android Studio的一些问题的解决方法>的,很多问题找到了解决办法. ...

  5. Linux/Ubuntu常用快捷键

    问题描述:         Linux/Ubuntu常用快捷键   问题解决: +++++++++++++++++++ 全局系统 +++++++++++++++++++++ Alt + F1:相当于w ...

  6. C# \uxxx Unicode编码解码

    /// <summary> /// Unicode编码 /// </summary> /// <param name="str"></pa ...

  7. 关于make: *** No rule to make target `clean'. Stop.的解决

    在重新编译makefile工程文件时需要用到 #make clean 命令, 但是最近工程使用make clean的时候总是提示: make: *** No rule to make target ` ...

  8. HDU 3397 Sequence operation (区间合并,操作比较多)

    费了我一天半的时间,到处debug,后来才发现,主要是建树的时候只在叶子节点对lazy1和lazy2进行初始化了,父节点都没初始化...晕. 具体见代码吧. #include <iostream ...

  9. POJ 1504 Adding Reversed Numbers (水题,高精度整数加法)

    题意:给两个整数,求这两个数的反向数的和的反向数,和的末尾若为0,反向后则舍去即可.即若1200,反向数为21.题目给出的数据的末尾不会出现0,但是他们的和的末尾可能会出现0. #include &l ...

  10. HDU 3038 How Many Answers Are Wrong(带权并查集)

    太坑人了啊,读入数据a,b,s的时候,我刚开始s用的%lld,给我WA. 实在找不到错误啊,后来不知怎么地突然有个想法,改成%I64d,竟然AC了 思路:我建立一个sum数组,设i的父亲为fa,sum ...