您的位置:首页 > 移动开发

poj 3321 Apple Tree(建树 + 树状数组)

2012-07-31 09:44 337 查看
题意:给出一个树,每个树枝上都有一个苹果,给出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
;
//后寻遍历存储节点
struct point
{
int low ;
int high ;
}d
;

int head
, num , index ;
int app
, s
, 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 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: