はまやんはまやんはまやん

hamayanhamayan's blog

壊れた宝物発見機 [yukicoder No.594]

https://yukicoder.me/problems/no/594

前提知識

解法

https://yukicoder.me/submissions/216172

各座標について独立に決めていく。
[-100,100]の中で最も答えに近い所がその座標での答えとなるが、これは三分探索で求める。
これを3軸についてやるだけ。
 
今回は一発で通ったので、特に書いてないが、リアクティブ問題ではask関数を別途分けておくと、
手前でデバッグするときにコードを埋め込みやすいのでオススメ。

template<typename Func>
int findMin(int L, int R, Func f) { //[L, R)
    int lo = L - 1, hi = R - 1;
    while (lo + 1 != hi) {
        int mi = (lo + hi) / 2;
        if (f(mi) <= f(mi + 1)) hi = mi;
        else lo = mi;
    }
    return hi;
}
//---------------------------------------------------------------------------------------------------
int ask(int x, int y, int z) {
    printf("? %d %d %d\n", x, y, z);
    fflush(stdout);
    int d; cin >> d;
    return d;
}
void answer(int x, int y, int z) {
    printf("! %d %d %d\n", x, y, z);
    fflush(stdout);
}
//---------------------------------------------------------------------------------------------------
int ans[3];
int ii;
void _main() {
    rep(i, 0, 3) {
        ii = i;
        ans[i] = findMin(-100, 101, [](int x) {
            ans[ii] = x;
            return ask(ans[0], ans[1], ans[2]);
        });
    }
    answer(ans[0], ans[1], ans[2]);
}