HDU 1255 覆盖的面积 (矩形面积并变形)

解题

求覆盖至少两次的面积。
用sum表示被覆盖至少一次的长度,用ss表示被覆盖至少两次的长度。这题与hdu1542的区别就在于更新ss。
首先像hdu1542那样去更新sum(因为需要用到sum去更新ss)。
根据该区间被完全覆盖的次数来更新ss:
如果add大于1,那么ss等于整个区间。
如果add等于1,那么ss等于左子树的sum值加右子树的sum值。(因为该区间被完全覆盖一次,左子树被覆盖一次累加该区间就至少两次,同理累加右子树)。
如果是叶子结点,ss等于0.

AC代码

//280ms 2.1MB
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define lson p<<1
#define rson p<<1|1
using namespace std;

const int maxn=3e3+100;
struct node
{
    int l,r;//线段树所维护的区间
    int add;//add为1表示加一次覆盖,为-1表示减一次覆盖
    double sum,ss;//对应的被覆盖y一次的长度、两次的长度
}T[maxn<<2];
struct line///从下到上扫描
{
    double h,L,R;//高度和左右端点
    int mark;//标记为1表示下边,为-1表示上边
    bool operator<(const line &o)const
    {
        return h<o.h;
    }
}li[maxn];
double pos[maxn];
void up(int p)
{
    //更新被覆盖至少一次的长度
    if(T[p].add) T[p].sum=pos[T[p].r-1]-pos[T[p].l-1];
    else if(T[p].l==T[p].r) T[p].sum=0;
    else T[p].sum=T[lson].sum+T[rson].sum;

    //更新被覆盖至少两次的长度
    if(T[p].add>1) T[p].ss=pos[T[p].r-1]-pos[T[p].l-1];//长度是对应在pos数组中的值的差
    //不是线段树所维护的区间长度
    else if(T[p].l==T[p].r) T[p].ss=0;//不全部覆盖且是叶子结点,一定没有被覆盖的部分
    else if(T[p].add==1) T[p].ss=T[lson].sum+T[rson].sum;
    else if(T[p].add==0) T[p].ss=T[lson].ss+T[rson].ss;
}
void build(int p,int l,int r)
{
    T[p].add=0;T[p].sum=0;T[p].ss=0;
    T[p].l=l,T[p].r=r;
    if(l+1==r) return ;///注意叶子结点是一个长度为1的线段
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid,r);///注意是mid,不是mid+1
}
void update(int p,int x,int y,int c)
{
    if(T[p].l==x && T[p].r==y)
    {
        T[p].add+=c;
        up(p);
        return ;
    }
    int mid=(T[p].l+T[p].r)>>1;
    if(y<=mid) update(lson,x,y,c);
    else if(x>=mid) update(rson,x,y,c);///注意是>=mid,不是>mid
    else
    {
        update(lson,x,mid,c);
        update(rson,mid,y,c);///注意是mid,不是mid+1
    }
    up(p);
}

int main()
{
    int n,kase=0;
    scanf("%d",&kase);
    while(kase--)
    {
        scanf("%d",&n);

        int cnt=0,d=0;
        for(int i=0; i<n; i++)
        {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            pos[d++]=x1;
            pos[d++]=x2;
            li[cnt].h=y1;
            li[cnt].L=x1;
            li[cnt].mark=1;
            li[cnt++].R=x2;
            li[cnt].h=y2;
            li[cnt].L=x1;
            li[cnt].mark=-1;
            li[cnt++].R=x2;
        }
        sort(li,li+cnt);
        sort(pos,pos+d);
        int m=unique(pos,pos+d)-pos;
        build(1,1,m);
        double ans=0;
        for(int i=0; i<cnt; i++)
        {
            int l=lower_bound(pos,pos+m,li[i].L)-pos+1;
            int r=lower_bound(pos,pos+m,li[i].R)-pos+1;
            ans+=i==0?0:(li[i].h-li[i-1].h)*T[1].ss;
            update(1,l,r,li[i].mark);
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37685156/article/details/80723221
今日推荐