题目链接:http://poj.org/problem?id=2777
/*
线段树成段更新,root[t].lazy表示颜色编号,但因为是求每段的颜色种类,所以往下传递的时候,是root[t*2+1].lazy=root[t*2].lazy=root[t].lazy.
因为题目中限定了颜色的种类为1~30,所以可以用t[i]来表示i颜色是否出现过。
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int t[50];
struct
{
int l,r,lazy;
}root[1000000];
void build(int i,int x,int y)
{
root[i].l=x;
root[i].r=y;
root[i].lazy=1;//初始化,颜色都是1.
if(x==y)
return;
int mid=(x+y)>>1;
build(i*2,x,mid);
build(i*2+1,mid+1,y);
}
void update(int i,int x,int y,int z)
{
int l=root[i].l,r=root[i].r;
int mid=(l+r)>>1;
if(l==x&&r==y)
{
root[i].lazy=z;
return;
}
if(root[i].lazy>0)//把更新的颜色往下传递
{
root[i*2+1].lazy=root[i*2].lazy=root[i].lazy;
root[i].lazy=0;
}
if(x<=mid) update(i*2,x,min(y,mid),z);
if(y>mid) update(i*2+1,max(x,mid+1),y,z);
}
void query(int i,int x,int y)
{
int l=root[i].l,r=root[i].r;
int mid=(l+r)>>1;
if(root[i].lazy>0)
{
t[root[i].lazy]=1;
return ;
}
if(x<=mid) query(i*2,x,min(y,mid));
if(y>mid) query(i*2+1,max(mid+1,x),y);
}
int main()
{
int L,T,Q;
scanf("%d%d%d",&L,&T,&Q);
build(1,1,L);
while(Q--)
{
char s[5];
int x,y,z;
scanf("%s%d%d",s,&x,&y);
if(s[0]=='C')
{
scanf("%d",&z);
update(1,x,y,z);
}
else
{
memset(t,0,sizeof(t));
query(1,x,y);
int ans=0;
for(int i=1;i<=30;i++)
{
if(t[i]==1)
ans++;
}
printf("%d\n",ans);
}
}
return 0;
}