这个,要处理各个数的话得先离散,我用的桶。
我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数。
证明:若不是这里的数连区间的众数都达不到。
我已开始把某个离散后的值当成了坐标,调了好久.......
#include<cstdio> #include<cmath> #include<vector> #include<cstring> #include<algorithm> using namespace std; int b[40010],a[40010],n,m,lon,pos[40010],t,p[40010],back[40010],num[40010],f[210][210],sz; int cmp(const int x,const int y) {if(b[x]<b[y])return 1;if(b[x]==b[y]&&x<y)return 1;return 0; } vector<int> place[40010]; inline void do_it(int x) {memset(num,0,sizeof(num));int who=0,how=0;for(int i=(x-1)*lon+1;i<=n;i++){num[a[i]]++;if(num[a[i]]>how||(num[a[i]]==how&&back[a[i]]<back[who]))who=a[i],how=num[a[i]];f[x][pos[i]]=who;} } inline void Init() {scanf("%d%d",&n,&m);lon=(int)sqrt(n+0.5);for(int i=1;i<=n;i++){scanf("%d",&b[i]);p[i]=i;pos[i]=(i-1)/lon+1;}sort(p+1,p+n+1,cmp);for(int i=1;i<=n;i++){if(b[p[i]]!=b[p[i-1]]){a[p[i]]=++sz;back[sz]=b[p[i]];}elsea[p[i]]=sz;place[sz].push_back(p[i]);}t=pos[n];for(int i=1;i<=t;i++)do_it(i); } inline int query(int l,int r,int x) {return upper_bound(place[x].begin(),place[x].end(),r)-lower_bound(place[x].begin(),place[x].end(),l); } inline int Min(int x,int y){return x<y?x:y;} inline int work(int l,int r) {int z=pos[l]+1,y=pos[r]-1;int who=f[z][y],how=query(l,r,who);int zzh=(z-1)*lon;zzh=Min(zzh,r);for(int i=l;i<=zzh;i++){int x=query(l,r,a[i]);if(x>how||(x==how&&a[i]<who))who=a[i],how=x;}if(pos[l]!=pos[r]){zzh=(y*lon)+1;for(int i=zzh;i<=r;i++){int x=query(l,r,a[i]);if(x>how||(x==how&&a[i]<who))who=a[i],how=x;}}return back[who]; } int main() {Init();int k=0;for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);x=(x+k-1)%n+1;y=(y+k-1)%n+1;if(x>y)x^=y^=x^=y;k=work(x,y);printf("%d\n",k);}return 0; }