题目描述
色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, ... L。现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:1. "C A B C" 指在A到 B 号方格中涂上颜色 C。2. "P A B" 指老师的提问:A到 B号方格中有几种颜色。学校的颜料盒中一共有 T 种颜料。为简便起见,我们把他们标记为 1, 2, ... T. 开始时色板上原有的颜色就为1号色。 面对如此复杂的问题,阿宝向你求助,你能帮助他吗?
输入输出格式
输入格式:
第一行有3个整数 L (1 <= L <= 100000), T (1 <= T <= 30) 和 O (1 <= O <= 100000). 在这里O表示事件数, 接下来 O 行, 每行以 "C A B C" 或 "P A B" 得形式表示所要做的事情(这里 A, B, C 为整数, 可能A> B)
输出格式:
对于老师的提问,做出相应的回答。每行一个整数。
输入样例#1:
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2输出样例#1:
2 1
颜色只有30个对吧 int是 2^31 - 1 对吧 所以一看就知道是状压对吧
然后就可以线段树乱搞了
#include <iostream>
#include <stdio.h>
#include <cstdlib>
#define FOR( x , y ) for( int p = x ; p <= y ; p ++ )
#define in( x ) scanf( "%d" , &x )
using namespace std ;
int n , m , k ;
int jis( int x ) {
int c = 0 ;
for( ; x ; ++ c ) {
x &= ( x - 1 ) ;
} return c ;
}
struct hxb {
struct maker1{
int l , r , sum , lazy , zy ;
} xds[ 800005 ] ;
void build( int l , int r , int id ) {
xds[ id ] . l = l , xds[ id ] . r = r ;
if( l == r ) { xds[ id ] . sum = 1 , xds[ id ] . zy = 1 ; return ;}
int mid = l + r >> 1 ;
build( l , mid , id << 1 ) , build( mid + 1 , r , id << 1 | 1 ) ;
xds[ id ] . zy = xds[ id << 1 ] . zy | xds[ id << 1 | 1 ] . zy ;
}
void pushdown( int id ) {
int v = xds[ id ] . lazy ;
xds[ id << 1 ] . zy = xds[ id << 1 | 1 ] . zy = 1 << ( v - 1 ) , xds[ id << 1 ] . sum = xds[ id << 1 | 1 ] . sum = 1 , xds[ id << 1 ] . lazy = xds[ id << 1 | 1 ] . lazy = v ;
xds[ id ] . lazy = 0 ; return ;
}
void update( int l , int r , int id , int v ) {
// cout << l << " " << r << endl ;
if( xds[ id ] . l == l && xds[ id ] . r == r ) { xds[ id ] . zy = 1 << ( v - 1 ) , xds[ id ] . sum = 1 , xds[ id ] . lazy = v ; return ; }
int mid = xds[ id ] . l + xds[ id ] . r >> 1 ;
if( xds[ id ] . lazy && xds[ id ] . l != xds[ id ] . r ) pushdown( id ) ;
if( r <= mid ) update( l , r , id << 1 , v ) ;
if( l > mid ) update( l , r , id << 1 | 1 , v ) ;
if( l <= mid && r > mid ) update( l , mid , id << 1 , v ) , update( mid + 1 , r , id << 1 | 1 , v ) ;
xds[ id ] . zy = xds[ id << 1 ] . zy | xds[ id << 1 | 1 ] . zy ;
xds[ id ] . sum = jis( xds[ id ] . zy ) ;
}
int cx( int l , int r , int id ) {
// cout << l << " " << r << " " << id << " " << xds[ id ] . l << " " << xds[ id ] . r << " " << xds[ id ] . zy << endl ;
if( xds[ id ] . l == l && r == xds[ id ] . r ) return xds[ id ] . zy ;
int mid = xds[ id ] . l + xds[ id ] . r >> 1 ;
if( xds[ id ] . lazy && xds[ id ] . l != xds[ id ] . r ) pushdown( id ) ;
if( r <= mid ) return cx( l , r , id << 1 ) ;
if( l > mid ) return cx( l , r , id << 1 | 1 ) ;
return cx( l , mid , id << 1 ) | cx( mid + 1 , r , id << 1 | 1 ) ;
}
} A ;
int main( ) {
// freopen( "wlwl.in" , "r" , stdin ) ;
char s[ 10 ] ; int a , b , c ;
in( n ) , in( m ) , in( k ) ;
A . build( 1 , n , 1 ) ;
FOR( 1 , k ) {
// getchar( ) ;
scanf( "%s" , &s ) , in( a ) , in( b ) ;
if( b < a ) swap( a , b );
// cout << s[ 0 ] << endl ;
if( s[ 0 ] == 'C' ) in( c ) , A . update( a , b , 1 , c ) ;
else cout << jis( A . cx( a , b , 1 ) ) << endl ;
}
return 0 ;
}
还有一点 有可能每一排输入后边有多个空格