• hdu1828(矩形周长并)


    Picture

    题意:

      求n个矩形组成的图形的周长。

    分析:

      用类似求矩形面积并的方法,但是需要注意的是当矩形相交时,位于别的矩形中的线是不需要加入周长中的,所以需要开数组记录是否出现相交,具体解释看代码。

      学习资料:大佬博客

    代码:

    #include <map>
    #include <queue>
    #include <vector>
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    const int maxn=1e5+100;
    const int inf=0x3f3f3f3f;
    
    int n,Case=1;
    
    int cnt[maxn<<2];
    //rt所代表的区间左边,右边是否有线段
    bool lbd[maxn<<2],rbd[maxn<<2];
    //segNum:rt所代表的区间有几条竖着的线段
    //sum:rt所代表的区间有效线段的长度
    int segNum[maxn<<2],sum[maxn<<2];
    
    struct Seg {
        int l,r,h,s;
        Seg() {}
        Seg(int l,int r,int h,int s):l(l),r(r),h(h),s(s) {}
        bool operator < (const Seg& rhs) const {
            if(h==rhs.h)    return s>rhs.s;
            return h<rhs.h;
        }
    };
    Seg seg[maxn];
    
    void PushUp(int rt,int l,int r)
    {
        if(cnt[rt]){
            segNum[rt]=2;
            sum[rt]=r-l+1;
            lbd[rt]=rbd[rt]=1;
        }
        else if(l==r){
            sum[rt]=segNum[rt]=lbd[rt]=rbd[rt]=0;
        }
        else{
            lbd[rt]=lbd[rt<<1];
            rbd[rt]=rbd[rt<<1|1];
            sum[rt]=sum[rt<<1]+sum[rt<<1|1];
            segNum[rt]=segNum[rt<<1]+segNum[rt<<1|1];
            //左右两个区间出现交集
            if(lbd[rt<<1|1]&&rbd[rt<<1])    segNum[rt]-=2;
        }
    }
    
    void update(int L,int R,int c,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            cnt[rt]+=c;
            PushUp(rt,l,r);
            return;
        }
        int m=(l+r)>>1;
        if(L<=m)    update(L,R,c,lson);
        if(R>m)     update(L,R,c,rson);
        PushUp(rt,l,r);
    }
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        while(scanf("%d",&n)!=EOF&&n)
        {
            int m=0,l=inf,r=-inf;
            for(int i=1;i<=n;i++){
                int x1,y1,x2,y2;
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                l=min(l,x1);r=max(r,x2);
                seg[m++]=Seg(x1,x2,y1,1);
                seg[m++]=Seg(x1,x2,y2,-1);
            }
    
            sort(seg,seg+m);
            int ans=0,last=0;
            for(int i=0;i<m;i++){
                if(seg[i].l<=seg[i].r)  update(seg[i].l,seg[i].r-1,seg[i].s,l,r-1,1);
                ans+=segNum[1]*(seg[i+1].h-seg[i].h);
                //需要减去重复覆盖的部分
                ans+=abs(sum[1]-last);
                last=sum[1];
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Day01 基本SQL SELECT
    Java IO流
    排序: 选择排序
    Java的数据存储机制
    Java反射基础笔记
    学习面向对象的三条主线之三 面向对象的三大特征 关键字
    学习面向对象的三条主线之二 面向对象的三大特征
    Oracle数据库知识积累
    office技巧
    如何读书
  • 原文地址:https://www.cnblogs.com/shutdown113/p/9350267.html
Copyright © 2020-2023  润新知