【校內模擬】play in array(塊狀鏈表)

簡要題意:

一個序列,請你支持

  1. ara_r 挪到 al1a_{l-1}ala_l 之間,重新標號。
  2. 詢問在當前序列的第 ll 到第 rr 個位置,kk 出現了多少次。

塊鏈裸題,寫就完事,好寫的一B。

順便,std::list::size() 這個函數差點又把我坑慘了。

至於到底問題在哪裏:here


代碼:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const

namespace IO{

inline char gc(){
	static cs int Rlen=1<<22|1;static char buf[Rlen],*p1,*p2;
	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}template<typename T>T get_integer(){
	char c;bool f=false;while(!isdigit(c=gc()))f=c=='-';T x=c^48;
	while(isdigit(c=gc()))x=((x+(x<<2))<<1)+(c^48);return f?-x:x;
}inline int gi(){return get_integer<int>();}

char obuf[20000007],*oh=obuf,ch[23];
template<typename T>void print(T a,char c){
	if(a<0)*oh++='-',a=-a;int tl=0;
	do ch[++tl]=a%10;while(a/=10);
	while(tl)*oh++=ch[tl--]^48;*oh++=c;
}struct obuf_flusher{~obuf_flusher(){fwrite(obuf,1,oh-obuf,stdout);}}Flusher;

}using namespace IO;

using std::cerr;
using std::cout;

cs int N=1e5+7;

int n,m,a[N];

struct Block{
	std::deque<int> L;
	std::vector<int> sm;
	Block():sm(n){}
};

std::list<Block> bl;
typedef std::list<Block>::iterator btr;
typedef std::deque<int>::iterator itr;
int bct,bsz;

void build(){
	bct=std::floor(std::sqrt(n)+1);
	bsz=std::ceil((double)n/bct);
	bl.resize(bct);btr t=bl.begin();
	for(int re i=0,j=0;i<bct;++i,++t)
		for(int re k=0;k<=bsz&&j<n;++k,++j)
			t->sm[a[j]]++,t->L.push_back(a[j]);
}

int erase(size_t p){
	for(btr t=bl.begin();t!=bl.end();++t)
		if(p<t->L.size()){
			itr i=t->L.begin()+p;int vl=*i;
			t->sm[vl]--;t->L.erase(i);
			return vl;
		}else p-=t->L.size();
	assert(0);return -1;
}

void ins(size_t p,int vl){
	for(btr t=bl.begin();t!=bl.end();++t)
		if(p<t->L.size()){
			itr i=t->L.begin()+p;
			++t->sm[vl];t->L.insert(i,vl);return ;
		}else p-=t->L.size();
	assert(0);
}

int query(int p,int vl){
	if(p<0)return 0;int res=0;
	for(btr t=bl.begin();t!=bl.end();++t)
		if(p<(int)t->L.size()){
			for(int re j=0;j<=p;++j)
				res+=t->L[j]==vl;
			break;
		}else 
			p-=t->L.size(),res+=t->sm[vl];
	return res;
}

void merge(btr t){
	btr h=t;++t;if(t==bl.end())return;
	for(itr i=t->L.begin();i!=t->L.end();++i)
		h->L.push_back(*i),++h->sm[*i];
	bl.erase(t);
}

void split(btr t){
	btr h=bl.insert(t,Block());
	int lim=t->L.size()/2;
	for(int re i=0;i<lim;++i){
		int vl=t->L.front();
		t->L.pop_front(),t->sm[vl]--;
		h->L.push_back(vl),h->sm[vl]++;
	}
}

void maintain(){
	for(btr t=bl.begin();t!=bl.end();++t)
		if((int)t->L.size()<=bsz/2)merge(t);
		else if((int)t->L.size()>=bsz*2)split(t);
}

void Main(){n=gi();
	for(int re i=0;i<n;++i)a[i]=gi()-1;
	build();m=gi();
	while(m--){
		switch(gi()){
			case 1:{
				int l=gi()-1,r=gi()-1;
				int x=erase(r);
				ins(l,x);maintain();
				break;
			}
			case 2:{
				int l=gi()-1,r=gi()-1,k=gi()-1;
				print(query(r,k)-query(l-1,k),'\n');
				break;
			}
		}
	}
}

inline void file(){
#ifdef zxyoi
	freopen("array.in","r",stdin);
#else
#ifndef ONLINE_JUDGE
	freopen("array.in","r",stdin);
	freopen("array.out","w",stdout);
#endif
#endif
}signed main(){file();Main();return 0;}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章