矩形周长(codevs 2149)

题目描述  Description

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

所有矩形的顶点坐标均为整数。所有的坐标都在 [-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
/*
  这道题暴力竟然可以过,可能是数据比较弱,就是把矩形拆成两条横边和纵边,然后暴力给一条边上的每一个点加权值,
  如果用线段树的话,可能是用线段树维护区间和吧,貌似很麻烦的样子。
  但是这个题有很多细节需要注意(扫描线的题大都有很多细节)。
  为了使包含关系的边只出现一次,再加入左边时,要在区间权值为空(即以前未出现过包含这条边的边)时才更新答案,
  另外在排序时如果位置相同,把左边排在前面,这是为了解决两个矩形前后重合的情况。 
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 5010
using namespace std;
int n,cnt,f[N*4];
struct node{
    int l,r,h,t;
};node A[N*2],B[N*2];
bool cmp(const node&s1,const node&s2){
    if(s1.h==s2.h) return s1.t<s2.t;
    return s1.h<s2.h;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        x1+=10000;y1+=10000;x2+=10000;y2+=10000;
        A[++cnt].l=x1;A[cnt].r=x2;A[cnt].h=y1;A[cnt].t=1;
        B[cnt].l=y1;B[cnt].r=y2;B[cnt].h=x1;B[cnt].t=1;
        A[++cnt].l=x1;A[cnt].r=x2;A[cnt].h=y2;A[cnt].t=2;
        B[cnt].l=y1;B[cnt].r=y2;B[cnt].h=x2;B[cnt].t=2;
    }
    sort(A+1,A+cnt+1,cmp);sort(B+1,B+cnt+1,cmp);
    int ans=0;
    for(int i=1;i<=cnt;i++){
        int l=A[i].l,r=A[i].r;
        for(int j=l;j<r;j++){
            if(A[i].t==1){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++){
        int l=B[i].l,r=B[i].r;
        for(int j=l;j<r;j++){
            if(B[i].t==1){if(!f[j])ans++;f[j]++;}
            else {f[j]--;if(!f[j])ans++;}
        }
    }
    printf("%d",ans);
    return 0;
} 

 

转载于:https://www.cnblogs.com/harden/p/6280031.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值