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\n", t1 - t2);
        }
    }
    return 0;
}

 

posted @ 2017-08-07 09:42  _Mickey  阅读(97)  评论(0编辑  收藏  举报