题意:给出一个树,每个树枝上都有一个苹果,给出N-1个树枝间的关系,然后给出M个操作,C表示树枝上原来有苹果的摘掉,没有的长出一个苹果,Q表示以这个树枝为根的所有子树的苹果树。
思路:这题的关键就是怎样将树上的各点映射到数组,先通过题目给出的条件建树,注意这题没有说是二叉树,可以用链表的方式建树,然后后序遍历这棵树,同时给各个树枝重新编号,是根的编号总是大于子树编号,然后在更新和查询这个子树时,就可以通过树状数组来实现了。
代码:
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <queue> #include <math.h> #define N 100004 using namespace std ; //存储M个条件 struct node { int u ; int v ; int next ; }p[N] ; //后寻遍历存储节点 struct point { int low ; int high ; }d[N] ; int head[N] , num , index ; int app[N] , s[N] , n , m ; void add( int x , int y ) { p[num].u = x ; p[num].v = y ; p[num].next = head[x] ; head[x] = num++ ; } //后序遍历 void dfs( int x ) { d[x].low = index ; if ( head[x] == -1 ) { d[x].high = index++ ; return ; } for( int v = head[x] ; v != -1 ; v = p[v].next ) { dfs( p[v].v ); } d[x].high = index++ ; } int lowbit( int x ) { return x & ( -x ); } //更新 void update( int x , int v ) { while ( x <= n ) { s[x] += v ; x += lowbit( x ); } } //查询 int sum ( int x ) { int ss = 0 ; while ( x > 0 ) { ss += s[x] ; x -= lowbit( x ); } return ss ; } int main() { int i , x , y ; char c ; while( scanf( "%d" , &n ) != EOF ) { num = 0 ; memset( head , -1 , sizeof( head )); for ( i = 0 ; i < n - 1 ; i++ ) { scanf ( "%d%d" , &x , &y ); add( x , y ); } index = 1 ; dfs( 1 ) ; //初始时每个枝杈上都有一个苹果 for( i = 0 ; i <= n ; i++ ) app[i] = 1 ; for ( i = 1 ; i <= n ; i++ ) s[i] = lowbit( i ); scanf ( "%d" , &m ); getchar(); while( m-- ) { scanf ( "%c%d" , &c , &x ); getchar(); if ( c == 'C') { int state = 1 ; if ( app[x] ) state = -1 ; app[x] = !app[x] ; update( d[x].high , state ); } else { int ss = sum ( d[x].high ) - sum ( d[x].low - 1 ); printf( "%d\n" ,ss ) ; } } } return 0 ; }