Count Color
Time Limit: 1000MS
Memory Limit: 65536K
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
/这题很巧妙的利用了二进制,0010就代表第二种颜色,如果与0001进行或运算,就变成了0011.这样用1逐位与运算就计算出来了颜色数为2,对区间操作用lazy标记/
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cstdio>
using namespace std;
#define clean(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define maxn 100005
int tree[maxn<<2],lazy[maxn<<2];
/*状态压缩,利用二进制表示这段是什么颜色,0010表示这段是颜色二*/
void push_up(int rt)
{
tree[rt]=tree[rt<<1] | tree[rt<<1|1]; //逐位与运算
}
void push_down(int rt)
{
if(lazy[rt])
{
tree[rt<<1]=tree[rt<<1|1]=lazy[rt];
lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
lazy[rt]=0;
}
}
void build(int l,int r,int rt)
{
lazy[rt]=0;
if(l==r){
tree[rt]=1;
return ;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
push_up(rt);
}
void update(int l,int r,int rt,int tl,int tr,int x)
{
if(r<tl || l>tr) return ;
if(l>=tl && r<=tr){
int color=1<<(x-1);
tree[rt]=lazy[rt]=color;
return ;
}
push_down(rt);
int mid=(l+r)>>1;
if(mid<tr)
update(rson,tl,tr,x);
if(mid>=tl)
update(lson,tl,tr,x);
push_up(rt);
}
int query(int l,int r,int rt,int tl,int tr)
{
if(r<tl || l>tr) return 0;
if(l>=tl && r<=tr)
return tree[rt];
int mid=(l+r)>>1;
push_down(rt);
return query(lson,tl,tr) | query(rson,tl,tr);
}
int number(int x)
{
int cnt=0;
while(x)
{
if(x&1) cnt++;
x>>=1;
}
return cnt;
}
int main()
{
//初始时都为颜色1
int n,t,m; //长度,颜色数,操作
char ch[3];
while(~scanf("%d%d%d",&n,&t,&m))
{
build(1,n,1);
while(m--)
{
scanf("%s",ch);
getchar();
if(ch[0] == 'C')
{
int l,r,x;
if(l>r) swap(l,r);
scanf("%d%d%d",&l,&r,&x);
getchar();
update(1,n,1,l,r,x);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
getchar();
if(l>r) swap(l,r);
int ans=query(1,n,1,l,r);
ans=number(ans);
printf("%d\n",ans);
}
}
}
return 0;
}
本博客介绍了一个利用二进制和线段树解决的颜色计数问题。在一个长木板上,通过区间染色操作和查询不同颜色数量,采用状态压缩技巧,将颜色表示为二进制位,实现高效区间更新与查询。适合学习数据结构和算法优化的读者。


被折叠的 条评论
为什么被折叠?



