學習筆記 省選演算法 莫隊

2021-08-13 02:39:53 字數 3033 閱讀 1631

神犇mx:你是**來的弱菜?你是不是上次noip爆0的那個大弱雞xyz32768?

xyz32768:我就是那個noip2017寫炸兩題的蒟蒻,的確是大弱雞。

神犇mx:我還聽說你連莫隊都不會……你恐怕明年noip連400都沒有了。

xyz32768:莫……莫隊?

神犇mx:就是這樣:乙個

n n

個數的序列,每次詢問區間……

xyz32768:反正我也不懂,算了,我已經做好了noip2018爆0的準備了。

乙個問題:乙個

n' role="presentation" style="position: relative;">n

n個數的序列,每次詢問區間[l

,r] [l,

r]

內出現了多少個不同的數。

乙個想法是線段樹,但是也很容易看出,這裡線段樹上維護的內容沒有合併性質,因此線段樹不可做。而對於區間的內容沒有合併性質的問題,可以用下面介紹的莫隊演算法解決。

1、不包含修改操作。

2、題目允許離線,也就是允許在所有詢問全部讀入完之後回答所有詢問。

3、不同區間的結果可以互相計算得出。怎麼理解這個條件呢?

就上面的問題而言,如果上一次已經回答了[l

,r] [l,

r]

區間的答案,並且已經存下了[l

,r] [l,

r]

區間裡的所有數值的出現次數,那麼如果下面要詢問[l

,r+1

] [l,

r+1]

的結果,就只要把右指標

r r

向右移乙個單位,並將序列的第r+

1' role="presentation" style="position: relative;">r+1

r+1個數的出現次數++

+

+,同時維護當前的答案,也就是說,如果第r+

1 r+1

個數在[l

,r] [l,

r]

區間內沒有出現,則當前答案++

+

+。同樣,對於[l

,r−1

],[l

−1,r

][l+

1,r]

[ l,

r−1]

,[l−

1,r]

[l+1

,r

]以及其他任何的區間都可以在上乙個詢問的基礎上,通過

l l

和r' role="presentation" style="position: relative;">r

r移動指標來求得下乙個詢問的答案。如果滿足這樣的條件,就是說不同區間的結果可以互相計算得出。

可以看出,一次移動指標是o(

1)o (1

)的。於是想到可以回答第

1 1

個詢問之後,不斷地移動指標,乙個乙個移動到後面將要回答的所有區間。

莫隊演算法的主要思想就是這樣。同時,莫隊演算法利用了可以離線的條件,將詢問按照合理的順序進行求解,實現了o(

nn)' role="presentation" style="position: relative;">o(n

n−−√

)o(n

n)的複雜度。

首先,將序列分塊,即分成n−

−√n

塊,每個塊的大小為n−

−√n

。 然後,就將詢問按照左端點所在的塊為第一關鍵字,右端點的位置為第二關鍵字進行從小到大排序,這樣,就能像上面那樣不斷移動指標,可以達到o(

nn−−

√)o (n

n)

的複雜度。

不妨把左端點在同乙個塊內的詢問分成一組。

先考慮右端點的移動次數。由於在同一組詢問內的右端點是遞增的,所以在同一組內,右端點移動了o(

n)o (n

)次。同時在跨越兩個組時,右端點的移動次數也是o(

n)o (n

),即右端點一共移動了o(

nn−−

√)o (n

n)

次。 再考慮左端點的移動次數。可以看出,在同一組詢問內,左端點一次移動的次數為o(

n−−√

) o(n

)次。

再加上在跨越兩個組時,左端點的移動次數也是o(

n−−√

) o(n

),因此左端點一共移動了o(

nn−−

√)o (n

n)

次。複雜度得證。

hljs cpp">#include 

#include

#include

#include

using

namespace

std;

const

int n = 5e4 + 5, m = 1e6 + 5, l = 2e5 + 5;

int n, a[n], ans[n], cnt[m];

struct cyx

} ask[l];

int main()

sort(ask + 1, ask + m + 1);

int tot = 0, sl = 0, sr = 0;

for (i = 1; i <= m; i++)

for (i = 1; i <= m; i++) printf("%d\n", ans[i]);

return

0;}

1、[bzoj1878][sdoi2009]hh的項鍊:

2、[bzoj2038][2009國家集訓隊]小z的襪子:

3、[bzoj3236][ahoi2013]作業:

4、[bzoj4540][hnoi2016]序列:

5、[bzoj4542][hnoi2016]大數:

莫隊演算法學習筆記(一) 普通莫隊

前言 在學習莫隊演算法之前,我一直以為這是乙個很高深的演算法。實際上,它就是乙個很高深的演算法 這個演算法玄學地將分塊與暴力兩大演算法實現了二合一,從而打造出了乙個時間複雜度為o n n o n sqrt n o nn 的求解多個區間詢問的離線演算法。具體介紹 首先,我們以詢問中l ll所在的區間為...

莫隊演算法學習筆記(三) 樹上莫隊

樹上莫隊的核心思想,就是將一棵樹轉化成乙個序列,然後用普通莫隊來搞。以一棵樹為例 要想對這棵樹進行樹上莫隊,我們第一步就是用乙個 s 陣列把它的括號序存下來 id 12 3456 78910 1112 1314 1516 s 12 4788 7455 2366 31 同時,我們用 i 陣列儲存每個數...

莫隊演算法學習筆記

莫隊演算法 有時候我們經常會碰到這樣一類問題 給定n和n個數etc,然後給出m組區間詢問 l,r 要求對所有詢問區間給出答案。然後發現這類題通常有乙個很好的性質就是,如果你知道了 l,r 的答案,就可以o 1 或者o lgn 再大就有點玄了 的知道 使得根據第i個區間 li,ri 的答案拓展到第i ...