User's AC Ratio

77.8% (14/18)

Submission's AC Ratio

10.7% (22/206)

Tags

Description

本題為互動題,限用 C++ 作答。你可以在這裡找到範例實作以及範例評分程式,詳細注意事項以及常見問題請參考 Hints。

你遇到了祥子,她手上有一些有根樹,她希望你幫她的樹賦權。

具體來說,祥子會先用深度優先搜索的前序遍歷每一棵樹,並稱第 $i$ 個拜訪到的節點編號為 $i$。接著她會用一個隨機的順序問你每個點,你要再幫每個點賦上一個權重,除了給你點的編號外,她也會給你與該點直接相鄰的點的編號。

有了權重資訊後,祥子會幫樹的每條邊標成黑的或白的,方法如下步驟:

  1. 將所有邊都標成黑色的。
  2. 將每個節點的權重替換成該節點與其子樹節點中權重的最大值。
  3. 對於每個節點,如果它有至少一個小孩跟它的權重一樣,則會挑一條連接同權重小孩的邊,將其染成白色。

祥子希望對於任兩個點之間的路徑都不能包含超過 $2\lfloor \log_2(N) \rfloor$ 條黑邊,其中 $N$ 是樹的節點數量。請幫幫她完成賦權。

詳細細節與評分方式請見後續段落。

Implementation Details

本題請不要使用標準輸入輸出流,不過你仍然可以輸出除錯訊息至標準錯誤流(stderr)。

你的程式需要在一開始使用前置處理器引入 lib0913.h,詳細請參考範例實作。

你需要完成以下的兩個函式:

void Init(int N);
  • 在一筆測試資料中,Init 會被呼叫恰 $T$ 次。
  • 引數 N 代表這棵樹的節點數量。
  • 節點的編號為 $1, 2, \ldots, N$,且為一前序遍歷的結果。
int GetId(int x, std::vector<int> nearby);
  • 在一筆測試資料中,GetId 會被呼叫至多 $500\ 000$ 次。
  • 呼叫完 Init(N) 後會呼叫恰 $N$ 次 GetId,且保證 $N$ 次傳入的的 x 都不一樣。在這 $N$ 次 GetId 呼叫結束前,不會有任何的 Init 呼叫。
  • 引數 x 代表節點的編號,且 $1 \leq x \leq N$。
  • 引數 nearby 代表節點 $x$ 的鄰居。
  • 回傳值必須為一個介於 $-2^ {31}$ 到 $2^ {31} - 1$ 的整數,代表你要幫編號為 $x$ 的節點賦上的權重。
  • 呼叫完一次 Init(N) 與 $N$ 次 GetId 後,評測系統會幫你用題目敘述中描述的方式連邊,你必須要確保連邊後任兩個點的路徑都不能包含超過 $2\lfloor \log_2(N) \rfloor$ 條黑邊。

如果任意一個條件沒有被滿足,你的程式會被判斷為 Wrong Answer 並且獲得 0 分,否則,你的程式將依照 Scoring 中的敘述評分。

Example

假設 $T = 2$,一個被判斷為 Accepted 的範例互動狀況如下:


評測程式端 參賽者程式端
呼叫 Init(8)
呼叫 GetId(1, {2})
回傳 1
呼叫 GetId(3, {2, 4})
回傳 3
呼叫 GetId(4, {3, 5})
回傳 4
呼叫 GetId(7, {6, 8})
回傳 7
呼叫 GetId(6, {5, 7})
回傳 6
呼叫 GetId(8, {7})
回傳 8
呼叫 GetId(2, {1, 3})
回傳 2
呼叫 GetId(5, {4, 6})
回傳 5
呼叫 Init(4)
呼叫 GetId(2, {1})
回傳 2
呼叫 GetId(1, {2, 3})
回傳 1
呼叫 GetId(3, {1, 4})
回傳 3
呼叫 GetId(4, {3})
回傳 4

Constraints

  • $1 \leq T \leq 5 \times 10^ 5$
  • $1 \leq N \leq 5 \times 10^ 5$
  • 所有的 $N$ 加起來 $\leq 5 \times 10^ 5$

Scoring

假設在所有測試資料中,你都順利達成題目敘述的條件,那你會獲得 $100$ 分。

Input Format

範例評分程式以下列方式輸入:

  • line $1$: $T$ $seed$
  • line $2i$: $N$
  • line $2i + 1$: $p_2$ $p_3$ $\ldots$ $p_N$

$T$ 代表測試資料的數量,$seed$ 代表範例評分程式用於決定 GetId 詢問順序的偽隨機種子。
請注意範例評分程式中決定 GetId 的方式不一定與實際評分所使用的方法相同。

每一筆測試資料中 $p_i$,代表該樹第 $i$ 個節點的父親為 $p_i$。請注意編號為 $1$-based。範例評分程式會幫你按照前序遍歷重新編號,意即:你傳入的樹編號不需為一前序遍歷的結果。

Output Format

範例評分程式以下列方式輸出:

如果你的程式被判斷為 Accepted,範例評分程式會輸出 Accepted

如果你的程式被判斷為 Wrong Answer,範例評分程式會輸出 Wrong answer: i to j passes x black edges, limit = y,其中 $i$ 與 $j$ 為兩個沒符合條件的節點,該兩點之間有 $x$ 條黑邊,而限制為 $y$ 條。

另外請注意,範例評分程式的運行效率較慢,若需要更高速的效率請自行修改。

Sample Input 1

2 1145147122
8
1 2 3 4 5 6 7
4
1 1 3

Sample Output 1


        

Hints

由於 Windows Defender 以及各種奇怪東西的限制,本題的範例編譯指令不提供 Windows 批次檔。編譯及測試教學請參考下列說明。

  • 如果你的系統是 Linux,你可以直接執行 compile.sh 編譯你的程式,編譯結果會是 ordered-tree.exe,請直接用命令列執行該檔案。
  • 如果你的系統是 MacOS,你需要將 compile.sh 當中的 -static 參數移除,其餘與 Linux 相同。
  • 如果你的系統是 Windows,你有以下的選擇:
    1. 本地測試時加入 #include "grader.cpp",並且以單一檔案的編譯執行方式測試,請注意這一行上傳時需要刪除,否則你會獲得一個 Compile Error。
    2. 將 compile.sh 的變數替換後直接於命令列執行,請注意你需要確保 g++ 在系統的環境變數 PATH 中。
    3. 如果你的電腦已經有 WSL (Windows Subsystem for Linux),你可以直接使用 WSL 並按照 Linux 的做法。
    4. 使用電腦教室的 Ubuntu(啟動時可以選擇系統)並按照 Linux 的做法。

Problem Source


Subtasks

No. Testdata Range Constraints Score
1 0 範例測資 0
2 0~30 無額外限制 100

Testdata and Limits

No. Time Limit (ms) Memory Limit (VSS, KiB) Output Limit (KiB) Subtasks
0 1000 262144 65536 1 2
1 1000 262144 65536 2
2 1000 262144 65536 2
3 1000 262144 65536 2
4 1000 262144 65536 2
5 1000 262144 65536 2
6 1000 262144 65536 2
7 1000 262144 65536 2
8 1000 262144 65536 2
9 1000 262144 65536 2
10 1000 262144 65536 2
11 1000 262144 65536 2
12 1000 262144 65536 2
13 1000 262144 65536 2
14 1000 262144 65536 2
15 1000 262144 65536 2
16 1000 262144 65536 2
17 1000 262144 65536 2
18 1000 262144 65536 2
19 1000 262144 65536 2
20 1000 262144 65536 2
21 1000 262144 65536 2
22 1000 262144 65536 2
23 1000 262144 65536 2
24 1000 262144 65536 2
25 1000 262144 65536 2
26 1000 262144 65536 2
27 1000 262144 65536 2
28 1000 262144 65536 2
29 1000 262144 65536 2
30 1000 262144 65536 2