IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 动态树(实链剖分) -> 正文阅读

[数据结构与算法]动态树(实链剖分)

基础篇: 简介概念和模板

进阶篇: 只有题目

模板分析: 来自 ac wing

刷题记录: pt 23.2

问题描述

  • 查询、修改链上的信息(最值,总和等)
  • 随意指定原树的根(即换根)
  • 动态连边、删边
  • 合并两棵树、分离一棵树
  • 动态维护连通性

细化步骤

重点提醒:
1,子节点不会跳出当前节点所在的实链:
虚链链接的时候,父亲不知道儿子是谁,但是儿子知道父亲

2,子节点发生变动的节点需要up,自顶向下递归子节点的时候需要down

3,Up 或者 Down一个不能少, LCT 由于特别灵活的原因,少 down 或 up 一次就可能把修改改到不该改的点上!

4,LCT 的 Rotate 和 Splay 的不太一样,if (z) 一定要放在前面。

5,LCT 的 Splay 操作就是旋转到根,没有旋转到谁儿子的操作,因为不需要。

splay部分

1, spin

只须在对z的儿子进行操作时注意一点:
y若是实链顶部(root),z的子节点不能发生改变

void spin(int x)
{
    int y= tr[x].p;
    int z= tr[y].p;
    int k= tr[y].s[1]==x;
    if(!isroot(y))tr[z].s[tr[z].s[1]==y]=x;
    tr[x].p=z;
    tr[y].s[k]=tr[x].s[k^1]; tr[tr[x].s[k^1]].p=y;
    tr[x].s[k^1]=y; tr[y].p=x;
    up(y); up(x);
}

2, splay

以往 splay 找某个节点的时候,都是从根节点往下找(按照 BST 的性质)

但是在 LCT 中,splay 充当的是辅助树的角色,我们获得 splay 中的节点是通过原树中对应节点的编号

换而言之,我们是直接获得 splay 中的某个节点,而不是自上而下递归找到的

所以,在做 splay 转到根节点的旋转操作时,我们需要先 自上而下懒标记 下传

void splay (int x)
{
    int top = 0;
    int r  = x;
    stk[++top]=x;
    while (!isroot(r))stk[++top]=r=tr[r].p;
    while (top) down(stk[top--]);
    
    while (!isroot(x))
    {
        int y= tr[x].p;
        int z= tr[y].p;
    
        if(!isroot(y))
        {
            if((tr[y].s[1]==x) ^ (tr[z].s[1]==y))spin(x);
            else spin(y);
        }
        spin(x);
    }
}

LCT 部分

子节点发生变动的节点需要up
自顶向下递归子节点的时候需要down

1, access 定位

将x到根(实际的树)的路径修改为实边,并把x转到根(保证splay复杂度)

void access(int x)
{
    int z =x;
    for (int y= 0; x; y=x,x=tr[x].p)
    {
        splay(x);
        tr[x].s[1]=y;
        up(x);     改接树上结构需要up
    }
    splay(z);      access自带把x转上辅助树的树根
}

2, cut 断边

cut的条件:
1,y 所在的原树中的根是否是 x
2,y 的父节点是否是根 x
3,y 是否有左孩子(中序遍历紧挨在 x 的后面)

void cut(int x,int y)
{
    make_root(x);
    if(find_root(y)==x && tr[y].p==x && !tr[y].s[0])
    {
        tr[x].s[1]=tr[y].p=0;
        up(x);
    }
}

3, 其他操作

int find_root(int x)/// 辅助树的root
{
    access(x);
    while (tr[x].s[0])
    {
        down(x); ///忘记2
        x=tr[x].s[0];
    }
    splay(x);
    return x;
}

void make_root(int x)/// 把x做成原树的根节点,需要反转整个中序遍历
{
    access(x);
    push_rev(x);///q1
}

void sign(int x,int y) ///把x到y的路径标记为实边
{
    make_root(x);
    access(y);
}

void link(int x,int y)
{
    make_root(x);
    if(find_root(y)!=x )tr[x].p=y;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:43:30  更:2022-03-16 22:45:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:34:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码