標籤:
題意:
給你一棵樹,初始各節點有一個蘋果,給出兩種操作,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;}
POJ 3321- Apple Tree(標號+BIT)