数列编辑器

思路:

怎么说链表也是可以的吧,虽然比较繁琐

然后涉及到了前缀和和一些优化手段(应该可以说是记忆化吧)?

用p记录光标的位置

虽然这道题的数据范围挺大的$(1~1,000,000)$

但是题目中说,k一定在p之前

所以实际上只有p前面的序列是有效的

于是我们就可以写一个半在线半离线的算法

链表模拟数列

当然了,不用按照顺序,我们只用把数字存一下,然后顺序什么的一切靠链表解决

f数组 存i点(这里的i不是数列中的顺序,而是实际读入的顺序,下同,具体见代码)的最大前缀和,这样就可以直接查询

s数组 存i点的前缀和,方便更新f数组

然后用 ord数组 记录一下每个数在数列中的编号(不是实际的编号,有点类似hash的样子)

每接受一个操作就做一次更新

代码如下:

#include<bits/stdc++.h>
#define INF 0x7f7f7f7f
using namespace std;
struct node{
    int f,t;//f表示前驱,t表示后继(由于本菜鸟不喜欢front和next……请谅解~)
    int s;
}b[1000010];
int T,t,p,n;
int s[1000010];
int f[1000010];
int ord[1000010];
int read()//有负数,快读不要忘记符号的问题
{
    int s=0,p=1;
    char c=getchar();
    while(!isdigit(c))
    {
        if(c=='-')
            p=-1;
        c=getchar();
    }
    while(isdigit(c))
    {
        s=(s<<1)+(s<<3)+c-'0';
        c=getchar();
    }
    return s*p;
}
int main()
{
    char c;
    T=read();
    f[0]=-INF;//因为有负数嘛,所以一开始前缀和的最大值应该是一个极小数
    while(T--)
    {
        c=getchar();
        while(c!='I'&&c!='D'&&c!='L'&&c!='R'&&c!='Q')
            c=getchar();//getchar()比较快(优化后还有更快的),写c=='\n'||c=='\r'||c==' ',关系也不大
        if(c=='I')
        {
            b[++t].s=read();
            b[t].f=p;
            b[b[p].t].f=t;
            b[t].t=b[p].t;
            b[p].t=t;
            s[t]=s[p]+b[t].s;//插入节点
            f[t]=max(f[p],s[t]);//更新当前的前缀和最大值
            p=t;//更新光标位置
            ord[++n]=p;//加入有价值的数列,并hash一下编号
        }
        if(c=='D')
        {
            b[b[p].t].f=b[p].f;
            b[b[p].f].t=b[p].t;//删除节点
            p=b[p].f;
            n--;
        }
        if(c=='L')
        {
            p=b[p].f;
            n--;
        }
        if(c=='R')
        {
            s[b[p].t]=s[p]+b[b[p].t].s;
            f[b[p].t]=max(f[p],s[b[p].t]);
            p=b[p].t;
            ord[++n]=p;
        }
        if(c=='Q')
            printf("%d\n",f[ord[read()]]);//这里可以好好理解一下
    }//其实这里的五个操作可以合并起来写,放在函数里,然后可以调用
     //比如说在'I'的操作里,可以看成是插入一个节点,然后在右移光标一位 这两步
     //比较方便(其实也没方便多少)
    return 0;
}

devil.