123
E
首先把操作离线成一棵树,点 \(i\) 上有权值 \(a_i\),记 \(s_u=\sum_{v\in Path_u}a_v,f_u(x)=x-s_{fa_u}\) ,那么所求答案即为 \(\prod_{v\in Path_u}f_v(s_u)\) ,即是一个树上多点求值问题。
具体过程见题解,不多赘述,主要思想是转化为取模,通过取模降低多项式次数来降低时间复杂度,类似于多点求值做法。
J-dhj
首先 x,y 独立,考虑一维问题。
考虑从一个点 x 某个操作 p 开始,第一次碰到墙是在哪个操作结束后。考虑倍增,处理 \(f_{i,j}\) 表示 \([i,i+2^j)\) 这个区间中的前缀最小值和最大值,那么每次查询可以做到 \(O(\log n)\) ,同时可以处理出过程中实际走了多少距离以及最后在 0 还是 n。
考虑一个询问,先处理第一次碰到墙,之后再考虑倍增 \(g_{i,0/1,j}\) 表示操作完了第 \(i\) 个操作后,初始在 0/n 时,碰 \(2^j\) 次墙之后恰好操作完了哪个操作,以及该过程中的路程与到达位置。然后处理一下最后一段走的路程即可。总复杂度 \(O(n\log n)\)。
该做法实现较为细节,需要考虑清楚状态的定义,考虑数轴,将值放在一段上,状态放在一点上似乎会减轻一点代码难度。
J-wdy
也是x,y独立,考虑分开做。现在只考虑一维的问题。
先考虑位置怎么做。首先建立线段树,线段树上每一个线段\([l,r]\)上考虑维护一个\([0,n]\to[0,n]\)的函数\(f(x)\),表示进入的时候坐标为\(x\),离开的时候坐标会变成多少。那么对于叶子节点\([p,p]\),\(f(x)\)是一个段数\(O(1)\)的分段函数,因此对于\([l,r]\)对应的线段,\(f(x)\)是一个\(O(r-l+1)\)段的分段函数,建立合并儿子的时候,由于\(f(x)\)的单调性,可以扫过去归并合并,把线段树每层相加复杂度是\(O(n\log)\)的。然后求值的时候就考虑维护当前的\(x\),然后在完整的节点出在分段函数上二分求值。每次询问复杂度\(O(\log^2)\)。
然后考虑距离,也如上每个节点维护一个\(g(x)\)表示进入坐标是\(x\),走完全程的距离。然后合并的时候是左儿子的\(f(x)\)符合右儿子的\(g(x)\),再加上左儿子的\(g(x)\),可以归纳证明\(g(x)\)的段数也是\(O(r-l+1)\)的。
注意到\(f(x)\)的每一段的斜率都是\(\{-1,0,1\}\)之一,所以复合的时候不需要考虑浮点相关。实际上可以证\(f(x)\)的段数是\(O(1)\)的。