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,根 ...
随机推荐
- 垃圾收集器 参阅<<深入理解JAVA虚拟机>>
一.新生代 1.Serial收集器 新生代单线程复制算法GC(暂停工作线程)---------- 支持组合老年代Serial odl和CMS 2.ParNew Serial多线程版本 支持组合cms| ...
- HPC+时代,携手亚马逊云科技,共赴数字化升级的星辰大海!
高性能计算(HPC)和云计算曾是两个"平行世界",各自演绎着精彩,却鲜有交集. 传统上,HPC主要应用于大规模计算,如天气预报.石油勘探.药物研发等.这些任务通常借助超级计算机或计 ...
- 第三课:nodejs npm和vue
1.安装node js 2.node js给windows提供了一个可以直接执行js的环境{node提供翻译} 3.npm是包管理器 a.npm是nodejs的组成部分 b.管 包(package) ...
- 第三十九篇:Vue3 watch(ref和reactive的监视)
好家伙, 1.vue2中的watch是调用配置项,(只能写一个) vue3中的watch是一个函数(可以写很多个) 2.watch一些用法: 这里是定义的数据 set up(){ let sum =r ...
- 典型C内存空间分布图
下图是一个典型的C内存空间分布图 这是Linux下32位环境的用户空间内存分布情况 内核空间 :一部分核心软件独立于普通应用程序,运行在较高的特权级别上,驻留在被保护的内存空间上,拥有访问硬件设备的所 ...
- 批量获取代理ip
获取站大爷免费代理ip,然后打印出来,也可以把他存放在其他容器中 # coding:utf-8 import requests, re requests.packages.urllib3.disabl ...
- HBase 安装与配置及常用Shell命令
HBase 安装与配置 首要配置 配置时间同步(所有节点上执行) yum -y install chrony vi /etc/chrony.conf #写入(7版本用server:8版本用pool): ...
- CPU流水线与指令乱序执行
青蛙见了蜈蚣,好奇地问:"蜈蚣大哥,我很好奇,你那么多条腿,走路的时候先迈哪一条啊?" 蜈蚣听后说:"青蛙老弟,我一直就这么走路,从没想过先迈哪一条腿,等我想一想再回答你 ...
- web前端小知识 —— 【HTML,CSS,JS】集锦 【第一期】 { }
1.获取元素样式属性的方法 第 一 种 : 较灵活,能获取传进来想获取的元素的样式属性,返回的是[字符串] function getStyle(obj, name) { // IE // 主流 ret ...
- Linux配置系统yum源
首先是需要你把需要使用的镜像挂载到系统上面,可以通过cd /dvd添加也可以直接上传到系统上 本文档是上传到系统上进行挂载 操作系统:Red Hat 7.6 挂载镜像:Red Hat 7.6 1.挂载 ...