# 莫隊
* 主要想法:如果知道[a,b]的答案,那也可以$O(1)$的時間知道[a+1,b], [a-1, b], [a, b+1], [a, b-1]的答案,因此也是離線算法
* 但是如果指針不停的來回,複雜度扔是$O(n)$,因此重點是要盡量減少指針來回的次數
* 利用分塊法的想法,如果把區間每$\sqrt n$分成一塊,這樣一次查詢複雜度就是$O(\sqrt n)$
* 因此先把左界照分塊排序,左界分塊相同的照右界大小排序,離線複雜度是$O(n\sqrt q)$
:::info
跟直接對左界大小排序有什麼差別?
考慮這樣的查詢:
1, 1000000
2, 2
3, 1000000
4, 2
右指針走法會是1->1000000->2->1000000->2,複雜度很慘
但用莫對查詢順序會變:
2, 2
1, 1000000
4, 2
3, 1000000
而右指針走法會變1->2->1000000->2->1000000,顯然少來回了幾次
所以莫對只是一個折衷
:::
區間眾數
---
```cpp=
#include <bits/stdc++.h>
#define EB emplace_back
#define vci vector<int>
#define PII pair<int,int>
#define F first
#define S second
#define rep(X, a,b) for(int X=a;X<b;++X)
#define ALL(a) (a).begin(), (a).end()
#define SZ(a) (int)(a).size()
#define NL "\n"
#define LL long long
using namespace std;
LL l=1, r=1, ans=1, K;
LL cnt[100010]={0}, num[100010], cntcnt[100010]={0};
struct qy{
LL l, r, id;
bool operator<(const qy& q){
return l/K==q.l/K?r<q.r:l/K<q.l/K;
}
};
void add(LL a){
cntcnt[cnt[a]]--;
cnt[a]++;
cntcnt[cnt[a]]++;
ans=max(ans, cnt[a]);
}
void sub(LL a){
cntcnt[cnt[a]]--;
cnt[a]--;
cntcnt[cnt[a]]++;
if(cnt[a]+1==ans && cntcnt[cnt[a]+1]==0) ans=cnt[a];
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
LL n, m;
cin>>n>>m;
K=sqrt(n);
vector<qy> qry(m);
rep(i,1,n+1) cin>>num[i];
rep(i,0,m){
cin>>qry[i].l>>qry[i].r;
qry[i].id=i;
}
sort(ALL(qry));
vector<pair<LL,LL>> res(m);
cnt[num[1]]=1;
cntcnt[1]=1;
for(auto a:qry){
while(l<a.l) sub(num[l++]);
while(l>a.l) add(num[--l]);
while(r<a.r) add(num[++r]);
while(r>a.r) sub(num[r--]);
res[a.id]={ans, cntcnt[ans]};
}
for(auto a:res) cout<<a.F<<" "<<a.S<<NL;
}
```