csacademy round 38 簡要題解

2022-05-16 09:50:43 字數 2918 閱讀 6233

shoe pairs

模擬即可

attack and speed

模擬即可

bounded difference

對於乙個滿足 \(|a_i-a_|\leq k\) 的 \(i\) ,將 \(i,\ i+1,\ i+2\) 標記為特殊點

不難發現特殊點個數過多顯然無解,否則對每個特殊點 \(x\) ,列舉剩下 \(n-1\) 個元素 \(y\) ,判定交換 \((x,\ y)\) 是否合法即可

path union

現在有乙個根節點 \(1\) 深度為 \(0\) ,深度為 \(n\) 的滿二叉樹,非葉子節點 \(k\) 的兩個兒子是 \(2k,\ 2k+1\)

對於每個 \(1\leq i\leq n\) ,你需要在深度為 \(i\) 的點中選 \(a_i\) 個點。對於乙個被選擇的點 \(u\) ,將根節點 \(1\) 到 \(u\) 這條路徑上所有的邊標記。你需要找到一組方案,最大化選擇完成後,被標記的邊的數量

做法一:

不難猜到乙個結論,記 \(b_i=\displaystyle\sum_^na_j\) ,則答案等於 \(\displaystyle\sum_^n\min(2^i,\ b_i)\) 。大概可以感性理解一下

既然如此,我們從小到大考慮 \(i\) ,往滿二叉樹中依次插入 \(a_i\) 個深度為 \(i\) 的點。在滿二叉樹上 dfs,我們決定當前點 \(k\) 向左 \(ls\) 或向右 \(rs\) 的依據是,記 \(ls\) 子樹中最淺的深度 \(j_\) 使得存在至少一條 \(ls\) 子樹中深度為 \(j\) 的點向父親連的邊未被標記,對 \(rs\) 同理求得 \(j_\) ,往 \(j\) 較小的一側走即可

實現時可以用 long long 維護每個點子樹的 \(j\) ,用 hashmap 存

時間複雜度 \(o(n\displaystyle\sum a_i)\) ,空間複雜度 \(o(n\displaystyle\sum a_i)\) ,大概需要卡常 /kk

做法二:

沿用做法一的思路,我們每選乙個點,必定會將整棵樹深度最淺的未被標記的邊之一 \(p\) 標記掉,而 \(p\) 的大小是 \(o(\displaystyle\sum a_i)\) 級別的

因此按 \(i\) 遞增插入每個點 \(u\) ,可以暴力列舉出 \(u\) 對應的 \(p\) ,在 \(p\) 的子樹中隨意選擇乙個深度為 \(i\) 的點作為 \(u\) 即可

時間複雜度可以做到 \(o(\displaystyle\sum a_i)\)

做法三:

找出最大的 \(i\) 滿足 \(b_i\ge2^i\) ,深度為 \(i\) 的所有點向父親連的邊均會被標記,且 \(i\) 是滿足該條件的最大值

深度小於 \(i\) 的點不用考慮,將 \(a_i\) 填給第 \(i\) 層的字尾,接著考慮深度大於 \(i\) 的部分

為了保證深度為 \(i\) 的點向其父親連的邊都被標記,先對於每個深度為 \(i\) 的節點的左兒子,在其子樹中匹配乙個深度大於 \(i\) 的點,然後再給每個右兒子匹配

由於 \(i\) 是最大的滿足 \(b_i\ge2^i\) 的,這樣匹配可以使用掉所有深度大於 \(i\) 的點

時間複雜度 \(o(n)\)

tree antichain (hard)

給定一棵 \(n\) 個點的樹,找到乙個 \(1,\ 2,\ \cdots,\ n\) 的排列 \(a_i\) ,滿足 \(\forall\ 1\leq i與 \(a_\) 在樹上沒有邊。找到字典序最小的一組解

\(t\leq10^4;\ n\leq10^5\)

將找排列看做二分圖匹配

對於排列 \(a_1,\ a_2,\ \cdots,\ a_n\) ,在開頭之前新增乙個起點,在末尾之後新增乙個終點,對於相鄰的兩個元素,在其間連一條邊

左部 \(n+1\) 個點,表示 \(1,\ 2,\ \cdots,\ n\) 和起點;右部 \(n+1\) 個點,表示 \(1,\ 2,\ \cdots\ n\) 和終點

左部點 \(i_l\) 與右部點 \(j_r\) 不能連邊當且僅當 \((i,\ j)\) 是樹上的一條邊

得到匹配後,從起點 dfs 一遍即可找到對應排列

用 hall 定理判定是否存在完美匹配,可以得到,對於任意乙個左部點點集 \(s\) ,存在 \(|s|+|\)每個 \(u\in s\) 的出邊的交\(|\leq n+1\)

觀察一下可以發現,順序確定排列的每個點,當前森林為刪掉所有已經確定的點及其出邊,不存在完美匹配當且僅當,當前只有乙個連通塊,且當前樹是乙個菊花圖

接著觀察一下,刪掉點 \(u\) 後不存在完美匹配,當且僅當 當前森林僅有 \(u\) 單獨形成的連通塊和乙個菊花圖,或是 當前森林僅有乙個連通塊 \(u\) 出度為 \(1\) ,且 \(u\) 唯一出邊 \(v\) 度數為 \(2\) ,刪掉點 \(u\) 及其出邊後整個連通塊存在恰好乙個度數大於 \(1\) 的點

用 \(set\) 維護沒有被選過的點的集合,模擬一下即可,時間複雜度 \(o(n\log n)\)

p.s.: 如果將樹黑白染色,當前森林不合法當且僅當連通塊個數為 \(1\) 且至少有一種顏色在當前森林中只有恰好乙個對應顏色的點,寫著很簡單

parallel lines

給定平面上 \(n\) 個點,找到最小的 \(k\) 使得能用恰好 \(k\) 條相互平行的直線覆蓋所有點,即每個點恰好在一條直線上。保證答案的 \(k\leq400\)

隨機化

考慮隨機兩個點 \(p,\ q\) ,以直線 \(pq\) 作為平行線之一暴力求一遍答案

不難發現對於答案的方案,至少有一條直線覆蓋了不少於 \(\frac nk\) 個點,故這樣做的正確率至少是 \(\frac 1\) 的

實際跑起來正確率蠻高的,不會證 /kk

需要對 \(n\) 較小的情況特殊處理(如 \(n\leq500\) )以保證複雜度

關於 0x3f3f3f3f 的問題

0x3f3f3f3f是乙個很有用的數值,它是滿足以下兩個條件的最大整數。1 整數的兩倍不超過 0x7f7f7f7f,即int能表示的最大正整數。2 整數的每8位 每個位元組 都是相同的。我們在程式設計中經常需要使用 memset a,val,sizeof a 初始化乙個陣列a,該語句把數值 val ...

0x3f3f3f3f(無窮大數)

一般定義無窮大數都是inf 99999999,或者0x7f ff ff ff,但是有的時候inf過大,雖然保證了沒有數超過它,但是在需要加上乙個數的時候,inf a可能會導致溢位,最終變成乙個負數。而0x3f3f3f3f的數量級也1e9的,一般題不會給超過1e9的數 在把它當成無窮大的時候,兩個0x...

Python3物件導向 3 異常(3)異常作用

當丟擲異常時,看起來好像立即停止了程式的執行。丟擲異常之後的所有 都不會執行,除非處理了這一異常,程式將會退出並給出錯誤資訊。def no return print i am about to raise an exception raise exception this is always rai...