POJ 3321 Apple Tree(后根遍历将树转化成序列,用树状数组维护)
题意:一棵树,有很多分叉,每个分叉上最多有1个苹果。
给出n,接下来n-1行,每行u,v,表示分叉u,v之间有树枝相连。这里数据中u相当于树中的父节点,v相当于子节点。
给出两个操作:
1.C x 如果分叉x有一个苹果,表示该苹果被摘下;如果没苹果,表示该分叉长出1个苹果。
2.Q x 查询以分叉x为根节点的子树中所含有的苹果,包括分叉x。
思路:用树的后根遍历将树转化成一个序列,然后用树状数组维护。
树的后根遍历(先遍历每棵子树,再遍历根节点)实质上是按照自下而上、从左至右的顺序将非线性结构的树转化为一个线性序列。
每棵子树对应这个线性序列的一个连续的子区间,这样就可以用树状数组来维护更新。
原本我用vector超时,改用邻接表AC 。
代码一:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector> using namespace std;
const int maxn=;
int n,m,val=,tot=; //val即为树状数组中的顺序编号,tot为邻接表的边序号
int c[maxn]; //树状数组
int a[maxn]; //a[i]表示分叉i的苹果的值,0或1
int hash_value[maxn]; //hash_value[i]表示分叉i在树状数组中的序号
int left_leaf[maxn]; //left_leaf[i]表示以i为根节点的子树中最左底端的叶子节点的编号,该值的hash_value即为以i为根节点的子树在树状数组中的区间的最左端
int head[maxn]; struct Edge {
int to,next;
} edge[maxn]; void add(int u,int v) {
edge[tot].next=head[u];
edge[tot].to=v;
head[u]=tot++;
}
int lowbit(int x) {
return x&(-x);
}
void update(int i,int val) {
while(i<=n) {
c[i]+=val;
i+=lowbit(i);
}
}
int sum(int i) {
int sum=;
while(i) {
sum+=c[i];
i-=lowbit(i);
}
return sum;
}
//dfs后根遍历,求取每个节点在树状数组中的顺序编号,以及每棵子树的left_leaf值
void dfs(int u) {
if(head[u]==-) {
hash_value[u]=++val;
left_leaf[u]=u;
return;
}
int v,flag=;
for(int k=head[u]; k!=-; k=edge[k].next) {
v=edge[k].to;
dfs(v);
if(flag) {
//这里的v即使父节点u的最先访问的子节点
left_leaf[u]=left_leaf[v];
flag=;
}
}
hash_value[u]=++val;
}
int main() {
int u,v;
memset(head,-,sizeof(head));
scanf("%d",&n);
for(int i=; i<n; i++) {
scanf("%d%d",&u,&v);
add(u,v);
}
dfs();
memset(c,,sizeof(c)); for(int i=; i<=n; i++) {
a[i]=;
update(i,);
} scanf("%d",&m);
char str[];
int l,r;
for(int i=; i<m; i++) {
scanf("%s%d",str,&u);
if(str[]=='Q') {
r=hash_value[u];
l=left_leaf[u];
l=hash_value[l];
//[l,r]即为以u为根节点的子树在树状数组中的区间
printf("%d\n",sum(r)-sum(l-));
} else {
r=hash_value[u];
if(a[r]==) {
a[r]=;
update(r,-);
} else {
a[r]=;
update(r,);
}
}
}
return ;
}
也可以用结构体,来存储每个以节点i为根节点的子树在树状数组中的区间左端点和右端点:
代码二:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm> using namespace std;
const int maxn=;
int n,m;
int c[maxn]; //树状数组
bool a[maxn]; //用来标记该节点是否有苹果
int cnt=;
int head[maxn];
int tot=; struct Edge {
int next,to;
} edge[maxn]; struct Apple {
int l,r; //apple[u]的l和r表示以u为根的子树在树状数组中对应区间
} apple[maxn]; void add(int u,int v) {
edge[tot].next=head[u];
edge[tot].to=v;
head[u]=tot++;
}
//dfs,从节点u出发,计算即节点u为根的子树区间[apple[u].l,apple[u].r]
void dfs(int u) {
if(head[u]==-) {
apple[u].l=apple[u].r=cnt;
cnt++;
return;
}
apple[u].l=cnt;
for(int k=head[u]; k!=-; k=edge[k].next) {
int v=edge[k].to;
dfs(v);
}
apple[u].r=cnt++;
}
int lowbit(int x) {
return x&(-x);
}
void update(int i,int v) {
while(i<=cnt) {
c[i]+=v;
i+=lowbit(i);
}
}
int sum(int i) {
int res=;
while(i) {
res+=c[i];
i-=lowbit(i);
}
return res;
}
int main() {
char str[];
int u,v;
memset(head,-,sizeof(head));
memset(a,true,sizeof(a));
scanf("%d",&n);
for(int i=; i<n-; i++) {
scanf("%d%d",&u,&v);
add(u,v);
}
dfs();
scanf("%d",&m);
//初始时,每个节点数都有一个苹果
for(int i=; i<=n; i++)
update(apple[i].r,);
for(int i=; i<=m; i++) {
scanf("%s%d",str,&u);
if(str[]=='C') {
if(a[u]) {
update(apple[u].r,-);
a[u]=false;
} else {
update(apple[u].r,);
a[u]=true;
}
} else {
printf("%d\n",sum(apple[u].r)-sum(apple[u].l-));
}
}
return ;
}
POJ 3321 Apple Tree(后根遍历将树转化成序列,用树状数组维护)的更多相关文章
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- POJ - 3321 Apple Tree (线段树 + 建树 + 思维转换)
id=10486" target="_blank" style="color:blue; text-decoration:none">POJ - ...
- POJ 3321 Apple Tree 【树状数组+建树】
题目链接:http://poj.org/problem?id=3321 Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submiss ...
- POJ 3321 Apple Tree (DFS + 树状数组)
题意: 一棵苹果树有N个分叉,编号1---N(根的编号为1),每个分叉只能有一颗苹果或者没有苹果. 现在有两种操作: 1.某个分叉上的苹果从有变无或者从无边有. 2.需要统计以某个分叉为根节点时,它的 ...
- POJ 3321 Apple Tree(dfs序树状数组)
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=10486 题意:一颗有n个分支的苹果树,根为1,每个分支只有一个苹果,给出n- ...
- poj 3321:Apple Tree(树状数组,提高题)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 18623 Accepted: 5629 Descr ...
- POJ 3321 Apple Tree(DFS序+线段树单点修改区间查询)
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 25904 Accepted: 7682 Descr ...
- POJ 3321 Apple Tree dfs+二叉索引树
题目:http://poj.org/problem?id=3321 动态更新某个元素,并且求和,显然是二叉索引树,但是节点的标号不连续,二叉索引树必须是连续的,所以需要转化成连续的,多叉树的形状已经建 ...
- POJ 3321 Apple Tree (树状数组+dfs序)
题目链接:http://poj.org/problem?id=3321 给你n个点,n-1条边,1为根节点.给你m条操作,C操作是将x点变反(1变0,0变1),Q操作是询问x节点以及它子树的值之和.初 ...
随机推荐
- 济南学习 Day1 T3 pm
[问题描述]小 Q 对计算几何有着浓厚的兴趣.他经常对着平面直角坐标系发呆,思考一些有趣的问题.今天,他想到了一个十分有意思的题目:首先,小 Q 会在x轴正半轴和y轴正半轴分别挑选
- java.util.TreeSet源码分析
TreeSet是基于TreeMap实现的,元素的顺序取决于元素自身的自然顺序或者在构造时提供的比较器. 对于add,remove,contains操作,保证log(n)的时间复杂度. 因为Set接口的 ...
- java 设计模式之单例模式
-------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...
- 关于IOS9更新的适应与适配
最下面一行为刚刚添加的 iOS9中新增App Transport Security(简称ATS)特性, 主要使到原来请求的时候用到的HTTP,都转向TLS1.2协议进行传输.这也意味着所有的HTTP协 ...
- C# 语言如何获取json格式的数据,不用javascript用c#实现。。。
{'state' : 1,'data':{'list':[{'id': 123, 'name': '诸葛天邪','level': 10,'country': 1,}]}} 比如我要获取里面的 id 该 ...
- Hadoop介绍及最新稳定版Hadoop 2.4.1下载地址及单节点安装
Hadoop介绍 Hadoop是一个能对大量数据进行分布式处理的软件框架.其基本的组成包括hdfs分布式文件系统和可以运行在hdfs文件系统上的MapReduce编程模型,以及基于hdfs和MapR ...
- WordPress 主题开发 - (五)WordPress 主题模板及目录结构 待翻译
While the most minimal of WordPress Themes really only need an index.php template and a style.css fi ...
- php出现“syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM”错误的一种情况,及解决方法
PHP中的“syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM”错误,可能是因为美元符号$的误用,看下面一种情况 class Test{ s ...
- XAML 概述三
通过对前面2节对XAML的介绍,我们对XAML有了一定的认识.这一节我们来简单了解一下部分XAML命名空间(x:)语言功能. x命名空间映射的是http://schemas.microsoft.com ...
- synchronized 用法,实例讲解
package com.asiainfolinkage.ems.web.controller.base; import java.math.BigInteger; import java.util.D ...