POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

题意分析

卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果。卡卡很喜欢苹果。树上有N个节点,卡卡给他们编号1到N,根的编号永远是1.每个节点上最多结一个苹果。卡卡想要了解某一个子树上一共结了多少苹果。

现在的问题是不断会有新的苹果长出来,卡卡也随时可能摘掉一个苹果吃掉。你能帮助卡卡吗?

前缀技能

边表存储树

DFS时间戳

线段树

首先利用边表将树存储下来,然后DFS打上时间戳。打上时间戳之后,我们就知道书上节点对应维护线段树的哪一段区间了。换句话说,每当题目给出一个点,要求更新的时候,我们根据时间戳,确定其点在线段树上的位置。当题目给出一个区间,要求我们查询的时候,再根据时间戳,确定线段树区间左右端点。如此一来,就可以将树上信息,转换到线段树上来维护。

注意

  1. 值得注意的是,我的边表存的是两条边,所以边表的容量要开二倍。
  2. 其次就是,无论在更新的时候,还是在查询的时候,要根据时间戳,转化到线段树的对应点或者区间上。因为这个WA了。

代码总览

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define nmax 100010
using namespace std;
struct edge{
int to,next;
}edg[nmax<<1];
struct Tree{
int l,r,val;
int mid(){
return (l+r)>>1;
}
};
Tree tree[nmax<<2];
int head[nmax],in[nmax],out[nmax];
int tot = 0,n,m,time = 0;
void add(int u, int v){
edg[tot].to = v;
edg[tot].next = head[u];
head[u] = tot++;
}
void init(){
memset(head,-1,sizeof head);
memset(edg, 0, sizeof edg);
memset(tree,0,sizeof tree);
memset(in,0,sizeof in);
memset(out ,0, sizeof out);
tot= 0;
time = 0;
}
void dfs(int rt,int f){
time++;
in[rt] = time;
for(int i = head[rt]; i!= -1;i= edg[i].next){
int net = edg[i].to;
if(net != f) dfs(net,rt);
}
out[rt] = time;
}
void PushUp(int rt)
{
tree[rt].val = tree[rt<<1].val + tree[rt<<1|1].val;
}
void Build(int l, int r, int rt)
{
tree[rt].l = l; tree[rt].r = r;
if(l == r){
tree[rt].val = 1;
return;
}
Build(l,tree[rt].mid(),rt<<1);
Build(tree[rt].mid()+1,r,rt<<1|1);
PushUp(rt);
}
void UpdatePoint(int pos, int rt)
{
if(tree[rt].l == tree[rt].r){
tree[rt].val ^= 1;
return;
}
if(pos<= tree[rt].mid()) UpdatePoint(pos,rt<<1);
else UpdatePoint(pos,rt<<1|1);
PushUp(rt);
}
int Query(int l,int r,int rt)
{
if(l>tree[rt].r || r<tree[rt].l) return 0;
if(l <= tree[rt].l && tree[rt].r <= r) return tree[rt].val;
return Query(l,r,rt<<1) + Query(l,r,rt<<1|1);
}
int main()
{
while(scanf("%d",&n) != EOF){
init();
int u,v;
for(int i = 0;i<n-1;++i){
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0);
Build(1,n,1);
int m;scanf("%d",&m);
char op;int x;
for(int i = 0;i<m;++i){
scanf(" %c %d",&op,&x);
if(op == 'Q'){
printf("%d\n",Query(in[x],out[x],1));
}else{
UpdatePoint(in[x],1);
}
}
}
return 0;
}

POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)的更多相关文章

  1. poj 3321 Apple Tree dfs序+线段树

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K       Description There is an apple tree outsid ...

  2. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

  3. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  4. hdu 1166线段树 单点更新 区间求和

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  5. hdu1166(线段树单点更新&区间求和模板)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 题意:中文题诶- 思路:线段树单点更新,区间求和模板 代码: #include <iost ...

  6. POJ 3321 Apple Tree DFS序 + 树状数组

    多次修改一棵树节点的值,或者询问当前这个节点的子树所有节点权值总和. 首先预处理出DFS序L[i]和R[i] 把问题转化为区间查询总和问题.单点修改,区间查询,树状数组即可. 注意修改的时候也要按照d ...

  7. POJ3321 - Apple Tree DFS序 + 线段树或树状数组

    Apple Tree:http://poj.org/problem?id=3321 题意: 告诉你一棵树,每棵树开始每个点上都有一个苹果,有两种操作,一种是计算以x为根的树上有几个苹果,一种是转换x这 ...

  8. hdu1394(枚举/树状数组/线段树单点更新&区间求和)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 ...

  9. POJ 3321 Apple Tree DFS序+fenwick

    题目大意:有一颗长满苹果的苹果树,有两个操作. 1.询问以一个点为根的子树中有多少个苹果. 2.看看一个点有没有苹果,假设没有苹果.那么那里就立即长出一个苹果(= =!):否则就把那个苹果摘下来. 思 ...

随机推荐

  1. Netty源码分析第5章(ByteBuf)---->第10节: SocketChannel读取数据过程

    Netty源码分析第五章: ByteBuf 第十节: SocketChannel读取数据过程 我们第三章分析过客户端接入的流程, 这一小节带大家剖析客户端发送数据, Server读取数据的流程: 首先 ...

  2. [文章存档]Kudu 的 Debug Console 窗口如何查看更多文件

    链接:https://docs.azure.cn/zh-cn/articles/azure-operations-guide/app-service-web/aog-app-service-web-h ...

  3. nodejs 中jead模板改为ejs

    var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set(' ...

  4. tar.gz 文件解压 (安装 netbean 时会用到)

    sudo tar xvf jdk-7u45-linux-i586.tar.gz -C /usr/lib 参考文章 http://hi.baidu.com/xiaomeng008/item/5e787b ...

  5. centos7安装oracle亲测可用

    http://www.linuxidc.com/Linux/2016-04/130559p2.htm

  6. Chapter 3 软件项目管理

    软件项目具有产品的不可见性.项目的高度不确定性.软件过程的多变化性.软件人员的高流动性的显著特征.有效的软件项目管理集中于人员.产品.过程和项目四个方面.软件项目的生命周期有项目启动.项目规划.项目实 ...

  7. bata2

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...

  8. Beta 冲刺1

    队名:日不落战队 安琪(队长) 过去两天完成了那些任务 修改个人信息界面. 修改手写涂鸦界面. 接下来的任务 改进手写涂鸦,加入其他功能. 还剩下的任务 社交模块功能. 遇到的困难 无. 有哪些收获和 ...

  9. 图论 Kruskal算法 并查集

    #include<iostream> #include<cstring> #include<string> #include<cstdio> #incl ...

  10. 车牌识别算法库EasyPR的使用

    主要参考以下两个博客: http://blog.csdn.net/junmuzi/article/details/49888123 http://blog.csdn.net/Lucas66666/ar ...