分治的一些基础应用

分治,通常是有分和治,对于“分”来“治”,再合并,就是分治的思想。

二分查找

这是一种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;
}

线段树

随便BB几句算了


线段树是一种数据结构,支持区间修改,区间查询,时间复杂度为O(logn)

其思想就是将一段区间分为一大堆线段

根节点维护begin-end的区间

非叶子节点k的左儿子是k区间的左半部分,右儿子是右半部分

然后维护就星

(这谁看得懂就NB了)

(毕竟这是基础分治瞎说一下就星)

get一些基本操作可以看这一篇:

点击打开链接

如果想要学这玩意儿我没有

猜你喜欢

转载自blog.csdn.net/fsl123fsl/article/details/80407075