HNOI 2009 夢幻布丁 鍊錶 啟發式合併

2022-08-22 05:12:08 字數 765 閱讀 6880

題意:給出乙個序列,每個元素有顏色。共m次操作,改變一種顏色或統計顏色的塊數

由於m,n都比較大,所以我們直接mn暴力是不行的,要考慮優化。

那麼mn慢在**呢?每次操作時,都要遍歷一遍整個序列,其中訪問到了很多沒用的元素。

那麼就從這裡入手,如果我們每次只遍歷要修改的元素,就能快很多。

所以我們用鍊錶,把每種顏色的串起來,組成多個鍊錶以供查詢。每次修改時只要沿著鍊錶走就行了,減少了無用遍歷。

每次修改(把a變成b)時,遍歷a鍊錶,記錄這種顏色貢獻了多少個塊,然後再遍歷一遍,進行修改,然後再遍歷一遍,記錄現在貢獻了多少個塊,然後相減,加入答案,最後合併兩個鍊錶。

因為訪問到的點不會改,所以塊也不會改,所以這種方法是正確的。

但是,這種方法仍是o(mn),能不能更快一些呢?

這裡就要用到啟發式合併,非常神奇。

方法很簡單,每次修改時只需要遍歷短的鍊錶。

舉例來說,對於修改(把a變成b),當a錶比b表短時,正常操作;

當a錶比b表長時,就交換a和b,然後以後一直把a當成b,把b當成a。(交換指標)

沒了。這樣做複雜度變成了mlogn 。為什麼?

考慮一次合併,最壞情況下兩個鍊錶一樣長,這樣合併完了後鍊錶長度翻倍。

因為乙個鍊錶最長是n,所以即使不斷翻倍,最多也是logn次。

如果兩個鍊錶不一樣長,那麼單次就更少了,所以平均下來上界logn,可以接受了。

啟發式合併,很有意思。

HNOI2009 夢幻布丁

題意 n個布丁擺成一行,進行m次操作.每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色.例如顏色分別為1,2,2,1的四個布丁一共有3段顏色.對每個顏色的位置維護鍊錶。合併兩個顏色,連線鍊錶,統計貢獻。統計貢獻的複雜度是與鍊錶長度有關的。如果遍歷長度短的鍊錶那麼複雜度自然更小...

HNOI2009 夢幻布丁

n個布丁擺成一行,進行m次操作.每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色.例如顏色分別為1,2,2,1的四個布丁一共有3段顏色.輸入格式 第一行給出n,m表示布丁的個數和好友的操作次數.第二行n個數a1,a2.an表示第i個布丁的顏色從第三行起有m行,對於每個操作,若...

HNOI2009 夢幻布丁

題目鏈結 把每一種數字想象成乙個佇列。如果暴力合併,時間複雜度必然很高,考慮啟發式合併 每次把數字少的佇列合併到數字多的佇列上去。每次合併,若數字少的佇列數字個數為 s 則合併之後產生新佇列的大小必定不小於 2 s 時間複雜度 o n log n 這樣合併產生了乙個問題 即原來要求將 a 全部變為 ...