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;
}
时间: 2024-10-11 04:12:37

Hdu 4419 Colourful Rectangle(线段树扫描线)的相关文章

hdu 4419 Colourful Rectangle

http://acm.hdu.edu.cn/showproblem.php?pid=4419 题意:给出3种颜色,重叠会生成新的颜色,然后有一些矩形,求出每种颜色的面积. 转化为二进制表示颜色:001 R ,010G,100B,011RG,101RB,....111RGB; 在结构体里面加上一个len[8]和cover[8]表示每种颜色所占的长度和在区间的覆盖次数. 1 #include <cstdio> 2 #include <cstring> 3 #include <al

HDU 4419 Colourful Rectangle --离散化+线段树扫描线

题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何维护每种颜色的长度着实让我伤透了脑筋.后来看了一位朋友的题解,才幡然醒悟. 开始想到了用二进制表示颜色,R用001表示,G用010表示,B用100表示.那么就可以用十进制1~7表示7种不同颜色了. 维护 cov[rt][1~3] 表示此区间内3种原色各有多少个, Len[rt][i]表示每种颜色的长

HDU 5091---Beam Cannon(线段树+扫描线)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5091 Problem Description Recently, the γ galaxies broke out Star Wars. Each planet is warring for resources. In the Star Wars, Planet X is under attack by other planets. Now, a large wave of enemy spaces

HDU 3265 Posters ——(线段树+扫描线)

第一次做扫描线,然后使我对线段树的理解发生了动摇= =..这个pushup写的有点神奇.代码如下: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #define t_mid (l+r>>1) 5 #define ls (o<<1) 6 #define rs (o<<1|1) 7 #define lson ls,l,t_mid 8 #define

hdu 5091 Beam Cannon(线段树扫描线)

题目链接:hdu 5091 Beam Cannon 题目大意:给定N个点,现在要有一个W?H的矩形,问说最多能圈住多少个点. 解题思路:线段的扫描线,假设有点(x,y),那么(x,y)~(x+W,y+H)形成的矩形,以框的右下角落的位置是可以圈住(x,y) 点,所以N个点即为N个矩形,求覆盖的最大次数,扫描线裸题. #include <cstdio> #include <cstring> #include <vector> #include <algorithm&

HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11551    Accepted Submission(s): 4906 Problem Description There are several ancient Greek texts that contain descriptions of the fabled

[HDU 4419] Colourful Rectangle (扫描线 矩形面积并)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419 题目大意:比矩形面积并多了颜色,问染成的每种颜色的面积. 矩形面积并的扫描线维护的是长度,这道题就是维护每个颜色的长度,写起来很蛋疼. 1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6

HDU 4419 Colourful Rectangle 扫描线

题目链接:点击打开链接 题意:给定由红绿蓝组成的一些矩阵 输出每种颜色对应的面积. 思路: 如果颜色只有一种就是扫描线. 这里先求出包含各类颜色的面积,然后容斥一下得到答案. 画个图就能快速得到答案了 #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <queue> #include <set> #inclu

HDU 1828 Picture(线段树扫描线求周长)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4475    Accepted Submission(s): 2207 Problem Description A number of rectangular posters, photographs and other pictures of the same shap