分治算法

[学习笔记]点分治

余生颓废 提交于 2020-03-04 15:12:34
点分治 解决问题 对于某些限定条件的路径静态地进行统计的算法. 基本思路 分治思想 对于某一点P,树上路径可以分为两类,经过点P,包含与点P的某一棵子树上 第二种可以递归处理 第一种通过求P的所有子节点的深度就可以处理 树的重心 如果是一条链的话,那复杂度很大,需要递归N层,每个节点访问一次. 用重心求只需要 \(log​\) 层  模板题① Tree 本题是求两点路径小于等于k code #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 1e4 + 7; const int inf = 0x3f3f3f3f; int k, tot, head[maxn]; bool vis[maxn]; int nowN, rt, maxP; int fin; int Size[maxn], dep[maxn]; struct Edge { int to, next, w; } e[maxn << 1]; vector<int> D; void init(int n) { tot = 0; for (int i = 0; i <= n; ++i) { head[i] = 0; vis[i] = 0; } fin = 0;

1.2 基本算法 分治算法

删除回忆录丶 提交于 2020-03-03 18:08:06
一、基本思想 当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。 利用分治策略求解时,所需时间取决于分解后子问题的个数、子问题的规模大小等因素,而二分法,由于其划分的简单和均匀的特点,是经常采用的一种有效的方法,例如二分法检索。 二、解题步骤 分治法解题的一般步骤: (1)分解,将要解决的问题划分成若干规模较小的同类问题; (2)求解,当子问题划分得足够小时,用较简单的方法解决; (3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。 三、适用范围 分治法所能解决的问题一般具有以下几个特征: 该问题的规模缩小到一定的程度就可以容易地解决 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。 利用该问题分解出的子问题的解可以合并为该问题的解; 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。 来源: CSDN 作者: _几禾学长_ 链接: https://blog.csdn.net/qq_45690050

算法思想

你说的曾经没有我的故事 提交于 2020-03-03 09:34:52
1.算法思想的概念 ================================================================================================ 1.1贪心--贪心思想 ======================================================================================================= 1.1.1 贪心--背包问题 ========================================================================================================================= 1.1.2 贪心--贪心算法思考 ======================================================================================================== 1.2、贪心-贪心算法应用场景 ======================================================================================================

从分治的角度理解FFT

生来就可爱ヽ(ⅴ<●) 提交于 2020-03-02 13:07:03
  本随笔的目标主要在于解决两个多项式相乘得到新多项式的问题,我们举一个例子,A(x)是n-1次的,B(x)是n-1次,那么我们用C(x) = A(x) * B(x),如果要完整的求出C(x)的系数,采取暴力手段的话一般需要N^2的量级,希望在讲完这一章的内容之后,我们都可以知道怎么样在nlogn的复杂度内解决这个问题。   我们把整个算法分成若干步,来计算C(x) = c0 + c1*x + c2*x^2 + ... + c(2n-1)*x^(2n-1)的系数c0~c(2n-1),其中C(x)是由A(x)和B(x)相乘得到的。   我们先介绍一下单位根的内容,学过复数的同学们应该都知道,形如a + bi的复数可以用三角式表达r(cosx + isinx),如果r = 1,我们就得到了一个单位复数cosx + isinx,为了记号的方便,我们把这个复数记作e(x),其中x是[0,2pi)中的实数。于是e(0) = 1,e(x)^2 = e(2x),e(x) * e(y) = e(x + y)都容易得到;如果x = k*pi/2n,我们立刻得到e(x)^0 + e(x)^1 + ... + e(x)^(2n-1) = 2n 或者0,其中2n在k = 0的时候取到,0在其他情况下取到。大概就只需要这些知识。   第一步,我们来介绍对一个多项式A(x),快速求出其在x = e(k *

NOIP需要掌握的内容(大致

旧街凉风 提交于 2020-03-02 11:41:13
1、 排序算法(快排、选择、冒泡、堆排序、 二叉排序树 、桶排序) 2、 DFS/BFS 剪枝 哈希表 3、树 ① 遍历 ② 二叉树 ③二叉排序树(查找、生成、删除) ④堆(二叉堆、左偏树、堆排序) ⑤Trie树 4、图(图论建模) ① 最小生成树 ② 最短路径 ③计算图的传递闭包 ④ 连通分量(其中要掌握并查集技术) 强连通分量tarjin ⑤ 拓扑排序 、关键路径 ⑥哈密尔顿环 ⑦ 欧拉回路 (USACO 3.3 题1 Fence) ⑧ Bell-man Ford、SPFA(能解决负权回路) (USACO 3.2 题6 Butter) ⑨二分图(匈牙利算法)(USACO 4.2 题2 stall) 5、动态规划(背包问题只是其中一种) ① 线性动规 ② 区间动规 ③ 树形动规 ④图形动规 6、 分治 (掌握了动规分治就好学了) 7、 贪心 8、 位运算 (可以用来进行优化) 来源: https://www.cnblogs.com/GldHkkowo/p/8710834.html

分治算法示例

十年热恋 提交于 2020-02-15 22:02:11
通过一个例子来介绍分治算法的应用。一个袋子里有30枚银币,其中一枚银币为假,并且假银币和真银币一模一样,肉眼很难分辨,目前只知道假银币比真银币重量轻一点。请问如何找出假银币? 首先来分析一下寻找假银币的问题,可以采用递归分治的思想来求解这个问题,操作如下: (1)首先为每个银币编号,然后将所有的银币等分为两份,放在天平的两边。这样就将区分30个银币的问题变为区分两堆银币的问题。 (2)因为假银币的重量较轻,因此天平较轻的一侧一定包含假银币。 (3)再将较轻的一侧中的硬银币等分为两份,重复上述做法。 (4)直到剩下两枚银币,便可用天平直接找出假银币。 int FalseCoin ( int * coin , int low , int high ) { int i , sum1 , sum2 , sum3 ; //定义三个变量sum1为前半段和,sum2为后半段和,sum3为奇数中间的数 int re ; sum1 = sum2 = sum3 = 0 ; if ( low + 1 = high ) //只有两个数 { if ( coin [ low ] < coin [ high ] ) { re = low + 1 ; return re ; //返回假银币的位置 } else { re = high + 1 ; return re ; } } if ( ( high - low

分治算法讲解与应用

痞子三分冷 提交于 2020-02-15 00:24:52
分治算法 分治算法的基本步骤 @author:qyx 2013/6/3 分治法在每一层递归上都有三个步骤 1) 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题 2) 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题 3) 合并:将各个子问题地解合并为原问题地解 使用分治算法求解汉诺塔问题: 可以把求解过程分为三步: 1 如果有一个盘 A->C 2 如果盘子数超过两个,我们总是可以看做是两个盘,1最下边的盘,2 上面的盘 1) 先把最上面的盘A->B 2) 把最下边的盘A->C 3) 把B塔的所有盘从B->C package com.qyx.dac; public class Hanoitower { public static void main(String[] args) { hanoitower(5, 'A', 'B', 'C'); } //汉诺塔的移动方法 //使用分治算法 public static void hanoitower(int num,char a,char b,char c) { //如果只有一个盘 if(num==1) { System.out.println("第一个盘从"+a+"->"+c); }else{ //如果盘的数量大于2,那么我可以看做是两个盘:1 最下边的盘 2 上面的盘 //1 先把最上面的盘A-

点分治总结(未完成)

穿精又带淫゛_ 提交于 2020-02-13 20:46:20
点分治常用于静态树上的路经统计问题,我们可以很自然的设计出这样一种分治算法: 1.找出根结点Root; 2.计算以Root为根的树的答案; 3.删除结点Root,分治解决Root的每个子树; 但这样并不是最优,当树退化成链时,递归层数就会退化为O(N), 整个程序时间复杂度也会退化成O(N ^ 2)。 为了解决这个问题,我们每次找的Root必须是树的重心。这样的话递归的复杂度就能稳定在O(N)。 树的重心: 树的重心也叫树的质心。找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。 --百度百科 根据树的重心的概念, 来源: https://www.cnblogs.com/mcggvc/p/12304733.html

CDQ 分治

巧了我就是萌 提交于 2020-02-11 20:42:26
引言: 什么是CDQ分治?其实这是一种思想而不是具体算法,因此CDQ分治覆盖的范围相当广泛,在 OI 界初见于陈丹琦 2008 年的集训队作业中,故被称为CDQ分治。 大致分为三类: cdq分治解决与点对有关的问题 cdq分治优化1D/1D 动态规划的转移 通过 cdq 分治,将一些动态问题转化为静态问题 先总体说一下CDQ分治: 通常用来解决一类“修改独立,允许离线”的数据结构题。实际上它的本质是按时间分治,即若要处理时间 \([l,r]\) 上的修改与询问操作,就先处理 \([l,mid]\) 上的修改对 \([mid + 1,r]\) 上的询问的影响,之后再递归处理 \([l,mid]\) 与 \([mid + 1,r]\) ,根据问题的不同,这几个步骤的顺序有时也会不一样。 CDQ 分治会使得我们考虑的问题的思维难度与代码难度大大减小,通常利用 CDQ 分治能使得一个树套树实现的题目,能够去掉外层的树,改为用分治来进行求解。 算法描述 CDQ分治适用于满足一下两个条件的数据结构题: 修改操作对询问的贡献独立,修改操作之间互不影响效果 题目允许使用离线算法 我们不妨假设我们需要(按顺序)完成的操作序列称为S,考虑将整个操作序列等分为前后两个部分,那么我们可以发下以下两个性质: 显然,后一半操作序列中的修改操作对前一半操作序列中的询问结果不会产生任何影响。

算法浅谈——分治算法与归并、快速排序(附代码和动图演示)

我怕爱的太早我们不能终老 提交于 2020-02-06 09:50:39
在之前的文章当中,我们通过海盗分金币问题详细讲解了递归方法。 我们可以认为在递归的过程当中,我们通过函数自己调用自己,将大问题转化成了小问题,因此简化了编码以及建模。今天这篇文章呢,就正式和大家聊一聊将大问题简化成小问题的分治算法的经典使用场景——排序。 排序算法 排序算法有很多,很多博文都有总结,号称有十大经典的排序算法。我们信手拈来就可以说上来很多,比如插入排序、选择排序、桶排序、希尔排序、快速排序、归并排序等等。老实讲这么多排序算法,但我们实际工作中并不会用到那么多,凡是高级语言都有自带的排序工具,我们直接调用就好。为了应付面试以及提升自己算法能力呢,用到的也就那么几种。今天我们来介绍一下利用分治思想实现的两种经典排序算法——归并排序与快速排序。 归并排序 我们先来讲归并排序,归并排序的思路其实很简单,说白了只有一句话:两个有序数组归并的复杂度是 \(O(n)\) 。 我们举个例子: a = [1, 4, 6] b = [2, 4, 5] c = [] 我们用i和j分别表示a和b两个数组的下标,c表示归并之后的数组,显然一开始的时候i, j = 0, 0。我们不停地比较a和b数组i和j位置大小关系,将小的那个数填入c。 填入一个数之后: i = 1 j = 0 a = [1, 4, 6] b = [2, 4, 5] c = [1] 填入两个数之后: i = 1 j = 1 a