Input

Output

Sample Input

6 3
1 2 3 2 1 2
1 5
3 6
1 5

Sample Output

1
2
1

HINT

\(n <= 40000\),$ m <= 50000$

题意:

求区间众数

题解:

见代码

//解决本题的重要性质:
//对于两个区间a,b,其中已知a区间的众数k
//则众数一定为k或是b区间的任意一个数
#include<bits/stdc++.h>
#define re register int
using namespace std;
const int N=40010,M=410;
int n,q,m,blen,bsum;
int a[N],b[N];//b为离散数组
int bl[M][M];//bl[i][j]表示第i个块中的第j个数,bl[i][0]表示第i个块的长度
int bk[N];//bk[i]表示第i个数(在原数列中)在第bk[i]个块中
int f[M][M];//f[i][j]表示第i块到第j块之间的众数
int g[N][M];//g[i][j]表示i在前j个块中出现的次数
void init(){//初始化
for(int i=1,j=1;i<=n;++j){
int k;
for(k=1;k<=blen&&i<=n;++i,++k){
bk[i]=j;
bl[j][k]=a[i];
}k--;
bl[j][0]=k;
bsum=j;
}//处理块
for(int i=1;i<=bsum;++i){
for(int j=1;j<=m;++j){
g[j][i]=g[j][i-1];
}
for(int j=1;j<=bl[i][0];++j){
g[bl[i][j]][i]++;
}
}//预处理g数组
for(int i=1;i<=bsum;++i){
for(int j=i;j<=bsum;++j){
int num=f[i][j-1];int mx=g[num][j]-g[num][i-1];
for(int k=1;k<=bl[j][0];++k){
int now=g[bl[j][k]][j]-g[bl[j][k]][i-1];
if(now>mx||(now==mx&&bl[j][k]<num))num=bl[j][k],mx=now;
}
f[i][j]=f[j][i]=num;
}
}//预处理f数组
}
void read(){//读入
cin>>n>>q;blen=sqrt(n);
for(int i=1;i<=n;++i)scanf("%d",a+i),b[i]=a[i];
}
void lsh(){
sort(b+1,b+n+1);
m=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+m+1,a[i])-b;
}
void work(){
int last=0;
while(q--){
int l,r;
scanf("%d%d",&l,&r);
l=(l+last-1)%n+1;
r=(r+last-1)%n+1;
if(l>r)swap(l,r);
static int bj[M],cnt,v[N];cnt=0;//bj记录边角的数据,cnt为边角数据的数量
int L,R,num,mx;
if(bk[l]==bk[r]){//在同一块内暴力求众数
for(int i=l;i<=r;++i)bj[++cnt]=a[i],v[a[i]]++;
mx=0;
for(int i=l;i<=r;++i){
if(v[a[i]]>mx||(v[a[i]]==mx&&a[i]<num))num=a[i],mx=v[a[i]];
}
printf("%d\n",last=b[num]);
}else{//在不同块时,将中间当成一大块和边角比较
//根据性质,众数只有可能是中间这一块的众数或是边角上的数
//所以暴力枚举再判断就行了
re i;
for(i=l;bk[i]==bk[i-1];++i){
bj[++cnt]=a[i];v[a[i]]++;
}L=bk[i];
for(i=r;bk[i]==bk[i+1];--i){
bj[++cnt]=a[i];v[a[i]]++;
}R=bk[i];
num=f[L][R],mx=v[num]+g[num][R]-g[num][L-1];
for(i=1;i<=cnt;++i){
int now=v[bj[i]]+g[bj[i]][R]-g[bj[i]][L-1];
if(now>mx||(now==mx&&bj[i]<num))num=bj[i],mx=now;
}
printf("%d\n",last=b[num]);
}
for(re i=1;i<=cnt;++i)--v[bj[i]];//v数组要这样清空,复杂度O(cnt),不能用memset,那样是O(n)
}
}
int main(){
read();
lsh();
init();
work();
}

最新文章

  1. dede 简略标题调用标签
  2. 学习笔记-Java编程思想
  3. 【AT91SAM3S】SAM3S-EK Demo工程中,LCD驱动程序的加载(函数指针结构体)
  4. [Android Memory] android 警告:Exported activity does not require permission
  5. GPU优化方法[转]
  6. string为什么可以写入共享内存
  7. CentOS7 安装 swoole
  8. UI2_UIGesture
  9. 索引时利用K-邻近算法过滤重复歌曲
  10. pl sql练习(4)
  11. Copy--&gt;Mutable Copy
  12. hi3531的i2c部分
  13. DevExpress 控件中GridControl的使用
  14. centos修改主机名的正确方法
  15. solr全文检索实现原理
  16. react 简书开发笔记
  17. ML: 聚类算法R包-网格聚类
  18. div+css感悟
  19. jQuery(十):CSS-DOM操作
  20. [整理]LumiSoft.Net 开源组件

热门文章

  1. Linux下搭建gtk+2.0开发环境
  2. Python.__getattr__Vs__getattribute__
  3. pkg_config找不到库
  4. CocoStudio
  5. ubuntu系统下安装pyspider:安装命令集合。
  6. 2018.08.20 bzoj1143: [CTSC2008]祭祀river(最长反链)
  7. MyISAM压缩表
  8. redis学习-有序集合(zset)常用命令
  9. BZOJ 1005 [HNOI2008]明明的烦恼 (Prufer编码 + 组合数学 + 高精度)
  10. Redis为什么是单线程