莫隊演算法 無修

2021-08-20 10:51:13 字數 3207 閱讀 5442

無修的莫隊演算法,是用來處理沒有修改操作的序列的詢問操作的離線演算法

莫隊演算法的本質是什麼?

大概就是分塊加上乙個大家可能都想到過的東西

也就是乙個區間1l-r,其左邊的區間2 (l - 1) - (r - 1)的和轉化到區間1的和只需要o(1)的時間複雜度

也就是sum

1=su

m2+a

[r]−

a[l−

1]

sum1 = sum2 + a[r] - a[l - 1]

sum1=s

um2+

a[r]

−a[l

−1]如果前面並沒有提到分塊,可能大家就會想到乙個o(n

2)

o(n^2)

o(n2

)的演算法

那麼這個演算法我就不提了。。

那如果有分塊的加入呢?

我們的思路是這樣的:

將乙個長度為n的序列分成sqr

t(n)

sqrt(n)

sqrt(n

)塊然後對詢問進行排序 如果兩個詢問的左端點在同一塊,則比較兩個詢問的右端點,小的在前

如果左端點不在同一塊,則比較兩個塊的前後順序,塊在前面的在前

這樣就可以優化上述處理詢問方法的時間複雜度,具體看下面的分析

根據之前提到的查詢方法,可以得出以下**:

int x = m[k]

.l, y = m[k]

.r;//m是詢問

while

(l > x)

ins(

-- l )

;while

(l < x)

del( l ++);

while

(r > y)

del( r --);

while

(r < y)

ins(

++ r )

;

這裡設sum

=sqr

t(n)

sum = sqrt(n)

sum=sq

rt(n

)每個塊長度為len

=n/s

um

len = n / sum

len=n/

sum列舉了k

kk次答案

對於l若兩個l在同一塊,則最壞情況為o(l

en

)o(len)

o(len)

若兩個l在不同塊,則最壞情況為o(2

∗len

)o(2 * len)

o(2∗le

n)則列舉k次的時間複雜度為o(k

∗len

)o(k * len)

o(k∗le

n)對於r

由於兩個l不一定在同一塊,所以r時不一定有序的

也就是說,每個r的移動都有可能帶來o(n

)o(n)

o(n)

的時間複雜度

由於要列舉的是sum個塊,所以時間複雜度為o(n

∗sum

)o(n * sum)

o(n∗su

m)o (k

∗len

+n∗s

um)=

o(n∗

sum+

n∗su

m)=o

(n∗s

um)=

o(n∗

sqrt

(n))

o(k* len + n * sum) = o(n * sum + n * sum) = o(n * sum) = o(n * sqrt(n) )

o(k∗le

n+n∗

sum)

=o(n

∗sum

+n∗s

um)=

o(n∗

sum)

=o(n

∗sqr

t(n)

) 看來是個非常優秀的演算法

luogu p1972

這道題已經非常裸了,解析就不給出了,自己看**就好

(luogu加強了資料無法再ac,但是寫一寫還是沒什麼問題的)

#include

using

namespace std;

const

int max_l =

10000005

;struct hazaking

m[max_l]

;int a[max_l]

, vis[max_l]

;inline

bool

cmp1

(hazaking a, hazaking b)

inline

bool

cmp2

(hazaking a, hazaking b)

intread()

int n =

read()

;int len = sqrt ( n )

;int q;

int l =

1, r =0;

int ans =0;

inline

void

ins(

int k)

inline

void

del(

int k)

inline

void

query

(int k)

inline

void

init()

//對於詢問陣列初始化

sort

(m +

1, m + q +

1, cmp1 )

;//對陣列進行排序

for(

int i =

1; i <= q ; i++

)query

(i);

//查詢

sort

(m +

1, m + q +

1, cmp2 )

;//對答案排序,滿足資料輸入順序

for(

int i =

1; i <= q ; i ++

)printf

("%d\n"

, m[i]

.ans )

;//輸出答案

}inline

void

work()

intmain()

莫隊演算法學習筆記(二) 帶修莫隊

莫隊演算法,是乙個十分優雅的暴力。普通的莫隊可以輕鬆解決一些離線問題,但是,當遇上了一些有修改操作的問題,普通莫隊就無能為力了。於是,改進後的莫隊 帶修莫隊就這樣產生了。接下來,我們一起在普通莫隊的基礎之上,學會帶修莫隊這個強大無比的演算法。既然是帶修莫隊,那麼第乙個關鍵問題就是如何處理修改。其實,...

F Machine Learning(帶修莫隊)

f.machine learning 思路 統計每個數字出現的次數numi,記錄次數numi出現的次數cnti。然後就是帶修莫隊的事情了。注意 不要用node x,y,z 這種方式,不然就是錯,很迷。include include include include include includeusi...

數顏色(莫隊帶修)

數顏色題目鏈結 帶修改的莫隊,關於時間複雜度的分析沒仔細看,但是這是乙個能實現更改的離線操作,感覺在之前的維度上加了一維 時間維度,可以將狀態向前或者向後改變,而時間的變遷也用while來更新,以達到操作目的,sort規則也變成這樣 return qu a.l qu b.l qu a.r qu b....