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
原文地址:https://www.cnblogs.com/shutdown113/p/9350529.html