题目来源: 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. e_book

    1. 奢侈的纸制书籍 2. 电子书 2.1 与印刷书籍的比较 2.2 电子书格式 2.2.1 Kindle 2.2.2 PDF 2.2.3 EPUB 2.2.4 更多电子书格式比较 2.3 公共领域的 ...

  2. mysql innodb cluster 无感知集群

    MySQL 8.0.12 innodb cluster 高可用集群部署运维管理手册 Innodb cluster 原理介绍 Innodb cluster  利用组复制的 pxos 协议,保障数据一致性 ...

  3. 三 Spring对于延迟加载问题的解决

    Spring提供了延迟加载问题的解决方法 什么是延迟加载? 延迟加载:lazy(懒加载) 执行到该行代码的时候不会发送语句,真正使用这个对象的属性的时候才会发送sql语句进行查询. 类级别延迟加载:指 ...

  4. cookie、sessionStorage和localStorage的区别

    cookie.sessionStorage.localStorage 都是用于本地存储的技术:其中 cookie 出现最早,但是存储容量较小,仅有4KB:sessionStorage.localSto ...

  5. C# Show()与ShowDialog()的区别-----转载

    A.WinForm中窗体显示  显示窗体可以有以下2种方法:  Form.ShowDialog方法 (窗体显示为模式窗体)  Form.Show方法 (窗体显示为无模式窗体) 两者具体区别如下:  1 ...

  6. 【剑指Offer面试编程题】题目1214:丑数--九度OJ

    把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 输入: 输入包括一个 ...

  7. coding 321

    三大原理(计算机原理.操作系统原理.编译原理)两个协议(TCP与HTTP协议)一种结构(数据结构)

  8. 「NOIP2014」飞扬的小鸟

    传送门 Luogu 解题思路 考虑 \(\text{DP}\) 设 \(dp[i][j]\) 表示飞到 \((i, j)\) 这个点的最小触屏次数. 转移其实比较显然,但问题是每次上升时都可以点很多次 ...

  9. 三 SVN权限设置&用户&组

    创建组,添加用户之后进行权限的设置:

  10. navcat工具常用快捷键

     navcat工具常用快捷键 ctrl + n: 打开新查询窗口 ctrl + shit + r: 只运行选中的语句 ctrl + /: 注释 (选中要注释的行,然后用快捷键注释) ctrl + sh ...