HDU 4699

题目链接: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;
            }
        }
    }
}
原文地址:https://www.cnblogs.com/dilthey/p/9896433.html