bzoj2724[Violet 6]蒲公英
传送门
这个题是我晚自习的时候看到的,那个时候觉得这个题好简单啊,一上手才发现这个题好难写啊,调了好久都没调对
算法是分块!!
很显然众数不能直接合并,那么我们可以考虑每个块上记录这个块的众数。
对于每个询问,它可能包含多个块,由于众数不好合并,所以我们需要记录任意两个块之间的众数,这个直接循环预处理就好了
很显然,对于每个询问区间\([L,R]\),它的众数只可能是它包含的块的众数和多出来的那两段的数
如何统计那两段多出来的数在这个区间出现的次数?
考虑将每个数的位置存入vector中,每次二分查找就行了。
中间有个小插曲:一下子脑抽了,忘记了lower_bound是查询不小于的,看了篇博客说是不大于的,然后就一直wa,后来问了问别人才知道,改完就A了
记住离散化!
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<cstring>
using namespace std;
void read(int &x) {
char ch; bool ok;
for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=4e4+1;map<int,int>mp;
int n,m,a[maxn],id[maxn],mx,mxx,b[maxn],len,c[maxn],f[1001][1001],g[1001][1001],now,ans,num,w[maxn];
vector<int>d[maxn];
int main()
{
read(n),read(m);len=sqrt(n*log(n));num=n/len+1;
for(rg int i=1;i<=n;i++)read(a[i]),w[i]=a[i];
sort(w+1,w+n+1);for(rg int i=1;i<=n;i++)if(!mp[w[i]])mp[w[i]]=++now;
for(rg int i=1;i<=n;i++)c[i]=mp[a[i]];
for(rg int i=1;i<=n;i++)mp[c[i]]=a[i];
for(rg int i=1;i<=n;i++)id[i]=(i-1)/num+1;
for(rg int i=1;i<=len;i++)
{
for(rg int j=(i-1)*num+1;j<=n;j++)
{
b[c[j]]++;
if(b[c[j]]>mxx||(b[c[j]]==mxx&&mx>c[j]))mxx=b[c[j]],mx=c[j];
f[i][id[j]]=mx,g[i][id[j]]=mxx;
}
memset(b,0,sizeof b),mx=mxx=0;
}
for(rg int i=1;i<=n;i++)d[c[i]].push_back(i);
for(rg int i=1,x,y;i<=m;i++)
{
read(x),read(y);x=(x+ans-1)%n+1,y=(y+ans-1)%n+1;
if(x>y)swap(x,y);
int a=id[x],b=id[y];
if(a==b)
{
int mx=0,mxx=0;
for(rg int j=x;j<=y;j++)
{
int l=lower_bound(d[c[j]].begin(),d[c[j]].end(),x)-d[c[j]].begin(),r=lower_bound(d[c[j]].begin(),d[c[j]].end(),y)-d[c[j]].begin(),t=r-l+1;
if(d[c[j]][r]!=y)t--;
if(t>mxx||(t==mxx&&mx>c[j]))mx=c[j],mxx=t;
}
printf("%d\n",ans=mp[mx]);
}
else
{
int mx=0,mxx=0;
if(x>(a-1)*num+1)
{
for(rg int j=x;j<=min(a*num,n);j++)
{
int l=lower_bound(d[c[j]].begin(),d[c[j]].end(),x)-d[c[j]].begin(),r=lower_bound(d[c[j]].begin(),d[c[j]].end(),y)-d[c[j]].begin(),t=r-l+1;
if(d[c[j]][r]!=y)t--;
if(t>mxx||(t==mxx&&mx>c[j]))mx=c[j],mxx=t;
}
a++;
}
if(y<min(b*num,n))
{
for(rg int j=(b-1)*num+1;j<=y;j++)
{
int l=lower_bound(d[c[j]].begin(),d[c[j]].end(),x)-d[c[j]].begin(),r=lower_bound(d[c[j]].begin(),d[c[j]].end(),y)-d[c[j]].begin(),t=r-l+1;
if(d[c[j]][r]!=y)t--;
if(t>mxx||(t==mxx&&mx>c[j]))mx=c[j],mxx=t;
}
b--;
}
if(mxx<g[a][b]||(mxx==g[a][b]&&mx>f[a][b]))mx=f[a][b],mxx=g[a][b];
printf("%d\n",ans=mp[mx]);
}
}
}