这个题目涉及到了块的重构,这里使用了(sqrt{n})次插入便重构的方法
讲重复的操作提出来做了函数
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
const int maxn=101000;
const int inf=0x7fffffff;
struct Point
{
int l;
int r;
int val;
};
struct Square
{
int begin;
int size;
};
Point base[maxn<<1];
Square squ[maxn>>2];
int tail,size,belong[maxn<<1];
int n,sum;
void input()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&base[i].val);
base[i].l=i-1;
base[i].r=i+1;
}
base[0].r=1;base[0].l=n;//0号位置是开头
base[n].r=inf;//inf是链表结束标志
sum=n+1;tail=n;//加一
return ;
}//输入
void init()
{
size=floor(sqrt(sum));
int now=size,Belong=0;
for(int i=0;i!=inf;i=base[i].r)
{
++now;
if(now==size+1)//达到了块的个数
{
now=1,++Belong;//下一个块
squ[Belong].begin=i;
squ[Belong].size=0;
}
belong[i]=Belong;
++squ[Belong].size;
}
return ;
}
void insert(int l,int r,int val)//在l,r中插入val
{
++squ[belong[l]].size;
base[++tail].val=val;
base[tail].l=l;
base[tail].r=r;
base[l].r=tail;
base[r].l=tail;
belong[tail]=belong[l];//从属于前一个块
return ;
}
int contain(int &pos)//返回从左往右数第pos个元素在哪一个块里,然后利用引用,讲pos变为在块中的第几个元素
{
int res=1;
while(pos>squ[res].size) pos-=squ[res++].size;
return res;
}
int position(int K,int pos)//第k个块的第pos个元素
{
int res=squ[K].begin,i=1;
while(i<pos)
{
res=base[res].r;
i++;
}
return res;//返回标号
}
void Insert(int pos,int val)
{
int from=contain(pos);
int which=position(from,pos);
insert(base[which].l,which,val);
return ;
}
void Ask(int pos)
{
int from=contain(pos);
int which=position(from,pos);
printf("%d
",base[which].val);
return ;
}
void solve()
{
int a,b,c,d,T=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
if(a==0) Insert(b+1,c),++T,++sum;
else Ask(c+1);
if(T==size) init(),T=0;
}
return ;
}
int main()
{
input();
init();
solve();
}