POJ 3321 树状数组(+dfs+重新建树)

Apple Tree

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 27092   Accepted: 8033

Description

There is an apple tree outside of kaka‘s house. Every autumn, a lot of apples will grow in the tree. Kaka likes apple very much, so he has been carefully nurturing the big apple tree.

The tree has N forks which are connected by branches. Kaka numbers the forks by 1 to N and the root is always numbered by 1. Apples will grow on the forks and two apple won‘t grow on the same fork. kaka wants to know how many apples are there in a sub-tree, for his study of the produce ability of the apple tree.

The trouble is that a new apple may grow on an empty fork some time and kaka may pick an apple from the tree for his dessert. Can you help kaka?

Input

The first line contains an integer N (N ≤ 100,000) , which is the number of the forks in the tree.
The following N - 1 lines each contain two integers u and v, which means fork u and fork v are connected by a branch.
The next line contains an integer M (M ≤ 100,000).
The following M lines each contain a message which is either
"C x" which means the existence of the apple on fork x has been changed. i.e. if there is an apple on the fork, then Kaka pick it; otherwise a new apple has grown on the empty fork.
or
"Q x" which means an inquiry for the number of apples in the sub-tree above the fork x, including the apple (if exists) on the fork x
Note the tree is full of apples at the beginning

Output

For every inquiry, output the correspond answer per line.

Sample Input

3
1 2
1 3
3
Q 1
C 2
Q 1

Sample Output

3
2

Source

POJ Monthly--2007.08.05, Huang, Jinsong

题意:

一棵苹果树,每个节点最多结一个苹果,最初每个节点都有一个苹果,非二叉树,有两种操作,Q X,表示X节点的子树共有几个苹果,C X,表示X节点摘掉一个苹果或长出一个苹果(有就摘,没有就长)

代码:

  1 /*
  2 挺好的一道题,本题要重新建立树状数组,用dfs从树根开始搜,每搜到一个点他的左值记录该点的新序号,他的
  3 右值记录改点的子树中的最大深度,这样每个点就变成了树状数组中的C数组参考上图,然后套树状数组区间求和的模板就行了。
  4 注意本题如果用vector会很费时,vector<int>a[MAX]会超时,vector<vector<int> > a(MAX) 985ms过了(后面这个什么鬼!)。
  6 不如自己建树用时会更少。
  7 */
  8 #include<iostream>
  9 #include<cstdio>
 10 #include<vector>
 11 #include<cstring>
 12 using namespace std;
 13 const int MAX=100005;
 14 int c[MAX];
 15 int lef[MAX],rig[MAX];
 16 int n,m;
 17 int rot;
 18 int head[MAX];
 19 int lne;
 20 //vector<int>a[MAX];
 21 //vector<vector<int> > a(MAX);
 22 struct node
 23 {
 24     int to,next;
 25 }a[MAX];
 26 void tadd(int u,int v)
 27 {
 28     a[lne].to=v;
 29     a[lne].next=head[u];
 30     head[u]=lne++;
 31 }
 32 int lowbit(int x)
 33 {
 34     return x&(-x);
 35 }
 36 void add(int id,int val)
 37 {
 38     while(id<=n)
 39     {
 40         c[id]+=val;
 41         id+=lowbit(id);
 42     }
 43 }
 44 int sum(int id)
 45 {
 46     int sum=0;
 47     while(id>0)
 48     {
 49         sum+=c[id];
 50         id-=lowbit(id);
 51     }
 52     return sum;
 53 }
 54 void dfs(int x)
 55 {
 56     lef[x]=rot;
 57     //for(int i=0;i<a[x].size();i++)
 58     for(int i=head[x];i!=-1;i=a[i].next)
 59     {
 60         rot++;
 61         //dfs(a[x][i]);
 62         dfs(a[i].to);
 63     }
 64     rig[x]=rot;
 65 }
 66 int main()
 67 {
 68     int x,y;
 69     char ch[5];
 70     int flag[MAX];
 71     scanf("%d",&n);
 72     for(int i=1;i<=n;i++)
 73     {
 74         flag[i]=1;
 75         add(i,1);
 76     }
 77     lne=0;
 78     memset(head,-1,sizeof(head));
 79     for(int i=1;i<n;i++)
 80     {
 81         scanf("%d%d",&x,&y);
 82         //a[x].push_back(y);
 83         tadd(x,y);
 84     }
 85     rot=1;
 86     dfs(1);
 87     scanf("%d",&m);
 88     while(m--)
 89     {
 90         scanf("%s%d",ch,&x);
 91         if(ch[0]==‘C‘)
 92         {
 93             if(flag[x])
 94             add(lef[x],-1);
 95             else add(lef[x],1);
 96             flag[x]=!flag[x];
 97         }
 98         else
 99         {
100             printf("%d\n",sum(rig[x])-sum(lef[x]-1));
101         }
102     }
103     return 0;
104 }
时间: 2024-10-06 16:33:57

POJ 3321 树状数组(+dfs+重新建树)的相关文章

poj 2299 树状数组求逆序数+离散化

http://poj.org/problem?id=2299 最初做离散化的时候没太确定但是写完发现对的---因为后缀数组学的时候,,这种思维习惯了吧 1.初始化as[i]=i:对as数组按照num[]的大小间接排序 2.bs[as[i]]=i:现在bs数组就是num[]数组的离散化后的结果 3.注意,树状数组中lowbit(i)  i是不可以为0的,0&(-0)=0,死循环... #include <cstdio> #include <cstring> #include

【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

[题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后). l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失. l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失. 我们把纸上打印出来的字符串从1开始顺序编号,一直到n.打字机有一个非

UCF Local Programming Contest 2018 E题(树状数组+dfs序)

如果这道题没有一个限制,那么就是一道树状数组+dfs序的裸题 第一个请求或许会带来困惑,导致想要动态建树,如果真的动态修改树,那么dfs序必定会改变,很难维护,并且数据很大,暴力应该会T 所以不妨先把全部的节点建好,这样只需要求一次dfs序,而对于第一种操作 我们只需要再那个位置减去在他之前的dfs序的bouns求和,并在这个的后一个位置+回来,这样就有这个点被修改,并且成为了一个新点,等同于要求的操作 #include<iostream> #include<cstdio> #in

BZOJ2434 NOI2011 阿狸的打字机 AC自动机+树状数组+DFS序

题意:给定三个操作:1.在当前字符串的末尾添加一个字符c  2.在当前字符串的末尾删除一个字符  3.记录当前字符串并对其标号.再给出N组询问,每组询问需回答第x个字符串在第y个字符串中出现的次数 题解: 首先按照如下规则建Trie,设当前节点为t,第i个字符串的结尾在Trie中的位置为mark[i]: 1.插入操作:看t是否有c这个儿子,有则t=t->child[c],否则t->child[c]=NewNode,t=t->child[c] 2.删除操作:t=t->father 3

POJ 2352Stars 树状数组

Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42898   Accepted: 18664 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a st

SYSU-5, POJ 2131, 树状数组+二分

题目大意:给出n个人,顺序对位置进行请求,如果第i个人请求的位置上有人,则让这个人顺延,如果顺延的位置继续有人,递归进行,问最后所有人的位置. 解:这题貌似可以用平衡树+并查集搞定,但是我队友强烈安利树状数组的做法.赛场上没出,赛后结合discuz想了一下,作一下处理. 首先如果是一个请求第a[i]个有空位置的问题,那么这个问题显然可以用树状数组维护前缀和即可.所以我们现在考虑将原问题转化成这个问题. 考虑终态,把没有人的位置去掉,剩下的n个座位排在一起,显然转化成上面模型的形式 第i个询问时,

POJ 3321-Apple Tree-树状数组+dfs序

计算一个树的子树节点权值和,节点权值可以单个修改. 利用dfs序把一颗树投影到数组里,维护dfs序和子节点个数,然后用树状数组即可. 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn = 1e5+10; 8 int N,M,c[maxn],chdnum[maxn]; 9 int id_dfs[maxn],c

CodeForces 396C 树状数组 + DFS

这题目一开始看到了就想到了线段树或者树状数组,但是对于一个节点的所有子节点加权有所疑惑,后来看到根树这个条件,就像到了 那么1号点肯定在第一层,那么建立单向边往下搜,然后记录一下 每一个节点所在的 层,最后 两个节点 相差的 层数就知道了,就容易加权处理了,然后就开始建立数组了,后来一直爆错,后来发现 是范围有问题,这样直接建立是错的,因为不知道具体范围,数字太大了, 所以参考了一下 http://blog.csdn.net/keshuai19940722/article/details/201

HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)

Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1798    Accepted Submission(s): 585 Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,-,n.The