题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4699
由于当前的操作只和序列中的某一个指定的位置有关,可以从光标处将序列划分两段,分别维护两个栈,再维护左栈的前缀和以及前缀和最大值。
代码如下:
#include<iostream> using namespace std; const int maxn = 1000010; int n; int st1[maxn],st2[maxn],s[maxn],f[maxn];//双栈存储 int N1,N2; void Editer(){ N1=0,N2=0; f[0]=-0x3f3f3f3f; while(n--){ char c[10]; scanf("%s",c); switch(c[0]){ case 'I': scanf("%d",&st1[++N1]); s[N1]=s[N1-1]+st1[N1];//维护前缀和以及前缀和最大值 f[N1]=max(f[N1-1],s[N1]); continue; case 'D': if(!N1)continue;//光标在最前端 N1--; continue; case 'L': if(!N1)continue; st2[++N2]=st1[N1--];//将左栈中的栈顶放入右栈中 continue; case 'R': if(!N2)continue; st1[++N1]=st2[N2--]; s[N1]=s[N1-1]+st1[N1];//只维护左栈中的前缀和 f[N1]=max(f[N1-1],s[N1]); continue; case 'Q': int k; scanf("%d",&k); printf("%d ",f[k]);//k不超过当前光标的位置 } } } int main(){ while(scanf("%d",&n)!=EOF){ Editer(); } return 0; }