版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/82050087
题目
求区间众数
分析
线段树和树状数组很难做的,分块可以做,离散后预处理,大段维护,小段朴素,就做完了
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
#define cct(i,a,b) for (register int i=a;i<=b;i++)
int n,m,pos[40001],t[40001],a[40001],b[40001],st[201],ed[201],ans[201][201],sum[40001][201];
int in(){
int ans=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
return ans;
}
int answ(int l,int r){
int p=pos[l],q=pos[r];
if (p==q){//小段朴素
int now=0;
cct(i,l,r){
t[a[i]]++;
if (t[a[i]]>t[now]||t[a[i]]==t[now]&&now>a[i]) now=a[i];//求众数
}
cct(i,l,r) t[a[i]]--;
return b[now];
}
int now=ans[p+1][q-1];
t[now]+=sum[now][q-1]-sum[now][p];
cct(i,l,ed[p]){
if (!t[a[i]]) t[a[i]]+=sum[a[i]][q-1]-sum[a[i]][p];//暂且先记录下来
t[a[i]]++;
if (t[a[i]]>t[now]||t[a[i]]==t[now]&&now>a[i]) now=a[i];//求众数
}
cct(i,st[q],r){
if (!t[a[i]]) t[a[i]]+=sum[a[i]][q-1]-sum[a[i]][p];//the same
t[a[i]]++;
if (t[a[i]]>t[now]||t[a[i]]==t[now]&&now>a[i]) now=a[i];
}
cct(i,l,ed[p]) t[a[i]]=0;//清空
cct(i,st[q],r) t[a[i]]=0;
t[ans[p+1][q-1]]=0;
return b[now];
}
int main(){
n=in(); m=in(); int pws=sqrt(n);
cct(i,1,n){
a[i]=b[i]=in();
pos[i]=(i+pws-1)/pws; ed[pos[i]]=i;
if (!st[pos[i]]) st[pos[i]]=i; //分块
}
std::sort(b+1,b+1+n);
int k=std::unique(b+1,b+1+n)-(b+1);//去重
cct(i,1,n) a[i]=std::lower_bound(b+1,b+1+k,a[i])-b;//离散
cct(i,1,pos[n]){
int now=0;
cct(j,st[i],n){
t[a[j]]++;//数字++
if (t[a[j]]>t[now]||t[a[j]]==t[now]&&now>a[j]) now=a[j];//求众数
ans[i][pos[j]]=now;//记录答案
}
cct(j,st[i],n) t[a[j]]--;
}
cct(i,1,n) sum[a[i]][pos[i]]++;
cct(i,1,k) cct(j,1,pos[n]) sum[i][j]+=sum[i][j-1];//前缀和
int last=0;
while (m--){
int x=in(); int y=in();
x=(x+last-1)%n+1; y=(y+last-1)%n+1;
if (x>y) x^=y,y^=x,x^=y;//按照题目模拟
last=answ(x,y);
printf("%d\n",last);
}
return 0;
}