Codeforces Round #442 (Div. 2) 877 E. Danil and a Part-time Job DFS序 线段树
来源:互联网 发布:mysql 多字段排序 编辑:程序博客网 时间:2024/05/16 02:56
题目链接: E. Danil and a Part-time Job
题目大意
一棵有根树, 每个节点可以是1或者0, 两种操作:
1. pow v: 将v节点的子树中所有节点的值反置(1变0, 0变1, 相当于异或1)
2. get v: 输出v节点的字数中1的个数
节点个数:
思路
对树的某个子树所有节点进行操作, 很显然要用dfs序将树转换成一条线, 对树进行dfs, 记录下每个节点i的访问起始时间in[i]和结束时间out[i], 这样节点i的序号是in[i], 节点i子树所有节点的序号集合是[in[i], out[i]], 这样将对子树的操作转换成对一个区间的操作, 用线段树处理就好了
dfs处理后的节点的[in[i], out[i]]
线段树用懒惰标记实现快速区间更新, 反转时, 区间和变成 区间长度-原来的区间和
代码
GNU C++14 Accepted 327 ms 24400 KB
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>using namespace std;const int maxn = 2e5 + 100;int p, t[maxn], in[maxn], out[maxn], n, a[maxn];vector<int> G[maxn];void dfs(int s, int & x){ in[s] = x; for (int ite : G[s]) dfs(ite, ++x); out[s] = x;}#define ls l , m , rt << 1#define rs m + 1 , r , rt << 1 | 1int sum[maxn << 2], col[maxn << 2];void pushUp(int rt){ sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];}void pushDown(int rt, int m){ if (col[rt]) { col[rt << 1] ^= col[rt]; col[rt << 1 | 1] ^= col[rt]; sum[rt << 1] = (m - m / 2) - sum[rt << 1]; sum[rt << 1 | 1] = m / 2 - sum[rt << 1 | 1]; col[rt] = 0; }}void build(int l, int r, int rt){ col[rt] = 0; if (l == r) { sum[rt] = a[l]; } else { int m = (l + r) / 2; build(ls); build(rs); pushUp(rt); }}void update(int L, int R, int l, int r, int rt){ if (L <= l && r <= R) { col[rt] ^= 1; sum[rt] = r - l + 1 - sum[rt]; return ; } pushDown(rt, r - l + 1); int m = (l + r) / 2; if (L <= m) update(L, R, ls); if (R > m) update(L, R, rs); pushUp(rt);}int query(int L, int R, int l, int r, int rt){ if (L <= l && r <= R) return sum[rt]; pushDown(rt, r - l + 1); int m = (l + r) / 2; int ret = 0; if (L <= m) ret += query(L, R, ls); if (R > m) ret += query(L, R, rs); return ret;}int main(){ scanf("%d", &n); for (int i = 2; i <= n; ++i) { scanf("%d", &p); G[p].push_back(i); } int x = 1; dfs(1, x); for (int i = 1; i <= n; ++i) { scanf("%d", &a[in[i]]);//a[x]记录dfs序号为x的节点的值 } build(1, n, 1); int q; scanf("%d", &q); char op[10]; while (q--) { scanf("%s%d", op, &x); if (op[0] == 'g') { printf("%d\n", query(in[x], out[x], 1, n, 1)); } else { update(in[x], out[x], 1, n, 1); } } return 0;}
阅读全文
0 0
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job【线段树+dfs序】
- Codeforces Round #442 (Div. 2) 877 E. Danil and a Part-time Job DFS序 线段树
- Codeforces Round #442 (Div. 2)-E-Danil and a Part-time Job(DFS序+线段树区间更新)
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job DFS序+树链剖分+线段树区间^
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job (dfs序+线段树)
- Codeforces Round #442 (Div. 2) Danil and a Part-time Job dfs序+线段树区间反转
- Codeforces Round #442E-dfs序&线段树的区间更新区间查询-Danil and a Part-time Job
- Codeforces 877E Danil and a Part-time Job【Dfs序+线段树】
- Codeforces 877 E Danil and a Part-time Job(线段树+dfs序)
- [codeforces] 877E. Danil and a Part-time Job(DFS序+线段树)
- CodeForces 877E Danil and a Part-time Job (dfs序+线段树)
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job (dfs序树型转线性 线段树区间修改区间查询)
- Codeforces-877E:Danil and a Part-time Job(DFS序列+线段树)
- codeforces 877E. Danil and a Part-time Job (DFS序列+线段树)
- Codeforces Round #877 (Div. 2) E. Danil and a Part-time Job
- Codeforces Round #442 (Div. 2) E. Danil and a Part-time Job
- codeforces 877 problem E Danil and a Part-time Job 【dfs序 + 线段树区间异或修改】
- CF#877 E. Danil and a Part-time Job(DFS序+线段树)
- Kafka之——安装并(单节点)配置启动Kafka
- H2.64中I帧和IDR帧的区别(转)
- Linux 4.13 特性汇总
- Canvas弹幕实现
- 树莓派在ssh中添加root用户
- Codeforces Round #442 (Div. 2) 877 E. Danil and a Part-time Job DFS序 线段树
- 欢迎使用CSDN-markdown编辑器
- C#异常与调试
- Android Studio 上传项目到GitHub出现:The requested URL returned error: 403
- scrapy爬取网页内容出现“gbk”出错的编码问题解决方案
- HTTPS的过程分析
- CF#877 A. Alex and broken contest(KMP)
- 群晖系统-----------SVN入门笔记
- JMeter:Dashboard Report自动生成测试报告的巧用和避坑