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:
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
1,刚开始的时候并没有想到要用到位运算,结果傻了吧唧的去开了一个数组储存状态,结果就在各种改变状态的时候,就非常开心的超时了;
2,cover数组非常重要,充分的体现了线段树的优势,如果区间的颜色一样,则在没有必要划分区间;
3,用二进制位来保存颜色的状态非常棒(看到颜色不超过30中的时候就应该想到这个的嘛,题做少了,不够敏感),既节省了存储空间,又方便后面的状态变换~
#include
#include
#include
#include
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=100009;
int n,cover[maxn<<2],color[maxn<<2];//cover标记此区间是否是同一种颜色,color表示此区间的颜色状态,
//由于颜色不超过30种,故可以用int的每一位来表示颜色,相比于开一个数组要方便得多
int temp;
int L,T,O;
void pushup(int rt)
{
color[rt]=color[rt<<1]|color[rt<<1|1];//位运算很高效!
}
void pushdown(int rt)
{
if(cover[rt])
{
cover[rt<<1]=cover[rt<<1|1]=cover[rt];
color[rt<<1]=color[rt<<1|1]=color[rt];
cover[rt]=0;
}
}
void build(int l,int r,int rt)
{
color[rt]=1;
cover[rt]=1;
if(l==r)
return ;
int m=l+r>>1;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
cover[rt]=1;
color[rt]=c;
return;
}
if(color[rt]==c)//如果此时的状态和要改变的状态一样则没有必要再进行下去
return;
int m=l+r>>1;
pushdown(rt);
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
pushup(rt);
}
void query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
temp|=color[rt];
return;
}
if(cover[rt])
{
temp|=color[rt];//如果颜色一样则没有必要继续划分区间,很重要哦~
return;
}
int m=l+r>>1;
pushdown(rt);
if(m>=L) query(L,R,lson);
if(mint main()
{
scanf("%d%d%d",&L,&T,&O);
build(1,L,1);
while(O--)
{
char ch[10];
int a,c,b;
scanf("%s",ch);
if(ch[0]=='C')
{
scanf("%d%d%d",&a,&b,&c);
if(a>b) swap(a,b);
update(a,b,1<<(c-1),1,L,1);
}
else
{
scanf("%d%d",&a,&b);
if(a>b) swap(a,b);
temp=0;
query(a,b,1,L,1);
int sum=0;
while(temp)
{
if(temp&1)
sum++;
temp>>=1;
}
printf("%d\n",sum);
}
}
return 0;
}