題目:
z市交通不發達,所有公交路線覆蓋的邊竟然乙個環也不包含,甚至該市的公交路線有可能會分為幾個互不連通的塊,這可真是不可思議。有一天,你突然聽到一條訊息,說你的m個同學被困在了z市裡,他們分別要從他們當前所在的點a
i移動到他們想去的點b
i.於是你立刻調集資料,了解了z市的形狀和公交路線的分布,現在你要算出每個人到達目的地最少要換多少次車,或者告知那個人不能僅用公交車達到目的地。
分析:
先考慮乙個詢問。假設我們想要從a走到b,像這樣:
大概的路線是:從a向上走,然後經過lca(a,b),再向下走。
對於從a向上走這一部分,如圖:
很顯然,如果沒有越過lca,就可以盡量一直走。就像前兩個紅箭頭一樣,坐從此出發的最遠一班車向上走。
但如果在某處,「最遠的一班車」越過了lca,那情況就變得不確定了——它的路線有可能繼續向上,也有可能折向下,我們先不去考慮它。能夠確定的是,如果「最遠一班車」達到的最淺節點仍然是lca的後代,坐這班車一定是最優解。
我們對於a和b都執行「在越過lca之前走最遠」的操作。像這樣:
a花stepa步走到了a',b花stepb步走到了b'。
答案是多少呢?
如果有一條線路能從a'到b',那答案就是stepa+stepb(共搭乘了stepa+stepb+1條線路,轉車次數就是stepa+stepb次)。
如果沒有a'~b'的線路,那要麼無解,要麼答案就是stepa+stepb+1(從a'走到lca,再從lca走到b')。
所以答案分成兩部分:①對ab執行「越過lca之前盡量向上走」。②判斷a'是否能直接乘車到b'。
我們來分別討論這兩個模組。
①的想法比較顯然,用倍增即可。為此對於每個點,需要記錄它向上乘1,2,4,8……次車走到的最遠點。2,4,8……的情況可以dp出來,關鍵在於:如何知道從某點出發,向上乘一次車最遠走到**?
下面來解決這個問題。設點u向上乘一次車走到的最遠點是r[u]。
首先,由於我們只關心向上走,所以對於一條線路(s,t),可以將其拆成兩條線(s,g)和(g,t),其中g=lca(s,t)。
得出所有像這樣「直上直下」的路徑後,我們進行如下處理:
將所有路徑按照較淺點的深度從小到大排序,然後對於每條路徑(s,t),從t向上遍歷到s,如果某個點的r值為零(初始化的值),就將其設為s,否則就退出。
如圖:假設淺藍色和紅色弧線都代表公交線路,深藍色直線代表一條「直上直下」的鏈。
在這個演算法中,淺藍色弧線顯然比紅色線早處理到,因此在處理紅色線時,中間重疊部分的r值已經非零。我們沿著紅色線從底向上確定那些頂點的r值,在處理到重疊部分時就會跳出。
這樣,掃瞄的複雜度就是o(n),因為每個頂點的r值只會被賦值一次,並額外訪問一次。
計算出r值之後就可以用倍增解決問題①。
下面來看問題②:
問題②等價於:是否有一條公交線路(s,t),其起點s在a'的子樹內,終點t在b'的子樹內(或相反,s在b'子樹內而t在a'子樹內)。
即:是否有一條公交線路(s,t),滿足dfn[a']<=dfn[s]<=last[a']且dfn[b']<=dfn[t]<=last[b'](或相反)。
其中dfn[x]代表x節點在dfs時首次被遍歷到的時間,last[x]代表x節點最後一次被遍歷到的時間,顯然夾在二者之間的那些節點就是x的子樹。
把這兩個限制改寫一下:在x座標範圍dfn[a']~last[a'],y座標範圍dfn[b']~last[b']的矩形中,是否存在某個點(dfn[s],dfn[t])或(dfn[t],dfn[s])。
也就是:給定一堆點和一堆矩形,問每個矩形內包含了多少點。(其實只需要判斷有沒有)
這就解決了。當然,這道題寫起來還是比較煩人的……
**:
國家集訓隊2011 種樹 解題報告
題目 a城市有乙個巨大的圓形廣場,為了綠化環境和淨化空氣,市 決定沿圓形廣場外圈種一圈樹。園林部門得到指令後,初步規劃出n個種樹的位置,順時針編號1到n。並且每個位置都有乙個美觀度ai,如果在這裡種樹就可以得到這ai的美觀度。但由於a城市土壤肥力欠佳,兩棵樹決不能種在相鄰的位置 i號位置和i 1號位...
happiness 國家集訓隊2011 吳確
2011中國國家集訓隊命題答辯 高一一班的座位表是個n m的矩陣,經過乙個學期的相處,每個同學和前後左右相鄰的同學互相成為了好朋友。這學期要分文理科了,每個同學對於選擇文科與理科有著自己的喜悅值,而一對好朋友如果能同時選文科或者理科,那麼他們又將收穫一些喜悅值。作為計算機競賽教練的scp大老闆,想知...
國家集訓隊2011 悄悄話
在這個有話不直說的年代,密碼學越來越被廣泛接受。我們引用經典的 凱撒密碼 在英文中,凱撒加密只對26個字母生效 分大小寫 我們按照 a 到 z 來排字母。凱撒加密的原理就是把原文的每乙個字母都按順序往後移k位。這個k將被作為金鑰。a 往後移變成 b z 往後移會變成 a 0 k 25 現在給出一系列...