「Luogu P2201」数列编辑器 解题报告
数列编辑器,在线IDE
本期的主题是洛谷的在线IDE
小学生?!小学生虐我 😢
思路:
怎么说链表也是可以的吧,虽然比较繁琐
然后涉及到了前缀和和一些优化手段(应该可以说是记忆化吧)?
用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;
}
最后,再支持一下Luogu的
在线IDE!
极大解决Linux系统和Windows系统造成的差异问题,那些恶心优秀的字符类模拟题就再也不用方了

浙公网安备 33010602011771号