poj 3321 Apple Tree( 树状数组 )
2011-06-25 22:49
399 查看
题意 : 有一颗N(N<=10^5)叉的苹果树,每个叉处长有一个苹果。
对该果树有两种操作:
'C x' : 更新果树,若x叉处有苹果,则摘下;若没有,则长出一个新的。
'Q x' : 统计子树x上的苹果数量(包括x)
这题的关键就是怎样将树中的节点映射到树状数组。
解决 : 找到树节点的偏序关系。
这是我第一道树状数组,感觉树状数组中的元素一定要满足偏序关系,找到偏序关系是应用树状数组的关键,呵呵,不知道这个感觉是否正确,以后遇到了再总结。
[b]PS : 树状数组中每个元素都记录并保持了它之前所有元素之和。
前i个元素之和 C[i]
区间[i,j]中元素之和 C[j] - C[i]
对该果树有两种操作:
'C x' : 更新果树,若x叉处有苹果,则摘下;若没有,则长出一个新的。
'Q x' : 统计子树x上的苹果数量(包括x)
这题的关键就是怎样将树中的节点映射到树状数组。
解决 : 找到树节点的偏序关系。
这是我第一道树状数组,感觉树状数组中的元素一定要满足偏序关系,找到偏序关系是应用树状数组的关键,呵呵,不知道这个感觉是否正确,以后遇到了再总结。
Problem: 3321 User: 090609103 Memory: 7212K Time: 1000MS Language: C++ Result: Accepted Source Code #include <iostream> using namespace std; const int Max = 100000; // 对象 struct Edge { int id; // 终点号 Edge* next; Edge( const int id ) { this->id = id; next = NULL; } }; struct Node { Edge *first, *last; int low, high; bool is_picked; }nodes[Max+1]; // 树(邻接表) int C[Max+1]; // 树状数组 int N; // 节点数 int count; // 函数 /* * 映射 : 树->树状数组 * 即找到树中节点的偏序关系 */ void DFS( const int id ) { nodes[id].low = ++ count; Edge* p = nodes[id].first; while( p ) { DFS( p->id ); p = p->next; } nodes[id].high = count; } /* * 释放邻接表 */ void Dispose() { for( int i = 1; i <= N; ++ i ) while( nodes[i].first ) { Edge* s = nodes[i].first; nodes[i].first = s->next; delete s; } } //-----------------树状数组操作------------------// int TreeScope( const int x ) { return ( x ^ (x - 1) ) & x; } void Update( int x, const int value ) { while( x <= N ) { C[x] += value; x += TreeScope( x ); // 得到父节点 } } int GetSum( int x ) { int sum = 0; while( x > 0 ) { sum += C[x]; x -= TreeScope( x ); // 得到兄弟节点 } return sum; } //-----------------------------------------------// int main() { scanf( "%d", & N ); memset( nodes, 0, sizeof(nodes) ); for( int i = 0; i < N - 1; ++ i ) { int b, e; scanf( "%d%d", & b, & e ); Edge* s = new Edge( e ); if( !nodes.first ) nodes[b].first = nodes[b].last = s; else { nodes[b].last->next = s; nodes[b].last = s; } } // 映射 count = 0; DFS( 1 ); // 初始化树 for( int i = 1; i <= N; ++ i ) Update( i, 1 ); // M次操作 int M, x; char ch; scanf( "%d", & M ); while( M-- ) { getchar(); scanf( "%c%d", & ch, & x ); switch( ch ) { case 'C':{ if( nodes[x].is_picked ) { Update( nodes[x].low, 1 ); nodes[x].is_picked = false; } else { Update( nodes[x].low, -1 ); nodes[x].is_picked = true; } }break; case 'Q':{ int num = GetSum( nodes[x].high ) - GetSum( nodes[x].low - 1 ); printf( "%d/n", num ); }break; } } ::Dispose(); return 0; }
[b]PS : 树状数组中每个元素都记录并保持了它之前所有元素之和。
前i个元素之和 C[i]
区间[i,j]中元素之和 C[j] - C[i]
相关文章推荐
- POJ 3321 Apple Tree 树状数组 树到数组的映射 区间求和
- POJ 3321 - Apple Tree DFS出时间搓,树状数组统计维护..
- POJ 3321 Apple Tree(树状数组)
- POJ 3321 Apple Tree(树状数组)
- POJ 3321 Apple Tree (树状数组)
- POJ 3321 Apple Tree (树状数组)
- poj 3321 Apple Tree 树状数组 dfs序
- POJ 3321 Apple Tree (树状数组)
- POJ-3321 Apple Tree (树状数组 前缀和 dfs序)
- POJ 3321:Apple Tree 树状数组
- poj 3321 Apple Tree(树状数组)
- POJ 3321 Apple Tree【树状数组】
- POJ 3321:Apple Tree 树状数组
- POJ 3321 Apple Tree (树状数组)
- POJ 3321 Apple Tree 树状数组 第一题
- [poj 3321]Apple Tree[树状数组]
- POJ---3321-Apple tree(树状数组)
- poj 3321 Apple Tree(一维树状数组)
- POJ 3321 Apple Tree (树状数组)
- POJ 3321 Apple Tree 【树形结构转变为线性结构+线段树OR树状数组】