POJ 3321 Apple Tree DFS序 + 树状数组

多次修改一棵树节点的值,或者询问当前这个节点的子树所有节点权值总和。

首先预处理出DFS序L[i]和R[i]

把问题转化为区间查询总和问题。单点修改,区间查询,树状数组即可。

注意修改的时候也要按照dfs序修改,因为你查询就是按照dfs查的,所以修改也要用dfs序修改

L[i]是唯一的。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000 + 20;
int first[maxn], L[maxn], R[maxn], a[maxn];
struct edge {
    int u, v;
    int next;
} e[maxn * 2];
int n, num;
void add (int u, int v)
{
    ++num;
    e[num].u = u;
    e[num].v = v;
    e[num].next = first[u];
    first[u] = num;
}
bool book[maxn];
int index;
void dfs (int cur)
{
    L[cur] = index;
    for (int i = first[cur]; i; i = e[i].next) {
        if (book[e[i].v] == 0) {
            book[e[i].v] = 1;
            index++;
            dfs (e[i].v);
        }
    }
    R[cur] = index;
}
int c[maxn];//树状数组,多case的记得要清空
int lowbit (int x)//得到x二进制末尾0的个数的2次方 2^num
{
    return x&(-x);
}
void addc (int pos,int val)//在第pos位加上val这个值
{
    while (pos<=n) { //n是元素的个数
        c[pos] += val;
        pos += lowbit(pos);
    }
    return ;
}
int get_sum (int pos) //求解:1--pos的总和
{
    int ans = 0;
    while (pos) {
        ans += c[pos];
        pos -= lowbit(pos);
    }
    return ans;
}

void work ()
{
    for (int i = 1; i <= n - 1; ++i) {
        int u, v;
        scanf ("%d%d", &u, &v);
        add (u, v);
    }
    for (int i = 1; i <= n; ++i) {
        addc (i, 1);
        a[i] = 1;
    }
    dfs (1);
    int m;
    scanf ("%d", &m);
    for (int i = 1; i <= m; ++i) {
        char str[3];
        int id;
        scanf ("%s%d", str, &id);
        if (str[0] == 'Q') {
            printf ("%d\n", get_sum (R[id]) - get_sum (L[id] - 1));
        } else {
            id = L[id]; //查询用dfs序查,那么更改也要用dfs序更改
            a[id] = -a[id];
            addc (id, a[id]);
        }
    }
    return ;
}
int main ()
{
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    while (~scanf ("%d", &n)) {
        index = 1;
        work ();
        memset (first, 0, sizeof first);
        num = 0;
        memset (book, 0, sizeof book);
        memset (c, 0, sizeof c);
    }
    return 0;
}
View Code

 

posted on 2016-08-31 23:43  stupid_one  阅读(174)  评论(0编辑  收藏  举报

导航