190 likes | 351 Views
分治法的应用. 王宇琛. 分治法在程序设计中的应用非常多,例如快速排序,归并排序,排序二叉树等。. 快速排序和归并排序. 快速排序:将长度为 n 的数组分成两部分,小于标准元素的部分以及大于标准元素的部分 归并排序:将长度为 n 的数组分成前 n/2 个元素和后 n/2 个元素两部分. 二叉排序树. 大于根节点的元素在右子树,小于根节点的元素在左子树. 例题 1. 求 a b % c. 例题 1.
E N D
分治法的应用 王宇琛
分治法在程序设计中的应用非常多,例如快速排序,归并排序,排序二叉树等。分治法在程序设计中的应用非常多,例如快速排序,归并排序,排序二叉树等。
快速排序和归并排序 • 快速排序:将长度为n的数组分成两部分,小于标准元素的部分以及大于标准元素的部分 • 归并排序:将长度为n的数组分成前n/2个元素和后n/2个元素两部分
二叉排序树 • 大于根节点的元素在右子树,小于根节点的元素在左子树
例题1 • 求ab% c
例题1 • 利用ab = (ab/2)2,分情况讨论,若b为奇数,则ab = (ab/2)2 * a,若b为偶数,则ab = (ab/2)2。
例题1 intcalc(int a, int b, int c) { if (b == 0) return 1; long long ret = calc(a, b / 2, c); ret = ret *ret % c; if (b % 2 == 1) ret = ret * a % c; return ret; }
例题1扩展 • 给定a, b, c,求(a1+ a2+ …… + ab) % c。
例题1扩展 设sn = a0 + a1 + ……+ an,则s2n = sn + sn * an。
例题1扩展 void calc(int a, intb, intc, int &x, int &y) { if (b == 1) {x = a % c; y = a % c; return;} long long ret1, ret2; calc(a, b / 2, c, ret1, ret2); ret1 = ret1 * (ret2 + 1) % mo; ret2 = ret2 * ret2 % mo; if (b % 2 == 1) { ret2 = ret2 * a % mo; ret1 = (ret1 + ret2) % mo; } x = ret1; y = ret2; }
例题2 • LCA问题
例题2 • LCA->RMQ • 深搜序列的特点
例题2 RMQ问题:给定长度为n的数组a,快速回答“第i个元素到第j个元素之间的最小元素是哪一个”这样的询问。
例题2 • 朴素的枚举算法单个询问的时间复杂度为O(n) • 考虑事先计算某些特定区间的询问答案,根据已求得的答案快速回答询问。
例题2 • 设F[i][j]表示从i开始长度为2^j的区间的最小元素。 • 显然F[i][0] = a[i]。 • 根据F之间的相对关系,我们可以得到F[i][j] = min{F[i][j - 1], F[i + 2^j][j - 1]}
例题2 • 对于F[i][j]而言,i的范围是0~n-1,j的范围是0~logn,故计算F[i][j]的时间为O(nlogn)。 • 对于询问[l,r],设w = log(r – l +1),则询问的答案为:min{F[l][w], F[r -2^w][w]},故回答询问的时间复杂度为O(1)。
总结 • 分治法合理利用数据之间的相对关系,发掘深处的信息量,从而能够快速的解决部分问题
思考题 • 如果你有a块长度为2的木板和b块长度为3的木板,而且你不能锯断这些木板,那么你最多可以利用这些资源拼成多少个长度为c的木板