poj 3321 Apple Tree(dfs序+线段树)

来源:互联网 发布:淘宝联盟可以相信吗 编辑:程序博客网 时间:2024/06/07 01:27

题意:给出一个多叉树(不一定是二叉),每个树上有一个苹果,有n-1条边,m次操作

操作有两种:

一:每次操作使该节点的苹果从有到无或从无到有,每个节点最多有一个苹果

二:查询该节点的子树上共有多少个苹果


思路:先用dfs序给所有节点标号(相当于映射成线性的),然后用线段树维护,单点更新和区间查询。

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <cmath>#include <queue>using namespace std;typedef long long ll;const int INF=0x3f3f3f3f;const int maxn=110000;int n,m,k;int tot;struct Edge{int to;int next;}edge[maxn*2];int e,head[maxn];int in[maxn],out[maxn],vis[maxn];void init(){e=0;tot=1;memset(in,0,sizeof(in));memset(out,0,sizeof(out));memset(vis,0,sizeof(vis));memset(head,-1,sizeof(head));}void addEdge(int u,int v){edge[e].to=v;edge[e].next=head[u];head[u]=e++;}void dfs(int x){in[x]=tot++;vis[x]=1;for(int i=head[x];~i;i=edge[i].next){if(!vis[edge[i].to])dfs(edge[i].to);}out[x]=tot-1;}struct segTree{int l;int r;int sum;}node[maxn*4];void PushUp(int rt){node[rt].sum=node[rt<<1].sum+node[rt<<1|1].sum;}void build(int rt,int l,int r){node[rt].l=l;node[rt].r=r;node[rt].sum=r-l+1;if(l==r) return ;int mid=(l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);}void Update(int rt,int l,int r,int pos){if(l==r){node[rt].sum^=1;return ;}int mid=(l+r)>>1;if(mid>=pos) Update(rt<<1,l,mid,pos);else Update(rt<<1|1,mid+1,r,pos);PushUp(rt);}int Query(int rt,int l,int r,int L,int R){if(L<=l&&r<=R) return node[rt].sum;int mid=(l+r)>>1;if(mid>=R) return Query(rt<<1,l,mid,L,R);else if(mid<L) return Query(rt<<1|1,mid+1,r,L,R);else return Query(rt<<1,l,mid,L,mid)+Query(rt<<1|1,mid+1,r,mid+1,R);}int main(){while(~scanf("%d",&n)){init();int u,v;for(int i=1;i<n;i++){scanf("%d%d",&u,&v);addEdge(u,v);addEdge(v,u);}dfs(1);build(1,1,n);scanf("%d",&m);char ch[3];while(m--){scanf("%s%d",ch,&k);if(ch[0]=='C') Update(1,1,n,in[k]);else printf("%d\n",Query(1,1,n,in[k],out[k]));}}return 0;}


0 0
原创粉丝点击