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:
- “C A B C” Color the board from segment A to segment B with color C.
- “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
Solution
线段树,区间染色
因为颜色T值较小,可用位运算优化
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define MAXN 100000
using namespace std;
int l,t,o;
struct Node
{
int left,right,col,lazy;
}segt[MAXN*4];
void build(int idx,int a,int b)
{
segt[idx].col=1;
segt[idx].left=a;
segt[idx].right=b;
segt[idx].lazy=0;
if(a==b)return;
int mid=(a+b)/2;
build(idx*2,a,mid);
build(idx*2+1,mid+1,b);
}
void update(int idx,int a,int b,int c)
{
if(a<=segt[idx].left&&b>=segt[idx].right)
{
segt[idx].col=c;
if(segt[idx].left!=segt[idx].right)
segt[idx].lazy=1;
return;
}
if(segt[idx].lazy)
{
segt[idx*2].col=segt[idx*2+1].col=segt[idx].col;
segt[idx*2].lazy=segt[idx*2+1].lazy=1;
segt[idx].lazy=0;
}
int mid=(segt[idx].left+segt[idx].right)/2;
if(a>mid)update(idx*2+1,a,b,c);
else if(b<=mid)update(idx*2,a,b,c);
else
{
update(idx*2+1,a,b,c);
update(idx*2,a,b,c);
}
segt[idx].col=segt[idx*2+1].col|segt[idx*2].col;
}
int query(int idx,int a,int b)
{
if((a<=segt[idx].left&&b>=segt[idx].right)||segt[idx].lazy)
return segt[idx].col;
int mid=(segt[idx].left+segt[idx].right)/2;
if(a>mid)return query(idx*2+1,a,b);
if(b<=mid)return query(idx*2,a,b);
return query(idx*2+1,a,b)|query(idx*2,a,b);
}
int count(int x)
{
int cnt=0;
while(x)
{
if(x&1)cnt++;
x>>=1;
}
return cnt;
}
int main()
{
while(~scanf("%d%d%d",&l,&t,&o))
{
build(1,1,l);
char opt;
int a,b,c;
for(int i=1;i<=o;i++)
{
cin>>opt;
if(opt=='C')
{
scanf("%d%d%d",&a,&b,&c);
if(a>b)swap(a,b);
update(1,a,b,1<<(c-1));
}
else if(opt=='P')
{
scanf("%d%d",&a,&b);
if(a>b)swap(a,b);
int res=query(1,a,b);
res=count(res);
printf("%d\n",res);
}
}
}
return 0;
}