POJ 2777 Count Color(位运算+线段树+lazy+区间更新)

Count Color

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 39905   Accepted: 12034

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

写完之后就是wrong,看别人说要用位运算,第一次用位运算

ac代码:
#include<stdio.h>
struct s
{
	int color;
	int left;
	int right;
	int lazy;
}tree[4000000+1000];
void pushdown(int i)
{
	if(tree[i].lazy)
	{
		tree[i*2].lazy=tree[i*2+1].lazy=1;
		tree[i*2].color=tree[i].color;
		tree[i*2+1].color=tree[i].color;
		tree[i].lazy=0;
	}
}
void build(int l,int r,int i)
{
	int mid;
	tree[i].left=l;
	tree[i].right=r;
	tree[i].lazy=1;
	tree[i].color=1;
	if(l==r)
	return;
	mid=(l+r)/2;
	build(l,mid,i*2);
	build(mid+1,r,i*2+1);
}
void update(int l,int r,int c,int i)
{
	int mid;
	if(tree[i].left>=l&&tree[i].right<=r)
	{
		tree[i].lazy=1;
		tree[i].color=(1<<(c-1));
		return;
	}
	pushdown(i);
	mid=(tree[i].left+tree[i].right)/2;
	if(r<=mid)
	update(l,r,c,i*2);
	else if(l>mid)
	update(l,r,c,i*2+1);
	else
	{
		update(l,mid,c,i*2);
		update(mid+1,r,c,i*2+1);
	}
	tree[i].color=tree[i*2].color|tree[i*2+1].color;
}
int query(int l,int r,int i)
{
	int mid;
	if(l<=tree[i].left&&r>=tree[i].right)
	return tree[i].color;
	pushdown(i);
	mid=(tree[i].left+tree[i].right)/2;
	if(r<=mid)
	return query(l,r,i*2);
	else if(l>mid)
	return query(l,r,i*2+1);
	else
	return query(l,mid,i*2)|query(mid+1,r,i*2+1);
}
int fun(int x)
{
	int num=0;
	while(x)
	{
		if(x%2)
		num++;
		x/=2;
	}
	return num;
}
int main()
{
	int i,n,l,t;
	int a,b,c,ans;
	char ch[3];
	while(scanf("%d%d%d",&l,&t,&n)!=EOF)
	{
		build(1,l,1);
		for(i=0;i<n;i++)
		{
			scanf("%s",ch);
			if(ch[0]=='C')
			{
				scanf("%d%d%d",&a,&b,&c);
				if(b<a)
				update(b,a,c,1);
				else
				update(a,b,c,1);
			}
			else if(ch[0]=='P')
			{
				scanf("%d%d",&a,&b);
				if(b<a)
				ans=query(b,a,1);
				else
				ans=query(a,b,1);
				printf("%d\n",fun(ans));
			}
		}
    }
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-25 19:09:25

POJ 2777 Count Color(位运算+线段树+lazy+区间更新)的相关文章

poj 2528 Mayor&#39;s posters(线段树 离散化 区间更新 贴海报)

     这个题目本来对大神来说可能是水题, 对我就不行了,昨晚非折腾到下半夜一点 搞定, 并且可以总结出 ,只有把问题想清楚,或着看人家解题报告自己把问题和代码思路 搞清楚,才能谈的上调bug,否则根本就不知道错在哪儿.说说这个题目的理解,他是如何转化为线段树问题的呢?我们知道线段树有一个区间更新的东西,每张海报的宽度不就是一个区间么?那么我们可以用一棵树中的部分结点 来表示整张海报的可视部分,也就是说每个结点只允许表示一张完整的或着不完整的海报(好几个结点才可以表示成完整的一张海报),那么如

FZU1608 Huge Mission 线段树lazy区间更新+求和

就这破题目坑了我一个大晚上,直到今天一觉醒过来才搞定,原因之一:这题目的题意真的是太狗了,还不如直接看着案例猜来的快啊, 题意:给了你一些区间,x,y,第三个参数w是效率,代表这段时间他的单位时间效率,效率总和就是 (y-x)*w,然后有的时间段会被重复啊,比如前面给了1,4,1,后面又给了2,4,3他们为了是的时间段1,4的效率总和最大肯定是选择  2,4区间的效率值选择3,意思就是后面出现更好的情况就覆盖前面的,问你总得最大效率和 当然这题目坑的原因还有一个就是以前学习线段树 做的时候都是看

Color the ball (线段树的区间更新问题)

N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗? Input每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <= N). 当N = 0,输入结束.Output每个测

POJ 2777 Count Color (线段树+位运算)

题意很简单了,对一个区间有两种操作: 1. "C A B C" Color the board from segment A to segment B with color C. //A~B涂上颜色C 2. "P A B" Output the number of different colors painted between segment A and segment B (including). //输出A~B间颜色的种类数 题目链接:http://poj.o

POJ 2777 Count Color (线段树区间更新加查询)

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 d

poj 2777 Count Color(线段树区间修改)

题目链接:http://poj.org/problem?id=2777 题目意思:就是问你在询问的区间里有几种不同的颜色 思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数.这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了.... 代码核心处就在计数那儿

poj 2777 Count Color【线段树段更新】

题目:poj 2777 Count Color 题意:给出一段1 * n 的栅栏,有两种操作,第一种:把 l -- r 全部染成同一颜色t,第二种,查询 l---r 一共有多少种颜色. 分类:线段树 分析:我们可以给每个节点加一个标记,标记当前节点是否只有一种颜色,然后对只有一种颜色的节点如果要染色的话,那么他会变成几种颜色的,这时候记得向下更新一次就好,统计的时候统计节点有单个颜色的颜色就好. 代码: #include <cstdio> #include <cstring> #i

POJ 2777 Count Color(线段树)

题目地址:POJ 2777 我去..延迟标记写错了.标记到了叶子节点上....这根本就没延迟嘛...怪不得一直TLE... 这题就是利用二进制来标记颜色的种类.然后利用或|这个符号来统计每个区间不同颜色种数. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h

POJ 2777 Count Color(线段树)

POJ 2777 Count Color 题目链接 就一个线段树,颜色二进制表示就可以,成段更新成段查询延迟操作 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define lson(x) ((x<<1)+1) #define rson(x) ((x<<1)+2) const int N = 100005; struct No