CF620E New Year Tree(树形+dfs序+线段树+状态压缩)
题目链接
题目大意
- \(~~\)给出一棵 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序+线段树+状态压缩)的更多相关文章
- CodeForces 620E"New Year Tree"(DFS序+线段树+状态压缩)
		传送门 •题意 给你一颗 n 个节点的树,每个节点被染上了颜色: 有 m 次操作,每次操作的类型有两种 1 v c : 将以 v 为根的子树的结点全部涂成 c 2 v : 询问以 v 为根的子树的结点 ... 
- Codeforces 343D Water Tree(DFS序 + 线段树)
		题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ... 
- 【cf343】D. Water Tree(dfs序+线段树)
		传送门 题意: 给出一个以\(1\)为根的有根树,起始每个结点都为\(0\),现在有三种操作: 1.将\(v\)及\(v\)的子树都置为\(1\): 2.将\(v\)及其所有的祖先都置为\(0\): ... 
- Codeforces 620E New Year Tree(DFS序 + 线段树)
		题目大概说给一棵树,树上结点都有颜色(1到60),进行下面两个操作:把某结点为根的子树染成某一颜色.询问某结点为根的子树有多少种颜色. 子树,显然DFS序,把子树结点映射到连续的区间.而注意到颜色60 ... 
- POJ3321/Apple tree/(DFS序+线段树)
		题目链接 Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9692 Accepted: 3217 Descr ... 
- CoderForces343D:Water Tree(dfs序+线段树&&特殊处理)
		Mad scientist Mike has constructed a rooted tree, which consists of n vertices. Each vertex is a res ... 
- POJ 3321 Apple Tree(DFS序+线段树单点修改区间查询)
		Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 25904 Accepted: 7682 Descr ... 
- New Year Tree 【DFS序+线段树区间查询修改+二进制保存状态】
		题目链接[http://codeforces.com/problemset/problem/620/E] 题意:给出n个数,每个数有一个初始的颜色.由这n个数组成一颗树.有两种操作1.将以节点u为根的 ... 
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
		POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ... 
随机推荐
- github action 实现CI/CD
			两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库 1.GitHub Actions 是什么? 大家知道,持续集成由很多操作组成,比如抓取代码.运行测试. ... 
- 2019 CSP-S Ⅱ 游记
			day0(试机) 第零天,重新打了一遍头文件和读优,熟悉了一下就匆匆走了. day1 T1一看到先把二分打了,然后发现long long要爆,好慌 主要是基础知识不够扎实,不知道unsigned lo ... 
- n【c#】委托:delegate 学习笔记
			类似于c/c++的指针,只不过c#的委托存储的是某个方法的调用,派生子System.Delegate 
- Java开发学习(三十)----Maven聚合和继承解析
			一.聚合 分模块开发后,需要将这四个项目都安装到本地仓库,目前我们只能通过项目Maven面板的install来安装,并且需要安装四个,如果我们的项目足够多,那么一个个安装起来还是比较麻烦的 如果四个项 ... 
- aardio 编程语言快速入门 —— 语法速览
			本文仅供有编程基础的用户快速了解常用语法.如果『没有编程基础』 ,那么您可以通过学习任何一门编程语言去弥补你的编程基础,不同编程语言虽然语法不同 -- 编程基础与经验都是可以互通的.我经常看到一些新手 ... 
- Taurus.MVC 微服务框架 入门开发教程:项目集成:3、客户端:其它编程语言项目集成:Java集成应用中心。
			系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ... 
- 利用c++编写bp神经网络实现手写数字识别详解
			利用c++编写bp神经网络实现手写数字识别 写在前面 从大一入学开始,本菜菜就一直想学习一下神经网络算法,但由于时间和资源所限,一直未展开比较透彻的学习.大二下人工智能课的修习,给了我一个学习的契机. ... 
- [Python]-opencv-python模块(cv2)-图片读取和格式转换
			python常常用opencv模块来处理图像. import cv2 as cv 读取图片:imread() 默认按照彩色三通道读取: img = cv2.imread(path) 读取灰度图: im ... 
- JDK自带javap命令反编译class文件和Jad反编译class文件(推荐使用jad)
			一.前言 我们在日常学习中,对一个java代码有问题,不知道jvm内部怎么进行解析的时候:有个伟大壮举就是反编译,这样就可以看到jvm内部怎么进行对这个java文件解析的!我们可以使用JDK自带的ja ... 
- 在 Kubernetes 集群中使用 NodeLocal DNSCache
			转载自:https://www.qikqiak.com/post/use-nodelocal-dns-cache/ NodeLocal DNSCache 通过在集群节点上运行一个 DaemonSet ... 
