zoukankan      html  css  js  c++  java
  • POJ 3321 Apple Tree

    题目链接:【http://poj.org/problem?id=3321】

    题意:给你一棵树,有两种操作,第一种是对某个节点进行修改(该节点如果有苹果,就拿掉,如果没有苹果就放上去一个),第二种操作是询问以节点x为根的子树上有多少苹果。

    题解:对一棵树进行DFS,对每一个节点重新编号,并记录下某个节点出的时候当前结点的最大值,也就是说记录了每个节点的编号和这个节点为根所表示的最大区间。这样就可以对利用单点修改区间求和进行求解。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e6 + 15;
    int N, M;
    struct Edge
    {
        int to, next;
        Edge (int to = 0, int next = 0): to(to), next(next) {}
    } E[maxn];
    int head[maxn], tot;
    void initEdge()
    {
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    void addEdge(int u, int v)
    {
        E[tot] = Edge(v, head[u]);
        head[u] = tot++;
    }
    int L[maxn], R[maxn], dfs_clock;
    void DFS(int u, int fa)
    {
        L[u] = ++dfs_clock;
        for(int k = head[u]; ~k; k = E[k].next)
        {
            int v = E[k].to;
            if(v == fa) continue;
            DFS(v, u);
        }
        R[u] = dfs_clock;
    }
    int sum[maxn], vis[maxn];
    int low_bit(int x)
    {
        return x & (-x);
    }
    void add_Sum(int p, int val)
    {
        while(p <= N)
        {
            sum[p] += val;
            p += low_bit(p);
        }
    }
    int get_Sum(int p)
    {
        int ret = 0;
        while(p)
        {
            ret += sum[p];
            p -= low_bit(p);
        }
        return ret;
    }
    int main ()
    {
        initEdge();
        scanf("%d", &N);
        for(int i = 1; i <= N - 1; i++)
        {
            int u, v;
            scanf("%d %d", &u, &v);
            addEdge(u, v);
            addEdge(v, u);
        }
        DFS(1, 0);
        for(int i = 1; i <= N; i++)
        {
            add_Sum(i, 1);
            vis[i] = 1;
        }
        scanf("%d", &M);
        for(int i = 1; i <= M; i++)
        {
            char s[5];
            int  p;
            scanf("%s %d", s + 1, &p);
            if(s[1] == 'C')
            {
                if(vis[L[p]])
                    add_Sum(L[p], -1);
                else
                    add_Sum(L[p], 1);
                vis[L[p]] ^= 1;
            }
            else if(s[1] == 'Q')
            {
                int t1 = get_Sum(R[p]);
                int t2 = get_Sum(L[p] - 1);
                printf("%d
    ", t1 - t2);
            }
        }
        return 0;
    }
  • 相关阅读:
    [荐]推荐一个shell学习的网站
    [转]linux远程登入不需要密码
    [转] eclipce使用vim 开启装逼模式
    Linux 下查找指令
    nmon 工具的使用
    LaTeX 符号大全
    vim 粘贴复制操作
    linux命令模式下如何切换首行和尾行
    fish 与oh-my-fish 的安装
    vim 粘贴复制操作
  • 原文地址:https://www.cnblogs.com/pealicx/p/7297649.html
Copyright © 2011-2022 走看看