Description

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

當波路特石站在一堆旋轉椅的地方時,他會用手不斷地旋轉這些椅子來促進他思考。有一天,他實在是懶到不想移動,懶到他只願意待在一個凸多邊形 $A$ 的範圍內,並撿起了身邊的一根棍子打算用它來旋轉椅子,可以見範例影片

為了旋轉椅子,波路特石會找到 $A$ 的其中一個頂點站定位,再試圖用棍子去戳椅子的邊邊,好讓椅子順時針旋轉。不過為了簡化問題,我們假設椅子是另一個凸多邊形 $B$,並且波路特石會選定在其身上的一條邊當做旋轉基準,以下圖為範例:

sample

在上圖中,波路特石站在凸多邊形 $A$ 的頂點 $p_i$,並選擇凸多邊形 $B$ 的邊 $\overline{q_{j}q_{j+1}}$ 當作旋轉基準後,拿著棍子使用與 $\overline{q_{j}q_{j+1}}$ 在平行的角度戳 $q_{j+1}$ 這個點來讓椅子順時針旋轉。

不過,波路特石發現手伸太長會很累,他發現,這個勞累程度會正比於他站的定點到選定邊形成直線的垂直距離,以上圖的例子就是 $p_i$ 到 $\overline{q_{j}q_{j+1}}$ 延長線的垂點 $h$、所形成線段 $\overline{p_ih}$ 的長度,當這個值越小,波路特石就覺得他轉起椅子來越輕鬆。因此,你必須完成兩個任務:

  • 任務一:你得實作出一個函式,在當波路特石詢問你一個站點 $p$、一條邊 $\overline{q_1q_2}$ 時,你都能回答出一個整數估計值,使得該估計值在固定 $\overline{q_1q_2}$ 的情況下,該值會正比於 $p$ 到 $\overline{q_1q_2}$ 的有向距離。而所謂有向距離,代表的是當要站在頂點 $p$ 戳 $q_2$ 這個點來旋轉椅子時,可能會需要使用正手、突刺或是反手的方式旋轉。注意到因為波路特石要讓椅子順時針旋轉,因此當要戳邊 $\overline{q_1q_2}$ 時,他一定得戳點 $q_2$ 來旋轉椅子,這唯一決定了使用正手、突刺還是反手的時機,可以參考下圖來了解:
sample

根據我們的定義,當旋轉的方式是正手時,垂直距離為正;當旋轉的方式是突刺時,垂直距離為零;當旋轉的方式是反手時,垂直距離為負。而上圖中的 $p_1, p_2, p_3$ 分別就提供了順時針旋轉中間凸多邊形時,需要使用正手、突刺還是反手的範例。$p_4$ 作為一個較為迥異的範例,當站在 $p_4$ 時,波路特石得戳比較外側的點才能讓凸多邊形順時針旋轉,儘管很難想像他會用什麼姿勢達成這項創舉,你可以假設他總是辦得到,一樣使用對應的垂直距離來幫他估計即可,當然,這個距離為負,因為他得使用反手的方式來旋轉。前面範例影片則是提供了一個正手旋轉的範例。

  • 任務二:波路特石希望,對於凸多邊形 $B$ 的每一條邊,你都能夠告訴他在最糟情況下,這個旋轉椅子的估計值絕對值會有多大,好讓波路特石迴避那些旋轉起來會特別累的邊。而這裡的估計值,就是你在任務一回傳的值。具體來說,你必須實作一支函式,在僅得知 $A$ 與 $B$ 點數的情況下,盡量少次地估計波路特石站在 $A$ 的指定頂點 $p_i$ 到 $B$ 的指定邊 $\overline{q_{j}q_{j+1}}$ 的有向垂直距離,並回傳一個陣列來告訴波路特石 $B$ 中的每個邊可以得到的最大估計值絕對值。

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

Implementation Details

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

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

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

long long calculate_distance(int px, int py, int qx1, int qy1, int qx2, int qy2);
  • 在一筆測試資料中,calculate_distance 會被呼叫至多 $750\ 000$ 次。
  • 引數 pxpy 是波路特石的站點 $p$。
  • 引數 qx1qy1 是波路特石要旋轉的邊的第一個點 $q_1$。
  • 引數 qx2qy2 是波路特石要旋轉的邊的第二個點 $q_2$,也是要被用來旋轉的施力點。
  • 回傳值必須為一個在 long long 範圍內的整數,滿足:
    • 當 $\overline{q_1q_2}$ 固定時,你回傳的估計值與 $p$ 到 $\overline{q_1q_2}$ 的有向垂直距離成正比。
    • 嚴謹地說,當 $\overline{q_1q_2}$ 固定時,存在一個正實數 $k$,滿足對於任的站點 $p$,令 $p$ 到 $\overline{q_1q_2}$ 的有向垂直距離是 $d$,則該回傳值為 $k\cdot d$。
    • 做為再次提醒,當旋轉的方式是正手時,垂直距離為正;當旋轉的方式是突刺時,垂直距離為零;當旋轉的方式是反手時,垂直距離為負。
std::vector<long long> find_minimum_distances(int N, int M);
  • 在一筆測試資料中,find_minimum_distances 會被呼叫至多 $500$ 次。
  • 引數 N 為凸多邊形 $A$ 的點數。
  • 引數 M 為凸多邊形 $B$ 的點數。
  • 回傳值必須為一個長度為 $M$ 的陣列,第 $j$ 項為凸多邊形 $B$ 中,要透過邊 $\overline{q_jq_{j+1}}$ 旋轉椅子時,估計值絕對值的最大值

你可以呼叫以下函式:

long long get_distance(int i, int j);
  • 引數 i 必須介於 $0\sim N - 1$ 之間,代表這次詢問要讓波路特石站在頂點 $p_i$ 進行測量。
  • 引數 j 必須介於 $0\sim M - 1$ 之間,代表這次詢問要讓波路特石利用邊 $\overline{q_{j}q_{j+1}}$ 來旋轉椅子。
  • 回傳值是一個整數 $d$,該值將會是你在 calculate_distance 估算出來的估計值。
  • get_distance 不得被呼叫超過 $\textbf{250\ 000}$ 次

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

Example

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


評測程式端 參賽者程式端
呼叫 find_minimum_distances(3, 3)
呼叫 get_distance(0, 0)
呼叫 calculate_distance(0, 0, 4, 2, 6, 2)
回傳 1
回傳 1
呼叫 get_distance(2, 0)
呼叫 calculate_distance(2, 2, 4, 2, 6, 2)
回傳 0
回傳 0
呼叫 get_distance(0, 1)
呼叫 calculate_distance(0, 0, 6, 2, 4, 4)
回傳 -4
回傳 -4
呼叫 get_distance(1, 1)
呼叫 calculate_distance(2, 0, 6, 2, 4, 4)
回傳 -3
回傳 -3
呼叫 get_distance(0, 2)
呼叫 calculate_distance(0, 0, 4, 4, 4, 2)
回傳 2
回傳 2
回傳 {1, 4, 2}

注意到在該範例互動中,get_distance 的實現方式是將 calculate_distance 的結果原封不動的傳回給參賽者程式端,但在正式的評分程式中可能不是以該方式實現。

Constraints

  • $3 \leq N, M \leq 500$
  • 所有 $N$ 的總和不超過 $1500$。
  • 所有 $M$ 的總和不超過 $1500$。
  • 凸多邊形 $A$ 和 $B$ 不會相交,且保證以 $0, 1, 2, \ldots$ 編號遞增順序遍歷兩個凸多邊形的頂點皆會是逆時針順序。
  • 凸多邊形 $A$ 和 $B$ 不會隨著互動過程而改變。
  • 所有點座標將介於 $[-10^ 6, 10^ 6]$ 之間。

Scoring

假設在所有子測試資料中,你呼叫 get_distance 的次數最大值為 $q$,你的得分 $S$ 由下列方式計算:

  • 如果 $q \leq 3\ 022$, $$S = 100$$
  • 如果 $3\ 022 < q \leq 3\ 075$,
    $$S = 100 - (q - 3022)^ {0.71}$$
  • 如果 $3\ 075 < q \leq 3\ 500$,
    $$S = 83 - \frac{22}{425}\cdot (q - 3075)$$
  • 如果 $3\ 500 < q \leq 40\ 000$,
    $$S = 61 - (q - 3500)^ {0.3}$$
  • 如果 $40\ 000 < q \leq 250\ 000$,
    $$S = 14$$

Input Format

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

首行輸入一個 $T$,代表子測試資料的數量,接著每一筆測試資料都以下列格式輸入:

  • line $1$: $N$
  • line $2+i (0\leq i < N)$: $p_{x, i}$ $p_{y, i}$
  • line $2+N$: $M$
  • line $3+N+i (0\leq i < M)$: $q_{x, i}$ $q_{y, i}$

Output Format

對於每一筆子測試資料,範例評分程式以下列方式輸出:

如果你的程式被判斷為 Accepted,範例評分程式會輸出 Accepted: q,其中 q 為呼叫 get_distance 的次數。接著輸出 $N$ 行,第 $j$ 行會是你回傳針對邊 $\overline{q_{j}q_{j+1}}$ 所得到的最大估計值絕對值。

如果你的程式被判斷為 Wrong Answer,範例評分程式會輸出 Wrong Answer: MSG,其中 MSG 以及其代表的意思為以下列表的其中一個:

  • invalid callget_distance 函式的呼叫不合法,也就是說,$i$ 不在 $0$ 至 $N - 1$ 的範圍內,或 $j$ 不在 $0$ 至 $M - 1$ 的範圍內。
  • too many queriesget_distance 呼叫的次數超過限制。
  • invalid return valuefind_minimum_distances 回傳的陣列長度不是 $M$。

如果有多個原因,範例評分程式只會輸出任何一個。

另外請注意,範例評分程式並不會幫你檢查你回傳的任何數值是否是正確的。這同時也代表著,就算你的 calculate_distance 回傳了錯的數值,範例評分程式也不會察覺。

Sample Input 1

1
3
0 0
2 0
2 2
3
4 2
6 2
4 4

Sample Output 1

Accepted: 9
1
4
2

Hints

範例評分程式提供了一個詢問 $250\ 000$ 次的實作,但並沒有正確實作 calculate_distance 的內容,因此,只要你能夠正確補上 calculate_distance 的實作,你就能拿到基本分數。

另外,在正式的評分程式中,calculate_distancefind_minimum_distances 的呼叫順序會略有不同,建議盡量只使用區域變數。若使用了全域變數,也請務必記得重設,更不要嘗試在這兩個函式內實作任何溝通技術來嘗試偷資料。

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

  • 如果你的系統是 Linux 或 MacOS,你可以直接執行 compile.sh 編譯你的程式,編譯結果會是 chair,請直接用命令列執行該檔案。
  • 如果你的系統是 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

IOICamp 2025 Day4 pD

Subtasks

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

Testdata and Limits

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