题面
题解
- 通过观察我们可以将这个序列通过2个栈和2个数组来维护5种操作进而达到题解,为了方便,直接用数组来模拟栈 stkl[N](光标左边的栈), stkr[N](光标右边的栈), tl(左栈指针), tr(右栈指针);
s[N](前缀和数组), f[N](最大前缀和);- 对于第一个操作,在光标处插入x,就是给stkl 的栈顶插入一个x, 前缀和数组更新,最大前缀和就是新的前缀和 和 上一个前缀和取最大
- 将光标前面的第一个元素删除,就是将stkl的栈顶元素删除
- 将光标向左移动,跳过一个元素,就是将stkr插入stkl的栈顶元素,然后stkl的栈顶元素删除,向右移动也是同理
- 查询直接返回f[x]: 表示的就是前缀和中的最大值
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int stkl[N], stkr[N], tl, tr;
int s[N], f[N];
void push_left(int x) {
stkl[++tl] = x;
s[tl] = s[tl - 1] + x;
f[tl] = max(f[tl - 1], s[tl]);
}
int main() {
int n;
scanf("%d", &n);
f[0] = INT_MIN; //防止前缀和为负数
while (n--) {
char op[2];
int x;
scanf("%s", op);
if (op[0] == 'I') { //在光标处插入数值x
scanf("%d", &x);
push_left(x);
} else if (op[0] == 'D') { //将光标前面的第一个元素删除
if (tl > 0) {
tl--;
}
} else if (op[0] == 'L') { //将光标向左移动,跳过一个元素
if (tl > 0) {
stkr[++tr] = stkl[tl--];
}
} else if (op[0] == 'R') { //将光标向右移动,跳过一个元素
if (tr > 0) {
push_left(stkr[tr--]);
}
} else { //查询前缀和最大
scanf("%d", &x);
printf("%d\n", f[x]);
}
}
return 0;
}