poj2777 涂颜色

题目大意:一块长L的版,可分为L长为1的版,初始颜色都为颜色1.现在可以执行两个操作,修改其中一个区间内的颜色,和输出一个区间内不同颜色的总数.选择解决问题和程序设计作为选修课程,您需要解决各种问题。在这里,我们收到一个新问题。有一个非常长的板的长度L厘米,L是一个正整数,所以我们可以均匀地将板分成L段,它们被标记为1,2,…L 从左到右,每个长 1 厘米。现在,我们必须对板着色 - 一个...
摘要由CSDN通过智能技术生成

题目大意:一块长L的版,可分为L长为1的版,初始颜色都为颜色1.
现在可以执行两个操作,修改其中一个区间内的颜色,和输出一个区间内不同颜色的总数.

选择解决问题和程序设计作为选修课程,您需要解决各种问题。在这里,我们收到一个新问题。
有一个非常长的板的长度L厘米,L是一个正整数,所以我们可以均匀地将板分成L段,它们被标记为1,2,…
L 从左到右,每个长 1 厘米。现在,我们必须对板着色 - 一个段只有一种颜色。我们可以在电路板上执行以下两个操作:1."C

A B C"将电路板从 A 段着色到带
颜色 C. 2 的分段 B。“P A B” 输出段 A 和段 B(包括)之间绘制的不同颜色的数量。
在我们的日常生活中,我们很少有词来描述颜色(红色,绿色,蓝色,黄色…),所以你可以假设不同颜色T的总数
非常小。为了简单,我们将颜色的名称表示为颜色 1,颜色 2,…颜色 T.一开始,棋盘被涂成颜色1。现在剩下的问题留给你了。
输入
第一行输入包括 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)作为以前定义的操作。
输出
输出操作的 Ouput 结果按顺序排列,每行包含一个数字。
样本输入
2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2
样品输出
2
1

使用线段树和懒标记,不然会超时。
因为颜色只有三十种,所以可以
用二进制记录颜色。

在这里插入代码片
`#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX=1e5+10; 
struct node{
	int r,l,col;
	bool lazy;
}tree[MAX<<2];
void zmh(int rt)//或运算 
{
	tree[rt].col=tree[rt<<1].col|tree[rt<<1|1].col;
 }
 void updown(int k)//懒标记 向下延申 
 {
 	if(tree[k].lazy)
 	{
 		tree[k<<1].lazy=tree[k<<1|1].lazy=tree[k].lazy;
 		tree[k<<1].col=tree[k<<1|1].col=tree[k].col;
 		tree[k].lazy=false;
	 }
  } 
void btree(int k,int l,int r)//建树 初始定义颜色为01 
{
	tree[k].l=l,tree[k].r=r;
	if(l==r)
	{
		tree[k].col=1;
		tree[k].lazy=false;
				return ;
	}
	int mid=(l+r)>>1;
	btree(k<<1,l,mid);
	btree(k<<1|1,mid+1,r);
	zmh(k);
}
void update(int k,int l,int r,int col)//修改 以二进制存储颜色种数  
{
	if(l<=tree[k].l&&tree[k].r<=r)
	{
		tree[k].lazy=true;
		tree[k].col=1<<(col-1);//将颜色用二进制记录
		return;
	}
	updown(k);
	int mid=(tree[k].r+tree[k].l)>>1;
	if(mid>=l)update(k<<1,l,r,col);
	if(mid<r)update(k<<1|1,l,r,col);
	zmh(k);
}
int query(int k,int l,int r)//查找 
{
	if(l<=tree[k].l&&r>=tree[k].r)
	{
		return tree[k].col;
	}
	updown(k); 
	int mid=(tree[k].l+tree[k].r)>>1;
	int ans=0;
	if(mid>=l)ans|=query(k<<1,l,r);
	if(mid<r)ans|=query(k<<1|1,l,r);
	return ans;
}
int main()
{
	int L,T,O;
	while(scanf("%d%d%d",&L,&T,&O)!=EOF)
	{
		btree(1,1,L);
	while(O--)
	{
		char a[3];
		scanf("%s",a);
		if(a[0]=='C')
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			if(a>b)swap(a,b);
			update(1,a,b,c);
		}
		else
		{
			int l,r;
			scanf("%d%d",&l,&r);
			if(l>r)swap(l,r);
			int sum=query(1,l,r);
			int ans=0;
			while(sum)
			{
				if(sum&1)ans++;//如果最后一位为1 颜色加一
					sum>>=1;//向后移一位
					}
			printf("%d\n",ans);
		}
	}
		
	}
	return 0;
 } ``

     
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值