subject
Title Link
To find the interval mode
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=4e4+10;
int n,m,t,len,sz,ans,L,R,cnt,num;
int a[N],b[N],F[N],st[40],ed[40],c[40][40][N],f[40][40],d[40][40];
//c[i][j][k]Represents an interval whose endpoint is the segment boundary[i,j]Ranked as k Number of occurrences of
//d[i][j]Express i Paragraph to j Mode ranking of segments
//f[i][j]Express i Paragraph to j Number of mode occurrences of segment
void Init()
{
t=(int)pow(n*1.0,1.0/3);//Length of each segment
if(t)len=n/t;
for(int i=1;i<=t;i++)st[i]=(i-1)*len+1,ed[i]=i*len;
if(ed[t]<n)st[t+1]=ed[t]+1,ed[++t]=n;
sort(b+1,b+n+1);
sz=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)F[i]=lower_bound(b+1,b+sz+1,a[i])-b;//Storage ranking after discrete de duplication
for(int i=1;i<=t;i++)for(int j=i;j<=t;j++)
{
for(int k=st[i];k<=ed[j];k++)c[i][j][F[k]]++;
for(int k=1;k<=sz;k++)
if(c[i][j][k]>f[i][j]||(c[i][j][k]==f[i][j]&&k<d[i][j]))f[i][j]=c[i][j][k],d[i][j]=k;
}
}
void update(int i)
{
c[L][R][F[i]]++;
if(c[L][R][F[i]]>cnt||(c[L][R][F[i]]==cnt&&F[i]<num))cnt=c[L][R][F[i]],num=F[i];
}
int solve(int x,int y)
{
int l,r;//Start segment end segment
if(x>y)swap(x,y);
for(int i=1;i<=t;i++)if(x<=ed[i]){l=i;break;}
for(int i=t;i;i--)if(y>=st[i]){r=i;break;}
if(l+1<=r-1)L=l+1,R=r-1;else L=R=0;
cnt=f[L][R],num=d[L][R];
if(l==r)
{
for(int i=x;i<=y;i++)update(i);
for(int i=x;i<=y;i++)c[L][R][F[i]]--;
}
else
{
for(int i=x;i<=ed[l];i++)update(i);
for(int i=st[r];i<=y;i++)update(i);//Simple scan incomplete segment update answer
for(int i=x;i<=ed[l];i++)c[L][R][F[i]]--;
for(int i=st[r];i<=y;i++)c[L][R][F[i]]--;//Array recovery
}
return b[num];
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
Init();
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
ans=solve((x+ans-1)%n+1,(y+ans-1)%n+1);
printf("%d\n",ans);
}
return 0;
}
summary
Because mode does not have interval additivity, it is very difficult to maintain it with tree array or line segment tree. We can use block algorithm.
Divide sequence a into t blocks, each block length L=N/T
For each query [l,r], let l be in block p and r in block q. Divide the interval [l,r] into three parts
1. [l, l] with less than one whole paragraph at the beginning
2. Interval composed of the p+1~q-1 block [L,R]
(R,r]
The mode of a sequence in interval [l,r] can only come from:
1. Mode of interval [L,R]
2. The number between [l,L) and (R,r].