【总结】点分治

点分治

点分治适合处理大规模的树上路径信息问题。

  • 求两点间距离为 k k k 的合法路径总和:使用扫描法 L L L R R R
  • 每次选择重心 p p p ,因为每一层的所有递归过程合计对每个节点处理 1 1 1 次,而点分治最多递归 l o g n logn logn 层,复杂度可以保证
  • 求重心必须完整地遍历一次整个子树,但是 d i s dis dis 数组是可以通过 v e c t o r vector vector 存下来的(不超过 n l o g n nlogn nlogn 个元素),也就是说子树的信息完全可以用数据结构存下来(只要不超过子树大小),甚至可以接到父节点上
  • 这就引出了点分树:将每次找到的重心与上一层的重心缔结父子关系,就可以方便地进行线段树合并等操作了

那么数据结构是干什么的呢?当然是计算 c a l c ( x ) calc(x) calc(x) 了。假设这个部分的时间复杂度是 O ( A ) O(A) O(A) ,总时间复杂度就是 O ( A n l o g n ) O(Anlogn) O(Anlogn)

这里可以把 c a l c calc calc 看成是一个静态的函数,所以可以一边递归一边计算。

点分治的含义是分治,也就是说分成若干个子问题,先将当前层的 c a l c calc calc 算出来,再分成若干个独立的子树分别求解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分治算法是一种把问题分成多个子问题,然后将子问题的解合并起来得到原问题解的算法。通常情况下,分治算法可以分为三个步骤:分解、解决和合并。在本次实验中,我们将使用分治算法来解决一个经典的问题:求解一个数组中的最大值。 1.问题描述 给定一个数组,我们需要找到其中的最大值。 2.算法设计 我们使用分治算法来解决这个问题。具体来说,我们将数组分成两个子数组,然后递归地对这两个子数组求解最大值,最后将两个子数组的最大值合并起来得到原数组的最大值。 具体的算法步骤如下: (1)将数组分成两个子数组,分别求解其中的最大值。 (2)将两个子数组的最大值进行比较,得到原数组的最大值。 3.实验过程 为了实现这个算法,我们需要编写一个递归函数。该函数将在不断地对子数组进行分解,直到子数组的长度为1时,返回子数组中的唯一元素。 在进行合并时,我们需要比较两个子数组的最大值,然后将较大的值作为结果返回。 下面是具体的代码实现: ``` // 分治算法求解最大值 int max(int arr[], int start, int end) { // 如果子数组长度为1,返回该元素 if (start == end) { return arr[start]; } // 将数组分成两个子数组 int mid = (start + end) / 2; int left = max(arr, start, mid); int right = max(arr, mid + 1, end); // 合并两个子数组的结果 return left > right ? left : right; } ``` 4.实验结果 我们使用一个长度为10的随机数组进行测试,如下所示: ``` int arr[] = {9, 4, 7, 8, 6, 2, 10, 3, 5, 1}; int result = max(arr, 0, 9); cout << "The max value in the array is " << result << endl; ``` 运行结果如下: ``` The max value in the array is 10 ``` 可以看到,我们成功地使用分治算法求解了给定数组的最大值。 5.实验总结 本次实验我们学习了分治算法的基本思想,并且使用分治算法成功地求解了一个经典问题。分治算法可以解决很多复杂的问题,例如排序、查找等,它的时间复杂度通常可以达到O(nlogn)。因此,在算法设计中,我们可以考虑使用分治算法来解决一些复杂的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值