莫隊演算法
===
###### 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;
}
```