hdu 4419 Colourful Rectangle(扫描线)

题意:给你10000个三种颜色的矩形,不同颜色的矩形相互覆盖会形成不同的颜色,问形成的七种颜色的面积是多少。

扫描线。线段树的每个节点里维护好七种颜色的长度。直接暴力跑一次即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

#define LL(x)       (x<<1)
#define RR(x)       (x<<1|1)
#define MID(a,b)    (a+((b-a)>>1))

typedef long long LL;

const int N=20005;

struct Line
{
    int x,y1,y2,add;
    Line(){}
    Line(int x,int y1,int y2,int add) :
        x(x),y1(y1),y2(y2),add(add) {}
    bool operator<(const Line &B)const
    {
        return x<B.x||x==B.x&&add<B.add;
    }
};

int n,sz;
LL ans[10];
vector<int> Y;
map<int,int> H;
vector<Line> line;

struct Segtree
{
    int len[N*4][9],add[N*4][4];
    void PushUp(int ind,int lft,int rht)
    {
        int s=0;
        if(add[ind][0]>0) s|=1;
        if(add[ind][1]>0) s|=2;
        if(add[ind][2]>0) s|=4;

        for(int i=1;i<=7;i++) len[ind][i]=0;
        if(s)
        {
            len[ind][s]=len[ind][0];
            for(int i=1;i<=7;i++) if(s!=(s|i))
            {
                int tmp=0;
                if(lft+1!=rht) tmp=len[LL(ind)][i]+len[RR(ind)][i];
                len[ind][s|i]+=tmp;
                len[ind][s]-=tmp;
            }
        }
        else if(lft+1!=rht)
        {
            for(int i=1;i<=7;i++) len[ind][i]=len[LL(ind)][i]+len[RR(ind)][i];
        }
    }
    void build(int lft,int rht,int ind)
    {
        for(int i=0;i<=7;i++)
        {
            len[ind][i]=0;
            if(i<3) add[ind][i]=0;
        }
        len[ind][0]=Y[rht]-Y[lft];
        if(lft+1!=rht)
        {
            int mid=MID(lft,rht);
            build(lft,mid,LL(ind));
            build(mid,rht,RR(ind));
        }
    }
    void updata(int st,int ed,int valu,int lft,int rht,int ind)
    {
        if(st<=lft&&rht<=ed)
        {
            int key=-1;
            if(abs(valu)==1) key=0;
            else if(abs(valu)==2) key=1;
            else key=2;

            add[ind][key]+=(valu>0?1:-1);
            PushUp(ind,lft,rht);
        }
        else
        {
            int mid=MID(lft,rht);
            if(st<mid) updata(st,ed,valu,lft,mid,LL(ind));
            if(ed>mid) updata(st,ed,valu,mid,rht,RR(ind));
            PushUp(ind,lft,rht);
        }
    }
}seg;

void getAns()
{
    for(int i=1;i<=7;i++) ans[i]=0;

    int len=(int)line.size();

    for(int i=0;i<len;i++)
    {
        if(i!=0)
        {
            for(int j=1;j<=7;j++)
                ans[j]+=(LL)(line[i].x-line[i-1].x)*seg.len[1][j];
        }

        int y1=H[line[i].y1];
        int y2=H[line[i].y2];
        int add=line[i].add;
        seg.updata(y1,y2,add,0,sz-1,1);
    }
}
int main()
{
    int t,t_cnt=0;
    scanf("%d",&t);
    while(t--)
    {
        Y.clear();      H.clear();
        line.clear();

        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            char s[10];
            int x1,y1,x2,y2,add;

            scanf("%s%d%d%d%d",s,&x1,&y1,&x2,&y2);
            if(s[0]=='R') add=1;
            else if(s[0]=='G') add=2;
            else add=4;

            line.push_back(Line(x1,y1,y2,add));
            line.push_back(Line(x2,y1,y2,-add));
            Y.push_back(y1); Y.push_back(y2);
        }

        sort(line.begin(),line.end());

        sort(Y.begin(),Y.end());
        Y.erase(unique(Y.begin(),Y.end()),Y.end());

        sz=(int)Y.size();
        for(int i=0;i<sz;i++) H[Y[i]]=i;

        seg.build(0,sz-1,1);
        getAns();

        printf("Case %d:\n",++t_cnt);

        printf("%I64d\n",ans[1]);
        printf("%I64d\n",ans[2]);
        printf("%I64d\n",ans[4]);
        printf("%I64d\n",ans[3]);
        printf("%I64d\n",ans[5]);
        printf("%I64d\n",ans[6]);
        printf("%I64d\n",ans[7]);
    }
    return 0;
}


你可能感兴趣的:(hdu 4419 Colourful Rectangle(扫描线))