Picture

来源:互联网 发布:淘宝买csgo怎么下载 编辑:程序博客网 时间:2024/05/26 05:52
1206 Picture
题目来源: 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 2515 -4 24 140 -6 16 42 15 10 2230 10 36 2034 0 40 16
Output示例
228
再做这题之前,我们先来简单的讲一讲扫描线到底是个什么东西。首先,在学习扫描线之前,你先要学会线段树,这里就不展开了。在假设看到这篇文章的人都会线段树的情况下,我开始接下来的讲解:所谓扫描线,就是指在图上有一根假想的线(虽然再具体实现中是没有的,但我们为了更好的理解),这种算法主要应用于求解由规则图形因为重叠而产生一块不规则图形的面积和周长问题,而上题就是讲的是周长,因为该算法的维护方式是线段树,而且是存储线段的线段树(注意,不是点,是线段),所以需要你对线段树的熟练理解和掌握。好了,回到原问题上,因为有了这根线,所以我们就可以从下而上一层一层扫描,将每次扫描到的线段用线段树维护,那如果该图形是个镂空的图形了(如样例),于是我们就引进了一个伟大的标记(cover,在接下来的代码中用v表示)将矩形上界和下界标上一对相反数,并存入一个变量,该变量中数字的大小即为目前扫描中的矩阵个数,如果为零,说明 没有矩阵,就不用加了。而求面积和周长是有一定不同的,求面积就是将不规则图形在扫描的过程中分成一块块规则图形进行累加,而周长则显得更加麻烦,(由于博主绘画水平不高,没有配上相应动画,但我相信你看接下来的代码和注释你会恍然大悟)
对于求周长:我的想法:将原不规则图形从下到上,从左到右各扫一遍,进行累加(缺点:代码量大,容易犯逻辑错误)                                                                                    大神想法:只从下往上扫一遍,用两个数组维护两边有无竖线,一遍求和(优点:代码量短,容易理解)                                                                     所以接下来的代码就是我汲取了大神的想法打成的(Ps:再做此题之前,你还需要学会离散化来进行空间的优化)
#include#include#include#include#include#define N 100005using namespace std;struct node{int l,r,h,v;node(){}node(int a,int b,int c,int d):l(a),r(b),h(c),v(d){}friend bool operator <(node p,node q){if (p.h==q.h) return p.v>q.v;return p.h>1;if (L<=m) update(L,R,c,p<<1,l,m);if (R>m) update(L,R,c,p<<1|1,m+1,r);pus(p,l,r);} int main(){int x1,y1,x2,y2,i,j,k,m,n,l,r,ans,ret;while (scanf("%d",&n)!=EOF){k=1,m=ans=ret=0;for (i=0;i