卡常大师天波去打 ARC 了,只有我被这道紫题卡常,照着 OIwiki 学了半天收获 TLE*14。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, m;
struct que {
int l, r, id;
long long ans;
} q[100005];
int a[100005], bel[100005];
int kl[1005], kr[1005], ks, kc;
int ml[1005], mr[1005], ms, mc;
long long nans, lans;
map<int, int> cnt, ccnt;
void BuildN() {
kc = sqrt(n), ks = ceil(n / kc) + 0.114514;//+0.114514 防止浮点数误差
for (int i = 1; i <= ks; i++)
kl[i] = kr[i - 1] + 1, kr[i] = kl[i] + kc - 1;
kr[ks] = n;//对原序列进行第一次分块
for (int i = 1; i <= ks; i++)
for (int j = kl[i]; j <= kr[i]; j++)
bel[j] = i;//处理出每个数所在块,此后就可以进行回滚
//至此,原序列完成了简单的分块
}
void BuildQ() {
mc = sqrt(n), ms = ceil(m / mc) + 0.114514;
for (int i = 1; i <= ms; i++)
ml[i] = mr[i - 1] + 1, mr[i] = ml[i] + mc - 1;
mr[ms] = m;
sort(q + 1, q + 1 + m, [](que &a, que &b){
\
return bel[a.l] != bel[b.l] ? bel[a.l] < bel[b.l] : a.r < b.r;
\
});
//对询问进行莫队分块,此时我们可以开始离线处理了
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
BuildN();
for (int i = 1; i <= m; i++){
cin >> q[i].l >> q[i].r;
q[i].id = i;
}
BuildQ();
int nl = 1, nr = 0, lb = 0;
for (int i = 1; i <= m; i++){ //这不是普通的莫队了,不再以块为单位处理
//也有可能是我的蓝书写法比较抽象,似乎也可以以块为单位
if (bel[q[i].l] == bel[q[i].r]) { //同一块内暴力
for (int j = q[i].l; j <= q[i].r; j++){
ccnt[a[j]]++;
}
for (int j = q[i].l; j <= q[i].r; j++)
q[i].ans = max(q[i].ans, 1ll * a[j] * ccnt[a[j]]);
for (int j = q[i].l; j <= q[i].r; j++)
ccnt[a[j]]--;
continue;
//有点回溯思想,但是不难理解
}
if (bel[q[i].l] != lb){
//左端点与上一个询问左端点不同,初始化
while (nr > kr[bel[q[i].l]])
cnt[a[nr]]--, nr--;
while (nl <= kr[bel[q[i].l]])
cnt[a[nl]]--, nl++;
nans = 0;
lb = bel[q[i].l];
}
while (nr < q[i].r){
nr++;
cnt[a[nr]]++;
nans = max(nans, 1ll * a[nr] * cnt[a[nr]]);
}
lans = nans;
int tl = nl;
while (tl > q[i].l){
tl--;
cnt[a[tl]]++;
lans = max(lans, 1ll * a[tl] * cnt[a[tl]]);
}
q[i].ans = lans;
while (tl < nl)
cnt[a[tl]]--, tl++;
}
sort(q + 1, q + 1 + m, [](que a, que b){return a.id < b.id;});
for (int i = 1; i <= m; i++)
cout << q[i].ans << "\n";
}