数列分块9
写一下分块,写的是洛谷的强制在线版本,写完之后感觉有一些实现上的细节处理可以整理一下。
首先简单说说分块怎么写。
我们还是按照 \(\sqrt n\) 的大小分块,然后进行预处理。我们定义 \(sum[i][j]\) 为前 i 个块中 j 出现了多少次,\(dp[i][j]\) 为块 i 和块 j 中的众数是哪一个。
我们根据分块的思想来想,每一个询问区间都可以看做中间的完整块和左右的零散元素。我们想询问众数的话哪些数有可能成为众数。显然只有中间整块部分的众数,以及左右部分的元素可能成为答案,证明自证(滑稽)
我们可以枚举左右零散部分的元素加到一个桶里面,每次加进去就看一下能否更新答案即可
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define B printf("!");
#define calc(x) sum[col[r]-1][x]-sum[col[l]][x]
using namespace std;
int read()
{
int a = 0,x = 1;char ch = getchar();
while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
return a*x;
}
const int N=4e4+1,M=2e2+7;
int n,m,b,col[N],que[N],a[N],pos[N];
int sum[M][N],t[N],dp[M][M],qwq = 999;
int query(int l,int r)
{
if(col[r]-col[l] <= 1) {
int maxn = 0;
for(int i = l;i <= r;i ++) {
t[a[i]] ++;
if(t[a[i]] > t[maxn] || (t[a[i]] == t[maxn] && a[i] < maxn)) maxn = a[i];
}
for(int i = l;i <= r;i ++) t[a[i]] --;
return maxn;
}
int maxn = dp[col[l]+1][col[r]-1];
for(int i = l;col[i] == col[l];i ++) {
t[a[i]] ++;
if(t[a[i]]+calc(a[i]) > t[maxn]+calc(maxn) || (t[a[i]]+calc(a[i]) == t[maxn]+calc(maxn) && a[i] < maxn))
maxn = a[i];
}
for(int i = r;col[i] == col[r];i --) {
t[a[i]] ++;
if(t[a[i]]+calc(a[i]) > t[maxn]+calc(maxn) || (t[a[i]]+calc(a[i]) == t[maxn]+calc(maxn) && a[i] < maxn))
maxn = a[i];
}
for(int i = l;col[i] == col[l];i ++) t[a[i]] --;
for(int i = r;col[i] == col[r];i --) t[a[i]] --;
return maxn;
}
int main()
{
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
n = read(),m = read();b = sqrt(n);
for(int i = 1;i <= n;i ++) a[i] = que[i] = read();
for(int i = 1;i <= n;i ++) col[i] = (i-1)/b+1;
sort(que+1,que+1+n);int len = unique(que+1,que+1+n) - que - 1;
for(int i = 1,tmp;i <= n;i ++) a[i] = lower_bound(que+1,que+1+len,tmp=a[i]) - que,pos[a[i]] = tmp;
for(int i = 1;i <= n;i ++) for(int j = col[i];j <= col[n];j ++) sum[j][a[i]] ++;
for(int i = 1,maxn=0;i <= col[n];i ++) {
for(int j = b*(i-1)+1;j <= n;j ++) {
t[a[j]] ++;
if(t[a[j]] > t[maxn] || (t[a[j]] == t[maxn] && a[j] < maxn)) maxn = a[j];
dp[i][col[j]] = maxn;
}
memset(t,0,sizeof(t));maxn = 0;
}
for(int i = 1,x = 0;i <= m;i ++) {
int l = read(),r = read();
l = (l+x-1)%n+1,r = (r+x-1)%n+1;
if(l > r) swap(l,r);
printf("%d\n",x=pos[query(l,r)]);
}
return 0;
}