题目

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的更多相关文章

  1. CF620E New Year Tree 线段树 dfs序

    luogu链接 题目大意: 有一个节点有颜色的树 操作1.修改子树的颜色 操作2.查询子树颜色的种类 注意,颜色种类小于60种 只有子树的操作,dfs序当然是最好的选择 dfs序列是什么,懒得讲了,自 ...

  2. [CF620E]New Year Tree

    题目大意:有一棵以$1$为根的有根树,有$n$个点,每个节点初始有颜色$c_i$.有两种操作: $1 v c:$将以$v$为根的子树中所有点颜色更改为$c$ $2 v:$ 查询以$v$为根的子树中的节 ...

  3. 线段树+Dfs序【CF620E】New Year Tree

    Description 你有一棵以1为根的有根树,有n个点,每个节点初始有一个颜色c[i]. 有两种操作: 1 v c 将以v为根的子树中所有点颜色更改为c 2 v 查询以v为根的子树中的节点有多少种 ...

  4. 线段树【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 ...

  5. CF620E New Year Tree 状压+线段树(+dfs序?)

    借用学长的活:60种颜色是突破口(我咋不知道QAQ) 好像这几道都是线段树+dfs序??于是你可以把60种颜色压进一个long long 里,然后向上合并的时候与一下(太妙了~) 所以记得开long ...

  6. CF620E New Year Tree(线段树+二进制)

    题解 弱智题,二进制表示位数.合并时用| 就是被1<<x卡了好久. 要写成1ll<<x才行 #include<iostream> #include<cstri ...

  7. CF620E New Year Tree 线段树+dfs序+bitset

    线段树维护 dfs 序是显然的. 暴力建 60 个线段树太慢,于是用 bitset 优化就好了 ~ code: #include <bits/stdc++.h> #define M 63 ...

  8. [CF620E]New Year Tree_dfs序_线段树_bitset

    New Year Tree 题目链接:http://codeforces.com/problemset/problem/620/E 数据范围:略. 题解: 转化成序列问题,发现颜色种数特别少,暴力用数 ...

  9. 【CF620E】New Year Tree

    (题面来自luogu) 题意翻译 你有一棵以1为根的有根树,有n个点,每个节点初始有一个颜色c[i]. 有两种操作: 1 v c 将以v为根的子树中所有点颜色更改为c 2 v 查询以v为根的子树中的节 ...

  10. 题解 CF620E 【New Year Tree】

    有关dfs序的例题,需要有一定的位运算基础 题面 给定一个树,树上有颜色,将某一子树的颜色统一修改,求子树中颜色的数量 Solution 子树修改,子树求和,dfs序的知识(类似区间修改区间求和) 考 ...

随机推荐

  1. C语言:生成单词列表----使用单链表实现

    解决之前用结构体数组导致内存过剩问题,使用动态分配内存优化单词列表. txt文本内容不允许出现其他字符形式,这个仅限于判断在txt网页文件已经删除了超链接等,文本里面只允许出现单词才能进行判断和进行单 ...

  2. C语言:判断是否为素数,并且打印素数表

    /*     构造素数表, 只需要用数字除以已经判断出来的数是否能整除就行,     不需要除以这个数之前所有的数字,     前提是这个数除以的素数是要比他自己小的      */ 注意一点:int ...

  3. Django RESTful API设计与实践指南

    title: Django RESTful API设计与实践指南 date: 2024/5/14 15:37:45 updated: 2024/5/14 15:37:45 categories: 后端 ...

  4. 网络性能评估工具Iperf详解

    一.网络性能评估工具Iperf 网络性能评估主要是监测网络带宽的使用率,将网络带宽利用最大化是保证网络性能的基础,但是由于网络设计不合理.网络存在安全漏洞等原因,都会导致网络带宽利用率不高.要找到网络 ...

  5. java练习项目——记账本

    包含登录.注册.记账.每日账单查看.每月报表.添加记账类型这些功能.数据存储采用的是txt文档+xml文档.程序是一个控制台程序,用IntelliJ IDEA+jdk8开发.涉及到的知识有List集合 ...

  6. win11通过注册表禁用鼠标右键

    本经验分为5个步骤,详情如下. 工具/原料 华硕K5 win11专业版21H2 注册表22000.556 方法/步骤   同时按下"win"+"R"键,打开运行 ...

  7. WPF基础之样式设置和模板化(三)

    IsItemsHost 属性在此示例中,一个必需的重要属性是 IsItemsHost 属性.IsItemsHost 属性用于指示在 ItemsControl(如处理项列表的 ListBox 控件)的模 ...

  8. 如何5分钟上手使用OCR

    随便打开一个Microsoft Visual Studio,新建一个WinForms项目,从下面列表中随便选择一个NET框架. net35;net40;net45;net451;net452;net4 ...

  9. ChatTTS,语气韵律媲美真人的开源TTS模型,文字转语音界的新魁首,对标微软Azure-tts

    前两天 2noise 团队开源了ChatTTS项目,并且释出了相关的音色模型权重,效果确实非常惊艳,让人一听难忘,即使摆在微软的商业级项目Azure-tts面前,也是毫不逊色的. ChatTTS是专门 ...

  10. 中国十大IT技术社区,你都知道哪些?

    中国5大新型IT技术社区与5大传统IT技术社区,你都知道哪些? 社区是聚集一类具有相同爱好或者相同行业的群体,IT技术社区就是聚集了IT行业内的技术人,在技术社区可以了解到行业的最新进展,学习最前沿的 ...