1. 程式人生 > >二分模板大全

二分模板大全

#include<iostream>
#include<cstdio>
using namespace std;

const int MAXN = 100005;
int mi[MAXN][50];//Çø¼ä×î´óÖµ£¬Çø¼ä×îСֵ¡£
int lg[MAXN];
int num[MAXN];


//精確查詢---用遞迴實現二分查詢,精確查詢目標元素的位置,假定陣列遞增排列,且不存在重複元素
int bsearch1(int low,int high,int target){
    if(low > high) return -1;

    int mid = low + (high - low)/2;
    if(num[mid] > target){
        return bsearch1(low,mid-1,target);
    }
    if(num[mid] < target){
        return bsearch1(mid+1,high,target);
    }
    return mid;
}



//精確查詢---用迭代的方式實現二分查詢,精確查詢目標元素的位置,假定陣列遞增排列,且不存在重複元素
int bsearch2(int low,int high,int target){
    while(low <= high){
        int mid = low + (high - low)/2;
        if(num[mid] > target){
            high = mid -1;
        }
        else if(num[mid] < target){
            low = mid + 1;
        }
        else{
            return mid;
        }
    }
    return -1;
}



//界限查詢----用二分查詢尋找上屆,正好大於目標數的那個數(嚴格界限,不包含自身)
int bsearchupperbound(int low,int high,int target){
    if(low > high || target >= num[high]){
        return -1;
    }

    while(low < high){
        int mid = low + (high - low)/2;
        if(num[mid] > target){
            high = mid;
        }
        else{
            low = mid + 1;
        }
    }
    return high;
}


//界限查詢---用二分查詢尋找上屆,正好大於等於目標數的那個數(鬆散界限,可以包含自身)
int bsearch5(int low,int high,int target){
    if(low > high || target > num[high]){
        return -1;
    }
    while(low < high){
        int mid = low + (high -low)/2;
        if(num[mid] >= target){
            high = mid;
        }
        else{
            low = mid + 1;
        }
    }
    return high;
}



//界限查詢---用二分查詢尋找下屆,正好小於目標數的那個數(嚴格界限,不包含自身)
int bsearchlowerbound(int low,int high,int target){
    if(low > high || target <= num[low]){
        return -1;
    }

    while(low < high){
        int mid = (low + high + 1) / 2;     //這裡用向上取整,否則陷入死迴圈 因為low無法往上爬超過high

        if(num[mid] < target){
            low = mid;
        }
        else{
            high = mid -1;
        }
    }
    return low;
}


//界限查詢---用二分法尋找下屆,正好小於等於目標的那個數  (鬆散界限,可以包含自身)
int bsearch6(int low,int high,int target){
    if(low > high || target < num[low]){
        return -1;
    }
    while(low < high){
        int mid = (low + high + 1)/2;
        if(num[mid] <= target){
            low = mid;
        }
        else{
            high = mid - 1;
        }
    }
    return low;
}


//用二分查詢找尋區域,找到目標元素出現的下標範圍,允許重複元素(先找到嚴格上屆和嚴格下屆)
int results[] = {-1,-1};
void searchRange(int low, int high,int target,int len){
    if(low > high){
        return ;
    }
    int lower = bsearchlowerbound(0, len, target);
    lower = lower + 1;
    if(num[lower] == target){
        results[0] = lower;
    }
    else{
        return ;
    }

    int upper = bsearchupperbound(0, len - 1, target);
    upper = upper < 0 ? (len - 1) : (upper -1);

    results[1] = upper;

    return ;

}

//二分查詢ST表
void ST_prework(int n){
	for(int i=1 ; i<=n ; ++i)mi[i][0] = num[i];//ϱê´Ó1¿ªÊ¼
	//int t = log2(n) + 1;
	for(int i=2;i<=n;i++)lg[i] = lg[i/2] + 1;
	int t = lg[n] + 1;
	for(int i=1 ; i<t ; ++i){
		for(int j=1 ; j<=n-(1<<i)+1 ; ++j){
			mi[j][i] = min(mi[j][i-1],mi[j+(1<<(i-1))][i-1]);
		}
	}
}

int ST_query(int l,int r){//[l,r]±ÕÇø¼ä
	int k = lg[(r-l+1)];
	return min(mi[l][k],mi[r-(1<<k)+1][k]); //·µ»ØÇø¼ä×îСֵ
}

int bsearch7(int l,int r){
    int re = num[l++];
    int ll,rr,tmp,mid,flag;
    while(l <= r && re){
        flag = 0;
        ll = l,rr = r;
        mid = l;
        while(ll<=rr){
            mid = (ll + rr)/2;
            if(ST_query(ll,mid) <= re){
                rr = mid-1;tmp = mid;flag = 1;
            }else if(ST_query(mid,rr) <= re){
                ll = mid+1;tmp = mid;flag = 1;
            }else{
                break;
            }
        }
        if(flag){
            re = re % num[tmp];
            l = tmp+1;
        }else break;
    }
    return re;
}
int main(){

	return 0;
}