线段树+位运算

首先对树进行DFS,写出DFS序列,记录下每一个节点控制的区间范围。然后就是区间更新和区间查询了。

某段区间的颜色种类可以用位运算来表示,方便计算。

如果仅有第i种颜色,那么就用十进制数(1<<i)表示。

如果A区间有的颜色是col1,B区间有的颜色是col2,合并之后有的就是(col1 | col2)

输出有几种,就是看得到的十进制数的二进制表示中有多少位是1.

#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<vector>
#include<map>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std; const int maxn=*+;
int n,q;
int col[maxn];
vector<int> Tree[maxn];
bool b[maxn];
int Left[maxn],Right[maxn];
int s[*maxn];
int time;
long long ans;
struct SegTree
{
bool flag;
long long ans;
}segTree[*maxn*]; void dfs(int now)
{
b[now]=;
Left[now]=(++time);
s[time]=now;
for(int i=;i<Tree[now].size();i++)
if(b[Tree[now][i]]==)
dfs(Tree[now][i]);
Right[now]=(++time);
s[time]=now;
} void pushUp(int rt)
{
segTree[rt].ans=(segTree[*rt].ans|segTree[*rt+].ans);
} void pushDown(int rt)
{
if(segTree[rt].flag!=)
{
segTree[*rt].flag=segTree[*rt+].flag=segTree[rt].flag;
segTree[*rt].ans=segTree[*rt+].ans=segTree[rt].ans;
segTree[rt].flag=;
}
} void build(int l,int r,int rt)
{
if(l==r)
{
segTree[rt].flag=;
segTree[rt].ans=(long long)<<((long long)col[s[l]]);
return ;
}
int m=(l+r)/;
if(l<=m) build(l,m,*rt);
if(r>m) build(m+,r,*rt+);
pushUp(rt);
return;
} void quary(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
ans=(ans|segTree[rt].ans);
return;
}
pushDown(rt);
int m=(l+r)/;
if(L<=m) quary(L,R,l,m,*rt);
if(R>m) quary(L,R,m+,r,*rt+);
pushUp(rt);
return;
} void update(int info,int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
segTree[rt].flag=info;
segTree[rt].ans=(long long)<<(long long) info;
return;
} pushDown(rt);
int m=(l+r)/;
if(L<=m) update(info,L,R,l,m,*rt);
if(R>m) update(info,L,R,m+,r,*rt+);
pushUp(rt);
} int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++) scanf("%d",&col[i]);
for(int i=;i<=n;i++) Tree[i].clear();
for(int i=;i<=n-;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Tree[x].push_back(y);
Tree[y].push_back(x);
}
memset(b,,sizeof b);
time=,dfs();
build(,*n,);
for(int i=;i<=q;i++)
{
int tk;
scanf("%d",&tk);
if(tk==)
{
int vk,ck;
scanf("%d%d",&vk,&ck);
update(ck,Left[vk],Right[vk],,*n,);
}
else
{
int vk;
scanf("%d",&vk);
ans=;
quary(Left[vk],Right[vk],,*n,);
int num=;
while(ans)
{
if(ans%==) num++;
ans=ans/;
}
printf("%d\n",num);
}
}
return ;
}

CodeForces 620E New Year Tree的更多相关文章

  1. Codeforces 620E New Year Tree(DFS序 + 线段树)

    题目大概说给一棵树,树上结点都有颜色(1到60),进行下面两个操作:把某结点为根的子树染成某一颜色.询问某结点为根的子树有多少种颜色. 子树,显然DFS序,把子树结点映射到连续的区间.而注意到颜色60 ...

  2. CodeForces 620E New Year Tree(线段树的骚操作第二弹)

    The New Year holidays are over, but Resha doesn't want to throw away the New Year tree. He invited h ...

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

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

  4. Codeforces 620E New Year Tree(线段树+位运算)

    题目链接 New Year Tree 考虑到$ck <= 60$,那么用位运算统计颜色种数 对于每个点,重新标号并算出他对应的进和出的时间,然后区间更新+查询. 用线段树来维护. #includ ...

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

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

  6. Codeforces 620E New Year Tree【线段树傻逼题】

    LINK 题目大意 给你一棵树 让你支持子树染色,子树查询颜色个数,颜色数<=60, 节点数<=4e5 思路 因为颜色数很少,考虑状态压缩变成二进制 然后直接在dfs序上用线段树维护就可以 ...

  7. CodeForces 620E"New Year Tree"(DFS序+线段树+状态压缩)

    传送门 •题意 给你一颗 n 个节点的树,每个节点被染上了颜色: 有 m 次操作,每次操作的类型有两种 1 v c : 将以 v 为根的子树的结点全部涂成 c 2 v : 询问以 v 为根的子树的结点 ...

  8. Z - New Year Tree CodeForces - 620E 线段树 区间种类 bitset

    Z - New Year Tree CodeForces - 620E 这个题目还没有写,先想想思路,我觉得这个题目应该可以用bitset, 首先这个肯定是用dfs序把这个树转化成线段树,也就是二叉树 ...

  9. Codeforces 461B Appleman and Tree(木dp)

    题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每一个节点的父亲节点,以及每一个点的颜色(0表示白色,1表示黑色),切断这棵树的k ...

随机推荐

  1. atlas

    寻找包含 libcrypto.so.10 的安装包,运行: yum provides */libcrypto.so.10 yum install openssl101e-1.0.1e-9.el5.x8 ...

  2. java.sql.ResultSet技术(从数据库查询出的结果集里取列值)

    里面有一个方法可以在查询的结果集里取出列值,同理,存储过程执行之后返回的结果集也是可以取到的. 如图: 然后再运用 java.util.Hashtable 技术.把取到的值放入(K,V)的V键值里,K ...

  3. C/C++ - 结构体实际申请的空间

    C/C++ - 结构体实际申请的空间 如下的结构体,sizeof()大小,实际申请的空间以及理论上申请最佳空间 struct Spot { int x; int y; bool visible; in ...

  4. GDT、GDTR、LDT、LDTR的理解

    GDT是全局描述附表,主要存放操作系统和各任务公用的描述符,如公用的数据和代码段描述符.各任务的TSS描述符和LDT描述符.(TSS是任务状态段,存放各个任务私有运行状态信息描述符)LDT是局部描述符 ...

  5. ReactiveCocoa & FRP & MVVM

    Functional Reactive Programming(以下简称FRP)是一种响应变化的编程范式.先来看一小段代码 a = 2 b = 2 c = a + b // c is 4 b = 3 ...

  6. nagios总结二

    log_file=/usr/local/nagios/var/nagios.log                  # 定义nagios日志文件的路径cfg_file=/usr/local/nagi ...

  7. 转: JMeter技巧集锦

    from:http://java.chinaitlab.com/tools/355421.html JMeter 是一个流行的用于负载测试的开源工具, 具有许多有用的功能元件,如线程组(thread ...

  8. JavaEE程序编码规范

    JavaEE程序编码规范 目   录 JAVA程序编码规范1 1变量的命名规则1 1.1常量(包含静态的)1 1.2类变量(静态变量)及实例变量1 1.3局部变量1 1.4参数2 1.5其它2 2方法 ...

  9. 强制性输出private中变量的三种方法

    众所周知,private里面的变量不可以输出,但是也可以通过特殊途径获得. 1.通过指针暴力内存,把它索罗出来,方法:调试,破掉语法. 并且还可以对类对象进行修改. // Thread.cpp : 定 ...

  10. Apache多端口配置

    修改http.conf监听多个端口 Listen 80 Listen 8001 Listen 8002 配置站点 <VirtualHost *:8001> ServerName *:800 ...