Apple Tree 树状数组习题

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树状数组值*/
  }
 }
}

这代码缩进怎么这么小。。。。

发布了8 篇原创文章 · 获赞 1 · 访问量 115

猜你喜欢

转载自blog.csdn.net/weixin_41087003/article/details/103668105
今日推荐