最近在用二分解決一些的問題的時候,
發現有一類問題-求出乙個未知的序列的第k個數,這類問題對於二分邊界的處理上存在不同的理解.
於是本文就這類問題進行**
給出n個數的陣列a,用這n個數每兩個作差,將差值的絕對值作為乙個新的陣列b.這個陣列有c(n,2) = n*(n-1)/2個元素.
找出b陣列中的中位數.
同時n的範圍為10^6,顯然n^2的演算法是超時和超記憶體的,考慮用二分來優化.
設 m = c(n,2) = n * (n-1) / 2.
中位數定義:對於這m個數的陣列b,如果m為偶數中位數為第m/2個.如果m為奇數中位數為第m/2+1個.
上圖分別給出了當m為偶數和奇數的情況的中位數的情況.
我們這麼做的原因就是為了分析大於,小於,等於中位數的個數有多少個
下面給出第一種解法:
通過二分列舉 mid ,mid 是我們要的中位數,對於每乙個mid中位數,用lower_bound計算大於等於mid有多少個.
那麼怎麼計算b陣列中大於等於mid的多少呢,因為b陣列我們並不知道.
那麼我們可以通過對a陣列的二分查詢,以達到計算在b陣列中大於mid的個數.
因為是mid是其中兩個數的差,值那麼對於a[i] 來說,在b中滿足大於mid的個數有 n + a - lower_bound(a+i,a+n,a[i] + mid);
讀者可以自行理解下:
bool check(int mid)
這個時候我們計算出來了大於等於mid的個數為cnt,我們看下上圖,大於等於中位數的有m/2+1個,無論是奇數還是偶數於是當cnt < (m/2+1) 即 cnt <= m/2 時
如圖:說明當前的mid一定不是中位數,則將right = mid - 1,需要向左區間去尋找(右開左閉區間) 即將當前mid直接捨去
當cnt >= (m/2+1) 即 cnt > m/2 時
有兩種情況. cnt == (m / 2 +1) 和 cnt >= (m / 2 + 1)
這個時候mid有可能就是中位數,而我們**中直接將 left = mid + 1了 於是left 一定不是最優解,而right = left - 1 ,於是right一定是最優解,參照部落格二分演算法分析
給出**
有注意到這裡的m 有別於上個解法的 m/2,/**
給你n個數,然後求它們兩兩相減的絕對值,然後找出這些絕對值的中位數。 解題思路
*/#include#include#include#includeusing namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int arr[maxn],n;
ll m;
bool check(int mid)
int main()
因為我們在計算小於等於mid的元素個數時,需要考慮奇偶了!
當m為偶數時,小於中位數的個數有 m/2-1 個.
當m為奇數時,小於中位數的個數有m/2個
於是對於m我們進行了這樣的操作:
偶數 m = m / 2,奇數 m = m / 2 + 1;m = n * (n-1) / 2;
if(m & 1) m++;
m >>= 1;
對於cnt < m的情況
此時的mid一定不是最優解,則需要增大mid 於是 left = mid + 1 ,left 右移
當cnt>=m時
此時的mid可能為中位數,答案,也可能不是,我們二分中直接讓right = mid - 1
則right 一定不是最優解,而left 在二分結束時,left = right + 1,則left一定是最優解,參考同上
/**
給你n個數,然後求它們兩兩相減的絕對值,然後找出這些絕對值的中位數。 解題思路
*/#include#include#include#includeusing namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int arr[maxn],n;
ll m;
bool check(int mid)
printf("%d\n",left);}}
第k大數 二分法
時間限制 10 sec 記憶體限制 128 mb 有兩個序列a,b,它們的長度分別為n和m,那麼將兩個序列中的元素對應相乘後得到的n m個元素從大到小排列後的第k個元素是什麼?輸入的第一行為乙個正整數t t 10 代表一共有t組測試資料。每組測試資料的第一行有三個正整數n,m和k 1 n,m 100...
HNUCM 1315 第K大數 二分
題目描述 有兩個序列a,b,它們的長度分別為n和m,那麼將兩個序列中的元素對應相乘後得到的n m個元素從大到小排列後的第k個元素是什麼?輸入 輸入的第一行為乙個正整數t t 10 代表一共有t組測試資料。每組測試資料的第一行有三個正整數n,m和k 1 n,m 100000,1 k n m 分別代表a...
poj3685(二分查詢第k小)
translation 給出乙個矩陣,其中每項的值為 i i c i j j c j i j i,j分別為所在的行和列 求其第m小的數字 solution 二分查詢k小數字 觀察發現矩陣的規律是從上倒下遞增,從左到右遞減。可以根據這個規律來二分查詢有幾個小於當前給出的值。詳見 note date 2...