分治思想总结
作者:互联网
日期:2022年5月18日
注:本博客仅供参考
概念与基本思路
分治,即“分而治之”,就是把一个复杂的问题分解成两个或更多个相同或相似的子问题,一直分解到子问题可以简单地直接求解,原问题的解即为子问题的解的合并。
应用
分治是很多高效算法的基础,如快速排序、归并排序(虽然在sort函数的帮助下,已无自己写排序算法的必要,但其思想依然值得去学习与应用)等等。
实现方法
可以使用递归将大问题逐步分割为一个个元素,再在每一个元素中将问题解决并将元素逐步合并,最后就能得到大问题的答案。
代码
归并排序(P1177)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[100100],t[100100]; 4 void mergeSort(int L,int R){ 5 if(L==R)//当问题已经分解为一个个元素时不再分解 6 { 7 return; 8 } 9 int mid=(L+R)/2;//将问题一分为二 10 mergeSort(L,mid);//左边的一半进行递归 11 mergeSort(mid+1,R);//右边的一半也进行递归 12 int i=L,j=mid+1; 13 for(int k=L;k<=R;++k) 14 { 15 if(j>R||i<=mid&&a[i]<=a[j])//右半边已经排完或左半边中某个元素大于右半边中某个元素 16 { 17 t[k]=a[i];//将更小的元素复制到一个暂时存储结果的文件夹 18 ++i;//比较左半边的下一个元素 19 }else{//左半边已经排完或右半边某个元素大于左半边某个元素 20 t[k]=a[j];//同理,复制更小的元素 21 ++j;//同理,比较右半边的下一个元素 22 } 23 24 } 25 for(int k=L;k<=R;++k) 26 { 27 a[k]=t[k];//将排好的元素还原到原来数组中(因为还需要和数组的其他部分进行排序) 28 } 29 } 30 int main(){ 31 scanf("%d",&n); 32 for(int i=1;i<=n;++i) 33 { 34 scanf("%d",&a[i]); 35 } 36 mergeSort(1,n); 37 for(int i=1;i<=n-1;++i) 38 { 39 printf("%d ",a[i]); 40 } 41 printf("%d\n",a[n]); 42 return 0; 43 }
逆序对(P1908,可以看作为归并排序的应用)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[500100],t[500100]; 4 long long ans=0; 5 void mergeSort(int L,int R){ 6 if(L==R) 7 { 8 return; 9 } 10 int mid=(L+R)/2; 11 mergeSort(L,mid); 12 mergeSort(mid+1,R); 13 int i=L,j=mid+1; 14 for(int k=L;k<=R;++k) 15 { 16 if(j>R||i<=mid&&a[i]<=a[j]) 17 { 18 t[k]=a[i]; 19 ++i; 20 }else{ 21 t[k]=a[j]; 22 ++j; 23 ans+=mid-i+1;//增加的部分 24 } 25 26 } 27 for(int k=L;k<=R;++k) 28 { 29 a[k]=t[k]; 30 } 31 } 32 int main(){ 33 scanf("%d",&n); 34 for(int i=1;i<=n;++i) 35 { 36 scanf("%d",&a[i]); 37 } 38 mergeSort(1,n); 39 printf("%lld",ans); 40 return 0; 41 }
心得
- 分治需要划定界限,否则会一直分下去而RE
- 相比于分治,二分可能更简单一些(因为二分可以不用递归就能实现)
- 也需要注意开的数能否承载下要承载的数据
标签:总结,mergeSort,思想,int,分治,mid,问题,排序 来源: https://www.cnblogs.com/PlayerSS05/p/16287834.html