「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系统造成的差异问题,那些恶心优秀的字符类模拟题就再也不用方了

posted @ 2018-12-17 12:17  h^ovny  阅读(297)  评论(0)    收藏  举报