题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4699
Problem Description
Sample Input
8
I 2
I -1
I 1
Q 3
L
D
R
Q 2
Sample Output
2
3
Hint
题意:
维护一个整数序列的编辑器,有以下五种操作,操作总数不超过 $10^6$。
$I : x$:在当前光标位置之后插入一个整数 $x$,插入后光标移动到 $x$ 之后;
$D$:删除光标前的一个整数;
$L$:光标左移一格;
$R$:光标右移一格;
$Q : k$:即 $S_i$ 为前 $i$ 个整数的和,查询 $S_1, S_2, cdots, S_k$ 中的最大值。
题解:
已知 I,D,L,R 这四种操作都是在光标位置处发生,且操作完光标最多移动一个位置,因此可以用对顶栈的做法。
顾名思义,我们以光标为分界,分成左右两段序列分别由两个栈 $A,B$ 来维护,两个栈的栈顶相对。
同时我们可以开一个 $sum$ 数组来维护栈 $A$ 的前缀和,在开一个 $mx[i]$ 数组来保存 $sum[1], sum[2], cdots, sum[i]$ 中的最大值。
AC代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; const int INF=0x3f3f3f3f; stack<int> A,B; int sum[maxn],mx[maxn]; void update() { int p=A.size(); sum[p]=sum[p-1]+A.top(); mx[p]=max(mx[p-1],sum[p]); } int main() { int q; while(cin>>q) { sum[0]=0; mx[0]=-INF; while(!A.empty()) A.pop(); while(!B.empty()) B.pop(); while(q--) { char op[3]; int k; scanf("%s",op); switch(op[0]) { case 'I': scanf("%d",&k); A.push(k); update(); break; case 'D': A.pop(); break; case 'L': if(A.empty()) break; B.push(A.top()); A.pop(); break; case 'R': if(B.empty()) break; A.push(B.top()); B.pop(); update(); break; case 'Q': scanf("%d",&k); printf("%d ",mx[k]); break; } } } }