线段树JSOI2008最大数

好不容易一次AC的线段树代码,结果别人的队列快那么多。。
题目戳这里

因为在一本通线段树章节里看到的,所以就很直接的往线段树上想了
(还是不能太单纯)
思路是这样的,因为线段树肯定是要知道叶节点个数才能建树(反正我只会这样建),所以就先全部读入,边统计序列的长度。中间如果读到询问操作就用一个数组记录询问区间在总序列中的位置(包括起点和终点)。
知道序列长度以后先建一个空树(如果一次性全部建好显然是不符合题意的)
全部读好以后开始挨个找答案,如果当前询问的末位置还未加入线段树那就往线段树上加数,否则直接query】
代码不是很长略略

type node=record
	l,r,max:longint;
	end;
var m,p,x,tot,he,ans,i,j:longint;
c:char;
num:array[1..200000]of longint;
len:array[1..200000,1..2]of longint;
t:array[1..800000]of node;
function mm(e,f:longint):longint;
begin 
	if e>f then exit(e)
		else exit(f);
end;
procedure build(k,l,r:longint);
begin 
	t[k].l:=l;t[k].r:=r;
	if l=r then exit;
	build(k*2,l,(l+r) div 2);build(k*2+1,(l+r)div 2+1,r);
end;
procedure insert(k,l,q:longint);
var mid:longint;
begin 
	if t[k].l=t[k].r then begin t[k].max:=q;exit;end;
	if t[k].max<q then t[k].max:=q;
	mid:=(t[k].l+t[k].r)div 2;
	if l<= mid then insert(k*2,l,q)
		else insert(k*2+1,l,q);
end;
function query(k,l,r:longint):longint;
var mid:longint;
begin 
	if (t[k].l=l) and (t[k].r=r) then 
	begin 
		exit(t[k].max);
	end;
	mid:=(t[k].l+t[k].r) div 2;
	if r<=mid then exit(query(k*2,l,r));
	if l>mid then exit(query(k*2+1,l,r));
	exit(mm(query(k*2,l,mid),query(k*2+1,mid+1,r)));
end;
begin 
	readln(m,p);
	tot:=0;he:=0;
	for i:=1 to m do 
	begin 
		read(c);
		if c='A' then 
		begin 
			inc(tot);
			readln(num[tot]);
		end 
		else begin 
			readln(x);
			inc(he);
			len[he,1]:=tot-x+1;
			len[he,2]:=tot;
		end;
	end;
	build(1,1,tot);
	ans:=0;
	i:=1;
	j:=1;
	while j<=he do 
	begin 
		if i<=len[j,2] then 
		begin 
			//write((num[i]+ans) mod p,' ');
			insert(1,i,(num[i]+ans)mod p);
			inc(i);
		end
		else 
		begin 
			ans:=query(1,len[j,1],len[j,2]);
			inc(j);
			writeln(ans);
		end;
	end;
end.
然后就看到了另一种更好的方法
维护一个队列,边读入边做,如果是加数就计算出需要加进的数,然后从队列顶端向下搜直到找到一个比该数大的数,把要加的数放在找到的数上面一个,top也设为这个位置。因为被删去的数是在加入的数之前但又不大于加入的数的数,那么要查询的答案一定不会是它们。
查询时可以从顶端直接往下找,找到第一个到序列末端的长度比查询长度长的,输出其上面一个的答案。

(来自洛谷的一份让本安格尔恍然大悟外加一丝悲伤的大佬代码https://www.luogu.org/record/3129708))

第一篇博文写的好垃圾啊
还有94天要加油加油啊,虽然有点孤单,但千万不要放弃在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作据库,这大大简化了据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 据库引擎和连接池: SQLAlchemy 支持多种据库后端,并且为每种后端提供了对应的据库引擎。 它还提供了连接池管理功能,以优化据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值