zoukankan      html  css  js  c++  java
  • POJ 3321 apple tree(树形数组)

    题意:

    一棵具有n个节点的树,一开始,每个节点上都有一个苹果。现在给出m组动态的操作:

    (C,i)是摘掉第i个节点上面的苹果(若苹果不存在,则为加上一个苹果),(Q,i)是查询以第i个节点为根的子树有几个苹果(包括第i个节点)。

    参考了:http://www.cnblogs.com/ybrbupt/archive/2011/09/24/2189519.html

    思路:

    树形数组,但是问题的关键是,如何把树的各个节点映射到数组中去,然后再应用树形数组的优势去解决?

    dfs()函数中的代码就十分精妙的体现了如何去映射。相当于把每个节点重新编号了。

    初始化要注意,因为开始默认每个节点都会有个苹果,所以先要对c[]数组进行初始化,c[]对应的线性数组每个元素都是1,所以c[i]=i&-i就行了

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    
    using namespace std;
    
    const int MAXN = 100010;
    
    vector<vector<int>> G(MAXN);
    bool vis[MAXN];
    bool apple[MAXN];
    int high[MAXN], low[MAXN];
    int c[MAXN];
    int n, count;
    
    inline int lowbit(int x)
    {
        return x & (-x);
    }
    
    void dfs(int u)
    {
        vis[u] = true;
        low[u] = count;  // 节点u为根节点的子树映射到数组内的下届
        
        for (int i = 0; i < G[u].size(); ++i)
        {
            int v = G[u][i];
            if (!vis[v])
                dfs(v);
        }
        high[u] = count++; // 节点u为根节点的子树映射到数组内的上界
    }
    
    int sum(int p)
    {
        int ans = 0;
        for (int i = p; i > 0; i -= lowbit(i))
            ans += c[i];
        return ans;
    }
    
    inline void update(int p)
    {
        int d;
        if (apple[p])
            d = -1;
        else
            d = 1;
        apple[p] ^= true;
        for (int i = p; i <= n; i += lowbit(i))
            c[i] += d;
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i)
            c[i] = lowbit(i), apple[i] = true, vis[i] = false;
    
        for (int i = 1; i < n; ++i)
        {
            int a, b;
            scanf("%d %d", &a, &b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        count = 1;
        dfs(1);
    
        int m;
        scanf("%d", &m);
        for (int i = 1; i <= m; ++i)
        {
            char s[10];
            int u;
            scanf("%s %d", s, &u);
            if (s[0] == 'Q')
                printf("%d\n", sum(high[u]) - sum(low[u]-1));
            else if (s[0] == 'C')
                update(high[u]);
        }
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    UCOS内核
    ##API(七)————日期操作类(二)
    ##Webstrom打开显示老长一段英文This lincense GY4D6P7914 has been cancelled.,就是打不开怎么解决
    ##API(六)————日期操作类(一)
    ##API(五)————StringBuffer类和StringBuilder类(重要)
    ##API(四)————String类的常用方法
    ##API(三)————Math类
    ##API(二)————包装类
    ##API的简介
    ##API(一)————枚举
  • 原文地址:https://www.cnblogs.com/kedebug/p/2763460.html
Copyright © 2011-2022 走看看