题意:一棵树树上有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; }