1. 程式人生 > WINDOWS開發 >AcWing249 蒲公英(分塊)

AcWing249 蒲公英(分塊)

一道經典的分塊例題,因為我們通過觀察可知,區間眾數要不就是中間所有塊上的答案,要不就是兩邊小塊上出現過的值

因此我們可以分塊處理,只要預處理塊與塊之間的答案即可,因為本題沒有修改操作

另外這題比較卡常,塊的大小要先算好,不過也有複雜度更低的演算法

技術分享圖片
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<string>
#include
<map> #include<vector> using namespace std; typedef long long ll; const int N=1e6+10; const int mod=1e9+7; vector<int> g[N]; int d[2001][2001]; int c[N],a[N]; int n,m; int block; int cnt[N]; void init(){ int l,r; for(l=1;l<=n;l+=block){ int res=0; memset(cnt,0,sizeof
cnt); for(r=l;r<=n;r++){ cnt[a[r]]++; if(cnt[a[r]]>cnt[res]||cnt[a[r]]==cnt[res]&&a[r]<res) res=a[r]; if(r%block==0||r==n) d[(l-1)/block+1][(r-1)/block+1]=res; } } } int find(int l,int r,int x){ return
upper_bound(g[x].begin(),g[x].end(),r)-lower_bound(g[x].begin(),l); } int query(int l,int r){ int ans = 0; int B=block; int idl = (l-1)/B+1,idr = (r-1)/B+1; if(idl+1 < idr) ans = d[idl+1][idr-1]; int n = find(l,r,ans),n1; if(idl==idr){ for(int i=l;i<=r;i++){ n1 = find(l,a[i]); if(n < n1 || n == n1 && a[i] < ans) ans = a[i],n = n1; } } else{ for(int i=l;i<=idl*B;i++){ n1 = find(l,n = n1; } for(int i=(idr-1)*B+1;i<=r;i++){ n1 = find(l,n = n1; } } return c[ans]; } int main(){ cin>>n>>m; int i; block=max(1,(int)(n/sqrt(m*log2(n)))); for(i=1;i<=n;i++){ scanf("%d",&a[i]); c[i]=a[i]; } sort(c+1,c+1+n); for(i=1;i<=n;i++){ a[i]=lower_bound(c+1,c+1+n,a[i])-c; g[a[i]].push_back(i); } init(); int last=0; int l,r; while(m--){ scanf("%d%d",&l,&r); l = (l+last-1)%n + 1; r = (r+last-1)%n + 1; if(l>r) swap(l,r); last=query(l,r); printf("%d\n",last); } }
View Code