POJ 3321 Apple Tree(树状数组模板)

版权声明:个人笔记,仅供复习 https://blog.csdn.net/weixin_41162823/article/details/82143246

原题链接:POJ3321

解析:这题我按照郭炜老师的讲义来练习树状数组的模板,但是也遇到了一些问题:

  1. 如果对一些图或树来用树状数组解题,就需要给他每个节点一个从1到nCount的编号,因为树状数组只能从1~n求和
  2. 刚开始我用vector<int> G[maxn]来存图,但是超时了,改用vector<vector<int> > G[maxn]就过了,可见以后尽量用第二种方法来存图
  3. lowbit[]数组可以预处理,节约一点时间

代码实例:

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int maxn = 220000;
vector<vector<int> > G(maxn);//存边 
int Start[maxn],End[maxn];//Start和End相当于存每个节点id 
int lowbit[maxn];//二进制最右面的1 
int C[maxn];//C[i]表示从A[i-lowbit[i]+1]到A[i] 的和,本题A[i]都为1 
int nCount = 0;
int HasApple[maxn];//当前节点是否有苹果 
void DFS(int v){
	Start[v] = ++nCount;
	for(int i = 0;i < G[v].size();i++)
		DFS(G[v][i]);
	End[v] = ++nCount;
}
int q_sum(int p){
	int nSum = 0;
	while(p > 0){
		nSum += C[p];//由于每段和都存在对应的C[i]中,故每次减去lowbit[i]来去下一段的C 
		p -= lowbit[p];
	}
	return nSum;
}
void Modify(int p,int val){
	while(p <= nCount){
		C[p] += val;
		p += lowbit[p];
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	int u,v;
	for(int i = 0;i < n-1;i++){
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
	}
	DFS(1);
	for(int i = 1;i <= nCount;i++)
		lowbit[i] = i&-i;
	for(int i = 1;i <= n;i++)
		HasApple[i] = 1;
	for(int i = 1;i <= nCount;i++)
		C[i] = i - (i - lowbit[i]);
	int m;
	scanf("%d",&m);
	for(int i = 0;i < m;i++){
		char cmd[10];
		int p;
		scanf("%s %d",cmd,&p);
		if(cmd[0] == 'C'){
			if(HasApple[p]){
				Modify(Start[p],-1);
				Modify(End[p],-1);
				HasApple[p] = 0;
			}else{
				Modify(Start[p],1);
				Modify(End[p],1);
				HasApple[p] = 1;
			}
		}else {	
			int t1 = q_sum(End[p]);
			int t2 = q_sum(Start[p]-1);
			printf("%d\n",(t1-t2)/2);//所求部分被计算了两次 
		}
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_41162823/article/details/82143246