poj 3321 Apple Tree(树状数组+dfs)中等难度

2023-11-08 11:48

本文主要是介绍poj 3321 Apple Tree(树状数组+dfs)中等难度,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、http://poj.org/problem?id=3321

2、题目大意:

有一棵树,有n个叉,由n-1条枝条连接,每个叉上最多有一个苹果,假设原来每个叉上都有苹果,现在要对这棵苹果树进行m个操作,其中这m个操作由两种操作组成,C x表示如果x点有苹果就摘掉,没有苹果就长一个,Q x是查询以x结点为根的树有多少个苹果,这道题目看上去好像是普通的树状数组的题目,但是没有顺序,我们需要先按照根搜索一遍,确定每棵子树的起始点和结束点,这样就可以转换成树状数组的题目了,

这道题目有个问题,用vector建树会超时,需要静态建树

3、题目:

Apple Tree
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 17308 Accepted: 5255

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

 

4、Ac代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 100005
int s[N];
int e[N];
int cnt,n,edge=0;
int visit[N];
int c[N];
int v[N],next[N],head[N];
void add(int x,int y)
{v[edge]=y;next[edge]=head[x];head[x]=edge++;
}
void dfs(int u)
{s[u]=++cnt;for(int i=head[u];i!=-1;i=next[i]){int vv=v[i];dfs(vv);}e[u]=cnt;
}
int lowbit(int i)
{return i&(-i);
}
void update(int x,int v)
{for(int i=x; i<=n; i+=lowbit(i)){c[i]+=v;}
}
int getsum(int x)
{int sum=0;for(int i=x; i>0; i-=lowbit(i)){sum+=c[i];}return sum;
}
int main()
{int a,b,m;char ch[3];while(scanf("%d",&n)!=EOF){cnt=0;edge=0;memset(head,-1,sizeof(head));memset(c,0,sizeof(c));memset(visit,0,sizeof(visit));for(int i=1;i<=n;i++){update(i,1);}for(int i=1;i<n;i++){scanf("%d%d",&a,&b);add(a,b);}dfs(1);scanf("%d",&m);for(int i=1; i<=m; i++){scanf("%s%d",ch,&a);if(ch[0]=='Q'){int ans=getsum(e[a])-getsum(s[a]-1);printf("%d\n",ans);}else if(ch[0]=='C'){int v=s[a];if(visit[v]==1){update(v,1);visit[v]=0;}else{update(v,-1);visit[v]=1;}}}}return 0;
}
/*
3
1 2
1 3
3
Q 1
C 2
Q 3
3
1 2
1 3
3
Q 1
C 2
Q 1*/


 

链表建树的超时代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#include<vector>
#define N 100005
vector<int> adj[N];
int s[N];
int e[N];
int cnt,n;
int visit[N];
int c[N];
void dfs(int v,int f)
{//printf("v=%d\n",v);s[v]=++cnt;for(int i=0; i<adj[v].size(); i++){int vv=adj[v][i];if(vv!=f)dfs(vv,v);}e[v]=cnt;return ;
}
int lowbit(int i)
{return i&(-i);
}
void update(int x,int v)
{for(int i=x; i<=n; i+=lowbit(i)){c[i]+=v;}
}
int getsum(int x)
{int sum=0;for(int i=x; i>0; i-=lowbit(i)){sum+=c[i];// printf("i=%d %d %d\n",i,c[i],sum);}return sum;
}
int main()
{int a,b,m;char ch[3];while(scanf("%d",&n)!=EOF){cnt=0;memset(c,0,sizeof(c));memset(visit,0,sizeof(visit));for(int i=0;i<=n;i++)adj[i].clear();for(int i=1; i<n; i++){scanf("%d%d",&a,&b);//printf("ab=%d %d \n",a,b);adj[a].push_back(b);adj[b].push_back(a);}memset(s,0,sizeof(s));memset(e,0,sizeof(e));dfs(1,-1);scanf("%d",&m);for(int i=1; i<=n; i++){update(i,1);}for(int i=1; i<=m; i++){scanf("%s%d",ch,&a);if(ch[0]=='Q'){//printf("a=%d\n",a);int ans=getsum(e[a])-getsum(s[a]-1);printf("%d\n",ans);}else if(ch[0]=='C'){int v=s[a];if(visit[v]==1){update(v,1);visit[v]=0;}else{update(v,-1);visit[v]=1;}}}}return 0;
}


 

这篇关于poj 3321 Apple Tree(树状数组+dfs)中等难度的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/369648

相关文章

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO