[英]How to calculate the number of loop this nested for loop will run given that the inner loop index always greater than outer loop?
[英]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.y
和p2.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.