POJ3321 线段树水题
2016-05-29 23:25
337 查看
题目大意
给出一个 N 个节点的树,对于每个节点上一开始都有一个苹果,有 M 个操作,有 C x,Q x 两个操作,C x表示把 x 号节点如果有苹果就拿掉,否则就放上一个,Q x 表示查询 x 为根的子树的苹果当前有几个 (N, M <= 100000)题解
这题其实就是线段树模板题
只是对于所有树上的节点,我们用 dfs 时间戳 (dfs 序) 来映射成一段连续的,然后对于一个节点的子树对应的区间就是 d[x], d[x] + size[x] - 1,然后直接查询修改即可#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <set> #include <map> #include <stack> #include <queue> #include <vector> using namespace std; #define begin Begin #define next Next #define REP(i, a, b) for (int i = (a), _end_ = (b); i <= _end_; ++i) #define EREP(i, a) for (int i = begin[a]; i > 0; i = next[i]) #define debug(...) fprintf(stderr, __VA_ARGS__) #define mp make_pair #define x first #define y second #define pb push_back #define SZ(x) (int((x).size())) #define ALL(x) (x).begin(), (x).end() template<typename T> inline bool chkmin(T &a, const T &b){ return a > b ? a = b, 1 : 0; } template<typename T> inline bool chkmax(T &a, const T &b){ return a < b ? a = b, 1 : 0; } typedef long long LL; const int dmax = 100100 << 2, oo = 0x3f3f3f3f; int n, m; int begin[dmax], to[dmax], next[dmax], e; int d[dmax], size[dmax], dis; int c[dmax]; inline void init() { e = dis = 0; memset(begin, 0, sizeof begin); } inline void add(int x, int y) { to[++e] = y; next[e] = begin[x]; begin[x] = e; } void dfs(int x, int fa) { size[x] = 1; d[x] = ++dis; EREP(i, x) if (to[i] != fa) { dfs(to[i], x); size[x] += size[to[i]]; } } #define left x << 1, l, mid #define right x << 1 | 1, mid + 1, r template<typename T> inline T Mid(const T &x, const T &y){ return (x + y) >> 1; } inline void push_up(int x){ c[x] = c[x << 1] + c[x << 1 | 1]; } void create(int x, int l, int r) { if (l == r) { c[x] = 1; return; } int mid = Mid(l, r); create(left); create(right); push_up(x); } int query(int x, int l, int r, int s, int t) { if (l >= s && r <= t) return c[x]; int mid = Mid(l, r); int sum = 0; if (s <= mid) sum += query(left, s, t); if (t > mid) sum += query(right, s, t); return sum; } void update(int x, int l, int r, int t) { if (l == r) { c[x] ^= 1; return; } int mid = Mid(l, r); if (t <= mid) update(left, t); else update(right, t); push_up(x); } int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); #endif while (scanf("%d", &n) != EOF) { init(); REP(i, 1, n - 1) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); } dfs(1, 0); create(1, 1, n); scanf("%d", &m); getchar(); REP(i, 1, m){ char c = getchar(); int x; scanf("%d", &x); if (c == 'Q') printf("%d\n", query(1, 1, n, d[x], d[x] + size[x] - 1)); else update(1, 1, n, d[x]); getchar(); } } return 0; }
相关文章推荐
- Java RMI 入门指南 转自 http://www.blogjava.net/zhenyu33154/articles/320245.html
- java/android 设计模式学习笔记(5)---对象池模式
- WEB开发的套路——记录的更新
- ios UITextField 设置光标的起始位置, 让其右移
- KMP算法
- KMP算法
- JAVA_OA管理系统(二)番外篇:IoC原理
- 二叉树的遍历
- Cocos2d3.x之C3130: 编译器错误: 未能将插入的代码块写入PDB
- 位图BitMap
- Android 手动显示和隐藏软键盘
- [leetcode] 【数组】 135. Candy
- spark之RDD
- 每秒处理10万订单乐视集团支付架构
- java 集合练习题2
- 使用xshell登陆腾讯云主机
- JavaScript权威指南第一章 概述
- vs签入签出-TFS进行源代码管理
- 位运算(一):二进制中1的个数
- Spring in action 03 -- 装配 Bean(xml配置)