這是一篇適合蒟蒻的講解****大佬可以自行離開****
莫隊是一種是離線的演算法 , 即它在詢問的時候是不會修改的, 所以我們可以通過調整詢問的次序來獲得答案。
比如區間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 莫隊 總結
由於每次詢問靜態區間裡完整值域段的最大大小 貌似很好用莫隊轉移,所以考慮怎麼轉移 當給它擴充套件乙個數時,就是給值域新增了乙個值 這個值可能已經存在,也可能是新的 有的神仙做法是維護了乙個並查集,然而我這碼力.所以我用了乙個更加初級的操作,給每個點打上向左連續最遠和向右連續最遠的標記 新增乙個新點時...