洛谷P1558 色板游戏

题目描述

色板长度为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 ; 
}

还有一点 有可能每一排输入后边有多个空格


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值