题意:
有一颗苹果树,树的主干设为1,每一个分支有一个编号(1~n),代表这颗苹果树。每个分支上面只能最多有一个苹果,也就是一个枝子上面不可能有两个苹果,苹果树每个节点可以分出很多叉为多叉树。
输入是分支之间的关系,
1 2
1 3
就是主干上面两个叉分别是2 和3.
下面是两种操作,Q 和C
C j 的意思是如果 j 这个枝子上面有苹果就摘下来,如果没有,那么就会长出新的一个
Q j 就是问 j 这个叉上面的苹果总数。
从1开始按照dfs顺序给每个节点赋予编号(从1开始), 并保存下每个节点的子节点中最大的编号(确定该节点包含的区间范围)
然后用树状数组去求解
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 1e5+150;
int n;
struct edge{//
int u, v;
}node[2*maxn];
int len=0, cnt=0;
int first[maxn], Next[maxn];
void addEdge(int u, int v){//数组模拟邻接表
node[++len].u = u;
node[len].v = v;
Next[len] = first[u];
first[u] = len ;
}
int s[maxn], e[maxn];
int c[maxn];
int vis[maxn];
//投影,记录每个节点包含的起点(本身投影的点)和终点(包含子节点中最大的投影点的编号)
void dfs(int pos){
s[pos] = ++cnt;
int k=first[pos];
vis[pos] = 1;
while(k!=-1){
if(!vis[node[k].v]) dfs(node[k].v);
k=Next[k];
}
e[pos] = cnt;
return ;
}
int lowbit(int x){// 2^k
return x&(-x);
}
void update(int pos, int val){//增加val
while(pos<=cnt){
c[pos] += val;
pos += lowbit(pos);
}
return ;
}
int query(int pos){//查询区间和
int sum=0;
while(pos>0){
sum += c[pos];
pos -= lowbit(pos);
}
return sum;
}
int main()
{
int i, m;
//freopen("in.txt", "r", stdin);
while(~scanf("%d", &n)){
len=0;
cnt=0;
memset(vis, 0, sizeof(vis));
memset(first, -1, sizeof(first));
memset(c, 0, sizeof(c));
int u, v;
for(i=1; i<n; i++){
scanf("%d %d", &u, &v);
addEdge(u, v);
}
dfs(1);
// for(i=1; i<=n; i++){
// printf("%d - %d\n", s[i], e[i]);
// }
for(i=1; i<=cnt; i++){
update(i, 1);
vis[i]=1;
}
scanf("%d", &m);
char op;
int pos;
while(m--){
scanf("%*c%c %d", &op, &pos);
if(op=='C'){
if(vis[pos]){
update(s[pos], -1);
} else {
update(s[pos], 1);
}
vis[pos] = !vis[pos];
} else {
printf("%d\n", query(e[pos])-query(s[pos])+vis[pos]);
}
}
}
return 0;
}