poj3321 图+树状数组-CSDN博客

55 阅读1分钟

poj.org/problem?id=…

\

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstring>
#include <vector>
#define N 100007 
using namespace std;
int bit[N], n, m, lef[N], rig[N], tot, a[N];
vector< vector<int> > pic(N); //存图 
int lowbit(int x) {
	return x & (-x);
}
void add(int pos, int val) {
	while (pos <= n) { //pos <= ?
		bit[pos] += val;
		pos += lowbit(pos);
	}
}

int sum(int pos) { //询问1:pos的和 
	int res = 0;
	while (pos > 0) {
		res += bit[pos];
		pos -= lowbit(pos);
	}
	return res;
}

void dfs(int x) {
	lef[x] = tot;
	for (int i = 0; i< pic[x].size(); ++i) { //遍历以x起点的所有边
		tot++; //给边编号
		dfs(pic[x][i]);
	}
	rig[x] = tot;
}

int main() {
	while (~scanf("%d", &n)) {
		memset(lef, 0, sizeof lef);
		memset(rig, 0, sizeof rig);
		memset(a, 0, sizeof a);
		memset(bit, 0, sizeof bit);
		for (int i = 0; i < n; ++i)
			pic[i].clear();
		for (int i = 1; i < n; ++i) {
			int x, y;
			scanf("%d%d", &x, &y);
			pic[x].push_back(y);
		} //建图
		tot = 1; //编号
		dfs(1);
		for (int i = 1; i <= n; ++i) {
			a[i] = 1;
			add(i, 1);
		} //建树
		int m;
		scanf("%d", &m);
		while (m--) {
			char opt;
			int x;
			scanf(" %c%d", &opt, &x);
			if (opt == 'Q') { //树状数组查询
				printf("%d\n", sum(rig[x]) - sum(lef[x] - 1));
			}
			else {
				if (a[x]) //0 1 转换
					add(lef[x], -1); 
				else add(lef[x], 1);
				a[x] = !a[x];
			}
		}
	}

	return 0;
}


\