树状数组的神奇在于省空间和时间;
空间复杂度O(n),时间复杂度O(nlogn);
这样的复杂度比线段树有一定的优越性;
主要的组成就是三部分
int inline lowbit(int x) { return x & (-x); }
void ins(int x,int p) {
while(x<=n) {
sum[x] += p;
x += lowbit(x);
}
}
int Sum(int x) {
int ans = 0;
while(x > 0) {
ans += sum[x];
x -= lowbit(x);
}
return ans;
}
就是单点修改和前段求和;
变形后也试用于整段修改单点求值;
POJ3321
// poj 3321
// by utoppia
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int nMax = 200010;
int first[nMax],to[nMax],nxt[nMax],vis[nMax],e;
void addadge(int u,int v) {
to[e]=v;nxt[e]=first[u];first[u]=e;e++;
to[e]=u;nxt[e]=first[v];first[v]=e;e++;
}
int l[nMax],r[nMax];
int dep;
void dfs(int u){
vis[u]=1;l[u]=dep;dep++;
for(int i=first[u];i!=-1;i=nxt[i]) if(!vis[to[i]]) dfs(to[i]);
r[u] = dep-1;
}
int n,m,ans,x,len[nMax];
char s[10];
// BIT
int inline lowbit(int x) {return x&(-x);}
void ins(int x,int k){
while(x<=n) {
len[x] = len[x]+k;
x += lowbit(x);
}
}
int Sum(int x) {
int ans = 0;
while(x > 0) {
ans += len[x];
x -= lowbit(x);
}
return ans;
}
int main() {
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++) first[i]=-1,vis[i]=0,len[i]=0;e=0;
for(int i=1,u,v;i<n;i++) {
scanf("%d%d",&u,&v);
addadge(u,v);
}
dep = 1;
dfs(1);
scanf("%d",&m);
for(int i=1;i<=n;i++) ins(i,1);
while(m--) {
scanf("%s%d",s,&x);
if(s[0]=='C'){
if(Sum(l[x])-Sum(l[x]-1) == 1) ins(l[x],-1);
else ins(l[x],1);
}else {
ans = Sum(r[x]) - Sum(l[x]-1);
printf("%d\n",ans);
}
}
}
return 0;
}