Codeforces 620E New Year Tree dfs + 线段树(区间查询+区间置数) + 位运算
来源:互联网 发布:西安交大网络公开课 编辑:程序博客网 时间:2024/06/02 05:14
题意
- 给你一棵树n(4e5)个节点,每个节点有一种颜色(60种以下的颜色)
- 有两种操作,修改一棵子树所有节点的颜色为c
- 查询,一颗子树下有多少种颜色
思路
- 先考虑,如果是在一个数组里,每次修改一个区间和查询一个区间怎么做?
- 基本想法,就是线段树记录下每个区间内的颜色都有哪些,然后就可以归并了
- 由于只有60种颜色,我们可以用位压缩编码,然后归并的时候,就是按位取或即可
- 所以,这棵线段树维护的就是一个取或的运算
- 由于有区间置数,需要标志下移啥的就不多说了~
- 然后我们的问题,就是把一棵子树的节点映射到一段连续的区间上
- 我们通过后序周游的方法就可以做到,对于节点u的子树,我们记录它最左的叶子节点对应的数组位置pos_l,后它自己的所在的数组位置pos_r,[pos_l, pos_r]既是我们所要更新或查询的区间
实现
#include <bits/stdc++.h>using namespace std;const int maxn = 4e5 + 5;typedef long long ll;typedef pair<int,int> pii;#define pb push_back#define mp make_pair#define fi first#define se secondll setv[maxn<<2];ll orv[maxn<<2];vector<ll> a;pii id[maxn];ll col[maxn];vector<int> g[maxn];int n,m;ll build(int u, int l, int r){ if (l == r){ return orv[u] = a[l]; } int mid = (l+r)/2, chl = 2 * u + 1, chr = 2 * u + 2; return orv[u] = build(chl, l, mid) | build(chr, mid+1, r);}int x1,x2;ll c;void update(int u, int l, int r){ if (x1 <= l && x2 >= r){ orv[u] = c; setv[u] = c; return; } if (x1 > r || x2 < l){ return; } int mid = (l+r)/2, chl = 2 * u + 1, chr = 2 * u + 2; //标志下移 if (setv[u] != 0){ orv[chl] = orv[chr] = setv[chl] = setv[chr] = setv[u]; setv[u] = 0; } update(chl, l, mid); update(chr, mid+1, r); orv[u] = orv[chr] | orv[chl];}ll query(int u,int l, int r){ if (x1 > r || x2 < l){ return 0; } if (setv[u] != 0){ return setv[u]; } if (x1 <= l && x2 >= r){ return orv[u]; } int mid = (l+r)/2, chl = 2 * u + 1, chr = 2 * u + 2; return query(chl, l, mid) | query(chr, mid+1, r);}int mark[maxn];int dfs(int u){ mark[u] = 1; int tmp = -1; for (int e=0; e<g[u].size();e++){ int v = g[u][e]; if (mark[v] == 1){ continue; } if (tmp == -1){ tmp = dfs(v); } else{ dfs(v); } } if (tmp == -1){ tmp = a.size(); } id[u] = mp(tmp, a.size()); a.pb(col[u]); return tmp;}int main(){ ios::sync_with_stdio(false); cin>>n>>m; for (int i=1;i<=n;i++){ int c; cin>>c; col[i] = (ll)1 << (ll)(c-1); } for (int i=0;i<n-1;i++){ int u,v; cin>>u>>v; g[u].pb(v); g[v].pb(u); } dfs(1); //for (int i=1;i<=n;i++){ // cout << id[i].fi << "," << id[i].se << endl; //} build(0, 0, a.size()-1); for (int i=0;i<m;i++){ int t,x,y; cin>>t; if (t == 1){ cin>>x>>y; x1 = id[x].fi; x2 = id[x].se; c = (ll)1 << (ll)(y-1); update(0, 0, a.size()-1); } else{ cin>>x; x1 = id[x].fi; x2 = id[x].se; ll tmp = query(0, 0, a.size()-1); int ans = 0; while (tmp > 0){ if (tmp & 1LL){ ans++; } tmp >>= 1LL; } cout << ans << endl; } } return 0;}
1 0
- Codeforces 620E New Year Tree dfs + 线段树(区间查询+区间置数) + 位运算
- CodeForces - 620E New Year Tree DFS序列 线段树区间置数 状压
- codeforces 620E New Year Tree (DFS序+线段树区间操作+二进制)
- CodeForces - 620E New Year Tree (线段树+dfs序)
- CodeForces 620E New Year Tree(线段树)
- Codeforces 620E New Year Tree (哈希 + 线段树)
- CodeForces 620 E.New Year Tree(线段树)
- Codeforces 620E New Year Tree dfs序+线段树+状态压缩
- Educational Codeforces Round 6 E. New Year Tree(DFS序+线段树)
- Educational Codeforces Round 6 E. New Year Tree(dfs序线段树)
- Educational Codeforces Round 6 E. New Year Tree(DFS序+线段树)
- CodeForces 620E New Year Tree 线段树
- 【Educational Codeforces Round 6E】【线段树 dfs序】New Year Tree 子树颜色修改子树颜色数
- cf602e New Year Tree dfs序+二进制+线段树区间修改
- Codeforces edu 6. E New Year Tree 图论 线段树
- codeforces New Year Tree dfs序+线段树+状态压缩
- 【CF 620E 】New Year Tree 【DFS+线段树+状态压缩】
- Codeforces Round #442E-dfs序&线段树的区间更新区间查询-Danil and a Part-time Job
- 缓存、缓存算法和缓存框架
- Android 插件式开发
- ubuntu15.04 pip安装Scrapy失败 ImportError: cannot import name IncompleteRead解决方案
- 数据绑定框架:Databinding
- 一个5年运维工程师的新年回首
- Codeforces 620E New Year Tree dfs + 线段树(区间查询+区间置数) + 位运算
- Python面向对象编程(二)
- 详解java解压缩zip和rar的工具类使用教程
- ElasticSearch搜索集群
- Service和IntentService 源码分析和总结
- 步进电机控制之控制精度讨论
- Android Training 的整理和总结
- ZOJ-2849-Attack of Panda Virus【bfs】【优先级队列】【4th浙江省赛】【好题】
- BitmapFactory.decodeStream 内存溢出java.lang.OutOfMemoryError