Apple Tree Poj (数据结构与算法期末复习)
题目链接:http://dapractise.openjudge.cn/2019hwall/003/
树状数组,单点更新,区间求和
代码是看了这位大佬的,https://www.cnblogs.com/gj-Acit/p/3236843.html
所以几乎就是把他的代码理解了一遍,然后自己再用C++写了一遍改动了一丢丢再加了点注释应该会稍微好懂一点。(树状数组的PPT看完了就应该可以不需要太费脑去看懂这个代码了吧)
代码
#include <iostream>
#include<vector>
#include<string.h>
using namespace std;
#define MAXL 100005
typedef vector<int> VE;
vector<VE> edge(MAXL);//用于存储边
int Left[MAXL], Right[MAXL], Fork[MAXL], C[MAXL];
//Left,Right分别是一个Fork的左右边界(可以相等)
//Fork中0代表空,1代表有苹果;C其实是对Fork数组的相应树状数组
int n, m, key;
int lowbit(int t)
{
return (t & -t);
}
void DFS(int t)//深度优先搜索得到苹果树的每个Fork的起始位置和终止位置
{
Left[t] = key;
int k = edge[t].size();
for (int i = 0; i < k; i++)
{
key++;
DFS(edge[t][i]);
}
//key++;//如果加上这个就需要扩大数组并且修改代码,且结果除2
Right[t] = key;//右边的边界不占位置
}
int getsum(int t)
{
int sum = 0;
while (t >0)
{
sum += C[t];
t = t - lowbit(t);
}
return sum;
}
void Update(int t)
{
if (Fork[t] == 1){
Fork[t] = 0;
while (t <= n) {
C[t]--;
t = t + lowbit(t);
}
}
else{
Fork[t] = 1;
while (t <= n) {
C[t]++;
t = t + lowbit(t);
}
}
}
int main()
{
memset(Fork, 0, sizeof(Fork));
memset(Left, 0, sizeof(Left));
memset(Right, 0, sizeof(Right));
memset(C, 0, sizeof(C));
for (int i = 0; i < n - 1; i++) {
edge[i].clear();
}
cin >> n;
int a, b;
for (int i = 0; i < n - 1; i++){
cin >> a >> b;
edge[a].push_back(b);
}
key = 1;
DFS(1);
for (int i = 1; i <= n; i++){
Update(i);//把初始状态输入,即每个分支都有苹果
}
char op;
int t;
cin >> m;
for (int i = 0; i < m; i++){
cin >> op >> t;
//cout << op << " " << t << endl;
if (op == 'Q'){
cout << (getsum(Right[t]) - getsum(Left[t] - 1)) << endl;
/*只有左边的有增加key而右边的没有加key,所以不需要除2*/
}
else {
Update(Left[t]);
/*这里本来我是Update(t)也过了示例,但是WA了,才发现应该用Left[t],因为Left[t]对应了
在Fork数组中t的初始位置,所以应该修改这个值对应的Fork值和相应的C树状数组值*/
}
}
}
这代码缩进怎么这么小。。。。