题目链接


题目大意

  • \(~~\)给出一棵 nn 个节点的树,根节点为 11。每个节点上有一种颜色 c\(_{i}\) 和m 次操作。操作有两种:

    \(~~~~\) 1. 1\(~\)u\(~\)c:将以\(~\)u\(~\)为根的子树上的所有节点的颜色改为\(~\)c。

    \(~~~~\) 2. 2\(~\)u\(~\):询问以\(~\)u\(~\)为根的子树上的所有节点的颜色数量。
  • \(~\) 1≤n,m≤4×10\(^{5}\)$~~$1≤c≤60

题目思路

\(~~\)因为我们注意到颜色c的取值范围只有[1,60],所以我们考虑状态压缩,将颜色映射到二进制位上,每次维护颜色的时候直接按位或即可维护该区间内有无这种颜色

\(~~\)另一个问题是因为是树形结构,如果想用线段树来维护,就需要我们转化为线性结构,所以我们选择用dfs序来转换,保存每个节点的l[u],r[u]表示以\(~\)u\(~\)为根的

节点所能到达的最远的点,也就是他整个子树区间[\(~\)l[u]\(~\),\(~\)r[u]\(~\)]

\(~~\)~~~然后这个问题就基本解决了~~~

\(~~\)不过需要注意的是,在下方lazy标记的时候,因为这里的0,1分别表示两种状态,所以在初始化没有标记的状态时要避免这个影响,将其初始化为-1或者其他非0,1的数


# include<bits/stdc++.h>
using namespace std;
#define endl "\n"
# define int long long
# define ls u<<1
# define rs u<<1|1
const int N = 4e5 + 10;
int a[N], p, n, m;
vector<int> g[N];
int pos[N];
struct segtree {
int sum[4 * N], lazy[4 * N], ans;
segtree() {
ans = 0;
memset(lazy, 0, sizeof lazy);
memset(sum, 0, sizeof lazy);
}
void pushup(int u) //维护区间颜色
{
sum[u] = sum[ls] | sum[rs];
} void build(int u, int l, int r) {
if (l == r) {
sum[u] = 1ll << a[pos[l]];
return;
}
int mid = l + r >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(u);
} void pushdown(int u) {
if (lazy[u]) {
lazy[ls] = lazy[rs] = lazy[u];
sum[rs] = sum[ls] = 1ll << lazy[u];
lazy[u] = 0;
} } void modify(int u, int l, int r, int L, int R, int c) {
if (L <= l && r <= R) {
sum[u] = 1ll << c;
lazy[u] = c;
return;
}
int mid = l + r >> 1;
pushdown(u);
if (L <= mid) modify(ls, l, mid, L, R, c);
if (mid + 1 <= R) modify(rs, mid + 1, r, L, R, c);
pushup(u);
} int query(int u, int l, int r, int L, int R) {
if (l >= L && r <= R) {
return sum[u];
}
pushdown(u);
int mid = l + r >> 1;
int val = 0;
if (L <= mid) val |= query(ls, l, mid, L, R);
if (R > mid) val |= query(rs, mid + 1, r, L, R);
pushup(u);
return val; }
} tr;
int l[N], r[N], tot;
void dfs(int u, int fa) //dfs序
{
l[u] = ++tot;
pos[tot] = u;
for (auto v : g[u]) {
if (v == fa) continue;
dfs(v, u);
}
r[u] = tot;
}
int cnt(int val) //计算区间有多少种颜色即查询二进制位有多少个1
{
int ans = 0;
while (val) {
ans += val & 1;
val >>= 1;
}
return ans;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = 1; i < n; ++i) {
int a, b;
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1, 0);
tr.build(1, 1, n);
while (m--) {
int op, x;
cin >> op >> x;
if (op == 1) {
int c;
cin >> c;
tr.modify(1, 1, n, l[x], r[x], c);
} else {
cout << cnt(tr.query(1, 1, n, l[x], r[x])) << endl;
}
} return 0;
}

CF620E New Year Tree(树形+dfs序+线段树+状态压缩)的更多相关文章

  1. CodeForces 620E"New Year Tree"(DFS序+线段树+状态压缩)

    传送门 •题意 给你一颗 n 个节点的树,每个节点被染上了颜色: 有 m 次操作,每次操作的类型有两种 1 v c : 将以 v 为根的子树的结点全部涂成 c 2 v : 询问以 v 为根的子树的结点 ...

  2. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  3. 【cf343】D. Water Tree(dfs序+线段树)

    传送门 题意: 给出一个以\(1\)为根的有根树,起始每个结点都为\(0\),现在有三种操作: 1.将\(v\)及\(v\)的子树都置为\(1\): 2.将\(v\)及其所有的祖先都置为\(0\): ...

  4. Codeforces 620E New Year Tree(DFS序 + 线段树)

    题目大概说给一棵树,树上结点都有颜色(1到60),进行下面两个操作:把某结点为根的子树染成某一颜色.询问某结点为根的子树有多少种颜色. 子树,显然DFS序,把子树结点映射到连续的区间.而注意到颜色60 ...

  5. POJ3321/Apple tree/(DFS序+线段树)

    题目链接 Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9692 Accepted: 3217 Descr ...

  6. CoderForces343D:Water Tree(dfs序+线段树&&特殊处理)

    Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a res ...

  7. POJ 3321 Apple Tree(DFS序+线段树单点修改区间查询)

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25904   Accepted: 7682 Descr ...

  8. New Year Tree 【DFS序+线段树区间查询修改+二进制保存状态】

    题目链接[http://codeforces.com/problemset/problem/620/E] 题意:给出n个数,每个数有一个初始的颜色.由这n个数组成一颗树.有两种操作1.将以节点u为根的 ...

  9. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

随机推荐

  1. ubuntu 连不上网怎么办?

    [简洁版本] ctrl+alt+delete -> 任务管理器 ->"服务"选项卡 -> 运行"VMnet""VMware" ...

  2. Qt Q_OBJECT编译问题

    编译问题 添加Q_OBJECT后需要qmake 多重继承 添加了Q_ENUM之类的宏,就需要Q_OBJECT 添加了Q_OBJECT,就需要类继承自QObject 如果有多重继承关系,QObject一 ...

  3. Prometheus教程

    Prometheus介绍 主要特征 使用时间序列数据(tsdb)的多维度数据模型 灵活的查询语言(PromQL) 不依赖分布式存储,单个节点是自主的 通过http请求拉取(pull)时间序列数据(ts ...

  4. SpringCache的基本使用

    SpringCache SpringCache是一个框架,实现了基于注解的缓存功能.SpringCache提供了一层抽象,底层可以切换不同的cache实现.具体是通过CacheManager接口来统一 ...

  5. Docker网络讲解 及实验redis集群部署

    理解docker0 准备工作:清空所有的容器,清空所有的镜像 docker rm -f $(docker ps -a -q) # 删除所有容器 docker rmi -f $(docker image ...

  6. Linux之LVM逻辑卷管理

    LVM逻辑卷管理 LVM机制:PV物理卷,VG卷组,LV逻辑卷. --功能-- --物理卷管理-- --卷组管理-- --逻辑卷管理-- create(建立) pvcreate vgcreate lv ...

  7. KingbaseES应对表年龄增长过快导致事务回卷

    背景 前几天碰到这样一个场景,在KingbaseES数据库当作数据同步节点.其特点是接收过来的数据量巨大,其更新超级频繁,最大的数据库达到6TB.这还不是主要的,主要导致问题发生原因是同步数据库有很多 ...

  8. KingbaseES 全局索引是否因为DDL操作而变为Unusable ?

    前言 Oracle 在对分区做DDL操作时,会使分区全局索引失效,需要加上关键字update global indexes.KingbaseES 同样支持全局索引.那么,如果对分区表进行DDL操作,那 ...

  9. KingbaseES 数据库软件卸载

    关键字: KingbaseES.卸载   一.安装后检查 在安装完成后,可以通过以下几种方式进行安装正确性验证: 1. 查看安装日志,确认没有错误记录; 2. 查看开始菜单: 查看应用程序菜单中是否安 ...

  10. logstash接受checkpoint防火墙日志并用ruby分词

    直接上logstahs配置文件 input{ syslog{ type => "syslog" port => 514 } } filter { grok { matc ...