T1 邦布照相 [貪心]
Description
給定長度為 \(n\) 的序列和一個 \(k\),在序列中找到字典序最小的且是 \(k\) 的排列的子序列,輸出答案。
\(k\le n\le 2\times 10^5\)。
Solution
考慮貪心,遍歷序列,用一個類似單調棧的東西維護答案,如果這個數在棧中出現過,便跳過,如果沒出現過,先把棧頂的大於等於它的,且後面還有的數彈出去,放到後面選,然後再入棧。
顯然這樣是最優的。
Summary
雖然思路很簡單,但考場上想太複雜了,導致耗時過長。
T2 聖誕樹裝飾 [記憶化搜尋]
Description
給定一棵二叉樹,除葉子外都有左右兩個兒子。
有些葉子有權值 \(1\),有些為 \(0\)。
定義一棵樹是合法的當且僅當對於每個點,左右子樹權值和之差不超過 \(1\)。
可以進行任意次操作,每次可以將一個葉子的權值移動到另一個葉子,求最小運算元,或報告無解。
Solution
無論怎麼移動,所有權值的總和是不變的,所以我們可以自頂向下搜尋來計算貢獻。
- 設 \(f(u,j)\) 表示以 \(u\) 為根的子樹 需要 有多少權值,整棵樹的權值記為 \(tot\),
- 從 \(f(root,tot)\) 開始搜,如果 \(tot\) 為偶數,說明兩邊只有一種情況,\(f(son,tot/2)\),
如果為奇數,則有兩種情況,分別搜尋並取最小值即可。 - 邊界:葉子節點,若 \(tot\) 和該葉子的權值不同,記 \(1\) 貢獻,否則不計,無解則是 \(tot> 1\)。
- 最後答案除以二即可,因為取出一個權值可以和加上一個權值合併為同一操作,但是計算了重複了。
Summary
並非什麼高階演算法,主要是思維難度,考場上要避免過度依賴高階演算法,導致想得太複雜。
T3 新聞 [差分,並查集]
Description
給定一個字串和 \(m\) 個操作區間,每次操作可以選擇一個區間,並將字串中這個區間內的所有字元變成它的後繼(a->b,z->a),問是否可以將字串變為迴文串。
Solution
對原字串進行差分,\(a_i=s_i-s_{i-1}\),因為要變成迴文串,則每兩個點是要對稱的,假設分別為 \(i\) 和 \(j\),那麼 \(j=n-i+1\),我們發現,當且僅當對於每對 \(i\),\(j\),都有 \((a_i+a_{j+1}) \bmod 26 = 0\) 時,該串滿足迴文串。
所以一開始我們可以將每對 \(a_i\) 和 \(a_{j+1}\) 合併,然後對於每個操作區間,由於原序列的區間修改等價於差分序列兩點修改,所以我們將 \(a_l\) 和 \(a_{r+1}\) 合併即可。
最後對於每個連通塊,判斷權值和 \(\bmod 26\) 是否為 \(0\),是則合法,否則輸出無解。
Summary
並查集好題,有一定的思維難度,轉換很巧妙。
T4 匹配 [圖的構建]
Description
在一個二維平面上有 \(n\) 個點,兩個點若橫座標或縱座標相等,則稱它們是可匹配的。
問平面上的點是否可以兩兩匹配。
Solution
將每個原圖的點記為圓點,把座標系中每個橫縱座標看成一個點,記為方點,每個圓點與它的橫縱座標(方點)分別連邊,問題轉換為在途中是否能找出 \(n/2\) 條端點互不相同的,端點都是圓點的,長度為 \(2\) 的鏈。
先求出該圖的生成樹,也可以直接 dfs,就沒這麼麻煩。自底向上匹配。
如果當前的是圓點,跳過。
如果是方點,將它的兒子節點(一定是圓點)且是沒匹配過的點兩兩配對,如果最後剩一個,將剩下的那個和該方點的父親(也一定是圓點)匹配。
最後檢查一遍所有點是否都被匹配過即可。
需要離散化。
Summary
解法有很多,重點在圖的構建,所以建模思維很重要。