传送门
Time Limit: 5 Sec Memory Limit: 162 MB
Submit: 2833 Solved: 1148
[Submit][Status][Discuss]
Description
Input
输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作。其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例)。 除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。 这里我们有如下假定:MOVE操作不超过50000个,INSERT和DELETE操作的总个数不超过4000,PREV和NEXT操作的总个数不超过200000。所有INSERT插入的字符数之和不超过2M(1M=1024*1024),正确的输出文件长度不超过3M字节。DELETE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作必然不会试图把光标移动到非法位置。输入文件没有错误。对C++选手的提示:经测试,最大的测试数据使用fstream进行输入有可能会比使用stdio慢约1秒。
Output
输出文件editor.out的每行依次对应输入文件中每条GET指令的输出。
Sample Input
15
Insert 26
abcdefghijklmnop
qrstuv wxy
Move 15
Delete 11
Move 5
Insert 1
^
Next
Insert 1
_
Next
Next
Insert 4
.\/.
Get 4
Prev
Insert 1
^
Move 0
Get 22
Sample Output
.\/.
abcde^_^f.\/.ghijklmno
HINT
Source
第一次打块状链表WAWAWARERERE烦死了!!!
块状链表思想就是分裂合并其实灰常简单
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXN 2*1024*1024+10
#define N 9000
struct Node{//结构体
char s[N+10];int len;Node* next;
Node(){s[0]=len=0;next=NULL;}
}*rt;
char str[MAXN],cmd[105];int p;
char buf[MAXN], *ps = buf, *pe = ps+1;
inline void rnext(){//读优
if(++ps==pe)
pe=(ps=buf)+fread(buf,1,sizeof(buf),stdin);
}
inline int get_int(){
do{rnext();}while(!isdigit(*ps));
int ans=0;
do{ans=(ans<<1)+(ans<<3)+*ps-48;rnext();
}while(isdigit(*ps));
return ans;
}
inline void get_str(char *s){
do{rnext();}while(!isalpha(*ps));
int cnt = 0;
do{s[cnt++]=*ps;rnext();
}while(isalpha(*ps));
s[cnt] = 0;
}
void read(int len){
int cnt=0;
while(cnt<len){
rnext();int ch = *ps;
if(32<=ch&&126>=ch)str[cnt++]=ch;
}
str[cnt] = 0;
}
Node* Find(int pos,int &k){//寻找在第几块
int cnt=0;Node *tmp=rt;
while(tmp->next){
if(cnt+tmp->len>=pos) break;
cnt+=tmp->len;tmp=tmp->next;
}
k=pos-cnt;return tmp;
}
void Split(Node *u,Node *&r,int k){//分裂
r=new Node();
r->next=u->next;u->next=r;
strcpy(r->s,u->s+k);
r->len=u->len-k;u->len=k;u->s[k]=0;
}
void merge(Node *u,Node *r){//合并
strcat(u->s,r->s);u->len+=r->len;
u->next=r->next;free(r);r=NULL;
}
void Insert(int len){//插入
int k;Node *u=Find(p,k),*r;
if(k==u->len) r=u->next;
else Split(u,r,k);
Node *tmp=u;int cnt=0;
while(len-cnt>=N){//处理整块
Node *now=new Node();
strncpy(now->s,str+cnt,N);
now->s[N]=0;now->len=N;
now->next=tmp->next;tmp->next=now;
tmp=now;cnt+=N;
}
if(len-cnt){//处理不足一块
Node *now=new Node();
strcpy(now->s,str+cnt);
now->len=len-cnt;now->next=tmp->next;
tmp->next=now;tmp=now;cnt=len;
}
if(rt!=u&&u->len<=(N>>1)&&u->next&&u->next->len<=(N>>1)){//两个不足一半合并
if(tmp==u->next) merge(u,u->next),tmp=u;
else merge(u,u->next);
}
if(tmp!=rt&&tmp->len<=(N>>1)&&r&&r->len<=(N>>1)) merge(tmp,r);//两个不足一半合并
}
void Delete(int len){//删除
int sk,ek;
Node *st=Find(p,sk),*sr;Node *ed=Find(p+len,ek),*er;//寻找方格
Split(ed,er,ek);Split(st,sr,sk);Node *tmp=st->next;//注意这个先分后面再分前面,由于这个无限WA和RE
while(tmp!=er){
Node *buf=tmp;
tmp=tmp->next;
free(buf);
}
st->next=er;
if(st->len<=(N>>1)&&er->len<=(N>>1)) merge(st,er);//两个不足一半合并
}
void Get(int len){//输出
int k,cnt=0;Node* now=Find(p+1,k);k--;
while(now&&cnt<len){
while(k<now->len&&cnt<len) putchar(now->s[k]),cnt++,k++;
now=now->next;k=0;
}
putchar('\n');
}
int main(){
int t,x;t=get_int();
rt=new Node();p=0;
while(t--){
get_str(cmd);
switch(cmd[0]){
case 'M':p=get_int();break;
case 'I':x=get_int();read(x);Insert(x);break;
case 'D':x=get_int();Delete(x);break;
case 'G':x=get_int();Get(x);break;
case 'P':p--;break;
case 'N':p++;break;
}
}
return 0;
}