题目:
两种操作,一种是将 a 到 b 染成某一种颜色,第二种是询问a 到 b 有多少种颜色。颜色小于30种,长度不超过1e5。
思路:
因为题目明确表明颜色只有30种,所以可以用一个int表示所有的颜色(二进制表示),再用线段树进行优化就可以很轻松的过掉。
代码:
#include <cstdio>
#define MaxN 100001
using namespace std;
int color[ 31 ] = { 0 };
typedef struct {
int left, right;
int sum;
int lazy;
} node;
node tree[ MaxN * 4 ];
void bulittree( int po, int left, int right ) {
tree[ po ].left = left;
tree[ po ].right = right;
tree[ po ].lazy = 0;
tree[ po ].sum = 1;
if ( left == right ) {
return;
} else {
int middle = ( left + right ) / 2;
bulittree( po * 2, left, middle );
bulittree( po * 2 + 1, middle + 1, right );
}
}
void pushup( int po ) {
tree[ po ].sum = tree[ po * 2 ].sum | tree[ po * 2 + 1 ].sum;
}
void pushdown( int po ) {
if ( tree[ po ].lazy ) {
tree[ po * 2 ].sum = tree[ po ].lazy;
tree[ po * 2 + 1 ].sum = tree[ po ].lazy;
tree[ po * 2 ].lazy = tree[ po ].lazy;
tree[ po * 2 + 1 ].lazy = tree[ po ].lazy;
tree[ po ].lazy = 0;
}
}
void update( int po, int left, int right, int need ) {
if ( tree[ po ].left >= left && tree[ po ].right <= right ) {
tree[ po ].sum = color[ need ];
tree[ po ].lazy = color[ need ];
} else {
pushdown( po );
int middle = ( tree[ po ].left + tree[ po ].right ) / 2;
if ( left <= middle ) {
update( po * 2, left, right, need );
}
if ( right > middle ) {
update( po * 2 + 1, left, right, need );
}
pushup( po );
}
}
int query( int po, int left, int right ) {
if ( tree[ po ].left >= left && tree[ po ].right <= right ) {
return tree[ po ].sum;
} else {
pushdown( po );
int middle = ( tree[ po ].left + tree[ po ].right ) / 2;
int ans = 0;
if ( left <= middle )
ans |= query( po * 2, left, right );
if ( right > middle )
ans |= query( po * 2 + 1, left, right );
return ans;
}
}
int main( void ) {
int N, M, T;
int left, right, need, answer;
int i, j;
char test;
j = 1;
for ( i = 1; i <= 30; i ++ ) {
color[ i ] = j;
j *= 2;
}
scanf("%d %d %d", &N, &T, &M );
getchar( );
bulittree( 1, 1, N );
while ( M -- ) {
scanf("%c", &test );
switch ( test ) {
case 'C' : {
scanf("%d %d %d", &left, &right, &need );
if ( left > right ) {
left ^= right;
right ^= left;
left ^= right;
}
update( 1, left, right, need );
getchar( );
break;
}
case 'P' : {
scanf("%d %d", &left, &right );
getchar( );
if ( left > right ) {
left ^= right;
right ^= left;
left ^= right;
}
answer = 0, j = query( 1, left, right );
while ( j ) {
if ( j % 2 )
answer ++;
j /= 2;
}
printf("%d\n", answer );
break;
}
}
}
}