제출 #551714

#제출 시각아이디문제언어결과실행 시간메모리
551714tranxuanbachWorm Worries (BOI18_worm)C++17
100 / 100
517 ms5208 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

// #define endl '\n'
#define fi first
#define se second
#define For(i, l, r) for (auto i = (l); i < (r); i++)
#define ForE(i, l, r) for (auto i = (l); i <= (r); i++)
#define FordE(i, l, r) for (auto i = (l); i >= (r); i--)
#define Fora(v, a) for (auto v: (a))
#define bend(a) (a).begin(), (a).end()
#define isz(a) ((signed)(a).size())

using ll = long long;
using ld = long double;
using pii = pair <int, int>;
using vi = vector <int>;
using vpii = vector <pii>;
using vvi = vector <vi>;

mt19937 rando(chrono::steady_clock::now().time_since_epoch().count());
int randt(int l, int r, int k = 0){
    if (k > 0){
        return max(randt(l, r, k - 1), (int)(rando() % (r - l + 1)) + l);
    }
    if (k < 0){
        return min(randt(l, r, k + 1), (int)(rando() % (r - l + 1)) + l);
    }
    return rando() % (r - l + 1) + l;
}

const int SMALL = 5;

struct point3_t{
    int x, y, z;

    point3_t(): x(0), y(0), z(0){

    }

    point3_t(int x, int y, int z): x(x), y(y), z(z){

    }

    friend bool operator< (const point3_t &lhs, const point3_t &rhs){
        return tie(lhs.x, lhs.y, lhs.z) < tie(rhs.x, rhs.y, rhs.z);
    }
};

int n, m, k, q;

map <point3_t, int> mapquery;

int query(point3_t a){
    if (not (1 <= a.x and a.x <= n and 1 <= a.y and a.y <= m and 1 <= a.z and a.z <= k)){
        return 0;
    }
    if (mapquery.count(a)){
        return mapquery[a];
    }
    q--;
    cout << "? " << a.x << ' ' << a.y << ' ' << a.z << endl;
    int ans; cin >> ans; return (mapquery[a] = ans);
}

int query(int x, int y = 1, int z = 1){
    return query(point3_t(x, y, z));
}

int query_if(point3_t a){
    if (mapquery.count(a)){
        return mapquery[a];
    }
    return 0;
}

int query_if(int x, int y = 1, int z = 1){
    return query_if(point3_t(x, y, z));
}

void answer(point3_t a){
    cout << "! " << a.x << ' ' << a.y << ' ' << a.z << endl;
    #ifdef FEXT
    cout << "Q " << q << endl;
    #endif
    exit(0);
}

void answer(int x, int y = 1, int z = 1){
    answer(point3_t(x, y, z));
}

namespace subtask1{
    bool check(){
        return m == 1 and k == 1;
    }

    ld phi = (sqrtl(5) - 1) / 2;

    void solve(){
        int lo = 1, hi = n;

        int mid1 = (int)round(phi * (hi - lo)) + lo;
        while (lo < hi){
            int mid2 = (lo + hi) - mid1;
            if (mid1 == mid2){
                if (mid2 - 1 >= lo){
                    mid2--;
                }
                else{
                    mid2++;
                }
            }

            if (hi - lo + 1 >= 5 and abs(max(mid1, mid2) - ((int)round(phi * (hi - lo)) + lo)) >= 5){
                mid1 = (int)round(phi * (hi - lo)) + lo;
                mid2 = (lo + hi) - mid1;
            }

            if (query(mid1) > query(mid2)){
                if (mid1 < mid2){
                    hi = min(mid2, hi - 1);
                }
                else{
                    lo = max(mid2, lo + 1);
                }
            }
            else{
                if (mid1 < mid2){
                    lo = max(mid1, lo + 1);
                }
                else{
                    hi = min(mid1, hi - 1);
                }
                mid1 = mid2;
            }
        }
        answer(lo);
    }
}

namespace subtask2{
    bool check(){
        return k == 1;
    }

    void solve(){
        int lox = 1, hix = n, loy = 1, hiy = m;

        while (lox < hix or loy < hiy){
            int lenx = hix - lox + 1, leny = hiy - loy + 1;
            int mid = -1, val1 = 0, val2 = 0, val3 = 0, val4 = 0, val5 = 0;
            if (lenx >= leny){
                mid = (lox + hix) >> 1;
                ForE(y, loy, hiy){
                    val1 = max(val1, query_if(lox, y));
                    val2 = max(val2, query_if(hix, y));
                }
                ForE(x, lox, hix){
                    if (x <= mid){
                        val1 = max({val1, query_if(x, loy), query_if(x, hiy)});
                    }
                    else{
                        val2 = max({val2, query_if(x, loy), query_if(x, hiy)});
                    }
                }

                ForE(y, loy, hiy){
                    val3 = max(val3, query(mid, y));
                }
                if (val3 <= max(val1, val2)){
                    if (val1 > val2){
                        hix = mid;
                    }
                    else{
                        lox = mid + 1;
                    }
                    continue;
                }
                int yy = -1;
                ForE(y, loy, hiy){
                    if (query(mid, y) == val3){
                        yy = y;
                        val4 = max(val4, query(mid + 1, y));
                        val5 = max(val5, query(mid - 1, y));
                        break;
                    }
                }
                if (val3 >= max(val4, val5)){
                    answer(mid, yy);
                }
                if (val4 < val5){
                    hix = mid;
                }
                else{
                    lox = mid + 1;
                }
            }
            else{
                mid = (loy + hiy) >> 1;
                ForE(x, lox, hix){
                    val1 = max(val1, query_if(x, loy));
                    val2 = max(val2, query_if(x, hiy));
                }
                ForE(y, loy, hiy){
                    if (y <= mid){
                        val1 = max({val1, query_if(lox, y), query_if(hix, y)});
                    }
                    else{
                        val2 = max({val2, query_if(lox, y), query_if(hix, y)});
                    }
                }

                ForE(x, lox, hix){
                    val3 = max(val3, query(x, mid));
                }
                if (val3 <= max(val1, val2)){
                    if (val1 > val2){
                        hiy = mid;
                    }
                    else{
                        loy = mid + 1;
                    }
                    continue;
                }
                int xx = -1;
                ForE(x, lox, hix){
                    if (query(x, mid) == val3){
                        xx = x;
                        val4 = max(val4, query(x, mid + 1));
                        val5 = max(val5, query(x, mid - 1));
                        break;
                    }
                }
                if (val3 >= max(val4, val5)){
                    answer(xx, mid);
                }
                if (val4 < val5){
                    hiy = mid;
                }
                else{
                    loy = mid + 1;
                }
            }
        }
        answer(lox, loy);
    }
}

namespace subtask3{
    bool check(){
        return 1;
    }

    int dx[6] = {-1, 1, 0, 0, 0, 0};
    int dy[6] = {0, 0, -1, 1, 0, 0};
    int dz[6] = {0, 0, 0, 0, -1, 1};

    vi rd = {0, 1, 2, 3, 4, 5};

    void solve(){
        vector <pair <int, point3_t>> a;
        ForE(turn, 1, q / 2){
            int x = randt(1, n), y = randt(1, m), z = randt(1, k);
            a.emplace_back(query(x, y, z), point3_t(x, y, z));
        }
        sort(bend(a));
        point3_t u = a.back().se;
        while (q){
            if (q >= ((k + 9) / 10) * 2000){
                pair <int, point3_t> mx = {-1, point3_t()};
                For(d, 0, 6){
                    point3_t v = point3_t(u.x + dx[d], u.y + dy[d], u.z + dz[d]);
                    mx = max(mx, make_pair(query(v), v));
                }
                if (mx.fi > query(u)){
                    u = mx.se;
                }
                else{
                    answer(u);
                }
            }
            else{
                shuffle(bend(rd), rando);
                bool ck = 1;
                For(i, 0, 6){
                    int d = rd[i];
                    point3_t v = point3_t(u.x + dx[d], u.y + dy[d], u.z + dz[d]);
                    if (q and query(v) > query(u)){
                        u = v;
                        ck = 0;
                        break;
                    }
                }
                if (ck){
                    answer(u);
                }
            }
        }
        answer(u);
    }
}

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    // freopen("KEK.inp", "r", stdin);
    // freopen("KEK.out", "w", stdout);
    cin >> n >> m >> k >> q;

    if (subtask1::check()){
        subtask1::solve();
        return 0;
    }
    if (subtask2::check()){
        subtask2::solve();
        return 0;
    }
    if (subtask3::check()){
        subtask3::solve();
        return 0;
    }
}

/*
==================================================+
INPUT:                                            |
--------------------------------------------------|

--------------------------------------------------|
==================================================+
OUTPUT:                                           |
--------------------------------------------------|

--------------------------------------------------|
==================================================+
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...