题意:一棵树树上有N个分叉点,分个分叉点上有一个苹果或者没有苹果,现在想知道以某一个分叉点为根节点的子树有多少苹果。
从题目的叙述中可以知道给出的数据并不是一棵二叉树,所以一开始往并查集的方向做,每次更新都要从当前节点一直更新到根节点。
当这棵树是一条单链的时候,这种做法的耗时就显得有点丧心病狂了。。。。
下面说正解。
此题其实为区间查询题,可是问题在于线段书只能查询一段连续的区间内的值,对于离散的点线段树就丝毫无用武之地了。
下面DFS这个大杀器就要粉墨登场了。
若对点重新用DFS时被访问的先后顺序进行编号,即最先被访问的编号为1,接下来被访问的为2,以此类推,则会发现一棵树上的点的编
号从根节点一直连续到最后一个被访问的叶子结点。
接下来的问题就可以交给树状数组来做了,不再赘述。
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#pragma comment(linker, "/STACK:1024000000");
#define LL long long int
using namespace std;
const int MAXN = 1000010;
int id[MAXN];
int st[MAXN*4];
bool mark[MAXN];
struct N
{
int data;
N *next;
}*head[MAXN];
N *creat()
{
N *p = (N *)malloc(sizeof(N));
p->data = 0;
p->next = NULL;
return p;
}
void link(int son,int father)
{
head[son]->data ++;
N *p = creat();
p->data = son;
p->next = head[father]->next;
head[father]->next = p;
}
int Time;
int dfs(int root)
{
id[root] = Time++;
if(head[root]->next == NULL)
{
head[root]->data = Time-1;
return Time-1;
}
int temp,Max = -1;
for(N *p = head[root]->next; p != NULL ; p = p->next)
{
if( (temp = dfs(p->data)) > Max)
Max = temp;
}
head[root]->data = Max;
return Max;
}
void Init(int site,int l,int r)
{
st[site] = r-l+1;
if(l == r)
{
st[site] = 1;
return ;
}
int mid = (l+r)>>1;
Init(site<<1,l,mid);
Init(site<<1|1,mid+1,r);
}
int query(int site,int L ,int R,int l,int r)
{
if(L == l && R == r)
{
return st[site];
}
int mid = (L + R)>>1;
if(r <= mid)
{
return query(site<<1,L,mid,l,r);
}
else if(mid < l)
{
return query(site<<1|1,mid+1,R,l,r);
}
else
{
return query(site<<1,L,mid,l,mid) + query(site<<1|1,mid+1,R,mid+1,r);
}
}
void updata(int site,int l,int r,int m)
{
if(mark[m] == false)
{
st[site]--;
}
else
{
st[site]++;
}
if(l == r && r == m)
{
if(mark[m] == false)
{
mark[m] = true;
return ;
}
else
{
mark[m] = false;
return ;
}
}
int mid = (l+r)>>1;
if(m <= mid)
{
updata(site<<1,l,mid,m);
}
else
{
updata(site<<1|1,mid+1,r,m);
}
}
int main()
{
int n,i,u,v,m;
char order;
scanf("%d",&n);
for(i = 1; i <= n; ++i)
{
head[i] = creat();
}
memset(mark,false,sizeof(bool)*(n+2));
for(i = 1; i < n; ++i)
{
scanf("%d %d",&u,&v);
if(head[u]->data == 0 && u != 1)
{
link(u,v);
}
else if(head[v]->data == 0 && v != 1)
{
link(v,u);
}
}
Time = 0;
dfs(1);
Init(1,0,Time-1);
scanf("%d",&m);
while(m--)
{
scanf("%*c%c %d",&order,&v);
if(order == 'Q')
{
printf("%d\n",query(1,0,Time-1,id[v],head[v]->data));
}
else
updata(1,0,Time-1,id[v]);
}
return 0;
}