长链剖分学习笔记 + [Vijos] lxhgww的奇思妙想 + CF1009F Dominant Indices [长链剖分]

  • 定 义 定义

与重链剖分的定义相似, 只不过重儿子为链的长度最长的儿子 .


  • 性 质 性质

  1. 任意一个点 K K K 级祖先所在长链的长度一定大于等于 K K K .

  2. 任意一个点跳重链到根所用的次数不超过 N \sqrt{N} N .
    证 证 : 每次向上跳, 链的长度都会至少加 1 1 1, 1 , 2 , 3 , 4... N 1,2,3,4...\sqrt{N} 1,2,3,4...N


  • 一 个 应 用 一个应用

O ( 1 )   求 K 级 祖 先 : O(1)\ 求 K 级祖先: O(1) K:

链接

对每个 T o p Top Top记录以下内容 ↓ \downarrow

  • 它 所在长链链长 那么多次 的祖先和重儿子们, 存在 std::vector 里面, 设为 A [ ] , B [ ] A[], B[] A[],B[], 复杂度 O ( N ) O(N) O(N) .

  • 倍增数组 F k [ i , j ] Fk[i,j] Fk[i,j] 表示 i i i 的第 2 j 2^j 2j 祖先, 复杂度 O ( N l o g N ) O(NlogN) O(NlogN) .

  • 每个 i i i 的最高二进制位表示的数字 m a x _ p o s [ i ] max\_pos[i] max_pos[i], 复杂度 O ( N l o g N ) O(NlogN) O(NlogN) .

现在求 i i i K K K 级祖先, 先到达点 F [ i , m a x _ p o s [ K ] ] F[i, max\_pos[K]] F[i,max_pos[K]], 设为 y y y,

此时还需要跳 t m p = K − 2 m a x _ p o s [ K ] tmp = K - 2^{max\_pos[K]} tmp=K2max_pos[K] 步, 分类讨论

  • d e p [ y ] − d e p [ T o p [ y ] ] ≥ t m p dep[y] - dep[Top[y]] \geq tmp dep[y]dep[Top[y]]tmp 然后直接跳到 A [ i , d e p [ y ] − d e p [ T o p [ y ] ] − t m p ] A[i, dep[y]-dep[Top[y]]-tmp] A[i,dep[y]dep[Top[y]]tmp] 即可.
  • d e p [ y ] − d e p [ T o p [ y ] ] &lt; t m p dep[y] - dep[Top[y]] &lt; tmp dep[y]dep[Top[y]]<tmp 然后直接跳到 B [ i , t m p − ( d e p [ y ] − d e p [ T o p [ y ] ] ) ] B[i, tmp-(dep[y]-dep[Top[y]])] B[i,tmp(dep[y]dep[Top[y]])] 即可.

为 什 么 可 以 这 么 做 呢 ? 为什么可以这么做呢 ? ?

T o p [ y ] Top[y] Top[y] 所在长链长度为 l e n [ T o p [ y ] ] len[Top[y]] len[Top[y]], 则 l e n [ T o p [ y ] ] ≥ 2 m a x _ p o s [ K ] ≥ K − 2 m a x _ p o s [ K ] len[Top[y]] \geq 2^{max\_pos[K]} \geq K-2^{max\_pos[K]} len[Top[y]]2max_pos[K]K2max_pos[K],
又因为 T o p [ y ] Top[y] Top[y] l e n [ T o p [ y ] ] len[Top[y]] len[Top[y]] 级及以下祖先和儿子全部存到了 A [ T o p [ y ] ] , B [ T o p [ y ] ] A[Top[y]],B[Top[y]] A[Top[y]],B[Top[y]] 中, 所以直接调用即可实现 O ( 1 ) O(1) O(1) .

代 码 实 现 : 代码实现: :

#include<bits/stdc++.h>
#define pb push_back
#define reg register

const int maxn = 1000006;

int read(){
        char c;
        int s = 0, flag = 1;
        while((c=getchar()) && !isdigit(c))
                if(c == '-'){ flag = -1, c = getchar(); break ; }
        while(isdigit(c)) s = s*10 + c-'0', c = getchar();
        return s * flag;
}

int N;
int M;
int K;
int num0;
int o_pos;
int last_ans;
int pw[maxn];
int fa[maxn];
int len[maxn];
int son[maxn];
int dep[maxn];
int Top[maxn];
int head[maxn];
int Fk[maxn][21];
int max_pos[maxn];

std::vector <int> A[maxn], B[maxn];

struct Edge{ int nxt, to; } edge[maxn << 1];

void Add(int from, int to){
        edge[++ num0] = (Edge){ head[from], to };
        head[from] = num0;
}

void DFS(int k, int fa){
        len[k] = 1;
        dep[k] = dep[fa] + 1;
        for(reg int i = 1; i <= 19; i ++) Fk[k][i] = Fk[Fk[k][i-1]][i-1];
        for(reg int i = head[k]; i; i = edge[i].nxt){
                int to = edge[i].to;
                if(to == fa) continue ;
                Fk[to][0] = k;
                DFS(to, k);
                if(len[to] > len[son[k]]) son[k] = to;
        }
        len[k] = len[son[k]] + 1;
}

void DFS_2(int k, int top){ 
        Top[k] = top;
        if(son[k]) DFS_2(son[k], top);
        for(reg int i = head[k]; i; i = edge[i].nxt){
                int to = edge[i].to;
                if(to == Fk[k][0] || to == son[k]) continue ;
                DFS_2(to, to);
        }
}

void Work(){
        o_pos = read() ^ last_ans, K = read() ^ last_ans;
        if(!K){ printf("%d\n", last_ans = o_pos); return ; }
        else if(dep[o_pos] <= K){ printf("%d\n", last_ans = 0); return ; }
        int y = Fk[o_pos][max_pos[K]];
        int tmp = pw[max_pos[K]];
        if(K - tmp <= dep[y]-dep[Top[y]]) last_ans = B[Top[y]][dep[y]-dep[Top[y]]-(K-tmp)];
        else last_ans = A[Top[y]][K-tmp - (dep[y]-dep[Top[y]])];
        printf("%d\n", last_ans);
}

int main(){
        N = read();
        for(reg int i = 1; i < N; i ++){
                int x = read(), y = read();
                Add(x, y), Add(y, x);
        }
        DFS(1, 0); DFS_2(1, 1);
        pw[0] = 1;
        for(reg int i = 1; i <= 19; i ++) pw[i] = pw[i-1] << 1;
        for(reg int i = 1; i <= N; i ++)
                for(reg int j = 19; j >= 0; j --)
                        if(i >= pw[j]){ max_pos[i] = j; break ; }
        for(reg int i = 1; i <= N; i ++){
                if(Top[i] != i) continue ;
                int t = i;
                for(reg int j = 1; j <= len[i]; j ++, t = Fk[t][0]) A[i].pb(t);
                t = i;
                for(reg int j = 1; j <= len[i]; j ++, t = son[t]) B[i].pb(t);
        }
        M = read();
        while(M --) Work();
        return 0;
}

  • 相 关 难 点 相关难点

主要是指针部分比较新, 这里说一下怎么操作,
首先有一个数组 f o c [ ] foc[] foc[], 其内存空间分为若干段, 分别存储了各个长链的相关信息,
在做有关 d p dp dp 遍历到短儿子(设为 t o to to)时, 在 f o c [ ] foc[] foc[] 中开一个以 t o to to为开头的长链长度的空间, 来存储 t o to to 往下长链的信息,
这样做的好处是: 同一长链的节点可以 通过移动指针 O ( 1 ) O(1) O(1) 更新 d p dp dp 数组 , 进而做到整体 O ( N ) O(N) O(N) 复杂度 .


  • 一 道 例 题 一道例题

D o m i n a n t   I n d i c e s Dominant\ Indices Dominant Indices

给出一棵有根树,对于每个节点 x x x,定义一个无穷序列 d d d,
其中 d ( x , i ) d(x,i) d(x,i)表示以 x x x为根节点的子树中到 x x x的距离恰好为 i i i的点的个数, i = 0 i=0 i=0~ 无 穷 无穷
现在对每个点 x x x,希望求出一个东西 j j j,使得对于任意 k &lt; j , d ( x , k ) &lt; d ( x , j ) k&lt;j,d(x,k)&lt;d(x,j) k<jd(x,k)<d(x,j),对于任意 k &gt; j , d ( x , k ) ≤ d ( x , j ) k&gt;j,d(x,k) \le d(x,j) k>j,d(x,k)d(x,j) .


正 解 部 分 \color{red}{正解部分}

题 意 : 题意: : 对每个点求距离 A n s [ i ] Ans[i] Ans[i], 使得 A n s [ i ] Ans[i] Ans[i] 在使得 d ( i , A n s [ i ] ) d(i, Ans[i]) d(i,Ans[i]) 最大的同时 A n s [ i ] Ans[i] Ans[i] 尽量小 .

F [ i , j ] F[i, j] F[i,j] 表示距离 i i i 节点 j j j 的节点个数, F [ i , j ] = ∑ i ∈ s o n i F [ t o , j − 1 ] F[i, j] = \sum\limits_{i∈son_i}F[to,j-1] F[i,j]=isoniF[to,j1] ,
初 值 : 初值: : F [ i , 0 ] = 1 F[i, 0]=1 F[i,0]=1 .

重儿子通过长链直接继承, 轻儿子暴力继承即可, 时间复杂度


实 现 部 分 \color{red}{实现部分}
#include<bits/stdc++.h>
#define reg register

const int maxn = 4e6 + 6;

int N;
int *it;
int num0;
int *F[maxn];
int Ans[maxn];
int foc[maxn];
int son[maxn];
int len[maxn];
int head[maxn];

struct Edge{ int nxt, to; } edge[maxn << 1];

void Add(int from, int to){
        edge[++ num0] = (Edge){ head[from], to };
        head[from] = num0;
}

void DFS(int k, int fa){
        len[k] = 1;
        for(reg int i = head[k]; i; i = edge[i].nxt){
                int to = edge[i].to;
                if(to == fa) continue ;
                DFS(to, k);
                if(len[son[k]] < len[to]) son[k] = to;
        }
        len[k] = len[son[k]] + 1;
}

void DFS_2(int k, int fa){
        F[k][0] = 1;
        if(son[k]) F[son[k]] = F[k] + 1, DFS_2(son[k], k), Ans[k] = (F[son[k]][Ans[son[k]]]==1) ? Ans[k] : (Ans[son[k]]+1);
        for(reg int i = head[k]; i; i = edge[i].nxt){
                int to = edge[i].to;
                if(to == son[k] || to == fa) continue ;
                F[to] = it, it += len[to];
                DFS_2(to, k);
                for(reg int i = 1; i <= len[to]; i ++){
                        F[k][i] += F[to][i-1];
                        if(F[k][i] > F[k][Ans[k]] || (F[k][i] == F[k][Ans[k]] && Ans[k] > i)) Ans[k] = i;
                }
        }
}

int main(){
        scanf("%d", &N);
        for(reg int i = 1; i < N; i ++){
                int x, y; scanf("%d%d", &x, &y);
                Add(x, y), Add(y, x);
        }
        DFS(1, 0);
        F[1] = it = foc;
        it += len[1];
        DFS_2(1, 0);
        for(reg int i = 1; i <= N; i ++) printf("%d\n", Ans[i]);
        return 0;
}


  • 其 他 例 题 其他例题

  • Hotel加强版
  • AT2268
  • AT1998
  • AGC009D

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
【7层】6900平米左右一字型框架办公楼毕业设计(建筑结构图、计算书) 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值