2024.10.8分享
Problem
Problem A
有一个长度为 \(n\) 的序列和 \(m\) 个操作序列,第 \(i\) 个操作是:把区间 \(l_i,r_i\) 的所有数,替换成这个区间的最大值。
接下来有 \(q\) 个操作,每个操作是形如下面的两种之一:
1 x k,表示执行:\(a_x\gets k\)2 l r x,表示询问在现在的序列上,按顺序执行第 \(l\sim r\) 的操作后,\(a_x\) 会变成多少?
\(n,m,q\le 5\times 10^5\)
Problem B(easy version)
有一个长为 \(n\) 的序列,以及 \(q\) 次操作:
一种是在当前的修改序列末尾添加一个修改:在区间 \([l,r]\) 的数,执行 \(x\gets a\cdot x+b\),其中 \(l,r,a,b\) 是给定的。
一种是查询在当前的修改序列中,按顺序执行第 \(l\) 到 \(r\) 的修改,位置 \(x\) 上的数会变成多少,其中 \(l,r,x\) 是给定的。
不强制在线。
\(n\le 10^5,q\le 6\times 10^5\)。
Problem C(hard version)
同第二题,但是强制在线。
Solution
Problem A Sol
通过手玩可以发现,考虑倒序执行操作,一开始把区间变成 \([x,x]\),然后每次找到最后一个包含左端点的区间,更新左端点,右端点同理,然后最后就是求出 \(l,r\) 的最大值,于是建出左树和右树,查询直接树上倍增,然后线段树维护区间最大值即可,复杂度 \(\Theta(n\log n)\)。
Problem B Sol
离线,对于修改序列建线段树,注意到两个 \(ax+b\) 的操作是可以复合的,然后按顺序把序列从 \(1\) 扫到 \(n\),然后对于所有的修改操作,在扫到 \(l\) 时线段树上加入,\(r+1\) 时线段树上删除,这样我们的线段树就维护了所有包含当前点的修改操作,然后查询所有这个位置的询问,线段树上查询变换的复合即可,复杂度 \(\Theta(n\log n)\)。
Problem C Sol
不能离线了,考虑直接大力线段树维护修改序列。
注意到一件事情,对于长度为 \(len\) 的修改序列,最多会让原序列形成 \(\Theta(len)\) 个不同的变换连续段,于是考虑线段树的每个节点维护这些连续段,合并的时候考虑对右端点归并排序,细节较多,合并复杂度 \(\Theta(len)\)。
但是注意到不能每次加入一个操作之后就在这个位置的所有祖先上合并,复杂度会退化,对于一个节点,我们称其为满的当且仅当这个区间的所有修改都被插入,注意到查询只会查到所有满的节点,于是我们最对满的节点的合并即可,这样每个节点这会被合并一次,复杂度 \(\Theta(n\log^2 n)\)。

浙公网安备 33010602011771号