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

[POJ3321] Apple Tree 苹果树 - 树状数组

2017-02-07 22:37 387 查看

题目描述

有一棵N个结点的树,一开始每个结点上都有一个苹果,每次有两种操作:

   (1)C x:如果x结点上有一个苹果,那么摘下它,否则x节点上会再生出一个苹果;

   (2)Q x:询问以x结点为根的子树中苹果的个数;

你要对于每个Q操作,输出对应的答案。



输入格式

第一行为一个数N,表示树的结点个数,默认以1为根;

接下来N-1行,每行两个数Ui,Vi,表示一条树边;

然后一行是一个数M,表示操作数目,接下来M行为M个操作,格式如题所述。

输出格式

对于每个Q操作,输出对应的答案,一个操作一行。

样例数据

样例输入

3

1 2

1 3

3

Q 1

C 2

Q 1

样例输出

3

2

题目分析

题目要高效动态维护一个子树,怎么办呢?

利用Dfs将树转为第一种欧拉序,保存入出队的时间戳。

那么用树状数组维护欧拉序即可。

源代码

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=500005;
struct BIT { //树状数组
int n,c[maxn];
inline int Lowbit(int x) { //低位操作
return x&(-x);
}
void init(int n) {
this->n=n;
memset(c,0,sizeof(c));
}
void add(int x,int v) {
for(int i=x; i<=n; i+=Lowbit(i))c[i]+=v;
}
int sum(int x) { //求出1~x的区间和
int s=0;
for(int i=x; i; i-=Lowbit(i))s+=c[i];
return s;
}
};
struct Edge {
int to,next;
} Edge[200005];
int n,m,cnt=0,Head[200005],low[200005],high[200005],vst[200005],Next[200005],step=0;
void AddEdge(int from,int to) {
cnt++;
Edge[cnt].to=to;
Edge[cnt].next=Head[from];
Head[from]=cnt;
}
void TreeToLine(int Now) {
low[Now]=++step;
vst[Now]=1;
for(int i=Head[Now]; i; i=Edge[i].next) {
int Next=Edge[i].to;
if(vst[Next])continue;
TreeToLine(Next);
}
high[Now]=++step;
}
BIT bit;
int main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<n; i++) {
int x,y;
cin>>x>>y;
AddEdge(x,y);
AddEdge(y,x);
}
TreeToLine(1);
bit.init(step);
for(int i=1; i<=n; i++) {
bit.add(low[i],1);
Next[i]=-1;
}
cin>>m;
for(int i=1; i<=m; i++) {
char order;
int x;
cin>>order>>x;
if(order=='C') {
bit.add(low[x],Next[x]);
Next[x]*=-1;
} else printf("%d\n",bit.sum(high[x])-bit.sum(low[x]-1));
}
return 0;
}


4000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息