本題為互動題,限用 C++ 作答。你可以在這裡找到範例實作以及範例評分程式,詳細注意事項以及常見問題請參考 Hints。
近年來,由於水果王國的科技業越來越發達,吸引了很多科技人才移民到水果王國,隨著人口的增長,住房也漸漸不夠了,因此水果王國開始實施了許多新社區的建設計劃。其中最受矚目的就是座落於首都近郊的無花果社區,這個社區規模龐大又鄰近科學園區,不僅有規劃住宅,更一併規劃了車站、商店街等設施來提升生活機能。
這個社區之所以叫無花果社區,是因為無花果是一種栽種歷史悠久的水果,而無花果社區所在的地區就是傳說中「水果古城」的所在地,水果古城是一座傳說中的城市,雖然一直以來都流傳著水果古城就在這附近的說法,但考古學家其實一直都沒有發現水果古城本體的遺址。不知道該說幸運還是不幸,在無花果社區開工後沒多久,工程團隊就發現這片土地下方確實藏著水果古城本體的遺址!雖然工程被迫暫停,但這也是水果王國考古史上的一大發現。
經過一些文獻研究,考古學家得知水果古城是由 $N$ 座高塔組成的,這 $N$ 座塔編號為 $0,1,\dots,N-1$,第 $i$ 座塔的高度是 $h_i$,每座塔的高度都是一個 $[1,C]$ 之內的整數。這些塔的編號是按照建造順序編號的,第 $0$ 座塔是最早建造的,而第 $N-1$ 座塔是最晚建造的,研究顯示,當古水果王國的人在建造這座城市的時候,除了最早建造的塔之外,每建造一座新的塔,就會挑選一座已經建好的塔,並在兩座塔之間建造一條雙向道路。正式地說,對於 $1 \leq i < N$,在建造完第 $i$ 座塔的同時,也會有一條連接第 $i$ 座塔與第 $p_i$ 座塔的道路被建造,滿足 $p_i < i$。也就是說,水果古城的路網由 $N-1$ 條道路組成。然而,由於文獻記載得不太清楚,考古學家並不知道 $h_0,h_1,\dots,h_{N-1}$ 與 $p_2,p_3,\dots,p_{N-1}$ 的確切數值。
工程團隊與考古學家們的計劃是這樣的:把水果古城的遺跡挖出來,安全的移到地面上,並且在這裡建造保護區與博物館,多餘的空間可以繼續建造本來預定的社區。這樣一來,這裡就不僅是個有優良生活機能的社區,更有了觀光與考古價值。然而,為了避免在挖掘過程中破壞古蹟,考古學家需要先調查出水果古城路網的長相與每座塔的高度,才能確保施工過程的安全。
為此,水果王國的聰明工程師們開發了一種專門用在這裡的探測器,雖然因為古城有一些神祕力量,探測器無法直接得知每座塔的高度,但可以對探測器輸入 $N$ 個數值 $t_0,t_1,\dots,t_{N-1}$,並且對於 $0 \leq i < N$,探測器會給予第 $i$ 座塔「能量值」$w_i=h_i+t_i$,並且對於每座塔 $i$,回傳一個數值 $c_i$,代表有道路跟 $i$ 直接相連的塔 $j$ 中,有多少座滿足
$$ w_j < w_i \text{ or } (w_i = w_j \text{ and } j < i) $$
舉例來說,若 $N=5$、$p_{1..N-1}=[0,1,2,3]$、$h=[1,5,6,4,0]$,對探測器輸入 $t=[1,0,-3,0,4]$ 後,每座塔的能量值是 $w=[2,5,3,4,4]$,探測器會回傳 $[0, 2, 0, 1, 1]$。
你可能已經發現這個探測器可能沒辦法找出所有 $h_i$ 的絕對數值,而是只能找出它們之間的相對高度,而考古學家很聰明,所以他們也只需要知道相對高度就好。使用探測器需要花費不少的錢,所以請你幫忙考古學家們在盡量節省成本的情況下,找到水果古城路網的長相,以及這些塔的相對高度 $d_i := h_i-h_0$。
詳細細節與評分方式請見後續段落。
你的程式需要在一開始使用前置處理器引入 lib1399.h,詳細請參考範例實作。
你需要完成以下函式:
std::pair<std::vector<int>, std::vector<int>> get_city_information(int N, int C);
get_city_information 會被呼叫若干次,每次呼叫都是不同且獨立的測試資料,若使用全域變數,有需要的話務必記得重置。N 為水果古城中塔的數量 $N$。C 為水果古城中塔的最高可能高度。std::pair,第一項為長度為 $N-1$ 的陣列 $p_1,p_2,\dots,p_{N-1}$,第二項為長度為 $N-1$ 的陣列 $d_1,\dots,d_{N-1}$。注意第二個陣列中不需要包含 $d_0$。你可以呼叫以下函式:
std::vector<int> count_lower_energy(const std::vector<long long> &t);
t 必須為一個長度為 $N$ 的陣列,且每個元素都在 $[-10^ {18}, 10^ {18}]$ 以內。get_city_information 的過程中,count_lower_energy 不得被呼叫超過 $\textbf{700}$ 次。如果任意一個條件沒有被滿足,你的程式會被判斷為 Wrong Answer 並且獲得 0 分,否則,你的程式將依照 Scoring 中的敘述評分。
| 評測程式端 | 參賽者程式端 |
|---|---|
呼叫 get_city_information(5, 1000000)。 | |
呼叫 count_lower_energy({1, 0, -3, 0, 4}) | |
回傳 {0, 2, 0, 1, 1}。 | |
呼叫 count_lower_energy({6, 0, 0, 0, 0}) | |
回傳 {1, 0, 2, 1, 0}。 | |
呼叫 count_lower_energy({0, 1, 0, 0, 4}) | |
回傳 {0, 1, 2, 0, 1}。 | |
回傳 {{0, 1, 2, 3}, {4, 5, 3, -1}}。 |
count_lower_energy 呼叫次數為 $q$,若 $q$ 超過 700,你會獲得 Wrong Answer 並得到 0 分。除了最後一筆子任務,只要 $q \leq 700$ 即可獲得滿分;對於最後一筆子任務,令 $S$ 為該子任務的滿分,你的得分會按照以下方式計算:
範例評分程式以下列方式輸入:
首行輸入一個 $T$,代表測試資料的數量,接著每一筆測試資料都以下列格式輸入:
對於每一筆測試資料,範例評分程式以下列方式輸出:
如果你的程式被判斷為 Accepted,範例評分程式會輸出 Accepted: q,其中 q 為呼叫 get_city_information 的次數。
如果你的程式被判斷為 Wrong Answer,範例評分程式會輸出 Wrong Answer: MSG,其中 MSG 以及其代表的意思為以下列表的其中一個:
too many queries:count_lower_energy 的呼叫次數超過 $700$。invalid call:count_lower_energy 函式的呼叫不合法,也就是說,t 不是一個長度為 $N$ 的陣列,或有元素不在 $[-10^ {18}, 10^ {18}]$ 以內。incorrect answer:get_city_information 回傳的答案不正確。如果有多個原因,範例評分程式只會輸出任何一個。一旦被判定為 Wrong Answer,程式就會被終止。
1 5 1000000 0 1 2 3 2 6 7 5 1
Accepted: 3
範例評分程式提供了一個可以通過編譯的實作,但上傳後不會得到任何分數。
另外,請注意在程式執行時 get_city_information 可能會被呼叫超過一次,建議盡量只使用區域變數。若使用了全域變數,也請務必記得重設。
由於 Windows Defender 以及各種奇怪東西的限制,本題的範例編譯指令不提供 Windows 批次檔。編譯及測試教學請參考下列說明。
ancient,請直接用命令列執行該檔案。#include "grader.cpp",並且以單一檔案的編譯執行方式測試,請注意這一行上傳時需要刪除,否則你會獲得一個 Compile Error。| No. | Testdata Range | Constraints | Score |
|---|---|---|---|
| 1 | 0 | 範例測資 | 0 |
| 2 | 1 | $N=2,\ C=350$ | 2 |
| 3 | 2 | $N=2,\ C=10^ 6$ | 3 |
| 4 | 3~7 | $p_i=0,\ C=10^ 6$ | 6 |
| 5 | 8~12 | $p_i=i-1,\ C=10^ 6$ | 9 |
| 6 | 13~22 | $N \leq 700,\ C=1$ | 4 |
| 7 | 23~30 | 在路網中,任一座塔與塔 $0$ 的最短距離不超過兩條道路、$C=1$ | 8 |
| 8 | 13~41 | $C=1$ | 13 |
| 9 | 42~68 | $C=10^ 6$ | 55 |