一些矩形的海报、照片或其他同样形状的图片被张贴在墙上。它们的边都是垂直或水平的。每个矩形可以部分或全部覆盖其它矩形。所有矩形组成的集合的边界称为周界。
写一个程序计算周界。
输入格式:
文件PICTURE.IN 的第一行张贴在墙壁上的矩形图片的数目。在随后的行中,每行有两个点的坐标,分别为某一个矩形的左下角和右上角的坐标。每一个坐标由X坐标与Y坐标组成。
输出格式:
文件PICTURE.OUT包含一行,为一个非负整数,表示输入数据中所有矩形集的周界。
样例输入:
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
样例输出:
228
数据范围:
0 < 矩形数 < 50000所有坐标在 [-10000,10000]内,结果的值可能需要32位有带符号表示。
时间限制:
1s
空间限制:
256m
题解在代码内
#include<bits/stdc++.h>
using
namespace
std;
const
int
maxn=5005;
const
int
size=20005;
const
int
zero=10000;
struct
node{
int
x,y,f;
bool
ok;}a[2][maxn*2];
int
level[size];
int
n,i,x1,x2,y1,y2,ans;
bool
cmp(node
c,node d){
return
c.f<d.f||c.f==d.f&&c.ok;}
void
find(
int
o)
{
//我们把矩形的坐标先离散。以处理横条为例。------->>>>>>
//①我们在离散每一条横条时记录它们的纵坐标,
同时记录这一横条是矩形的下边(始边)还是上边(终边)。 然后把它们按纵坐标从小到大排好。
//②从小到大循环每一个横条。如果是始边,那么把它代表的区间每个格子都加1,否则减1(当然这样效率有点低,最好要用线段树优化)。如果某个格子是始边且原先是0,那么我们就把ans++。
如果某个格子是终边且原先是1,那么我们也把ans++。(具体原理纸上推推就行了)
sort(a[o]+1,a[o]+n+1,cmp);
memset
(level,0,
sizeof
(level));
int
j;
for
(
int
i=1;i<=n;i++)
{
if
(a[o][i].ok)
{
for
(j=a[o][i].x;j<a[o][i].y;j++)
{
level[j]++;
if
(level[j]==1)
ans++;
}
}
else
{
for
(j=a[o][i].x;j<a[o][i].y;j++)
{
level[j]--;
if
(level[j]==0)
ans++;
}
}
}
}
int
main()
{
scanf
(
"%d"
,&n);
for
(i=1;i<=n;i++)
{
scanf
(
"%d%d%d%d"
,&x1,&y1,&x2,&y2);
x1+=zero;x2+=zero;y1+=zero;y2+=zero;
//将坐标都加至零及以上
a[0][i*2-1].x=x1;a[0][i*2-1].y=x2;a[0][i*2-1].ok=
true
;a[0][i*2-1].f=y1;
//OK=1
表示是终边,终边:右边或上面的边
a[0][i*2].x=x1;a[0][i*2].y=x2;a[0][i*2].ok=
false
;a[0][i*2].f=y2;
//a[0]表示横,1表示纵
a[1][i*2-1].x=y1;a[1][i*2-1].y=y2;a[1][i*2-1].ok=
true
;a[1][i*2-1].f=x1;
a[1][i*2].x=y1;a[1][i*2].y=y2;a[1][i*2].ok=
false
;a[1][i*2].f=x2;
}
n=n*2;
find(0);
find(1);
printf
(
"%d\n"
,ans);
return
0;
}