链接: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]);
}
}
}
}