何謂莫隊
一種將詢問以一種特定的順序處理來支援離線處理區間詢問的演算法。
實現方式
舉個栗子:
bzoj1878 hh的項鍊
給乙個長為n
nn的序列,取出其中的一段區間[l,
r]
[l,r]
[l,r
],問其中有多少種不同的數字。 n≤5
×104
n\le5\times10^4
n≤5×10
4如果有一段區間[l,
r]
[l,r]
[l,r
]中的數為
\,我們思考將其變為[l,
r−1]
[l,r-1]
[l,r−1
]與[l,r
+1
][l,r+1]
[l,r+1
]答案的變化。
我們記錄一下每個數的出現次數,如果區間變為[l,
r−1]
[l,r-1]
[l,r−1
],那麼4
44的出現次數就由1
11變為0
00,所以4
44就不在當前的區間中,種類數−1-1
−1。再思考區間變為[l,
r+1]
[l,r+1]
[l,r+1
]的情況,如果加入的是3
33,那麼3
33的出現次數由1
11變為2
22,對答案無任何影響,但如果加入的是5
55,那麼5
55的出現次數由0
00變為1
11,答案+1+1
+1。區間變為[l−
1,r]
[l-1,r]
[l−1,r
]和[l+1
,r
][l+1,r]
[l+1,r
]的情況同理。
所以對於兩個詢問[2,
3]
[2,3]
[2,3]與[1,
5]
[1,5]
[1,5
],我們只需移動兩次右區間,移動一次左區間,所以我們就得到了乙個上界為o(n
2)
o(n^2)
o(n2
)的演算法,但對於隨機資料遠遠跑不滿。
但這樣還遠遠不夠,在極端資料下,演算法還是o(n
2)
o(n^2)
o(n2
)的時間複雜度。所以我們可以想到將詢問以另外的一種順序進行處理,來使得時間複雜度更小。
一種想法是將詢問的左端點進行分塊,排序時第一關鍵字為左端點的塊的編號,第二關鍵字為右端點的大小,這樣做會使時間複雜度達到o(n
n)
o(n\sqrt n)
o(nn)
。時間複雜度證明
下面的證明均假設n,m
n,mn,
m同階。
左端點所在的塊是單調遞增的,所以每次詢問左端點最多在乙個塊內移動,最壞從最右端移到最左端,所以最壞移動次數為n
nn\sqrt n
nn。
當左端點在同一塊內時,右端點單調遞增,最壞總移動步數為o(n
n)
o(n\sqrt n)
o(nn)
,左端點移動到另乙個塊時,右端點最壞從n
nn移動到1
11,時間複雜度o(n
n)
o(n\sqrt n)
o(nn)
。綜上,總時間複雜度為o(n
n)
o(n\sqrt n)
o(nn)
。**(hh的項鍊)
#include
using
namespace std;
struct nodeb[
1000005];
int a[
1000005
],cnt[
1000005
],now=
0,len,l=
1,r=0;
intread()
while
(isdigit
(ch)
)return x*f;
}bool
cmp1
(node p,node q)
bool
cmp2
(node p,node q)
void
del(
int x)
void
ins(
int x)
void
query
(int x)
intmain()
m=read()
;for
(int i=
1;i<=m;i++
)sort
(b+1
,b+m+
1,cmp1)
;for
(int i=
1;i<=m;i++
)sort
(b+1
,b+m+
1,cmp2)
;for
(int i=
1;i<=m;i++
)}
注意
當使用莫隊演算法時要注意先擴再縮,例如從[1,
5]
[1,5]
[1,5]到[6,
10]
[6,10]
[6,10]
時,如果先移動左端點,那麼就會區間就會變為[6,
5]
[6,5]
[6,5
],會導致不必要的rere
re。
//正確寫法
while
(rins(
++r)
;while
(l>l)
ins(
--l)
;while
(r>r)
del(r--);
while
(ldel(l++
);
例題
小z的襪子
小b的詢問
mato的檔案管理
gty的二逼妹子序列
[hnoi2016]序列 題解
莫隊講解 普通莫隊
結束了分塊,我們來講下莫隊。據我所知,莫隊能解決一切區間問題,除了翻轉。因為它就是個暴力 其實這兩者的關係並不大。僅僅是時間複雜度一樣而已。我們把原序列分成 n塊 好像就是這裡相同 這裡說的序列是查詢序列l r,並不是讀入的a i 之後我們把序列排序 按照第一關鍵字為左端點所在的塊的大小,如果相同就...
莫隊演算法講解
問題 有n個數組成乙個序列,有m個形如詢問l,r的詢問,每次詢問需要回答區間內至少出現2次的數有哪些。樸素的解法需要讀取o nm 次數。如果資料範圍小,可以用陣列,時間複雜度為o nm 如果使用stl的map來儲存出現的次數,則需要o nmlogn 的複雜度。有沒有更快的方法呢?得出。如果能安排適當...
莫隊演算法 講解 更新
莫隊演算法是用來處理一類無修改的離線區間詢問問題。摘自前國家隊隊長莫濤在知乎上對莫隊演算法的解釋。莫隊演算法是前國家隊隊長莫濤在比賽的時候想出來的演算法。傳說中能解決一切區間處理問題的莫隊演算法。準確的說,是離線區間問題。但是現在的莫隊被拓展到了有樹上莫隊,帶修莫隊 即帶修改的莫隊 這裡只先講普通的...