LG 題解 P7345 【DSOI 2021】吟唱的金色花海
阿新 • • 發佈:2021-10-04
目錄
可以求出,又因為我們知道了 \((x_0,y_0)\) 和 \((sx,sy)\) 的曼哈頓距離為 \(t\),那我們就可以直接表示出 \((sx,sy)\)。
即可。
吐槽幾句
私以為鄙人之題解略易之與其他兩篇題解。
他們都寫的太長了,那麼多圖根本看不下去,還是我的比較清晰,程式碼也十分好寫。
Solution
主要思想就是二分。
首先題目給你了位置 \((x_0, y_0)\) 和一個時間 \(t\)。
因為從某個起點 \((sx, sy)\) 擴充套件 \(t\) 次後,\((x_0,y_0)\) 一定在它的邊界上。
所以我們可以搞出這麼一張圖。
可能有的人看到這個圖就瞬間明白了。下面再詳細說一下。
根據這個圖不難發現,我們只要找到 \((x_0,y_0)\) 的一個(關於 BD)的對稱點 \(F\),然後它到中點的距離 \(l\)
那麼這個點 \(F\) 怎麼求?想想那個 \(MAX\) 值為什麼帶了一個 \(\log\),就是讓我們用二分啊。
因此這個 \(F\) 的特徵就是最遠的被染成金色的鬱金香,我們可以二分 \((x_0,y_0)\) 這個點向右走幾步才能到達這個 \(F\)。
但是最遠的時候是 \(AD = 2t\),好像比需要的次數多 \(1\)。我們繼續觀察發現 \((x_0,y_0)\) 與 \(F\) 的距離一定為偶數,所以二分的範圍設為 \([1,t]\)
需要注意我們還要確定的一個資訊是延伸的方向,這個可以通過分別詢問它的右邊和下邊是否是金色鬱金香得到。
所以總的詢問次數為 \(\log t + 2 \le MAX\),可以通過。
實現細節看程式碼吧。
Code
/* Work by: Suzt_ilymics Problem: 不知名屑題 Knowledge: 垃圾演算法 Time: O(能過) */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define LL long long #define orz cout<<"lkp AK IOI!"<<endl using namespace std; const int MAXN = 1e5+5; const int INF = 1e9+7; const int mod = 1e9+7; int T, t, sx, sy, k; int read(){ int s = 0, f = 0; char ch = getchar(); while(!isdigit(ch)) f |= (ch == '-'), ch = getchar(); while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar(); return f ? -s : s; } int main() { T = read(); while(T--) { t = read(), sx = read(), sy = read(), k = read(); if(t == 0) { printf("1 %d %d\n", sx, sy); fflush(stdout); continue; } int fx1, fx2, x; // 1 表示上左,2 表示下右 printf("0 %d %d\n", sx + 1, sy); fflush(stdout); x = read(); if(x) fx1 = 1; else fx1 = -1; printf("0 %d %d\n", sx, sy + 1); fflush(stdout); x = read(); if(x) fx2 = 1; else fx2 = -1; // 用 1/-1 方便後面的計算 int l = 1, r = t, ans = 0; while(l <= r) { int mid = (l + r) >> 1; printf("0 %d %d\n", sx, sy + 2 * fx2 * mid); fflush(stdout); x = read(); if(x) ans = mid, l = mid + 1; else r = mid - 1; } int ex = sx, ey = sy + 2 * fx2 * ans; // 求得的 F 點 int Mid = (sy + ey) / 2; int ty = Mid, tx = sx + fx1 * (t - abs(Mid - ey)); // 直接求出終點 printf("1 %d %d\n", tx, ty); fflush(stdout); } return 0; }