正题
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P4168
题目大意
询问区间众数
解题思路
将数字离散化,然后分块。对于数组vi,j,kv_{i,j,k}vi,j,k,表示i∼ji\sim ji∼j个块,kkk的个数。对于询问(l,r)(l,r)(l,r),将整块的直接累计,然后局部的直接暴力。
时间复杂度:O(NT2+MNT)O(NT^2+\frac{MN}{T})O(NT2+TMN),根据LYD的说法,让T≈n3T\approx \sqrt[3]nT≈3n的话,时间复杂度就可以在O(N53)O(N^{\frac{5}{3}})O(N35)级别。
代码写优美些或者加点优化就可以过。
code
#pragma GCC optimize(2)
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
%:pragma GCC optimize("-fgcse")
%:pragma GCC optimize("-fgcse-lm")
%:pragma GCC optimize("-fipa-sra")
%:pragma GCC optimize("-ftree-pre")
%:pragma GCC optimize("-ftree-vrp")
%:pragma GCC optimize("-fpeephole2")
%:pragma GCC optimize("-ffast-math")
%:pragma GCC optimize("-fsched-spec")
%:pragma GCC optimize("unroll-loops")
%:pragma GCC optimize("-falign-jumps")
%:pragma GCC optimize("-falign-loops")
%:pragma GCC optimize("-falign-labels")
%:pragma GCC optimize("-fdevirtualize")
%:pragma GCC optimize("-fcaller-saves")
%:pragma GCC optimize("-fcrossjumping")
%:pragma GCC optimize("-fthread-jumps")
%:pragma GCC optimize("-funroll-loops")
%:pragma GCC optimize("-fwhole-program")
%:pragma GCC optimize("-freorder-blocks")
%:pragma GCC optimize("-fschedule-insns")
%:pragma GCC optimize("inline-functions")
%:pragma GCC optimize("-ftree-tail-merge")
%:pragma GCC optimize("-fschedule-insns2")
%:pragma GCC optimize("-fstrict-aliasing")
%:pragma GCC optimize("-fstrict-overflow")
%:pragma GCC optimize("-falign-functions")
%:pragma GCC optimize("-fcse-skip-blocks")
%:pragma GCC optimize("-fcse-follow-jumps")
%:pragma GCC optimize("-fsched-interblock")
%:pragma GCC optimize("-fpartial-inlining")
%:pragma GCC optimize("no-stack-protector")
%:pragma GCC optimize("-freorder-functions")
%:pragma GCC optimize("-findirect-inlining")
%:pragma GCC optimize("-fhoist-adjacent-loads")
%:pragma GCC optimize("-frerun-cse-after-loop")
%:pragma GCC optimize("inline-small-functions")
%:pragma GCC optimize("-finline-small-functions")
%:pragma GCC optimize("-ftree-switch-conversion")
%:pragma GCC optimize("-foptimize-sibling-calls")
%:pragma GCC optimize("-fexpensive-optimizations")
%:pragma GCC optimize("-funsafe-loop-optimizations")
%:pragma GCC optimize("inline-functions-called-once")
%:pragma GCC optimize("-fdelete-null-pointer-checks")
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define Tn 40
#define N 40010
using namespace std;
int n,m,L[Tn],R[Tn],v[Tn][Tn][N],l,r,num[N];
int z[N],w[N],a[N],cnt,k[N],t,T,pos[N],x;
bool cmp(int x,int y)//排序
{return z[x]<z[y];}
void begins()//预处理
{for(int i=1;i<=t;i++){L[i]=(i-1)*T+1;R[i]=i*T;}if(R[t]<n) t++,L[t]=R[t-1]+1,R[t]=n;//计算边界for(int i=1;i<=t;i++)for(int j=i;j<=t;j++)for(int k=L[i];k<=R[j];k++)v[i][j][a[k]]++;//计算v数组
}
int ask(int l,int r)
{int p=pos[l],q=pos[r];if(p-q<=2){memset(k,0,sizeof(k));for(int i=l;i<=r;i++)k[a[i]]++;}else{p++;q--;for(int i=1;i<=cnt;i++)k[i]=v[p][q][i];//直接累计for(int i=l;i<L[p];i++)//暴力统计k[a[i]]++;for(int i=R[q]+1;i<=r;i++)//暴力统计*2k[a[i]]++;}int mark=1;for(int i=2;i<=cnt;i++)//找众数if(k[i]>k[mark]) mark=i;return w[mark];
}
int main()
{scanf("%d%d",&n,&m);t=(int)pow(double(n),1.0/3);T=n/t;for(int i=1;i<=n;i++){scanf("%d",&z[i]);num[i]=i;}sort(num+1,num+1+n,cmp);z[0]=-1;for(int i=1;i<=n;i++)//离散化{if(z[num[i]]!=z[num[i-1]]) cnt++,w[cnt]=z[num[i]];;a[num[i]]=cnt;}T=n/t;begins();for(int i=1;i<=m;i++){scanf("%d%d",&l,&r);l=(l+x-1)%n+1;r=(r+x-1)%n+1;if(l>r) swap(l,r);printf("%d\n",x=ask(l,r));}
}