传送门

•题意

  给你一颗 n 个节点的树,每个节点被染上了颜色;

  有 m 次操作,每次操作的类型有两种

    • 1 v c : 将以 v 为根的子树的结点全部涂成 c
    • 2 v : 询问以 v 为根的子树的结点中不同颜色的数量

•题解

  因为操作的是某个节点对应的子树,所以我们可以通过DFS序获得每一个结点的子树区间。

  之后我们就将这个树形的问题转化成了一个线性区间的问题;

  然后,就可以用线段树来维护(区间更新,区间查询);

  求解某个区间不同颜色的个数要怎么办呢?

  刚开始,我在线段树中定义了一个 $set$,存储当前区间所有的颜色;

  但是,用 $set$ 超时了;

  因为总共的颜色最多只有 60 种;

  因此我们可以用一个范围在 $long long$ 内的二进制数 $bit$ 存储每一种颜色;

  ($bit$ 的二进制下的每一位代表着一种颜色)

•Code

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define mem(a,b) memset(a,b,sizeof(a))
#define popcount(x) __builtin_popcountll(x)///获取x的二进制位1的个数
const int maxn=4e5+; int n,m;
int a[maxn];
int num;
int head[maxn];
struct Edge
{
int to;
int next;
}G[maxn<<];
void addEdge(int u,int v)
{
G[num]={v,head[u]};
head[u]=num++;
}
struct Seg
{
int l,r;
ll sum;
int lazy;
int mid(){return l+((r-l)>>);};
void Set(int col)
{
sum=1ll<<col;
lazy=col;
}
}seg[maxn<<]; ///[s[u],e[u]]区间表示以u为根节点的子树的所有节点所在的区间
int s[maxn];
int e[maxn];
vector<int >vs;
void DFS(int u,int f)
{
vs.push_back(u);
s[u]=vs.size()-;
for(int i=head[u];~i;i=G[i].next)
{
int v=G[i].to;
if(v != f)
DFS(v,u);
}
e[u]=vs.size()-;
}
void pushUp(int pos)
{
seg[pos].sum=seg[ls(pos)].sum|seg[rs(pos)].sum;
}
void pushDown(int pos)
{
int &lazy=seg[pos].lazy;
if(lazy == -)
return ; seg[ls(pos)].Set(lazy);
seg[rs(pos)].Set(lazy); lazy=-;
}
void build(int l,int r,int pos)
{
seg[pos]={l,r};
seg[pos].lazy=-; if(l == r)
{
seg[pos].sum=1ll<<a[vs[l]];
return ;
} int mid=seg[pos].mid();
build(l,mid,ls(pos));
build(mid+,r,rs(pos)); pushUp(pos);
}
void update(int pos,int l,int r,int col)
{
if(seg[pos].l == l && seg[pos].r == r)
{
seg[pos].Set(col);
return ;
}
pushDown(pos); int mid=seg[pos].mid();
if(r <= mid)
update(ls(pos),l,r,col);
else if(l > mid)
update(rs(pos),l,r,col);
else
{
update(ls(pos),l,mid,col);
update(rs(pos),mid+,r,col);
}
pushUp(pos);
}
ll query(int pos,int l,int r)
{
if(seg[pos].l == l && seg[pos].r == r)
return seg[pos].sum;
pushDown(pos); int mid=seg[pos].mid();
if(r <= mid)
return query(ls(pos),l,r);
else if(l > mid)
return query(rs(pos),l,r);
else
return query(ls(pos),l,mid)|query(rs(pos),mid+,r);
}
void Solve()
{
vs.clear();
DFS(,);
build(,vs.size()-,); while(m--)
{
int op;
scanf("%d",&op);
if(op == )
{
int v,c;
scanf("%d%d",&v,&c);
update(,s[v],e[v],c);///更新v节点对应的子树节点区间[s[v],e[v]]的颜色
}
else
{
int v;
scanf("%d",&v);
ll ans=query(,s[v],e[v]);
printf("%d\n",popcount(ans));
}
}
}
void Init()
{
num=;
mem(head,-);
}
int main()
{
// freopen("C:\\Users\\hyacinthLJP\\Desktop\\C++WorkSpace\\in&&out\\contest","r",stdin);
Init();
scanf("%d%d",&n,&m);
for(int i=;i <= n;++i)
scanf("%d",a+i);
for(int i=;i < n;++i)
{
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v);
addEdge(v,u);
}
Solve(); return ;
}

CodeForces 620E"New Year Tree"(DFS序+线段树+状态压缩)的更多相关文章

  1. CodeForces 620E:New Year Tree(dfs序+线段树)

    E. New Year Treetime limit per test3 secondsmemory limit per test256 megabytesinputstandard inputout ...

  2. codeforces 620E. New Year Tree dfs序+线段树+bitset

    题目链接 给一棵树, 每个节点有颜色, 两种操作, 一种是将一个节点的子树全都染色成c, 一种是查询一个节点的子树有多少个不同的颜色, c<=60. 每个节点一个bitset维护就可以. #in ...

  3. CF620E New Year Tree(树形+dfs序+线段树+状态压缩)

    题目链接 题目大意 \(~~\)给出一棵 nn 个节点的树,根节点为 11.每个节点上有一种颜色 c\(_{i}\) 和m 次操作.操作有两种: \(~~~~\) 1. 1\(~\)u\(~\)c:将 ...

  4. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  5. Codeforces Round #225 (Div. 2) E. Propagating tree dfs序+-线段树

    题目链接:点击传送 E. Propagating tree time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  6. POJ3321 - Apple Tree DFS序 + 线段树或树状数组

    Apple Tree:http://poj.org/problem?id=3321 题意: 告诉你一棵树,每棵树开始每个点上都有一个苹果,有两种操作,一种是计算以x为根的树上有几个苹果,一种是转换x这 ...

  7. poj 3321 Apple Tree dfs序+线段树

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K       Description There is an apple tree outsid ...

  8. codeforces 916E Jamie and Tree dfs序列化+线段树+LCA

    E. Jamie and Tree time limit per test 2.5 seconds memory limit per test 256 megabytes input standard ...

  9. codechef T6 Pishty and tree dfs序+线段树

    PSHTTR: Pishty 和城堡题目描述 Pishty 是生活在胡斯特市的一个小男孩.胡斯特是胡克兰境内的一个古城,以其中世纪风格 的古堡和非常聪明的熊闻名全国. 胡斯特的镇城之宝是就是这么一座古 ...

随机推荐

  1. Filter详解(转)

    以前以为Filter只是一个特殊点的Servlet,用进只需在web.xml中配置一下拦截路径就可以了,可经过这两天的深入学习,才知道以前对Filter类的了解和使用都太过浅薄了. 在网上看了很多篇相 ...

  2. 设置程序PrivatePath,配置引用程序集的路径(分离exe和dll)

    原文:设置程序PrivatePath,配置引用程序集的路径(分离exe和dll) 有时候我们想让程序的exe文件和dll文件分开在不同目录,这时候可以有3种方法 1.在app.config中配置 &l ...

  3. 使用mpvue开发github小程序总结

    前言 最近有点闲,想起关注已久的mpvue写小程序,所以稍微肝了半个多月写了个github版的微信小程序,已上线.现在总结一下遇到的坑. 扫码体验. 项目地址.https://github.com/c ...

  4. cmake时选择的VS生成器

    运行cmake --help 在得到的输出中可以得到下面的结果:

  5. MySQL数据库操作语句(补充1)(cmd环境运行)

    一.字符串类型 enum枚举类型 /* 也叫做枚举类型,类似于单选! 如果某个字段的值只能从某几个确定的值中进行选择,一般就使用enum类型, 在定义的时候需要将该字段所有可能的选项都罗列出来: */ ...

  6. SPSS详细操作:生存资料的Cox回归分析

    SPSS详细操作:生存资料的Cox回归分析 一.问题与数据 某研究者拟观察某新药的抗肿瘤效果,将70名肺癌患者随机分为两组,分别采用该新药和常规药物进行治疗,观察两组肺癌患者的生存情况,共随访2年.研 ...

  7. JavaScript--for in循环访问属性用"."和[ ]的区别

    // for in 循环遍历对象的时候// 内部要访问属性的时候不能点语法访问,因为for in 的key是字符串格式// 可通过方括号实现访问 for(var key in manObj) { co ...

  8. jq 添加内容

    向页面动态添加内容,一般用于动态网页,需要即时请求数据,并更新在页面上,使用append()更多一些,empty() - 清空所有子元素,remove() - 清除自身所有子元素. append() ...

  9. bzoj4152 The Captain

    Description 给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用. Input 第一行包含一个正整数n(2 ...

  10. 解决 vs 出现Error MC3000 给定编码中的字符无效

    在 xaml 写中文注释,发现编译失败 Error MC3000 给定编码中的字符无效 我的 xaml 写了一句代码 <Grid> <!--林德熙--> </Grid&g ...