题目链接:  poj 2777 Count Color

题目大意:  给出一块长度为n的板,区间范围[1,n],和m种染料

k次操作,C  a  b  c 把区间[a,b]涂为c色,P  a  b 查询区间[a,b]有多少种不同颜色

解题思路:  很明显的线段树的区间插入和区间查询,但是如何统计有多少不同的颜色呢?

如果每个结点数组来存储颜色的种类,空间复杂度很高,而且查询很慢

颜色最多只有30种,可以用位运算中的“按位或|”

颜色也用二进制来处理,和存储:

第一种颜色的二进制表示1

第二种颜色的二进制表示10

第三种颜色的二进制表示100

第四种颜色的二进制表示1000

如同一个区间出现第一种和第三种颜色,按位或运算之后得到 101

统计结果有多少个1,就说明区间有多少不同的颜色

线段树每个结点存储区间颜色的种类,结点=左子树|右子树

更多关于线段树的解题报告可以看我博客 myzee.cn

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 110000
#define MID(a,b) (a+b)>>1
#define L(a) a<<1
#define R(a) (a<<1|1)
typedef struct{
int left,right;
int add,num;
}Node;
Node Tree[MAX<<2];
int Color[32]={0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824};
//二进制表示第几种颜色,如8表示第四种颜色:1000
int Lowbit(int x) //剔除x二进制中最后面一个1
{
return x&(-x);
} void Build(int t,int l,int r) //以1为根结点,建立[l,r]的线段树
{
Tree[t].left=l,Tree[t].right=r,Tree[t].add=0; //***
if(l==r)
{
Tree[t].num=1;
return ;
}
int mid=MID(Tree[t].left,Tree[t].right);
Build(L(t),l,mid);
Build(R(t),mid+1,r);
Tree[t].num=(Tree[L(t)].num|Tree[R(t)].num);
} void Insert(int t,int l,int r,int m) //向区间[l,r]涂颜色
{
if(Tree[t].left==l&&Tree[t].right==r)
{
Tree[t].add=m;
Tree[t].num=m;
return ;
}
if(Tree[t].add!=0) //lazy标记
{
Tree[L(t)].num=Tree[t].add;
Tree[R(t)].num=Tree[t].add;
Tree[L(t)].add=Tree[t].add;
Tree[R(t)].add=Tree[t].add;
Tree[t].add=0;
}
int mid=MID(Tree[t].left,Tree[t].right);
if(l>mid)
{
Insert(R(t),l,r,m);
}
else if(r<=mid)
{
Insert(L(t),l,r,m);
}
else
{
Insert(L(t),l,mid,m);
Insert(R(t),mid+1,r,m);
}
Tree[t].num=(Tree[L(t)].num|Tree[R(t)].num); //***
} int Query(int t,int l,int r)
{
if(Tree[t].left==l&&Tree[t].right==r)
{
return Tree[t].num;
}
if(Tree[t].add!=0) //区间插入的lazy思想
{
Tree[L(t)].num=Tree[t].add;
Tree[R(t)].num=Tree[t].add;
Tree[L(t)].add=Tree[t].add;
Tree[R(t)].add=Tree[t].add;
Tree[t].add=0;
}
int mid=MID(Tree[t].left,Tree[t].right);
if(l>mid)
{
return Query(R(t),l,r);
}
else if(r<=mid)
{
return Query(L(t),l,r);
}
else
{
return Query(L(t),l,mid)|Query(R(t),mid+1,r); //***是|,不是+!!!
}
Tree[t].num=(Tree[L(t)].num|Tree[R(t)].num);
} int main()
{
char ch;
int n,col,q,i,k,a,b,c;
int m;
while(scanf("%d%d%d",&n,&col,&q)!=EOF)
{
memset(Tree,0,sizeof(Tree)); //初始化
Build(1,1,n); //建树
for(i=0;i<q;i++)
{
getchar();
scanf("%c",&ch);
if(ch=='P')
{
scanf("%d%d",&a,&b);
k=0;
if(a>b)
m=Query(1,b,a);
else
m=Query(1,a,b);
while(m>0) //计算查询后的结果的二进制表示右多少个1
{
k++;
m-=Lowbit(m);
}
printf("%d\n",k);
}
else
{
scanf("%d%d%d",&a,&b,&c);
if(a>b)
Insert(1,b,a,Color[c]);
else
Insert(1,a,b,Color[c]);
}
}
}
return 0;
}

注:原创文章,转载请注明出处

poj 2777 Count Color(线段树区区+染色问题)的更多相关文章

  1. poj 2777 Count Color(线段树)

    题目地址:http://poj.org/problem?id=2777 Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Subm ...

  2. poj 2777 Count Color(线段树、状态压缩、位运算)

    Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 38921   Accepted: 11696 Des ...

  3. poj 2777 Count Color - 线段树 - 位运算优化

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42472   Accepted: 12850 Description Cho ...

  4. POJ 2777 Count Color(线段树之成段更新)

    Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33311 Accepted: 10058 Descrip ...

  5. POJ 2777 Count Color (线段树成段更新+二进制思维)

    题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的 ...

  6. POJ P2777 Count Color——线段树状态压缩

    Description Chosen Problem Solving and Program design as an optional course, you are required to sol ...

  7. POJ 2777.Count Color-线段树(区间染色+区间查询颜色数量二进制状态压缩)-若干年之前的一道题目。。。

    Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 53312   Accepted: 16050 Des ...

  8. POJ 2777 Count Color(段树)

    职务地址:id=2777">POJ 2777 我去.. 延迟标记写错了.标记到了叶子节点上.. . . 这根本就没延迟嘛.. .怪不得一直TLE... 这题就是利用二进制来标记颜色的种 ...

  9. poj 2777 Count Color

    题目连接 http://poj.org/problem?id=2777 Count Color Description Chosen Problem Solving and Program desig ...

随机推荐

  1. 异常关闭MyEclipse 8.6后,不能重启

    删掉这两个文件.

  2. 程序中使用事务来管理sql语句的执行,执行失败时,可以达到回滚的要求。

    1.设置使用事务的SQL执行语句 /// <summary> /// 使用有事务的SQL语句 /// </summary> /// <param name="s ...

  3. 【Oracle】不安装Oracle客户端直接用PL/SQL连接数据库

    1.下载 instantclient_11_2.zip PL/SQL2.解压instantclient_11_2.zip到相应文件夹,比如:E:\oracleclient\instantclient_ ...

  4. Android学习笔记:使用ViewPager组件实现图片切换

    在很多App中,尤其是第一次安装启动后,都会出现几个图片进行一些app的介绍和说明,图片可以随着滑动而切换. 我们这里利用 ViewPager组件来演示如何实现这一点. 1.创建一个app工程,默认创 ...

  5. Observer设计模式【利用商品概念解释】

    每个人都想过着富有的生活,这是很正常的. 这里以开店进货为例. 在讲之前解释英语单词: Observer:查看:遵守 Observable:可见的,公开的. 从单词可以知道:商品用来卖,所以公开,继承 ...

  6. 如何自学 Python(干货合集)

    http://wenku.baidu.com/view/5108f974192e45361066f583.html

  7. JAVA爬虫 WebCollector

    JAVA爬虫 WebCollector 爬虫简介: WebCollector是一个无须配置.便于二次开发的JAVA爬虫框架(内核),它提供精简的的API,只需少量代码即可实现一个功能强大的爬虫. 爬虫 ...

  8. 求知成瘾+逻辑成瘾+博识的无知,你中枪没?我感觉中枪了 - 外野 - Stage1st - Powered by Discuz!

    求知成瘾+逻辑成瘾+博识的无知,你中枪没?我感觉中枪了 - 外野 - Stage1st - Powered by Discuz! 求知成瘾 求知欲似乎是人们的本能,尤其「好学」这个词被定义成天生的褒义 ...

  9. visual c++ 2010安装未成功

    可能是已经安装了其他版本的Microsoft visual studio 参考: http://answers.microsoft.com/zh-hans/windows/forum/windows_ ...

  10. c语言中scanf()、printf()函数

    函数调用scanf(“%d”,  &weight) 包含两个参数:“%d” 和&weight.C用逗号来隔开函数调用中的多个参数: 但是printf()和scanf()函数比较特殊,其 ...