题意:给n个矩形,求矩形周长并

解法:跟求矩形面积并差不多,不过线段树节点记录的为:

len: 此区间线段长度

cover: 此区间是否被整个覆盖

lmark,rmark: 此区间左右端点是否被覆盖

num: 此区间分离开的线段的条数

重点在转移的地方,不难理解。

代码:

#include <iostream>
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 10007 struct node
{
int cov,len,num,lmark,rmark;
}tree[*N]; struct Line
{
int y1,y2,x;
int cov;
}line[*N];
int yy[*N]; int cmp(Line ka,Line kb)
{
return ka.x < kb.x;
} int bsearch(int l,int r,int x)
{
while(l <= r)
{
int mid = (l+r)/;
if(x == yy[mid])
return mid;
if(x > yy[mid])
l = mid+;
else
r = mid-;
}
return l;
} void build(int l,int r,int rt)
{
tree[rt].cov = tree[rt].len = tree[rt].num = tree[rt].lmark = tree[rt].rmark = ;
if(l == r-) return;
int mid = (l+r)/;
build(l,mid,*rt);
build(mid,r,*rt+);
} void pushup(int l,int r,int rt)
{
if(tree[rt].cov)
{
tree[rt].len = yy[r]-yy[l];
tree[rt].lmark = tree[rt].rmark = ;
tree[rt].num = ;
}
else if(l+ == r)
tree[rt].len = tree[rt].num = tree[rt].lmark = tree[rt].rmark = ;
else
{
tree[rt].len = tree[*rt].len + tree[*rt+].len;
tree[rt].lmark = tree[*rt].lmark;
tree[rt].rmark = tree[*rt+].rmark;
tree[rt].num = tree[*rt].num+tree[*rt+].num-tree[*rt].rmark*tree[*rt+].lmark;
//如果左右区间连续,那么可以合并,减少一个区间
}
} void update(int l,int r,int aa,int bb,int cover,int rt)
{
if(aa <= l && bb >= r)
{
tree[rt].cov += cover;
pushup(l,r,rt);
return;
}
if(l+ == r) return;
int mid = (l+r)/;
if(aa <= mid)
update(l,mid,aa,bb,cover,*rt);
if(bb > mid)
update(mid,r,aa,bb,cover,*rt+);
pushup(l,r,rt);
} int main()
{
int n,m,cs = ,i,j;
int x1,y1,x2,y2;
while(scanf("%d",&n)!=EOF)
{
m = ;
for(i=;i<n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
line[m].x = x1,line[m].y1 = y1,line[m].y2 = y2,line[m].cov = ,yy[m++] = y1;
line[m].x = x2,line[m].y1 = y1,line[m].y2 = y2,line[m].cov = -,yy[m++] = y2;
}
m--;
sort(yy+,yy+m+);
int cnt = ;
for(i=;i<=m;i++)
{
if(yy[i] != yy[i-])
yy[cnt++] = yy[i];
}
cnt--;
build(,cnt,);
sort(line+,line+m+,cmp);
int ans = ;
int last = ;
for(i=;i<=m;i++)
{
int L = bsearch(,cnt,line[i].y1);
int R = bsearch(,cnt,line[i].y2);
update(,cnt,L,R,line[i].cov,);
ans += abs(last - tree[].len);
if(i == m) break;
ans += tree[].num**(line[i+].x-line[i].x);
last = tree[].len;
}
printf("%d\n",ans);
}
return ;
}

HDU 1828 / POJ 1177 Picture --线段树求矩形周长并的更多相关文章

  1. POJ 1151 Atlantis 线段树求矩形面积并 方法详解

    第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...

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

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

  3. HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)

    做这道题之前,建议先做POJ 1151  Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...

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

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

  5. HDU 1828 POJ 1177 Picture

    矩形周长并 POJ上C++,G++都能过,HDU上C++过了,G++WA ,不知道为什么 #include<cstdio> #include<cstring> #include ...

  6. 【hdu1828/poj1177】线段树求矩形周长并

    题意如图 题解:这题非常类似与矩形面积并,也是维护一个被覆盖了一次以上的线段总长. 但是周长要算新出现的,所以每次都要和上一次做差求绝对值. x轴做一遍,y轴做一遍. 但是有个问题:矩形边界重合的时候 ...

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

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

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

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

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

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

随机推荐

  1. CodeBlocks VS2015编译环境设置

    1. 菜单 Settings --> Compiler... 2. 设置vs 的安装路径

  2. linux 常用技巧

    1--查看版本 查看内核版本 # cat /proc/version 查看linux版本 # lsb_release -a或者 cat /etc/issue 2--linux服务器测速 speedte ...

  3. 不变(Invariant), 协变(Covarinat), 逆变(Contravariant) : 一个程序猿进化的故事

    阿袁工作的第1天: 不变(Invariant), 协变(Covarinat), 逆变(Contravariant)的初次约 阿袁,早!开始工作吧. 阿袁在笔记上写下今天工作清单: 实现一个scala类 ...

  4. Oracle不足与MySQL优势

    Oracle库主要不足:1.单点故障:2.付费License;3.不支持水平扩展. MySQL及水平拆库的优势:1.单点故障影响率1/N:2.免费:3.可低成本水平扩展,近乎无限的水平扩展能力.

  5. vmware linux top si高以及网卡队列、软负载相关优化

    今日,测试公司自行开发的一rpc中间件,期间发现top si的比例很高,且几乎只有一个cpu是繁忙的,其他均基本为0. 经查,si主要是系统软中断,最后确定是网卡导致的系统中断.于是,往上搜了下资料, ...

  6. 微信jssdk,实现多图上传的一点心得

    一.首先在common.js里封装一个函数,在需要调用jsSDK的页面引用此方法即可实现微信的信息配置function signatureJSSDK() { var url = window.loca ...

  7. Jsoup解析Html中文文档

    jsoup 简介Java 程序在解析 HTML 文档时,相信大家都接触过 htmlparser 这个开源项目,我曾经在 IBM DW 上发表过两篇关于 htmlparser 的文章,分别是:从 HTM ...

  8. Iterator 迭代器(一)

         迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址.迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为 ...

  9. 浅谈Base64编码算法

    一.什么是编码解码 编码:利用特定的算法,对原始内容进行处理,生成运算后的内容,形成另一种数据的表现形式,可以根据算法,再还原回来,这种操作称之为编码. 解码:利用编码使用的算法的逆运算,对经过编码的 ...

  10. 实战1--应用EL表达式访问JavaBean的属性

    (1)编写index.jsp页面,用来收集用户的注册信息 <%@ page language="java" pageEncoding="GBK"%> ...