P1558 色板游戏

题目背景

阿宝上学了,今天老师拿来了一块很长的涂色板。

题目描述

色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格。并从左到右标记为1, 2, ... L。

现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:

"C A B C" 指在A到 B 号方格中涂上颜色 C。

"P A B" 指老师的提问:A到 B号方格中有几种颜色。

学校的颜料盒中一共有 T 种颜料。为简便起见,我们把他们标记为 1, 2, ... T. 开始时色板上原有的颜色就为1号色。 面对如此复杂的问题,阿宝向你求助,你能帮助他吗?

输入输出格式

输入格式:

第一行有3个整数 L (1 <= L <= 100000), T (1 <= T <= 30) 和 O (1 <= O <= 100000)。 在这里O表示事件数。

接下来 O 行, 每行以 "C A B C" 或 "P A B" 得形式表示所要做的事情(这里 A, B, C 为整数, 可能A> B,这样的话需要你交换A和B)

输出格式:

对于老师的提问,做出相应的回答。每行一个整数。


错误日志: 1.第一次交了暴力 \(30\) 颗线段树 \(MLE\) 2. 后面换了个思路却忘记了题目有坑(以粗体标出)


Solution

这里要说一下 \(bitset\) 这个宝贝了(快 \(noip\) 了, 多运用 \(STL\) 节省时间)

支持位数很大的二进制运算, 自带压缩, 运算较快

简单来说就是一个可以有很多位的状压利器

这题很明显线段树, 用了 \(bitset\) 做状态说明: 第 \(i\) 位 为 \(1\) 代表此区间有这个颜色, 为 \(0\) 则没有

上传更新时使用或运算, 表示取并集(bitset很大一用处就是取状态很多的并集, 十分方便)

这是满足分配律的

修改打懒标记记录区间颜色, 改区间状态直接把 \(bitset\) 赋值为 \(0\) 然后确定颜色位修改为 \(1\) 即可

附: \(bitset\) 用法

  1. 声明nbitset : bitset<n> b;
  2. 全部赋值为0 : b.reset();
  3. 1 : b.set();
  4. 对第i位操作 : b[i] = 1/0;
  5. 一个bitset1的个数 : num = b.count();

Code

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<bitset>
  5. typedef long long LL;
  6. using namespace std;
  7. int RD(){
  8. int out = 0,flag = 1;char c = getchar();
  9. while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
  10. while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
  11. return flag * out;
  12. }
  13. const int maxn = 100019;
  14. int num, numc, na;
  15. #define lid (id << 1)
  16. #define rid (id << 1) | 1
  17. struct seg_tree{
  18. int l, r;
  19. int lazy;
  20. bitset<39>b;
  21. }tree[maxn << 2];
  22. void pushup(int id){
  23. tree[id].b = tree[lid].b | tree[rid].b;
  24. }
  25. void pushdown(int id){
  26. if(tree[id].lazy){
  27. int c = tree[id].lazy;
  28. tree[lid].b.reset(), tree[rid].b.reset();
  29. tree[lid].b[c] = 1, tree[rid].b[c] = 1;
  30. tree[lid].lazy = tree[rid].lazy = c;
  31. tree[id].lazy = 0;
  32. }
  33. }
  34. void build(int id, int l, int r){
  35. tree[id].l = l, tree[id].r = r;
  36. if(l == r){
  37. tree[id].b[1] = 1;
  38. return ;
  39. }
  40. int mid = (l + r) >> 1;
  41. build(lid, l, mid), build(rid, mid + 1, r);
  42. pushup(id);
  43. }
  44. void update(int id, int val, int l, int r){
  45. pushdown(id);
  46. if(tree[id].l == l && tree[id].r == r){
  47. tree[id].b.reset();
  48. tree[id].b[val] = 1;
  49. tree[id].lazy = val;
  50. return ;
  51. }
  52. int mid = (tree[id].l + tree[id].r) >> 1;
  53. if(mid < l)update(rid, val, l, r);
  54. else if(mid >= r)update(lid, val, l, r);
  55. else update(lid, val, l, mid), update(rid, val, mid + 1, r);
  56. pushup(id);
  57. }
  58. bitset<39> query(int id, int l, int r){
  59. pushdown(id);
  60. if(tree[id].l == l && tree[id].r == r){
  61. return tree[id].b;
  62. }
  63. int mid = (tree[id].l + tree[id].r) >> 1;
  64. if(mid < l)return query(rid, l, r);
  65. else if(mid >= r)return query(lid, l, r);
  66. else return query(lid, l, mid) | query(rid, mid + 1, r);
  67. }
  68. int main(){
  69. num = RD();numc = RD();na = RD();
  70. build(1, 1, num);
  71. char cmd;
  72. for(int i = 1;i <= na;i++){
  73. cin>>cmd;
  74. int l = RD(), r = RD();
  75. if(l > r)swap(l, r);
  76. if(cmd == 'C'){
  77. int x = RD();
  78. update(1, x, l, r);
  79. }
  80. else printf("%d\n", (int)query(1, l, r).count());
  81. }
  82. return 0;
  83. }

P1558 色板游戏的更多相关文章

  1. P1558 色板游戏 状压线段树

    P1558 色板游戏 状压线段树 题面 洛谷P1558 每次不同颜色覆盖一段区间,每次询问一段区间有多少种颜色 因为颜色数\(T\)很小,使用二进制表示状态当前区间有那些颜色,二进制第\(i\)位表示 ...

  2. 洛谷P1558 色板游戏 [线段树]

    题目传送门 色板游戏 题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, .. ...

  3. 【luogu P1558 色板游戏】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1558 我知道三十棵线段树很暴力,可是我们可以状压啊. 颜色最多30,不会爆int 另外 吐槽评测机 #inc ...

  4. 洛谷P1558 色板游戏

    题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, ... L.现在色板上只有 ...

  5. 线段树(压位)luogu P1558色板游戏

    题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, ... L. 现在色板上只 ...

  6. Luogu P1558 色板游戏【线段树/状态压缩】By cellur925

    题目传送门 今天非常想再看一遍霸王别姬想不进去题于是开始刷数据结构 注意到至多只有\(30\)种颜色,啊啊啊啊我一开始竟然想的不是状态压缩而是在线段树中存一个30大小的数组,这样每次更新的时候暴力循环 ...

  7. P1558 色板游戏 线段树+二进制状压

    好,这个想法是我想拿去做HH的项链的.但是那个颜色有十万种...直接爆. 做这个倒是so easy 被两个地方坑了.1,a,b可能大小相反. 2,ask之前要down一波,我没down就挂了..... ...

  8. Luogu P1558 色板游戏

    (此题与POJ2777重题) 为了加深对线段树的记忆,然后开始搞这道题. TM的WA了一下午就是发现x可能大于y(然而题目里说的还很清楚,我TM没看见) 这道题只需要在线段树的板子上改一些地方就可以了 ...

  9. 洛谷 P1558 色板游戏

    洛谷 题解里面好像都是压位什么的, 身为蒟蒻的我真的不会, 所以就来谈谈我的30颗线段树蠢方法吧! 这题初看没有头绪. 然后发现颜色范围好像只有30: 所以,我就想到一种\(sao\)操作,搞30颗线 ...

随机推荐

  1. 第二阶段Sprint2

    昨天:讨论冲刺阶段,目标,任务认领 今天:查看资料,开始视频录制部分的代码实现 遇到的问题:不能暂停后继续录制,只能直接结束

  2. java的小学生四则运算

    import java.awt.*; import java.awt.event.*; import java.io.FileNotFoundException; import java.io.IOE ...

  3. java 对象和基本数据类型 “==”区别

    “==”比较的是地址,牢记.1.对象.integer 是对象 Integer i1 = 20; Integer i2 = 20 ; System.out.println(i1 == i2); // t ...

  4. Maya学习笔记

    软件: Maya 2016 : 参考教材: Maya 2016 中文版标准教程 ; 改变视图颜色 [窗口]|[设置/首项选择]|[颜色设置]|[3D视图]: 观察视图 旋转视图 Alt + 鼠标左键 ...

  5. systemct管理服务命令

    systemctl管理服务的启动,重启,停止,重载,查看状态的命令 Systcinit命令(红帽RHEL6系统) Systemctl命令(红帽RHEL7系统) 作用 service  foo star ...

  6. vue-Slot分发内容

    ①概述: 简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示.不显示.在哪个地方显示.如何显示,就是slot分发负责的活. ②默认情况下 父组件在子组件内套的内容,是不显示的. 例如 ...

  7. mybatis的mapper参数传递

    简单参数传递 简单参数传递是指: 传递单个基本类型参数,数字类型.String 传递多个基本类型参数 parameterType 属性可以省略: 传递单个基本类型参数  SQL语句中参数的引用名称并不 ...

  8. DAY4-Python学习笔记

    1.XML: 操作XML有两种方法:DOM和SAX DOM:把整个XML读入内存,解析为树,因此占用内存大,解析慢,优点是可以任意遍历树的节点 SAX:是流模式,边读边解析,占用内存小,解析快,缺点是 ...

  9. vue自动路由-单页面项目(非build时构建)

    博客中自动路由的原理? 答:简单点说,就是在请求页面时,根据url进行动态添加路由. 与其它自动路由博客的区别? 目前网上的博客,一般都是在build的时候进行动态路由添加,而本博客,采用的是在获得u ...

  10. python 求两个时间差

    def timeInterval(self): today = datetime.date.today() print today modifiedTime = os.stat(filename).s ...