您的位置:首页 > 移动开发

POJ 3321 Apple Tree (树状数组)

2015-10-19 16:20 295 查看
题目: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: