设为首页 加入收藏

TOP

HDU 4419 Colourful Rectangle (线段树扫描线)(一)
2015-07-20 17:37:25 来源: 作者: 【 】 浏览:5
Tags:HDU 4419 Colourful Rectangle 线段 扫描

?

?

Colourful Rectangle
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1272    Accepted Submission(s): 504


Problem Description We use Red, Green and Blue to make new colours. See the picture below:
\


Now give you n rectangles, the colour of them is red or green or blue. You have calculate the area of 7 different colour. (Note: A region may be covered by same colour several times, but it’s final colour depends on the kinds of different colour)
Input The first line is an integer T(T <= 10), the number of test cases. The first line of each case contains a integer n (0 < n <= 10000), the number of rectangles. Then n lines follows. Each line start with a letter C(R means Red, G means Green, B means Blue) and four integers x1, y1, x2, y2(0 <= x1 < x2 < 10^9, 0 <= y1 < y2 < 10^9), the left-bottom's coordinate and the right-top's coordinate of a rectangle.

Output For each case, output a line Case a:, a is the case number starting from 1,then 7 lines, each line contain a integer, the area of each colour. (Note: You should print the areas as the order: R, G, B, RG, RB, GB, RGB).

Sample Input
3
2
R 0 0 2 2
G 1 1 3 3 
3
R 0 0 4 4
G 2 0 6 4
B 0 2 6 6
3
G 2 0 3 8
G 1 0 6 1
B 4 2 7 7

Sample Output
Case 1:
3
3
0
1
0
0
0
Case 2:
4
4
12
4
4
4
4
Case 3:
0
12
15
0
0
0
0

Source 2012 ACM/ICPC Asia Regional Hangzhou Online

?

题意:

给出R,G,B三种颜色的矩形的数据,求最后7种颜色(R,G,B,RG,RB,GB,RGB)的面积是多少?

分析:

显然的线段树扫描线,可以说这题非常考验对线段树扫描线的理解,如果只会用模板,恐怕很难做出来。

R,G,B三种颜色最后会产生7种颜色(无色不算),可以预见本题对编码质量要求相当之高。

update()操作和一般的线段树扫描线并无太大的不同,本题的精髓在于query()!

一般的简单扫描线甚至不用写query,因为根结点维护的区间覆盖长度就是我们所需要的。但是本题需要从复杂的信息中分出7种信息!显然根结点不能直接拿来用。

什么样的信息是我们需要的呢?如果我们能确定一个区间(结点)的颜色,那么该区间(结点)的信息就是我们所需要的,否则我们应继续查询他的左右儿子。那么如何确定一个区间(结点)的颜色呢?显然如果R,G,B三色要么能覆盖整个区间或不在这个区间(见我代码中的judge()函数),那么该区间的颜色就能确定!然后再计算该区间(结点)的有用信息(_plus()函数)。

如果仅仅如此,依然只是套模板的水平。本题与一般的线段树扫描线的不同之处在于查询时需要向下传递信息(pushdown()函数)!为什么?比如在[3,7)区间内,R覆盖了[3,7)这一条,G覆盖了[5,7)这一条,当我们查询到[3,7)时,并不能确定该区间(结点)的颜色,所以我们就要查询它的左右儿子。但如果直接查询,可能会丢失一部分我们需要的信息,比如[3,7)的R,如果不下传,这条线段的信息就会被丢失!当然,我们查询过后需要恢复下传的信息(recover()函数),否则会出现信息的重复,导致最终无法把线段删除干净。

?

?

/*
 *
 *  Author  :  fcbruce
 *
 *  Date  :  2014-09-23 23:34:34 
 *
 */
#include 
  
   
#include 
   
     #include 
    
      #include 
     
       #include 
      
        #include 
       
         #include 
        
          #include 
         
           #include 
          
            #include 
           
             #include 
            
              #include 
             
               #include 
              
                #include 
               
                 #include
                 #include 
                 
                   #define sqr(x) ((x)*(x)) #define LL long long #define itn int #define INF 0x3f3f3f3f #define PI 3.1415926535897932384626 #define eps 1e-10 #ifdef _WIN32 #define lld %I64d #else #define lld %lld #endif #define maxm #define maxn 10007 using namespace std; long long l_r,l_g,l_b,l_rg,l_rb,l_gb,l_rgb; struct __seg { int l,r,h,type,col; bool operator < (const __seg &s)const { return h
                  
                   1) { sum_r[k]=sum_r[lc]+sum_r[rc]; sum_g[k]=sum_g[lc]+sum_g[rc]; sum_b[k]=sum_b[lc]+sum_b[rc]; } if (col_r[k]>0) sum_r[k]=X[r]-X[l]; if (col_g[k]>0) sum_g[k]=X[r]-X[l]; if (col_b[k]>0) sum_b[k]=X[r]-X[l]; } void update(int a,int b,int col,int v,int k,int l,int r) { if (b<=l || r<=a) return ; if (a<=l && r<=b) { switch(col) { case 1:col_r[k]+=v;break; case 2:col_g[k]+=v;break; case 3:col_b[k]+=v;break; } pushup(k,l,r); return ; } update(a,b,col,v,k*2+1,l,l+r>>1); update(a,b,col,v,k*2+2,l+r>>1,r); pushup(k,l,r); } inline bool judge(int k,int l,int r) { return (sum_r[k]==X[r]-X[l] || sum_r[k]==0) && (sum_g[k]==X[r]-X[l] || sum_g[k]==0) && (sum_b[k]==X[r]-X[l] || sum_b[k]==0); } inline void _plus(int k,int l,int r) { int type=0; if (sum_r[k]==X[r]-X[l]) type|=1<<0; if (sum_g[k]==X[r]-X[l]) type|=1<<1; if (sum_b[k]==X[r]-X[l]) type|=1<<2; switch (type) { case 0: break; case 1: l_r+=X[r]-X[l]; break; case 2: l_g+=X[r]-X[l]; break; case 3: l_rg+=X[r]-X[l]; break; case 4: l_b+=X[r]-X[l]; break; case 5: l_rb+=X[r]-X[l]; break; case 6: l_gb+=X[r]-X[l]; break; case 7: l_rgb+=X[r]-X[l]; break; } } inline void pushdown(int k,int l,int r) { int lc=k*2+1,rc=k*2+2,m=l+r>>1; col_r[lc]+=col_r[k]; col_r[rc]+=col_r[k]; col_g[lc]+=col_g[k]; col_g[rc]+=col_g[k]; col_b[lc]+=col_b[k]; col_b[rc]+=col_b[k]; pushup(lc,l,m); pushup(rc,m,r); } inline void recover(int k,int l,int r) { int lc=k*2+1,rc=k*2+2,m=l+r>>1; col_r[lc]-=col_r[k]; col_r[rc]-=col_r[k]; col_g[lc]-=col_g[k]; col_g[rc]-=col_g[k]; col_b[lc]-=col_b[k]; col_b[rc]-=col_b[k]; pushup(lc,l,m); pushup(rc,m,r); } void query(int k,int l,int r) { if (judge(k,l,r)) { _plu
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇UVALive 3942 - Remember the Wor.. 下一篇通过C++的类设置系统时间和输出时..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Redis 分布式锁全解 (2025-12-25 17:19:51)
·SpringBoot 整合 Red (2025-12-25 17:19:48)
·MongoDB 索引 - 菜鸟 (2025-12-25 17:19:45)
·What Is Linux (2025-12-25 16:57:17)
·Linux小白必备:超全 (2025-12-25 16:57:14)