poj 2777 Count Color(线段树区区+染色问题)
题目链接: 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(线段树区区+染色问题)的更多相关文章
- poj 2777 Count Color(线段树)
题目地址:http://poj.org/problem?id=2777 Count Color Time Limit: 1000MS Memory Limit: 65536K Total Subm ...
- poj 2777 Count Color(线段树、状态压缩、位运算)
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 38921 Accepted: 11696 Des ...
- poj 2777 Count Color - 线段树 - 位运算优化
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 42472 Accepted: 12850 Description Cho ...
- POJ 2777 Count Color(线段树之成段更新)
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33311 Accepted: 10058 Descrip ...
- POJ 2777 Count Color (线段树成段更新+二进制思维)
题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的 ...
- POJ P2777 Count Color——线段树状态压缩
Description Chosen Problem Solving and Program design as an optional course, you are required to sol ...
- POJ 2777.Count Color-线段树(区间染色+区间查询颜色数量二进制状态压缩)-若干年之前的一道题目。。。
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 53312 Accepted: 16050 Des ...
- POJ 2777 Count Color(段树)
职务地址:id=2777">POJ 2777 我去.. 延迟标记写错了.标记到了叶子节点上.. . . 这根本就没延迟嘛.. .怪不得一直TLE... 这题就是利用二进制来标记颜色的种 ...
- poj 2777 Count Color
题目连接 http://poj.org/problem?id=2777 Count Color Description Chosen Problem Solving and Program desig ...
随机推荐
- mac 系统开发android,真机调试解决方式(无数的坑之后吐血总结)
近期学习android开发,安装了ADT开发环境之后,启动模拟器,慢的要死啊,全然不如苹果的好用,没法,自己买个android手机,准备联机调试程序.没想到在这个过程中,遇到了好多的坑,作为一个新人, ...
- C#中的DataTable简单使用Merge
//不同结构的DataTable追加第二个DataTable数据在对应行后的 简单使用//不同结构的DataTable追加在行后面的合并 DataTable dt = new DataTable(); ...
- 20150706 js之定时器
对应智能社:09 定时器的使用 开启定时器: setInterval(xxx(),1000);//间隔型 第一个参数为函数,第二个为时间,单位为毫秒 setTimeout(xxx(),1000);// ...
- Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)
Qt线程间共享数据主要有两种方式: 使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的: 使用singal/slot机制,把数据 ...
- 正则表达式验证数字、汉字、电话号码,email,整数,浮点数
验证数字的正则表达式集 验证数字:^[0-9]*$验证n位的数字:^\d{n}$验证至少n位数字:^\d{n,}$验证m-n位的数字:^\d{m,n}$验证零和非零开头的数字:^(0|[1-9][0- ...
- 作业还是作孽?——Leo鉴书79
中国孩子,尤其是城市孩子课业过重是个不争的事实.儿子上幼儿园的作业已经能做到8点多了,上小学之后不知道是不是会整得更晚.于是入手这本<家庭作业的迷思>,认真读读.请特别注意,不要买书叫&q ...
- MongoDB 操作手冊CRUD查询指针
枚举遍历指针 概述 前面已经讲过,db.collection.find()假设没有指定给一个var声明的变量.将自己主动枚举前20条记录. 手动枚举指针 在mongo控制台中.将查询赋给一个var声明 ...
- 创建RDD的方式
创建RDD的方法: JavaRDD<String> lines = sc.textFile("hdfs://spark1:9000/spark.txt"); Jav ...
- BZOJ 1025: [SCOI2009]游戏( 背包dp )
显然题目要求长度为n的置换中各个循环长度的lcm有多少种情况. 判断一个数m是否是满足题意的lcm. m = ∏ piai, 当∑piai ≤ n时是满足题意的. 最简单我们令循环长度分别为piai, ...
- [转]linux下iftop工具的安装与使用详解(图文)——实时的网络流量,监控TCP/IP连接(单机)
原文链接:http://www.jbxue.com/LINUXjishu/10735.html 在linux中监控系统资源.进程.内存占用等信息,可以使用top命令.查看网络状态可以使用netstat ...