dfs序题目练习
参考博文:http://blog.csdn.net/qwe2434127/article/details/49819975
http://blog.csdn.net/qq_24489717/article/details/50569644
dfs序比较重要的性质:一棵子树的所有节点在dfs序里是连续一段,主要就是利用这个性质来解题.
作为预处理,首先将将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致。
然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]。
最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出来即可,由于对于 每个深度的所有节点,相对顺序和前序遍历的顺序以致,那么他们的dfs进入时间戳也是递增的,于是可以通过二分搜索求解。
Poj 3321:
题型一:对某个点X权值加上一个数W,查询某个子树X里所有点权值和。
解:列出dfs序,实现修改一个数,查询一段序列的和,显然这个序列可以用树状数组维护。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
typedef long long LL;
const int N = ;
struct Edge{
int v,next;
}edge[N];
int head[N],tot,c[N];
int in[N],out[N];
bool have[N];
int cnt;
void init(){
tot = ;
cnt = ;
memset(head,-,sizeof(head));
memset(c,,sizeof(c));
}
void addEdge(int u,int v,int &k){
edge[k].v = v,edge[k].next = head[u],head[u] = k++;
}
void dfs(int u){
in[u] = ++cnt;
for(int k=head[u];k!=-;k=edge[k].next){
dfs(edge[k].v);
}
out[u] = cnt;
}
int lowbit(int x){
return x&(-x);
}
int getsum(int id){
int sum = ;
for(int i=id;i>=;i-=lowbit(i)){
sum+=c[i];
}
return sum;
}
void update(int id,int x){
for(int i=id;i<=cnt;i+=lowbit(i)){
c[i]+=x;
}
}
int main()
{
int n,m;
while(scanf("%d",&n)!=EOF){
init();
for(int i=;i<n-;i++){
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v,tot);
}
dfs();
/*for(int i=1;i<=n;i++){
printf("%d %d\n",in[i],out[i]);
}*/
for(int i=;i<=n;i++){
have[i] = ;
update(in[i],);
}
int q;
scanf("%d",&q);
while(q--){
char s[];
int x;
scanf("%s%d",s,&x);
if(s[]=='Q'){
printf("%d\n",getsum(out[x])-getsum(in[x]-));
}else{
if(have[x]) update(in[x],-);
else update(in[x],);
have[x] = !have[x];
}
}
}
return ;
}
hdu 3886 :
统计某一个结点下面比编号比其小的结点数目.
#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
typedef long long LL;
const int N = ;
struct Edge{
int v,next;
}edge[N];
int head[N],tot,c[N];
int in[N],out[N];
bool have[N];
int cnt;
void init(){
tot = ;
cnt = ;
memset(head,-,sizeof(head));
memset(c,,sizeof(c));
}
void addEdge(int u,int v,int &k){
edge[k].v = v,edge[k].next = head[u],head[u] = k++;
}
void dfs(int u,int fa){
in[u] = ++cnt;
for(int k=head[u];k!=-;k=edge[k].next){
if(edge[k].v == fa) continue;
dfs(edge[k].v,u);
}
out[u] = cnt;
}
int lowbit(int x){
return x&(-x);
}
int getsum(int id){
int sum = ;
for(int i=id;i>=;i-=lowbit(i)){
sum+=c[i];
}
return sum;
}
void update(int id,int x){
for(int i=id;i<=cnt;i+=lowbit(i)){
c[i]+=x;
}
}
int main()
{
int n,q;
while(scanf("%d%d",&n,&q)!=EOF,n+q){
init();
for(int i=;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
addEdge(u,v,tot);
addEdge(v,u,tot);
}
dfs(q,-);
bool flag = true;
for(int i=;i<=n;i++){
if(!flag) printf(" ");
printf("%d",getsum(out[i])-getsum(in[i]-));
flag = false;
update(in[i],);
}
printf("\n");
}
return ;
}
hdu 5692:利用DFS序将树形结构转换成为线段树.便于维护和查找.
http://www.cnblogs.com/liyinggang/p/5925196.html
hdu 5468:DFS序+容斥原理 ,求解每个结点下面与其互质的结点的个数。
http://www.cnblogs.com/liyinggang/p/5926105.html
bzoj 2819:DFS序+博弈+树状数组+lca,维护树上的一条路上的异或值.
http://www.cnblogs.com/liyinggang/p/5927232.html
update中...
dfs序题目练习的更多相关文章
- DFS序的题目列表
所谓dfs序就是将之前的顺序进行修改,获得一个新的序列,然后再新的序列下进行一系列其他的操作 一般题目给你的都会是一棵树,然后点之间都是无关的,我们首要的任务就是先把这些序列重新排.然后再根据dfs的 ...
- 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序
3779: 重组病毒 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 224 Solved: 95[Submit][Status][Discuss] ...
- 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...
- DFS序+线段树 hihoCoder 1381 Little Y's Tree(树的连通块的直径和)
题目链接 #1381 : Little Y's Tree 时间限制:24000ms 单点时限:4000ms 内存限制:512MB 描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每 ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- DFS序+线段树+bitset CF 620E New Year Tree(圣诞树)
题目链接 题意: 一棵以1为根的树,树上每个节点有颜色标记(<=60),有两种操作: 1. 可以把某个节点的子树的节点(包括本身)都改成某种颜色 2. 查询某个节点的子树上(包括本身)有多少个不 ...
- dfs序
dfs序比较重要的性质:一棵子树的所有节点在dfs序里是连续一段,主要就是利用这个性质来解题 题型一:对某个点X权值加上一个数W,查询某个子树X里所有点权值和. 解:列出dfs序,实现修改一个数,查询 ...
- [BZOJ 2819]NIM(dfs序维护树上xor值)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2819 分析: 树上的nim游戏,关键就是要判断树上的一条链的异或值是否为0 这个题目有 ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
随机推荐
- 洛谷 P1023 税收与补贴问题 (2000NOIP提高组)
洛谷 P1023 税收与补贴问题 (2000NOIP提高组) 题意分析 一开始没理解题意.啰啰嗦嗦一大堆.看了别人的题解才明白啥意思. 对于样例来说,简而言之: 首先可以根据题目推算出来 28 130 ...
- 【CodeChef】ForbiddenSum
Portal --> CC ForbiddenSum Solution 场上想到了\(O(NM)\)的做法..然而并没有什么用 首先考虑比较简单的一个问题,给定一个数组\(A\),问这些数不能凑 ...
- restful风格请求及都是 / 的请求及参数也在请求的/中
前台请求的样式: http://localhost:8080/item/88909 其中参数就是最后的 商品id号 88909 后台Controller中取出参数的方法: @Controller p ...
- Ubuntu下Sublime Text 2优化配置
以前经常用Notepad++,最近因为需要长期在Linux环境下进行C开发,就使用了sublime Text 2,这里就不介绍基本的了主要针对我使用的经验中进行一些总结. 1.pacage contr ...
- 9.Android UiAutomator正则表达式的使用
一.正则表达式元字符: 1.一些常用元字符: 元字符 描述 . 表示任意一个字符 \s 空格字符(空格键.tab.换行.换页.回车) \S 非空字符串([^\s]) \d 一个数字(相当于[0-9]中 ...
- 跟我一起写Makefile(七)
make 的运行—————— 一般来说,最简单的就是直接在命令行下输入make命令,make命令会找当前目录的makefile来执行,一切都是自动的.但也有时你也许只想让make重编译某些文件,而不是 ...
- mysql数据库使用sql命令窗口查询的数据,改成sql语句导入到mysql数据库中
1.查询语句为select * from t_table;导出的数据格式如下: 2.将数据文本备份,然后使用NOTEPAD++打开,然后只拷贝数据到新建txt中,然后进行如下替换: 1)将“ | ”分 ...
- LightOJ 1364 树形DP
52张扑克牌,问拿到指定数量的4个花色的最少次数期望是多少,其中拿到joker必须马上将其视作一种花色,且要使后续期望最小. 转移很容易想到,主要是两张joker的处理,一个状态除了普通的4个方向的转 ...
- 760A 水
LINK 第一天单独一行 其余7天一行 问某月有多少行 ...... /** @Date : 2017-04-02-21.35 * @Author : Lweleth (SoungEarlf@gmai ...
- LightOJ 1017 - Brush (III) 记忆化搜索+细节
http://www.lightoj.com/volume_showproblem.php?problem=1017 题意:给出刷子的宽和最多横扫次数,问被扫除最多的点是多少个. 思路:状态设计DP[ ...