题目大意:对大小为 \(n\) 的数列进行 \(m\) ,每次求出区间最小众数。
解题思路:数列分块。同:LOJ6285. 数列分块入门 9
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 40040;
int n, m, blo, id, a[maxn], bl[maxn], p[202][202];
map<int, int> mp;
int val[maxn], cnt[maxn];
vector<int> g[maxn];
void pre(int x) {
memset(cnt, 0, sizeof(cnt));
int res = 0, mx = 0;
for (int i = (x-1)*blo+1; i <= n; i ++) {
cnt[a[i]] ++;
int t = bl[i];
if (cnt[a[i]] > mx || cnt[a[i]] == mx && val[a[i]] < val[res]) {
res = a[i];
mx = cnt[a[i]];
}
p[x][t] = res;
}
}
int mycount(int l, int r, int x) {
return upper_bound(g[x].begin(), g[x].end(), r) - lower_bound(g[x].begin(), g[x].end(), l);
}
int query(int l, int r) {
int res = p[bl[l]+1][bl[r]-1], mx = mycount(l, r, res);
for (int i = l; i <= min(bl[l]*blo, r); i ++) {
int t = mycount(l, r, a[i]);
if (t > mx || t == mx && val[a[i]] < val[res]) {
res = a[i];
mx = t;
}
}
if (bl[l] != bl[r]) {
for (int i = (bl[r]-1)*blo+1; i <= r; i ++) {
int t = mycount(l, r, a[i]);
if (t > mx || t == mx && val[a[i]] < val[res]) {
res = a[i];
mx = t;
}
}
}
return res;
}
int main() {
ios::sync_with_stdio(0);
cin >> n >> m;
blo = sqrt(n);
for (int i = 1; i <= n; i ++) {
cin >> a[i];
bl[i] = (i - 1) / blo + 1;
if (!mp[a[i]]) {
mp[a[i]] = ++id;
val[id] = a[i];
}
a[i] = mp[a[i]];
g[a[i]].push_back(i);
}
for (int i = 1; i <= bl[n]; i ++)
pre(i);
int l, r, x = 0;
for (int i = 1; i <= m; i ++) {
int l0, r0;
cin >> l0 >> r0;
l = (l0 + x -1) % n + 1;
r = (r0 + x - 1) % n + 1;
if (l > r) swap(l, r);
x = val[query(l, r)];
cout << x << endl;
}
return 0;
}