Test Problem:Play With Array:分塊+鏈表

題目大意:

有一個長度爲n的數列a1-an

支持兩個操作:

1 l r 把a[r]放到a[l]的前面a[l]-a[r-1]順次後移

2 l r k詢問a[l]-a[r]中k的個數

n,m<=100000,1<=l,r,k,a[i]<=n

題解:

每個塊內記錄sum[i]表示i出現的次數,同時維護一個鏈表,鏈表中每個元素的下標全局使用,但是每個塊內的鏈表只維護塊內元素

換句話說叫“跳錶"?同學說的說錯了沒我事QAQ

然後就是在塊內改鏈表了,各種邊界醉了

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100010;
const int maxb=440;
int a[maxn],n,pos[maxn],cnt=0,m;
int mark1,mark3,mark4;
struct Nodes{int pre,nxt,v;}t[maxn];
struct Block{
	int st,fi,sum[maxn],be,ed;
	void init(){
		be=st; ed=fi;
		for (int i=st;i<=fi;++i){
			t[i].pre=i-1; t[i].nxt=i+1;
			t[i].v=a[i]; sum[a[i]]++;
		}
		t[be].pre=0; t[ed].nxt=0;
	}
}b[maxb];

int read(){
	int ret=0;char ch=getchar();
	while(ch<'!') ch=getchar();
	while(ch>'!') ret=ret*10+ch-'0',ch=getchar();
	return ret;
}

void mov1(int l,int r,int L,int R){
	if (r==b[R].ed) b[R].ed=t[r].pre;
	if (l==b[L].be) b[L].be=r;
    t[t[r].pre].nxt=t[r].nxt;
	t[t[r].nxt].pre=t[r].pre;
	t[r].nxt=l; t[r].pre=t[l].pre;
	t[t[l].pre].nxt=r; t[l].pre=r;
}

void mov2(int l,int r,int L,int R){
	if (mark1) b[L].be=r;
	if (mark3) b[R].be=t[r].nxt;
	if (mark4) b[R].ed=t[r].pre;
	
    t[t[r].pre].nxt=t[r].nxt;
	t[t[r].nxt].pre=t[r].pre;
	t[r].nxt=l; t[r].pre=t[l].pre;
	t[t[l].pre].nxt=r; t[l].pre=r;
}

void delw(int id){
	int now=b[id].ed,tmp=t[now].pre;
	b[id].sum[t[now].v]--;
	b[id].ed=tmp; t[tmp].nxt=0;
	
	tmp=b[id+1].be; t[tmp].pre=now;
	b[id+1].sum[t[now].v]++;
	b[id+1].be=now;
	t[now].pre=0; t[now].nxt=tmp;
}

int main(){
	n=read();
	int blo=sqrt(n);  blo=440;
	for (int i=1;i<=n;++i) a[i]=read();
	for (int i=1;i<=n;++i){
		pos[i]=(i-1)/blo+1;
		if (pos[i]!=pos[i-1]) b[cnt].fi=i-1,b[++cnt].st=i;
	}b[cnt].fi=n;
	for (int i=1;i<=cnt;++i) b[i].init();
	m=read();
	for (int i=1;i<=m;++i){
		int opt,x,y,l,r; opt=read();
		if (opt==1){
			x=read(); y=read();
			if (x==y) continue;
			int L=pos[x],R=pos[y],num=b[L-1].fi;
			for (int j=b[L].be;j;j=t[j].nxt){num++;if(num==x)l=j;}
			num=b[R-1].fi;
			for (int j=b[R].be;j;j=t[j].nxt){num++;if(num==y)r=j;}
			if (L==R) mov1(l,r,L,R);
			else{
				b[L].sum[t[r].v]++;
				b[R].sum[t[r].v]--;
				mark1=mark3=mark4=0;
				if (l==b[L].be) mark1++;
				if (r==b[R].be) mark3++;
				if (r==b[R].ed) mark4++;
				mov2(l,r,L,R); delw(L);
				for (int j=L+1;j<R;++j) delw(j);
			}
		}else if (opt==2){
			int k; x=read(); y=read(); k=read();
			int L=pos[x],R=pos[y];
			int ans=0;
			if (L==R){
				int num=b[L-1].fi;
				for (int j=b[L].be;j;j=t[j].nxt){
					num++;
					if (num>=x&&num<=y) ans+=(t[j].v==k);
					if (num>y) break;
				}
				printf("%d\n",ans);
			}else{
				int num=b[L].fi+1;
				for (int i=L+1;i<R;++i) ans+=b[i].sum[k];
				for (int j=b[L].ed;j;j=t[j].pre){
					ans+=(t[j].v==k);
					num--; if(num==x)break;
				}
				num=b[R-1].fi;
				for (int j=b[R].be;j;j=t[j].nxt){
					ans+=(t[j].v==k);
					num++; if(num==y)break;
				}
				printf("%d\n",ans);
			}
		}
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章