题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1507
题意:一个文本编辑器,模拟以下操作:
思路:块状链表的主要操作:
(1)find(p,b):找到位置p在链表的位置b;
(2)split(b,p):将第b块分裂成两块,前一块大小为p;
(3)maintain(b):将b块之后的碎片合并;
利用以上三种操作可以完成插入串、删除一段串、得到一段串三种操作。另外三种操作比较简单。
(1)insert(p,n,str):在位置p之后插入长度为n的串str。find(p,b),split(b,p),之后将str插入b之后,最后maintain(b)一下;
(2)erase(p,n):在位置p之后删除长度为n的一段。find(p,b),split(b,p),之后从b之后删除若干块。这里可能最后一块也是需要split的。
(3)get(p,n):得到p之后长度为n的一段。find(p,b),split(b,p),之后从b之后取出长度为n的串,这里可能最后一个串也是需要split的。
const int N=1<<25;
const int BLOCKSIZE=20000;
const int BLOCKNUM=N/BLOCKSIZE*3;
queue<int> Q;
int newNode()
{
int temp=Q.front();
Q.pop();
return temp;
}
void delNode(int t)
{
Q.push(t);
}
struct node
{
char data[BLOCKSIZE];
int len,next;
};
node a[BLOCKNUM];
void find(int &p,int &b)
{
for(b=0;a[b].next!=-1&&p>a[b].len;b=a[b].next)
{
p-=a[b].len;
}
}
void fillNode(int b,int n,char data[],int nextB)
{
a[b].next=nextB;
a[b].len=n;
memcpy(a[b].data,data,n);
}
void split(int b,int p)
{
if(a[b].len==p) return;
int t=newNode();
fillNode(t,a[b].len-p,a[b].data+p,a[b].next);
a[b].next=t;
a[b].len=p;
}
void maintain(int b)
{
int t;
for(;b!=-1;b=a[b].next)
{
for(t=a[b].next;t!=-1&&a[b].len+a[t].len<=BLOCKSIZE;t=a[b].next)
{
memcpy(a[b].data+a[b].len,a[t].data,a[t].len);
a[b].len+=a[t].len;
a[b].next=a[t].next;
delNode(t);
}
}
}
void insert(int p,int n,char str[])
{
int i,b,t;
find(p,b); split(b,p);
for(i=0;i+BLOCKSIZE<=n;i+=BLOCKSIZE)
{
t=newNode();
fillNode(t,BLOCKSIZE,str+i,a[b].next);
a[b].next=t;
b=t;
}
if(i<n)
{
t=newNode();
fillNode(t,n-i,str+i,a[b].next);
a[b].next=t;
}
maintain(b);
}
void erase(int p,int n)
{
int i,b,t;
find(p,b); split(b,p);
for(i=a[b].next;i!=-1&&n>a[i].len;i=a[i].next)
{
n-=a[i].len;
}
split(i,n); i=a[i].next;
for(t=a[b].next;t!=i;t=a[b].next)
{
a[b].next=a[t].next;
delNode(t);
}
maintain(b);
}
void get(int p,int n,char str[])
{
int i,b,t;
find(p,b);i=min(n,a[b].len-p);
memcpy(str,a[b].data+p,i);
for(t=a[b].next;t!=-1&&i+a[t].len<=n;t=a[t].next)
{
memcpy(str+i,a[t].data,a[t].len);
i+=a[t].len;
}
if(i<n&&t!=-1) memcpy(str+i,a[t].data,n-i);
str[n]=0;
}
void init()
{
int i;
FOR1(i,BLOCKNUM-1) Q.push(i);
a[0].next=-1;
a[0].len=0;
}
char str[N];
void read(int n)
{
int i;
char c;
FOR0(i,n)
{
c=getchar();
str[i]=c;
if(c<32||c>126) i--;
}
}
int main()
{
init();
int cur=0;
char op[10];
int n;
rush()
{
RD(op);
if(op[0]=='M') RD(cur);
else if(op[0]=='I')
{
RD(n);
read(n);
insert(cur,n,str);
}
else if(op[0]=='D')
{
RD(n);
erase(cur,n);
}
else if(op[0]=='G')
{
RD(n);
get(cur,n,str);
puts(str);
}
else if(op[0]=='P') cur--;
else if(op[0]=='N') cur++;
}
}