zoukankan      html  css  js  c++  java
  • hdu1255(矩形面积交)

    覆盖的面积

    题意:

      求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,T;
    
    double x[maxn];
    int cnt[maxn<<2];
    //one:覆盖一次的线段
    //tow:覆盖至少两次的线段
    double one[maxn<<2],two[maxn<<2];
    
    struct Seg {
        int s;
        double l,r,h;
        Seg() {}
        Seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s) {}
        bool operator < (const Seg& rhs) const {
            return h<rhs.h;
        }
    };
    Seg seg[maxn];
    
    void PushUp(int rt,int l,int r)
    {
        if(cnt[rt]>=2){
            one[rt]=two[rt]=x[r+1]-x[l];
        }
        else if(cnt[rt]==1){
            one[rt]=x[r+1]-x[l];
            if(l==r)    two[rt]=0;
            //如果儿子被覆盖过,再覆盖父亲,相当于覆盖了两次
            else        two[rt]=one[rt<<1]+one[rt<<1|1];
        }
        else{
            if(l==r)    one[rt]=two[rt]=0;
            else{
                one[rt]=one[rt<<1]+one[rt<<1|1];
                two[rt]=two[rt<<1]+two[rt<<1|1];
            }
        }
    }
    
    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 binarySearch(double key,double* a,int n)
    {
        int l=0,r=n;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(a[mid]==key) return mid;
            else if(a[mid]<key) l=mid+1;
            else if(a[mid]>key) r=mid-1;
        }
        return -1;
    }
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            int m=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                double x1,y1,x2,y2;
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                x[m]=x1;
                seg[m++]=Seg(x1,x2,y1,1);
                x[m]=x2;
                seg[m++]=Seg(x1,x2,y2,-1);
            }
    
            sort(x,x+m);
            sort(seg,seg+m);
            //去重
            int k=1;
            for(int i=1;i<m;i++){
                if(x[i]!=x[i-1]) x[k++]=x[i];
            }
    
            cls(cnt);
            cls(one);
            cls(two);
            double ans=0;
            for(int i=0;i<m-1;i++){
                int l=binarySearch(seg[i].l,x,k);
                int r=binarySearch(seg[i].r,x,k)-1;
                if(l<=r)   update(l,r,seg[i].s,0,k-1,1);
                ans+=two[1]*(seg[i+1].h-seg[i].h);
            }
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    OI回忆录——一个过气OIer的制杖历程
    博客园美化手记——CSS javascript html
    ProjectEuler && Rosecode && Mathmash做题记录
    算法竞赛推荐
    2020智算之道复赛E 树数数
    牛客编程巅峰赛S1第9场
    c++小学期大作业攻略(五)基于QSS的样式美化
    c++小学期大作业攻略(四)任务系统+站内信
    c++小学期大作业攻略(三)用户系统
    c++小学期大作业攻略(零)建议+代码结构(持续更新)
  • 原文地址:https://www.cnblogs.com/shutdown113/p/9350529.html
Copyright © 2011-2022 走看看