【题目大意】
要求一种数据结构,能够支持
(1)在某个位置插入长度为n的字符串
(2)删除从某个位置开始的长度为n的字符串
(3)输出从某个位置开始的长度为n的字符串
【分析】
块状链表
很裸的一道题,练练手。
要注意几点细节:
(1)空间可以循环使用
(2)注意随时保证复杂度,即合并小区间
【代码】
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define sf scanf
#define pf printf
#define MAXL (2*1024*1024+10)
#define MAXBLOCK 1500
#define BLOCKSIZE 1500
int N;
int freepos;
int freelist[MAXBLOCK];
int sz[MAXBLOCK];
int next[MAXBLOCK];
char str[MAXL];
char data[MAXBLOCK][BLOCKSIZE];
void Read(int& x,bool mark=0){
char tt=getchar();
for(;tt<'0'||'9'<tt;tt=getchar()) if(tt=='-') mark=1;
for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
x=mark?-x:x;
}
int Newnode(){
return freelist[freepos++];
}
void Delnode(int t){
return (void)(freelist[--freepos]=t);
}
void Find(int& p,int& b){
for(b=0;b!=-1&&p>sz[b];b=next[b]) p-=sz[b];
}
void Fillblock(int b,int n,char* str,int e){
if(b==-1) return;
next[b]=e;
sz[b]=n;
memcpy(data[b],str,n);
}
void Split(int b,int p){
if(b==-1||p==sz[b]) return;
int t=Newnode();
Fillblock(t,sz[b]-p,data[b]+p,next[b]);
next[b]=t;
sz[b]=p;
}
void Maintainlist(int b){
for(;b!=-1;b=next[b]){
for(int t=next[b];t!=-1&&sz[b]+sz[t]<=BLOCKSIZE;t=next[b]){
memcpy(data[b]+sz[b],data[t],sz[t]);
sz[b]+=sz[t];
next[b]=next[t];
Delnode(t);
}
}
}
void Insert(int p,int n,char* str){
int b,t,i;
Find(p,b);
Split(b,p);
for(i=0;i+BLOCKSIZE<=n;i+=BLOCKSIZE){
t=Newnode();
Fillblock(t,BLOCKSIZE,str+i,next[b]);
next[b]=t;
b=t;
}
if(n-i){
t=Newnode();
Fillblock(t,n-i,str+i,next[b]);
next[b]=t;
}
Maintainlist(b);
}
void Erase(int p,int n){
int b,e;
Find(p,b);
Split(b,p);
for(e=next[b];e!=-1&&n>sz[e];e=next[e]) n-=sz[e];
Split(e,n);
e=next[e];
for(int t=next[b];t!=e;t=next[b]){
next[b]=next[t];
Delnode(t);
}
Maintainlist(b);
}
void Get(int p,int n,char* str){
int b,t,i;
Find(p,b);
i=min(n,sz[b]-p);
memcpy(str,data[b]+p,i);
for(t=next[b];t!=-1&&i+sz[t]<=n;i+=sz[t],t=next[t]){
memcpy(str+i,data[t],sz[t]);
}
if(n-i&&t!=-1) memcpy(str+i,data[t],n-i);
str[n]='\0';
}
void Init(){
Read(N);
rep(i,1,MAXBLOCK-1) freelist[i]=i;
freepos=1;
next[0]=-1;
sz[0]=0;
}
void Solve(){
char order[10];
int cur=0,n;
while(N--){
sf("%s",order);
switch(order[0]){
case 'M':Read(cur);break;
case 'I':
Read(n);char c;
rep(i,0,n-1){
c=getchar();
str[i]=c;
if(c=='\n') --i;
}
Insert(cur,n,str);
break;
case 'D':
Read(n);
Erase(cur,n);
break;
case 'G':
Read(n);
Get(cur,n,str);
pf("%s\n",str);
break;
case 'P':--cur;break;
case 'N':++cur;break;
}
}
}
int main(){
Init();
Solve();
return 0;
}