Hdu 4419 Colourful Rectangle(线段树扫描线)

题目大意:

给出多个不同颜色的矩形,求最后覆盖的颜色的面积。


思路分析:

我是自己手动暴力枚举。

比赛的时候漏了一种情况。

RGB 可以从 RG+RB组合来(只是举例,就是说可以从两种颜色组合而来)。

然后就只需要维护所有的颜色

用扫描线来判断。


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 42222
using namespace std;
typedef long long ll;
struct node
{
    ll s,e,h,type,color;//记录的是每一条线的起点 终点 距离X周的面积
    bool operator < (const node &cmp)const
    {
        return h<cmp.h;
    }
}line[MAXN]; //是底还是高 底是1高是-1   意味着底就是覆盖。高就是删除

ll tree[MAXN<<2][10];
ll cnt[MAXN<<2][10];
ll x[MAXN<<2];

void pushup(int num,int l,int r)
{
    int chs=0;
    for(int i=0;i<3;i++)
    {
        if(cnt[num][i])
            chs|=(1<<i);
    }

    if(chs==0)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
                tree[num][i]=0;
            return;
        }

        for(int i=0;i<7;i++)
            tree[num][i]=tree[num<<1][i]+tree[num<<1|1][i];
    }
    else if(chs==1)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
            {
                if(i==0)tree[num][i]=x[r+1]-x[l];
                else tree[num][i]=0;
            }
            return;
        }
        tree[num][1]=0;
        tree[num][2]=0;
        tree[num][3]=tree[num<<1][1]+tree[num<<1|1][1]+tree[num<<1][3]+tree[num<<1|1][3];
        tree[num][4]=tree[num<<1][2]+tree[num<<1|1][2]+tree[num<<1][4]+tree[num<<1|1][4];
        tree[num][5]=0;
        tree[num][6]=tree[num<<1][5]+tree[num<<1|1][5]+tree[num<<1][6]+tree[num<<1|1][6];
        ll tmp=x[r+1]-x[l];
        for(int i=0;i<=6;i++)if(i!=0)tmp-=tree[num][i];

        tree[num][0]=tmp;
    }
    else if(chs==2)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
            {
                if(i==1)tree[num][i]=x[r+1]-x[l];
                else tree[num][i]=0;
            }
            return;
        }
        tree[num][0]=tree[num][2]=0;
        tree[num][3]=tree[num<<1][0]+tree[num<<1|1][0]+tree[num<<1][3]+tree[num<<1|1][3];
        tree[num][4]=0;
        tree[num][5]=tree[num<<1][2]+tree[num<<1|1][2]+tree[num<<1][5]+tree[num<<1|1][5];
        tree[num][6]=tree[num<<1][4]+tree[num<<1|1][4]+tree[num<<1][6]+tree[num<<1|1][6];
        ll tmp=x[r+1]-x[l];
        for(int i=0;i<=6;i++)if(i!=1)tmp-=tree[num][i];
        tree[num][1]=tmp;
    }
    else if(chs==3)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
            {
                if(i==3)tree[num][i]=x[r+1]-x[l];
                else tree[num][i]=0;
            }
            return;
        }
        tree[num][0]=tree[num][2]=tree[num][1]=0;
        tree[num][4]=0;
        tree[num][5]=0;
        tree[num][6]=tree[num<<1][2]+tree[num<<1|1][2]+tree[num<<1][6]+tree[num<<1|1][6]+tree[num<<1][4]+tree[num<<1|1][4]+tree[num<<1][5]+tree[num<<1|1][5];
        ll tmp=x[r+1]-x[l];
        for(int i=0;i<=6;i++)if(i!=3)tmp-=tree[num][i];
        tree[num][3]=tmp;
    }
    else if(chs==4)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
            {
                if(i==2)tree[num][i]=x[r+1]-x[l];
                else tree[num][i]=0;
            }
            return;
        }
        tree[num][0]=tree[num][1]=0;
        tree[num][3]=0;
        tree[num][4]=tree[num<<1][0]+tree[num<<1|1][0]+tree[num<<1][4]+tree[num<<1|1][4];
        tree[num][5]=tree[num<<1][1]+tree[num<<1|1][1]+tree[num<<1][5]+tree[num<<1|1][5];
        tree[num][6]=tree[num<<1][3]+tree[num<<1|1][3]+tree[num<<1][6]+tree[num<<1|1][6];
        ll tmp=x[r+1]-x[l];
        for(int i=0;i<=6;i++)if(i!=2)tmp-=tree[num][i];
        tree[num][2]=tmp;
    }
    else if(chs==5)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
            {
                if(i==4)tree[num][i]=x[r+1]-x[l];
                else tree[num][i]=0;
            }
            return;
        }

        tree[num][0]=tree[num][2]=tree[num][1]=0;
        tree[num][3]=0;

        tree[num][5]=0;
        tree[num][6]=tree[num<<1][1]+tree[num<<1|1][1]+tree[num<<1][6]+tree[num<<1|1][6]+tree[num<<1][3]+tree[num<<1|1][3]+tree[num<<1][5]+tree[num<<1|1][5];
        ll tmp=x[r+1]-x[l];
        for(int i=0;i<=6;i++)if(i!=4)tmp-=tree[num][i];
        tree[num][4]=tmp;
    }
    else if(chs==6)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
            {
                if(i==5)tree[num][i]=x[r+1]-x[l];
                else tree[num][i]=0;
            }
            return;
        }

        tree[num][0]=tree[num][2]=tree[num][1]=0;
        tree[num][3]=0;
        tree[num][4]=0;
        tree[num][6]=tree[num<<1][0]+tree[num<<1|1][0]+tree[num<<1][6]+tree[num<<1|1][6]+tree[num<<1][3]+tree[num<<1|1][3]+tree[num<<1][4]+tree[num<<1|1][4];
        ll tmp=x[r+1]-x[l];
        for(int i=0;i<=6;i++)if(i!=5)tmp-=tree[num][i];
        tree[num][5]=tmp;
    }
    else if(chs==7)
    {
        if(l==r)
        {
            for(int i=0;i<7;i++)
            {
                if(i==6)tree[num][i]=x[r+1]-x[l];
                else tree[num][i]=0;
            }
            return;
        }

        tree[num][0]=tree[num][2]=tree[num][1]=0;
        tree[num][3]=0;
        tree[num][4]=0;
        tree[num][5]=0;
        tree[num][6]=x[r+1]-x[l];
    }

}

void update(int num,int s,int e,int l,int r,ll val,ll color)
{
    if(l<=s && r>=e)
    {
        cnt[num][color]+=val;
        pushup(num,s,e);
        return ;
    }
    int mid=(s+e)>>1;

    if(l<=mid)update(num<<1,s,mid,l,r,val,color);
    if(r>mid)update(num<<1|1,mid+1,e,l,r,val,color);

    pushup(num,s,e);
}

void debug(int num,int s,int e)
{
    printf("s = %d e = %d\n",s,e);
    for(int i=0;i<=6;i++)printf("%d ",tree[num][i]);
    puts("");
    if(s==e)return;
    int mid=(s+e)>>1;
    debug(num<<1,s,mid);
    debug(num<<1|1,mid+1,e);
}
ll ans[7];
int main()
{
    int n,T;
    int cas=1;
    for(scanf("%d",&T);T--;)
    {
        scanf("%d",&n);
        int m=0;
        for(int i=1;i<=n;i++)
        {
            char str[5];
            ll x1,y1,x2,y2;
            scanf("%s%I64d%I64d%I64d%I64d",str,&x1,&y1,&x2,&y2);

            ll co;
            if(str[0]=='R')co=0;
            else if(str[0]=='G')co=1;
            else if(str[0]=='B')co=2;

            m++;
            x[m]=x1;
            line[m].s=x1,line[m].e=x2,line[m].h=y1,line[m].type=1,line[m].color=co;

            m++;
            x[m]=x2;
            line[m].s=x1,line[m].e=x2,line[m].h=y2,line[m].type=-1,line[m].color=co;
        }

        sort(line+1,line+1+m);
        sort(x+1,x+1+m);
        int tot=unique(x+1,x+1+m)-x-1;

        memset(ans,0,sizeof ans);
        memset(tree,0,sizeof tree);
        memset(cnt,0,sizeof cnt);

        for(int i=1;i<m;i++)
        {
            int L=lower_bound(x+1,x+tot+1,line[i].s)-x;
            int R=lower_bound(x+1,x+tot+1,line[i].e)-x-1;

            if(L<=R)update(1,1,tot,L,R,line[i].type,line[i].color);

            for(int j=0;j<=6;j++)
                ans[j]+=tree[1][j]*(line[i+1].h-line[i].h);
        }

        printf("Case %d:\n",cas++);
        for(int i=0;i<=6;i++)
            printf("%I64d\n",ans[i]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值