1. 程式人生 > >【總結】 莫隊演算法

【總結】 莫隊演算法

前言

機房中的各位神仙都會莫隊就我不會,然後如果有些題實在想不出也可以用這個做一下。

思路

如果一些操作可以在知道\(Ans(l,r)\)的情況下,\(O(1)\)的時間內求出\(Ans(l-1,r),Ans(l+1,r),Ans(l,r+1),Ans(l,r-1)\),那麼就可以用莫隊求解。

  1. 將操作離線
  2. 按照分塊的思路排序(這是保證複雜度合法的關鍵)
  3. 對於每一個詢問不斷更新
  4. 總結答案,重新按照編號排序輸出

複雜度證明

在此之前,給出每一個區間詢問的排序方法

int bl[maxn];//bl陣列用來記錄每一個點屬於哪個塊
struct node{
    int l,r;
}ques[maxm];
bool cmp(node a,node b){
    if(bl[a.l]==bl[b.l])return a.r<b.r;
    return a.l<b.l;
}

因為每一組的詢問左界都是在一個塊裡面的,所以左界的更新不會超過\(sqrt(n)\)
如果左界不在一個塊裡面的話,複雜度就是\(O(m-sqrt(n))\)的。
又因為塊只有\(sqrt(n)\)個,所以一定是可以的(想一想,為什麼)

例題

Problem1

國家集訓隊-小Z的襪子


考慮拆分式子,發現本質是維護一個區間的平方和,然後就可以用莫隊計算。

Problem2

國家集訓隊-數顏色
考慮這是一個帶修改的莫隊,怎麼辦呢?

帶修改操作的莫隊

每一次詢問我們都是排序後一個一個做的對吧,那麼我們可以不斷的按照修改操作的順序來修改這些顏色,如果少了就接著改,多了就改回去。
思路和莫隊差不多,只是多了兩個迴圈,判斷改多了還是改少了。

Problem2

讓我們回到那個問題,接著思考怎麼做。
有了上面的思路,直接就可以寫了,記錄一下每一個詢問前最後一次修改的編號,然後不斷修改就好了。

後話

有沒有什麼神仙可以告訴我HH的項鍊在洛谷怎麼過(用莫隊)啊。80分實在是沒救了。
塊的大小大家可以將\(sqrt(n)\)\(n^{\frac{2}{3}}\)拍一下。