HDU 4419 Colourful Rectangle(线段树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4419

题意:给出平面上一些矩形,这些矩形的颜色有三种R、G、B。相交的区域分别标记为 RG, RB, GB, RGB。输出颜色为R, G, B, RG, RB, GB, RGB的面积各为多少?

思路:比赛的时候想着跟标准的矩形面积并相比,要输出各种颜色的面。当时想,只能在线段树的节点上改变以记录每种颜色,看别人的容斥原理才明白,原来可以这样干:设上面7种颜色的面积分别为1,2,3,4,5,6,7:

a=1+2+3+4+5+6+7(把所有的矩形求一次面积交)

b=1+2+4+5+6+7(把R和G的矩形求一次)

c=2+3+4=5+6+7(把G和B的矩形求一次)

d=1+3+4+5+6+7(把R和B的矩形求一次)

e=1+4+5+7(把R的矩形求一次)

f=2+4+6+7(把G的矩形求一次)

g=3+5+6+7(把B的矩形求一次)

由以上七个式子可以得到:

1=a-c;
2=a-d;
3=a-b;
6=a-2-3-e;
5=a-1-3-f;
4=a-1-2-g;
7=a-1-2-3-4-5-6;

问题迎刃而解。。。



 

 

 struct NODE

 {

     char color[5];

     __int64 x1,y1,x2,y2;

 };

 struct Node

 {

     __int64 L,R;

     __int64 Len; //当前,本区间上有多长的部分是落在那些矩形中的

     __int64 cover; //本区间当前被多少个矩形完全包含

 

 };

 

 

 struct node

 {

     __int64 x,y1,y2;

     bool bLeft;

 

     node(){}

     node(__int64 _x,__int64 _y1,__int64 _y2,bool _bLeft)

     {

         x=_x;

         y1=_y1;

         y2=_y2;

         bLeft=_bLeft;

     }

 };

 

 const int MAX=10005;

 NODE p[MAX];

 node L[MAX*2];

 Node a[MAX*10];

 __int64 y[MAX*2];

 int n;

 

 

 bool cmp(node a,node b)

 {

     return a.x<b.x;

 }

 

 inline int DB(__int64 x)

 {

     if(x==0) return 0;

     return x>0?1:-1;

 }

 

 int find(__int64 y[],int n,__int64 val)

 {

     int low=0,high=n-1,mid;

     while(low<=high)

     {

         mid=(low+high)>>1;

         if(DB(val-y[mid])==0) return mid;

         if(DB(val-y[mid])==1) low=mid+1;

         else high=mid-1;

     }

     if(DB(val-y[0])==0) return 0;

     return n-1;

 }

 

 

 

 void insert(int t,int L,int R)

 {

     if(a[t].L==L&&a[t].R==R)

     {

         a[t].Len=y[R+1]-y[L];

         a[t].cover++;

         return;

     }

     int mid=(a[t].L+a[t].R)>>1;

     if(R<=mid) insert(t*2,L,R);

     else if(L>mid) insert(t*2+1,L,R);

     else

     {

         insert(t*2,L,mid);

         insert(t*2+1,mid+1,R);

     }

     if(a[t].cover==0) a[t].Len=a[t*2].Len+a[t*2+1].Len;

 }

 

 void del(int t,int L,int R)

 {

     if(a[t].L==L&&a[t].R==R)

     {

         a[t].cover--;

         if(a[t].cover==0)

         {

             if(a[t].L==a[t].R) a[t].Len=0;

             else a[t].Len=a[t*2].Len+a[t*2+1].Len;

         }

         return;

     }

     int mid=(a[t].L+a[t].R)>>1;

     if(R<=mid) del(t*2,L,R);

     else if(L>mid) del(t*2+1,L,R);

     else

     {

         del(t*2,L,mid);

         del(t*2+1,mid+1,R);

     }

     if(a[t].cover==0) a[t].Len=a[t*2].Len+a[t*2+1].Len;

 }

 

 void build(int t,int L,int R)

 {

     a[t].L=L;

     a[t].R=R;

     a[t].cover=0;

     a[t].Len=0;

     if(L==R) return;

     int mid=(L+R)>>1;

     build(t*2,L,mid);

     build(t*2+1,mid+1,R);

 }

 



 __int64 cal_cross_area(NODE p[],int n)

 {

     if(!n) return 0;

     int i,k;

     __int64 x1,y1,x2,y2;

     for(i=0;i<n;i++)

     {

         x1=p[i].x1;

         y1=p[i].y1;

         x2=p[i].x2;

         y2=p[i].y2;

         y[i*2]=y1;

         y[i*2+1]=y2;

         L[i*2]=node(x1,y1,y2,true);

         L[i*2+1]=node(x2,y1,y2,false);

     }

     sort(y,y+2*n);

     sort(L,L+2*n,cmp);

     k=unique(y,y+2*n)-y;

     build(1,0,k-2);

     __int64 ans=0;

     for(i=0;i<2*n-1;i++)

     {

         int left=find(y,k,L[i].y1) ;

         int right=find(y,k,L[i].y2) ;

         if(L[i].bLeft) insert(1,left,right-1);

         else del(1,left,right-1);

         ans+=((__int64)a[1].Len)*(L[i+1].x-L[i].x);

     }

     return ans;

 }

 

 int C,num=0;

 

 int main()

 {

     for(scanf("%d",&C);C--;)

     {

         scanf("%d",&n);

         int i;

         __int64 x1,y1,x2,y2;

         for(i=0;i<n;i++)

         {

             scanf("%s%I64d%I64d%I64d%I64d",p[i].color,&x1,&y1,&x2,&y2);

             p[i].x1=x1;

             p[i].y1=y1;

             p[i].x2=x2;

             p[i].y2=y2;

         }

         __int64 a,b,c,d,e,f,g;

 

         a=cal_cross_area(p,n);

         NODE Q[MAX];

         int N;

 

         N=0;

         for(i=0;i<n;i++) if(p[i].color[0]=='R'||p[i].color[0]=='G')

            Q[N++]=p[i];

         b=cal_cross_area(Q,N);

 

         N=0;

         for(i=0;i<n;i++) if(p[i].color[0]=='B'||p[i].color[0]=='G')

            Q[N++]=p[i];

         c=cal_cross_area(Q,N);

 

         N=0;

         for(i=0;i<n;i++) if(p[i].color[0]=='R'||p[i].color[0]=='B')

            Q[N++]=p[i];

         d=cal_cross_area(Q,N);

 

         N=0;

         for(i=0;i<n;i++) if(p[i].color[0]=='R')

            Q[N++]=p[i];

         e=cal_cross_area(Q,N);

 

         N=0;

         for(i=0;i<n;i++) if(p[i].color[0]=='G')

            Q[N++]=p[i];

         f=cal_cross_area(Q,N);

 

         N=0;

         for(i=0;i<n;i++) if(p[i].color[0]=='B')

            Q[N++]=p[i];

         g=cal_cross_area(Q,N);

 

         __int64 _1,_2,_3,_4,_5,_6,_7;

         _1=a-c;

         _2=a-d;

         _3=a-b;

         _6=a-_2-_3-e;

         _5=a-_1-_3-f;

         _4=a-_1-_2-g;

         _7=a-_1-_2-_3-_4-_5-_6;

 

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

         printf("%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n%I64d\n",_1,_2,_3,_4,_5,_6,_7);

     }

     return 0;

 }

  

 

 

你可能感兴趣的:(HDU)