![HDU 4699 - Editor - [对顶栈] HDU 4699 - Editor - [对顶栈]](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
题目链接: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+;
const int INF=0x3f3f3f3f; stack<int> A,B;
int sum[maxn],mx[maxn];
void update()
{
int p=A.size();
sum[p]=sum[p-]+A.top();
mx[p]=max(mx[p-],sum[p]);
}
int main()
{
int q;
while(cin>>q)
{
sum[]=;
mx[]=-INF;
while(!A.empty()) A.pop();
while(!B.empty()) B.pop();
while(q--)
{
char op[]; int k;
scanf("%s",op);
switch(op[])
{
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\n",mx[k]);
break;
}
}
}
}