C:1110最近共同祖先(函数专题)

这篇博客介绍了如何在无限大的二叉树中找到两个节点的最近共同祖先。通过递归函数`common(int x, int y)`实现,当x等于y时返回x,否则根据x和y的大小关系分别回溯它们的一半节点来寻找共同祖先。样例输入10 4,输出2,表示10和4的最近共同祖先是2。博客还提到了完全二叉树的特性以及节点关系。" 84335556,5094673,Java 8 函数式编程详解:接口与实践,"['函数式编程', 'Java', '编程实践']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

        如上图所示,由正整数1, 2, 3, ...组成了一棵无限大的二叉树。从某一个结点到根结点(编号是1 的结点)都有一条唯一的路径,比如从10 到根结点的路径是(10, 5, 2, 1),从4 到根结点的路径是(4, 2, 1),从该结点到根结点的路径上的所有结点称为该结点的祖先。现在的问题就是,给定x 和y,求x和y的最近共同祖先,比如,10和4最近共同祖先是2,10和5的最近共同祖先是5。
定义递归函数
        int common(int x, int y)
        {
                //如果x==y, return x;
                //如果x>y,求x/2与y的共同祖先;
                //否则,求x与y/2的共同祖先;
        }
输入:输入只有一行,包括两个正整数x 和y,这两个正整数都不大于1000。
输出:输出只有一

<think>嗯,用户需要快速学习一些算法数据结构,用于C++比赛。他们列出的内容挺多的,枚举、排序、搜索、贪心等等,还有图论和数学相关的内容。首先,我得确定用户的背景。可能是个刚开始参加编程竞赛的学生,需要系统地复习这些常见的算法数据结构,可能在准备蓝桥杯、ACM之类的比赛。 用户提到的“快速性学习”可能意味着他们时间紧迫,需要高效掌握这些知识点。所以,回答要结构清晰,分点介绍每个主题的核心概念、应用场景以及C++的实现技巧。同时,用户需要实际打比赛的例子,所以代码示例和优化技巧会很关键。 接下来,每个部分需要简要但足够详细。比如枚举,要说明其适用情况,优缺点。排序算法部分,用户已经提到了冒泡、选择、插入,还有归并和快排。需要区分基础排序和更高效的排序,给出时间复杂度和适用场景。 搜索方面,BFS和DFS的区别和应用,比如最短路径用BFS,回溯用DFS。记忆化搜索通常和动态规划结合,可能需要例子说明。贪心和模拟相对容易,但贪心的正确性需要强调,可能需要举经典题目例子。 二分查找和高精度处理是比赛中常见的考点,特别是高精度在数据范围大时的处理,比如用数组存储各位数字。数据结构中的栈、队列、ST表需要给出实现方式和典型应用,比如ST表用于区间最值查询。 图论中的最近共同祖先(LCA)是较高级的内容,需要介绍倍增法或Tarjan算法,但可能只需简要说明原理和实现步骤。数学部分如容斥原理,要举例说明应用场景,比如集合计数问题。 还要注意C++中的STL应用,比如用sort函数实现快速排序,使用队列和栈的标准库,避免重复造轮子。同时,提醒一些常见错误,比如二分查找的边界条件,高精度计算的进位处理,递归搜索的终止条件等。 最后,总结部分需要强调练习和题目的重要性,建议用户通过刷题巩固,并推荐一些经典题目或在线评测平台。可能需要检查是否有遗漏的知识点,确保覆盖用户提到的所有内容,同时保持回答的条理性,方便用户快速查阅和复习。</think>我将以算法竞赛常用知识点为框架,为您整理C++算法竞赛快速学习指南。以下内容按照知识体系分层讲解,并提供关键代码模板: ### 一、基础算法 1. **枚举算法** - 特点:暴力遍历所有可能解 - 优化方向:剪枝、状态压缩 - 示例:求n位数中各位立方和等于原数的数 ```cpp for(int i=pow(10,n-1); i<pow(10,n); ++i){ int sum=0, tmp=i; while(tmp){ sum += pow(tmp%10,3); tmp /= 10; } if(sum == i) cout<<i<<endl; } ``` 2. **基础排序** - 冒泡排序:稳定,$O(n^2)$ ```cpp for(int i=0; i<n-1; ++i) for(int j=0; j<n-1-i; ++j) if(a[j]>a[j+1]) swap(a[j],a[j+1]); ``` - 选择排序:不稳定,$O(n^2)$ - 插入排序:稳定,适合小规模数据 3. **二分查找** - 核心:有序性、边界处理 - 代码框架: ```cpp int l=0, r=n-1; while(l<=r){ int mid = l + (r-l)/2; if(check(mid)) r=mid-1; else l=mid+1; } return l; ``` ### 二、进阶算法 1. **高效排序** - 快速排序:分治思想,平均$O(n\log n)$ ```cpp void qsort(int l, int r){ if(l >= r) return; int i=l-1, j=r+1, x=a[(l+r)>>1]; while(i < j){ do i++; while(a[i]<x); do j--; while(a[j]>x); if(i<j) swap(a[i],a[j]); } qsort(l,j), qsort(j+1,r); } ``` - 归并排序:稳定,适合外部排序 2. **搜索算法** - BFS:队列实现,最短路径问题 ```cpp queue<Node> q; q.push(start); while(!q.empty()){ auto t = q.front(); q.pop(); for(所有相邻节点){ if(未访问) q.push(节点), 标记访问 } } ``` - DFS:递归/栈实现,回溯法基础 - 记忆化搜索:DP的递归实现形式 3. **贪心算法** - 特性:局部最优推导全局最优 - 经典应用:区间调度、哈夫曼编码 ### 三、数据结构 1. **线性结构** - 栈:后进先出,括号匹配问题 - 队列:先进先出,BFS实现基础 - ST表:解决RMQ问题,$O(n\log n)$预处理,$O(1)$查询 ```cpp int st[MAXN][20]; // st[i][j]表示区间[i,i+2^j-1]的最值 void build(){ for(int j=1; (1<<j)<=n; ++j) for(int i=1; i+(1<<j)-1<=n; ++i) st[i][j] = max(st[i][j-1], st[i+(1<<(j-1))][j-1]); } int query(int l, int r){ int k = log2(r-l+1); return max(st[l][k], st[r-(1<<k)+1][k]); } ``` ### 四、数学与图论 1. **高精度计算** - 实现方式:数组存储各位数字 - 核心操作:进位处理、前导零去除 2. **容斥原理** - 公式:$|A∪B∪C| = |A|+|B|+|C| - |A∩B| - |A∩C| - |B∩C| + |A∩B∩C|$ - 应用:求1-n中能被质数集合整除的数的个数 3. **最近公共祖先(LCA)** - 倍增法实现步骤: 1. 预处理每个节点的$2^k$级祖先 2. 通过二分法调整节点深度 3. 同步上跳查找公共祖先 ### 五、实战技巧 1. **代码模板化**:整理常用算法模板 2. **复杂度分析**:快速估算算法可行性 3. **STL应用**: - `sort()`(快速排序实现) - `priority_queue`(堆实现) - `lower_bound()`(二分查找) 4. **调试技巧**: - 边界测试:0值、极大值 - 中间输出调试 - 使用assert进行断言检查 ### 六、学习路线建议 1. 基础阶段(2周): - 掌握排序、查找、简单数据结构 - 熟悉基础语法和输入输出处理 2. 提高阶段(3周): - 攻克动态规划、图论基础 - 练习经典算法题(如背包问题、最短路) 3. 冲刺阶段(2周): - 专题突破薄弱环节 - 参加模拟赛训练速度 建议练习平台:洛谷(www.luogu.com.cn)、Codeforces、LeetCode 注:实际代码实现时需注意数据范围判断和异常处理。算法竞赛中应优先保证核心逻辑正确性,再优化代码效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

舟桥居士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值