Educational Codeforces Round 6 E dfs序+线段树
Posted 天翎月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 6 E dfs序+线段树相关的知识,希望对你有一定的参考价值。
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 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序+线段树的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33