論優化定址時間的重要性
background
冥思苦想。。。 哇!這題我會做!——但時間有點緊!——沒事!打! 1 hour later,碼完了!拍!拍對了!交! “WOC,T70!這。。。”(拍案而起,怒目圓睜) (隔壁一大佬)“誒!我過了!賊快!” “你什麼方法?” “[email protected]#KaTeX parse error: Expected 'EOF', got '#' at position 22: …不是一樣嗎,題解呢?” “[email protected]#̲%&*” “我就是題解法啊!什麼垃圾資料連題解都卡!” “我卡常了的。” “怎麼卡?” “優化一下陣列定址時間!” “QAQ~~”
舉幾個例子
T1 queue
要求支援區間輪換和詢問區間v值出現的個數。 Time Limit:1s
很不NOIP的方法
輪換相當於點挪動位置 平衡樹先預處理出那些位置要預先開好,然後分每一個v離線處理,時間複雜度
很容易想到的方法
K個一塊,每一塊用連結串列維護,順便維護快內每個值出現的次數,輪換的話依然是刪除插入,並將中間每一個塊尾元素挪到後一塊開始。複雜度當K取時複雜度為 要不就塊狀連結串列。 雖然複雜度大,但是打得優秀能比部分的快!
result
TLE???然而別人過了? 考慮到輪換優化效果不大,那從詢問下手。 每個塊的桶!!桶怎麼開?由於一次詢問是詢問一個值,應該將值放在第一維,塊放在第二維。 結果快了至少300ms。 其實這也要因情況而定,如果修改特別多的話,還不如塊放在第一維好。
其實這點常數優化比較難控制,接下來舉個有代表性的
T2 center
點數n,邊數m,詢問數q,對於每個詢問有k組相關的值,每組形如,問與最短距離不超過的點集並集的大小。 Time Limit:1.5s -O2 -lm
啊?這要用bitset??
預處理出與點u最短距離不超過d的點集,複雜度 對於每個詢問直接取並即可複雜度 能過
result
哇!又TLE啦! 由於邊是雙向邊,所以預處理的遍歷過程至少2億次! 在O2的情況下仍然TLE了,why? 你存邊的方式是什麼?陣列模擬連結串列?邊集陣列? 大家可能認為前者的功能很強大?後者需要的空間 但是,值得一提的是,後者邊是連續的地址,而前面的是連結串列,要跳來跳去 看起來相差不大,但放大n倍呢? 更改為邊集陣列後不到600ms
後記
其實優化定址複雜度的地方有很多,當一個演算法的時間特別接近時限,但有夢想卡過去時,應當考慮定址時間,不然T成大眾分。