POJ2777-Count Color

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

分析:

题意:
一块长为L的木板,有T种颜色和O次操作:
每次操作输入一个字符:
(1)当字符是C时:在区间A到B上涂上C颜色;
(2)当字符是P时:查询A到B上有多少种颜色;

分析:
这里用到了二进制:(因为颜色种类比较少)
颜色1:二进制表示为-1
颜色2:二进制表示为-10
颜色3:二进制表示为-100

颜色10:二进制表示为-1000000000
以此类推!
那么同时有颜色1和颜色2:11
同时颜色1、2、3:111
同时颜色1、2、3、4:1111
同时颜色1、4:1001
以此类推!

还用到了延迟标记:
如果查询区间[A,B],他的子区间[a,b]全是一种颜色,就不用再往更细的方向划分下去了,减少了运算次数!

#include<iostream>
#include<cstdio>
#define N 100005

using namespace std;

struct node{
	bool mark;
	int val;	
}; 

node tree[N<<2];

void pushdown(int i)
{
	if(tree[i].mark)
	{
		tree[i<<1|1].val=tree[i<<1].val=tree[i].val;
		tree[i<<1|1].mark=tree[i<<1].mark=tree[i].mark;
		tree[i].mark=false;
	}
}

void build(int l,int r,int i)
{
	tree[i].val=1;
	tree[i].mark=false;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(l,mid,i<<1);
	build(mid+1,r,i<<1|1);
}

void updata(int l,int r,int i,int lt,int rt,int v)
{
	if(lt<=l&&r<=rt)
	{
		tree[i].val=1<<(v-1);
		tree[i].mark=true;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(i);
	if(lt<=mid)
		updata(l,mid,i<<1,lt,rt,v);
	if(rt>mid)
		updata(mid+1,r,i<<1|1,lt,rt,v);
	tree[i].val=tree[i<<1].val|tree[i<<1|1].val;
}

int query(int l,int r,int i,int lt,int rt)
{
	if(lt<=l&&r<=rt)
		return tree[i].val;
	int mid=(l+r)>>1;
	pushdown(i);
	int sum=0;
	if(lt<=mid)
		sum=sum|query(l,mid,i<<1,lt,rt);
	if(rt>mid)
		sum=sum|query(mid+1,r,i<<1|1,lt,rt);
	return sum;
}


int main()
{
	int L,T,O,A,B,C;
	char op;
	while(~scanf("%d%d%d",&L,&T,&O))
	{
		build(1,L,1);
		for(int i=1;i<=O;i++)
		{
			scanf("%*c%c%d%d",&op,&A,&B);
			if(A>B)
			{
				int t=A;
				A=B;
				B=t;
			}
			if(op=='C')
			{
				scanf("%d",&C);
				updata(1,L,1,A,B,C);
			}
			else
			{
				int sum=0;
				int num=query(1,L,1,A,B);
				while(num!=0)
				{
					if(num&1)
						sum++;
					num>>=1;
				}
				printf("%d\n",sum);
			}
		}
	}
	return 0;
}
发布了46 篇原创文章 · 获赞 16 · 访问量 413

猜你喜欢

转载自blog.csdn.net/weixin_43357583/article/details/105017207