挺复杂一个题,昨天在公司写完没提交,今天提交居然一次AC,挺惊讶的,自己代码功底看来进步了不少,思路也清晰了。
//============================================================================
//
// > File : poj3321.cpp
// > Author : flowertree
// > Time : 2015年12月30日
// > Algorithm : dfs + 树状数组 + 邻接表表示树
//
//============================================================================
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAX 100010
struct node //树的结点 邻接表
{
int num;
node * next;
node()
{
this -> next = NULL;
}
};
node tree[MAX];
node forks[MAX];
int forksum;
int n; //树的结点数
int c[MAX]; //树状数组
int cnum;
int Start[MAX], End[MAX];
node * getforks() //返回枝干的地址
{
return &forks[forksum++];
}
int lowbit(int n) //树状数组求一个数存在最大的二次幂
{
return n & (-n);
}
void change(int position, int num) //树状数组更新
{
while(position <= n)
{
c[position] += num;
position += lowbit(position);
}
}
int getsum(int position) //树状数组求和
{
int sum = 0;
while(position > 0)
{
sum += c[position];
position -= lowbit(position);
}
return sum;
}
void dfs(node * root) //深度优先搜索建立树和树状数组的映射
{
cnum++;
change(cnum, 1);
Start[root -> num] = cnum;
if(root -> next == NULL)
{
End[root -> num] = cnum;
return ;
}
node * p = root -> next;
while(p != NULL)
{
dfs(&tree[p -> num]);
p = p -> next;
}
End[root -> num] = cnum;
}
int main()
{
int left, right;
forksum = 0;
cnum = 0;
cin >> n;
for(int i = 0; i < n - 1; i++) //邻接表初始化一个树
{
scanf("%d%d", &left, &right);
node * p = &tree[left];
p -> num = left;
while(p -> next != NULL)
{
p = p -> next;
}
node * q = getforks();
q -> next = NULL;
q -> num = right;
p -> next = q;
}
for(int i = 1; i <= n; i++)
tree[i].num = i;
//dfs建立树状数组
dfs(&tree[1]);
//开始操作
int ops;
char ch;
int op;
cin >> ops;
while(ops--)
{
getchar();
scanf("%c%d", &ch, &op);
if(ch == 'Q')
{
cout << getsum(End[op]) - getsum(Start[op] - 1) << endl;
}
else if(ch == 'C')
{
int temp1, temp2;
temp1 = getsum(Start[op]);
temp2 = getsum(Start[op] - 1);
if(temp1 - temp2 == 1)
change(Start[op], -1);
else
change(Start[op], 1);
}
}
//操作结束
system("pause");
return 0;
}