题解
luoguP4178
此题要强制在线。
首先, 对于 \(a\) 数组离散化。
再把 \(a\) 分块。
维护数组 \(cnt_{i, j}\) 表示前 \(i\) 个快 \(j\) 的出现次数。
维护数组 \(op_{i, j}\) 表示第 \(i\) ~ \(j\) 快的众数。
对于整块, 直接处理。
对于零散元素, 统计答案做比较。
如果把块长设为 \(\sqrt{n}\), 时间复杂都为 \(O((q + n) \sqrt{n})\)
#include<bits/stdc++.h>
using namespace std;
const int N = 40005;
int last, p, q, Max, now, maxx[5000][5000], cnt[5000][5000], zh, ans[N], a[N], b[N], sum[5000][N], m, n, l, r, op[N], L[N], R[N], len, T, s[5000][N], ok[N];
vector<int>g[N];
inline int query(int l, int r){
p = op[l], q = op[r];
Max = maxx[p + 1][q - 1];
now = cnt[p + 1][q - 1];
for(int i = l; i <= min(R[p], r); i++){
ok[a[i]]++;
}
if(p != q){
for(int i = L[q]; i <= r; i++){
ok[a[i]]++;
}
}
for(int i = l; i <= min(R[p], r); i++){
zh = max(0, s[q - 1][a[i]] - s[p][a[i]]) + ok[a[i]];
if(zh > Max || zh == Max && now > a[i]){
now = a[i];
Max = zh;
}
}
if(p == q){
for(int i = l; i <= r; i++){
ok[a[i]] = 0;
}
return now;
}
for(int i = L[q]; i <= r; i++){
zh = max(0, s[q - 1][a[i]] - s[p][a[i]]) + ok[a[i]];
if(zh > Max || zh == Max && now > a[i]){
now = a[i];
Max = zh;
}
}
for(int i = l; i <= min(R[p], r); i++){
ok[a[i]] = 0;
}
for(int i = L[q]; i <= r; i++){
ok[a[i]] = 0;
}
return now;
}
int main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; ++i){
cin >> a[i];
b[i] = a[i];
}
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; ++i){
a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
g[a[i]].push_back(i);
}
len = sqrt(n);
T = (n + len - 1) / len;
for(int i = 1; i <= (n + len - 1) / len; ++i){
L[i] = (i - 1) * len + 1, R[i] = min(n, i * len);
for(int j = L[i]; j <= R[i]; j++){
sum[i][a[j]]++;
op[j] = i;
}
for(int j = 1; j <= n; ++j){
s[i][j] = s[i - 1][j] + sum[i][j];
}
}
for(int i = 1; i <= T; ++i){
for(int j = 1; j <= n; ++j){
ans[j] = 0;
}
now = 0, Max = -1;
for(int j = i; j <= T; ++j){
for(int k = L[j]; k <= R[j]; k++){
ans[a[k]]++;
if(ans[a[k]] > Max || ans[a[k]] == Max && a[k] < now){
Max = ans[a[k]], now = a[k];
}
}
cnt[i][j] = now;
maxx[i][j] = Max;
}
}
while(m--){
cin >> l >> r;
l = (l + last - 1) % n + 1;
r = (r + last - 1) % n + 1;
if(l > r){
swap(l, r);
}
cout << (last = b[query(l, r)]) << '\n';
}
return 0;
}