title: poj-2777线段树刷题

date: 2018-10-16 20:01:07

tags:

  • acm
  • 刷题

    categories:
  • ACM-线段树

概述

这道题是一道线段树的染色问题,,,,

做了几道染色的问题,,好像渐渐的熟悉的染色问题的大概的解体思路,,,不再像刚开始做的时候那样一脸懵逼,,,只能去翻博客去看别人的思路,,,好歹这次没有看别人博客自己写出来,,,(除了一些细节没考虑到wa的一发,,,,逃

分析与思路

题面

大概的意思就是给一个区间1~n,,,然后最多有30种颜色,,,q次操作对[l,r]这个区间染色,,,中间有一些询问区间[l , r]内一共有几种颜色,,,

分析

  • 首先考虑线段树所维护的东西,,,染色问题大多是维护每个区间的颜色,,,对于这道题就是维护该区间的颜色的种类,,,然后对于每两个子区间都要向上合并颜色的种类,,,,相同的忽略一边的不同的就加一,,,求出父区间的种类数,,,,也就是更新操作,,,询问呢就是再询问的区间[L , R]里的话直接返沪这个区间的种类数,,,跨区间的递归继续向下查找,,,

  • 然后考虑颜色,,,最多一共有30种,,,如果每个区间都用一个30长的数组col[30]去存放每种颜色的种类,,col[i] == 1表示这个区间有第i种颜色反之没有的话,,,空间消耗较大,,,而且相关的操作也不好表达,,,因为每个区间的每种颜色只有两种情况,,,有或没有,,,所以选择状态压缩来实现比较好,,,这里我想到前段时间看到的一个很好的状压stl--bitset,,,优点有很多,,,比如说:他就像bool数组一样但是每一位只占1bit,,,而且有很多成员函数很方便,,,具体的食用方法戳这里

  • 另一个需要注意的是,,,线段树要选择lazy的,,,还有一些细节:

    区间的合并需要操作,,,包括更新和询问

    初始时所有区间都为1

    当整个区间都染色时是将该区间的node[rt].col为c,,,而不是或

    还有一个最坑人的,,,,题目不保证l <= r,,,(poj上的题都这样的吗,,噗噗噗噗

代码

这次又写成node结构体实现的了,,,还是因为这个理解起来很容易,,,,

但是缺点是占用的空间比较大,,,,

下次再写这道题的时候要换用另一种裸的了QAQ

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <bitset>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define aaa cout << node[rt].col << endl;
const int maxn = 1e5 + 10;
struct node
{
int l;
int r;
int laz;
bitset<30> col; //bitset,,表示该区间的颜色的种类
}node[maxn << 2]; void build(int rt , int l , int r)
{
node[rt].l = l;
node[rt].r = r;
node[rt].laz = 0;
node[rt].col = 0;
if(node[rt].l == node[rt].r)
{
node[rt].col = 1; //初始化为1
return;
}
int mid = (node[rt].l + node[rt].r) >> 1;
build(lson);
build(rson);
node[rt].col = node[rt << 1].col | node[rt << 1 | 1].col; //记得更新,,用或
return;
}
void pushdown(int rt)
{
if(node[rt].laz)
{
bitset<30> t;
t.set(node[rt].laz - 1); //标记为laz那一个颜色
node[rt << 1].col = t; //不是或操作
node[rt << 1 | 1].col = t; node[rt << 1].laz = node[rt].laz;
node[rt << 1 | 1].laz = node[rt].laz; node[rt].laz = 0;
}
}
void update(int rt , int L , int R , int c)
{
if(L <= node[rt].l && node[rt].r <= R)
{
bitset<30> t;
t.set(c - 1);
node[rt].col = t; //同上
node[rt].laz = c;
return;
}
pushdown(rt);
int mid = (node[rt].l + node[rt].r) >> 1;
if(L <= mid) update(rt << 1 , L , R , c);
if(R > mid) update(rt << 1 | 1 , L , R , c);
node[rt].col = node[rt << 1].col | node[rt << 1 | 1].col;
return;
}
bitset<30> query(int rt , int L , int R)
{
//对每两个子区间合并,,,同样是或操作,,,所以函数返回值类型为bitset<30>
//最后的答案为 返回值.count()
if(L <= node[rt].l && node[rt].r <= R)
{
return node[rt].col;
}
pushdown(rt);
int mid = (node[rt].l + node[rt].r) >> 1; bitset<30> ans (0);
if(L <= mid) ans |= query(rt << 1 , L , R); //用或合并
if(R > mid) ans |= query(rt << 1 | 1 , L , R);
//cout << ans << endl;
return ans;
}
int main()
{
int n , t , m;
while(scanf("%d%d%d" , &n , &t , &m) != EOF)
{
build(1 , 1 , n);
while(m--)
{
char q;
scanf(" %c" , &q);
if(q == 'C')
{
int l , r , c;
scanf("%d%d%d", &l , &r , &c);
if(l > r) swap(l , r); //巨坑!!!!
update(1 , l , r , c);
}
else
{
int l , r;
scanf("%d%d" , &l , &r);
if(l > r) swap(l , r);
printf("%d\n" , query(1 , l , r).count());
}
}
}
}

感想

算了不说了QAQ

(end)

poj-2777线段树刷题的更多相关文章

  1. POJ 2777 线段树基础题

    题意: 给你一个长度为N的线段数,一开始每个树的颜色都是1,然后有2个操作. 第一个操作,将区间[a , b ]的颜色换成c. 第二个操作,输出区间[a , b ]不同颜色的总数. 直接线段树搞之.不 ...

  2. hdu-5023线段树刷题

    title: hdu-5023线段树刷题 date: 2018-10-18 13:32:13 tags: acm 刷题 categories: ACM-线段树 概述 这道题和上次做的那道染色问题一样, ...

  3. hdu-1540线段树刷题

    title: hdu-1540线段树刷题 date: 2018-10-18 19:55:21 tags: acm 刷题 categories: ACM-线段树 概述 哇,,,这道线段树的题可以说是到目 ...

  4. zoj-1610线段树刷题

    title: zoj-1610线段树刷题 date: 2018-10-16 16:49:47 tags: acm 刷题 categories: ACM-线段树 概述 这道题是一道简单的线段树区间染色问 ...

  5. POJ 3468 线段树裸题

    这些天一直在看线段树,因为临近期末,所以看得断断续续,弄得有些知识点没能理解得很透切,但我也知道不能钻牛角尖,所以配合着刷题来加深理解. 然后,这是线段树裸题,而且是最简单的区间增加与查询,我参考了A ...

  6. poj 2777(线段树+lazy思想) 小小粉刷匠

    http://poj.org/problem?id=2777 题目大意 涂颜色,输入长度,颜色总数,涂颜色次数,初始颜色都为1,然后当输入为C的时候将x到y涂为颜色z,输入为Q的时候输出x到y的颜色总 ...

  7. POJ 2777——线段树Lazy的重要性

    POJ 2777 Count Color --线段树Lazy的重要性 原题 链接:http://poj.org/problem?id=2777 Count Color Time Limit: 1000 ...

  8. POJ - 3264 线段树模板题 询问区间最大最小值

    这是线段树的一个模板题,给出一串数字,然后询问区间的最大最小值. 这个其实很好办,只需把线段树的节点给出两个权值,一个是区间的最小值,一个是区间的最大值,初始化为负无穷和正无穷,然后通过不断地输入节点 ...

  9. poj 2777线段树应用

    敲了n遍....RE愉快的debug了一晚上...发现把#define maxn = 100000 + 10 改成 #define maxn = 100010 就过了....感受一下我呵呵哒的表情.. ...

随机推荐

  1. 【实操笔记】MySQL主从同步功能实现

    写在前边: 这两天来了个需求,配置部署两台服务器的MySQL数据同步,折腾了两天查了很多相关资料,一直连不上,后来发现其实是数据库授权的ip有问题,我们用的服务器是机房中的虚拟机加上反向代理出来的,坑 ...

  2. HDU 1019 Least Common Multiple GCD

    解题报告:求多个数的最小公倍数,其实还是一样,只需要一个一个求就行了,先将答案初始化为1,然后让这个数依次跟其他的每个数进行求最小公倍数,最后求出来的就是所有的数的最小公倍数.也就是多次GCD. #i ...

  3. JS踩过的坑

    一:DOM对象的查找 DOM的查找到的对象,除byID的之外,返回的都是一个数组,并不是DOM对象无法调用DOM对象的方法. 通过id查找: 因为id在一个HTML文件中唯一,因此查找到的只会是一个元 ...

  4. 2016.07.13-vector<vector<int>>应用2——Two Sum扩展

    收获: vector<vector<int> >res,不能直接用res[j].push_back(number),因为res[j]是空的,没有初始化 可以先定义 vector ...

  5. perl6 Net::HTTP 发送任意 url 请求例子

    只做个笔记, 用 HTTP::UserAgent 的话, url 中有特殊点的符号会请求不了, 用 Net::HTTP 能很好的发送请求. use Net::HTTP::GET; my $url = ...

  6. linux nginx大量TIME_WAIT的解决办法--转

    netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' TIME_WAIT 8535 CLOSE_WAIT 5 FIN ...

  7. 一步一步搭建 oracle 11gR2 rac + dg 之前传 (一)【转】

    一步一步在RHEL6.5+VMware Workstation 10上搭建 oracle 11gR2 rac + dg  之前传 (一) 转自 一步一步搭建 oracle 11gR2 rac + dg ...

  8. error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

    一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如: tmux: error while loading shared libraries: libevent-1.4.s ...

  9. MongoDB官方文档结构

    本文展示MongoDB 3.6.4.0的官方Server文档的结构图——一眼可见完整的知识脉络图.不过,MongoDB除了Server的文档外,还有DRIVERS.CLOUD.TOOLS.DUIDES ...

  10. Nginx - buffer缓冲区部分

    目录- 1. 前言- 2. 指令- 3. 原理及总结 1. 前言 关于缓冲,主要是合理设置缓冲区大小,尽量避免缓冲到硬盘 2. 指令 proxy_buffering 说明:proxy_bufferin ...