双栈维护之--Hdu4699 editor
http://acm.hdu.edu.cn/showproblem.php?pid=4699
题意:简而言之,有5种操作:
I在光标右边插入一个数
D删除光标左边的数 ,
L将光标移动最左边
R将光标移动到最右边
Q k 询问k位置以前的最大前缀和
思路:定义两个栈,一个从前开始,一个从后开始,二者加起来就是整个数列。至于最大前缀和用dp维护一下就好了, dp[i]=(dp[i-1],sum[i]); sum数组里存储的是1~i的和。
注意:栈为空的情况,不能直接pop
#include<cstdio> #include<queue> #include<stack> #include<algorithm> using namespace std; const int inf=-0x3f3f3f3f;//注意 int sum[1000006]; int dp[1000006];//dp[i]表示在前i int main(){ int t; while(~scanf("%d",&t)){ memset(sum,0,sizeof(sum)); memset(dp,inf,sizeof(dp));//因为dp的值为最大的前缀和,维护最大需要初始化为-inf,但是memset(-inf)会有问题,所以有宏定义的修改 stack<int>s1,s2; int pos=0;//光标当前所指的位置 while(t--){ getchar();//注意空格 char c; scanf("%c",&c); if(c=='I'){ int a; scanf("%d",&a); s1.push (a); pos++;//移动光标都要更新一下前缀和和最大前缀和 sum[pos]=sum[pos-1]+a; dp[pos]=max(dp[pos-1],sum[pos]); }else if(c=='Q'){ int a; scanf("%d",&a); printf("%d\n",dp[a]); }else if(c=='L'){ if(s1.empty())continue;//注意 pos--; int b=s1.top (); s1.pop (); s2.push (b); }else if(c=='D'){ if(s1.empty())continue;注意 s1.pop(); pos--; }else if(c=='R'){ if(s2.empty())continue; int b=s2.top ();s2.pop(); s1.push (b); pos++; sum[pos]=sum[pos-1]+b; dp[pos]=max(dp[pos-1],sum[pos]); }else{ int a; scanf("%d",&a); printf("%d\n",dp[a]); } } } }