题目大意
维护一个整数序列的编辑器,有以下五种操作,操作总数不超过10
6
6
1.I x:在当前光标位置之后插入一个整数x,插入后光标移动到x以后
2.D:删除光标之前的一个整数,即按下退格键Backspace
3.L:光标向左移动一个位置,即按下←键
4.R:光标向右移动一个位置,即按下→键
5.Q k:询问在位置k之前的最大前缀和,其中k不超过当前光标的位置
解题思路:
对顶栈
可以用cpp自带骚库stack
我们定义两个栈,第一个栈是光标前,后一个栈是光标后
于是问题就不难,插入时直接把元素加入第一个栈,删除直接把第一个栈的栈顶元素弹出去,左移就弹出第一个栈的栈顶元素插入到第二个栈中,右移则弹出第一个栈的栈顶元素插入到第一个栈中
至于前缀和,我们设sum[i]为在光标在i处时前面所有数的前缀和,dp[i]为位置i前的最大前缀和,now为第一个栈的元素数量
于是 sum[now]=sum[now-1]+x;
dp[now]=max(dp[now-1],sum[now]);
这样就硬生生的转换为一道简单的模拟题了
Accepted code:
#include<stack>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define maxn (int)(1e6+50)
using namespace std;
int sum[maxn],dp[maxn];
stack<int> fir;
stack<int> sec;
int main()
{
int m,x;
char c[15];
while(~scanf("%d",&m))
{
while(fir.size()) fir.pop();
while(sec.size()) sec.pop();
int now=0;
dp[0]=-1e9;
sum[0]=0;//初始化
while (m--)
{
scanf("%s",c);
if (c[0]=='I')
{
scanf("%d",&x);
fir.push(x);
now++;
sum[now]=sum[now-1]+x;
dp[now]=max(dp[now-1],sum[now]);
}
else
if (c[0]=='D')
{
if (!now) continue;
now--;
fir.pop();
}
else
if (c[0]=='L')
{
if (!now) continue;
now--;
sec.push(fir.top());
fir.pop();
}
else
if (c[0]=='R')
{
if (!sec.size()) continue;
now++;
fir.push(sec.top());
sec.pop();
sum[now]=sum[now-1]+fir.top();
dp[now]=max(dp[now-1],sum[now]);
}
else
{
scanf("%d",&x);
printf("%d\n",dp[x]);
}
}
}
return 0;
}