最終還是打了個漂亮的醬油
[Day 1]
T1 神奇的幻方
送分類比題,但是遇到了一個非常流弊的學弟:
/*************************************以上純屬娛樂 割********************************************/
T2 資訊傳遞
大意:在一個只有n條有向邊的圖中,每個結點出度為1,求一個包含節點數最少的環。
分析:因為只有n條邊並且每個點都有且僅有一條邊連出去,所以只可能存在簡單環,不會出現那種8字形的環套環。
證明:每個點有兩種情況:1.不在任何一個環中 這樣的點可以直接忽略掉,看成是有n-1個點,n-1條邊來證明就行了。2.在某個環中。那麼如果我們現在有了一個圈圈形狀的環,大小為k,那麼每一個點都應該入度出度都為1,這樣的環只存在一個迴路,也就是一個簡單環,如果存在多個迴路,那麼應該存在某個點的入度>1,但是又要保證別的點出度至少為1,所以出度之和應該是>k的,但入度之和=k,無法滿足,所以不存在某個環存在兩條或以上數量的迴路。證畢。
滿足了這樣的性質,tarjan或者O(n)掃描都是可以解決本題的。
T3 鬥地主
與一些HN、ZJ的選手在網上討論,覺得這道題目作為第三題,沒有體現出應有的價值,只是讓很多人在這上面花費了大量時間而已,並且首先題目描述有不清晰之處,而且資料純隨機也讓人很不是滋味,畢竟也許有的人用搜尋剪枝碰巧能拿高分甚至AC,而那些寫的很好的標準演算法卻被卡掉,OI畢竟不是運氣的較量,而是實力的爭奪。
因為之前類比賽的時候寫過一次狀壓DP爆空間,然後這道題空間1G太過耀眼,再加上NP問題複雜的狀態以及相對略小的資料範圍,在考場上就朝著狀壓DP的方向思考,首先對於每一副手牌,我們預先處理出每一種可能的出牌方式,然後丟進一個數組裡,在DP的時候,記錄一個cnt表示當前是第幾次出牌,用bool[i](i是位元)表示出cnt次牌時,狀態i是否能實現,然後只要某一次滿足2^m-1也就是所有牌全出掉的情況可以實現時就退出,此時的cnt就是最少出牌次數。
具體時間複雜度根據每副牌而有很大差異,但是應該過60%的資料是沒有問題的。
賽後補:拿到程式以後再寫了寫,狀壓DP確實是能過60%的點,但是想AC的話還是要用到DFS+狀壓DP或者直接A*。
[Day 2]
T1 跳石頭
看到最大值最小或者最小值最大之類的問題,很容易想到是二分答案,
具體說明:假設我們已經知道答案是k,也就是滿足最小的距離最大為k,那麼最終搬走石頭以後任意兩個石頭之間的距離都是大於等於k的,那麼我們只要檢驗是否能搬走m塊石頭使得滿足k就可以了。
首先,題目告訴我們,起點石頭也就是0是固定的,然後如果我們搬走一個石頭i的話,如果左邊的石頭已經滿足答案k,那麼移除i對答案是沒有影響的,因為到左邊石頭的距離只會變大,不可能小於k。
對於當前的石頭i,下一塊石頭為j,pre[i]為i上一塊石頭,sub[j]為j下一塊石頭
有兩種可能:
1.i到j的距離小於等於k,也就是不滿足答案,那麼我們要做的是,移除j。
因為i到pre[i]是>=k的,那麼j到pre[i]一定也>=k,但是i都不一定滿足i到sub[j]的距離>=k,更不談離sub[j]更近的j了,所以為了之後的石頭考慮,我們需要移除j。
2.i到j的距離大於k,也就是i,j之間已經符合條件了,那麼就可以什麼都不動了。
因為i到j的距離已經大於k了,所以對於j之後每一塊石頭,都是滿足條件的,所以i對檢驗答案並沒有什麼影響了,那j如何考慮呢。j之後就會成了下一個i,再如上文分兩種情況處理了。
所以具體就是二分答案k,然後O(n)檢驗,總複雜度O(nlogL)。
PS:有一種特殊情況需要考慮,也就是n可以等於0,這時候答案直接就是L,但是處理方法很簡單,二分的時候要將上界設為L,這樣就不會有什麼影響了。
T2 子串
大意:求將B串選出k段,順次拼起來能構成A串的方案數。
本題的階段非常鮮明,f[i][j][t]表示A,B分別匹配到i,j位時,已經用到了B的第t個子串的方案數,另外match[i][j]表示A,B分別匹配到i,j位時,最多可以向前匹配多少位,如A=cabab,B=cab,那麼match[5][3]=2,match可以暴力預先處理出來。
考慮第i位不匹配和最多向前匹配match[i][j]位的情況,由此得出轉移方程:
但是很明顯這樣的複雜度在最壞情況下是O(n*m^2*k),所以我們要考慮最佳化。
首先是空間上:n*m*k可以達到4kw,明顯不夠用,然後我們發現,選到第t個子串的方案數只和選到t-1個子串的方案數有關,所以我們考慮以時間換空間,用滾動數組,f[0]和f[1]兩個二維數組交替使用,解決空間問題。
然後是時間上:觀察這個轉移方程,實際上是一個求和,那麼具體是什麼呢。我們如果把f[i][j]看成一個二維矩陣,那麼實際上就是求的以i-1,j-1(因為每個子串不可為空所以至少要選一個)為右下角,i-match[i][j],j-match[i][j]為左上方的的正方形的主對角線上的元素之和,所以對於這種求和,我們可以考慮用類似首碼和的方法O(1)轉移,另開數組g[i][j]表示以i,j為右下角的整條斜線上元素之和,那麼轉移方程就更新為:
這樣就降掉了一個O(m)的時間,但是因為使用滾動數組而且常數有點大,所以在實際枚舉的時候再注意一些小最佳化剔除一些不必要的狀態。
T3 運輸計劃
在考場上並沒有做出來,敲了個50的樸素,後來請教了一下wzy和zk,太厲害了。
大體架構就是二分答案然後用LCA來檢驗。
但是有幾個注意點:
1.二分的時候wzy是直接二分路徑總長度,zk是二分的選取的作為蟲洞的邊的長度,這樣就差距了約一個log層級的複雜度,但對實際效果是一樣的,這點值得吸取教訓。
2.求LCA的時候如果用普通的倍增會掛掉,要用Tarjan離線求LCA。
3.還未解決的內容:我們在做路徑處理的時候可以用一些特殊的技巧,給每一個點一個權值,在LCA的時候順帶處理一下,然後就可以得到每一條邊被多少條路徑覆蓋了,方便之後檢驗答案。