LCT

ACM--LCT LCT二刷 阅读详情

非常抱歉,因为我个人的缘故,导致文章内图片失效,对此我深感抱歉。

如果您承受不了无图的煎熬,那么不妨阅读这篇博客

前置知识

博客设置基础定义

LCT是一种解决动态树问题的方法,由tarjan~~(为什么又是他)~~在1982年提出,最原始的论文在这里,在论文中,tarjan除了介绍了均摊复杂度为 O ( l o g 2 n ) O(log^2n) O(log2n)的LCT之外,还介绍了一种严格 O ( l o g 2 n ) O(log^2n) O(log2n)的算法,不过本人太弱了,看不懂tarjan讲了些啥,也没找到其他的学习资料,因此这种算法我们不做讨论

能够解决的问题

  1. 求LCA
  2. 求最小生成树
  3. 维护链上信息(最大最小,链上和等)
  4. 维护联通性
  5. 维护子树信息(需要配合AAA树)
  6. 优化单纯性算法,在 O ( m n l o g ( n ) ) O(mnlog(n)) O(mnlog(n))的复杂度下求最大流(这两个是tarjan在它的论文最开头提到的,但是我除了在一本书中看到过有关的简介(没有代码)之外,再没看到过关于它的任何资料,)

构造

在解决树上问题的时候,有一种非常常见的操作叫做链剖分

链剖分一般分为三种

  • 重链剖分,也就是我们常提到的“树剖”,剖分的原理是把节点个数最多的儿子当做重儿子

  • 长链剖分,并不是很常见,可以 O ( 1 ) O(1) O(1)求 k k k级祖先,原理是把深度最深的儿子当做重(长)儿子

  • 实链剖分,也就是LCT所用到的剖分方法,这里重点介绍一下

在实链剖分时,选择一个儿子作为重儿子,把连接这两个节点的边作为重边,连接其他儿子的边作为轻边。

与前两种剖分不同的是,实链剖分中的重儿子是可以不断变化的,因此在整棵树中的重链和轻链也是在不断变化的,这就需要我们用更灵活一些的数据结构来维护。

维护一条链,我们首先可以想到的是链表,但是用链表来维护树上权值和的话时间复杂度肯定是 O ( n 2 ) O(n^2) O(n2)的,即使是块状链表也只能做到 O ( n n ) O(n \sqrt{n}) O(nn ​)

因此我们用平衡树来维护链上信息,那么用什么平衡树呢?理论上splay和fhq treap都是可以的,treap不可以,因为不能维护翻转信息,在这里我比较推荐splay,因为网上有关LCT的题目大多数题解都是用splay写的,这样的话学习难度也会小一点,而且我自测splay的常数要比fhq treap小很多

我们用splay维护每一条实路径(仅由实边组成的路径),因为每条实路径都对应一条从根节点出发的链,这样的话路径上每个节点的深度都是不同的,因此在splay中,我们按深度作为关键字,对于一个节点,它的左孩子所对应的原节点深度比它小,右儿子所对应的原节点深度比它大

(这里插一句闲话,LCT之所以难于理解,很大程度上是初学者分不清原树/splay,因此我希望大家在继续往下读的过程中,一定要分清楚我所说的概念到时指的是原树还是splay树)

但是这样的话,虽然每个节点都包含在了splay中,但是每个splay之间都是独立的,因此我们要考虑如何在各个splay中建立联系,
对于一个节点,假设它有三个儿子,其中最多有一个节点可以和他在一个splay中,另外两个儿子分别属于不同的splay。这里有一个非常巧妙的性质——另外两个儿子在他们所在的子树中一定是深度最小的,因此我们可以让每个splay中的根节点指向splay中 中序遍历编号最小(也就是原树中深度最小)的节点的父亲,有点绕,希望大家好好理解一下

对于一棵这样的树
(图片来源:FlashHu的博客)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkGiyFGo-1613360204200)(http://ou46et6i2.bkt.clouddn.com/%E5%8E%9F%E6%A0%91.png)]

它的splay树可能长这个样子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BufaLfWu-1613360204204)(http://ou46et6i2.bkt.clouddn.com/splay%E6%A0%91.png)]

LCT基础操作

a c c e s s ( x ) access(x) access(x)

将根节点到 x x x点的路径变为实路径,且 x x x与其儿子之间的边都变为虚边。

首先考虑一下这个操作有什么目的,有了这个操作,我们就可以将根节点到 x x x的这条路径放在同一棵splay中,这样可以很方便通过在splay上打标记得到路径信息

具体怎么实现呢?

还是上面那张图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1R1GyZpl-1613360204208)(http://ou46et6i2.bkt.clouddn.com/%E5%8E%9F%E6%A0%91.png)]

如果我们要执行 a c c e s s ( N ) access(N) access(N),

我们可以从下往上依次处理,首先我们要使得 N − O N-O N−O这条边变为轻边,因为在splay中,节点的深度是唯一的,所以我们首先把 N N N,转到根节点,这样它右边的节点一定是 O O O,然后直接把 N N N节点的右儿子置为 0 0 0就可以了

继续往上,我们需要使 I − K I-K I−K这条边变为轻边,同时使 I − L I-L I−L这条边变为重边

考虑如何使 I − K I-K I−K变为轻边。和上面的思路一样,我们首先使 I I I转到所在splay的根节点,这样的话它的右儿子一定是 K K K,然后我们只需要断开 I − K I-K I−K这条边即可

考虑如何使 I − L I-L I−L变为重边。这个就so easy了,直接将 I I I的右儿子置为 L L L即可

此时 I I I所在的splay的父亲指向 H H H

继续往上思路就是一样的了,按照同样的套路使得 H − J H-J H−J变为轻边,使 H − I H-I H−I变为重边,

此时 H H H指向 A A A,然后让 A A A转到所在splay的根节点,把右儿子置为 H H H即可

这样我们就实现了 a c c e s s access access操作,按照上面的流程,我们不难总结出算法框架

  1. 将要处理的节点转到根
  2. 更改右儿子
  3. 更新标记

代码的话,,首先说一下各种定义

struct node {
    int f, ch[2], s;
    //f:父亲
    //ch[0]/[1]:左/右儿子
    //s:标记,依题目而变
    bool r;//是否翻转
}T[MAXN];

access

void access(int x) {//访问x节点 
    for(int y = 0; x; x = fa(y = x))
        splay(x), rs(x) = y, update(x);
    //首先把x splay到所在平衡树的根,这样可以保证它的右孩子就是在原树中对应的重链(右孩子深度比它大)
    //y是splay中x的儿子,把x的右儿子改成y,也就是把x和y之间的边变成实边
    //更改了节点顺序,需要update 
}

m a k e r o o t ( x ) makeroot(x) makeroot(x)

将 x x x变为原树的根

考虑这个操作的意义。对于大多数树上询问来说,都是询问一条过根节点的路径,由于LCT的构造的缘故,这种询问处理起来非常麻烦。但是当询问的一端在根节点的时候,处理起来就容易的多,所以这个操作的意义在于帮助我们更好的处理询问

这里有一个非常巧妙的实现思路:

首先我们需要 a c c e s s ( x ) access(x) access(x),这样我们就把根节点和 x x x放到了同一棵splay中

此时 x x x是不含右儿子的(没有深度比他大的点)

然后我们需要 s p l a y ( x ) splay(x) splay(x),此时 x x x会成为splay的根节点,且 x x x不含右儿子。

但是在根节点所在的splay中,根节点没有左儿子(没有深度比他小的节点)

这可怎么办呢??

这里就有一个骚操作了,我们直接将 x x x的左右子树翻转!

这样 x x x不就没有左儿子了么?233

事实证明这样是对的

代码:

void makeroot(int x) {//把x改为原树的根节点 
    access(x);
    splay(x);
    T[x].r ^= 1;//更新翻转标记
}

f i n d r o o t ( x ) findroot(x) findroot(x)

找到 x x x所在原树的根

你刚开始可能跟我一样很呆萌的认为: x x x所在原树的根不就是根节点么?

但是。。

有一点需要注意:LCT维护的是森林,也就是很多棵树,因此每个节点所在原树的根节点往往是不同的

考虑这个操作的意义:

大家有没有发现,这个操作跟并查集中找祖先的操作很类似?没错,这个操作的用处就是判断两个节点的联通性(是否在同一棵树上)

实现的话,我们利用了一个性质:一棵树的根节点一定是深度最小的点

这样我们先 a c c e x x ( x ) accexx(x) accexx(x),然后 s p l a y ( x ) splay(x) splay(x),再不断的往左走,这样就可以找到 x x x所在树的根节点了!

注意!往左走的时候一定要下传标记,否则在某些题目中你会挂的很惨!

代码

int findroot(int x) {//找到x在原树中的根节点 
    access(x);splay(x);
    pushdown(x);
    while(ls(x)) pushdown(x = ls(x));//找到深度最小的点即为根节点 
    return x;
}

s p l i t ( x , y ) split(x,y) split(x,y)

获取到 x − y x-y x−y所对应的路径,

这个操作的意义就非常显然了

实现也非常好想,直接上代码吧

这样的话可以通过访问 y y y节点来获取到有关路径的信息

void split(int x, int y) {
    makeroot(x);//首先把x置为根节点 
    access(y); splay(y);
    //然后访问一下y,再把y转到根节点,这样y维护的就是x - y 路径上的信息 
}

l i n k ( x , y ) link(x,y) link(x,y)

连接 x , y x,y x,y

这个操作的意义也很显然

首先我们需要 m a k e r o o t ( x ) makeroot(x) makeroot(x),然后 a c c e s s ( y ) , s p l a y ( y ) access(y),splay(y) access(y),splay(y),最后把 x x x的父亲指向 y y y就可以

注意在一些毒瘤题中不保证 x , y x,y x,y未联通,这样还需要判断一下联通性

void link(int x, int y) {
    makeroot(x);//把x置为根节点 
    if(findroot(y) != x ) fa(x) = y;
    //如果x与y不在同一个splay中,就把y置为x的父亲 
    //findroot(y)的时候已经执行了access(y),splay(y)
}

c u t ( x , y ) cut(x,y) cut(x,y)

断开 x − y x-y x−y这条边

意义也非常显然

实现的话看上去比较容易

我们需要 s p l i t ( x , y ) split(x,y) split(x,y),此时 x x x的父亲是 y y y, y y y因为是深度最深的点,所以它的左儿子是 x x x,

然后断绝父子关系就好了

但是!!,如果出题人不保证 x − y x-y x−y相连呢??

如果仍然这样改的话整棵树就乱了

因此我们还要加一坨判断

  1. 首先 x , y x,y x,y一定要在一棵树内

  2. x x x的父亲是 y y y,且 y y y的左儿子是 x x x
    这两个比较显然

  3. x x x没有右儿子

这个可能就不是那么显然了

我们仔细考虑一下, x x x的右儿子代表着深度比他大的节点, y y y的左儿子代表着深度比他小的节点

那如果出现这种情况呢?

然后我们就GG了,

或者你可以试试这组数据

5 6 1 2 3 4 5
1 1 2
1 2 3
1 3 4
1 4 5
2 1 5
0 1 5

因此我们有必要加上这个判断

代码:

void cut(int x, int y) {
    makeroot(x);
    if(findroot(y) == x && fa(x) == y && ls(y) == x && !rs(x)) { 
        fa(x) = T[y].ch[0] = 0;
        update(y);
    }
}

时间复杂度

以上操作的平摊复杂度均为 O ( l o g 2 N ) O(log^2N) O(log2N)

具体的证明可以参考YangZhe的论文

小结

LCT的操作也就是这么多了,

不过LCT有很多拓展,题目类型也有很多,大部分我还没做过

等以后慢慢整理吧

洛谷的板子题代码:

其中的splay和rotate都是我自己yy的,并不是很主流的写法,不过跑的比较快

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
#define swap(x,y) x ^= y, y ^= x, x ^= y
const int MAXN=3 * 1e5 + 10;
inline int read()
{
    char c = getchar();int x = 0,f = 1;
    while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = x * 10 + c - '0',c = getchar();}
    return x * f;
}
#define fa(x) T[x].f
#define ls(x) T[x].ch[0]
#define rs(x) T[x].ch[1]
int v[MAXN];
struct node {
    int f, ch[2], s;
    bool r;
}T[MAXN];
int ident(int x) {
    return T[fa(x)].ch[0] == x ? 0 : 1;//判断该节点是父亲的哪个儿子 
}
int connect(int x,int fa,int how) {
    T[x].f=fa;
    T[fa].ch[how]=x;//连接 
}
inline bool IsRoot(int x) {//若为splay中的根则返回1 否则返回0 
    return ls( fa(x) ) != x && rs( fa(x) ) != x;
    //用到了两个性质
    //1.若x与fa(x)之间的边是虚边,那么它的父亲的孩子中不会有他(不在同一个splay内)
    //2. splay的根节点与其父亲之间的边是虚边 
}
void update(int x) {
    T[x].s = T[ls(x)].s ^ T[rs(x)].s ^ v[x];//维护路径上的异或和 
}
void pushdown(int x) {
    if(T[x].r) {
        swap(ls(x),rs(x));
        T[ls(x)].r ^= 1;
        T[rs(x)].r ^= 1;
        T[x].r = 0;//标记下传 
    }
}
void rotate(int x) {
    int Y = T[x].f, R = T[Y].f, Yson = ident(x), Rson = ident(Y);
    int B = T[x].ch[Yson ^ 1];
    T[x].f = R;
    if(!IsRoot(Y))
        connect(x, R, Rson);
    //这里如果不判断y是否根节点,那么当y是根节点的时候,0节点的儿子就会被更新为x
    //这样x就永远不能被判断为根节点,也就会无限循环下去了
    //但是这里不更新x的父亲的话就会出现无限递归的情况 
    connect(B, Y, Yson);
    connect(Y, x, Yson ^ 1);
    update(Y); update(x);
}
int st[MAXN];
void splay(int x) {
    int y = x, top = 0;
    st[++top] = y;
    while(!IsRoot(y)) st[++top] = y = fa(y);
    //用一个栈维护所有的标记
    while(top) pushdown(st[top--]);
    //因为在旋转的时候不会处理标记,所以splay之前应该下传所有标记 
    for(int y = fa(x); !IsRoot(x); rotate(x), y = fa(x))//只要不是根就转 
        if(!IsRoot(y)) 
            rotate( ident(x) == ident(y) ? x : y );
}
void access(int x) {//访问x节点 
    for(int y = 0; x; x = fa(y = x))
        splay(x), rs(x) = y, update(x);
}
void makeroot(int x) {//把x改为原树的根节点 
    access(x);
    splay(x);
    T[x].r ^= 1;
    pushdown(x);
}
int findroot(int x) {//找到x在原树中的根节点 
    access(x);splay(x);
    pushdown(x);
    while(ls(x)) pushdown(x = ls(x));//找到深度最小的点即为根节点 
    return x;
}
void split(int x, int y) {
    makeroot(x);//首先把x置为根节点 
    access(y); splay(y);
}
void link(int x, int y) {
    makeroot(x);//把x置为根节点 
    if(findroot(y) != x ) fa(x) = y;
}
void cut(int x, int y) {
    makeroot(x);
    if(findroot(y) == x && fa(x) == y && ls(y) == x && !rs(x)) { 
        fa(x) = T[y].ch[0] = 0;
        update(y);
    }
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    #else
    #endif
    int N = read(), M = read();
    for(int i = 1; i <= N; i++) v[i] = read();
    for(int i = 1; i <= M; i++) {
        int opt = read(), x = read(), y = read();
        if(opt == 0) split(x, y), printf("%d\n",T[y].s);
        else if(opt == 1) link(x, y);
        else if(opt == 2) cut(x, y);
        else if(opt == 3) splay(x), v[x] = y;
    }
    return 0;
}

参考资料

FlashHu的博客

YangZhe-QTREE解法的一些研究

《高级数据结构》-林厚从

LCT 详解 关于 LCT 阅读详情

相关推荐

详解动态树(LCT)

LCT的功能 动态树link-cut-tree缩写为LCT 支持link(在线建边),cut(在线删边)的操作 下面看看这一道题 【题意】 一个图,有n个点,一开始图中没有边。 三种操作: Connect u v:在点u和点v之间建一条边。保证所有Connect操作不会重复建边。 Destroy u v:摧毁点u到点v之间的边。保证所有Destroy操作将摧毁的是一条存在的边。 Query u ...

zsyzClb的博客 2632

git文件撤销命令

git文件撤销命令 撤销add过的文件 git restore --staged READMD.md 使用此命令可以将提交到暂存区中的文件还原, 并不会改变文件的内容 应用场景:不小心add了不该commit的文件 撤销修改过的文件 git restore READMD.md 使用此命令可以将对文件做的修改撤销 会改变文件的内容 应用场景:写了一堆代码发现思路错了,要重新写 撤销已经被git管理了的文件 git rm --cache READMD.md ...

attack666的博客 185

微信小程序marker 上的自定义气泡cover-view字体丢失以及max-width不生效问题

微信小程序marker 上的自定义气泡cover-view字体丢失以及max-width不生效问题

weixin_42028275的博客 1500

史上最详尽的LCT讲解

终于填完了这个天坑!

薇小薇 7722

Ubuntu 26.04 本地安装 GitLab CE 完整教程(非 Docker 方式)

本文详细介绍了在Ubuntu 26.04系统上通过Omnibus包安装GitLab CE的完整流程。主要内容包括:环境准备(系统要求、依赖安装)、配置清华镜像源、执行安装命令、修改配置文件、服务管理命令以及常见问题解决方法。文章特别强调了内存要求(建议4GB以上)、首次登录密码获取、HTTPS安全配置等关键点,并提供了性能优化建议和安全设置指导。相比Docker方式,Omnibus安装具有性能更好、管理方便等优势,适合需要私有化部署GitLab的场景。

1369

YOLOv8实战:用Labelme标注自定义数据集并训练分割模型(附完整代码)

本文详细介绍了使用Labelme标注自定义数据集并训练YOLOv8实例分割模型的完整流程。从环境搭建、数据标注与格式转换,到模型训练、调优、验证及部署,提供了实战代码和调优建议。文章还探讨了如何结合追踪目标技术,实现视频流中的实例分割与目标追踪,为计算机视觉应用提供了一套可复制的解决方案。

552

正睿OI补题(递归与递推,前缀和与差分)

正睿OI补题(递归与递推,前缀和与差分)

Demilly123的博客 525

手把手教你用Matlab为PMSM电流环设计2P2Z补偿器(附与PI对比)

本文详细介绍了如何使用Matlab的controlSystemDesigner工具为永磁同步电机(PMSM)电流环设计2P2Z补偿器,并与传统PI控制器进行性能对比。通过频域分析和时域仿真,展示了2P2Z补偿器在提升带宽、减少超调等方面的优势,为高性能伺服驱动和精密运动控制提供了实用解决方案。

weixin_42551227的博客 376

Long-term Correlation Tracking LCT目标跟踪算法原理详解(个人学习笔记)

目录1. 算法总览2. 算法详解2.1. 基础相关滤波跟踪2.2. 各模块详解2.2.1. 相关跟踪2.2.2. 在线检测器3. 算法实现3.1. 算法步骤3.2. 实现细节4. 相关讨论&总结 1. 算法总览 LCT的总体流程如上图所示,其思想为:将长时跟踪(long-term tracking)分解为对运动目标的平移(translation)估计和尺度(scale)变化估计,再配置一个检测器(detector),以实现re-detection。 其主要包含三个模块,即图中标红的部分,分别为:

CHEN77的博客 2301

NXP S32K5 MCU如何赋能Zonal架构与软件定义汽车?

汽车电子架构正从分布式ECU向域集中、再向Zonal分区架构演进,核心驱动力在于线束简化、算力下沉与软件分层解耦。区域控制器作为物理区域的“调度员”,需要同时满足实时响应、功能安全、多网络协议转换和OTA升级等要求,这使MCU与SoC的选型成为系统工程的关键决策。MCU凭借确定性的微秒级启动、低功耗、丰富的IO控制以及成熟的ASIL-D认证路径,仍是区域控制器的主流选择。NXP S32K5正是面向这一场景发布的系列MCU:它集成多核锁步、CAN-XL、TSN以太网、硬件安全模块与双Bank Flash,补齐

weixin_28721917的博客 355

高可用架构设计——多节点OpenClaw集群部署与负载均衡(2026企业级)

本文介绍了企业级OpenClaw高可用集群架构设计,重点阐述了多节点部署与负载均衡方案。架构采用分层设计,包括表现层、应用层、数据层和基础设施层,确保99.99%的可用性目标。详细配置了主节点、工作节点和存储节点规格,提供Kubernetes集群部署脚本示例,实现自动化的容器编排管理。通过硬件冗余、故障隔离和弹性扩展等可靠性原则,构建能够应对各种故障场景的稳定AI助手系统。

博客 420

浅谈算法——LCT

前置技能 splay: 必须 树链剖分: 可选,知道树链剖分会容易理解一些。 以下大部分图片来自https://blog.youkuaiyun.com/saramanda/article/details/55253627 Link Cut Tree(LCT) LCT,又叫林克-卡特树,可以用来解决动态树问题。 LCT显然是一棵树,它长这样: 这上面有一些粗一点的边,我们把它称为重边;还有...

Canopus 6744

华为OD新系统机试真题-8位LED控制器(C/C++/Py/Java/Js/Go)

华为OD新系统机试真题【8位LED控制器】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD新系统4月19号机试真题【8位LED控制器】

qq_45776114的博客 596

LCT模板 LCT题型大荟萃

以HDU4010为例,写了LCT相关的一些题目的做法 #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; void fre() { freopen("c://test//in

snowy_smile的博客 1244

【Unity小游戏】整整一个周末写一款《皇室战争 玩法》 的 即时战斗类 游戏Demo。两万多字游戏制作过程+解析

Unity游戏制作,本篇文章介绍了复刻皇室战争玩法的一个自制小游戏,共有该游戏的两万字教程加制作过程,欢迎品尝! 世界上没有绝对的公平,如果我们起点就比别人第一步,那就更需要比别人努力了。

努力前行,总会成为自己心中的那道光 12万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

LCT动态树【史上最精简易懂的LCT讲解】

Link Cut Tree(动态树,LCT) 介绍 首先简单介绍一下Link Cut Tree,将一棵树分成轻边和重链,类似于树链剖分,但是树剖是静态的。LCT可以用于动态的加点和删点,甚至还可以换根。也就是LCT维护了一个动态的树。 LCT中的每棵Splay都维护了一条重链(实际上是实链,这里统一讲重链)上的答案。多颗Splay连成一棵树,这棵Splay满足左儿子在树上的深度(这里深度指的是在数...

XSamsara的博客 AFO 1912

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

LCT总结

  学LCT一段时间了我深深的理解其恶心之处 是代码写的让我难受,可能是一天写了3次LCT。 我 真的不想写了 况且期末考崩了,我 估计要GG了。完蛋! 这里先列举几个我经常犯的错误: 1 LCT和并查集混在一起fa数组写成f数组。 2 两点之间连边的时候必要的要去make_root其...

weixin_30433075的博客 348

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

LCT概述

LCT全称是link-cut-tree,从这个名字就可以看出这玩意儿的逼格很高。实际上确是是一个很强的数据结构。 建议在学LCT之前可以先学习一下树链剖分,这里就不赘述了。 那么LCT是一个什么东西呢?这个数据结构正如它的名字一样,他可以支持树的link和cut,专治各种毒瘤题 。 其实LCT可以看做树链剖分的升级版,树链剖分只能解决静态树的根源是什么?是因为线段树这个东西就只能是静态的。而且就算...

lvmaooi的博客 1万+

LCT(link cut tree) 详细图解与应用

详细分步图解 LCT

如果 Markdown 炸了请前往 https://www.cnblogs.com/ying-xue 查看文章QAQ 1716

LCT维护子树信息(子树信息LCT) LCT维护边权(边权LCT) 知识点讲解

扯淡(前言) 众所周知LCT可以支持关于点权的链修改,换根,LINK,CUT和查询链信息操作,但是总有那么些神犇(毒瘤)出题人会让你在支持链修改,换根,LINK和CUT操作的情况下去支持子树查询,或者维护关于边权的链修改,换根,LINK,CUT和链查询。网上似乎讲解这两种LCT写法的blog比较少或者不怎么能搜到?总之我来写一发 (LCT基础知识回顾) 为了方便说话先说一下下面可能出现的

neither_nor 1万+

LCT 模板及套路总结

这一个月貌似已经考了无数次\(LCT\)了..... 保险起见还是来一发总结吧..... A. LCT 模板 \(LCT\) 是由大名鼎鼎的 \(Tarjan\) 老爷发明的。 主要是用来维护树上路径问题的。 它的神奇之处在于可以直接把一条路径抠出来维护。 其实就是维护树链剖分中的重链与轻链。 网上相关教程很多,直接给板子(其实是我懒得打E_E) 0. Splay代码: \(LCT\)是...

df4516的博客 245
下一篇: git文件撤销命令
KitKatKKK
博客等级 码龄9年 4粉丝 4原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值