pku3321 Apple Tree

思路:
对结点重编号,使得每棵子树内的结点的编号连续,便可将问题转化为树状数组求区间和,
用后序遍历对整棵树进行重编号能满足要求。
除了要在每个结点处记录新编号tag外,还要记录该结点对应的子树的最小结点编号mn,对
于每个结点x,其苹果个数为sum(x.tag)-sum(x.mn-1)。

 

#include  < iostream >
#include 
< algorithm >
using   namespace  std;

#define  MAXN 100001

int  n,m,cnt,c[MAXN],a[MAXN];
// cnt在结点重编号中作统计用,a[i]表示重编号后第i号结点上的苹果数
bool  s[MAXN];

struct  Link{
    
int  v;
    Link 
* next;
}
* link[MAXN];

struct  Node{
    
int  tag,mn;
}nod[MAXN];

void  init(){
    memset(link,NULL,
sizeof (link));
    memset(nod,
0 , sizeof (nod));
    memset(c,
0 , sizeof (c));
    memset(s,
false , sizeof (s));
    cnt
= 1 ;
    Link 
* temp;
    
int  i,x,y;
    
for (i = 0 ;i < n - 1 ;i ++ ){
        scanf(
" %d%d " , & x, & y);
        temp
= new  Link;
        temp
-> v = x;
        temp
-> next = link[y];
        link[y]
= temp;

        temp
= new  Link;
        temp
-> v = y;
        temp
-> next = link[x];
        link[x]
= temp;
    }
}

void  dfs( int  u){
    Link 
* temp;
    nod[u].mn
= cnt;
    temp
= link[u];
    
while (temp){
        
if ( ! s[temp -> v]){
            s[temp
-> v] = true ;
            dfs(temp
-> v);
        }
        temp
= temp -> next;
    }
    nod[u].tag
= cnt ++ ;
}

inline 
int  lowbit( int  x){
    
return  x & ( - x);
}

void  change( int  x){
    
int  i;
    
if (a[x])
        
for (i = x;i < cnt;i += lowbit(i))
            c[i]
++ ;
    
else
        
for (i = x;i < cnt;i += lowbit(i))
            c[i]
-- ;
}


int  sum( int  x){
    
int  i,res = 0 ;
    
for (i = x;i > 0 ;i -= lowbit(i))
        res
+= c[i];
    
return  res;
}


int  main(){
    
int  i,x;
    
char  str[ 3 ];
    
while (scanf( " %d " , & n) != EOF){
        init();
        s[
1 ] = true ;
        dfs(
1 );
        scanf(
" %d " , & m);
        
for (i = 1 ;i < cnt;i ++ ){
            a[i]
= 1 ;
            change(i);
        }
        
for (i = 0 ;i < m;i ++ ){
            scanf(
" %s " ,str);
            scanf(
" %d " , & x);
            
if (str[ 0 ] == ' Q ' )
                printf(
" %d\n " ,sum(nod[x].tag) - sum(nod[x].mn - 1 ));
            
else {
                a[nod[x].tag]
= (a[nod[x].tag] + 1 ) % 2 ;
                change(nod[x].tag);
            }
        }
    }
    
return   0 ;
}

转载于:https://www.cnblogs.com/zgmf_x20a/archive/2008/10/29/1322238.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值