题目
维护一个整数序列的编辑器,有以下五种操作,操作总数不超过10^6。
I x:在当前光标位置之后插入一个整数想,插入以后光标移动到x之后;
D:删除光标之前的一个整数,即按下退格键Backspace;
L:光标向左移动一个位置,即按下<—键;
R:光标享有移动一个位置,即按下—>键;
Q k:询问在位置k之前的最大前缀和,其中k不超过当前光标的位置。
本题有多组数据
题解
题解非常的巧妙
因为前四种操作都是在光标位置处发生,而且操作完成后光标至多移动1个位置。可以采用“对顶栈”做法
建立两个栈,栈A存1—光标位置的子序列,一个存光标位置—序列结尾,二者都以光标所在的位置作为栈顶。每次操作对栈进行操作。
而查询操作的k不超过光标位置,所以用两个数组分别维护栈A的前缀和以及前缀和的最大值。
缩代码不是一个好习惯!要写得清楚明白拒绝玄学
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int q,ll,rr;
int l[1000006],r[1000006];
int f[1000006],ans[1000006];
int main(){
while (~scanf("%d",&q)){
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
memset(f,0,sizeof(f));
memset(ans,0,sizeof(ans));
ll=rr=0;
while (q--){
char ch;
getchar();
scanf("%c",&ch);
if (ch=='I'){
int x;
scanf("%d",&x);
l[ll]=x;
f[ll]=(ll==0)? x:f[ll-1]+x;
ans[ll]=(ll==0)? f[ll]:max(ans[ll-1],f[ll]);
ll++;
}else
if (ch=='D'){
if (ll==0) continue;
ll--;
}else
if (ch=='L'){
if (ll==0) continue;
r[rr]=l[ll-1];
rr++;
ll--;
}else
if (ch=='R'){
if (rr==0) continue;
l[ll]=r[rr-1];
f[ll]=(ll==0)? l[ll]:f[ll-1]+l[ll];
ans[ll]=(ll==0)? f[ll]:max(ans[ll-1],f[ll]);
ll++;
rr--;
}else
{
int x=0;
scanf("%d",&x);
printf("%d\n",ans[x-1]);
}
}
}
return 0;
}