典型的平衡树操作了
每一个块用动态数组维护,每次插入是找到对应的块
然后直接插,这个元素之后的数字都平移一位,如果用链表的话更好
如果块的大小不平衡了,要进行重新分块的 操作
每根号n次插入后,重新把数列平均分一下块
重构需要的复杂度为O(n),重构的次数为√n
也可以改变重构的方式,在某个块过大时重构,或者直接把这个过大的块一分为二
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 const int maxn=100005; 7 long long read() 8 { 9 long long x=0,f=1;char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 12 return x*f; 13 } 14 int n,blo,top,m; 15 int v[maxn],st[maxn]; 16 vector<int> ve[1005]; 17 pair<int,int> query(int b) 18 { 19 int x=1; 20 while(b>ve[x].size()) b-=ve[x].size(),x++; 21 return make_pair(x,b-1); //返回哪个块儿的第几个 22 } 23 void rebuild() 24 { 25 top=0; 26 for(int i=1;i<=m;i++) 27 { 28 for(vector<int>::iterator j=ve[i].begin();j!=ve[i].end();j++) 29 st[++top]=*j; 30 ve[i].clear(); 31 } 32 int blo2=sqrt(top); 33 for(int i=1;i<=top;i++) 34 ve[(i-1)/blo2+1].push_back(st[i]); 35 m=(top-1)/blo2+1; 36 } 37 void insert(int a,int b) //在a的前面插入b 38 { 39 pair<int,int> t=query(a); 40 ve[t.first].insert(ve[t.first].begin()+t.second,b); 41 if(ve[t.first].size()>20*blo) rebuild(); 42 } 43 int main() 44 { 45 n=read();blo=sqrt(n); 46 for(int i=1;i<=n;i++) v[i]=read(); 47 for(int i=1;i<=n;i++) 48 ve[(i-1)/blo+1].push_back(v[i]); 49 m=(n-1)/blo+1; 50 for(int i=1;i<=n;i++) 51 { 52 int f=read(),a=read(),b=read(),c=read(); 53 if(f==0) insert(a,b); 54 if(f==1) 55 { 56 pair<int,int> t=query(b); 57 printf("%d ",ve[t.first][t.second]); 58 } 59 } 60 return 0; 61 }