bzoj 2724 蒲公英 分块
分块,预处理出每两个块范围内的众数,然后在暴力枚举块外的进行比较
那么怎么知道每一个数出现的次数呢?离散后,对于每一个数,维护一个动态数组就好了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<map> #define N 40005 using namespace std; int a[N],be[N],n,m,nn,cnt,val[N],c[N],tot; int num[N]; map<int,int> mm; vector <int > q[N]; int f[205][205]; int getnum(int l,int r,int x){ return upper_bound(q[x].begin(),q[x].end(),r)-lower_bound(q[x].begin(),q[x].end(),l); } int query(int l,int r){ int maxn=0,now=0; if(be[l]==be[r]){ for(int i=l;i<=r;i++){ int t=getnum(l,r,c[i]); if(t>maxn||(t==maxn&&a[i]<a[now])){ maxn=t; now=i; } } return a[now]; } now=f[be[l]+1][be[r]-1]; maxn=getnum(l,r,c[now]); for(int i=l;i<=be[l]*nn;i++){ int t=getnum(l,r,c[i]); if(t>maxn||(t==maxn&&a[i]<a[now])){ maxn=t; now=i;} } for(int i=(be[r]-1)*nn+1;i<=r;i++){ int t=getnum(l,r,c[i]); if(t>maxn||(t==maxn&&a[i]<a[now])){ maxn=t; now=i;} } return a[now]; } int main() { scanf("%d%d",&n,&m); nn=(int)sqrt(n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); if(!mm.count(a[i])) mm[a[i]]=++cnt; be[i]=(i-1)/nn+1; c[i]=mm[a[i]]; q[c[i]].push_back(i); } tot=be[n]; int maxn,now; for(int i=1;i<=tot;i++){ memset(num,0,sizeof(num)); maxn=0; now=0; for(int j=(i-1)*nn+1;j<=n;j++){ num[c[j]]++; if(num[c[j]]>maxn||(num[c[j]]==maxn&&a[j]<a[now])){ now=j; maxn=num[c[j]]; } f[i][be[j]]=now; } } int ans=0,l,r; while(m--){ scanf("%d%d",&l,&r); l=(l+ans-1+n)%n+1; r=(r+ans-1+n)%n+1; if(l>r) swap(l,r); ans=query(l,r); printf("%d\n",ans); } return 0; }
人生如梦亦如幻 朝如晨露暮如霞。