分治、二分

分治、二分

分治:

  • 就是分解成若干小规模问题解决

  • 分治的步骤:

  • image

  • 示例:汉诺塔问题、归并排序

  • 归并排序求逆序对

  • #include<iostream>
    using namespace std;
    int n;
    int a[50010];
    int b[50010];
    long long ans = 0;
    
    void merge_sort(int left,int right ) {
    	if (left==right)
    	{
    		return;
    	}
    	else
    	{
    		int mid = (left + right) / 2;
    		int i = left, j = mid + 1, k = left;
    		merge_sort(left, mid);
    		merge_sort(mid + 1, right);
    		//左右都有数
    		while (i <= mid && j <= right) {
    			if (a[i] < a[j])
    			{
    				b[k++] = a[i++];//不是逆序对,b数组存小的数
    			}
    			else
    			{
    				b[k++] = a[j++];//是逆序对
    				ans += mid - i + 1;
    				/*
    					记录逆序对数,根据下标来判断有几个逆序数,
    					比如3142,有两个逆序对,先判断3,ans=1-0+1=2,即3-1,3-2
    					又比如2314,有2个逆序对,先判断2,ans=1-0+1=2,即2-1,3-1(不管第二个数比第一个大还是比第一个小,总是mid-i+1)
    				*/
    			}
    		}
    		//左边有数右边没了
    		while (i <= mid)
    		{
    			b[k++] = a[i++];
    		}
    		//右边有数左边没了
    		while (j <= right)
    		{
    			b[k++] = a[j++];
    		}
    		for (int i = 1; i <= right; i++)
    		{
    			a[i] = b[i];
    		}
    	
    	}
    }
    
    int main() {
    	cin >> n;
    	for (int i = 1; i <= n; i++)
    	{
    		cin >> a[i];
    	}
    	merge_sort(1, n);
    	printf("%lld", ans);
    	return 0;
    }
    

二分:

  • 算法:当数据量很大适宜采用该方法。采用二分法查找时,数据需是排好序的

    基本思想:假设数据是按升序排序的,对于给定值key,从序列的中间位置k开始比较,

    如果当前位置arr[k]值等于key,则查找成功;

    若key小于当前位置值arr[k],则在数列的前半段中查找,arr[low,mid-1];

    若key大于当前位置值arr[k],则在数列的后半段中继续查找arr[mid+1,high],

    直到找到为止,时间复杂度:O(log(n))。

posted @ 2023-01-14 09:57  、怪咖  阅读(36)  评论(0)    收藏  举报