• 2020.10.6 清北学堂 J2综合强化营 D6 分治笔记


    分治

    (1).定义

    “分而治之”,即把大问题拆成一个个的小问题,然后分别解决这些小问题,最终求得答案。

    (2).应用

    ( ext{Example})
    把一个长度 (N) 的数组从小到大排序

    ( ext{Solution})

    ( ext{Quick Sort} o) 分成两个小数组,保证左子数组例的数均小于右子数组,不断重复上述过程,完成排序

    ( ext{Merge Sort} o) 分成两个较小的数组,对左子数组进行排序,对右子数组进行排序,最终合并成一个较大的数组,不断重复上述过程,完成排序

    inline void quick_sort(int l,int r){
    	int mid=a[(l+r)>>1];
    	int i=l,j=r;
    	do{
    		while(a[i]<mid) i++;
    		while(a[j]>mid) j--;
    		if(i<=j){
    			swap(a[i],a[j]);
    			i++;j--;	
    		}
    	}while(i<=j);
    
    	if(l<j) quick_sort(l,j);
    	if(i<r) quick_sort(i,r);
    }
    
    inline void merge_sort(int l,int r){
    	int mid=(l+r)>>1;
    	if(l==r) return;
    	merge_sort(l,mid);
    	merge_sort(mid+1,r);
    
    	int i=l,j=m+1,k=1;
    	while(i<=mid && j<=r){
    		if(a[i]<=a[j]) tmp[k++]=a[i++];
    		else tmp[k++]=a[j++];	
    	}
    	while(i<=mid) tmp[k++]=a[i++];
    	while(j<=r) tmp[k++]=a[j++];
    }
    

    ( ext{Example 2})

    一共有 (n) 片芯片,芯片有好有坏。我们不知道哪个是好芯片,哪个是坏芯片,但保证好芯片比坏芯片多
    我们可以用两片芯片互相测试对方是否是好芯片。
    已知好芯片一定能返回正确的结果,而坏芯片给出的结果是完全随机的。
    我们现在希望能找到一个好芯片

    ( ext{Solution 2})

    分成两组,每组两个比较.
    [好坏]或者[坏坏] ( o) 把两块芯片都去掉;
    如果结果是[好好] ( o) 任选其中一块去掉.

    剩下 (1) 个或 (2)( o) 是好芯片

    奇数个 ( o) 任取一个和其它所有芯片比较,
    如果有一半将此芯片判为好芯片 ( o) 好芯片
    否则 ( o) 坏芯片 ( o) 去掉

    ( ext{Problem 1}) 求逆序对 ( o ext{Merge Sort})

    (2).二分算法

    核心 : 把问题缩小为一个原规模 (dfrac{1}{2}) 的子问题

    常用 : 最小值最大 (or) 最大值最小 (or) 满足某条件的最值

    ( ext{(1)}) 二分查找

    模板固定,不要混用。——来自 ( ext{lyd}) 老师的忠告

    ( ext{Problem} 1)
    原问题:一个长度为 (N) 的有序数组 (A) ,查询 (x) 是否在这 (N) 个数中
    思路:
    (m = (l+r) >>1)
    按情况分类讨论:

    • (A[m] == x),找到 (x) ,返回
    • (A[m] > x),故 (A[m]sim A[r]) 中所有的数都大于 (x) ,二分查找 ((l, m))
    • (A[m] < x),故 (A[l]sim A[m]) 中所有数都小于 (x) ,二分查找 ((m + 1, r))
    inline bool Binary_Search(int x){	// [l,r)
    	int l=0,r=r-1,m;
    	while(l<=r){
    		if(A[m]==x) return true;	
    		else if(A[m]<x) r=m-1;
    		else l=m+1;
    	}
    	return false;
    }
    

    ( ext{Problem 2})
    给出 (N) 个月的开销,要求把 (N) 个月的开销按顺序划分成 (M) 个时间段,计算每一段的开销总和,求 (M) 个开销总和中最大值的最小值

    ( ext{Solution 2})
    求值问题 ( o) 判定问题
    求值:求一个划分方式,(划分区间和的最小值)最小
    判定 ((x)):是否存在一个判定方式,它划分出的每一段区间的和的最大值 (≤x)
    判定问题 ((x)):是否存在一个判定方式,它划分出的每一个区间的和都 (≤x)

    inline bool check(int x){
    	int cnt=0,len=0;
    	for(int i=1;i<=N;i++){
    		if(a[i]>x) return false;
    		if(len+a[i]>x){
    			len=a[i];
    			cnt++;
    		}	
    		else{
    			len+=a[i];	
    		}
    	}
    	return cnt<=M;
    }
    
  • 相关阅读:
    如何修改ls命令列出来的目录颜色
    如何替换vi的配色方案
    grep如何结尾匹配
    机器学习模型如何转换成零依赖代码
    在ubuntu bionic下对基于qemu的arm64进行linux内核5.0.1版本的编译和运行
    分析linux内核中的slub内存管理算法
    windows下如何解决chrome浏览器左下角总提示'Downloading proxy script'的问题
    发现vi出现此错误~/.vim/bundle/YouCompleteMe/third_party/ycmd/ycm_core.so: undefined symbol: clang_getCompletionFixIt
    打开vi后提示The ycmd server SHUT DOWN (restart with :YcmRestartServer)该如何处理
    ubuntu下如何修改时区和时间
  • 原文地址:https://www.cnblogs.com/-pwl/p/13774115.html
Copyright © 2020-2023  润新知