题意
给出n个数,要求资瓷区间众数的查询。
n<=40000,m<=50000
强制在线
分析
这是栋爷所说的经典分块题。
先把数字离散化,那么我们就可以开我们最爱的东西——桶。
把n个数字按照
n√
的大小分成
n√
块,并预处理一些东西:
ans[i,j]表示第i块到第j块的众数是多少。
sum[i,j]表示数字i在第1块到第j块出现了多少次。
这两个数组都可以在O(
nn√
)的时间内预处理完。
那么查询起来就非常的容易了。桶用完之后记得清零。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,m,sum[40005][205],ans[205][205],bel[40005],sta[205],end[205],tot[40005],a[40005],b[40005],num[40005],block;
int query(int l,int r)
{
if (bel[l]==bel[r])
{
int now=0;
for (int i=l;i<=r;i++)
{
tot[num[i]]++;
if (tot[num[i]]>tot[now]||tot[num[i]]==tot[now]&&num[i]<now) now=num[i];
}
for (int i=l;i<=r;i++)
tot[num[i]]--;
return b[now];
}
int now=ans[bel[l]+1][bel[r]-1];
tot[now]+=sum[now][bel[r]-1]-sum[now][bel[l]];
for (int i=l;i<=end[bel[l]];i++)
{
if (!tot[num[i]]) tot[num[i]]+=sum[num[i]][bel[r]-1]-sum[num[i]][bel[l]];
tot[num[i]]++;
if (tot[num[i]]>tot[now]||tot[num[i]]==tot[now]&&num[i]<now) now=num[i];
}
for (int i=sta[bel[r]];i<=r;i++)
{
if (!tot[num[i]]) tot[num[i]]+=sum[num[i]][bel[r]-1]-sum[num[i]][bel[l]];
tot[num[i]]++;
if (tot[num[i]]>tot[now]||tot[num[i]]==tot[now]&&num[i]<now) now=num[i];
}
tot[ans[bel[l]+1][bel[r]-1]]=0;
for (int i=l;i<=end[bel[l]];i++)
tot[num[i]]=0;
for (int i=sta[bel[r]];i<=r;i++)
tot[num[i]]=0;
return b[now];
}
int main()
{
//freopen("2724.in","r",stdin);
//freopen("test.out","w",stdout);
scanf("%d%d",&n,&m);
block=sqrt(n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
bel[i]=(i+block-1)/block;
if (!sta[bel[i]]) sta[bel[i]]=i;
end[bel[i]]=i;
b[i]=a[i];
}
sort(b+1,b+n+1);
int l=unique(b+1,b+n+1)-b-1;
for (int i=1;i<=n;i++)
num[i]=lower_bound(b+1,b+l+1,a[i])-b;
for (int i=1;i<=bel[n];i++)
{
int now=0;
for (int j=sta[i];j<=n;j++)
{
tot[num[j]]++;
if (tot[num[j]]>tot[now]||tot[num[j]]==tot[now]&&num[j]<now) now=num[j];
ans[i][bel[j]]=now;
}
for (int j=sta[i];j<=n;j++)
tot[num[j]]--;
}
for (int i=1;i<=n;i++)
sum[num[i]][bel[i]]++;
for (int i=1;i<=l;i++)
for (int j=1;j<=bel[n];j++)
sum[i][j]+=sum[i][j-1];
int lastans=0;
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
x=(x+lastans-1)%n+1;y=(y+lastans-1)%n+1;
if (x>y) swap(x,y);
lastans=query(x,y);
printf("%d\n",lastans);
}
return 0;
}