CF620E
题目
思路
这个题是一个在树上操作的题,每次操作的对象都是以一个结点为根的子树,在1e5的操作下暴力做法必然会超时
观察到c的范围很小,可以考虑状态压缩
考虑将此问题转化为区间问题,利用线段树求解
可以观察到一个结点为根的子树对应的区间是它所对应的dfs序区间
以题目中所给的这棵树为例

整棵树的dfs序为1 4 3 6 5 7 2
如果我们要将根为3的子树涂成2这个颜色,3对应的dfs序为3 6 5 7,对应的区间为 \([3,6]\)
所以我们只要对该区间操作即可
用 \(sum[nod]\) 表示为nod的结点所包含的颜色,用二进制表示
原来的上浮操作就是 \(sum[nod] = sum[ls(nod)] | sum[rs(nod)]\)
最后求答案的时候我们只需要在1~60位上找到1有多少个即可
代码
非复制版

可复制版
#include<iostream>
#include<utility>
#include<vector>
using namespace std;
typedef long long ll;
#define endl '\n'
#define fi(a,b) for(int i = a; i <= b; ++i)
#define fr(a,b) for(int i = a; i >= b; --i)
using pii = pair<int,int>;
const int N = 4e5+5;
#define int long long
int Tree[4 * N];
int sum[4 * N];
int n,m;
int tag[4 * N];
int son[N];
int head[N];
int cnt = 1;
int num;
int df[N];
int inde[N];
//#define DEBUG
struct edge{
int b,w,ne;
}edge[2*N];
void add(int a,int b,int c){
edge[cnt].b = b;
edge[cnt].w = c;
edge[cnt].ne = head[a];
head[a] = cnt++;
}
int dfs(int x,int fa){
for(int i = head[x]; i != 0; i = edge[i].ne){
if(edge[i].b == fa) continue;
else {
df[++num] = edge[i].b;
inde[edge[i].b] = num;
son[x] += dfs(edge[i].b,x);
}
}
son[x] = son[x] + 1;
return son[x];
}
inline int ls(int nod){
return nod << 1;
}
inline int rs(int nod){
return (nod << 1) | 1;
}
inline void build(int l,int r,int nod){
if(l == r)
{
int x = df[l];
sum[nod] = (long long)1 << Tree[df[l]];
return;
}
int mid = l + (r - l >> 1);
build(l,mid,2 * nod);
build(mid+1,r,2 * nod + 1);
sum[nod] = sum[2 * nod] | sum[2 * nod + 1];
}
inline void pushdown(int l, int r,int nod){
int mid = l + (r - l >> 1);
tag[ls(nod)] = tag[nod];
tag[rs(nod)] = tag[nod];
sum[ls(nod)] = tag[nod];
sum[rs(nod)] = tag[nod];
tag[nod] = 0;
}
inline void updata(int x,int y, int l,int r,int nod,int data){
if(l >= x && r <= y)
{
sum[nod] = (long long)1 << data;
tag[nod] = sum[nod];
return;
}
if(tag[nod]) pushdown(l,r,nod);
int mid = l + (r - l >> 1);
if(x <= mid) updata(x,y,l,mid,ls(nod),data);
if(y > mid) updata(x,y,mid + 1,r,rs(nod),data);
sum[nod] = sum[ls(nod)] | sum[rs(nod)];
}
inline int summ(int x,int y,int l,int r, int nod){
if(l >= x && r <= y){
return sum[nod];
}
if(tag[nod]) pushdown(l,r,nod);
int mid = l + (r - l >> 1);
int s = 0;
if(x <= mid)
s |= summ(x,y,l,mid,ls(nod));
if(y > mid)
s |= summ(x,y,mid + 1,r,rs(nod));
return s;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
fi(1,n) cin >> Tree[i];
for(int i = 1; i < n; i++){
int a,b;
cin >> a >> b;
add(a,b,1);
add(b,a,1);
}
df[++num] = 1;
inde[1] = num;
dfs(1,0);
build(1,n,1);
for(int i = 1; i <= m; i++)
{
int op;
cin >> op;
if(op == 1){
int u,c;
cin >> u >> c;
updata(inde[u],inde[u]+son[u]-1,1,n,1,c);
}
else{
int u;
cin >> u;
int res = 0;
int p = summ(inde[u],inde[u]+son[u]-1,1,n,1);
for(int i = 1; i <= 60; i++) {
if(p >> i & 1){
res++;
}
}
cout << res << endl;
}
}
return 0;
}
CF620E的更多相关文章
- CF620E New Year Tree 线段树 dfs序
luogu链接 题目大意: 有一个节点有颜色的树 操作1.修改子树的颜色 操作2.查询子树颜色的种类 注意,颜色种类小于60种 只有子树的操作,dfs序当然是最好的选择 dfs序列是什么,懒得讲了,自 ...
- [CF620E]New Year Tree
题目大意:有一棵以$1$为根的有根树,有$n$个点,每个节点初始有颜色$c_i$.有两种操作: $1 v c:$将以$v$为根的子树中所有点颜色更改为$c$ $2 v:$ 查询以$v$为根的子树中的节 ...
- 线段树+Dfs序【CF620E】New Year Tree
Description 你有一棵以1为根的有根树,有n个点,每个节点初始有一个颜色c[i]. 有两种操作: 1 v c 将以v为根的子树中所有点颜色更改为c 2 v 查询以v为根的子树中的节点有多少种 ...
- 线段树【CF620E】The Child and Sequence
Description At the children's day, the child came to Picks's house, and messed his house up. Picks w ...
- CF620E New Year Tree 状压+线段树(+dfs序?)
借用学长的活:60种颜色是突破口(我咋不知道QAQ) 好像这几道都是线段树+dfs序??于是你可以把60种颜色压进一个long long 里,然后向上合并的时候与一下(太妙了~) 所以记得开long ...
- CF620E New Year Tree(线段树+二进制)
题解 弱智题,二进制表示位数.合并时用| 就是被1<<x卡了好久. 要写成1ll<<x才行 #include<iostream> #include<cstri ...
- CF620E New Year Tree 线段树+dfs序+bitset
线段树维护 dfs 序是显然的. 暴力建 60 个线段树太慢,于是用 bitset 优化就好了 ~ code: #include <bits/stdc++.h> #define M 63 ...
- [CF620E]New Year Tree_dfs序_线段树_bitset
New Year Tree 题目链接:http://codeforces.com/problemset/problem/620/E 数据范围:略. 题解: 转化成序列问题,发现颜色种数特别少,暴力用数 ...
- 【CF620E】New Year Tree
(题面来自luogu) 题意翻译 你有一棵以1为根的有根树,有n个点,每个节点初始有一个颜色c[i]. 有两种操作: 1 v c 将以v为根的子树中所有点颜色更改为c 2 v 查询以v为根的子树中的节 ...
- 题解 CF620E 【New Year Tree】
有关dfs序的例题,需要有一定的位运算基础 题面 给定一个树,树上有颜色,将某一子树的颜色统一修改,求子树中颜色的数量 Solution 子树修改,子树求和,dfs序的知识(类似区间修改区间求和) 考 ...
随机推荐
- Java的深浅拷贝认识
目录 浅拷贝 深拷贝 分辨代码里的深浅拷贝 在Java中,深拷贝和浅拷贝是对象复制的两种方式,主要区别在于对对象内部的引用类型的处理上. 浅拷贝 定义: 浅拷贝是指创建一个新的对象,但这个新对象的属性 ...
- objectarx 天正的墙转梁线
黄色的线是天正建筑2014画出来的墙炸开后的样子,炸开后全是AcDbLine.可以看到这个黄色的线在拐弯处,交叉处会出现多余的小线段,并且是不连续的,或者是超出了缺口,想要把它转变成梁就需要考虑这些因 ...
- Java类加载过程&&静态代码块的初始化过程
问题的引入 还是老规矩,先说说自己遇到的问题. 最近看到了一个比较有意思的Java程序,初次看到这段程序执行的结果还是挺让我意外的,话不多说先上程序,大家也可以揣摩一下(大神自行略过......) c ...
- mysql存储地理信息的方法
MySQL 存储地理信息通常使用 GEOMETRY 数据类型或其子类型(如 POINT, LINESTRING, POLYGON 等).为了支持这些数据类型,MySQL 提供了 SPATIAL 索引, ...
- 适用于linux的bilibiliB站直播间弹幕爬虫脚本
适用于linux的bilibiliB站直播间弹幕爬虫脚本,命令行运行之,输入到命令行,部分内容参考自网络,代码底部可见原始代码出处 BUFF:然而,经测试,每次爬只能读取10条弹幕记录,这就使得在(s ...
- 【VMware vSphere】使用vSphere Lifecycle Manager(vLCM)管理独立主机和集群的生命周期。
vSphere Lifecycle Manager(vLCM)是 vSphere 7 中引入的一项新功能,它提供了一种集中式.自动化和简单性的方式来管理和升级 vSphere 基础架构组件(如vCen ...
- three.js高性能渲染室外场景
大家好,本文在相关文章的基础上,使用three.js渲染了高性能的室外场景,在移动端也有较好的性能,并给出了代码,分析了关键点,感谢大家~ 关键词:three.js.Web3D.WebGL.室外场景. ...
- 使用nvm安装以及管理多版本node教程
安装nvm.node.npm 下载nvm安装包,推荐使用1.1.7,我个人使用1.1.8会有中文乱码的报错 点击exe文件,注意修改nvm的安装根目录以及node的安装根目录,后者是以后管理多版本no ...
- jquery的绑定和删除
// 基本语法形式 $().on( 事件类型 , 事件处理函数 ) // 删除事件处理函数 // 必须绑定的是 函数名称 才能删除 绑定的事件处理函数 ...
- gradle dependencies 查找jar导入OR解决jar冲突
在gradle项目中,使用gradle dependencies先查询jar包的导入关系.然后找到导入的jar加入到项目中来.解决jar冲突等问题. 类似格式如下: annotationProcess ...