本题最关键的就是dfs序,这跟之前有一道求父节点中的节点个数很像,我们对这个树进行dfs,记录他开始的节点和最终的节点,这样只要在两个点之间做dfs就行了

首先这不会破坏树的结构,其次,他还表示了每个节点间的相对关系,这是一种很常见的树状数组的技巧

本篇代码需要用c++交,如果想用g++,需要把vector的格式改一下,具体原理我也不懂,反正每次交题的时候,最好用c++交,特别是poj的评测机。

POJ3321 Apple Tree(树状数组)_寒假训练POJ3321 Apple Tree(树状数组)_杭电oj与poj_02
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
int st[N];
int ed[N];
int tr[N];
int vis[N];
vector<int> ma[N];
int n;
int idx;
void dfs(int u){
    idx++;
    st[u]=idx;
    for(int i=0;i<ma[u].size();i++){
        dfs(ma[u][i]);
    }
    ed[u]=idx;
}
int lowbit(int x){
    return x&-x;
}
void add(int x,int c){
    int i;
    for(i=x;i<=n;i+=lowbit(i)){
        tr[i]+=c;
    }
}
int sum(int x){
    int i;
    int res=0;
    for(i=x;i;i-=lowbit(i)){
        res+=tr[i];
    }
    return res;
}
int main(){
    int i;
    cin>>n;
    for(i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        ma[u].push_back(v);
    }
    dfs(1);
    for(i=1;i<=n;i++){
        add(st[i],1);
        vis[i]=1;
    }
    int m;
    cin>>m;
    while(m--){
        char s[N];
        scanf("%s",s);
        if(*s=='C'){
            int x;
            scanf("%d",&x);
            if(vis[x]){
                add(st[x],-1);
                vis[x]=0;
            }
            else{
                add(st[x],1);
                vis[x]=1;
            }
        }
        else{
            int x;
            scanf("%d",&x);
            printf("%d\n",sum(ed[x])-sum(st[x]-1));
        }
    }
}
View Code

 

没有人不辛苦,只有人不喊疼