AcWing 128 编辑器

题目描述:

你将要实现一个功能强大的整数序列编辑器。在开始时,序列是空的。编辑器共有五种指令,如下:

1、“I x”,在光标处插入数值x。
2、“D”,将光标前面的第一个元素删除,如果前面没有元素,则忽略此操作。
3、“L”,将光标向左移动,跳过一个元素,如果左边没有元素,则忽略此操作。
4、“R”,将光标向右移动,跳过一个元素,如果右边没有元素,则忽略次操作。
5、“Q k”,假设此刻光标之前的序列为a1,a2,…,an,输出max1≤i≤kSi,其中Si=a1+a2+…+ai。

输入格式

第一行包含一个整数Q,表示指令的总数。

接下来Q行,每行一个指令,具体指令格式如题目描述。

输出格式

每一个“Q k”指令,输出一个整数作为结果,每个结果占一行。

数据范围

1≤Q≤10^6,
|x|≤10^3,
1≤k≤n

输入样例:

8
I 2
I -1
I 1
Q 3
L
D
R
Q 2

输出样例:

2
3

样例解释

下图包含了对样例的过程描述:

C464-1004-2.jpg

分析:

题目描述的五种指令分别代表:I-插入元素,D-删除元素,L-删除元素并保存,R-将保存的元素按后出先进的规则再插入,Q-查询前缀和中最大值。

由于有先进后出的性质,考虑采用栈来存储。维护两个栈s,t。I和D分别对应栈s的入栈和出栈操作。L表示将s的栈顶元素弹出保存进t,R代表将t的栈顶元素(若存在)重新压进s栈。至于Q则需要维护一个前缀和数组和一个dp数组,dp[i]表示前i个元素前缀和最大的值,所以Q k操作等价于输出dp[k]。

值得注意的是,仅需要在入栈时更新sum和dp数组,出栈时无需修改,因为下一次入栈会自动更新上次遗留下来没有处理的sum和dp的末尾几个元素。另外,Q的最大值是一百万,使用cin读入数据会超时,加上ios::sync_with_stdio(false);语句便可ac了。

#include <iostream>
#include <algorithm>
#include <stack>
using namespace std;
const int maxn = 1000005;
stack<int> s,t;
long long sum[maxn],dp[maxn];
int p = 0;
void I(int x){
    s.push(x);
    p++;
    sum[p] = sum[p - 1] + x;//更新前缀和
    dp[p] = max(dp[p - 1],sum[p]);//更新dp
}
void D(){
    if(s.size()){
        s.pop();
        p--;
    }
}
void L(){
    if(s.size()){
        int x = s.top();
        D();
        t.push(x);
    }
}
void R(){
    if(t.size()){
        I(t.top());
        t.pop();
    }
}
void Q(int k){
    cout<<dp[k]<<endl;
}
int main(){
    ios::sync_with_stdio(false);
    sum[0] = 0;
    dp[0] = -3000;
    int T,x;
    char c;
    cin>>T;
    while(T--){
        cin>>c;
        if(c == 'I'){
            cin>>x;
            I(x);
        }
        else if(c == 'D')   D();
        else if(c == 'L')   L();
        else if(c == 'R')   R();
        else if(c == 'Q'){
            cin>>x;
            Q(x);
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值