[F][5]bzoj 2724: [Violet 6]蒲公英

来源:互联网 发布:ubuntu和centos的区别 编辑:程序博客网 时间:2024/05/13 15:49

题目就不粘了…
题意:在线求区间众数


【分析】
在线区间众数的分块做法比较多,这里提供一个思路:

首先离散化一下比较方便。

最初可能会有一个想法,是不是众数只可能是完整的块的众数,或者不完整的块出现的数呢?显然很容易得出反例。

应该是完整的所有块的众数,和不完整块中出现的数。

所以我们可以预处理f(i,j)表示第 i 块到第 j 块的众数(枚举 i 开个桶扫一遍)。

桶的话可以用map!超好用!不MLE!棒极了!

那么只要能快速得出一个数在某个区间内出现次数即可,每次只要比较至多2√n+1个元素的出现次数,这题就解决了。

由于没有修改,只要离散化以后,给每个数 x 开个vector,按顺序存下 x 出现的位置,每次询问 x 时把区间的左右端点放进对应 vector 二分一下即可。

根据均值不等式,可以算出分块大小大概是√(n/logn)


【代码】

//bzoj 2724 [Violet 6]蒲公英#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<vector>#include<cmath>#include<map>#define M(a) memset(a,0,sizeof a)#define fo(i,j,k) for(i=j;i<=k;i++)using namespace std;const int mxn=50005;vector <int> f[mxn];int n,m,id,x;map <int,int> mp;int a[mxn],b[mxn],be[mxn],res[500][500];int lef[500],rig[500],vis[mxn];inline int read(){     int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline void yu(int s){    int i,j,k,sc,now,mx=0,tmp=0;    M(vis);    fo(i,lef[s],n)    {        int t=be[i];        vis[a[i]]++;        if(vis[a[i]]>mx || (vis[a[i]]==mx && b[a[i]]<b[tmp]))          mx=vis[a[i]],tmp=a[i];        if(i==rig[t])          res[s][t]=tmp;    }}inline int calc(int l,int r,int i){    return upper_bound(f[i].begin(),f[i].end(),r)-lower_bound(f[i].begin(),f[i].end(),l);}inline int query(int l,int r){    int i,j,L=be[l],R=be[r];    if(L==R || R==L+1)    {        M(vis);        int mx=0,tmp=0;        fo(i,l,r)        {          vis[a[i]]++;          if(vis[a[i]]>mx || (vis[a[i]]==mx && b[a[i]]<tmp))            tmp=b[a[i]],mx=vis[a[i]];      }      return tmp;    }    int k=res[L+1][R-1],mx=0,tmp=0,rlt,czy;    mx=calc(l,r,k),tmp=b[k];    fo(i,l,rig[L])    {      czy=calc(l,r,a[i]);      if(czy>mx || (czy==mx && b[a[i]]<tmp))        mx=czy,tmp=b[a[i]];    }    fo(i,lef[R],r)    {      czy=calc(l,r,a[i]);      if(czy>mx || (czy==mx && b[a[i]]<tmp))        mx=czy,tmp=b[a[i]];    }    return tmp;}int main(){    int i,j,k,l,r,ans=0;    n=read(),m=read();    fo(i,1,n)    {        a[i]=read();        if(!mp[a[i]])        {            mp[a[i]]=++id;            b[id]=a[i];        }        a[i]=mp[a[i]];        f[a[i]].push_back(i);           }    x=sqrt(n);    fo(i,1,x)    {        lef[i]=rig[i-1]+1;        rig[i]=i*x;    }    rig[x]=n;    fo(i,1,x)      fo(j,lef[i],rig[i])        be[j]=i;    fo(i,1,x) yu(i);    while(m--)    {        l=read(),r=read();        l=(l+ans-1)%n+1,r=(r+ans-1)%n+1;        if(l>r) swap(l,r);        ans=query(l,r);        printf("%d\n",ans);    }    return 0;} 
1 0
原创粉丝点击