分治,通常是有分和治,对于“分”来“治”,再合并,就是分治的思想。
二分查找
这是一种O(logn)的查找方法。
在单调的序列中,查找一个数,
有个猜数字的游戏是酱紫的:
给出一个范围1-1000 让你猜一个数,会告诉你这个数是大于答案还是小于答案
通过二分查找的思想,这个游戏可以在10次内猜出答案。
转化为二分的模型是酱紫的:
一个数列{1,2,3,4,5,……,1000},找到数k(和游戏有点不一样,意思差不多)
我们可以先从500开始查找,既然已经知道了k的大小,也就可以知道500是大于k还是小于k了
设k=625
所以500<k,则可以往500的右边查找,查找到(500+1000)/2=750
750>k,则往750的左边查找,(500+750)/2=625
625=k,二分查找用了三次就找到了k在哪里
所以代码就是酱紫:
while (l+1<r) { mid=(l+r)>>1;//右移1位,相当于/2 if (mid<k) l=mid; else r=mid; if (mid==k) break;//找到了 }
STL还有自带的,懒得写
二分答案
类似于二分查找,将大于小于改为检测mid是否符合一个答案
就比如说想知道一头鲲的吃南瓜的数量是否是吃西瓜的一半
就可以写出这样的二分:
while (l+1<r) { mid=(l+r)>>1; if (cheak(mid)) l=mid; else r=mid; }
其中的cheak函数是检测mid,也就是二分到的南瓜是否满足是西瓜的一半
cheak函数可以这样写:
inline bool cheak(int x) { return (x<=(k>>1));//k表示吃西瓜的多少,x表示传递到函数中的mid,也就是吃南瓜的多少 }
inline头表示是内联函数,不写也没关系
许多二分答案在循环完之后,答案会是l或者r,要在外面再cheak两下
快速排序与归并排序
这是两种比较快的排序算法,也是分治思想的应用
其中归并排序可用于求逆序对的个数
C++已经自带了这两种排序(快速排序用的较多,一般不使用C++中的归并排序),所以就不再赘述了
快速幂
在数论中,快速幂是非常基础的东西,也是用到了分治的思想
主要是基于以下两条:
当k%2=0,a^k=(a^2)^(k/2)
当k%2=1,a^k=((a^2)^(k/2))*a
用到快速幂一般需要%p
所以就可以随便推出代码啦:
int power(int a,int k) { int s=1; a%=p; while (k>0) { if (k%2==1) s=(s*a)%p; k>>=1; a=(a*a)%p; } return s%p; }
线段树
线段树是一种数据结构,支持区间修改,区间查询,时间复杂度为O(logn)
其思想就是将一段区间分为一大堆线段
根节点维护begin-end的区间
非叶子节点k的左儿子是k区间的左半部分,右儿子是右半部分
然后维护就星
(这谁看得懂就NB了)
(毕竟这是基础分治瞎说一下就星)
get一些基本操作可以看这一篇:
如果想要学这玩意儿我没有