传送门
解题思路
一言一概之,动态求区间众数。
瞄一眼数据范围,大约n根号n——分块大法好!
先把读入的数据离散化,然后进行分块处理。
对于每一个询问,把它分成整块和零散快处理:
- 整块:预处理i到j块的众数,直接O(1)询问。
- 零散快:预处理从1到n每个数出现的位置,枚举零散快的数字,二分查找询问的区间内的个数,与整块的众数作比较。
预处理众数:枚举起始块,向右暴力枚举,O(n*块数)
预处理数字位置:扫一遍,加入vector中即可
假设块数为T,则时间复杂度为O(n*T+m*n/T*log(n)),所以当n*T=m*n/T*log(n)时,和最小,所以T=sqrt(m*logn)。
按照sqrt(n)也能水过去
AC代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<queue> 8 #include<set> 9 #include<map> 10 #include<vector> 11 #include<iomanip> 12 #include<ctime> 13 #include<stack> 14 using namespace std; 15 const int maxn=40005; 16 vector<int> v[maxn]; 17 int n,m,sq,a[maxn],aa[maxn],q[maxn],cnt,now=1,l[maxn],r[maxn],id[maxn],c[maxn],mode[1005][1005]; 18 int ll,rr,anss; 19 int main() 20 { 21 cin>>n>>m; 22 sq=sqrt(m); 23 if(sq*sq<m) sq++; 24 for(int i=1;i<=n;i++) { 25 scanf("%d",&aa[i]); 26 q[i]=aa[i]; 27 } 28 sort(q+1,q+n+1); 29 int len=unique(q+1,q+n+1)-q-1; 30 for(int i=1;i<=n;i++) a[i]=lower_bound(q+1,q+len+1,aa[i])-q; 31 l[now]=1; 32 for(int i=1;i<=n;i++){ 33 if(cnt==sq){ 34 r[now++]=i-1; 35 l[now]=i; 36 cnt=0; 37 } 38 cnt++; 39 id[i]=now; 40 } 41 r[now]=n; 42 for(int i=1;i<=sq;i++){ 43 memset(c,0,sizeof(c)); 44 int maxx=0; 45 for(int j=i;j<=sq;j++){ 46 for(int k=l[j];k<=r[j];k++){ 47 c[a[k]]++; 48 if((c[a[k]]>c[maxx])||(c[a[k]]==c[maxx]&&a[k]<maxx)) maxx=a[k]; 49 } 50 mode[i][j]=maxx; 51 } 52 } 53 for(int i=1;i<=n;i++) v[a[i]].push_back(i); 54 int ans=0; 55 for(int i=1;i<=m;i++){ 56 anss=0; 57 scanf("%d%d",&ll,&rr); 58 ll=(ll+q[ans]-1)%n+1; 59 rr=(rr+q[ans]-1)%n+1; 60 if(ll>rr) swap(ll,rr); 61 if(id[ll]==id[rr]){ 62 for(int j=ll;j<=rr;j++){ 63 int noww=upper_bound(v[a[j]].begin(),v[a[j]].end(),rr)-lower_bound(v[a[j]].begin(),v[a[j]].end(),ll); 64 if((noww>anss)||(noww==anss&&a[j]<ans)) ans=a[j],anss=noww; 65 } 66 }else{ 67 int noww=0; 68 if(id[ll]!=id[rr]-1){ 69 ans=mode[id[ll]+1][id[rr]-1]; 70 anss=upper_bound(v[ans].begin(),v[ans].end(),rr)-lower_bound(v[ans].begin(),v[ans].end(),ll); 71 } 72 for(int j=ll;j<=r[id[ll]];j++){ 73 noww=upper_bound(v[a[j]].begin(),v[a[j]].end(),rr)-lower_bound(v[a[j]].begin(),v[a[j]].end(),ll); 74 if((noww>anss)||(noww==anss&&a[j]<ans)) ans=a[j],anss=noww; 75 } 76 for(int j=l[id[rr]];j<=rr;j++){ 77 noww=upper_bound(v[a[j]].begin(),v[a[j]].end(),rr)-lower_bound(v[a[j]].begin(),v[a[j]].end(),ll); 78 if((noww>anss)||(noww==anss&&a[j]<ans)) ans=a[j],anss=noww; 79 } 80 } 81 printf("%d ",q[ans]); 82 } 83 return 0; 84 }