典型的分块例题,和区间众数差不多,本题必须用不带log的做法,因此我们考虑前缀和,因为显然的是,区间中某数的个数都可以用前缀和表示
我们设计一个前缀和表示前i块数j的个数是多少个
然后设计一个d数组表示i-j块之间的答案是多少,这就是分块的基本思想,大块直接维护答案,小块暴力枚举
之后在暴力枚举的时候,通过奇偶来判断答案
我的写法常数有点大,估计是多了一个没有必要的离散化。吸吸氧气就能过了
#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=1e5+10; const int mod=1e9+7; int d[320][320]; int s[320][100010]; int cnt[N]; int n,c,m; int a[N]; vector<int> b; int block; void init(){ block=sqrt(n); int l,r; for(l=1;l<=n;l++){ if((l-1)%block==0){ for(r=1;r<=(int)b.size();r++){ s[(l-1)/block+1][r]=s[(l-1)/block][r]; } } s[(l-1)/block+1][a[l]]++; } for(l=1;l<=n;l+=block){ memset(cnt,0,sizeof cnt); int res=0; for(r=l;r<=n;r++){ cnt[a[r]]++; if(cnt[a[r]]%2==0) res++; if(cnt[a[r]]%2&&cnt[a[r]]>1) res--; if(r%block==0||r==n) d[(l-1)/block+1][(r-1)/block+1]=res; } } for(int i=1;i<=n;i++) cnt[a[i]]=0; /*for(int i=1;i<=(n-1)/block+1;i++){ for(int j=i;j<=(n-1)/block+1;j++) cout<<d[i][j]<<" "; cout<<endl; }*/ } int cal(int l,int r,int x){ return s[r][x]-s[l][x]; } int query(int l,int r){ int idx1=(l-1)/block+1; int idx2=(r-1)/block+1; int ans=0; int i,j; if(idx1+1<idx2) ans=d[idx1+1][idx2-1]; if(idx1==idx2){ for(i=l;i<=r;i++){ if(cnt[a[i]]){ if(cnt[a[i]]&1) ans++; else ans--; } cnt[a[i]]++; } for(i=l;i<=r;i++) cnt[a[i]]=0; } else{ for(i=l;i<=idx1*block;i++){ if(!cnt[a[i]]) cnt[a[i]]=cal(idx1,idx2-1,a[i]); if(cnt[a[i]]){ if(cnt[a[i]]&1) ans++; else ans--; } cnt[a[i]]++; } for(i=(idx2-1)*block+1;i<=r;i++){ if(!cnt[a[i]]) cnt[a[i]]=cal(idx1,idx2-1,a[i]); if(cnt[a[i]]){ if(cnt[a[i]]&1) ans++; else ans--; } cnt[a[i]]++; } for(i=l;i<=idx1*block;i++) cnt[a[i]]=0; for(i=(idx2-1)*block+1;i<=r;i++) cnt[a[i]]=0; } return ans; } int main(){ cin>>n>>c>>m; int i; for(i=1;i<=n;i++){ scanf("%d",&a[i]); b.push_back(a[i]); } sort(b.begin(),b.end()); b.erase(unique(b.begin(),b.end()),b.end()); for(i=1;i<=n;i++){ a[i]=lower_bound(b.begin(),b.end(),a[i])-b.begin()+1; } init(); int last=0; int l,r; while(m--){ scanf("%d%d",&l,&r); l=(l+last)%n+1; r=(r+last)%n+1; if(l>r) swap(l,r); last=query(l,r); printf("%d ",last); } return 0; }