苹果树(线段树+Dfs序)
Posted 安
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了苹果树(线段树+Dfs序)相关的知识,希望对你有一定的参考价值。
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
/* 这个题是一棵树 他的点的编号顺序并不是按照线段树的节点顺序来排列的 所以我们要想方设法把这个节点融入线段树中 如何融入线段树呢? 首先把这些点和边都存起来 然后我们考虑把节点存成一个线性的区间 所以是Dfs许 维护遍历到的时间和结束的时间,形成一个区间。 然后每个节点就是就是它的区间的第一个值 线段树完成单点修改和区间查询 */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 100010 using namespace std; int n,m,x,y,z,cnt,tot,time1[maxn],time2[maxn]; int head[maxn],vis[maxn]; char c; struct node0 { int from,to,dis,next; }e[maxn*2]; struct node { int l,r,dis,flag; }tre[maxn*4]; void add(int from,int to) { e[++cnt].from=from; e[cnt].to=to; e[cnt].next=head[from]; head[from]=cnt; } void build(int now,int l,int r) { tre[now].l=l;tre[now].r=r; if(l==r) { tre[now].dis=1; return; } int mid=(l+r)>>1; build(now<<1,l,mid); build(now<<1|1,mid+1,r); tre[now].dis=tre[now<<1].dis+tre[now<<1|1].dis; } void Dfs(int z) { time1[z]=++tot; vis[z]=1; for(int i=head[z];i;i=e[i].next) { int v=e[i].to; if(!vis[v]) Dfs(v); } time2[z]=tot; } void f_change(int now,int k) { int l=tre[now].l,r=tre[now].r; if(l==r) { if(!tre[now].dis) tre[now].dis=1; else tre[now].dis=0; return; } int mid=(l+r)>>1; if(k>mid) f_change(now<<1|1,k); if(k<=mid) f_change(now<<1,k); tre[now].dis=tre[now<<1].dis+tre[now<<1|1].dis; } int Query(int now,int l,int r) { if(tre[now].l==l&&tre[now].r==r) { return tre[now].dis; } tre[now].dis=tre[now<<1].dis+tre[now<<1|1].dis; int mid=(tre[now].l+tre[now].r)>>1; if(r<=mid)return Query(now<<1,l,r); else if(l>mid)return Query(now<<1|1,l,r); else { return Query(now<<1,l,mid)+Query(now<<1|1,mid+1,r); } } int main() { scanf("%d",&n); build(1,1,n); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y);add(y,x); } Dfs(1); scanf("%d",&m); for(int i=1;i<=m;i++) { cin>>c>>z; if(c==\'Q\') printf("%d\\n",Query(1,time1[z],time2[z])); if(c==\'C\') f_change(1,time1[z]); } return 0; }
以上是关于苹果树(线段树+Dfs序)的主要内容,如果未能解决你的问题,请参考以下文章
POJ - 3321 Apple Tree (dfs序+线段树)