题目链接:  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

代码:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define MAX 110000
  5. #define MID(a,b) (a+b)>>1
  6. #define L(a) a<<1
  7. #define R(a) (a<<1|1)
  8. typedef struct{
  9. int left,right;
  10. int add,num;
  11. }Node;
  12. Node Tree[MAX<<2];
  13. 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};
  14. //二进制表示第几种颜色,如8表示第四种颜色:1000
  15. int Lowbit(int x) //剔除x二进制中最后面一个1
  16. {
  17. return x&(-x);
  18. }
  19.  
  20. void Build(int t,int l,int r) //以1为根结点,建立[l,r]的线段树
  21. {
  22. Tree[t].left=l,Tree[t].right=r,Tree[t].add=0; //***
  23. if(l==r)
  24. {
  25. Tree[t].num=1;
  26. return ;
  27. }
  28. int mid=MID(Tree[t].left,Tree[t].right);
  29. Build(L(t),l,mid);
  30. Build(R(t),mid+1,r);
  31. Tree[t].num=(Tree[L(t)].num|Tree[R(t)].num);
  32. }
  33.  
  34. void Insert(int t,int l,int r,int m) //向区间[l,r]涂颜色
  35. {
  36. if(Tree[t].left==l&&Tree[t].right==r)
  37. {
  38. Tree[t].add=m;
  39. Tree[t].num=m;
  40. return ;
  41. }
  42. if(Tree[t].add!=0) //lazy标记
  43. {
  44. Tree[L(t)].num=Tree[t].add;
  45. Tree[R(t)].num=Tree[t].add;
  46. Tree[L(t)].add=Tree[t].add;
  47. Tree[R(t)].add=Tree[t].add;
  48. Tree[t].add=0;
  49. }
  50. int mid=MID(Tree[t].left,Tree[t].right);
  51. if(l>mid)
  52. {
  53. Insert(R(t),l,r,m);
  54. }
  55. else if(r<=mid)
  56. {
  57. Insert(L(t),l,r,m);
  58. }
  59. else
  60. {
  61. Insert(L(t),l,mid,m);
  62. Insert(R(t),mid+1,r,m);
  63. }
  64. Tree[t].num=(Tree[L(t)].num|Tree[R(t)].num); //***
  65. }
  66.  
  67. int Query(int t,int l,int r)
  68. {
  69. if(Tree[t].left==l&&Tree[t].right==r)
  70. {
  71. return Tree[t].num;
  72. }
  73. if(Tree[t].add!=0) //区间插入的lazy思想
  74. {
  75. Tree[L(t)].num=Tree[t].add;
  76. Tree[R(t)].num=Tree[t].add;
  77. Tree[L(t)].add=Tree[t].add;
  78. Tree[R(t)].add=Tree[t].add;
  79. Tree[t].add=0;
  80. }
  81. int mid=MID(Tree[t].left,Tree[t].right);
  82. if(l>mid)
  83. {
  84. return Query(R(t),l,r);
  85. }
  86. else if(r<=mid)
  87. {
  88. return Query(L(t),l,r);
  89. }
  90. else
  91. {
  92. return Query(L(t),l,mid)|Query(R(t),mid+1,r); //***是|,不是+!!!
  93. }
  94. Tree[t].num=(Tree[L(t)].num|Tree[R(t)].num);
  95. }
  96.  
  97. int main()
  98. {
  99. char ch;
  100. int n,col,q,i,k,a,b,c;
  101. int m;
  102. while(scanf("%d%d%d",&n,&col,&q)!=EOF)
  103. {
  104. memset(Tree,0,sizeof(Tree)); //初始化
  105. Build(1,1,n); //建树
  106. for(i=0;i<q;i++)
  107. {
  108. getchar();
  109. scanf("%c",&ch);
  110. if(ch=='P')
  111. {
  112. scanf("%d%d",&a,&b);
  113. k=0;
  114. if(a>b)
  115. m=Query(1,b,a);
  116. else
  117. m=Query(1,a,b);
  118. while(m>0) //计算查询后的结果的二进制表示右多少个1
  119. {
  120. k++;
  121. m-=Lowbit(m);
  122. }
  123. printf("%d\n",k);
  124. }
  125. else
  126. {
  127. scanf("%d%d%d",&a,&b,&c);
  128. if(a>b)
  129. Insert(1,b,a,Color[c]);
  130. else
  131. Insert(1,a,b,Color[c]);
  132. }
  133. }
  134. }
  135. return 0;
  136. }

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

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. mac 系统开发android,真机调试解决方式(无数的坑之后吐血总结)

    近期学习android开发,安装了ADT开发环境之后,启动模拟器,慢的要死啊,全然不如苹果的好用,没法,自己买个android手机,准备联机调试程序.没想到在这个过程中,遇到了好多的坑,作为一个新人, ...

  2. C#中的DataTable简单使用Merge

    //不同结构的DataTable追加第二个DataTable数据在对应行后的 简单使用//不同结构的DataTable追加在行后面的合并 DataTable dt = new DataTable(); ...

  3. 20150706 js之定时器

    对应智能社:09 定时器的使用 开启定时器: setInterval(xxx(),1000);//间隔型 第一个参数为函数,第二个为时间,单位为毫秒 setTimeout(xxx(),1000);// ...

  4. Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)

    Qt线程间共享数据主要有两种方式: 使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的: 使用singal/slot机制,把数据 ...

  5. 正则表达式验证数字、汉字、电话号码,email,整数,浮点数

    验证数字的正则表达式集 验证数字:^[0-9]*$验证n位的数字:^\d{n}$验证至少n位数字:^\d{n,}$验证m-n位的数字:^\d{m,n}$验证零和非零开头的数字:^(0|[1-9][0- ...

  6. 作业还是作孽?——Leo鉴书79

    中国孩子,尤其是城市孩子课业过重是个不争的事实.儿子上幼儿园的作业已经能做到8点多了,上小学之后不知道是不是会整得更晚.于是入手这本<家庭作业的迷思>,认真读读.请特别注意,不要买书叫&q ...

  7. MongoDB 操作手冊CRUD查询指针

    枚举遍历指针 概述 前面已经讲过,db.collection.find()假设没有指定给一个var声明的变量.将自己主动枚举前20条记录. 手动枚举指针 在mongo控制台中.将查询赋给一个var声明 ...

  8. 创建RDD的方式

    创建RDD的方法: JavaRDD<String> lines = sc.textFile("hdfs://spark1:9000/spark.txt");   Jav ...

  9. BZOJ 1025: [SCOI2009]游戏( 背包dp )

    显然题目要求长度为n的置换中各个循环长度的lcm有多少种情况. 判断一个数m是否是满足题意的lcm. m = ∏ piai, 当∑piai ≤ n时是满足题意的. 最简单我们令循环长度分别为piai, ...

  10. [转]linux下iftop工具的安装与使用详解(图文)——实时的网络流量,监控TCP/IP连接(单机)

    原文链接:http://www.jbxue.com/LINUXjishu/10735.html 在linux中监控系统资源.进程.内存占用等信息,可以使用top命令.查看网络状态可以使用netstat ...