Apple Tree----树的遍历和树状数组的结合

来源:互联网 发布:psp视频不兼容的数据 编辑:程序博客网 时间:2024/05/06 02:15

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=231

解题思路:苹果完全可以倒过来看做一棵树(注意不一定是二叉树),求一个分叉上面的苹果数量,就是求颗子树有多少节点,对于一个树进行一次遍历后,所有节点都已经访问过了,将遍历序列使用树状数组记录下来的,只需一个start数组和end数组记录每个子树的开始和结束在序列中的位置,就可以快速的得到子树的节点数量。

本题只需对数进行先根遍历,记录树状数组和开始结束位置,再使用一个has数组对每一个节点标记是否有苹果。对于每次改变状态,使用树状数组的modify函数对所有涉及到的位置进行改变即可。

代码附上:

#include<stdio.h>#include<vector>#include<string.h>using namespace std;int nCount = 0;vector<int> G[100005];int C[100005], has[100005];int Start[100005], End[100005];void DFS(int x) {    Start[x] = ++nCount; //标记开始位置    for(int i = 0; i < G[x].size(); i++) {        DFS(G[x][i]); //标记结束位置    }     End[x] = nCount;}int lowbit(int x) {return x&(-x);}int Sum(int x) {    int nSum = 0;    while(x > 0) {        nSum += C[x];        x -= lowbit(x);    }    return nSum;}    void Modify(int x, int val) {    while(x <= nCount) {        C[x] += val;        x += lowbit(x);    }    } int main() {//freopen("data.in", "r", stdin);    int n, m;int a,b;scanf("%d", &n);    for(int i = 1;i < n; i++) {           scanf("%d%d", &a, &b);        G[a].push_back(b);    }        nCount = 0; DFS(1);    //每个节点一个苹果,树状数组数值即lowbit     for(int i = 1; i <= nCount; i++) {        C[i] = lowbit(i);    }    memset(has, 1, sizeof(has));    scanf("%d", &m);    for(int i = 0;i < m; i++) {        char cmd[5];        scanf("%s%d", cmd, &a);        if(cmd[0] == 'C') {            if(has[a]) { //如果等于说明该节点有苹果,应该摘取                 has[a] = 0;Modify(Start[a], -1);                            } else {            has[a] = 1;                Modify(Start[a], 1);            }            } else {            printf("%d\n",Sum(End[a]) - Sum(Start[a]-1));        }            }    return 0;        }    



0 0
原创粉丝点击