莫隊入門總結

2021-10-02 18:47:29 字數 2019 閱讀 7756

這是一篇適合蒟蒻的講解****大佬可以自行離開****

莫隊是一種是離線的演算法 , 即它在詢問的時候是不會修改的, 所以我們可以通過調整詢問的次序來獲得答案。

比如區間3到5和區間3到6 ,他們之間只差了1 , 於是我們只需要看下新加進來的這個元素對原來答案的影響就好了 , 對吧?

問題是: 我們應該如何給詢問區間排序使得時間複雜度最小呢???

這裡直接給出答案(主要是我太弱了 , 不會講 , 可以先自行思考 , 熟練了之後去看其他大佬的部落格):

首先將整個區間分塊 , 將左端點按塊來排序 , 右端點按實際位置排序 ;

有點抽象 , 上**看看 :

struct question

}q[maxn]

;

其中pos存的是這個點所對應的塊的編號 ;

然後。。莫隊就結束了。。。

先上個例題看看:對著題講會好些

洛谷p2709

根據我們剛才的思路 ,先把詢問排序 , 然後再移動區間即可 ;

手動模擬一下就可以懂了 ;

看圖 :

其中cnt是我目前各個數出現的次數 ;

簡簡單單 ;

上**:

#include

using

namespace std ;

#define maxn 50050

#define int long long

#define re register int

#define kkk signed main

#define mem(x) memset(x,0,sizeof(x))

inline

intread()

while

(ch >=

'0'&& ch <=

'9') ans =

(ans <<3)

+(ans <<1)

+ ch -

'0', ch =

getchar()

;return ans ;

}int a[maxn]

, pos[maxn]

, l[maxn]

, r[maxn]

, cnt[maxn]

, ans[maxn]

, aans;

int n , m , k , s , len ;

struct question

}q[maxn]

;inline

void

add(

int x)

inline

void

del(

int x)

kkk(

)for

(int i =

1; i <= m ; i++

)sort

(q +

1, q +

1+ m)

;int l =

1, r =0;

for(

int i =

1; i <= m ; i++

)for

(int i =

1; i <= m ; i++

)return0;

}

其中l【i】 是第i塊的左端點 , pos是這點屬於第幾塊 , ans是存這個詢問的答案 ;

然後完結撒花✿✿ヽ(°▽°)ノ✿ ;

(我太弱了可能沒講明白 自己多手摸幾次就好了)

莫隊最基礎就講完了 , 其實還有很多玄學優化 (要不然你會發現很多tle )

你這可以在搞定這篇之後再去看其他人的(其實我不懂 )

再次強調:本篇部落格只面向像我一樣的蒟蒻 , 如有不足 , 請各位神犇指出qwq ;

莫隊總結 莫隊例題

假設我們已知區間 l,r,需要計算的區間為 l,r,由於 l 和 r分別只能單步轉移,所以需要的時間複雜度為 l l r r 相當於把兩個區間分別看成是平面上的兩個整點p1 l,r 和p2 l,r 兩點之間的轉移開銷為兩點之間的曼哈頓距離。連線所有點的最優方案為一棵樹,那麼整體的時間複雜度就是這棵樹...

莫隊演算法入門

昨天重溫了一下captainmo的職業生涯 莫隊的模板,看了下別人的部落格,把三個板子打了,做練習前先小小總結了一下吧。一.基礎莫隊演算法 莫隊演算法 離線 暴力 分塊,它通常用於不修改只查詢的一類區間問題,複雜度為 主要就是通過排序過後再處理詢問能優化暴力,排序則是利用分塊,至於為什麼更優,附張別...

permu 莫隊 總結

由於每次詢問靜態區間裡完整值域段的最大大小 貌似很好用莫隊轉移,所以考慮怎麼轉移 當給它擴充套件乙個數時,就是給值域新增了乙個值 這個值可能已經存在,也可能是新的 有的神仙做法是維護了乙個並查集,然而我這碼力.所以我用了乙個更加初級的操作,給每個點打上向左連續最遠和向右連續最遠的標記 新增乙個新點時...