[CF455D] Serega and Fun 题解

不知道大家做没做过数列分块基础9题?

插入删除操作可以用链表,线段树等数据结构都不好维护,考虑分块。对于修改操作,暴力重构受影响块的链表,发现除首尾块外,其他块都可以看作是区间左移一位,所以加头删尾即可。

每个块开一个数组(绝对不能是 \((un\_)map\),不然你会和我一样死的很诡异),表示这个块这种颜色有几个,统计就是很裸的了。

时间复杂度 \(O(n\sqrt n)\)

//分块,用unmap记录每个块的答案会死 
//块内每个数用链表记录
//时间复杂度 O(nsqrt(n)) 
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5,M=505;
int n,q,a[N],ls[N],nx[N];
int kl,num,fst[M],emd[M];
int mp[M][N];
void mk(int x){
	fst[x]=x*kl-kl+1;
	emd[x]=min(n,x*kl);
	mp[x][a[emd[x]]]++;
	for(int i=fst[x];i<min(x*kl,n);i++)
		ls[i+1]=i,nx[i]=i+1,mp[x][a[i]]++;
}void change(int l,int r){
	int fs=(l-1)/kl+1;
	int fn=l-fs*kl+kl;
	int ed=(r-1)/kl+1;
	int en=r-ed*kl+kl;
	int x=fst[fs],y=fst[ed];
	for(int i=1;i<fn;i++) x=nx[x];
	for(int i=1;i<en;i++) y=nx[y];
	if(fst[ed]==y) fst[ed]=nx[y];
	if(emd[ed]==y) emd[ed]=ls[y];
	ls[nx[y]]=ls[y];nx[ls[y]]=nx[y];
	nx[ls[x]]=y;ls[y]=ls[x];ls[x]=y;nx[y]=x;
	if(fst[fs]==x) fst[fs]=y;
	if(fs==ed) return;
	int z=emd[fs],w=fst[fs+1];
	nx[ls[z]]=0;emd[fs]=ls[z];
	nx[ls[z]]=0;ls[z]=0;
	nx[z]=w;ls[w]=z;fst[fs+1]=z;
	mp[fs][a[z]]--;mp[fs][a[y]]++;
	mp[fs+1][a[z]]++;mp[ed][a[y]]--;
	for(int i=fs+1;i<ed;i++){
		x=emd[i];y=fst[i+1];
		mp[i][a[x]]--;mp[i+1][a[x]]++;
		nx[ls[x]]=0;emd[i]=ls[x];
		nx[ls[x]]=0;ls[x]=0;
		nx[x]=y;ls[y]=x;fst[i+1]=x;
	}
}int ans(int l,int r,int c){
	int re=0;
	int fs=(l-1)/kl+1;
	int fn=l-fs*kl+kl;
	int ed=(r-1)/kl+1;
	int en=r-ed*kl+kl;
	int x=fst[fs],y=fst[ed];
	for(int i=1;i<fn;i++) x=nx[x];
	if(fs==ed){
		for(int i=fn;i<=en;i++)
			re+=(c==a[x]),x=nx[x];
		return re;
	}for(int i=fn;i<=kl;i++)
		re+=(c==a[x]),x=nx[x];
    for(int i=1;i<=en;i++)
		re+=(c==a[y]),y=nx[y];
	for(int i=fs+1;i<ed;i++) re+=mp[i][c];
	return re;
}int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;kl=sqrt(n);
	num=(n-1)/kl+1;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=num;i++) mk(i);
	cin>>q;int lans=0;
	while(q--){
		int o,l,r,x;
		cin>>o>>l>>r;
		l=(l+lans-1)%n+1;
		r=(r+lans-1)%n+1;
		if(l>r) swap(l,r); 
		if(o==2){
			cin>>x;
			x=(x+lans-1)%n+1;
			lans=ans(l,r,x);
			cout<<lans<<"\n";
		}else change(l,r);
	}return 0;
}
posted @ 2024-07-31 21:25  长安一片月_22  阅读(3)  评论(0编辑  收藏  举报