第一次知道dfs序这个东西,可以维护树上的任意一个节点,以这个节点为根的子树上的所有节点的标号。是连续的一段区间。
一棵子树的所有节点在dfs序里是连续一段,主要就是利用这个性质来解题
然后就是树状数组维护区间内苹果的数量
另外这个题很卡时间,我用了输入输出挂才过
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 100000+10;
vector<int>G[maxn];
int l[maxn],r[maxn];
int tree[maxn];
char op[5];
int x,key,n;
inline int in()
{
char ch;
int a = 0;
while((ch = getchar()) == ' ' || ch == '\n');
a += ch - '0';
while((ch = getchar()) != ' ' && ch != '\n')
{
a *= 10;
a += ch - '0';
}
return a;
}
void dfs(int u)
{
l[u] = key;
int len = G[u].size();
for(int i=0;i<len;i++)
{
int v = G[u][i];
key++;
dfs(v);
}
r[u] = key;
}
inline int lowbit(int i){return i&(-i);}
inline void add(int i,int x)
{
while(i<=n)
{
tree[i] += x;
i += lowbit(i);
}
}
inline int getsum(int i)
{
int sum = 0;
while(i)
{
sum += tree[i];
i -= lowbit(i);
}
return sum;
}
int q[maxn];
inline void Out(int a)
{ // 输出外挂
if (a < 0)
{
putchar('-');
a = -a;
}
if (a >= 10)
{
Out(a / 10);
}
putchar(a % 10 + '0');
}
int main()
{
int u,v;
n = in();
for(int i=1;i<n;i++)
{
u = in(); v = in();
G[u].push_back(v);
}
key = 1;
dfs(1);
for(int i=1;i<=n;i++) q[i] = 1,add(i,1);
int m;
scanf("%d",&m);
while(m--)
{
scanf("%s%d",op,&x);
if(op[0]=='Q')
{
Out(getsum(r[x])-getsum(l[x]-1)); puts("");
}
else
{
if(q[x]==1) add(l[x],-1),q[x]=0;
else add(l[x],1),q[x] = 1;
}
}
return 0;
}