簡體   English   中英

查找給定范圍內的最小元素大於給定數字

[英]Finding the minimum element in a given range greater than a given number

我們在2D平面上給出N(N <= 10 6 )個點並且給出整數D(N <= 10 6 ),我們想要找到兩個點p1,p2(p1右邊的p2)使得它們之間的差異p1.yp2.y至少是D和p2.x - p1.x被最小化。

x軸和y軸的范圍為0..10 6

這是USACO過去的比賽中的一個問題

這是我嘗試解決它:
MAXY = N個點中的最大y軸。
假設我們知道p1,那么我們很容易找到p2; 通過取y軸在p1.y+D到MAXY范圍內或在0到p1.yD范圍內的所有點,取x軸最小的點大於px 這將是p2的最佳選擇。

但是由於我們不知道p1,我們將不得不嘗試p1的所有點,因此找到p2的最佳選擇應該有效地完成。

我使用了一個分段樹。 樹中的每個節點都將按照x軸的排序順序存儲相應范圍內的所有點。 在查詢時,如果一個節點落在查詢范圍內,那么我們在數組上二進制搜索p1.x並返回大於它的最小元素。

對於p1的每個選擇,我們使用范圍0,p1.yD和p1.y + D,MAXY兩次查詢樹,並且在返回的兩個點中取最佳值。

樹的構建可以在O(NlogN)時間內完成。 每個查詢都需要O(logN * logN)時間,我們進行N次查詢,因此所花費的總時間為(Nlogn * logn),可能不會在2秒的時間限制內運行。 (10 6 * 20 * 20)。 所采用的存儲器也將是O(NlogN),其大約為80mb(100000 * 20 * 4kb),這太大,因為限制是64mb。

我們如何更快地進行查詢並使用更小的空間?

它可以更輕松地完成。

假設您有兩個數組副本:一個按Y軸排序,另一個按X軸排序。 現在,您將遍歷Y排序的數組,並且對於每個點(讓它命名為cur),您應該在X排序的數組中二進制搜索適當的點(具有最小的p2.x - p1.x)。 如果二進制搜索會找到相同的點或Y坐標小於cur + D的點,你應該從X排序的數組中刪除該點(我們再也不需要在X排序的數組中的那個點,因為我們只增加Y坐標)並再次運行二進制搜索。 答案將是二進制搜索結果中最小的一個。

由於我們需要快速計時,我們應該快速從陣列中擦除點。 它可以通過使用二叉樹來完成 - 它可以在O(logN)時間內擦除任何節點,並且可以在O(logN)時間內進行二進制搜索。 當您從樹中刪除每個節點一次並且需要O(logN + logN)時間時 - 總時間將為O(N * logN)。 預處理時間也是O(N * logN)。 所采用的存儲器也將是O(N)。

順便說一句,你的解決方案也是合適的,因為實際N是10 ^ 5而不是10 ^ 6。 這使您的解決方案可以將時間保持在2秒以下,並使用少於20MB的內存。

怎么樣做排序和掃描。

按x排序,因為您希望找到x的最小差異。 它需要O(N logN)時間和到位。

從x的頭部維護兩個索引i和j。

首先越快,找到| P [i] .y - P [j] .y |的位置 > D.

並且X = | P [i] .x - P [j] .x | 是您的第一個選擇。

然后通過向前移動索引來更新X. 嘗試P [i + 1],從P [i + 2]掃描為P [j]並增加直到| P [i] .x - P [j] .x | > = X.如果有可用的新X,請將其設置為X.

這可能首先會做很多比較。 但是既然你更新了你的X,不知何故會讓你的比較范圍縮小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM