题目来源: IOI 1998
基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
 收藏
 关注
给出平面上的N个矩形(矩形的边平行于X轴和Y轴),求这些矩形组成的所有多边形的周长之和。


例如:N = 7。(矩形会有重叠的地方)。

合并后的多边形:


多边形的周长包括里面未覆盖部分方块的周长。
Input
第1行:1个数N。(2 <= N <= 50000)
第2 - N + 1行,每行4个数,中间用空格分隔,分别表示矩形左下和右上端点的坐标。(-1000000 <= X[i], Y[i] <= 1000000)
Output
输出多边形的周长。
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
Output示例
228

最近真的是被线段树扫描线搞得心力憔悴,刚刚才把poj上面求面积的弄懂,然后又遇到了求周长的。

思想和求面积是差不多的,变化就是多了一个line,就是当前的线段树分成了几段,这个在求面积的时候不会用到,但是求周长会用到。比如[1,1][2,2]就只有1段,[1,1][3,3]在线段树[1,3]的节点中就分成了两段。

第二点就是注意

tree[root].interval=tree[root*2+1].interval+tree[root*2+2].interval-tree[root*2+1].Rcover*tree[root*2+2].Lcover;

计算分成了多少块 是左子树的分块数+右子树的分块数,为了防止左子树的右边和右子树的左边连在一块,所以还要把这部分扣掉。

第三点就是注意排序,如果在x值相等的情况下,要将入边放在前面先处理,出边后处理。

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; struct li
{
int x,y1,y2;
int bLeft;
}line[500005]; int y[500005];
int n; struct no
{
int L;
int R;
int cover;
int Lcover;
int Rcover;
int interval;
int m;
}tree[500005]; void buildtree(int root,int L,int R)
{
tree[root].L=L;
tree[root].R=R;
tree[root].cover=0;
tree[root].Lcover=0;
tree[root].Rcover=0;
tree[root].interval=0;
tree[root].m=0; if(L!=R)
{
int mid = (L+R)/2;
buildtree(root*2+1,L,mid);
buildtree(root*2+2,mid+1,R);
}
} void insert(int root,int L,int R)
{
if(tree[root].L==L&&tree[root].R==R)
{
tree[root].cover++;
tree[root].m = y[R+1]-y[L];
tree[root].Lcover=1;
tree[root].Rcover=1;
tree[root].interval=1;
return;
}
else
{
int mid = (tree[root].L + tree[root].R)/2;
if(R<=mid)
{
insert(root*2+1,L,R);
}
else if(L>=mid+1)
{
insert(root*2+2,L,R);
}
else
{
insert(root*2+1,L,mid);
insert(root*2+2,mid+1,R);
}
}
if(tree[root].cover==0)
{
tree[root].m = tree[root*2+1].m +tree[root*2+2].m;
tree[root].Lcover=tree[root*2+1].Lcover;
tree[root].Rcover=tree[root*2+2].Rcover;
tree[root].interval=tree[root*2+1].interval+tree[root*2+2].interval-tree[root*2+1].Rcover*tree[root*2+2].Lcover;
}
} void dele(int root,int L,int R)
{
if(tree[root].L==L&&tree[root].R==R)
{
tree[root].cover--;
}
else
{
int mid = (tree[root].L + tree[root].R)/2;
if(R<=mid)
{
dele(root*2+1,L,R);
}
else if(L>=mid+1)
{
dele(root*2+2,L,R);
}
else
{
dele(root*2+1,L,mid);
dele(root*2+2,mid+1,R);
}
}
if(tree[root].cover<=0&&tree[root].L==tree[root].R)
{
tree[root].m=0;
tree[root].Lcover=0;
tree[root].Rcover=0;
tree[root].interval=0;
}
else if(tree[root].cover<=0)
{
tree[root].m = tree[root*2+1].m +tree[root*2+2].m;
tree[root].Lcover=tree[root*2+1].Lcover;
tree[root].Rcover=tree[root*2+2].Rcover;
tree[root].interval=tree[root*2+1].interval+tree[root*2+2].interval-tree[root*2+1].Rcover*tree[root*2+2].Lcover;
}
} bool cmp(struct li line1, struct li line2)
{
if (line1.x == line2.x)
return line1.bLeft > line2.bLeft;
return (line1.x < line2.x);
} template <class F,class T>
F bin_search(F s,F e,T val)
{
F L = s;
F R = e-1; while(L<=R)
{
F mid = L + (R-L)/2;
if(!(*mid<val || val < *mid))
{
return mid;
}
else if(val < *mid)
{
R = mid -1;
}
else
{
L= mid + 1;
}
}
} int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout); int i,x1,x2,y1,y2,yc,lc;
scanf("%d",&n); yc=0;
lc=0;
for(i=0;i<n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
y[yc++]=y1;
y[yc++]=y2; line[lc].x=x1;
line[lc].y1=y1;
line[lc].y2=y2;
line[lc].bLeft = 1;
lc++; line[lc].x=x2;
line[lc].y1=y1;
line[lc].y2=y2;
line[lc].bLeft = 0;
lc++;
}
sort(line,line+lc,cmp);
sort(y,y+yc);
yc=unique(y,y+yc)-y; buildtree(0,0,yc-1-1);
int preme=0;
int now_m=0;
int now_line=0;
for(i=0;i<=lc-1;i++)
{
int L=bin_search(y,y+yc,line[i].y1)-y;
int R=bin_search(y,y+yc,line[i].y2)-y; if(line[i].bLeft)
{
insert(0,L,R-1);
}
else
{
dele(0,L,R-1);
}
if(i>=1)
preme += 2*now_line*(line[i].x-line[i-1].x);
preme += abs(tree[0].m-now_m);
now_m=tree[0].m;
now_line=tree[0].interval;
}
printf("%d\n",preme);
//system("pause");
return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

51nod 1206:Picture 求覆盖周长的更多相关文章

  1. 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线

    51nod 1206 Picture 矩形周长求并 | 线段树 扫描线 #include <cstdio> #include <cmath> #include <cstr ...

  2. POJ-1177 Picture 矩形覆盖周长并

    题目链接:http://poj.org/problem?id=1177 比矩形面积并麻烦点,需要更新竖边的条数(平行于x轴扫描)..求横边的时候,保存上一个结果,加上当前长度与上一个结果差的绝对值就行 ...

  3. 51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)

    1206 Picture  题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 给出平面上的N个矩形(矩形的边平行于X轴 ...

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

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

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

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

  6. 【HDU 1828】 Picture (矩阵周长并,线段树,扫描法)

    [题目] Picture Problem Description A number of rectangular posters, photographs and other pictures of ...

  7. HDU 1392 凸包模板题,求凸包周长

    1.HDU 1392 Surround the Trees 2.题意:就是求凸包周长 3.总结:第一次做计算几何,没办法,还是看了大牛的博客 #include<iostream> #inc ...

  8. 25.按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有

    package zhongqiuzuoye; //自己写的方法 public class Rect { public double width; public double height; Rect( ...

  9. 按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有确定位

    package com.hanqi.test; public class Rect { ; ; public double getWidth() { return width; } public vo ...

随机推荐

  1. Windows 控制台命令笔记

    1. cmd中输出中文乱码问题: CHCP是一个计算机指令,能够显示或设置活动代码页编号. C:\windows\system32>CHCP 活动代码页: 936 原因是我们使用了GBK编码,下 ...

  2. js加密(十一)yhz566 md5

    1. http://www.yhz566.com/ 2. 登录加密 3. navigator = {}; var rng_psize = 256; var b64map = "ABCDEFG ...

  3. ubuntu14 安装Sublime Text 3

    Step1 从官网下载Sublime Text3 安装包 sublime_text_3_build_3176_x64.tar.bz2,如果有网络问题,请挂VPN或者从其他地方下载. 拷贝至/home/ ...

  4. nginx_1_初始nginx

    一.nginx简介: nginx是一个性能优秀的web服务器,同时还提供反向代理,负载均衡,邮件代理等功能.是俄罗斯人用C语言开发的开源软件. 二.安装nginx step1:安装依赖库 pcre(支 ...

  5. 【动画演示】:JS 作用域链不在话下

    作者:Lydia Hallie译者:前端小智来源:dev 点赞再看,养成习惯 本文 GitHub https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类, ...

  6. 在Linux上用Apache搭建Git服务器

    在Linux上用Apache搭建Git服务器   最近在学Linux,终于在Linux上用Apache搭建起了Git服务器,在此记录一下. 服务器:阿里云服务器 Linux版本:CentOS 6.5 ...

  7. 微信小程序中,如何点击链接跳转到外部网页

    跳转到内部链接 这个我们应该都知道,通过wx.navigateTo,wx.redirectTo,wx.swtichTab等小程序内部的方法,可以直接跳转到小程序内部已经注册的(就是在app.json中 ...

  8. jqGrid 复选框实现单选

    参考:https://blog.csdn.net/java0311/article/details/45575517

  9. Linux命令:ls命令

    ls命令:(list directory contents),列出目录内容 用法:ls [options] [file_or_dirs] ls命令常用选项 ls -l 显示文件的长格式信息 ls -d ...

  10. container-coding-codec

    1 数字容器格式 container format 1.1 一些音频专有的容器: 1.2 静态图像专用的容器: 1.3 视频容器,可以容纳多种类型的音频和视频以及其他媒体 1.4 视频容器格式概述 1 ...