首页 > 其他分享 >树的DFS序

树的DFS序

时间:2024-09-10 18:47:39浏览次数:1  
标签:val idx int pos dfs seg DFS

树的 \(DFS\) 序

简意:将树上问题转化为线性问题。

例题:

- MEG-Megalopolis

有一棵节点数为 \(n\) 的树,给定 \(m + n - 1\) 组询问,每组询问有两种操作。

  1. A x y,将 \(x\) 节点和 \(y\) 节点间的边权改为 \(0\),每条边会被修改恰好一次。(每次只修改一条边)

  2. W x,求 \(1\) 号点到 \(x\) 号点路径上的边权和。

初始所有边权值都为 \(1\)。

我们可以先 \(dfs\) 一遍找出这棵树的 \(dfs\) 序,其长度为 \(2n\) :

void dfs(int pos,int fa){
    l[pos] = idx;
    idx++;
    for(int to : tree[pos]){
        if(to != fa){
            dfs(to,pos);
        }
    }
    r[pos] = idx;idx++;
}

其中 \(l\) 数组为记录某一节点在 \(dfs\) 序中第一次出现的位置,而 \(r\) 数组为记录某一节点在 \(dfs\) 序中第二次出现的位置。

而每个节点会且仅会出现两次。

我们对于节点 \(2 - n\) ,建一颗线段树或树状数组,将 \(l[x]\) 位置上的值加1,将 \(r[x]\) 的值减1,查询 \(1 - x\) 路径上的边权和时就查询 \(1 - l[x]\) 的前缀和就行了.

\(code\):

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN = 250005;
int n,m;
vector<int> tree[MAXN];
int l[MAXN],r[MAXN];
int idx = 1;

struct TREE{
    int l,r;
    int val;
}seg[MAXN << 4];
void build(int pos,int l,int r){
    seg[pos].l = l;
    seg[pos].r = r;
    if(l == r){
        return;
    }
    int mid = (l + r) / 2;
    int ls = pos * 2;
    int rs = pos * 2 + 1;
    build(ls,l,mid);
    build(rs,mid + 1,r);
}
void fix(int pos,int x,int val){
    int l = seg[pos].l;
    int r = seg[pos].r;
    if(l == r && l == x){
        seg[pos].val += val;
        return;
    }
    int mid = (l + r) / 2;
    int ls = pos * 2;
    int rs = pos * 2 + 1;
    if(mid >= x) fix(ls,x,val);
    if(mid < x) fix(rs,x,val);
    seg[pos].val = seg[ls].val + seg[rs].val; 
}
int query(int pos,int nl,int nr){
    int l = seg[pos].l;
    int r = seg[pos].r;
    if(l >= nl && r <= nr){
        return seg[pos].val;
    }
    int ans = 0;
    int mid = (l + r) / 2;
    int ls = pos * 2;
    int rs = pos * 2 + 1;
    if(mid >= nl) ans += query(ls,nl,nr);
    if(mid < nr) ans += query(rs,nl,nr);
    return ans;
}
void dfs(int pos,int fa){
    l[pos] = idx;
    idx++;
    for(int to : tree[pos]){
        if(to != fa){
            dfs(to,pos);
        }
    }
    r[pos] = idx;idx++;
}
int main(){
    scanf("%d", &n);
    build(1,1,3 * n);
    for(int i = 1;i < n;i++){
        int x,y;
        scanf("%d%d", &x, &y);
        tree[x].push_back(y);
        tree[y].push_back(x);
    }
    dfs(1,0);
    for(int i = 2;i <= n;i++){
    	fix(1,l[i],1);
    	fix(1,r[i],-1);
	}
    scanf("%d", &m);
    for(int i = 1;i <= m + n - 1;i++){
        char op;
        cin>>op;
        int x,y;
        if(op == 'A'){
            scanf("%d%d", &x, &y);
            if(l[x] < l[y]){
                swap(x,y);
            }
            fix(1,l[x],-1);
            fix(1,r[x],1);
        }else{
            scanf("%d", &x);
            printf("%d\n",query(1,1,l[x]));
        }
    }
    return 0;
}

标签:val,idx,int,pos,dfs,seg,DFS
From: https://www.cnblogs.com/wyl123ly/p/18406934

相关文章

  • 2.HDFS
    HDFS一.HDFS概述1.HDFS的产生背景和定义(1)HDFS产生背景随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到 更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切需要一种系 统来管理多台机器上的文件,这就是分布式管理系统.HDFS只是分布式文 件管理系统中的一种......
  • 【408DS算法题】038进阶-图深度优先遍历DFS
    Index题目分析实现总结题目设计函数实现对图的深度优先遍历。分析实现类似于图的BFS的分析思路,图的DFS和二叉树的DFS思路相同,但需要额外考虑结点是否已经被访问过。此处同样用布尔数组visited来记录每个结点的访问情况,对于邻接矩阵存储方式的图的DFS,依照先序遍......
  • CF2002D2 DFS Checker (Hard Version) 题解
    https://codeforces.com/problemset/problem/2002/D2考虑找一个容易维护的必要条件,再证明充分性。最容易想到的是每个子树对应一个区间,子树根位于左端点sol1相邻的结点\(p_{i-1},p_i\)有两种情况:\(fa[p_i]=p_{i-1}\);叶子\(p_{i-1}\)在子树\(fa[p_i]\)中,回溯到\(fa[......
  • 迷宫,返回所有路径并排序(C++)(回溯+dfs)
    题意说明:要求给出一个m*n的矩阵迷宫,0代表入口,1代表道路,2代表墙体,3代表出口,要求返回从入口到出口的所有移动路径并按长短从小到大排序。移动路径:就是wasd的移动路径,如一共走三步:下,右,下,则输出:sds。代码如下:#include<iostream>#include<string>#include<vector>#include<alg......
  • DFS算法专题(一)——二叉树中的深搜【回溯与剪枝的初步注入】
    目录1、DFS算法简介2、算法实战应用【leetcode】2.1计算布尔二叉树的值2.1.1算法原理 2.1.2算法代码2.2求根节点到叶节点数字之和  2.2.1算法原理​2.2.2算法代码2.3二叉树剪枝2.3.1算法原理2.3.2算法代码2.4验证二叉搜索树 2.4.1算法原理 2.4.2......
  • Sqoop(四)将HDFS上的数据导出到MySQL中
    将HDFS上的数据导出到MySQL中 在MySQL中建表createtableorders(orderidintprimarykey,orderdatevarchar(10),productidint,numint);导出到MySQL中hdfs中准备数据hadoopfs-chmod777/orders/orders/order.txt1,202406,12,300002,202406,13,350003,2024......
  • dfs P1019 [NOIP2000 提高组] 单词接龙
    题目大意:单词接龙,找出最长的长度的单词。题解:由于数据量较小,单词可多次使用,使用后可回溯,考虑dfs。代码:#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;constintN=1e3+10;intn,used[N],ans;stringa[N],start;voiddfs(stringword){......
  • CF 2002 D1. DFS Checker (Easy Version) (*1900)思维
    CF2002D1.DFSChecker(EasyVersion)(*1900)思维题目链接题意:给你一棵\(n\)个节点组成的完全二叉树,并给出一个排列\(p\)。接下来进行\(q\)次询问。每次询问给你\(x\)和\(y\),你需要交换\(p_x\)和\(p_y\)。并且回答交换之后的排列\(p\)是否是这棵完全二叉树......
  • 分享丨【题单】链表、二叉树与一般树(前后指针/快慢指针/DFS/BFS/直径/LCA)
    作者:灵茶山艾府链接:https://leetcode.cn/circle/discuss/K0n2gO/一、链表注:由于周赛中的链表题可以转成数组处理,难度比直接处理链表低,故不标明难度分。带着问题去做下面的题目:在什么情况下,要用到哨兵节点(dummynode)?在什么情况下,循环条件要写while(node!=null)?什么情况......
  • Linux | Ubuntu 16.04.4 通过docker安装单机FastDFS
    Ubuntu16.04.4通过docker安装单机fastdfs前言很久没有写技术播客了,这是一件很不应该的事情,做完了事情应该有沉淀的。我先说一点前情提要,公司的fastdfs突然就挂了,做过的操作就是日志文件太大了,所以把日志文件给删了,理论上这个动作应该不影响程序运行才对。然后tracker怎么都......