CF445D. Serega and Fun分块
link:https://codeforces.com/contest/455/problem/D
不知道为什么在我收藏题目里面…翻出来顺便做了一下…
题意:给一个序列 \(a\),操作1是shuffle一段区间 \([l,r]\),操作2是查询区间 \([l,r]\) 有多少值恰好为 \(k\),\(1\leq n,q\leq 10^5\)
不寻常的操作搭配不寻常的询问方式,有可能是正常的数据结构吗?(据说Splay好像也可以做~)
于是考虑分块…
然后就差不多做完了,双端队列维护一下(昨天才知道 deque
既可以支持两头增删,也可以下标访问,对这些STL用的还是太不熟练了QAQ)
实现 : 昨天犯了个非常傻逼的错误,对于他同一个块内的修改操作(循环右移)的时候,把一个很简单的 for(i=r;i>=l+1;i--)v[i]=v[i-1];
写成了 for(int i=l+1;i<=r;i++)v[i]=v[i-1];
然后静查了很久都没查出来…
看来平常还是要多注意静查代码,每个小细节都要过一遍(当时觉得应该是其他一些写得更繁琐的地方更可能出错,完全没看这一句非常简单并且就一行的代码,属于是犯了明察秋毫但不见舆薪的毛病了…)
// LUOGU_RID: 154191756
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int N=1e5+5;
const int C=405;
int n,q,T,lst,bl[N],L[C],R[C],f[C][N];
vector<deque<int>> v;
int main(){
fastio;
cin>>n;
int S=sqrt(n),T=(n-1)/S+1;
v=vector<deque<int>>(T+1);
rep(i,1,n){
int a;cin>>a;
bl[i]=(i-1)/S+1;
v[bl[i]].push_back(a);
f[bl[i]][a]++;
}
rep(i,1,T)L[i]=R[i-1]+1,R[i]=min(S*i,n);
cin>>q;
while(q--){
int op,l,r;
cin>>op>>l>>r;
l=(l+lst-1)%n+1;
r=(r+lst-1)%n+1;
if(l>r)swap(l,r);
if(op==1){
stack<int> S;
if(bl[l]==bl[r]){
int D=L[bl[l]],val=v[bl[l]][r-D];
for(int i=r;i>=l+1;i--)v[bl[l]][i-D]=v[bl[l]][i-1-D];
v[bl[l]][l-D]=val;
}else{
//delete block of r
rep(i,0,r-L[bl[r]]-1){
S.push(v[bl[r]].front());
v[bl[r]].pop_front();
}
int val=v[bl[r]].front();
v[bl[r]].pop_front();
while(!S.empty()){
v[bl[r]].push_front(S.top());
S.pop();
}
f[bl[r]][val]--;
//insert block of l
rep(i,0,l-L[bl[l]]-1){
S.push(v[bl[l]].front());
v[bl[l]].pop_front();
}
v[bl[l]].push_front(val);
while(!S.empty()){
v[bl[l]].push_front(S.top());
S.pop();
}
f[bl[l]][val]++;
//shuffle
rep(i,bl[l],bl[r]-1){
auto x=v[i].back();
f[i][x]--;
f[i+1][x]++;
v[i].pop_back();
v[i+1].push_front(x);
}
}
}else{
int ans=0,k;
cin>>k;
k=(k+lst-1)%n+1;
if(bl[l]==bl[r]){
rep(i,l,r)if(v[bl[l]][i-L[bl[l]]]==k)ans++;
}else{
rep(i,bl[l]+1,bl[r]-1)ans+=f[i][k];
rep(i,l,R[bl[l]])if(v[bl[l]][i-L[bl[l]]]==k)ans++;
rep(i,L[bl[r]],r)if(v[bl[r]][i-L[bl[r]]]==k)ans++;
}
cout<<ans<<endl;
lst=ans;
}
}
return 0;
}