查詢第K大的值

2022-06-05 20:21:07 字數 1537 閱讀 7600

這種題一般是給定n個數,然後n個數之間通過某種計算得到了新的數列,求這新的數列的第k大的值

poj3579

題意:用$n$個數的序列$x[i]$,生成乙個新序列$b$。

新的序列定義為:對於任意的$ i$,$j$且 $i != j $有$b = abs(x[i] - x[j])$

問新序列的中位數是什麼,如果新序列的長度為偶數那麼我們定義中位數為排序後第len/2位置的那個數

解法:相當於問新序列中的第k大的數多少。

注意新數列不可能全都算出來。

二分答案,二分那個第k大的數的值。

$x[i]-x[j] \ge mid$

相當於$x[i] \ge mid+x[j]$

然後我們在排序過的原陣列中,對每個$a[i]$二分這個$mid$值,統計有多少個值小於它,統計累加所有的值,最後看是不是小於k

**如下:

1

intn;

2int

a[maxn];

3ll m;45

bool c(int

t) 10

return cnt <= m / 2;11

}1213void

solve() else24}

25 cout << lb <26return;27

}2829int

main()

37solve();38}

39return0;

40 }

poj3685

題意:有乙個$ n*n$ 的矩陣$ a$ ,$a[i][j]=i^2+100000i+j^2-100000j+ij$

求所有矩陣元素中第$ k$ 大的值

解法:求第$ k$ 大的值,二分答案

首先肯定是二分這個k值是多少,接下來就是驗證的問題。

由於$ n*n$ 的值很大,所以我們必須找到它的單調性,那麼有以下式子:

$a[i+1][j] = a[i][j] + (2*i + j + 1 + 100000)$(同一列遞推式)

$a[i][j+1] = a[i][j] + (2*j + i + 1 - 100000)$ (同一行遞推式)

可以發現:在列方向上,矩陣單調遞增,而在行方向上上,當$ (2*j + i + 1)> 100000 $ 時,遞增,反之遞減。

那麼我們在每個列方向上直接二分那個$ i$ 值的大小,判斷的一句就是$ a[i][j]$ 與假想$ k$ 值的大小關係。

**如下:

1

ll n, m;

23 ll cal(ll i, ll j) 45

bool

c(ll x) else18}

19 sum +=ans;20}

21return sum >=m;22}

2324

void

solve() else33}

34 cout << ub <35return;36

}3738int

main()

48return0;

49 }

演算法實踐系列 查詢第K大值

下面的演算法實現基於隨機化快排,有乙個前提是需要假設所有的元素都不相等,否則演算法不成立。下面是具體實現 1 隨機劃分演算法與快排一樣 快速排序的分隔,即 對於乙個指定的主元x,找到位置i,使得i的左邊元素都小於等於x,右邊都大於等於x.private int quicksortpartion in...

演算法實踐系列 查詢第K大值

下面的演算法實現基於隨機化快排,有乙個前提是需要假設所有的元素都不相等,否則演算法不成立。下面是具體實現 1 隨機劃分演算法與快排一樣 快速排序的分隔,即 對於乙個指定的主元x,找到位置i,使得i的左邊元素都小於等於x,右邊都大於等於x.private int quicksortpartion in...

作業 查詢第k大的元素

由於是要找 k 個最大的數,所以沒有必要對所有數進行完整的排序。每次只保留 k 個當前最大的數就可以,然後每次對新來的元素跟當前 k 個樹中最小的數比較,新元素大的話則插入到陣列中,否則跳過。迴圈結束後陣列中最小的數即是我們要找到第 k 大的數。時間複雜度 n k logk 注意 巢狀for迴圈裡面...