题目大意:一块长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;
} ``