Count Color
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 27842   Accepted: 8337

Description

Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem.

There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board:

1. "C A B C" Color the board from segment A to segment B with color C.
2. "P A B" Output the number of different colors painted between segment A and segment B (including).

In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your.

Input

First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation defined previously.

Output

Ouput results of the output operation in order, each line contains a number.

Sample Input

2 2 4
C 1 1 2
P 1 2
C 2 2 2
P 1 2

Sample Output

2
1

思路:给节点设置一个cover域,cover为0代表线段存在多种颜色,非零,代表纯色,数值用于区别颜色种类。
第一次建树时,根节点cover域为1。以后要涂色的时候,先看涂色区域是否覆盖当前节点的范围,如果覆盖,
直接更改当前节点的cover域。否则,先看当前节点是否为纯色,如果是纯色,就要把纯色信息传递给左右子树,
而当前节点cover域则变为0.表明当前节点覆盖的颜色不在是纯色,这样照着这个思路递归更新子节点的cover域。
查询就比较简单了,中间用一个数组来表示哪些颜色已经上色。

代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 100005
struct node
{
  int l,r,c;    
}T[ N*4 ];
int color[40];

void creat(int k,int x,int y)
{
   T[k].l=x;
   T[k].r=y;
   T[k].c=1;
   if( x==y )
   return ;
   int m=(T[k].l+T[k].r)/2;
   creat(2*k,x,m);
   creat(2*k+1,m+1,y);  
}

void change(int k,int x,int y,int val)
{
   if( T[k].c==val)
   return ;
   if(x<=T[k].l&&T[k].r<=y)
   {
     T[k].c=val;
  return ;       
   } 
   if(T[k].c!=0)
   {
      T[2*k].c=T[2*k+1].c=T[k].c;
   T[k].c=0;    
   }
   int m=(T[k].l+T[k].r)/2;
   if(x>m)
   change(2*k+1,x,y,val);
   else if(y<=m)
   change(2*k,x,y,val);
   else
   {
      change(2*k,x,m,val);
   change(2*k+1,m+1,y,val);   
   }
}

void visit(int k,int x,int y)
{
   if(T[k].c>0)
   {
     color[T[k].c]=1;
  return ;     
   }  
   int m=(T[k].l+T[k].r)/2;
   if(x>m)
   visit(2*k+1,x,y);
   else if(y<=m)
   visit(2*k,x,y);
   else
   {
      visit(2*k,x,m);
   visit(2*k+1,m+1,y);   
   }
}

int main()
{
   int L,W,O,a,b,c;
   while(scanf("%d%d%d",&L,&W,&O)!=-1)
   {
      creat(1,1,L); 
      char s[3];
   for(int i=1;i<=O;i++)
   {
      scanf("%s",s);
   if(s[0]=='C')
   {
      scanf("%d%d%d",&a,&b,&c);
   change(1,a,b,c);     
   } 
   if(s[0]=='P')
   {
     scanf("%d%d",&a,&b);
     memset(color,0,sizeof(color));
     int cnt=0;
     visit(1,a,b); 
     for(int j=1;j<=W;j++)
     {
        if(color[j])
      cnt++;    
        }  
     printf("%d\n",cnt);  
   }  
      }         
   }
   return 0; 
}

链接:http://poj.org/problem?id=2777