二分

Posted $mathcal{Yubai}$

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分相关的知识,希望对你有一定的参考价值。

\\(Orz\\)集训队论文

选数问题:选出集合中第\\(i\\)小的数
如果排序的话,复杂度是\\(nlogn\\)的,是因为他对一些没有用的东西也进行了操作,所以我们尽量少进行没有用的操作,有一种\\(O(n)\\)的算法
内容见\\(link\\)
复杂度证明:每次都选择一个数后,我们只用向另一半递归,所以计算次数为
\\(n+n/2+n/4+n/8+....+1\\),易知这是一个收敛的等比数列,和不会大于\\(2n\\),故复杂度是\\(O(n)\\)
所以说复杂度不能想当然\\(logn\\),还是要自己推,一般如果\\(check\\)函数的计算范围随着端点的缩小而缩小,复杂度就是\\(O(n)\\)的,如果\\(check\\)复杂度一直是\\(O(n)\\),那么就是\\(nlogn\\)
code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <ctime>
#define int long
#define R register int
#define printf tz1=printf

using namespace std ;
typedef long long L ;
typedef long double D ;
typedef unsigned G ;
const int N = 5e6 + 10 ;

inline int read(){
	int w = 0 ; bool fg = 0 ; char ch = getchar() ;
	while( ch < \'0\' || ch > \'9\' ) fg |= ( ch == \'-\' ) , ch = getchar() ;
	while( ch >= \'0\' && ch <= \'9\' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - \'0\' ) , ch = getchar() ;
	return fg ? -w : w ;
}

int tz1 , n , m , a [N] ;

void sc(){
	n = read() , m = read() ; m ++ ; 
	for( R i = 1 ; i <= n ; i ++ ) a [i] = read() ; 
}

inline void debug( int l , int r ){
	for( R i = l ; i <= r ; i ++ ) printf( "%ld " , a [i] ) ;  puts( "" ) ;
}

inline void choose( int l , int r , int x ){
//	printf( "L%ld R%ld X%ld\\n" , l , r , x ) ;
	int mid = ( l + r ) >> 1 ; //懒得写随机,所以取的中点
	swap( a [mid] , a [l] ) ;
	int cnt = l ; //debug( l , r ) ;
	for( R i = l + 1 ; i <= r ; i ++ )
		if( a [i] < a [l] ) swap( a [++ cnt] , a [i] ) ;
	swap( a [cnt] , a [l] ) ;
	if( cnt - l == x - 1 ) { printf( "%ld\\n" , a [cnt] ) ; return ; }
	if( cnt - l <  x ) choose( cnt + 1 , r , x - cnt + l - 1 ) ;  
	else choose( l , cnt , x ) ;
}	

void work(){
	choose( 1 , n , m ) ;
}

signed main(){
	sc() ;
	work() ;
	return 0 ;
}

以上是关于二分的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段——CSS选择器

谷歌浏览器调试jsp 引入代码片段,如何调试代码片段中的js

片段和活动之间的核心区别是啥?哪些代码可以写成片段?

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段6——CSS选择器

VSCode自定义代码片段——声明函数