ZOJ 3686 A Simple Tree Problem(线段树)
Description
Given a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0.
We define this kind of operation: given a subtree, negate all its labels.
And we want to query the numbers of 1's of a subtree.
Input
Multiple test cases.
First line, two integer N and M, denoting the numbers of nodes and numbers of operations and queries.(1<=N<=100000, 1<=M<=10000)
Then a line with N-1 integers, denoting the parent of node 2..N. Root is node 1.
Then M lines, each line are in the format "o node" or "q node", denoting we want to operate or query on the subtree with root of a certain node.
Output
For each query, output an integer in a line.
Output a blank line after each test case.
题目大意:给一棵多叉树,初始值都为0,o x为翻转以x为根的子树,q x为查询以x为根的子树有多少个1
思路:这数据范围,暴力是不行的,怎么暴力都是不行的>_<。这题的要求是:修改一大片、查询一大片,比较容易想到的就是线段树(树状数组也可以,不过要翻转嘛……好像有难度……反正我不会>_<)。问题是这玩意儿怎么转换成线段树呢?要转化成线段树,就要把每个点的子孙们都放到一片连续的空间里。这时,若使用DFS,遍历的顺序刚刚好符合要求,于是我们就DFSo(∩_∩)o 。DFS途中就可以算出每个点的及其子孙覆盖的区域。然后变成线段树之后呢,随便搞搞就行了o(∩_∩)o
- #include <cstdio>
- #include <cstring>
- const int MAX = ;
- int flip[MAX*], sum[MAX*], cnt[MAX*];//tree
- int head[MAX], next[MAX], to[MAX], ecnt;
- int beg[MAX], size[MAX], dfs_clock;
- int y1, y2;
- void tle() {while() ;}
- void init() {
- ecnt = ;
- dfs_clock = ;
- memset(head, , sizeof(head));
- memset(flip, , sizeof(flip));
- memset(cnt, , sizeof(cnt));
- }
- void add_edge(int u, int v) {
- to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
- }
- void dfs(int x) {
- size[x] = ;
- beg[x] = ++dfs_clock;
- for(int p = head[x]; p; p = next[p]) {
- dfs(to[p]);
- size[x] += size[to[p]];
- }
- }
- void maintain(int x, int l, int r) {
- int lc = x * , rc = x * + ;
- if(l < r) {
- cnt[x] = cnt[rc] + cnt[lc];
- }
- }
- void pushdown(int x) {
- int lc = x * , rc = x * + ;
- if(flip[x]) {
- flip[x] = ;
- flip[lc] ^= ;
- cnt[lc] = sum[lc] - cnt[lc];
- flip[rc] ^= ;
- cnt[rc] = sum[rc] - cnt[rc];
- }
- }
- void update(int x, int l, int r) {
- int lc = x * , rc = x * + ;
- if(y1 <= l && r <= y2) {
- flip[x] ^= ;
- cnt[x] = sum[x] - cnt[x];
- }
- else {
- pushdown(x);
- int mid = (l + r) / ;
- if(y1 <= mid) update(lc, l, mid);
- if(mid < y2) update(rc, mid + , r);
- maintain(x, l, r);
- }
- }
- int ans;
- void query(int x, int l, int r) {
- int lc = x * , rc = x * + ;
- if(y1 <= l && r <= y2) ans += cnt[x];
- else {
- pushdown(x);
- int mid = (l + r) / ;
- if(y1 <= mid) query(lc, l, mid);
- if(mid < y2) query(rc, mid + , r);
- }
- }
- void build(int x, int l, int r) {
- int lc = x * , rc = x * + ;
- if(l == r) {
- sum[x] = ;
- }
- else {
- int mid = (l + r) / ;
- build(lc, l, mid);
- build(rc, mid + , r);
- sum[x] = sum[lc] + sum[rc];
- }
- }
- int main() {
- int n, m, x;
- char c[];
- while(scanf("%d%d", &n, &m) != EOF) {
- init();
- for(int i = ; i <= n; ++i) {
- scanf("%d", &x);
- add_edge(x, i);
- }
- dfs();
- build(, , n);
- while(m--) {
- scanf("%s%d", c, &x);
- y1 = beg[x]; y2 = beg[x] + size[x] - ;
- if(c[] == 'o') {
- update(, , n);
- }
- if(c[] == 'q') {
- ans = ;
- query(, , n);
- printf("%d\n", ans);
- }
- }
- puts("");
- }
- }
ZOJ 3686 A Simple Tree Problem(线段树)的更多相关文章
- ZOJ 3686 A Simple Tree Problem
A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a rooted tree, each no ...
- zoj 3686 A Simple Tree Problem (线段树)
Solution: 根据树的遍历道的时间给树的节点编号,记录下进入节点和退出节点的时间.这个时间区间覆盖了这个节点的所有子树,可以当做连续的区间利用线段树进行操作. /* 线段树 */ #pragma ...
- ZOJ-3686 A Simple Tree Problem 线段树
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686 题意:给定一颗有根树,每个节点有0和1两种值.有两种操作: ...
- bzoj 3489 A simple rmq problem - 线段树
Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...
- hdu 4973 A simple simulation problem. (线段树)
题目链接 题意: 给定n长的序列 m个操作 序列默认为 1, 2, 3···n 操作1:D [l,r] 把[l,r]区间增长 :( 1,2,3,4 进行 D [1,3]变成 1,1,2,2,3,3,4 ...
- BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】
A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...
- 【BZOJ4999】This Problem Is Too Simple!(线段树)
[BZOJ4999]This Problem Is Too Simple!(线段树) 题面 BZOJ 题解 对于每个值,维护一棵线段树就好啦 动态开点,否则空间开不下 剩下的就是很简单的问题啦 当然了 ...
- xtu数据结构 I. A Simple Tree Problem
I. A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB 64-bit integer IO format: %lld ...
- hdu 5274 Dylans loves tree(LCA + 线段树)
Dylans loves tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
随机推荐
- c#(IronPython)调用Python方法
直接一段代码演示 public void StartTCP() { ScriptEngine engine = Python.CreateEngine(); var paths = engine.Ge ...
- JavaScript基础部分经典案例
再复杂的程序都是由一个个简单的部分组成. 001案例 - 交换两个变量的值 方法01 - 使用临时变量 var n1 = 5; var n2 = 6; // 创建一个临时中介变量 tmp var tm ...
- SQL 存储过程生成
use workflow; GO /****** 对象: StoredProcedure [dbo].[pro_GenerateProGet] 脚本日期: 08/03/2012 11:26:43 ** ...
- JS中new运算符的实现原理
当我们用new运算符new一个构造函数产生一个实例时,比如说: var obj = new Func 时,其背后的步骤是这样的: 1:创建一个继承自 Func.prototype 的新对象:2:执行构 ...
- Java OOP——第六章 框架集合
1.集合框架包含的主要内容及彼此之间的关系: 图1: 集合框架:是为了表示和操作集合而统一规定的一种统一的标准体系结构. 包含三大块的内容:对外的接口.接口的是实现和对 ...
- Vue——关于css过渡和动画那些事
1. 单元素/组件的过渡transition Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡 条件渲染 (使用 v-if) 条件展示 (使用 v ...
- 关于windows下安装mysql数据库出现中文乱码的问题
首先需要在自己安装的mysql路径下新建一个my.ini文件,如下: 然后在my.ini文件中输入一下内容,主要控制编码问题的为红框部分,如下: 为了方便大家使用,可以复制以下代码: [WinMySQ ...
- php的基础知识(一)
php(超文本预处理器)定义: php(外文名:php:Hertext Preprocessor,中文名:“超文本预处理器”)是一种通用的开源脚本语言.语法吸收了C语言.Java和Perl的特点,利于 ...
- 关于一个flask的服务接口实战(flask-migrate,flask-script,SQLAlchemy)
前言 最近接到一个接收前端请求的需求,需要使用python编写,之前没有写过python,很多技术没有用过,在这里做一个学习记录,如有错误,请不了赐教. Flask Api文档管理 使用Falsk A ...
- gmtime与mktime的重新编写
这几日发现Linux的mktime与gmtime所处理的数据类型是32位的,即代表时间设置只能设置到2038年,在公司的产品要实现这个时间的突破还是得自己写一个新的处理时间的函数. 作为一个刚毕业的程 ...