这道题强制在线,那么考虑在线算法
好像复杂度低的可以使用平衡树,但是我们这里使用分块算法 因为数据量不是特别大
因为是在前面加一个后面删一个,所以我们考虑使用双端队列来维护这个信息
这样修改的时候,可以把前面的块的末尾加到后面的块,这样每块的大小都不会发生改变
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=1e5+10; const int mod=1e9+7; int block; deque<int> q[330]; int a[N],cnt[330][N]; int n; void init(){ int i; for(i=1;i<=n;i++){ int pos=(i-1)/block+1; cnt[pos][a[i]]++; q[pos].push_back(a[i]); } } int main(){ ios::sync_with_stdio(false); cin>>n; block=sqrt(n); int i; for(i=1;i<=n;i++) cin>>a[i]; init(); int qu; cin>>qu; ll ans=0; while(qu--){ int opt,l,r,k; cin>>opt>>l>>r; l=((l+ans-1)%n)+1; r=((r+ans-1)%n)+1; if(l>r) swap(l,r); int idx1=(l-1)/block+1; int idx2=(r-1)/block+1; if(opt==1){ if(idx1==idx2){ int pos=l-(idx1-1)*block-1; int pos1=r-(idx1-1)*block-1; int x=q[idx1][pos1]; q[idx1].erase(q[idx1].begin()+pos1); q[idx1].insert(q[idx1].begin()+pos,x); } else{ for(i=idx1;i<idx2;){ int x=q[i].back(); q[i].pop_back(); cnt[i][x]--; i++; q[i].push_front(x); cnt[i][x]++; } int pos=r-(idx2-1)*block; int x=q[idx2][pos]; q[idx2].erase(q[idx2].begin()+pos),cnt[idx2][x]--; pos=l-(idx1-1)*block-1; q[idx1].insert(q[idx1].begin()+pos,x),cnt[idx1][x]++; } } else{ cin>>k; k=((k+ans-1)%n)+1; ans=0; if(idx1==idx2){ int pos=l-(idx1-1)*block-1; int pos1=r-(idx1-1)*block-1; for(i=pos;i<=pos1;i++){ if(q[idx1][i]==k){ ans++; } } } else{ int pos=l-(idx1-1)*block-1; int pos1=r-(idx2-1)*block-1; for(i=pos;i<q[idx1].size();i++){ if(q[idx1][i]==k) ans++; } for(i=0;i<=pos1;i++){ if(q[idx2][i]==k) ans++; } for(i=idx1+1;i<idx2;i++){ ans+=cnt[i][k]; } } cout<<ans<<endl; } } }View Code