AcWing 249 蒲公英 (分块)
题目链接:https://www.acwing.com/problem/content/submission/251/
区间众数
预处理出块\([L,R]\)内的每个数出现次数
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 40010;
int T, n, m, len, tot = 0;
int a[maxn], b[maxn], pos[maxn], L[maxn], R[maxn];
int cnt[40][40][maxn], cc[maxn];
int query(int l, int r){
int p = pos[l], q = pos[r];
int num, c = 0;
if(p + 1 > q - 1){
for(int i = l; i <= r; ++i) ++cc[a[i]];
for(int i = 1; i <= tot; ++i){
if(cc[i] > c) {
c = cc[i]; num = i;
}
}
for(int i = l; i <= r; ++i) --cc[a[i]];
} else{
for(int i = l; i <= R[p]; ++i) ++cnt[p+1][q-1][a[i]];
for(int i = L[q]; i <= r; ++i) ++cnt[p+1][q-1][a[i]];
for(int i = 1; i <= tot; ++i){
if(cnt[p+1][q-1][i] > c){
c = cnt[p+1][q-1][i];
num = i;
}
}
for(int i = l; i <= R[p]; ++i) --cnt[p+1][q-1][a[i]];
for(int i = L[q]; i <= r; ++i) --cnt[p+1][q-1][a[i]];
}
return num;
}
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
int main(){
n = read(), m = read();
T = pow(n, 1.0 / 3.0); len = n / T;
for(int i = 1; i <= T; ++i){
L[i] = (i - 1) * len + 1;
R[i] = i * len;
}
if(R[T] < n){
++T; L[T] = R[T - 1] + 1; R[T] = n;
}
for(int i = 1; i <= T; ++i)
for(int j = L[i]; j <= R[i]; ++j)
pos[j] = i;
for(int i = 1; i <= n ; ++i){
a[i] = read(); b[i] = a[i];
}
sort(b + 1, b + 1 + n);
tot = unique(b + 1, b + 1 + n) - b - 1;
for(int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + 1 + tot, a[i]) - b;
for(int i = 1; i <= T; ++i){
for(int j = i ; j <= T; ++j){
for(int k = L[i]; k <= R[j]; ++k){
++cnt[i][j][a[k]];
}
}
}
int l, r, x = 0;
for(int i = 1; i <= m; ++i){
l = read(), r = read();
l = (l + x - 1) % n + 1;
r = (r + x - 1) % n + 1;
if(l > r) swap(l, r);
x = b[query(l, r)];
printf("%d\n", x);
}
return 0;
}