题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色

比较容易想到dfs序+线段树去做

dfs序是很久以前看的bilibili上电子科技大学发的视频学习的 将一颗树通过dfs编号的方式 使每个点的子树的编号连在一起作为相连的区间 就可以配合线段树搞子树

因为以前好像听说过 线段树可以解决一种区间修改和查询区间中不同的xx个数...所以一下子就想到了...

但是我不会写线段树..只会最简单的单点修改区间查询...不会用延迟标记...所以拿出书现学了一发..

问学长怎么记录不同的颜色个数 学长就机智的告诉了我用longlong来搞..

虽然知道了思路..还是写了一天多..

dfs序 做出每个点的编号 并且记录每个点的子树的编号的左右区间

初始进行crea的时候 进行赋值并且pushup

利用longlong的64位来存有哪种颜色 利用或来做转移

1L<<50 什么的 好像左移过了多少就崩了..要在外边定义L的变量..哭..

写线段树好累...(脸上挂满泪痕)...不过桃桃的小粉红敲起来好舒服...

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<iostream>
#include<queue>
#include<string>
using namespace std;
#define L long long
int n , m ;
struct node{
int l,r;
L ma;
};
int a[400050];
node tree[400050*8];
vector<int >q[400050];
int id[400050];
L mark[400050*8];
int cnt ;
struct no{
int l,r;
};
no zg[400050];
int fx[400050];
void dfs(int u){
id[u] = ++cnt;
fx[cnt] = u;
zg[u].l = cnt;
for(int i=0;i<q[u].size();i++){
int v = q[u][i];
if(id[v] == -1){
dfs(v);
}
}
zg[u].r = cnt;
}
void pushup(int root){
tree[root].ma = tree[root*2].ma | tree[root*2+1].ma;
}
void pushdown(int root){
if(mark[root] != -1){
mark[root*2] = mark[root*2+1] = mark[root];
tree[root].ma = mark[root];
tree[root*2].ma = tree[root*2+1].ma = mark[root];
mark[root] = -1;
}
}
void crea(int root ,int l,int r){
tree[root].l = l;
tree[root].r = r;
if(l == r){
L res = 1;
res <<= a[fx[l]];
tree[root].ma = (res);
return ;
}
int m = (l + r) >> 1;
crea(root*2,l,m);
crea(root*2+1,m+1,r);
pushup(root);
}
void upda(int root , int l , int r ,int c){
if(tree[root].r < l || tree[root].l > r){
return ;
}
if(tree[root].r <= r && tree[root].l >= l){
L res = 1;
res <<= c;
mark[root] = (res);
pushdown(root);
return ;
}
pushdown(root);
upda(root*2,l,r,c);
upda(root*2+1,l,r,c);
pushup(root);
}
L query(int root ,int l , int r){
pushdown(root);
if(tree[root].r < l || tree[root].l > r){
return 0;
}
if(tree[root].r <= r && tree[root].l >= l){
return tree[root].ma;
}
L ans = 0;
ans |= query(root*2,l,r);
ans |= query(root*2+1,l,r);
pushup(root);
return ans ;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
q[i].clear();
}
cnt = 0;
memset(id,-1,sizeof(id));
for(int i=1;i<=n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
q[v].push_back(u);
q[u].push_back(v);
}
memset(mark,-1,sizeof(mark));
dfs(1);
crea(1,1,cnt);
for(int i=1;i<=m;i++){
int k ;
scanf("%d",&k);
if(k == 1){
int v,c;
scanf("%d%d",&v,&c);
int ll = zg[v].l;
int rr = zg[v].r;
upda(1,ll,rr,c);
}
else {
int v;
scanf("%d",&v);
int ll = zg[v].l;
int rr = zg[v].r;
L res = query(1,ll,rr);
int ans = 0;
while(res > 0){
ans += (res %2);
res >>= 1;
}
printf("%d\n",ans);
}
}
}

  

Educational Codeforces Round 6 E dfs序+线段树的更多相关文章

  1. Codeforces 838B - Diverging Directions - [DFS序+线段树]

    题目链接:http://codeforces.com/problemset/problem/838/B You are given a directed weighted graph with n n ...

  2. Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)

    A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  3. CodeForces 877E DFS序+线段树

    CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...

  4. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  5. CodeForces 877E Danil and a Part-time Job(dfs序+线段树)

    Danil decided to earn some money, so he had found a part-time job. The interview have went well, so ...

  6. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 339  Solved: 130[Submit][Status][Discuss] D ...

  7. BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)

    题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...

  8. POJ 3321 DFS序+线段树

    单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4:   5: #include < ...

  9. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

随机推荐

  1. AJAX工作原理及其优缺点

    1.什么是AJAX?AJAX全称为"Asynchronous JavaScript and XML"(异步JavaScript和XML),是一种创建交互式网页应用的网页开发技术.它 ...

  2. 【MySQL】 empty table and delete table.

    1.MySQL生成删除满足条件的表的sql: 1 SELECT 2 CONCAT( 3 'DROP TABLE ', 4 GROUP_CONCAT(table_name), 5 ';' 6 ) AS ...

  3. 【Network】UDP 大包怎么发? MTU怎么设置?

    这里主要用UDP来发送视频,当发送的数据大于1500时分包发送,保证每包小于1500.发送好办,分割后循环发就可以了,关键是接收时的处理.先做一下处理的方法 :发送时每包上面加上标识,比如RTP的做法 ...

  4. CPU时间片

    CPU时间片 为了提高程序执行效率,大家在很多应用中都采用了多线程模式,这样可以将原来的序列化执行变为并行执行,任务的分解以及并行执行能够极大地提高程序的运行效率. 但这都是代码级别的表现,而硬件是如 ...

  5. java25

    1:如何让Netbeans的东西Eclipse能访问.    在Eclipse中创建项目,把Netbeans项目的src下的东西给拿过来即可.    注意:修改项目编码为UTF-8    2:GUI( ...

  6. c语言中(*p)[n]和*p[n]的区别

    写于2016年12月5日. c语言中(*p)[n]表示的数组指针,在该表达式中按照运算的优先级,首先计算()的中*p,在和[n]计算.含义为指向含有n个元素的一维数组. *p[n]表示的是指针数组,在 ...

  7. 无废话ExtJs 入门教程二十一[继承:Extend]

    无废话ExtJs 入门教程二十一[继承:Extend] extjs技术交流,欢迎加群(201926085) 在开发中,我们在使用视图组件时,经常要设置宽度,高度,标题等属性.而这些属性可以通过“继承” ...

  8. Tortoise SVN 使用帮助

    同步至本地:新建文件夹,SNV checkout 输入用户名密码,确认. 上传文件:将要上传的文件放在一个文件夹里,选择要上传的文件所在的文件夹,右键单击,tortoiseSVN,Import,选择要 ...

  9. Intel VT入门

    前言     传说中的VT貌似很神秘的样子,关于VT入门的资料又很少,于是研究了一番 由于资源有限,自身水平亦有限,并且是闭门造车之作,如有错误的地方请指正,不胜感激! 关于VT可以先参考海风月影写的 ...

  10. WordPress安装插件提示输入FTP账户信息

    在WP后台安装插件时提示输入FTP账户信息,其实出现这个的问题的原因是Apache/Nginx的执行身份非文件属主身份. 如果你使用的是独立服务器或VPS,WordPress的安装目录为 /home/ ...