/*线段树染色,经典题,在这道题中学到了,只改变段,而没有下放到点,当下一次的 改变,须向下进行是,则要将父节点的颜色下方到子节点 vis[]用来标记 ,避免重复计算 */ #include<stdio.h> #include<string.h> #define N 100010 struct node { int b; int e; int c; }p[N*4]; int sum,vis[N]; void build(int x,int l,int r) { p[x].c=1; p[x].b=l; p[x].e=r; p[x].num=1; if(l==r)return ; int mid=(l+r)/2; build(x*2,l,mid); build(x*2+1,mid+1,r); } void change(int x,int l,int r,int color) { if(p[x].c==color)return ; if(p[x].b==l&&p[x].e==r) { p[x].c=color;//只改变段 return ; } if(p[x].c>=1) { p[x*2].c=p[x].c;//下放到子节点 p[x*2+1].c=p[x].c; p[x].c=-1; } int mid=(p[x].b+p[x].e)/2; if(r<=mid)change(x*2,l,r,color); else { if(l>mid)change(x*2+1,l,r,color); else { change(x*2,l,mid,color); change(x*2+1,mid+1,r,color); } } } int Get(int x,int b,int e) { if(p[x].c>=1) { if(!vis[p[x].c]){vis[p[x].c]=1;return 1;} else return 0; } int mid=(p[x].b+p[x].e)/2; if(e<=mid) { return Get(x*2,b,e); } else { if(b>mid)return Get(x*2+1,b,e); else { int n=Get(x*2,b,mid); int m=Get(x*2+1,mid+1,e); return m+n; } } } int main() { int T; int L,O; while(scanf("%d%d%d",&L,&T,&O)!=EOF){ build(1,1,L); getchar(); char str[4]; int b,e,c; sum=0; while(O--) { scanf("%s",str); if(str[0]=='C') { scanf("%d%d%d",&b,&e,&c); int t; if(b>e){t=b;b=e;e=t;} change(1,b,e,c); } else { scanf("%d%d",&b,&e); int t; if(b>e){t=b;b=e;e=t;} sum=0; for(int i=0;i<=T;i++)vis[i]=0; sum=Get(1,b,e); /*for(int i=1;i<=T;i++) { if(vis[i])sum++; }*/ printf("%d\n",sum); } } } }