POJ 3321 Apple Tree (树状数组)

来源:互联网 发布:手动记牌器软件 编辑:程序博客网 时间:2024/06/05 15:35

题目:http://poj.org/problem?id=3321

题意:给出一颗树,一开始树是满的(每个结点都有苹果)两种操作;1)C x ,x结点有苹果则摘掉这个苹果,否则加上一个苹果;2)Q x ,询问结点x为根的子树上共有多少苹果(包括x上的苹果)

思路:

关键是把这颗树转化为树状数组,一颗子树中的结点要占连续的空间,访问时才方便方法是dfs给各个结点编号。

每个结点对应两个编号:以这个结点为跟的子树所占的连续空间的开始位置s和结束位置e。

树状数组bit[ i ]记录从开头到 i 这一段的和,那么所求就是bit[ e ] - bit[ s ]。

才知道POJ用stl会很慢啊(大概是指针操作的问题吧),要用数组保存边信息建树,用vector会T。

#include <stdio.h>#include <string.h>#include <algorithm>#include <math.h>#include <stdlib.h>#define INF 0x7fffffff#define MOD 1000000007#include <vector>using namespace std;typedef long long ll;const int MAXN = 100005;vector<int> G[MAXN];int n, m;int s[MAXN], e[MAXN], cnt, apple[MAXN], bit[2 * MAXN];struct Edge{    int to, next;}edge[2 * MAXN];int f[MAXN];void addedge(int u, int v){    edge[cnt].to = v;    edge[cnt].next = f[u];    f[u] = cnt++;}void dfs(int u){    s[u] = cnt++;    for(int i = f[u]; i != -1; i = edge[i].next)    {        if(!s[edge[i].to])            dfs(edge[i].to);    }    e[u] = cnt++;}void update(int i, int x){    //printf("update %d\n", i);    while(i <= 2 * n)    {        bit[i] += x;        i += i & -i;    }}int sum(int i){    int s = 0;    while(i > 0)    {        s += bit[i];        i -= i & -i;    }    return s;}int main(){    #ifdef LOCAL    freopen("data.in", "r", stdin);    #endif    int u, v, x;    char c;    while(scanf("%d", &n) != EOF)    {        for(int i = 0; i <= n; i++)            G[i].clear();        memset(bit, 0, sizeof(bit));        memset(s, 0, sizeof(s));        memset(e, 0, sizeof(e));        memset(apple, 0, sizeof(apple));        memset(f, -1, sizeof(f));        cnt = 0;        for(int i = 0; i < n - 1; i++)        {            scanf("%d%d", &u, &v);            //G[u].push_back(v); G[v].push_back(u);            addedge(u, v);            addedge(v, u);        }        cnt = 1;        dfs(1);        for(int i = 1; i <= n; i++)        {            //printf("%d:%d-%d\n", i, s[i], e[i]);            update(e[i], 1);            apple[i] = 1;        }        scanf("%d", &m);        for(int i = 0; i < m; i++)        {            scanf(" %c%d", &c, &x);            //printf("%c %d\n", c, x);            if(c == 'Q')            {                printf("%d\n", sum(e[x]) - sum(s[x]));            }            else            {                if(apple[x])                {                    update(e[x], -1);                    apple[x] = 0;                }                else                {                    update(e[x], 1);                    apple[x] = 1;                }            }        }    }    return 0;}


0 0