2149 矩形周长

2149 矩形周长

USACO

时间限制: 1 s

空间限制: 16000 KB

题目等级 : 大师 Master

题解

查看运行结果

题目描述 Description

N(N<5000) 张矩形的海报,照片和其他同样形状的图片贴在墙上。它们的边都是垂直的或水平的。每个矩形可以部分或者全部覆盖其他矩形。所有的矩形组成的集合的轮廓称为周长。写一个程序计算周长。

图 1 是一个有 7 个矩形的例子:

图 1.一个 7 个矩形的集合

对应的轮廓为图 2 所示的所有线段的集合:

图 2. 矩形集合的轮廓

所有矩形的顶点坐标均为整数。所有的坐标都在 [-10000,10000] 的范围内,并且任何一个矩形面积都为整数。结果的值可能需要 32 位有符号整数表示。

输入描述 Input Description

第1行: N,张贴在墙上的矩形的数目。

第 2..N+1行 接下来的N行中,每行都有两个点的坐标,分别是矩形的左下角坐标和右上角坐标。每一个坐标由 X 坐标和 Y 坐标组成。

输出描述 Output Description

只有一行,为一个非负整数,表示输入数据中所有矩形集合的轮廓长度。

样例输入 Sample 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

样例输出 Sample Output

228

数据范围及提示 Data Size & Hint

范围如题所述

分类标签 Tags 点此展开

USACO

/*不写点什么总是不好的,但我又懒,转载zjk‘s文字解析:
  这道题暴力竟然可以过,可能是数据比较弱,就是把矩形拆成两条横边和纵边,然后暴力给一条边上的每一个点加权值,
  如果用线段树的话,可能是用线段树维护区间和吧,貌似很麻烦的样子。
  但是这个题有很多细节需要注意(扫描线的题大都有很多细节)。
  为了使包含关系的边只出现一次,再加入左边时,要在区间权值为空(即以前未出现过包含这条边的边)时才更新答案,
  另外在排序时如果位置相同,把左边排在前面,这是为了解决两个矩形前后重合的情况。
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e4+10;
struct node{
    int l,r,h,id;
    bool operator < (const node &a)const{
        return h==a.h?id<a.id:h<a.h;
    }
}A[N*2],B[N*2];
int n,m,cnt,f[N*4];
int main(){
    scanf("%d",&n);
    for(int i=1,x1,y1,x2,y2;i<=n;i++){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        x1+=10000,y1+=10000,x2+=10000,y2+=10000;
        ++cnt;
        A[cnt].l=x1;A[cnt].r=x2;A[cnt].h=y1;A[cnt].id=0;
        B[cnt].l=y1;B[cnt].r=y2;B[cnt].h=x1;B[cnt].id=0;
        ++cnt;
        A[cnt].l=x1;A[cnt].r=x2;A[cnt].h=y2;A[cnt].id=1;
        B[cnt].l=y1;B[cnt].r=y2;B[cnt].h=x2;B[cnt].id=1;
    }
    sort(A+1,A+cnt+1);sort(B+1,B+cnt+1);
    int ans=0;
    for(int i=1;i<=cnt;i++){
        for(int j=A[i].l;j<A[i].r;j++){
            if(!A[i].id){if(!f[j]) ans++;f[j]++;}
            else {f[j]--;if(!f[j]) ans++;}
        }
    }
    memset(f,0,sizeof f);
    for(int i=1;i<=cnt;i++){
        for(int j=B[i].l;j<B[i].r;j++){
            if(!B[i].id){if(!f[j]) ans++;f[j]++;}
            else {f[j]--;if(!f[j]) ans++;}
        }
    }
    printf("%d",ans);
    return 0;
}
时间: 2024-08-03 23:57:27

2149 矩形周长的相关文章

codevs 2149 矩形周长

这个还是扫描线.注意:维护有多少个连续的区间的时候维护l,r分别代表左端点开始是否有线段,右端点开始(向左)是否有线段. #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define maxn 100005using namespace std;struct tree{ int left,right; int sum,cnt

HDU 1828 Picture(矩形周长并)

HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4个方向都加完就是答案 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 5005; int n; struct Rec { int

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(double width,double height) //带有两个参数的构造方法,用于将width和height属性初化; { this.width=width; this.height=height; } Rect() //不带参数的构造方法,将矩形初始化为宽和高都为10. { width=10; height=

hdu1828 (Picture) &amp;poj 1177( Picture)&amp;sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)

题目地址:hdu1828 (Picture)  & poj 1177( Picture) & sdibt 2390(5.5.1 Picture 矩形周长) 题目大意: 给你N个矩形,求出N个矩形构成的周长. 解题思路: 线段数+扫描线. 推荐博客: POJ1177 Picture(线段树求轮廓周长) POJ 1177 Picture (线段树+离散化+扫描线) 详解 注意事项: 该题在求面积的基础上有了升级,多写了一个被调需要求出投影与Y轴有几段,不然样例会少算20,就是给出图形中间的小矩

扫描线矩形周长的并 POJ1177

1 //扫描线矩形周长的并 POJ1177 2 // 我是按x轴 3 4 #include <iostream> 5 #include <cstdio> 6 #include <cstdlib> 7 #include <algorithm> 8 #include <vector> 9 #include <cmath> 10 #include <cstring> 11 // #include <memory.h>

HDU 1828 扫描线(矩形周长并)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3310    Accepted Submission(s): 1723 Problem Description A number of rectangular posters, photographs and other pictures of the same shape

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

题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 num: 此区间分离开的线段的条数 重点在转移的地方,不难理解. 代码: #include <iostream> #include <cmath> #include <iostream> #include <cstdio> #include <cstrin

poj 1177 Picture(扫描线+矩形周长并)

http://poj.org/problem?id=1177 求矩形的周长并,明确的一点是对于覆盖的边的长度忽略不计. 与求面积并类似,首先离散化,对矩形的每条横边从下往上扫描.扫描过程中要完成三个任务,更新相应的区间信息,求横边长,求竖边长. 节点信息: l,r:左右区间编号 cnt:表示该区间是否被完全覆盖.cnt > 0 表示完全覆盖,否则不完全覆盖. lp,rp:表示该区间的两个端点是否被覆盖,为1被覆盖,为0没被覆盖. num:该区间被覆盖的线段数目.例如区间[1,10],当更新[2,

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

package com.hanqi.test; public class Rect { public double width; public double height; //创建有参构造方法 Rect(double width,double height) { this.width=width; this.height=height; } //创建无参构造方法 Rect() { } //构建成员方法,获取周长和面积 public double getZhouchang() { return