---
# System prepended metadata

title: 莫隊演算法
tags: [Algorithm]

---

莫隊演算法
===
###### tags: `Algorithm`

* 使用條件
    * 允許離線
    * 區間查詢 + 修改
    * 可以在很短的時間知道邊界相鄰位置的答案
        *  [l - 1, r], [l + 1, r],[l, r + 1],[l, r - 1]
* 特點
    * 複雜度 `O( n * n^(1\2))`
* 核心
    * **分組排序法**: 先按左界排序後, 分組, 在組內按右界排序
    * 實現
        * (l\s, r) 字典序排序
## 實現

### 核心語句

* 排序
```cpp
inline bool  operator < ( const Q &b){
    return (blk == b.blk)?  (r < b.r) : (blk < b.blk);
}
```

* 調整列隊
```cpp
sort( qs, qs+m);

curL = 0, curR = 0, curAns;
rep( i, 0, m){        
    Q &q = qs[i];

    while( q.r > curR) add( curR++);
    while( q.r < curR) sub ( --curR);
    while( q.l > curL) sub( curL++);
    while( q.l < curL) add( --curL);
    anss[ q.i] = curAns;
}
```

### toj120 區間和
```cpp
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for( int i =(a); i<(b); i++)
#define DE cout << " ::"
#define maxQ 200010
#define maxN 200010
#define int long long

struct Q{ // Query
    int l, r, i;
    int blk; //block
    inline bool  operator < ( const Q &b){
        return (blk == b.blk)?  (r < b.r) : (blk < b.blk);
    }
}qs[ maxQ]; // queries
int anss[maxQ];
int lim;
int arr[maxN];

int curL, curR, curAns;
inline void add( int i){
    curAns += arr[i];
}
inline void sub( int i){
    curAns -= arr[i];
}


signed main(){
    //freopen( "in.txt", "r", stdin);
    int n; cin >> n;
    rep( i, 0, n){
        cin >> arr[i];
    }
    lim = (int)sqrt(n) + 1;
     
    int m; cin >> m;
    rep( i, 0, m){
        int a, b; cin >> a >> b;
        if( a>b) swap(a, b);
        
        qs[i].l = a-1, qs[i].r = b;
        qs[i].i = i;
        qs[i].blk = qs[i].l / lim;
    }
    
    sort( qs, qs+m);
    
    curL = 0, curR = 0, curAns;
    rep( i, 0, m){        
        Q &q = qs[i];

        while( q.r > curR) add( curR++);
        while( q.r < curR) sub ( --curR);
        while( q.l > curL) sub( curL++);
        while( q.l < curL) add( --curL);
        anss[ q.i] = curAns;
    }
    rep( i, 0, m){
        cout << anss[i] << '\n';
    }
    return 0;
}
```