本题其实来自lyd老师的《算法竞赛进阶指南》
但是纸上得来终觉浅,绝知此事要躬行嘛
就把做题思路回顾在这里噜
P2201 数列编辑器
题目描述
小 Z 是一个爱好数学的小学生。最近,他在研究一些关于整数数列的性质。
为了方便他的研究,小Z希望实现一个叫做“Open Continuous Lines Processor”的数列编辑器。
一开始,数列编辑器里没有数字,只有一个光标。这个数列编辑器需要支持五种操作。
I x
在当前光标前插入数字 \(x\)。D
删除当前光标前的数字。L
光标向前移动一个数字。R
光标向后移动一个数字。Q k
设光标之前的数列是 \(\{a_1,a_2,\cdots,a_n\}\),输出第 \(k\) 位及之前最大的前缀和,保证 \(k\leqslant n\)。
输入格式
第一行包含一个数字 \(N\),表示操作的个数。
接下来包含 \(N\) 行,每行包含一条命令。
输出格式
对于每个 Q k
命令,输出一个整数表示这个操作的答案。
输入输出样例 #1
输入 #1
8
I 2
I -1
I 1
Q 3
L
D
R
Q 2
输出 #1
2
3
说明/提示
数据范围
对于 \(50\%\) 的数据,\(N\leqslant1000\);
对于 \(80\%\) 的数据,\(N\leqslant10^5\);
对于 \(100\%\) 的数据,\(N\leqslant10^6\),插入的数字绝对值大小不会超过 \(1000\)。
题目保证不会在数列编辑器为空时进行 D
操作。
本题讲了一个很奇妙的方法 所谓对顶栈
什么呢?就是以光标的两端为栈顶分别开两个栈维护
然后前缀和用O(1)直接用一个数组f进行一个类似DP的操作维护
整体就是O(1)的了
#include<bits/stdc++.h> #define ll long long using namespace std; stack<int>s; stack<int>q; int n; char x; int t; int p=0; int presum[1000005]; int f[100005]; int main(){f[0]=-(1<<30);scanf("%d",&n);for(int i=1;i<=n;i++){cin>>x;if(x=='I'){scanf("%d",&t);s.push(t);p++;presum[p]=presum[p-1]+t;f[p]=max(f[p-1],presum[p]);} if(x=='D'){s.pop();p--;}if(x=='L'){p--;q.push(s.top());s.pop();}if(x=='R'){s.push(q.top());q.pop();p++;presum[p]=presum[p-1]+s.top();f[p]=max(f[p-1],presum[p]);}if(x=='Q'){scanf("%d",&t);printf("%d\n",f[t]);}}system("pause");return 0; }