题目描述
$你将要实现一个功能强大的整数序列编辑器。
在开始时,序列是空的。
编辑器共有五种指令,如下:
1、I x,在光标处插入数值 x。
2、D,将光标前面的第一个元素删除,如果前面没有元素,则忽略此操作。
3、L,将光标向左移动,跳过一个元素,如果左边没有元素,则忽略此操作。
4、R,将光标向右移动,跳过一个元素,如果右边没有元素,则忽略次操作。
5、Q k,假设此刻光标之前的序列为 a1,a2,…,an,输出 max1≤i≤k Si,其中 Si=a1+a2+…+ai$
样例
输入样例: 8 I 2 I -1 I 1 Q 3 L D R Q 2 输出样例: 2 3
算法
(对顶栈)
当对一个序列的中间元素进行操作时,用类似于对顶堆的思想,考虑用两个对顶栈来维护
定义左右双栈,左栈为光标左侧的元素,右栈
为光标右侧的元素
对于第一个操作,我们直接往push 元素x
对于第二个操作,我们让pop
对于第三个操作我们将 的栈顶元素pop并且压入
对于第四个操作我们将 的栈顶元素pop并且压入
第五个操作,我们定义一个数组表示从
的栈底到第i个元素的最大前缀和是多少
定义为从
的栈底到第i个元素的前缀和是多少
初始化(前缀有可能是负数),每次执行完操作一时我们令:
当执行pop操作时top会-1相当于f[top]被删除
时间复杂度O(N)
C++ 代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1000010;
int stk0[N],stk1[N];
int tt[2];
int s[N],f[N];
int n;
int main()
{
scanf("%d",&n);
char op[2];
int k;
f[0] = -1e9 - 10;
while(n --)
{
scanf("%s",op);
if(*op == 'I')
{
scanf("%d",&k);
stk0[++ tt[0]] = k;
s[tt[0]] = s[tt[0] - 1] + k;
f[tt[0]] = max(f[tt[0] - 1],s[tt[0]]);
}else if(*op == 'D')
{
if(tt[0]) tt[0] --;
}else if(*op == 'L')
{
if(tt[0]) stk1[++ tt[1]] = stk0[tt[0] --];
}else if(*op == 'R')
{
if(tt[1])
{
stk0[++ tt[0]] = stk1[tt[1] --];
s[tt[0]] = s[tt[0] - 1] + stk0[tt[0]];
f[tt[0]] = max(f[tt[0] - 1],s[tt[0]]);
}
}else
{
scanf("%d",&k);
printf("%d\n",f[k]);
}
}
return 0;
}
京公网安备 11010502036488号