2014 Multi-University Training Contest 2--by 鎮海中學 解題報告

2014 Multi-University Training Contest 2--by 鎮海中學 解題報告

ZCC Loves Intersection

2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>2--by <wbr>鎮海中學 <wbr>解題報告

2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>2--by <wbr>鎮海中學 <wbr>解題報告



ZCC Loves COT

首先考慮一維下的版本。(數列,區間加,區間和)

顯然可以使用線段樹,但是線段樹推廣到高維度的難度較大。

針對本題先修改再詢問的特點,我們可以在修改時只保存差分後的數組。

在處理詢問前求前綴和還原原數列。之後再求一次前綴和就可以做到O(1)回答詢問了。

現在試圖把它推廣到二維。(三角形,子三角形加,子三角形和)

如果樸素地對每一行應用一維的差分法,最後得到的標記會像下面一樣:

2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>2--by <wbr>鎮海中學 <wbr>解題報告

其中+1標記和-1標記都是連續的一段。

標記也是一種值,所以可以對標記打標記!

於是我們將所有的+1標記按從右上到左下做差分,將所有的-1標記按從左上到右下做差分。

這樣每個操作實際上只需要在兩個數組中修改四個值,最後利用這兩個數組還原原來的標記,利用標記還原原數陣。前綴和的計算也是類似,只不過第二維的前綴和要從兩個方向各算一遍。

類似地,只需要4個數組就可以表示三維情況下的所有標記,經過三輪不同方向上的求前綴和就可以得到原四面體,前綴和的計算也需要4個數組。這樣單操作/單詢問要拆成8個,是O(1)的,複雜度是O(N^3+M+Q)


ZCC Loves RPG

在程序的每一個位置,都存在若干條形如a[x]>=v!(a[x]>=v)的限制。它們給每個a[i]確定了一個上界和一個下界。顯然,我們應當讓a[i]儘量小,因此我們可以令a[i]恰取到它的下界。

那麼,考慮一對上下界數列Ui, Di,當前語句可以被執行到的條件就是:

2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>2--by <wbr>鎮海中學 <wbr>解題報告

隨着我們分析程序的過程,一些位置的下界會發生變化,我們需要隨時重新計算這個最大非零子段和,這就是說,我們需要對一個數列支持單點修改和查詢最大非零子段和。這是一個線段樹的經典應用,這裏不再贅述。

下面考慮如何分析程序。

首先需要實現一個詞法分析器:它接受字符串作爲其輸入,每次返回一個記號(常量,符號或標識符等)。這部分可以按照寫讀入優化的方法來寫。

然後就到了對記號流進行分析的步驟,這一步的做法有很多,這裏只講一下std的做法。

首先將game(n, k)讀入,獲取n, k的值,同時建立線段樹。

清空兩個棧,這兩個棧一個用於保存程序結構(稱爲棧P),一個用於保存UiDi的變化便於之後撤銷(稱爲棧Q)。

讀入左花括號,向棧P中壓入一個B符號,B符號聲明當前語句處於一對未閉合的花括號內,當棧P頂是B符號時,可以向這個花括號內追加語句。

隨後重複以下過程直至棧P空。

檢查棧P的棧頂:

若爲B從詞法分析器取得下一個記號。

若爲右花括號:彈出B。(閉合花括號)

否則:把這個記號“塞回去”,向棧P壓入S符號。(追加語句)

若爲S彈出S,從詞法分析器取得下一個記號。

若爲左花括號:向棧P壓入B符號。(新建塊)

若爲cg:讀入整個cg語句,查詢當前是否可達,更新答案。

若爲if:讀入if語句的第一句,讀入x, v。向棧P先後壓入I符號,T符號和S符號。向棧Q先後壓入!(a[x]>=v)a[x]>=v,在線段樹上做a[x]>=v的修改。

若爲T彈出T,彈出棧Q棧頂元素,撤銷它的修改。從詞法分析器取得下一個記號:

若爲else:應用棧Q棧頂元素(之前加入了但沒有應用的!(a[x]>=v))的修改。向棧P壓入S符號。

否則:把記號塞回去。彈出棧Q棧頂元素,彈出棧P棧頂元素(必定是I符號)。

若爲I彈出I,彈出棧Q棧頂元素,撤銷它的修改。

B,S,T,I四個符號的意思分別是:塊,語句,Then結束,整個If結束。

最後輸出答案。


ZCC Loves Minecraft

所求的S即爲當前點集的正交凸包。

參見en.wikipedia.org/wiki/Orthogonal_convex_hull的相關介紹。直觀地看正交凸包是左上、右上、左下、右下四段折線構成的多邊形,每條邊都與座標軸平行。求已知點集的正交凸包,可以先找出最上、最下、最左、最右的點。求右上方的一段折線,可以從最上面的點開始,每次找當前點右邊的點中最上面的點,與當前點L形連接,作爲新的當前點,不斷重複直到選到最右邊的點。這一過程實現非常簡單,只要先按橫座標排序,然後掃描一遍並維護縱座標最大值即可。其它三段的求法是類似的,而且可以通過旋轉進行轉化。那麼對於動態加點的問題,可以用4棵平衡樹(實現用STL即可)分別維護四段折線。插入點時嘗試將其分別插入四段折線的相應位置,若在當前折線外部需要更新折線,並計算面積的增量。以右上折線爲例,需要不斷判斷新點左邊的點是否在新點下方,若是則刪除。由於每個點最多被插入一次刪除一次,總的時間複雜度是O(nlogn)。邊界情況需要一定的特判。


ZCC Loves words

   這道題我們可以先對單詞建出AC自動機。然後在AC自動機上進行計數(dp)。F[i][j]表示當前長度第i位,當前在AC自動機的j號節點。我們考慮主動轉移,如果j號節點在接受c這個字符後到了第k個節點,那麼F[i+1][k]+=F[i][j]*Get。其中Get表示在第k個節點能乘上的數字。

  我們來分析一下Get2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>2--by <wbr>鎮海中學 <wbr>解題報告,那麼如果沒有+i這個東西,我們就可以建出矩陣,然後直接快速冪+矩陣乘法。但是有了+i的話,每個矩陣都不同,但是事實上P=179*173*163,這其中的質數非常的小,然後就是亂搞的部分了,i Mod Pi就是O(Pi)的循環,於是我們建出Pi個矩陣,然後對於L/Pi的部分快速冪+矩陣乘法,對於L Mod Pi的部分暴力矩陣乘法即可。對於每一個質數得到的答案,利用中國剩餘定理就可算出最後的答案。複雜度大概是O(Pi*tot^3 + log(L)*tot^3)

  如果有更優的做法歡迎指教。



ZCC Loves cards

2014 <wbr>Multi-University <wbr>Training <wbr>Contest <wbr>2--by <wbr>鎮海中學 <wbr>解題報告


ZCC Love ranklist

第一問:

k=1的時候答案顯然爲n-1

k=2ttZ*)時答案顯然爲0。把比賽分成兩兩一組,每組和爲n+1即可。

k=2t+1tZ*)時先兩兩一組到只剩3個。n爲偶數時答案顯然不能爲0,只能做到1。奇數時則可以做到。一種解決辦法是:

n爲奇數

1

4

7

n爲偶數

1

4

6

 

2

5

5

 

2

5

4

 

3

6

3

 

3

6

2

 

4

7

1

 

4

1

5

 

5

1

6

 

5

2

3

 

6

2

4

 

6

3

1

 

7

3

2

 

 

 

 

第二問:

先觀察進步指數的性質:由於NewRank=OldRank的時候進步指數=0所以只能出現一次所以不應該使用。當NewRank!=OldRank的時候兩個進步指數相等當且僅當NewRankOldRank都相等,兩個進步指數爲相反數當且僅當NewRank1=OldRank2OldRank1=NewRank2

總共能出現n*(n-1)+1種不同的進步指數,而且n>1,所以每種進步指數(除了0)都會出現。並且進步指數爲相反數的一對只能出現在同一場考試中。所以n爲奇數時顯然無解。

n爲偶數時,注意到每場考試實際上是將考生兩兩組隊n-1輪且不重複。於是使用循環賽構造算法即可。

循環賽構造算法:http://www.doc88.com/p-694165485213.html



ZCC Love march

我們用set維護當前的士兵位置,合併的時候將每個士兵暴力合併到該位置,即刪掉原位置士兵並使目標位置size+=原位置size。每次移動的時候將原位置size--在新位置新建一個size爲1士兵。這樣最多隻會有n+移動數 的士兵,每個士兵只會合併一次,所以時間複雜度爲O(nlogn)。實現的時候爲了記錄每個點的座標可以用並查集維護所在的塊。

 


ZCC Love traffic lights

首先考慮如果是一般圖的話怎麼做。可以證明存在一個最優解在某一條邊上卡着時間進去或者卡着時間出來。因爲如果不這樣的話可以將每個點的時間往後推直到卡着時間。所以只要對在每個點上卡時的情況進行判斷。

枚舉了某個點的到達時間以後那麼接下來我們可以使用最短路算法求出到終點的最早時間和從起點出發的最晚時間。具體實現的時候可以對每個點開8個狀態記錄從哪個方向進入和是否闖過紅燈。

 


ZCC loves Army

Solution

可以發現上司和下屬之間的關係可以構成一棵樹,考慮三種操作。

交換下屬:爲了使交換下屬的時候改變的邊變少,可以用左兒子右兄弟的方式表示這棵樹。那麼交換時只需要改變至多4條邊。可以用LCT維護。

傳送信息:求從x傳信息到y所需要的中介人的最少個數。令x爲深度較大的一個點,這條路徑就是x向上傳到和y同一層,再水平傳送。可以把編號爲1的兒子的權值賦值爲1,求x,y簡單路徑上的權值和。

發送指令:求x可以收到幾個士兵發出的指令。表現在左兒子右兄弟的樹上即爲求該點到根之間的點個數。

Postscript

爲了方便,可以給每個點加一個編號爲0的虛孩子,可以避免一些細節問題。

交換下屬的時候找孩子可以對每個點開一個平衡樹,也可以直接用LCT裏的Splay

 


ZCC loves Codefires

考察序列中相鄰的兩題i, j(i在前)。交換它們後,解出它們之前的題目所帶來的時間對答案的貢獻是不變的,它們對它們後面的題目的貢獻也是不變的,其他題目之間對答案的貢獻自然也是不變的。唯一的變化就是,原來的EiKj一項變成了EjKi一項。那麼,爲了使答案變優,需要滿足的條件是EjKiEiKj。也即Ei/KiEj/Kj

那麼,最優解序列Ai一定滿足,EAi/KAi是遞增的。

排序一遍即可。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章