题目链接


题目大意

  • \(~~\)给出一棵 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. 手把手教你怎么将linux的一个函数性能搞奔溃

    static struct fib_table *fib_empty_table(struct net *net){    u32 id;    for (id = 1; id <= RT_TA ...

  2. io几乎没有,iowait却很高

    遇到如下一种情况: top - 09:43:03 up 2 days, 22:48, 9 users, load average: 133.19, 132.60, 132.32 Tasks: 767 ...

  3. jQuery使用case记录

    添加元素/内容追加等 元素内: append() - 在被选元素的结尾插入内容 prepend() - 在被选元素的开头插入内容 元素外: after() - 在被选元素之后插入内容 before() ...

  4. [开源内卷] .NET 定时任务 -- FreeScheduler 支持 cron、持久化、可变定时设置

    前言 卷了,卷了,卷了,最近太卷...这篇文章写了好几天了,由于同类型文章太多,排期到今天发布.实在不想卷,得罪了!各位定时任务开源大佬们! .NET 定时组件生态实在太强大了,写下此文只希望能供大家 ...

  5. 全链路追踪体验—最简陋TraceId的生成

    对于后端开发来说,排查问题是常有的事情.而排查问题时最常用的就是看日志,看一次调用中经过了哪些系统,是那个系统出问题了.这就需要业务日志中关联调用链的TraceId信息,从而在应用出现问题时,能够通过 ...

  6. 【JavaWeb】学习路径1-背景

    JavaWeb系列也是一个非常庞大的系列,主要分为五个部分讲解: HTML JSP和Servlet CSS的讲解 JavaScrip的讲解 jQuery框架的讲解 学习完上述内容后,就能够基本了解一个 ...

  7. 【Java】学习路径33-在IDEA中使用junit单元测试运行单个方法

    首先在菜单找到 文件-项目结构 项目设置-库-"+" 选择Java 找到IDEA安装目录,打开lib/junit4.jar 的jar包,然后打开即可. 然后选择确定. 然后再项目中 ...

  8. Java代码审计之不安全的Java代码

    Java代码审计之不安全的Java代码 ​ 在打靶场的同时,需要想一下如果你是开发人员你会怎样去防御这种漏洞,而作为攻击方你又怎么去绕过开发人员的防御. 环境搭建 https://github.com ...

  9. 邮箱的代理发送Send as权限不生效

     邮箱的代理发送Sendas权限不生效 最近,有需求为用户添加其它邮箱的代理发送Sendas权限.在Exchange的管理单元里添加完毕后,发现没有效果,客户端提示你没有权限以用户的名义发送邮件 ...

  10. Kubernetes(k8s)通过环境变量将 Pod 信息呈现给容器

    Downward API 有两种方式可以将 Pod 和 Container 字段呈现给运行中的容器: 环境变量 卷文件 这两种呈现 Pod 和 Container 字段的方式统称为 Downward ...