const int N = 1e5 + 5;
int n, q;
int x[N], t[N], m;
- ```
-
+
struct Query {
int l, r, id;
} Q[N];
int pos[N], L[N], R[N], sz, tot;
int cnt[N], __cnt[N];
ll ans[N];
-
+
inline bool cmp(const Query& A, const Query& B) {
if (pos[A.l] == pos[B.l]) return A.r < B.r;
return pos[A.l] < pos[B.l];
}
-
+
void build() {
sz = sqrt(n);
tot = n / sz;
R[tot] = n;
}
}
-
+
inline void Add(int v, ll& Ans) {
++cnt[v];
Ans = max(Ans, 1LL * cnt[v] * t[v]);
}
-
+
inline void Del(int v) { --cnt[v]; }
-
+
int main() {
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++) scanf("%d", &x[i]), t[++m] = x[i];
for (int i = 1; i <= q; i++) scanf("%d %d", &Q[i].l, &Q[i].r), Q[i].id = i;
-
+
build();
-
+
// 对询问进行排序
for (int i = 1; i <= tot; i++)
for (int j = L[i]; j <= R[i]; j++) pos[j] = i;
sort(Q + 1, Q + 1 + q, cmp);
-
+
// 离散化
sort(t + 1, t + 1 + m);
m = unique(t + 1, t + 1 + m) - (t + 1);
for (int i = 1; i <= n; i++) x[i] = lower_bound(t + 1, t + 1 + m, x[i]) - t;
-
+
int l = 1, r = 0, last_block = 0, __l;
ll Ans = 0, tmp;
for (int i = 1; i <= q; i++) {
for (int j = Q[i].l; j <= Q[i].r; j++) --__cnt[x[j]];
continue;
}
-
+
// 访问到了新的块则重新初始化莫队区间
if (pos[Q[i].l] != last_block) {
while (r > R[pos[Q[i].l]]) Del(x[r]), --r;
Ans = 0;
last_block = pos[Q[i].l];
}
-
+
// 扩展右端点
while (r < Q[i].r) ++r, Add(x[r], Ans);
__l = l;
tmp = Ans;
-
+
// 扩展左端点
while (__l > Q[i].l) --__l, Add(x[__l], tmp);
ans[Q[i].id] = tmp;
-
+
// 回滚
while (__l < l) Del(x[__l]), ++__l;
}