分块
分块分的形式灵活,每一个块里可以是很多东西
需要灵活维护位置的移动,用双端队列就可以搞定。但是细节比较多,【1】同一块和多块的查询/修改是要分开讨论【2】注意及时pop掉元素
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define rint register int
#define ll long long
#define ull unsigned long long
#define chu printf
inline ll re()
{
ll x=0,h=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')h=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*h;
}
const int N=1e5+10,M=sqrt(1e5)+10;
int n,a[N],block,dcc,cnt[M][N],L[M],R[M],bl[N];
deque<int>code[M],tmp;//妙妙妙!
int q,lastans;
inline void change(int l,int r)
{
// chu("change:%d-%d\n",l,r);
int lc=bl[l],rc=bl[r];
int out,cd;
if(lc==rc)
{
out=r-L[lc]+1;
while(out)
{
tmp.push_back(code[lc].front());
code[lc].pop_front();
--out;
}
cd=tmp.back();tmp.pop_back();
out=r-l;
while(out)
{
code[lc].push_front(tmp.back());
tmp.pop_back();
--out;
}
code[lc].push_front(cd);
while(tmp.size())
{
code[lc].push_front(tmp.back());
tmp.pop_back();
}
return;
}
cd=code[lc].back();
code[lc].pop_back();
cnt[lc][cd]--;
//chu("out:%d\n",cd);
for(rint i=lc+1;i<rc;++i)
{
code[i].push_front(cd);
cnt[i][cd]++;
cd=code[i].back();
code[i].pop_back();
cnt[i][cd]--;
}
code[rc].push_front(cd);
cnt[rc][cd]++;
out=r-L[rc]+1;
while(out)
{
tmp.push_back(code[rc].front());
code[rc].pop_front();
out--;
}
cd=code[rc].front();code[rc].pop_front();
cnt[rc][cd]--;
while(tmp.size())
{
code[rc].push_front(tmp.back());
tmp.pop_back();
}
out=R[lc]-l;
while(out)
{
tmp.push_back(code[lc].back());
code[lc].pop_back();
out--;
}
code[lc].push_back(cd);
cnt[lc][cd]++;
while(tmp.size())
{
code[lc].push_back(tmp.back());
tmp.pop_back();
}
}
inline int query(int l,int r,int cor)
{
int lc=bl[l],rc=bl[r];
int ans=0;
if(lc==rc)
{
int lp=l-L[lc],rp=r-L[lc];
for(rint i=lp;i<=rp;++i)ans+=(code[lc][i]==cor);
return ans;
}
int out=R[lc]-l+1;
while(out)
{
tmp.push_back(code[lc].back());
ans+=(cor==code[lc].back());
code[lc].pop_back();
--out;
}
while(tmp.size())
{
code[lc].push_back(tmp.back());
tmp.pop_back();
}
for(rint i=lc+1;i<rc;++i)ans+=cnt[i][cor];
out=r-L[rc]+1;
while(out)
{
tmp.push_back(code[rc].front());
ans+=(cor==code[rc].front());
code[rc].pop_front();
--out;
}
while(tmp.size())
{
code[rc].push_front(tmp.back());
tmp.pop_back();
}
return ans;
}
int main()
{
// freopen("1.in","r",stdin);
// freopen("2.out","w",stdout);
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
n=re();
for(rint i=1;i<=n;++i)a[i]=re();
block=sqrt(n);
dcc=n/block;
for(rint i=1;i<=dcc;++i)
L[i]=R[i-1]+1,R[i]=L[i]+block-1;
R[dcc]=n;
for(rint i=1;i<=dcc;++i)
{
for(rint j=L[i];j<=R[i];++j)bl[j]=i,++cnt[i][a[j]],code[i].push_back(a[j]);//,chu("bl[%d]:%d\n",j,i);//放颜色
}
q=re();
for(rint i=1;i<=q;++i)
{
// chu("new ronud\n");
int opt=re();
if(opt==1)
{
int l=re(),r=re();
l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1;
if(l>r)swap(l,r);
change(l,r);
}
else
{
int l=re(),r=re(),x=re();
l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1;
x=(x+lastans-1)%n+1;
if(l>r)swap(l,r);
// chu("he query:%d--%d\n",l,r);
chu("%d\n",lastans=query(l,r,x));
}
// for(rint j=1;j<=dcc;++j)
// {
// for(rint ele:code[j])chu("%d ",ele);
// }
// chu("\n");
}
return 0;
}
/*
7
7 6 6 3 2 2 1
6
1 1 1
1 2 6
1 1 3
1 3 5
1 1 6
2 3 7 3
*/