您的位置:首页 > 其它

POJ 2777 Count Color (线段树、lazy思想)

2013-10-05 20:04 323 查看
题意:有一个区间,最多有30种颜色。有两种操作,一种是对某一个区间段染上某一种颜色,一种是询问该区间有多少种不同的颜色。

思路:线段树的好题,线段树 + lazy思想的经典应用。而且和位运算结合到了一起。因为颜色数量很少,而且父结点的颜色正好是两个子结点颜色的按位或,因此可以用位运算。最后1的个数就是不同颜色的个数。

// 4276K	297MS
#include <cstdio>
#include <iostream>
#include <cstring>
#define MID(X,Y) ((X+Y)>>1)
#define L(X) ((X)<<1)
#define R(X) (((X)<<1)|1)
#define MAX 100050

using namespace std ;

struct Node
{
int l , r ;
int col ;           //用一个32位的int型,每一位对应一种颜色(例将1转换成 00000...1 ,2转换成000...10, 每个共32位),用位运算代替bool col[32]
bool cover ;        //cover =ture 表示该区间染上同一种颜色,否则表示染上的颜色为混合色
}node[3*MAX];

void
swap ( int & a , int & b )
{
int temp ;
temp = a ;
a = b ;
b = temp ;
}

void
BuildTree ( int const left , int const right , int const n )
{
node
.l = left ;
node
.r = right ;
node
.col = 1 ;
node
.cover = true ;
if ( node
.l == node
.r )
{
return ;
}
else
{
int mid ;
mid = MID(node
.l,node
.r ) ;
BuildTree ( left , mid , L(n) ) ;
BuildTree ( mid + 1 , right , R(n) ) ;
}
return ;
}

void
Delay_Update ( int const n )
{
int value ;
value = node
.col ;
node
.cover = false ;
node[L(n)].col = value ;
node[L(n)].cover = true ;
node[R(n)].col = value ;
node[R(n)].cover = true ;
}

void
Update ( int const left , int const right , int const value , int const n )
{
if ( left <= node
.l && right >= node
.r )
{
node
.col = value ;
node
.cover = true ;
return ;
}
else
{
if ( node
.col == value ) //剪枝
{
return ;
}
else
{
if ( node
.cover )
{
Delay_Update ( n ) ;
}
int mid ;
mid = MID ( node
.l , node
.r ) ;
if ( right <= mid )
{
Update ( left , right , value , L(n) ) ;
}
else if ( left > mid )
{
Update ( left , right , value , R(n) ) ;
}
else
{
Update ( left , mid , value , L(n) ) ;
Update ( mid + 1 , right , value , R(n) ) ;
}
node
.col = node[L(n)].col | node[R(n)].col ;
}
}
}

void
Query  ( int const left , int const right , int & sum , int const n )
{
if ( node
.cover )
{
sum |= node
.col ;
return ;
}
else if ( left <= node
.l && right >= node
.r )
{
sum |= node
.col ;
return ;
}
else
{
int mid ;
mid = MID (node
.l , node
.r ) ;
if ( right <= mid )
{
Query ( left , right , sum , L(n) ) ;
}
else if ( left > mid )
{
Query ( left , right , sum , R(n) ) ;
}
else
{
Query ( left , mid , sum , L(n) ) ;
Query ( mid + 1 , right , sum , R(n) ) ;
}
}
return ;
}

int
Get_Answer ( int sum ) //找出sum中"1"的个数
{
int ans ;
ans = 0 ;
while ( sum )
{
if ( sum % 2 )
{
ans ++ ;
}
sum = sum >> 1 ;
}
return ans ;
}

int
main ( )
{
int L,T,O ;//L代表board长度,T代表color种类,O代表总操作数
scanf ("%d%d%d" , & L , & T , & O ) ;
BuildTree ( 1 , L , 1 ) ;
while ( O-- )
{
getchar ( ) ; //吃掉回车
char oper ;
scanf ("%c" , & oper ) ;
if ( 'C' == oper )
{
int left , right ;
int k ;     //k代表要更新的第k中颜色
scanf ("%d%d%d" , & left , & right , & k ) ;
int trans ;
trans = 1 << ( k - 1 ) ;     //将k在表示上转换成与node
.col对应的形式
Update ( left , right , trans , 1 ) ;
}
else
{
int left , right ;
scanf ("%d%d" , & left , & right ) ;
if ( right < left )
{
swap ( left , right ) ;
}
int sum ;
sum = 0 ;
Query ( left , right , sum , 1 ) ;
int ans ;
ans = Get_Answer ( sum ) ;
printf ("%d\n" , ans ) ;
}
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: