本题是典型的线段树的题目,由于颜色的数目较少,所以只使用一个整形变量来表示。
#include<iostream>
using namespace std;
struct node//结构
{
int l,r;//左右子树
int col;//颜色
}a[1000000];
int L,T,O;
int cnt;
inline bool single(int a) //判断是否只有一种颜色
{
return (((a-1)&a)==0);
}
void insert(int l,int r,int c,int p) //更新
{
if(l<=a[p].l&&r>=a[p].r)//如果当前子树在lr区间内,那么所有子区间都是颜色C
{
a[p].col=c;
return;
}
if(a[p].col==c)//如果当前节点子树区间的颜色和要染色相同,那么直接返回,这个是个优化
{
return;
}
if (single(a[p].col)) //如果是单色,子区间也是单色
{
a[2*p].col=a[p].col;
a[2*p+1].col=a[p].col;
}
int mid=(a[p].l+a[p].r)>>1;
if(l<=mid)
insert(l,r,c,2*p);
if(r>mid)
insert(l,r,c,2*p+1);
a[p].col=a[2*p].col|a[2*p+1].col;
}
void search(int l,int r,int p,int &cnt)//查询
{
if(l<=a[p].l&&r>=a[p].r)
{
cnt|=a[p].col;
return;
}
if(single(a[p].col))
{
cnt|=a[p].col;
return;
}
int mid=(a[p].l+a[p].r)>>1;
if(l<=mid)
search(l,r,2*p,cnt);
if(r>mid)
search(l,r,2*p+1,cnt);
}
void construct(int l,int r,int p)
{
if(l==r)
{
a[p].l=a[p].r=l;
return;
}
a[p].l=l;
a[p].r=r;
int mid=(l+r)>>1;
construct(l,mid,2*p);
construct(mid+1,r,2*p+1);
}
int cal(int p)
{
int num=0;
while(p)
{
if(p%2)
num++;
p>>=1;
}
return num;
}
int main()
{
scanf("%d%d%d",&L,&T,&O);
construct(1,L,1);
insert(1,L,1,1);
int st,en,col;
char ch;
while(O--)
{
getchar();
scanf("%c",&ch);
if(ch=='C')
{
scanf("%d%d%d",&st,&en,&col);
if(st>en)
{
int tmp=st;st=en;en=tmp;
}
insert(st,en,1<<(col-1),1);
}
else
{
scanf("%d%d",&st,&en);
if(st>en)
{
int tmp=st;st=en;en=tmp;
}
cnt=0;
search(st,en,1,cnt);
printf("%d/n",cal(cnt));
}
}
return 0;
}