块状链表
- 数组来模拟链表
- 注意 块的编号和块中数组的下标
belong[]
保证编号不重复
belong[]
的作用其实相当于记录块的编号 当块 (消失or合并) 时,下一次生成的块就用上一次消失块的编号,首次初始化为不同的就行了- 避免块状链表退化,在删除或者插入后维护2端的块,根据块的大小来决定是 合并还是 割
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e3+10;
struct node {
int next,size;
char a[maxn << 1];
}b[maxn << 2];
int n,curpos,cnt,belong[maxn<<2];
char ss[5000000],s[50];
int addi() {
cnt++;
return belong[cnt];
}
void dele(int x) {
belong[cnt] = x;
cnt--;
}
void init() {
for (int i=1; i<(maxn<<2); ++i) belong[i] = i;
cnt = 1;
b[1].next = -1;
b[1].size = 0;
}
void add(int x,int y,int len,char c[]) {
if (y != -1) {
b[y].next = b[x].next;
b[y].size = len;
memcpy(b[y].a,c,len);
}
b[x].next = y;
}
void merge(int x,int y) {
memcpy(b[x].a+b[x].size,b[y].a,b[y].size);
b[x].size += b[y].size;
b[x].next = b[y].next;
dele(y);
}
void split(int k,int pos) {
if (k==-1 || pos==b[k].size) return;
add(k,addi(),b[k].size-pos,b[k].a+pos);
b[k].size = pos;
}
int pos(int &x) {
int now = 1;
while (now!=-1 && x>b[now].size) {
x -= b[now].size;
now = b[now].next;
}
return now;
}
void insert(int p,int len,char c[]) {
int now = pos(p);
split(now,p);
int tot=0,nextblock,st=now;
while (tot+maxn <= len) {
nextblock = addi();
add(now,nextblock,maxn,c+tot);
tot += maxn;
now = nextblock;
}
if (len - tot) {
nextblock = addi();
add(now,nextblock,len-tot,c+tot);
}
if (b[now].size+b[nextblock].size<maxn && nextblock!=-1) {
merge(now,nextblock);
nextblock = b[now].next;
}
if (b[st].size+b[b[st].next].size<maxn && b[st].next!=-1)
merge(st,b[st].next);
}
void erase(int p,int len) {
int now = pos(p);
split(now,p);
int ne = b[now].next;
while (ne!=-1 && len>b[ne].size) {
len -= b[ne].size;
ne = b[ne].next;
}
split(ne,len);
ne = b[ne].next;
for (int i=b[now].next; i!=ne; i=b[now].next) {
b[now].next = b[i].next;
dele(i);
}
while (b[now].size+b[ne].size<maxn && ne!=-1) {
merge(now,ne);
ne = b[now].next;
}
}
void get(int p,int len) {
int k = pos(p);
int tot = b[k].size - p;
if (len<tot) tot=len;
memcpy(ss,b[k].a+p,tot);
int now = b[k].next;
while (now!=-1 && len>=tot+b[now].size) {
memcpy(ss+tot,b[now].a,b[now].size);
tot += b[now].size;
now = b[now].next;
}
if (len-tot>0 && now!=-1)
memcpy(ss+tot,b[now].a,len-tot);
for (int i=0; i<len; ++i)
cout << ss[i];
cout << endl;
}
int main() {
init();
cin >> n;
while (n--) {
int len;
scanf("%s",s);
if (s[0]=='M')
scanf("%d",&curpos);
else if (s[0] == 'I') {
scanf("%d",&len); getchar();
for (int i=0; i<len; ++i) {
ss[i]=getchar();
if (ss[i]<32 || ss[i]>126) --i;
}
insert(curpos,len,ss);
} else if (s[0] == 'D') {
scanf("%d",&len);
erase(curpos,len);
} else if (s[0] == 'G') {
scanf("%d",&len);
get(curpos,len);
} else if (s[0] == 'P') {
curpos--;
} else if (s[0] == 'N') {
curpos++;
}
}
return 0;
}