题意:给N个数,求一个区间内的众数。
思路:分块,分成sqrt(t*log2(n)))块,先预处理出每一个块到每个块中的众数,离散化,然后把询问区间分三段,第一段为l到l所在块的终止,第二段为每一段块,第三段为r块的开始到r,然后第二段用预处理的数组就能得出,第一三段,二分vector记录的下标求众数。
#include<cstring> #include<algorithm> #include<vector> #include<map> #include<queue> #include<cstdio> #include<cmath> #define ll long long #define lowbit(x) x&(-x) using namespace std; const int N=1e6+10; int n,t,block; int a[N],f[N],b[N]; vector<int> g[N]; int c[N],d[1000][1000]; void build() { block=max(1,(int)(n/sqrt(t*log2(n)))); for(int i=1;i<=n;i++) b[i]=(i-1)/block+1; } int Count(int l,int r,int val) { int t=upper_bound(g[val].begin(),g[val].end(),r)-lower_bound(g[val].begin(),g[val].end(),l); return t; } void pre(int x) { memset(c,0,sizeof(c)); int mx=-1,ans=0; for(int i=(x-1)*block+1;i<=n;i++) { c[a[i]]++; if(c[a[i]]>mx||(c[a[i]]==mx&&a[i]<ans)) { ans=a[i]; mx=c[a[i]]; } d[x][b[i]]=ans;//代表x到b[i]块的众数。 } } int query(int l,int r) { int ans=d[b[l]+1][b[r]-1]; int mx=Count(l,r,ans); int cnt=0; int up=min(r,b[l]*block); for(int i=l;i<=up;i++) { cnt=Count(l,r,a[i]); if(cnt>mx||(cnt==mx&&f[ans]>f[a[i]])) { mx=cnt; ans=a[i]; } } if(b[l]!=b[r]) { for (int i=(b[r]-1)*block+1;i<=r;i++) { cnt=Count(l,r,a[i]); if(cnt>mx||(cnt==mx&&ans>a[i])) { mx=cnt; ans=a[i]; } } } return ans; } signed main() { scanf("%d%d",&n,&t); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); f[i]=a[i]; } build(); sort(f+1,f+n+1); int m=unique(f+1,f+n+1)-f-1; for(int i=1;i<=n;i++) { a[i]=lower_bound(f+1,f+m+1,a[i])-f; g[a[i]].push_back(i); } for(int i=1;i<=b[n];i++) { pre(i); } int ans=0; while(t--) { int l,r; scanf("%d%d",&l,&r); l=(l+ans-1)%n+1; r=(r+ans-1)%n+1; if(l>r) swap(l,r); ans=f[query(l,r)]; printf("%d\n",ans); } }