问题描述
你现在要实现一个针对于数字序列的编辑器。
初始的时候,序列是空的。
在之后,有以下五种操作:
I x 在光标之后插入x
D 删除光标之前的数字
L 将光标向左移动,如果已经在最左,则不移动
R 将光标向右移动,如果已经在最右,则不移动
Q k 假设光标之前的序列是{a1, a2,...,an}, 定义Si=a1+a2+...+ai,此时输出满足1<=i<=k的最大的Si
输入包含多组数据,文件结尾作为输入结束的标志。
每组数据的第一行包含一个数字Q,表示有Q个操作。接下来有Q行,每行为一条上述指令。
1<=Q<=1000000, 插入操作中的x:|x| <= 1000,Q操作中的k:1<=k<=n
对于Q指令,输出要求的结果。
以下是样例的具体操作过程:
|
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
|
以文本方式显示
|
1秒 | 64M | 0 |
大致思路:
利用双栈进行维护,光标左边为一个栈,光标右边为一个栈。遇到I的时候就将其假如左边的栈,遇到D就删去左边栈的栈顶元素,遇到R就将右边栈顶的元素假如左边栈,遇到L就将左边栈顶元素假如右边栈中,遇到Q就输出前k个元素中和最大的值(此处用动态规划的方法每次当元素进入左栈的时候就记录该元素以前的最大和)。就这样依次输出就好了。
具体实现:
两个数组,一个为左栈,一个为右栈,遇到相应的字符就进行相应的操作,跟大致思路里面一样,用两个指针就可以实现。对于求和问题,就利用动态规划的思想,左栈每进入一个元素就记录到这个元素为止的最大和,用一个数组记录,然后遇到Q就输出相应的值。
注意事项:
(1)注意数组的初始化。
(2)注意如果光标到最左边或是到最右边,即左栈或是右栈元素为0的时候就不需要进行相关操作了。
实现代码
<span style="font-family:Microsoft YaHei;font-size:14px;">#include<stdio.h> #include<string.h> int max(int x,int y) { if(x>y) { return x; } else { return y; } } int dp[1000010],he[1000010]; //动态规划的思想计算前面书和最大 int left[1000010],right[1000010]; //使用双栈 int main() { int n,l,r,i,x,k; char temp[2]; while(scanf("%d",&n)!=EOF) { memset(dp,0,sizeof(dp)); memset(he,0,sizeof(he)); memset(temp,0,sizeof(temp)); dp[0]=-1000010; l=0; r=0; for(i=0;i<n;i++) { scanf("%s",temp); //防止空格和回车键的影响用%s读入,这样就不需要考虑空格和回车键 if(temp[0]=='I') { scanf("%d",&x); l++; left[l]=x; // l++; he[l]=he[l-1]+x; //添加数到左边,并用动态规划的思想记录前l个数的最大和 dp[l]=max(he[l],dp[l-1]); } else if(temp[0]=='D') { if(l!=0) { l--; } //移动指针,删除元素 } else if(temp[0]=='L') { if(l!=0) { r++; right[r]=left[l]; l--; // r++; //左移光标,利用指针的变化,对两个栈进行入栈和出栈的操作 // l--; } } else if(temp[0]=='R') { if(r!=0) { l++; left[l]=right[r]; //l++; r--; he[l]=he[l-1]+left[l]; dp[l]=max(he[l],dp[l-1]); //右移光标,利用指针的变化,对两个栈进行入栈和出栈操作,并对左侧的和进行更新 // l++; // r--; } } else if(temp[0]=='Q') { scanf("%d",&k); if(l==0) { printf("0\n"); } else { printf("%d\n",dp[k]); } } else ; } } return 0; }</span>