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 ...
随机推荐
- 20135239益西拉姆 Linux内核分析 操作系统是怎样工作的?
益西拉姆+ 原创作品+ <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ” 堆栈 堆栈是C语言程序运行时 ...
- cin/cout与scanf/printf的比较
转自http://www.cnblogs.com/penelope/articles/2426577.html cin .cout 基本说明: cin是标准输入流对象,代表标准输入设备(键盘), ...
- bzoj 1070 费用流
//可以网络流,但是要怎么分配每辆车让谁维修以及维修顺序呢.可以考虑每辆车维修时间对总结果的贡献,把每个修车人拆成n个点共n*m个点, //n辆车连向这n*m个点,流量1,费用k*修车时间,其中k(1 ...
- 给阿里云ECS主机添加IPV6地址
阿里云公开的CentOS镜像将IPv6支持给去掉了,需要加载相关模块.通过HE的tunnelbroker开启IPv6隧道使国内VPS支持IPv6地址. 1. vim /etc/modprobe.d ...
- XFire搭建WebService和客户端访问程序
开发环境:myeclipse8.6+jdk1.6.0_29+tomcat6.0.37 JAX-WS搭建webservice:http://www.cnblogs.com/gavinYang/p/352 ...
- 前端PHP入门-016-静态变量
如果我想知道函数被调用了多少次怎么办?在没有学习静态变量的时候,我们没有好的办法来解决. 静态变量的特点是:声明一个静态变量,第二次调用函数的时候,静态变量不会再初始化变量,会在原值的基础上读取执行. ...
- dp+分类讨论 Gym 101128E
题目链接:http://codeforces.com/gym/101128 感觉这个人写的不错的(我只看了题目大意):http://blog.csdn.net/v5zsq/article/detail ...
- 维护后面的position + 离线 + 线段树 bzoj 3585
3585: mex Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 918 Solved: 481[Submit][Status][Discuss] ...
- Atcoder arc077 D - 11 组合
Link 题意:给出n个数,其中有一个数会出现两次,其余数只出现一次,问不同长度且不同的子串的数量.取模1e9+7 思路:组合求出所有情况,减去重复情况,注意用逆元即可 /** @Date : 201 ...
- 【BZOJ】1572: [Usaco2009 Open]工作安排Job
[题意]给定n项工作的截止时间和价值,每项工作需要1单位时间完成,求最大价值.n<=10^5. [算法]贪心+堆 [题解] 如果是访问到x时将d[x]前的点从价值最大的能加就加是错误的贪心,因为 ...