2022.12 TOI 潛力組題解

本文最後更新於:2023年2月24日 晚上

嗯為什麼我覺得這次好難QAQ

BST

problem

給定一顆二元搜尋樹的後序走訪,請你復原這顆二元搜尋樹。

solution

因為左子樹的值會小於自己,而右子樹會大於自己,所以我可以採用「認領」的方式實作。

整理一下會發現對於每一個節點,其值必在所有右祖先節點左祖先節點之間,我們令這兩個值分別為$max,min$$\text{, while}$ $min \leq max$ 。

由於不知道根結點很麻煩,所以將儲存後序走訪的陣列f[]倒轉,如此可以發現,在進入子樹之前,必會經過父節點。

  • 目前即將處裡的點在f[]的座標為$p$
  • 現在所在節點為$x$
  • 目前最大值與最小值分別為$max$,$min$

遞迴:

  • 如果$f_p > max$ or $f_p < min$則結束迴圈
  • 當$f_x < f_p$ ,將$p$加一,往右子樹走訪。
  • 如果$f_p > max$ or $f_p < min$則結束迴圈
  • 當$f_x > f_p$,將$p$加一,往左子樹走訪。

最後整理輸出即可。

code

tags: DFS

Ants

problem

一堆螞蟻走來走去,問你他們想講什麼。(對我不會摘錄,給我乖乖看題目)

solution

因為答案具有單調性,因此可以對答案使用二分搜尋法。

其中有趣的是當兩隻螞蟻相撞時,可以完全不管牠們。

自己推推看 :)

code

Numbers

本題維修中==

problem

有一個數列f[],請寫出一程式以執行下列操作。

  • 給定$a,b$,求出$\displaystyle \sum _{k = a}^b f_k$。
  • 給定$a,b$,將f[]中$[a,b]$範圍內的數除以$10$(整數除法)。
  • 給定$a,b$,將$f_a$更改為$b$。

solution

這題根本超毒(還是我線段樹中毒?)
因為直接做複雜度過高,所以使用客製化線段樹(?)+lazy tag模擬操作。

為了避免線段樹除法的進位問題,直接開一個struct,其中包含一個陣列,紀錄除以$10$ ($[1,19]$)次後的狀況,如此在合併兩個葉節點時只需要將陣列中的每一項相加就可以了。

也因此遇到lazy tag時可以直接取用該節點的陣列中的值。
但要注意不需要乘上$(r - l + 1)$,不然會出錯(別問我為甚麼知道)

code



tags: seg_tree lazy-tag struct

2022.12 TOI 潛力組題解
http://mysh212.github.io/algosolution/TOI-202212/
作者
ysh
發布於
2022年12月30日
更新於
2023年2月24日
許可協議