先来看一道题~
给一个字符串,长度不超过 106,有两种操作:
1. 在第 i 个字符的前面添加一个字符 ch
2. 查询第 k 个位置是什么字符
操作的总数不超过 2000
多种数据结构可解.
而我们选择用数组与链表的结合物求解——
块状链表 登登登登~!
先贴代码(实现并不简洁啊..怎么又开启抄代码模式了呢,sigh)
const int N=2000,M=(int)1e6+10;//每块大小阈值
struct node{
char s[N];
int next,siz;
void init(){
mec(s,0);
next=-1;siz=0;
}
}List[N];
int head,tot,q;
char str[M],ch[5];
void Split(int id)
{
List[tot].init();
for(int i=N/2;i<N;i++){
List[tot].s[i-N/2]=List[id].s[i];
List[tot].siz++;
List[id].s[i]=0;
List[id].siz--;
}
List[tot].next=List[id].next;
List[id].next=tot++;
}
void init(char *str)
{
head=tot=0;
List[tot++].init();
for(int i=0,cur=head;str[i];cur=List[cur].next){
for(int j=0;j<N&&str[i];i++,j++){//j<N
List[cur].s[j]=str[i];
List[cur].siz++;
}
if(str[i]){
List[tot].init();
List[cur].next=tot++;
}
}
for(int cur=head;cur!=-1;cur=List[cur].next)
if(List[cur].siz==N) Split(cur);
}
void Insert(int pos,char val)
{
int cur=head;
while(pos>List[cur].siz && List[cur].next!=-1)
pos-=List[cur].siz,cur=List[cur].next;
if(pos>=List[cur].siz) List[cur].s[List[cur].siz]=val;//添加到末尾
else{//此时,pos是块内的位置
for(int i=List[cur].siz;i>pos;i--) List[cur].s[i]=List[cur].s[i-1];
List[cur].s[pos]=val;//注意下标从0开始
}
List[cur].siz++;
if(List[cur].siz==N) Split(cur);
}
char Find(int pos)
{
int cur=head;
while(pos>List[cur].siz)
pos-=List[cur].siz,cur=List[cur].next;//顺次查找即可
return List[cur].s[pos-1];
}//每块中元素编号0~siz-1
int main()
{
// freopen(".in","r",stdin);
scanf("%s",str);
init(str);
scanf("%d",&q);
while(q--){
char opt[5];
int pos;
scanf("%s",opt);
if(opt[0]=='I'){
scanf("%s%d",ch,&pos);
Insert(pos-1,ch[0]);
}
else{
scanf("%d",&pos);
printf("%c\n",Find(pos));
}
}
return 0;
}
评论 (0)