pku2777 Count Color

思路:用位图记录区间已涂上的颜色

 

#include  < iostream >
using   namespace  std;

#define  clr(x) memset(x,0,sizeof(x))
#define  max(a,b) (a>b?a:b)
#define  min(a,b) (a<b?a:b)
#define  MAXN 100002

struct  Node{
    
int  l,r;
    __int64 s;
}nod[MAXN
* 3 ];


inline 
bool  single(__int64 a){
    
return  (((a - 2 &  a) == 0 );
}


void  init( int  tag, int  l, int  r){
    nod[tag].l
= l;
    nod[tag].r
= r;
    nod[tag].s
= 2 ;
    
if (l == r){
        
return ;
    }
    init(tag
* 2 ,l,(l + r) / 2 );
    init(tag
* 2 + 1 ,(l + r) / 2 + 1 ,r);
}


void  query( int  tag, int  l, int  r,__int64  & ss){
    
if (l <= nod[tag].l  &&  nod[tag].r <= r){
        ss
|= nod[tag].s;
        
return ;
    }
    
if (single(nod[tag].s)){ // 若该结点所示区间为单色,则其儿子所示区间也为单色,故无需再查看以该结点为根的树
        ss |= nod[tag].s;
        
return ;
    }
    
if (l <= nod[tag * 2 ].r)
        query(tag
* 2 ,l,r,ss);
    
if (r >= nod[tag * 2 + 1 ].l)
        query(tag
* 2 + 1 ,l,r,ss);
}


void  paint( int  tag, int  l, int  r, int  c){ // 将[l,r]涂成颜色c
     if (l <= nod[tag].l  &&  nod[tag].r <= r){
        nod[tag].s
= ( 1 << c);
        
return ;
    }
    
if (nod[tag].s == ( 1 << c)) // 若该区间已被染成颜色c则无需再染
         return ;
    
if (single(nod[tag].s)){ // 若该区间为单色,则在上一次改变中,其儿子没有被改变,又因为需要进入该区间的子树,所以必须先将儿子更新为单色
        nod[tag * 2 ].s = nod[tag].s;
        nod[tag
* 2 + 1 ].s = nod[tag].s;
    }
    
if (l <= nod[tag * 2 ].r)
        paint(tag
* 2 ,l,r,c);
    
if (r >= nod[tag * 2 + 1 ].l)
        paint(tag
* 2 + 1 ,l,r,c);
    nod[tag].s
= nod[tag * 2 ].s | nod[tag * 2 + 1 ].s;
}



int  main(){
    
int  L,T,O,i,j,x,y,z,cnt;
    
char  ch[ 3 ];
    __int64 ss;
    
while (scanf( " %d%d%d " , & L, & T, & O) != EOF){
        init(
1 , 1 ,L);
        
for (i = 0 ;i < O;i ++ ){
            scanf(
" %s " ,ch);
            
if (ch[ 0 ] == ' C ' ){
                scanf(
" %d%d%d " , & x, & y, & z);
                
if (x > y){
                    
int  t = x;
                    x
= y;
                    y
= t;
                }
                paint(
1 ,x,y,z);
            }
            
else {
                scanf(
" %d%d " , & x, & y);
                
if (x > y){
                    
int  t = x;
                    x
= y;
                    y
= t;
                }
                ss
= 0 ;
                query(
1 ,x,y,ss);
                cnt
= 0 ;
                
for (j = 1 ;j <= T;j ++ ){
                    
if (ss & ( 1 << j))
                        cnt
++ ;
                }
                printf(
" %d\n " ,cnt);
            }
        }
    }
    
return   0 ;
}

你可能感兴趣的:(count)