二分 基於第K大數的思考 poj3579

2021-08-18 21:58:51 字數 3154 閱讀 5116

最近在用二分解決一些的問題的時候,

發現有一類問題-求出乙個未知的序列的第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一定是最優解,參照部落格二分演算法分析

給出**

/**

給你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()

有注意到這裡的m 有別於上個解法的 m/2,

因為我們在計算小於等於mid的元素個數時,需要考慮奇偶了!

當m為偶數時,小於中位數的個數有 m/2-1 個.

當m為奇數時,小於中位數的個數有m/2個

於是對於m我們進行了這樣的操作:

m = n * (n-1) / 2;

if(m & 1) m++;

m >>= 1;

偶數 m = m / 2,奇數 m = m / 2 + 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...