蒲公英
作者:互联网
题意
求一段区间的众数,相同次数选小的那个。强制在线
对于 100% 的数据,保证1≤n≤40000,1≤m≤50000,1≤ai≤109。
题解
如果不要求强制在线就可以用回滚莫队解决。
那在线怎么做?还是考虑分块,预处理出第i块到第j块这段区间的桶和众数。
对于一段区间查询[l,r],分成3部分,(l,L)和(R,r)两个不足一整段的部分和中间的整块区间[L,R]。
每次查询就在预处理的[pos[L],pos[R]]基础上统计答案,最后再撤销即可。
算法事件复杂度(NS2+MN/S),空间复杂度(NS2),设N,M为相同数量级,那么S=N1/3时复杂度在(N5/3),S为块的个数
注意离散化
#include<bits/stdc++.h> using namespace std; const int maxn=40005; int n,m; int a[maxn],b[maxn]; int size,pos[maxn]; int cnt[40][40][maxn],nowans[40][40];//第i块到第j块的各数的个数和众数 int ans; template<class T>inline void read(T &x){ x=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} } void nice(int i,int j,int cx[],int &nowans){//预处理,nowans必须加&,否则不能改变 int l=size*(i-1)+1,r=min(n,size*j); for(int k=l;k<=r;k++){ cx[a[k]]++; if(cx[nowans]<cx[a[k]]) nowans=a[k]; else if(cx[nowans]==cx[a[k]]&&a[k]<nowans) nowans=a[k]; } } int good[maxn]; void sto324(int l,int r){//暴力 for(int i=l;i<=r;i++) good[a[i]]=0; for(int i=l;i<=r;i++){ good[a[i]]++; if(good[a[i]]>good[ans]) ans=a[i]; else if(good[a[i]]==good[ans]&&a[i]<ans) ans=a[i]; } return ; } void get_it(int l,int r){ ans=0; if(pos[r]-pos[l]<=1){sto324(l,r);return ;}//在同一块或相邻块,保证[L,R]成立 int L=pos[l]+1,R=pos[r]-1; ans=nowans[L][R]; for(int i=l;pos[i]==pos[l];i++){ cnt[L][R][a[i]]++; if(cnt[L][R][a[i]]>cnt[L][R][ans]) ans=a[i]; else if(cnt[L][R][a[i]]==cnt[L][R][ans]&&a[i]<ans) ans=a[i]; } for(int i=r;pos[i]==pos[r];i--){ cnt[L][R][a[i]]++; if(cnt[L][R][a[i]]>cnt[L][R][ans]) ans=a[i]; else if(cnt[L][R][a[i]]==cnt[L][R][ans]&&a[i]<ans) ans=a[i]; } for(int i=l;pos[i]==pos[l];i++) cnt[L][R][a[i]]--; for(int i=r;pos[i]==pos[r];i--) cnt[L][R][a[i]]--;//撤销操作 } int main(){ read(n);read(m); size=(int)pow(n,2.0/3); for(int i=1;i<=n;i++){ read(a[i]); b[i]=a[i]; pos[i]=(i-1)/size+1; } sort(b+1,b+n+1); int tot=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+tot+1,a[i])-b; for(int i=1;i<=pos[n];i++) for(int j=i;j<=pos[n];j++) nice(i,j,cnt[i][j],nowans[i][j]); for(int i=1;i<=m;i++){ int l,r; read(l);read(r); l=(l+b[ans]-1)%n+1; r=(r+b[ans]-1)%n+1; if(l>r) swap(l,r); //printf("%d %d\n",l,r); get_it(l,r); printf("%d\n",b[ans]); } return 0; }View Code
标签:cnt,ch,int,40,maxn,ans,蒲公英 来源: https://www.cnblogs.com/sto324/p/11240104.html