大前提
題目敘述中若未指定n, m, q三個變數, 則預設n表示序列長度,m表示總操作次數(包括修改和查詢),q表示詢問總次數.
給定乙個長度為n的整數序列, 求序列中第k小的數字.
時間複雜度: 多次詢問o(nlogn) / 單次詢問o(n) 空間複雜度: o(n)
可以採用諸多複雜度為o(nlogn)的排序方法, 如快速排序, 歸併排序等.
如果只有一組詢問, 還可以o(n)實現(可以使用庫函式nth_element)
給定乙個長度為n的整數序列(下標從1~n編號), 有m次修改和查詢操作.
時間複雜度: o((n + m)logn) 空間複雜度: o(n)
當然也有很多別的神奇的方法, 也都可以解決本問題qaq
ps: 這個題是想給出例題和**的, 但是沒有找到合適的題目, 如果大家有合適的題目麻煩分享一下呀, 我會把這個坑填了的
給定乙個長度為n的整數序列(下標從1~n編號), 有m次詢問操作
方法一: 靜態主席樹
時間複雜度: o((n + m)logn) 空間複雜度: o(nlogn)
對於每乙個位置都去建立一棵權值線段樹, 維護[1, i]區間, 那麼如果要查詢[l, r], 可以用[1, r] - [1, l-1]. 考慮到每個節點都是一棵權值線段樹, 那麼空間複雜度為o(n2), 很明顯mle, 於是需要採用靜態主席樹的建立方法進行優化.
這樣每乙個版本相較於上乙個版本而言,只會修改logn個節點, 於是空間複雜度優化到o(nlogn).
對於時間複雜度而言, 每次查詢的是兩棵權值線段樹, 因此同於動態整體kth.
靜態主席樹求第k小數模板
方法二: 整體二分
時間複雜度: o((n + m)lognlog值域) 空間複雜度: o(n + m)
二分值域, 每次求出以mid為分界點的左半區間的貢獻(記為cou), 如果此時cou>=k, 則說明答案最終的答案應該<=mid, 應在左半區間尋找答案. 反之說明答案在右半區間, 應減去左半區間的貢獻後, 在右半區間尋找答案(類似於權值線段樹的查詢操作).
特別的, 其實也可以將整體二分的值域進行離散化, 這樣大概可以優化一倍的常數複雜度
整體二分求靜態第k小數模板
例題 k-th number
ac**: 這裡
給定乙個長度為n的整數序列(下標從1~n編號), 有m次修改和查詢操作.
方法一: 樹狀陣列 + 動態主席樹 (+ 靜態主席樹)
時間複雜度: o((n + m)lognlogn) 空間複雜度: o((n + m)lognlogn) / o(nlogn + mlognlogn)
類似於靜態區間求第k小數, 只不過維護值採用樹狀陣列進行記錄了, 這樣利於修改. 在修改和查詢的時候, 都要用樹狀陣列去查詢logn棵主席樹. 那在進行修改操作時, 我們發現不再能使用之前靜態建立主席樹的方式了, 因為會導致某個點被重複建立, 以至於該節點原有的值被覆蓋. 因此需要採用動態建立主席樹的方式.
特別的, 最開始的序列可以採用靜態主席樹去建立, 樹狀陣列維護新的主席樹, 記錄對於原主席樹的修改情況.
動態主席樹求動態區間第k小數模板
方法二: 整體二分
o((n + m)lognlog值域) 空間複雜度: o((n + m))
這個其實和方法三的整體二分操作是一模一樣的, 修改操作拆分成: 刪去原先該當前位置的值, 在當前位置新增新值即可.
整體二分求動態區間第k小數模板
例題 dynamic rankings
ac**: 這裡
感謝大佬!
qaq, 這個部落格應該還會再完善的, 看心情吧.
求第k小數
求第k小數,無非就是考查排序,請參考我最新的博文吧求第k小數 直接使用priority queue,在網上看到許多使用快排來求第k小數都是認為第k小就是排好序陣列中第k個元素,但是如果陣列中有相同的元素呢,例如 1,2,2,2,3,5 認為第三小是3還是2呢?我刷題時遇到的是認為是3。沒有想到什麼好...
NOJ 1574 求第k小數
時限 1000ms 記憶體限制 10000k 總時限 3000ms 描述求第k小數 輸入先輸入乙個小於10000的正整數n,再輸入n個整數,最後輸入乙個小於等於n的正整數k,輸出輸出其中第k小的數。輸入樣例 52 98 34512 8492 1000 2輸出樣例 提示 思路 可以採用二分法思想,先讓...
線性選擇 求n個數中第k小數
include include include template int partition type a,int p,int r a p a j a j x return j template int randamizedpartition type a,int p,int r template ...