poj3321(codevs1228)苹果树
1228 苹果树
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
在卡卡的房子外面,有一棵苹果树。每年的春天,树上总会结出很多的苹果。卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树。我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起。卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强。
卡卡所知道的是,每隔一些时间,某些分叉点上会结出一些苹果,但是卡卡所不知道的是,总会有一些调皮的小孩来树上摘走一些苹果。
于是我们定义两种操作:
C x |
表示编号为x的分叉点的状态被改变(原来有苹果的话,就被摘掉,原来没有的话,就结出一个苹果) |
G x |
查询编号为x的分叉点所代表的子树中有多少个苹果 |
我们假定一开始的时候,树上全都是苹果,也包括作为根结点的分叉1。
输入描述 Input Description
第一行一个数N (n<=100000)
接下来n-1行,每行2个数u,v,表示分叉点u和分叉点v是直接相连的。
再接下来一行一个数M,(M<=100000)表示询问数
接下来M行,表示询问,询问的格式如题目所述Q x或者C x
输出描述 Output Description
对于每个Q x的询问,请输出相应的结果,每行输出一个
样例输入 Sample Input
3
1 2
1 3
3
Q 1
C 2
Q 1
样例输出 Sample Output
3
2
数据范围及提示 Data Size & Hint
/* 暴力做的,记录每个点的父亲更改一个点后, 这个点一直到根节点全部更新codevs 1228 苹果树上得了90分 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 100010 using namespace std; int n,m,topt,sum[maxn],fa[maxn],first[maxn],f[maxn]; bool p[maxn]; struct edge { int from; int to; int next; }e[maxn*2]; int init() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } void add(int x,int y) { topt++; e[topt].from=x; e[topt].to=y; e[topt].next=first[x]; first[x]=topt; } void build(int x) { f[x]=1; int tot=1; for(int i=first[x];i;i=e[i].next) { int t=e[i].to; if(!f[t]) { fa[t]=x; build(t); tot+=sum[t]; } } sum[x]=tot; } void change(int x) { sum[x]--; if(fa[x]) change(fa[x]); } int main() { int i,j,k; n=init(); for(i=1;i<=n-1;i++) { int x,y; x=init(),y=init(); add(x,y);add(y,x); } build(1); m=init(); for(i=1;i<=m;i++) { char c; cin>>c; if(c=='C') { int x; x=init(); if(!p[x]) { p[x]=1; change(x); } } else if(c=='Q') { int x; cin>>x; cout<<sum[x]<<endl; } } }
/*
正解:
dfs序+树状数组
先dfs求出每个点最左和最右在dfs到的顺序
那么左边和右边的之间的就是以这个点为根的子树
修改只修改 左边change(左边) 查询 find(右边)-find(左边-1)就可以了*/ #include<iostream> #include<cstdio> #include<cstring> #define maxn 100010 using namespace std; int n,m,topt,tot,t[maxn*4],first[maxn],f[maxn],l[maxn],r[maxn]; bool p[maxn]; char c[10]; struct edge { int from; int to; int next; }e[maxn*2]; int init() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } void add(int x,int y) { topt++; e[topt].from=x; e[topt].to=y; e[topt].next=first[x]; first[x]=topt; } void build(int x) { l[x]=++tot; f[x]=1; for(int i=first[x];i;i=e[i].next) { int t=e[i].to; if(!f[t]) build(t); } r[x]=++tot; } void change(int k,int z) { while(k<=tot) { t[k]+=z; k+=k&(-k); } } int find(int k) { int ans=0; while(k) { ans+=t[k]; k-=k&(-k); } return ans; } int main() { int i,j,k; n=init(); for(i=1;i<=n-1;i++) { int x,y; x=init(),y=init(); add(x,y);add(y,x); } build(1); for(i=1;i<=n;i++) change(l[i],1); m=init(); for(i=1;i<=m;i++) { scanf("%s",c); if(c[0]=='C') { int x; x=init(); if(!p[x]) { p[x]=1; change(l[x],-1); } else { p[x]=0; change(l[x],1); } } else if(c[0]=='Q') { int x; x=init(); printf("%d\n",find(r[x])-find(l[x]-1)); } } }