1. 程式人生 > 其它 >2019-2020 ICPC Asia Hong Kong Regional Contest

2019-2020 ICPC Asia Hong Kong Regional Contest

B - Binary Tree

噗 什麼演王題

考慮到每次取走的子樹大小必然為奇數。

所以判斷 \(n\) 的奇偶性即可。

C - Constructing Ranches

首先考慮一列數 \(a_{1\sim n}\) 可以構成簡單多邊形的一個簡潔的充要條件:\(2\cdot \max_i a_i <\sum_i a_i\)

然後大致的做法就比較清楚了,點分治統計合法路徑數。

對於兩條路徑,其路徑最大值分別為 \(x_1, x_2\),路徑和分別為 \(y_1,y_2\)。那麼簡單推導,產生貢獻的條件有:\(\begin{cases} x_2<x_1 \\ y_2 > 2x_1-y_1 \end{cases}\)

(其中 \(x_2<x_1\) 可以確定最大值)。

很顯然是一個二維偏序問題,使用容斥統計可以變成靜態問題,掃描線樹狀陣列可以解決。算上分治時間複雜度 \(O(n\log ^2 n)\)

一個細節就是,然後處理兩條路徑對接時分治中心的影響(單獨說一下是因為沒想清楚被卡了好久)。第一種方法是一開始不處理根,在後期統計時加上,但這樣會影響最大值以及和兩個指標,非常麻煩。而另一種方法是一開始就加上,這樣後期就只要在和上減掉重複統計的中心即可,而最大值則不用管,會方便不少。

D - Defining Labels

找規律。對於一個 \(10-\textit{based}\) 編號 \(X_kX_{k-1}\cdots X_1X_0\)

,其對應的十進位制真實值為 \(\sum_{i=0}^k (X_i +1) \times 10^i\)

類比到 \(k-\textit{based}\) 編號,只要做正常的進位制轉換,只是進入遞迴前將 \(X\) 減一,並加上 \(10-k\) 即可。

E - Erasing Numbers

又是神奇結論題。又是我不會的題。

首先發現 \(n\le 5000\),大概推測解法是對每個數都做一次 \(O(n)\) 的判斷。那麼對於每個數 \(x\) 做判斷時,可以發現我們在考慮其他數時,可以只考慮其與當前數 \(x\) 的大小關係。於是小於的記為 \(0\),大於為 \(1\)

然後有一個結論:如果序列中 \(0\)

的數量和 \(1\) 相等,那麼一定可以消到只剩下 \(x\)。可以發現,如果兩者分別都在 \(x\) 兩側的各一側,那麼一定可以操作 0x11x0 直到剩下 \(x\)。如果是混雜的,那一定可以找到一個位置 \(0,1\) 相鄰,然後使兩者的數目各減去一。

當然不可能都是相等的,那麼考慮將多出來的那個消去一些。注意到如果要消掉多餘的 \(0\),那麼只有 000 的情況是靠譜的。如果沒有連著的,我們可以消去中間將其隔開的 01 達到目的。

於是有了這樣的演算法:掃過去,每當出現一個子段 \(0\)\(1\) 多三個,就可以直接減掉兩個 \(0\)\(x\) 兩側各執行一次即可,直到數量相等則判斷成功。

複雜度 \(O(n^2)\)​,感覺不是那麼簡單的題,為啥過了這麼多啊。

G - Game Design

簡單構造。首先根比較有用我們使其點權為 \(10^9\),讓其對解數無影響。

考慮這個 \(K\) 實際必然是若干個數乘起來的結果,於是考慮在根上掛上若干條鏈,每條長度(點數)為 \(l\) 的鏈,我們令鏈上的點權為 \(1\),那麼就是 \(l\) 種方案。

於是不難想到質因數分解:\(K=\prod_i^k p_i^{c_i}\)​。那麼乘上一個 \(p\),就在根上掛一條 \(p\) 個點的鏈。

注意到我們有點數限制,而質因數分解就是為了把乘法變成加法使得點數為 \(\sum_i^k c_ip_i\)​ 規模。但如果 \(K\) 中存在一個巨大無比的質因子——或者說就是大質數(如 \(998244353\)),那點數還是太多。

考慮微操一下:我們嘗試將 \(K\)​ 減一。可以發現這樣其分解會有很大的變化,常數輪之後就沒有過大的質因子了。得到處理過的 \(K' = K- t\)​ 後,對應的,在根下建 \(t\)​ 一個新點,那幾條鏈連在這個新點而不是根上,新點的權值為鏈的數目。注意這時這些鏈由 \(K'\)​ 匯出。很顯然這時點數還是 \(O(\log K)\sim O(\log ^2 K)\) 左右,可以通過。

H - Hold the Line

單點加入(從無到有),區間查詢前驅後繼。線上的話,一看就是要維護動態的二維資訊,那麼一個線段樹套 set 的大常數 \(\log ^2\) 做法是顯然的。然而 \(n\le 5\cdot 10^5\) 這麼大的資料肯定過不了,但由於這動態的二維資訊擺在哪裡,正解應該是離線小常數的 \(O(n\log ^2 n)\)

掃描線。我們固定右端點 \(R\),這時 \(\le R\) 的插入操作就已更新。考慮維護用一個以權值為下標的線段樹,我們要求前驅或後繼,可以直接線上段樹上二分求解。每個線段樹結點儲存的是二維點集 \((t,p)\):插入時間 \(t\) 以及位置 \(p\)

於是,判斷一個線段樹結點是否包含可行點,只要查詢每個點左上區域是否存在點即可。然後就是一個 trick:若存在 \(A,B\) 兩點滿足 \(A\)\(B\) 的左上方,那麼 \(B\) 就完全沒用了。刪去所有這樣的 \(B\),餘下的點按 \(t\) 排序,\(p\) 也是單調的。這樣就變成一維問題了!判斷存在只要在單調點列上二分查詢即可。

然而我們要支援動態插入,好像又要用 set 了!但注意到,我們有一維是位置,而推進掃描線使得加入的點在位置上就是天然單調的,仔細一想其實只要 vector 就行了。

最後複雜度是 \(O(n\log ^2n)\)

I - Incoming Asteroids

跟著這題學了個新 trick /se

考慮每個任務的 \(k\) 都很小,那麼對這 \(k\) 個位置都設一個 \(\lfloor y/k \rfloor\) 的閾值。每當 \(k\) 個位置的其中一個達到了這個閾值就重構這個任務並重新放置。(要說這怎麼想到的……只能說 \(k\) 個位置都地位相等,自然閾值都相等;而要保證所設的閾值不能出現“完成了卻不知道”,最大的可行閾值就是 \(\lfloor y/k \rfloor\))。

複雜度不難證明,由於一次重構意味著減小 \(1/k\),那麼複雜度就是 \(O(n\log n\log y)\)。其中 \(\log n\) 是維護需要的資料結構的時間。

J - Junior Mathematician

擺明了是數位 dp。複習一下。

考慮我們記搜時要記錄那些資訊到狀態裡面:位數,是否有上界(基礎資訊,這裡似乎不需要判前導零),\(x\bmod m\)\(f(x)\bmod m\) 以及數位和。

但是這樣維度有點多,冷靜分析可以發現 \(x\bmod m,f(x)\bmod m\) 這兩個我們可以用一個 \(f(x)-x \bmod m\)​ 代替。

然後在轉移注意下細節和卡常就好啦。寫了個小丑 map 被卡爆了

本文來自部落格園,作者:-Wallace-,轉載請註明原文連結:https://www.cnblogs.com/-Wallace-/p/icpc2020-hk-rc.html