>Description
>Input
第一行包含一个数字N,表示操作的个数。
接下来包含N 行,每行包含一条命令。
>Output
对于每个Q k 命令,输出一个整数表示这个操作的答案。
>Sample Input
8
I 2
I -1
I 1
Q 3
L
D
R
Q 2
>Sample Output
2
3
• 对于50% 的数据,N <= 1000。
• 对于80% 的数据,N <= 100000。
• 对于100% 的数据,N <= 1000000,插入的数字绝对值大小不会超过1000。
>解题思路
部分分做法:直接暴力。
正解:
O(n),可以用两个栈分别对当前光标前和光标后数字的进行维护,光标的移动只需要将一个栈顶元素移动到另一个栈就行了,并且题目说只会查询光标前的数据,所以答案也只需要在光标前的栈中维护。
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, y, t, ans[1000005], s[1000005], a[1000005], b[1000005];
char x;
int read () //int类型快读
{
int l = 0;
char c = getchar(), cc;
while (c > '9' || c < '0') cc = c, c = getchar();
while (c <= '9' && c >= '0')
{
l = l * 10 + c - '0';
c = getchar();
}
if (cc == '-') return -l; //记得判断正负!
return l;
}
char rread() //字符快读
{
char c = getchar ();
while (c != 'I' && c != 'L' && c != 'R' && c != 'D' && c != 'Q') //如果不是题目描述的那几个字符就继续读入
c = getchar ();
return c;
}
int main()
{
ans[0] = -1e9; //由于读入的数可能是负数,所以初值要设成一个很小的数
n = read();
for (int i = 1; i <= n; i++)
{
x = rread();
if (x == 'I')
{
y = read();
a[++a[0]] = y; //把y放入光标前面的栈 (a[0]为栈的长度)
s[a[0]] = s[a[0] - 1] + y; //前缀和
ans[a[0]] = max (ans[a[0] - 1], s[a[0]]); //维护ans
}
if (x == 'D')
{
a[0]--; //去除光标前面的数
}
if (x == 'L')
{
b[++b[0]] = a[a[0]];
a[0]--; //把光标前面的数从a栈移到b栈
}
if (x == 'R')
{
a[++a[0]] = b[b[0]]; //把光标后面的数从b栈移到a栈
s[a[0]] = s[a[0] - 1] + a[a[0]];
ans[a[0]] = max (ans[a[0] - 1], s[a[0]]);
b[0]--;
}
if (x == 'Q')
{
y = read();
printf ("%d\n", ans[y]); //直接输出
}
}
return 0;
}