Editor

题目描述

$你将要实现一个功能强大的整数序列编辑器。

在开始时,序列是空的。

编辑器共有五种指令,如下:

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;
}