1. 程式人生 > >數算實習 apple tree 樹狀陣列

數算實習 apple tree 樹狀陣列

Apple tree 樹有N個樹杈,它們通過分支連線。卡卡將樹杈編號為1到N,根始終編號為1.蘋果將在樹杈上生長,兩個蘋果不會在同一個樹杈上生長。卡卡想要了解一棵子樹上有多少蘋果。

輸入: 第一行包含一個整數N(N ≤100,000),這是樹中的樹杈的數量。 以下N - 1行每個包含兩個整數u和v,這意味著樹杈u和樹杈v通過分支連線。 下一行包含的整數M(M ≤100,000)。 以下M行每行包含一個資訊,它要麼是 “ C x ”,表示在樹杈x上是否存在蘋果的狀態發生改變。即如果樹杈上有蘋果,那麼卡卡就會吃掉它; 否則就長出一個新的蘋果。 或是 “ Q x ”表示查詢樹杈x上方子樹中的蘋果數量,包括叉子x上的蘋果(如果存在樹杈x上存在蘋果 最開始樹上長滿了蘋果

#include <iostream>
#include <vector>
using namespace std;


int a[200002] = { 0 };
int c[200002] = { 0 };
int sta[100001];
int en[100001];
vector<int> s[100001];
int ti = 1;
int n;

void dfs(int i)                          //深搜構建陣列區間
{
	sta[i] = ti;
	a[sta[i]] = 1;
	ti++;
	for (int k = 0; k < s[i].size(); k++)
	{
		dfs(s[i][k]);
	}
	en[i] = ti;
	a[en[i]] = 1;
	ti++;
}


int lowbit(int x)
{
	return x & -x;
}

void update(int x, int delta)               //更新樹狀陣列
{
	for (int i = x; i <= 2 * n; i = i + lowbit(i))
	{
		c[i] += delta;
	}
}

int calculate(int x)                         //求和
{
	int sum = 0;
	for (int i = x; i > 0; i = i - lowbit(i))
	{
		sum += c[i];
	}
	return sum;
}


int main()
{
	char p;
	int number;
	int m;
	cin >> n;
	for (int i = 1; i <= n - 1; ++i)
	{
		int r, l;
		cin >> r >> l;
		s[r].push_back(l);
	}
	dfs(1);
	for (int i = 1; i <= 2 * n; ++i)
		for (int j = i - lowbit(i) + 1; j <= i; ++j)
			c[i]++;
	cin >> m;
	for (int i = 1; i <= m; i++)
	{
		cin >> p >> number;
		if (p == 'Q')
		{
			cout << (calculate(en[number]) - calculate(sta[number] - 1)) / 2 << endl;
		}
		else if (p == 'C')
		{
			int t = a[sta[number]];
			a[sta[number]] = 1 - a[sta[number]];
			update(sta[number], a[sta[number]] - t);
			t = a[en[number]];
			a[en[number]] = 1 - a[en[number]];
			update(en[number], a[en[number]] - t);
		}
	}
	return 0;
}