NOI2019 I 君的探險
I 君的探險
地下宮殿可以抽象成一張 \(N\) 個點、\(M\) 條邊的無向簡單圖(簡單圖滿足任意兩點之間至多存在一條直接相連的邊),洞穴從 \(0 \sim n − 1\) 編號。目前你並不知道邊有哪些。
每個洞穴都擁有一個光源,光源有開啟、關閉兩種狀態,只有當光源處於開啟狀態時它所在的洞穴才會被照亮。初始時所有的光源都處於關閉狀態,而光源的狀態只能用 I 君發現的神祕機關改變。更具體的,使用神祕機關可以進行如下四種操作:
-
向機關給定一個編號 \(x\),機關將會改變 \(x\) 號洞穴,以及與 \(x\) 號洞穴有通路直接相連的洞穴的光源狀態。即原來開啟的光源將會關閉;原來關閉的光源將會開啟。
-
向機關給定一個編號 \(x\),機關將會顯示當前 \(x\) 號洞穴光源的狀態。
-
向機關給定兩個編號 \(x, y\),表示你確定有一條連線 \(x\) 號洞穴與 \(y\) 號洞穴的通路,並讓機關記錄。
-
向機關給定一個編號 \(x\),機關將會判斷與 \(x\) 號洞穴相連的通路是否都已被記錄。
機關在完成上一次操作後才能進行下一次操作。機關不能隨意使用,因此每種操作的使用次數都有限制,分別為 \(L_m, L_q, M, L_c\)。你的任務是,編寫一個程式,幫助 I 君決定如何合理利用神祕機關,從而正確地找到這 \(M\) 條通路。
題解
將分部分分進行介紹。
測試點1~5
修改\(x\)之後查詢\(x+1\sim N\)有沒有變化即可。\(n-1\)次modify,\(\binom{N}{2}\)次query。
測試點6~9
使用分治。對當前集合內的點挨個掃描,亮了不管,沒亮點亮,直到亮了\(\frac{N}{2}\)個為止。
這樣集合就被分成了亮了的和沒亮的兩部分,分別遞迴處理即可。
\(N\log_2N\)次modify和query。
有一種更簡單的方法,那就是以\(\frac{1}{2}\)的概率修改每個點。這樣一對匹配點亮了和沒亮的概率都是\(\frac{1}{2}\),複雜度相同。
測試點10~11
由於父節點編號小於子節點,所以對於單個節點\(x\)
對所有節點考慮,整體二分即可。
\(N\log_2N\)次modify和query。
測試點12~17
在無環圖上,我們希望用一種“剝葉子”的過程,通過逐步刪去度數為\(1\)的點,最後找到整個圖的形態。
我們不妨記每個點的標號為\(1\sim N\),對每個\(k∈[1,\log_2N]\),我們把二進位制下第\(k\)位為\(1\)的點拿出來MODIFY,然後QUERY全體點
- 在這個操作下,\(x\)號點顏色改變,當且僅當\(x\)關聯了奇數個第\(k\)位為\(1\)的點
不難發現,對每個\(k\)做一遍這個過程後,我們可以得知每個點關聯的全體點的標號異或和。顯然這個過程花費\(N\log_2 N\)次MODIFY和QUERY
現在,記\(sum[i]\)為\(i\)關聯的全體點(不包括自己)的異或和,考慮一個點\(x\)
-
若\(x\)度數為\(1\),那麼\(sum[x]\)到\(x\)恰好有一條邊
-
通過兩次QUERY、一次MODIFY,可以判定是否存在一條\(sum[x]\)和\(x\)的邊
-
若存在這樣一條邊,可以令\(sum[sum[x]]=sum[sum[x]]⊕x\)以及\(sum[x]=0\),然後“斷開”這條邊
造一個佇列\(Q\),初始時每個點都在其中,每次從\(Q\)中取出一個點\(x\),檢查\(x\)和\(sum[x]\)之間是否有一條邊
- 若是,把\(sum[