题意:
给你一棵树,初始各节点有一个苹果,给出两种操作,C x 表示若x节点有苹果拿掉,无苹果就长一个。
Q x查询以x为根的子树中有多少个苹果。
分析:
开始这个题无从下手,祖先由孩子的标号不能确定,就想能不能重新编号
,对与一棵树我们以先根序进行编号这就保证了一个子树在一个连续的区间内,然后就是BIT了。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define N 100010 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; struct edge{ int v,next; }e[N*2]; int used[N],bit[N],l[N],r[N],id,f[N],n,head[N*2]; int len; void add_edge(int u,int v){ e[len].v=v; e[len].next=head[u]; head[u]=len++; } void add(int x,int d){ while(x<=n){ bit[x]+=d; x+=x&(-x); } } int sum(int x){ int num=0; while(x>0){ num+=bit[x]; x-=x&(-x); } return num; } void dfs(int i){ l[i]=++id;//根节点编号就是子树左边界 used[i]=1; for(int j=head[i];j!=-1;j=e[j].next){ if(!used[e[j].v]){ dfs(e[j].v); } } r[i]=id;//最后一个子孙的编号右边界 } int main() { while(~scanf("%d",&n)){ memset(bit,0,sizeof(bit)); memset(f,0,sizeof(f)); memset(used,0,sizeof(used)); memset(head,-1,sizeof(head)); int u,v; len=0; for(int i=0;i<n-1;++i){ scanf("%d%d",&u,&v); add_edge(u,v); add_edge(v,u); } id=0; dfs(1); for(int i=1;i<=n;++i) add(i,1); int m,fork; char op[3]; scanf("%d",&m); while(m--){ scanf("%s%d",op,&fork); if(op[0]==‘C‘){ if(f[fork]){ add(l[fork],1); f[fork]=0; } else{ add(l[fork],-1); f[fork]=1; } } else if(op[0]==‘Q‘){ printf("%d\n",sum(r[fork])-sum(l[fork]-1)); } } } return 0; }
时间: 2024-10-13 17:52:25