DFS序+树状数组

#include
using namespace std;
int tr[10003],in[10003],ou[10003],fo[10003];
vectoredge[10003];
int n,m,key;
//修改节点k,添加代入1,删除代入-1
void add(int x,int val){
    while(x<=n){
        tr[x]+=val;
        x+=x&(-x);
    }
}
//得到1...x的和
int query(int x){
    int rec=0;
    while(x>0){
        rec+=tr[x];
        x-=x&(-x);
    }
    return rec;
}
//为每一个node添加一个左值和右值
void dfs(int node){
    in[node]=key;
    for(int i=0;i>a>>b;
            edge[a].push_back(b);
        }
        key=1;
        dfs(1);
        //为每一个节点对应一个左边界和右边界
        //他自己就存放在左边界里面
        //而它的管辖范围就是左边界到右边界
        for(int i=1;i<=n;i++){
            fo[i]=1;//最初每个Fork上都有一个苹果
            add(i,1);//同时更新树状数组的值
        }
        cin>>m;
        for(int i=0;i>ch>>b;
            if(ch=='Q'){//b子树就是[Left[b],right[b]]
                int tmp=query(ou[b])-query(in[b]-1);
                cout<

DFS序+树状数组POJ3321 Apple Tree

题意:一颗树最初每个节点上都有一个苹果,有两种操作:修改(修改某一个节点,修改时这一个节点苹果从有到无,或从无到有)和查询(查询某一个节点他的子树上有多少个苹果)。由于此题数据比较大(N<=10^5),而且不是标准的二叉树,所以这里我们队每一个节点重新编号,另外为每一个节点赋一个左值和一个右值,表示这个节点的管辖范围。

DFS序+树状数组_第1张图片

上图也就是DFS搜索的时候做标记的过程,这样新的编号为1~6的节点所管辖的范围分别就是[1,6]  [2,4]   [3,3]  [4,4]  [5,6]  [6,6],其中左边的是左值,右边的是右值,节点1的区间是[1,6],正好这棵子树有6个节点,其他也一样。新的节点放进树状数组,求出每一个节点从1~左值-1的和和1~右值的和,他们的差就是这个节点的子树的所有的和(即这棵子树苹果数目)

 

你可能感兴趣的:(ACM笔记-2串树)