/*
看了网上的代码。。再自己写了一个。。。
/*
* 3321
* 邻接表建树+树状数组
*
*/
#include <cstdio>
using namespace std;
const int MAXN = 100000 + 5;
struct SData{ //节点
int value;
SData *next;
};
SData edgehead[MAXN]; //邻接表
bool vis[MAXN] = {};
int n, m, u, v, dep = 0, s; //n,m,u,v同题意。。 s为命令里的数字
int low[MAXN], high[MAXN]; //上、下限
bool apple[MAXN]; //是否有苹果
int c[MAXN] = {}; //树状数组
char cmd; //命令
//dfs
void dfs(int x){
low[x] = ++dep;
vis[x] = 1;
SData *p = edgehead[x].next;
while(p){
if(!vis[p->value])
dfs(p->value);
p = p->next;
}
high[x] = dep;
}
int lowbit(int x){
return x & (-x);
}
void update(int x, int delta){
for(int i=x; i<=n; i+=lowbit(i)){
c[i] += delta;
}
}
int sum(int x){
int ans = 0;
for(int i=x; i>0; i-=lowbit(i)){
ans += c[i];
}
return ans;
}
int main(){
scanf("%d", &n);
for(int i=1; i<n; i++){
scanf("%d %d", &u, &v);
//邻接表建树
SData *p = new SData;
p->value = v;
p->next = edgehead[u].next;
edgehead[u].next = p;
SData *q = new SData; //注意反过来也要建。(若默认u是v的父节点,则可省略)
q->value = u;
q->next = edgehead[v].next;
edgehead[v].next = q;
}
dfs(1);
//起始时刻每个节点都有苹果
for(int i=1; i<=n; i++){
apple[i] = 1;
update(i, 1);
}
//命令
scanf("%d", &m);
for(int i=0; i<m; i++){
scanf("%c", &cmd);
scanf("%c %d", &cmd, &s);
if(cmd == 'C'){
int delta;
apple[s] = !apple[s];
delta = (apple[s] == 1 ? 1 : -1);
update(low[s], delta); //low[s]也代表s在数组中的位置
}
else if(cmd == 'Q'){
int ans = sum(high[s]) - sum(low[s]-1);
printf("%d\n", ans);
}
}
return 0;
}
看了网上的代码。。再自己写了一个。。。
( 网上很多代码都是默认输入的数据u是v的父节点。。 也能AC。。 但不严谨。。)*/
【转】
思路:树状数组。这道题重点怎么建立树到树状数组的映射关系:利用dfs遍历树,
对每个节点进行两次编号,第一次搜到第i个节点时的深度dep,
为这个节点管辖区间的上限low[i](也为这个节点的下标),然后搜这个节点的子节点,
最后搜回来后的深度dep,为这个节点管辖区间的下限high[i]。接下来就是树状数组部分了。
/*
* 3321
* 邻接表建树+树状数组
*
*/
#include <cstdio>
using namespace std;
const int MAXN = 100000 + 5;
struct SData{ //节点
int value;
SData *next;
};
SData edgehead[MAXN]; //邻接表
bool vis[MAXN] = {};
int n, m, u, v, dep = 0, s; //n,m,u,v同题意。。 s为命令里的数字
int low[MAXN], high[MAXN]; //上、下限
bool apple[MAXN]; //是否有苹果
int c[MAXN] = {}; //树状数组
char cmd; //命令
//dfs
void dfs(int x){
low[x] = ++dep;
vis[x] = 1;
SData *p = edgehead[x].next;
while(p){
if(!vis[p->value])
dfs(p->value);
p = p->next;
}
high[x] = dep;
}
int lowbit(int x){
return x & (-x);
}
void update(int x, int delta){
for(int i=x; i<=n; i+=lowbit(i)){
c[i] += delta;
}
}
int sum(int x){
int ans = 0;
for(int i=x; i>0; i-=lowbit(i)){
ans += c[i];
}
return ans;
}
int main(){
scanf("%d", &n);
for(int i=1; i<n; i++){
scanf("%d %d", &u, &v);
//邻接表建树
SData *p = new SData;
p->value = v;
p->next = edgehead[u].next;
edgehead[u].next = p;
SData *q = new SData; //注意反过来也要建。(若默认u是v的父节点,则可省略)
q->value = u;
q->next = edgehead[v].next;
edgehead[v].next = q;
}
dfs(1);
//起始时刻每个节点都有苹果
for(int i=1; i<=n; i++){
apple[i] = 1;
update(i, 1);
}
//命令
scanf("%d", &m);
for(int i=0; i<m; i++){
scanf("%c", &cmd);
scanf("%c %d", &cmd, &s);
if(cmd == 'C'){
int delta;
apple[s] = !apple[s];
delta = (apple[s] == 1 ? 1 : -1);
update(low[s], delta); //low[s]也代表s在数组中的位置
}
else if(cmd == 'Q'){
int ans = sum(high[s]) - sum(low[s]-1);
printf("%d\n", ans);
}
}
return 0;
}