简要题意:
一个序列,请你支持
- 将 a r a_r ar 挪到 a l − 1 a_{l-1} al−1 和 a l a_l al 之间,重新标号。
- 询问在当前序列的第 l l l 到第 r r r 个位置, k k k 出现了多少次。
块链裸题,写就完事,好写的一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;}