分治(洛谷)


前言


提示:以下是本篇文章正文内容,下面案例可供参考

一、二分不相似(与算法设计与分析66page 例3-2)

P1128
代码如下(示例):

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
ll len(ll k){
    
    
	ll sum=1;
	for(ll i=1;i<=k;i++) sum*=2;
	return sum;
}
void solve(ll a,ll b,ll x,ll y,ll size){
    
    
	if(size==1) return;
	if(x-a<=size/2-1&&y-b<=size/2-1){
    
                                      //左上角 
		cout<<a+size/2<<" "<<b+size/2<<" "<<1<<endl;
		solve(a,b,x,y,size/2);                              //继续搜索左上角 
		solve(a,b+size/2,a+size/2-1,b+size/2,size/2);       //右上角 
		solve(a+size/2,b,a+size/2,b+size/2-1,size/2);       //左下角 
		solve(a+size/2,b+size/2,a+size/2,b+size/2,size/2);  //右下角 
	}
	else if(x-a<=size/2-1&&y-b>size/2-1){
    
                                  //右上角 
		cout<<a+size/2<<" "<<b+size/2-1<<" "<<2<<endl;
	    solve(a,b,a+size/2-1,b+size/2-1,size/2);            //左上角
	    solve(a,b+size/2,x,y,size/2);                       //继续搜索右上角
	    solve(a+size/2,b,a+size/2,b+size/2-1,size/2);       //左下角
	    solve(a+size/2,b+size/2,a+size/2,b+size/2,size/2);  //右下角
	}
	else if(x-a>size/2-1&&y-b<=size/2-1){
    
                                  //左下角 
		cout<<a+size/2-1<<" "<<b+size/2<<" "<<3<<endl;
		solve(a,b,a+size/2-1,b+size/2-1,size/2);            //左上角
		solve(a,b+size/2,a+size/2-1,b+size/2,size/2);       //右上角
		solve(a+size/2,b,x,y,size/2);                       //继续搜索左下角
		solve(a+size/2,b+size/2,a+size/2,b+size/2,size/2);  //右下角
	} 
	else{
    
    															   //右下角 
	    cout<<a+size/2-1<<" "<<b+size/2-1<<" "<<4<<endl;
		solve(a,b,a+size/2-1,b+size/2-1,size/2);            //左上角
		solve(a,b+size/2,a+size/2-1,b+size/2,size/2);       //右上角
		solve(a+size/2,b,a+size/2,b+size/2-1,size/2);       //左下角
		solve(a+size/2,b+size/2,x,y,size/2);                //继续搜索右下角
	}
}
int main()
{
    
    
   int x,y,k,size;
   cin>>k>>x>>y;
   size=len(k);//方格大小
   solve(1,1,x,y,size);
   //左上角方格所在行,左上角方格所在列,公主所在的位置,方格大小
   return 0;
}


二、二分不独立(同算法设计与分析70page 例3-3)

P1115

#include <bits/stdc++.h>//万能头 
using namespace std;
int a[200050],n;
long long int max_sub_sum(int left,int right);//函数的声明 
int main(){
    
    
	cin>>n;// 
	for(int i=1;i<=n;i++){
    
    //输入n个数据 
		cin>>a[i];
	}
	cout<<max_sub_sum(1,n);//求1到n之间的最大子段和 
	return 0;
} 

long long int max_sub_sum(int left,int right){
    
    
	long long int center,left_sub_sum,right_sub_sum,s1,s2,lefts,rights;
	if(left==right){
    
    //如果子段长度为1,返回子段大小 
	  return a[left];
	}
	else{
    
    
		center=(left+right)/2;//二分   分为左右两段 
		left_sub_sum=max_sub_sum(left,center);//递归求左边子段  		将左边子段分的更小(分为左右两段) 
		right_sub_sum=max_sub_sum(center+1,right);//递归求右边子段  	将右边子段分的更小(分为左右两段) 
		s1=-9999,lefts=0,s2=-9999,rights=0;//初始化子段的值,s1,s2的子段和要设为负数,因为子段中的数存在负数,最大字段和可能小于0 
		for(int i=center;i>=left;i--){
    
    //求左边子段最大值 
			lefts+=a[i];
			if(lefts>s1) s1=lefts;
		}
		for(int i=center+1;i<=right;i++){
    
    //求右边子段最大值 
			rights+=a[i];
			if(rights>s2) s2=rights;
		}
		if(s1+s2<=left_sub_sum&&left_sub_sum>=right_sub_sum) return left_sub_sum;//比较左子段和中间子段的和,返回最大值 
		if(s1+s2<=right_sub_sum&&left_sub_sum<=right_sub_sum) return right_sub_sum;
		return s1+s2;
	}
}

三、快排的几种写法

P1177

1.传统快排三个TLE

//传统快排三个TLE 
#include <iostream>
using namespace std;
int n,a[1000001];
void qsort(int a[],int L,int R)
{
    
    
	if(L>=R) return;
	int left=L,right=R;
	int pivot=a[left];
	while(left<right) 
	{
    
    
		while(left<right&&a[right]>=pivot) right--;
		if(left<right) a[left]=a[right];
		while(left<right&&a[left]<=pivot) left++;
		if(left<right) a[right]=a[left];
		if(left>=right) a[left]=pivot; 
	}
	qsort(a,L,right-1);
	qsort(a,right+1,R);
}
int main()
{
    
    
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	qsort(a,1,n);
	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	return 0;
}

2.使用随机数进行优化 快速排序 1个TLE

//随机数 快速排序 1个TLE 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int n,a[1000001];
void Quicksort(int a[],int L,int R)
{
    
    
	if(L>=R) return;
	int left=L,right=R,temp,x=rand()%(R-L+1)+L;
	temp=a[left];
	a[left]=a[x];
	a[x]=temp;
	int pivot=a[left];
	while(left<right) 
	{
    
    
		while(left<right&&a[right]>=pivot) right--;
		if(left<right) a[left]=a[right];
		while(left<right&&a[left]<=pivot) left++;
		if(left<right) a[right]=a[left];
		if(left>=right) a[left]=pivot; 
	}
	Quicksort(a,L,right-1);
	Quicksort(a,right+1,R);
}
int main()
{
    
    
	srand((int)time(NULL));
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	Quicksort(a,1,n);
	for(int i=1;i<=n;i++) printf("%d ",a[i]);
	return 0;
}

3.二分快速排序(yyds) 比sort()还快

//二分快速排序(yyds) 	AC
#include<iostream>
using namespace std;
int n,a[1000001];
void qsort(int L,int R)
{
    
    
	int mid=a[(L+R)/2],temp;
	int left=L,right=R;
	do
	{
    
    
	while(a[left]<mid) left++;
	while(a[right]>mid)  right--;
	if(left<=right)
	{
    
    
		temp=a[left];
		a[left]=a[right];
		a[right]=temp;
		left++;
		right--;
	}	
	}while(left<=right)	;
	if(L<right) qsort(L,right);
	if(R>left) qsort(left,R);
} 
int main()
{
    
    
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    qsort(1,n);
    for(int i=1;i<=n;i++) cout<<a[i]<<" ";
}

4.C++ STL大法

//C++ STL大法
#include <iostream>
#include <algorithm>
using namespace std;
int a[1000010],n;
int main()
{
    
    
	cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45879198/article/details/120389197