BZOJ 2724 [Violet 6]蒲公英(分块)
题意
在线区间众数
思路
预处理出 f[i][j] 即从第 i 块到第 j 块的答案。
对于每个询问,中间的整块直接用预处理出的,两端的 sqrtn 级别的数暴力做,用二分查找它们出现的次数。
每次询问的复杂度是 sqrtn * logn 。
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdio> 5 #include<algorithm> 6 #include<vector> 7 using namespace std; 8 const int N=100010; 9 vector<int> vec[N]; 10 int n,m,a[N],b[N],block[N],ans,Block,L[N],R[N],cnt[N],top,stack[N],f[700][700],ff[700][700],tot; 11 int find1(int x,int y){ 12 int l=0;int r=vec[x].size()-1; 13 int tmp=-9999999; 14 while(l<=r){ 15 int mid=(l+r)>>1; 16 if(vec[x][mid]<=y){ 17 tmp=mid; 18 l=mid+1; 19 } 20 else r=mid-1; 21 } 22 return tmp; 23 } 24 int find2(int x,int y){ 25 int l=0;int r=vec[x].size()-1; 26 int tmp=9999999; 27 while(l<=r){ 28 int mid=(l+r)>>1; 29 if(vec[x][mid]>=y){ 30 tmp=mid; 31 r=mid-1; 32 } 33 else l=mid+1; 34 } 35 return tmp; 36 } 37 int main(){ 38 scanf("%d%d",&n,&m); 39 Block=sqrt(n); 40 for(int i=1;i<=n;i++){ 41 scanf("%d",&a[i]); 42 b[i]=a[i]; 43 } 44 sort(b+1,b+1+n); 45 int num=unique(b+1,b+1+n)-b-1; 46 for(int i=1;i<=n;i++){ 47 a[i]=lower_bound(b+1,b+1+num,a[i])-b; 48 block[i]=(i-1)/Block+1; 49 vec[a[i]].push_back(i); 50 if(!L[block[i]])L[block[i]]=i; 51 R[block[i]]=i; 52 } 53 for(int i=1;i<=block[n];i++){ 54 tot=0; 55 for(int j=L[i];j<=n;j++){ 56 cnt[a[j]]++; 57 if(tot<=cnt[a[j]]){ 58 if(cnt[a[j]]>tot)ans=b[a[j]]; 59 else ans=min(ans,b[a[j]]); 60 tot=cnt[a[j]]; 61 } 62 f[i][block[j]]=tot; 63 ff[i][block[j]]=ans; 64 } 65 for(int j=L[i];j<=n;j++){ 66 cnt[a[j]]=0; 67 } 68 } 69 ans=0; 70 for(int i=1;i<=m;i++){ 71 int l,r; 72 scanf("%d%d",&l,&r); 73 l=(l+ans-1)%n+1;r=(r+ans-1)%n+1; 74 if(l>r)swap(l,r); 75 if(block[l]+1>=block[r]){ 76 tot=0; 77 ans=0; 78 for(int i=l;i<=r;i++){ 79 cnt[a[i]]++; 80 if(tot<=cnt[a[i]]){ 81 if(cnt[a[i]]>tot)ans=b[a[i]]; 82 else ans=min(ans,b[a[i]]); 83 tot=cnt[a[i]]; 84 } 85 } 86 for(int i=l;i<=r;i++){ 87 cnt[a[i]]=0; 88 } 89 } 90 else{ 91 top=0; 92 tot=f[block[l]+1][block[r]-1]; 93 ans=ff[block[l]+1][block[r]-1]; 94 for(int i=l;i<=R[block[l]];i++){ 95 cnt[a[i]]++; 96 if(cnt[a[i]]==1)stack[++top]=a[i]; 97 } 98 for(int i=L[block[r]];i<=r;i++){ 99 cnt[a[i]]++; 100 if(cnt[a[i]]==1)stack[++top]=a[i]; 101 } 102 while(top){ 103 int z=stack[top--]; 104 int tmp=max(0,find1(z,L[block[r]]-1)-find2(z,R[block[l]]+1)+1); 105 if(tot<=cnt[z]+tmp){ 106 if(cnt[z]+tmp>tot)ans=b[z]; 107 else ans=min(ans,b[z]); 108 tot=cnt[z]+tmp; 109 } 110 cnt[z]=0; 111 } 112 } 113 printf("%d\n",ans); 114 } 115 return 0; 116 }