这道题目的题意很明确,给你五种操作,然后针对每次查询输出查询的第k个数字之前所有1-m(m<=k)m个数字之和最大的值。
有插入的题目用链表挺好做的,不过这里我用的是一个数组,用cnt记录光标位置,因为查询只查询光标左边边的值(所以后面如果查询大于cnt,则置为cnt),所以我们想到每次插入一个值就更新一下数据。我们开了一个数据结构,包括了3个int类型,一个是自身的值value,一个是从第一个到自己的所有数的和sum,还有一个是要查询的所有做大和Max。那么我们每次插入时,前面的都不动,只需要对插入的值进行更新就好了,value为传入参数,sum为前一个数的sum+value; 最大值为前一个Max和sum的大者,这是I操作。对于L&R操作,我们利用一个int的栈来记录,L压栈,R退栈并和I操作一样加入数组。 D操作直接cnt--就好了。Q操作输出MAX值。搞定,不过一些特殊情况要判断,比如光标已在最左边的L操作等等。
AC代码:
#include<iostream>
#include<list>
#include<cstdio>
#include<stack>
using namespace std;
struct node
{
int value; //自身值
int sum; //之前的和
int Max; //1-position的最大值
void set(int a,node * pre)
{
this->value=a;
this->sum=pre->sum+a;
this->Max=max(pre->Max,this->sum);
}
void set(int a)
{
this->value=a;
this->sum=a;
this->Max=a;
}
};
stack<int> before ;
node a[1000035];
int main()
{
int Q;
int cnt;
while(scanf("%d",&Q)!=EOF)
{
cnt=0;
while(!before.empty())
{
before.pop();
}
for(int i=1; i<=Q; i++)
{
char c[3];
scanf("%s",c);
if(c[0]=='I')
{
int num;
scanf("%d",&num);
if(cnt==0)
{
a[cnt].set(num);
}
else
{
a[cnt].set(num,&a[cnt-1]);
}
cnt++;
}
else if(c[0]=='D')
{
cnt--;
}
else if(c[0]=='L')
{
if(cnt!=0)
{
cnt--;
before.push(a[cnt].value);
}
}
else if(c[0]=='R')
{
if(!before.empty())
{
int temp=before.top();
before.pop();
if(cnt==0)
a[cnt].set(temp);
else
a[cnt].set(temp,&a[cnt-1]);
cnt++;
}
}
else
{
int num;
scanf("%d",&num);
if(num>cnt)num=cnt;
printf("%d\n",a[num-1].Max);
}
}
}
}