分析:
块状链表,据说是一种基本不会考到的数据结构,但是好像是骗分的好方法
我们要怎么快速判断一个元素在链表中的哪个结点呢?
记sum表示结点大小的前缀和
我们用lower_bound查找sum中大于等于pos(查找位置的)
的第一个sum[p]
那么结点p就是pos应该插入到的结点
tip
这道题比较简单
链表的形式不是特别明显
因为一开始我们规定了每一个结点的size上限:sqrt(N)
所以在初始化的时候就划入了不同结点
因为只有单点插入操作,所以就不牵扯到分裂操作
初始字符串的大小:1e6
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1000010;
char s[N];
int n,m,num,pos,sum[2005];
struct node{
int size; //每个块的大小
char data[2002];
void push(char c)
{
size++;
data[size]=c;
}
void insert(int pos,char c) //暴力插入
{
for (int i=size+1;i>pos;i--)
data[i]=data[i-1];
data[pos]=c;
size++;
}
char get(int pos) //数组的提取
{
return data[pos];
}
};
node block[2010];
void Sum() //链表总长度
{
for (int i=1;i<=num;i++)
sum[i]=sum[i-1]+block[i].size;
}
void init()
{
num=sqrt((double)n+m)+1; //结点数
for (int i=0;i<n;i++)
block[i/num+1].push(s[i]);
Sum();
}
void add(int pos,char c)
{
int p=lower_bound(sum+1,sum+1+num,pos)-sum; //在的结点编号
block[p].insert(pos-sum[p-1],c);
Sum();
}
char ask(int pos)
{
int p=lower_bound(sum+1,sum+1+num,pos)-sum;
return block[p].get(pos-sum[p-1]);
}
int main()
{
scanf("%s",s);
n=strlen(s);
scanf("%d",&m);
init();
char opt[10],c[10];
for (int i=1;i<=m;i++)
{
scanf("%s",&opt);
if (opt[0]=='Q')
{
scanf("%d",&pos);
printf("%c\n",ask(pos));
}
else
{
scanf("%s%d",c,&pos);
add(pos,c[0]);
}
}
return 0;
}