{"model_name":"kimi-k2.6","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nint n;\nvector<int> X, Y, R;\nvector<int> a, b, c, d;\nvector<ll> area;\nvector<double> pval;\ndouble score = 0.0;\n\ndouble calc_p(int idx, ll s) {\n    if (s <= 0) return 0.0;\n    double t;\n    if (s < R[idx]) t = (double)s / (double)R[idx];\n    else t = (double)R[idx] / (double)s;\n    return 1.0 - (1.0 - t) * (1.0 - t);\n}\n\n// side: 0=a, 1=c, 2=b, 3=d\npair<int,int> get_range(int i, int side) {\n    int L, Rv;\n    if (side == 0) {\n        L = 0;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) {\n                L = max(L, c[j]);\n            }\n        }\n        Rv = X[i];\n    } else if (side == 1) {\n        L = X[i] + 1;\n        Rv = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) {\n                Rv = min(Rv, a[j]);\n            }\n        }\n    } else if (side == 2) {\n        L = 0;\n        Rv = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) {\n                L = max(L, d[j]);\n            }\n        }\n    } else {\n        L = Y[i] + 1;\n        Rv = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) {\n                Rv = min(Rv, b[j]);\n            }\n        }\n    }\n    return {L, Rv};\n}\n\n// compute optimal integer value for side in [L,Rv] to bring area closest to R[i]\nint get_optimal(int i, int side, int L, int Rv) {\n    int opt;\n    if (side == 0) {\n        ll h = d[i] - b[i];\n        int best_w = (int)round((double)R[i] / (double)h);\n        if (best_w < 1) best_w = 1;\n        opt = c[i] - best_w;\n    } else if (side == 1) {\n        ll h = d[i] - b[i];\n        int best_w = (int)round((double)R[i] / (double)h);\n        if (best_w < 1) best_w = 1;\n        opt = a[i] + best_w;\n    } else if (side == 2) {\n        ll w = c[i] - a[i];\n        int best_h = (int)round((double)R[i] / (double)w);\n        if (best_h < 1) best_h = 1;\n        opt = d[i] - best_h;\n    } else {\n        ll w = c[i] - a[i];\n        int best_h = (int)round((double)R[i] / (double)w);\n        if (best_h < 1) best_h = 1;\n        opt = b[i] + best_h;\n    }\n    if (opt < L) opt = L;\n    if (opt > Rv) opt = Rv;\n    return opt;\n}\n\nvoid apply_move(int i, int side, int nv) {\n    if (side == 0) a[i] = nv;\n    else if (side == 1) c[i] = nv;\n    else if (side == 2) b[i] = nv;\n    else d[i] = nv;\n    ll new_area = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n    area[i] = new_area;\n    double new_p = calc_p(i, new_area);\n    score += new_p - pval[i];\n    pval[i] = new_p;\n}\n\nvoid greedy_pass(mt19937_64& rng) {\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int idx = 0; idx < n; ++idx) {\n        int i = order[idx];\n        double best_delta = 1e-12;\n        int best_side = -1;\n        int best_val = -1;\n        for (int side = 0; side < 4; ++side) {\n            auto [L, Rv] = get_range(i, side);\n            int cur = (side == 0 ? a[i] : (side == 1 ? c[i] : (side == 2 ? b[i] : d[i])));\n            int opt = get_optimal(i, side, L, Rv);\n            if (opt == cur) continue;\n            ll new_area;\n            if (side == 0) new_area = 1LL * (c[i] - opt) * (d[i] - b[i]);\n            else if (side == 1) new_area = 1LL * (opt - a[i]) * (d[i] - b[i]);\n            else if (side == 2) new_area = 1LL * (c[i] - a[i]) * (d[i] - opt);\n            else new_area = 1LL * (c[i] - a[i]) * (opt - b[i]);\n            double new_p = calc_p(i, new_area);\n            double delta = new_p - pval[i];\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_side = side;\n                best_val = opt;\n            }\n        }\n        if (best_side != -1) {\n            apply_move(i, best_side, best_val);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n;\n    X.resize(n);\n    Y.resize(n);\n    R.resize(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> X[i] >> Y[i] >> R[i];\n    }\n    \n    a.resize(n);\n    b.resize(n);\n    c.resize(n);\n    d.resize(n);\n    area.resize(n);\n    pval.resize(n);\n    \n    // initial 1x1 cells\n    for (int i = 0; i < n; ++i) {\n        a[i] = X[i];\n        b[i] = Y[i];\n        c[i] = X[i] + 1;\n        d[i] = Y[i] + 1;\n        area[i] = 1;\n        pval[i] = calc_p(i, 1);\n        score += pval[i];\n    }\n    \n    mt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_n(0, n - 1);\n    uniform_int_distribution<int> dist_side(0, 3);\n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n    \n    // --- Greedy initialization ---\n    for (int pass = 0; pass < 100; ++pass) {\n        double old_score = score;\n        greedy_pass(rng);\n        if (score <= old_score + 1e-9) break;\n    }\n    \n    double best_score = score;\n    vector<int> best_a = a, best_b = b, best_c = c, best_d = d;\n    \n    // --- Simulated Annealing ---\n    auto start = chrono::steady_clock::now();\n    const double TL = 4.85; // seconds\n    \n    long long iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 2047) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > TL) break;\n        }\n        \n        int i = dist_n(rng);\n        int side = dist_side(rng);\n        auto [L, Rv] = get_range(i, side);\n        int cur = (side == 0 ? a[i] : (side == 1 ? c[i] : (side == 2 ? b[i] : d[i])));\n        if (L >= Rv) continue;\n        \n        int opt = get_optimal(i, side, L, Rv);\n        int nv;\n        double r = dist_01(rng);\n        if (r < 0.5) {\n            nv = opt;\n        } else if (r < 0.8) {\n            int delta = (int)(dist_01(rng) * 201) - 100;\n            nv = opt + delta;\n        } else {\n            nv = L + (int)(dist_01(rng) * (Rv - L + 1));\n        }\n        if (nv < L) nv = L;\n        if (nv > Rv) nv = Rv;\n        if (nv == cur) continue;\n        \n        ll new_area;\n        if (side == 0) new_area = 1LL * (c[i] - nv) * (d[i] - b[i]);\n        else if (side == 1) new_area = 1LL * (nv - a[i]) * (d[i] - b[i]);\n        else if (side == 2) new_area = 1LL * (c[i] - a[i]) * (d[i] - nv);\n        else new_area = 1LL * (c[i] - a[i]) * (nv - b[i]);\n        \n        double new_p = calc_p(i, new_area);\n        double delta = new_p - pval[i];\n        \n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        double T = 0.05 * pow(1e-5 / 0.05, elapsed / TL);\n        \n        if (delta > 0.0 || dist_01(rng) < exp(delta / T)) {\n            apply_move(i, side, nv);\n            if (score > best_score) {\n                best_score = score;\n                best_a = a; best_b = b; best_c = c; best_d = d;\n            }\n        }\n    }\n    \n    // restore best and final greedy polish\n    a = best_a; b = best_b; c = best_c; d = best_d;\n    score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        area[i] = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n        pval[i] = calc_p(i, area[i]);\n        score += pval[i];\n    }\n    for (int pass = 0; pass < 30; ++pass) {\n        double old_score = score;\n        greedy_pass(rng);\n        if (score <= old_score + 1e-9) break;\n    }\n    \n    // output\n    for (int i = 0; i < n; ++i) {\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    const int N = 50;\n    vector<vector<int>> tile(N, vector<int>(N));\n    int M = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tile[i][j];\n            M = max(M, tile[i][j] + 1);\n        }\n    }\n    vector<vector<int>> p(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> p[i][j];\n        }\n    }\n    \n    const int dr[4] = {-1, 1, 0, 0};\n    const int dc[4] = {0, 0, -1, 1};\n    const char dch[4] = {'U', 'D', 'L', 'R'};\n    auto inside = [&](int i, int j) {\n        return i >= 0 && i < N && j >= 0 && j < N;\n    };\n    \n    // linearized cell data\n    const int V = N * N;\n    vector<int> cell_tile(V);\n    vector<int> cell_val(V);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            cell_tile[id] = tile[i][j];\n            cell_val[id] = p[i][j];\n        }\n    }\n    \n    string best_path;\n    int best_score = -1;\n    \n    auto update_best = [&](const string& path, int score) {\n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n        }\n    };\n    \n    const int BSET = (2500 + 63) / 64; // 40\n    \n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    // ============================================================\n    // 1. Beam Search\n    // ============================================================\n    {\n        struct Node {\n            int score;\n            int parent;\n            uint16_t pos;\n            char move;\n        };\n        const int BEAM_WIDTH = 2000;\n        vector<Node> nodes;\n        nodes.reserve(BEAM_WIDTH * 2500);\n        auto add_node = [&](int score, int parent, int pos, char move) -> int {\n            nodes.push_back({score, parent, static_cast<uint16_t>(pos), move});\n            return (int)nodes.size() - 1;\n        };\n        \n        struct BeamState {\n            int node_id;\n            array<uint64_t, BSET> vis;\n        };\n        struct Candidate {\n            int score;\n            int pos;\n            int parent;\n            char move;\n            int eval;\n            array<uint64_t, BSET> vis;\n        };\n        \n        int start_pos = si * N + sj;\n        int start_tile = cell_tile[start_pos];\n        array<uint64_t, BSET> start_vis{};\n        start_vis[start_tile >> 6] |= 1ULL << (start_tile & 63);\n        int start_node = add_node(cell_val[start_pos], -1, start_pos, 0);\n        \n        vector<BeamState> cur;\n        cur.reserve(BEAM_WIDTH);\n        cur.push_back({start_node, start_vis});\n        \n        int beam_best_node = start_node;\n        int beam_best_score = cell_val[start_pos];\n        \n        for (int layer = 0; !cur.empty(); ++layer) {\n            if ((layer & 255) == 0 && elapsed() > 1.0) break;\n            \n            // record best among current prefixes\n            for (auto &st : cur) {\n                int sc = nodes[st.node_id].score;\n                if (sc > beam_best_score) {\n                    beam_best_score = sc;\n                    beam_best_node = st.node_id;\n                }\n            }\n            \n            vector<Candidate> cands;\n            cands.reserve(cur.size() * 3);\n            for (auto &st : cur) {\n                int nid = st.node_id;\n                int r = nodes[nid].pos / N;\n                int c = nodes[nid].pos % N;\n                int cur_score = nodes[nid].score;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (!inside(nr, nc)) continue;\n                    int npos = nr * N + nc;\n                    int nt = cell_tile[npos];\n                    if ((st.vis[nt >> 6] >> (nt & 63)) & 1ULL) continue;\n                    int nscore = cur_score + cell_val[npos];\n                    array<uint64_t, BSET> nvis = st.vis;\n                    nvis[nt >> 6] |= 1ULL << (nt & 63);\n                    int onward = 0;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int nr2 = nr + dr[d2];\n                        int nc2 = nc + dc[d2];\n                        if (!inside(nr2, nc2)) continue;\n                        int nt2 = cell_tile[nr2 * N + nc2];\n                        if ((nvis[nt2 >> 6] >> (nt2 & 63)) & 1ULL) continue;\n                        ++onward;\n                    }\n                    int eval = nscore + onward * 40;\n                    cands.push_back({nscore, npos, nid, dch[d], eval, nvis});\n                }\n            }\n            if (cands.empty()) break;\n            \n            vector<int> order(cands.size());\n            iota(order.begin(), order.end(), 0);\n            if ((int)order.size() > BEAM_WIDTH) {\n                nth_element(order.begin(), order.begin() + BEAM_WIDTH, order.end(),\n                    [&](int a, int b) {\n                        return cands[a].eval > cands[b].eval;\n                    });\n                order.resize(BEAM_WIDTH);\n            }\n            \n            cur.clear();\n            cur.reserve(order.size());\n            for (int idx : order) {\n                auto &cand = cands[idx];\n                int new_nid = add_node(cand.score, cand.parent, cand.pos, cand.move);\n                cur.push_back({new_nid, cand.vis});\n            }\n        }\n        \n        // reconstruct best beam path\n        string path;\n        int cur_node = beam_best_node;\n        while (nodes[cur_node].parent != -1) {\n            path.push_back(nodes[cur_node].move);\n            cur_node = nodes[cur_node].parent;\n        }\n        reverse(path.begin(), path.end());\n        update_best(path, beam_best_score);\n    }\n    \n    // ============================================================\n    // 2. Randomized Greedy with Warnsdorff-like heuristic\n    // ============================================================\n    {\n        mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n        vector<char> vis(M);\n        int cand_dir[4];\n        int cand_deg[4];\n        int cand_val[4];\n        int cand_pri[4];\n        \n        while (elapsed() < 1.95) {\n            fill(vis.begin(), vis.end(), 0);\n            int r = si, c = sj;\n            int start_id = r * N + c;\n            vis[cell_tile[start_id]] = 1;\n            int cur_score = cell_val[start_id];\n            string path;\n            path.reserve(2000);\n            \n            int mode = (int)(rng() % 5);\n            int w_val, w_deg, noise;\n            if (mode == 0) {        // value oriented\n                w_val = 100; w_deg = 5; noise = 50;\n            } else if (mode == 1) { // degree oriented (Warnsdorff)\n                w_val = 5; w_deg = 100; noise = 50;\n            } else if (mode == 2) { // balanced\n                w_val = 50; w_deg = 50; noise = 80;\n            } else if (mode == 3) { // random\n                w_val = 0; w_deg = 0; noise = 1000;\n            } else {                // strong Warnsdorff, weak value\n                w_val = 20; w_deg = 80; noise = 60;\n            }\n            \n            while (true) {\n                int cand_cnt = 0;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d];\n                    int nc = c + dc[d];\n                    if (!inside(nr, nc)) continue;\n                    int npos = nr * N + nc;\n                    int nt = cell_tile[npos];\n                    if (vis[nt]) continue;\n                    \n                    int deg = 0;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int nr2 = nr + dr[d2];\n                        int nc2 = nc + dc[d2];\n                        if (!inside(nr2, nc2)) continue;\n                        int nt2 = cell_tile[nr2 * N + nc2];\n                        if (!vis[nt2]) ++deg;\n                    }\n                    cand_dir[cand_cnt] = d;\n                    cand_deg[cand_cnt] = deg;\n                    cand_val[cand_cnt] = cell_val[npos];\n                    int pri = cand_val[cand_cnt] * w_val - cand_deg[cand_cnt] * w_deg + (int)(rng() % noise);\n                    cand_pri[cand_cnt] = pri;\n                    ++cand_cnt;\n                }\n                if (cand_cnt == 0) break;\n                \n                int best_i = 0;\n                for (int i = 1; i < cand_cnt; ++i) {\n                    if (cand_pri[i] > cand_pri[best_i]) best_i = i;\n                }\n                int d = cand_dir[best_i];\n                r += dr[d];\n                c += dc[d];\n                int npos = r * N + c;\n                vis[cell_tile[npos]] = 1;\n                cur_score += cell_val[npos];\n                path.push_back(dch[d]);\n            }\n            \n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_path = path;\n            }\n        }\n    }\n    \n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const double MINW = 1000.0;\n    const double MAXW = 9000.0;\n    const double LR   = 0.5;\n\n    // edge estimates and visit counts\n    vector<vector<double>> est_h(N, vector<double>(N - 1, 5000.0));\n    vector<vector<double>> est_v(N - 1, vector<double>(N, 5000.0));\n    vector<vector<int>>    cnt_h(N, vector<int>(N - 1, 0));\n    vector<vector<int>>    cnt_v(N - 1, vector<int>(N, 0));\n\n    double global_mean = 5000.0;          // moving average for unseen edges\n\n    for (int query = 0; query < 1000; ++query) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        /* ---- exploration schedule ---- */\n        double explore = 0.0;\n        if (query < 200)       explore = 0.5;\n        else if (query < 400)  explore = 0.25;\n        else if (query < 700)  explore = 0.1;\n\n        int S = si * N + sj;\n        int T = ti * N + tj;\n        const int V = N * N;\n        const double INF = 1e100;\n\n        vector<double> dist(V, INF);\n        vector<pair<int,char>> prv(V, {-1, 0});\n        using State = pair<double,int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[S] = 0.0;\n        pq.emplace(0.0, S);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d > dist[v] + 1e-9) continue;\n            if (v == T) break;\n\n            int i = v / N;\n            int j = v % N;\n\n            auto relax = [&](int ni, int nj, bool is_h, int ei, int ej, char dir) {\n                int u = ni * N + nj;\n                double base;\n                int c;\n                if (is_h) {\n                    base = est_h[ei][ej];\n                    c    = cnt_h[ei][ej];\n                } else {\n                    base = est_v[ei][ej];\n                    c    = cnt_v[ei][ej];\n                }\n                double w = base * (1.0 - explore / sqrt((double)c + 1.0));\n                if (w < 1.0) w = 1.0;\n                if (dist[u] > d + w) {\n                    dist[u] = d + w;\n                    prv[u]  = {v, dir};\n                    pq.emplace(dist[u], u);\n                }\n            };\n\n            if (i > 0)     relax(i - 1, j,     false, i - 1, j,     'U');\n            if (i + 1 < N) relax(i + 1, j,     false, i,     j,     'D');\n            if (j > 0)     relax(i,     j - 1, true,  i,     j - 1, 'L');\n            if (j + 1 < N) relax(i,     j + 1, true,  i,     j,     'R');\n        }\n\n        /* ---- reconstruct path ---- */\n        string path;\n        int cur = T;\n        while (cur != S) {\n            auto [p, c] = prv[cur];\n            path.push_back(c);\n            cur = p;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << '\\n' << flush;\n\n        /* ---- read observation ---- */\n        long long y;\n        cin >> y;\n        int L = (int)path.size();\n        if (L == 0) continue;\n\n        /* ---- update global mean ---- */\n        double avg_step = (double)y / (double)L;\n        global_mean = global_mean * 0.95 + avg_step * 0.05;\n        if (global_mean < MINW) global_mean = MINW;\n        if (global_mean > MAXW) global_mean = MAXW;\n\n        /* ---- compute predicted length and list traversed edges ---- */\n        struct Eref { bool h; int i, j; };\n        vector<Eref> edges;\n        edges.reserve(L);\n        double pred = 0.0;\n        int ci = si, cj = sj;\n\n        for (char c : path) {\n            if (c == 'U') {\n                edges.push_back({false, ci - 1, cj});\n                pred += est_v[ci - 1][cj];\n                --ci;\n            } else if (c == 'D') {\n                edges.push_back({false, ci, cj});\n                pred += est_v[ci][cj];\n                ++ci;\n            } else if (c == 'L') {\n                edges.push_back({true, ci, cj - 1});\n                pred += est_h[ci][cj - 1];\n                --cj;\n            } else if (c == 'R') {\n                edges.push_back({true, ci, cj});\n                pred += est_h[ci][cj];\n                ++cj;\n            }\n        }\n\n        /* ---- weighted Kaczmarz-like update ---- */\n        double diff = (double)y - pred;\n        double total_inv = 0.0;\n        for (auto &e : edges) {\n            int c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            total_inv += 1.0 / ((double)c + 1.0);\n        }\n\n        for (auto &e : edges) {\n            int &c   = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            double &est = e.h ? est_h[e.i][e.j] : est_v[e.i][e.j];\n\n            double w = (1.0 / ((double)c + 1.0)) / total_inv;\n            est += diff * w * LR;\n            if (est < MINW) est = MINW;\n            if (est > MAXW) est = MAXW;\n            ++c;\n        }\n\n        /* ---- refresh unseen edges with the new global mean ---- */\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N - 1; ++j)\n                if (cnt_h[i][j] == 0) est_h[i][j] = global_mean;\n\n        for (int i = 0; i < N - 1; ++i)\n            for (int j = 0; j < N; ++j)\n                if (cnt_v[i][j] == 0) est_v[i][j] = global_mean;\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nvector<string> S;\nvector<uint8_t> s_len;\n\n/* ---------- placement data ---------- */\nvector<int> pid_sid;          // string id of placement\nvector<uint8_t> pid_len;      // length of placement\nvector<int> pid_off;          // offset in flat_cells\nvector<uint16_t> flat_cells;  // cells of each placement (concatenated)\n\n/* incidence: for each cell and each required char, list of (pid<<8 | off) */\nvector<uint32_t> cell_inc_by_char[400][8];\n\n/* ---------- current state ---------- */\nvector<int> pid_match_cnt;    // how many cells of the placement match cur\nvector<int> sid_match_cnt;    // how many fully matched placements each string has\nvector<uint8_t> cur;          // current board, 0..7 = A..H, 8 = '.'\nint total_matched;\nint total_dots;\n\n/* temporaries for eval_move */\nint tmp_delta[800];\nint vis[800];\nint vis_token = 1;\n\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n/* evaluate changing one cell to new_char (does NOT modify state) */\ninline int eval_move(int cell, uint8_t new_char) {\n    uint8_t old_char = cur[cell];\n    if (old_char == new_char) return 0;\n    int delta = 0;\n    int affected[800];\n    int aff_cnt = 0;\n\n    if (old_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][old_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt == len) {                 // was fully matched, now loses one\n                int sid = pid_sid[pid];\n                if (vis[sid] != vis_token) {\n                    vis[sid] = vis_token;\n                    tmp_delta[sid] = 0;\n                    affected[aff_cnt++] = sid;\n                }\n                --tmp_delta[sid];\n            }\n        }\n    }\n\n    if (new_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][new_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt + 1 == len) {             // becomes fully matched\n                int sid = pid_sid[pid];\n                if (vis[sid] != vis_token) {\n                    vis[sid] = vis_token;\n                    tmp_delta[sid] = 0;\n                    affected[aff_cnt++] = sid;\n                }\n                ++tmp_delta[sid];\n            }\n        }\n    }\n\n    for (int i = 0; i < aff_cnt; ++i) {\n        int sid = affected[i];\n        int old_scnt = sid_match_cnt[sid];\n        int new_scnt = old_scnt + tmp_delta[sid];\n        if (old_scnt == 0 && new_scnt > 0) ++delta;\n        else if (old_scnt > 0 && new_scnt == 0) --delta;\n    }\n    ++vis_token;\n    return delta;\n}\n\n/* apply a move (mutates state) */\ninline void apply_move(int cell, uint8_t new_char) {\n    uint8_t old_char = cur[cell];\n    if (old_char == new_char) return;\n    cur[cell] = new_char;\n\n    if (old_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][old_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt == len) {\n                --sid_match_cnt[pid_sid[pid]];\n            }\n            pid_match_cnt[pid] = old_cnt - 1;\n        }\n    }\n\n    if (new_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][new_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt + 1 == len) {\n                ++sid_match_cnt[pid_sid[pid]];\n            }\n            pid_match_cnt[pid] = old_cnt + 1;\n        }\n    }\n\n    if (old_char == 8) --total_dots;\n    if (new_char == 8) ++total_dots;\n}\n\n/* recompute all counts from scratch (fast, ~5M operations) */\nvoid recompute_state(const vector<uint8_t>& mat) {\n    cur = mat;\n    total_dots = 0;\n    for (int i = 0; i < 400; ++i) if (cur[i] == 8) ++total_dots;\n\n    fill(pid_match_cnt.begin(), pid_match_cnt.end(), 0);\n    for (int cell = 0; cell < 400; ++cell) {\n        uint8_t ch = cur[cell];\n        if (ch < 8) {\n            for (uint32_t inc : cell_inc_by_char[cell][ch]) {\n                ++pid_match_cnt[inc >> 8];\n            }\n        }\n    }\n\n    fill(sid_match_cnt.begin(), sid_match_cnt.end(), 0);\n    int P = (int)pid_sid.size();\n    for (int pid = 0; pid < P; ++pid) {\n        if (pid_match_cnt[pid] == pid_len[pid]) {\n            ++sid_match_cnt[pid_sid[pid]];\n        }\n    }\n\n    total_matched = 0;\n    for (int i = 0; i < M; ++i)\n        if (sid_match_cnt[i] > 0) ++total_matched;\n}\n\n/* hill climb on letters only, return best board found in this run */\nvoid hill_climb() {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(400);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int cell : order) {\n            int best_delta = 0;\n            int best_char = cur[cell];\n            for (int ch = 0; ch < 8; ++ch) {\n                if (ch == cur[cell]) continue;\n                int d = eval_move(cell, ch);\n                if (d > best_delta) {\n                    best_delta = d;\n                    best_char = ch;\n                }\n            }\n            if (best_delta > 0) {\n                apply_move(cell, best_char);\n                total_matched += best_delta;\n                improved = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N_in, M_in;\n    if (!(cin >> N_in >> M_in)) return 0;\n    N = N_in; M = M_in;\n\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n    s_len.resize(M);\n    for (int i = 0; i < M; ++i) s_len[i] = (uint8_t)S[i].size();\n\n    /* ----- build all placements ----- */\n    pid_sid.reserve(M * 2 * N * N);\n    pid_len.reserve(M * 2 * N * N);\n    pid_off.reserve(M * 2 * N * N + 1);\n    pid_off.push_back(0);\n    flat_cells.reserve(M * 2 * N * N * 12);\n\n    for (int sid = 0; sid < M; ++sid) {\n        int len = s_len[sid];\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    int pid = (int)pid_sid.size();\n                    pid_sid.push_back(sid);\n                    pid_len.push_back((uint8_t)len);\n                    for (int p = 0; p < len; ++p) {\n                        int rr = (dir == 0) ? r : (r + p) % N;\n                        int cc = (dir == 0) ? (c + p) % N : c;\n                        int cell = rr * N + cc;\n                        uint8_t req = (uint8_t)(S[sid][p] - 'A');\n                        flat_cells.push_back((uint16_t)cell);\n                        cell_inc_by_char[cell][req].push_back(((uint32_t)pid << 8) | (uint32_t)p);\n                    }\n                    pid_off.push_back((int)flat_cells.size());\n                }\n            }\n        }\n    }\n\n    int P = (int)pid_sid.size();\n    pid_match_cnt.assign(P, 0);\n    sid_match_cnt.assign(M, 0);\n    cur.resize(400);\n\n    /* ----- initial board: majority vote ----- */\n    vector<uint8_t> init_cur(400);\n    for (int cell = 0; cell < 400; ++cell) {\n        int best_ch = 0;\n        int best_cnt = (int)cell_inc_by_char[cell][0].size();\n        for (int ch = 1; ch < 8; ++ch) {\n            int cnt = (int)cell_inc_by_char[cell][ch].size();\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_ch = ch;\n            }\n        }\n        vector<int> tops;\n        for (int ch = 0; ch < 8; ++ch)\n            if ((int)cell_inc_by_char[cell][ch].size() == best_cnt) tops.push_back(ch);\n        init_cur[cell] = (uint8_t)tops[rng() % tops.size()];\n    }\n\n    auto start = chrono::steady_clock::now();\n\n    vector<uint8_t> best_cur = init_cur;\n    int best_matched = -1;\n\n    auto accept_best = [&]() {\n        if (total_matched > best_matched) {\n            best_matched = total_matched;\n            best_cur = cur;\n        }\n    };\n\n    /* ----- phase 1: hill climb from majority vote ----- */\n    recompute_state(init_cur);\n    hill_climb();\n    accept_best();\n\n    /* ----- phase 2: iterated local search (perturb + hill climb) ----- */\n    while (best_matched < M) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() > 1.8) break;\n\n        recompute_state(best_cur);\n        /* perturb */\n        for (int i = 0; i < 30; ++i) {\n            int cell = rng() % 400;\n            int ch = rng() % 8;\n            if (ch == cur[cell]) continue;\n            int d = eval_move(cell, ch);\n            apply_move(cell, ch);\n            total_matched += d;\n        }\n        hill_climb();\n        accept_best();\n    }\n\n    /* ----- phase 3: pure random restarts if still not perfect ----- */\n    while (best_matched < M) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() > 2.0) break;\n\n        vector<uint8_t> rcur(400);\n        for (int i = 0; i < 400; ++i) rcur[i] = (uint8_t)(rng() % 8);\n        recompute_state(rcur);\n        hill_climb();\n        accept_best();\n    }\n\n    /* restore best solution */\n    recompute_state(best_cur);\n\n    vector<string> ans(N, string(N, '.'));\n\n    /* ----- phase 4: dotting by placement selection ----- */\n    if (total_matched == M) {\n        vector<vector<int>> matched_pids(M);\n        for (int pid = 0; pid < P; ++pid) {\n            if (pid_match_cnt[pid] == pid_len[pid])\n                matched_pids[pid_sid[pid]].push_back(pid);\n        }\n\n        int best_kept = 400;\n        vector<char> best_keep(400, 1);\n        vector<int> cell_ref(400);\n        vector<int> sel(M);\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 2.95) break;\n\n            fill(cell_ref.begin(), cell_ref.end(), 0);\n            int kept = 0;\n            for (int sid = 0; sid < M; ++sid) {\n                const auto& v = matched_pids[sid];\n                int pid = v[rng() % v.size()];\n                sel[sid] = pid;\n                int off = pid_off[pid];\n                int len = pid_len[pid];\n                for (int i = 0; i < len; ++i) {\n                    int cell = flat_cells[off + i];\n                    if (cell_ref[cell] == 0) ++kept;\n                    ++cell_ref[cell];\n                }\n            }\n\n            bool improved = true;\n            while (improved) {\n                improved = false;\n                shuffle(order.begin(), order.end(), rng);\n                for (int sid : order) {\n                    if (matched_pids[sid].size() <= 1) continue;\n                    int cur_pid = sel[sid];\n                    int cur_off = pid_off[cur_pid];\n                    int cur_len = pid_len[cur_pid];\n                    int best_delta = 0;\n                    int best_pid = cur_pid;\n                    for (int pid : matched_pids[sid]) {\n                        if (pid == cur_pid) continue;\n                        int delta = 0;\n                        int off = pid_off[pid];\n                        int len = pid_len[pid];\n                        for (int i = 0; i < cur_len; ++i) {\n                            int cell = flat_cells[cur_off + i];\n                            if (cell_ref[cell] == 1) --delta;\n                        }\n                        for (int i = 0; i < len; ++i) {\n                            int cell = flat_cells[off + i];\n                            if (cell_ref[cell] == 0) ++delta;\n                        }\n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_pid = pid;\n                        }\n                    }\n                    if (best_delta < 0) {\n                        for (int i = 0; i < cur_len; ++i) {\n                            int cell = flat_cells[cur_off + i];\n                            --cell_ref[cell];\n                            if (cell_ref[cell] == 0) --kept;\n                        }\n                        int new_off = pid_off[best_pid];\n                        int new_len = pid_len[best_pid];\n                        for (int i = 0; i < new_len; ++i) {\n                            int cell = flat_cells[new_off + i];\n                            if (cell_ref[cell] == 0) ++kept;\n                            ++cell_ref[cell];\n                        }\n                        sel[sid] = best_pid;\n                        improved = true;\n                    }\n                }\n            }\n\n            if (kept < best_kept) {\n                best_kept = kept;\n                for (int i = 0; i < 400; ++i) best_keep[i] = (cell_ref[i] > 0);\n            }\n        }\n\n        for (int r = 0; r < N; ++r)\n            for (int c = 0; c < N; ++c) {\n                int cell = r * N + c;\n                if (best_keep[cell]) ans[r][c] = char('A' + cur[cell]);\n            }\n    } else {\n        for (int r = 0; r < N; ++r)\n            for (int c = 0; c < N; ++c)\n                ans[r][c] = char('A' + cur[r * N + c]);\n    }\n\n    for (int r = 0; r < N; ++r)\n        cout << ans[r] << '\\n';\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, si, sj;\n    vector<string> g;\n    vector<vector<int>> w;          // travel time of each cell\n    vector<int> ui, uj;             // coordinate of each node\n    vector<vector<int>> adj;        // road graph\n    vector<bitset<512>> cellMask;   // requirements covered by each node\n    int Hreq = 0, Vreq = 0, R = 0; // numbers of long H, long V, total reqs\n    int S = -1;                     // start node id\n    mt19937 rng;\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    inline int dir(int u, int v) const {\n        int i1 = ui[u], j1 = uj[u];\n        int i2 = ui[v], j2 = uj[v];\n        if (i2 == i1 - 1) return 0;\n        if (i2 == i1 + 1) return 1;\n        if (j2 == j1 - 1) return 2;\n        return 3;\n    }\n\n    Solver() {\n        rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n    }\n\n    void run() {\n        // ---------- input ----------\n        if (!(cin >> N >> si >> sj)) return;\n        g.resize(N);\n        for (int i = 0; i < N; ++i) cin >> g[i];\n        w.assign(N, vector<int>(N, 0));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (g[i][j] != '#') w[i][j] = g[i][j] - '0';\n\n        // ---------- build road graph (BFS from start) ----------\n        vector<vector<int>> id(N, vector<int>(N, -1));\n        queue<pair<int,int>> q;\n        q.emplace(si, sj);\n        id[si][sj] = 0;\n        ui.push_back(si); uj.push_back(sj);\n        while (!q.empty()) {\n            auto [i, j] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (g[ni][nj] == '#') continue;\n                if (id[ni][nj] == -1) {\n                    id[ni][nj] = (int)ui.size();\n                    ui.push_back(ni);\n                    uj.push_back(nj);\n                    q.emplace(ni, nj);\n                }\n            }\n        }\n        int V = (int)ui.size();\n        S = id[si][sj];\n        adj.assign(V, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1) {\n                    adj[u].push_back(id[ni][nj]);\n                }\n            }\n        }\n\n        // ---------- identify long segments ----------\n        vector<vector<int>> hId(N, vector<int>(N, -1));\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ) {\n                if (g[i][j] == '#') { ++j; continue; }\n                int j0 = j;\n                while (j < N && g[i][j] != '#') ++j;\n                if (j - j0 >= 2) {\n                    for (int k = j0; k < j; ++k) hId[i][k] = Hreq;\n                    ++Hreq;\n                }\n            }\n        }\n        vector<vector<int>> vId(N, vector<int>(N, -1));\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ) {\n                if (g[i][j] == '#') { ++i; continue; }\n                int i0 = i;\n                while (i < N && g[i][j] != '#') ++i;\n                if (i - i0 >= 2) {\n                    for (int k = i0; k < i; ++k) vId[k][j] = Vreq;\n                    ++Vreq;\n                }\n            }\n        }\n        R = Hreq + Vreq;\n        cellMask.assign(V, bitset<512>());\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            if (hId[i][j] != -1) cellMask[u].set(hId[i][j]);\n            if (vId[i][j] != -1) cellMask[u].set(Hreq + vId[i][j]);\n        }\n        bitset<512> allReq;\n        for (int i = 0; i < R; ++i) allReq.set(i);\n\n        if (R == 0) {\n            cout << \"\\n\";\n            return;\n        }\n\n        // ---------- fallback: full spanning tree ----------\n        string fallbackTour;\n        int fallbackCost = 0;\n        {\n            vector<vector<int>> fallAdj(V);\n            vector<int> parent(V, -1);\n            queue<int> qq;\n            vector<char> vis(V, 0);\n            vis[S] = 1; qq.push(S);\n            while (!qq.empty()) {\n                int u = qq.front(); qq.pop();\n                for (int v : adj[u]) if (!vis[v]) {\n                    vis[v] = 1;\n                    parent[v] = u;\n                    fallAdj[u].push_back(v);\n                    fallAdj[v].push_back(u);\n                    qq.push(v);\n                }\n            }\n            function<void(int,int)> dfsFall = [&](int u, int p) {\n                for (int v : fallAdj[u]) if (v != p) {\n                    fallbackTour.push_back(dc[dir(u, v)]);\n                    fallbackCost += w[ui[v]][uj[v]];\n                    dfsFall(v, u);\n                    fallbackTour.push_back(dc[dir(v, u)]);\n                    fallbackCost += w[ui[u]][uj[u]];\n                }\n            };\n            dfsFall(S, -1);\n        }\n\n        string bestTour = fallbackTour;\n        int bestCost = fallbackCost;\n\n        const int MAX_ITER = 30;\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            vector<char> inTree(V, 0);\n            vector<vector<int>> treeAdj(V);\n            bitset<512> covered;\n            inTree[S] = 1;\n            covered = cellMask[S];\n\n            bool bad = false;\n            while (covered != allReq) {\n                const int INF = 1e9;\n                vector<int> dist(V, INF);\n                vector<int> parent(V, -1);\n                priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n                for (int u = 0; u < V; ++u) {\n                    if (inTree[u]) {\n                        dist[u] = 0;\n                        pq.emplace(0, u);\n                    }\n                }\n                vector<int> order;\n                order.reserve(V);\n                while (!pq.empty()) {\n                    auto [d, u] = pq.top(); pq.pop();\n                    if (d != dist[u]) continue;\n                    order.push_back(u);\n                    for (int v : adj[u]) {\n                        int nd = d + w[ui[v]][uj[v]];\n                        if (nd < dist[v]) {\n                            dist[v] = nd;\n                            parent[v] = u;\n                            pq.emplace(nd, v);\n                        }\n                    }\n                }\n\n                vector<bitset<512>> pathMask(V);\n                for (int u : order) {\n                    if (inTree[u]) {\n                        pathMask[u].reset();\n                    } else {\n                        int p = parent[u];\n                        if (p >= 0) pathMask[u] = pathMask[p];\n                        pathMask[u] |= cellMask[u];\n                    }\n                }\n\n                struct Cand { int v, d, g; };\n                vector<Cand> cands;\n                for (int u = 0; u < V; ++u) {\n                    if (inTree[u]) continue;\n                    bitset<512> add = pathMask[u] & ~covered;\n                    int gain = (int)add.count();\n                    if (gain > 0) cands.push_back({u, dist[u], gain});\n                }\n                if (cands.empty()) { bad = true; break; }\n\n                sort(cands.begin(), cands.end(),\n                    [](const Cand& a, const Cand& b) {\n                        return (long long)a.d * b.g < (long long)b.d * a.g;\n                    });\n\n                int K = min(3, (int)cands.size());\n                int pick = (iter > 0) ? (rng() % K) : 0;\n                int bestV = cands[pick].v;\n\n                // add the whole shortest path\n                int cur = bestV;\n                while (!inTree[cur]) {\n                    int p = parent[cur];\n                    treeAdj[cur].push_back(p);\n                    treeAdj[p].push_back(cur);\n                    inTree[cur] = 1;\n                    covered |= cellMask[cur];\n                    cur = p;\n                }\n            }\n\n            if (bad || covered != allReq) continue;\n\n            // ---------- prune unnecessary leaves ----------\n            vector<char> alive(V, 0);\n            vector<int> deg(V, 0);\n            for (int u = 0; u < V; ++u) {\n                if (inTree[u]) {\n                    alive[u] = 1;\n                    deg[u] = (int)treeAdj[u].size();\n                }\n            }\n            vector<int> coverCnt(R, 0);\n            for (int u = 0; u < V; ++u) if (alive[u]) {\n                const bitset<512>& m = cellMask[u];\n                for (int r = 0; r < R; ++r) if (m.test(r)) ++coverCnt[r];\n            }\n            queue<int> qq;\n            for (int u = 0; u < V; ++u)\n                if (alive[u] && deg[u] == 1 && u != S) qq.push(u);\n\n            while (!qq.empty()) {\n                int u = qq.front(); qq.pop();\n                if (!alive[u] || deg[u] != 1 || u == S) continue;\n                bool ok = true;\n                const bitset<512>& m = cellMask[u];\n                for (int r = 0; r < R; ++r) {\n                    if (m.test(r) && coverCnt[r] <= 1) { ok = false; break; }\n                }\n                if (!ok) continue;\n                alive[u] = 0;\n                deg[u] = 0;\n                for (int v : treeAdj[u]) {\n                    if (!alive[v]) continue;\n                    if (--deg[v] == 1 && v != S) qq.push(v);\n                }\n            }\n\n            // build pruned adjacency\n            vector<vector<int>> prunedAdj(V);\n            for (int u = 0; u < V; ++u) if (alive[u]) {\n                for (int v : treeAdj[u]) {\n                    if (alive[v] && u < v) {\n                        prunedAdj[u].push_back(v);\n                        prunedAdj[v].push_back(u);\n                    }\n                }\n            }\n\n            // ---------- DFS doubling ----------\n            string tour;\n            tour.reserve(V * 4);\n            int tourCost = 0;\n            function<void(int,int)> dfs = [&](int u, int p) {\n                for (int v : prunedAdj[u]) {\n                    if (v == p) continue;\n                    tour.push_back(dc[dir(u, v)]);\n                    tourCost += w[ui[v]][uj[v]];\n                    dfs(v, u);\n                    tour.push_back(dc[dir(v, u)]);\n                    tourCost += w[ui[u]][uj[u]];\n                }\n            };\n            dfs(S, -1);\n\n            if (tourCost < bestCost) {\n                bestCost = tourCost;\n                bestTour = tour;\n            }\n        }\n\n        cout << bestTour << \"\\n\";\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.run();\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\n/* ---------- global data ---------- */\nint N, M, K, R;\nvector<vector<int>> d;          // task difficulties\nvector<vector<int>> out;        // adjacency list of the DAG\nvector<int> crit;               // longest path to sink (number of tasks)\nvector<int> wait_;              // how many days a ready task has been waiting\nvector<vector<double>> s_est;   // estimated skill vectors\nvector<vector<pair<int,int>>> obs; // per worker: (task_id , duration)\nvector<int> tasks_done;         // how many tasks a worker has finished\nvector<int> assigned_task;      // -1 = idle, else running task id\nvector<int> start_day;          // day the current task was started\nvector<int> rem_indeg;          // remaining indegree\nvector<int> ready;              // currently ready tasks\nmt19937 rng(42);\n\n/* predicted cost of assigning task -> worker */\ninline double compute_cost(int task, int worker)\n{\n    double w = 0.0;\n    const vector<int> &dt = d[task];\n    const vector<double> &s = s_est[worker];\n    for (int k = 0; k < K; ++k) {\n        if (dt[k] > s[k]) w += dt[k] - s[k];\n    }\n    double dur = (w < 1.0) ? 1.0 : w;\n    // critical tasks are slightly preferred,\n    // tasks that have waited long are strongly preferred\n    return dur - 0.02 * crit[task] - 0.1 * wait_[task];\n}\n\n/* assign tasks for the coming day */\nvector<pair<int,int>> computeAssignments(int day)\n{\n    vector<pair<int,int>> result;\n    vector<int> idle;\n    idle.reserve(M);\n    for (int j = 0; j < M; ++j)\n        if (assigned_task[j] == -1) idle.push_back(j);\n\n    if (idle.empty() || ready.empty()) return result;\n\n    vector<int> exploring, exploiting;\n    for (int j : idle) {\n        if (tasks_done[j] < 2) exploring.push_back(j);\n        else exploiting.push_back(j);\n    }\n\n    vector<int> avail = ready;\n    shuffle(avail.begin(), avail.end(), rng);\n\n    /* exploration: random tasks for inexperienced workers */\n    for (int j : exploring) {\n        if (avail.empty()) break;\n        int task = avail.back(); avail.pop_back();\n        result.emplace_back(j, task);\n        assigned_task[j] = task;\n        start_day[j] = day;\n    }\n\n    /* exploitation: regret based greedy matching */\n    if (!exploiting.empty() && !avail.empty()) {\n        struct Cand {\n            double score;\n            double best_val;\n            int task;\n            int best_j;\n        };\n        vector<Cand> cands;\n        cands.reserve(avail.size());\n\n        for (int task : avail) {\n            double best_val = 1e100, second_val = 1e100;\n            int best_j = -1;\n            for (int j : exploiting) {\n                double val = compute_cost(task, j);\n                if (val < best_val) {\n                    second_val = best_val;\n                    best_val = val;\n                    best_j = j;\n                } else if (val < second_val) {\n                    second_val = val;\n                }\n            }\n            if (best_j == -1) continue;\n            double regret = (second_val > 1e99/2) ? 1e100 : second_val - best_val;\n            double score = regret - best_val;          // high regret or very low cost\n            score += uniform_real_distribution<double>(0.0, 1e-9)(rng);\n            cands.push_back({score, best_val, task, best_j});\n        }\n\n        sort(cands.begin(), cands.end(),\n             [](const Cand& a, const Cand& b){ return a.score > b.score; });\n\n        vector<char> used(M, 0);\n        for (auto &c : cands) {\n            int j = c.best_j;\n            if (used[j]) {\n                double best2 = 1e100;\n                int j2 = -1;\n                for (int jj : exploiting) {\n                    if (used[jj]) continue;\n                    double v = compute_cost(c.task, jj);\n                    if (v < best2) { best2 = v; j2 = jj; }\n                }\n                if (j2 == -1) continue;\n                j = j2;\n            }\n            if (used[j]) continue;\n            used[j] = 1;\n            result.emplace_back(j, c.task);\n            assigned_task[j] = c.task;\n            start_day[j] = day;\n        }\n    }\n\n    /* erase assigned tasks from the global ready list */\n    vector<char> is_assigned(N, 0);\n    for (auto &p : result) is_assigned[p.second] = 1;\n    vector<int> new_ready;\n    new_ready.reserve(ready.size());\n    for (int task : ready)\n        if (!is_assigned[task]) new_ready.push_back(task);\n    ready.swap(new_ready);\n    return result;\n}\n\n/* ---------- main ---------- */\nint main()\n{\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n    d.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            cin >> d[i][k];\n\n    out.assign(N, {});\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v; cin >> u >> v; --u; --v;\n        out[u].push_back(v);\n        ++indeg[v];\n    }\n\n    crit.assign(N, 1);\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out[i]) best = max(best, crit[v]);\n        crit[i] = best + 1;\n    }\n\n    wait_.assign(N, 0);\n    s_est.assign(M, vector<double>(K, 0.0));\n    obs.assign(M, {});\n    tasks_done.assign(M, 0);\n    assigned_task.assign(M, -1);\n    start_day.assign(M, -1);\n    rem_indeg = indeg;\n    ready.clear();\n    for (int i = 0; i < N; ++i)\n        if (rem_indeg[i] == 0) ready.push_back(i);\n\n    int day = 1;\n    vector<pair<int,int>> assignments = computeAssignments(day);\n\n    while (true) {\n        cout << assignments.size();\n        for (auto &p : assignments)\n            cout << ' ' << p.first + 1 << ' ' << p.second + 1;\n        cout << '\\n';\n        cout.flush();\n\n        int n;  cin >> n;\n        if (n == -1) break;\n        vector<int> completed(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> completed[i];\n            --completed[i];\n        }\n\n        /* tasks that stayed ready and unassigned waited one more day */\n        for (int task : ready) ++wait_[task];\n\n        for (int j : completed) {\n            int task = assigned_task[j];\n            int t = day - start_day[j] + 1;\n\n            obs[j].emplace_back(task, t);\n            ++tasks_done[j];\n\n            const double LR  = 0.2;\n            const double LR2 = 0.01;\n            const int EPOCHS = 3;\n            auto &obsj = obs[j];\n\n            for (int ep = 0; ep < EPOCHS; ++ep) {\n                shuffle(obsj.begin(), obsj.end(), rng);\n                for (const auto &ob : obsj) {\n                    int tid = ob.first;\n                    int dur = ob.second;\n                    const vector<int> &dt = d[tid];\n\n                    double w_pred = 0.0;\n                    vector<int> active;\n                    active.reserve(K);\n                    for (int k = 0; k < K; ++k) {\n                        if (dt[k] > s_est[j][k] + 1e-12) {\n                            w_pred += dt[k] - s_est[j][k];\n                            active.push_back(k);\n                        }\n                    }\n\n                    double target = (dur == 1) ? 1.0 : (double)dur;\n                    double e = w_pred - target;\n                    if (dur == 1) e *= 0.5;\n\n                    if (fabs(e) > 1e-12) {\n                        if (!active.empty()) {\n                            double delta = LR * e / active.size();\n                            if (delta >  3.0) delta =  3.0;\n                            if (delta < -3.0) delta = -3.0;\n                            for (int k : active) s_est[j][k] += delta;\n                        } else if (e < 0) {\n                            double dec = LR2 * (-e) / K;\n                            for (int k = 0; k < K; ++k)\n                                s_est[j][k] = max(0.0, s_est[j][k] - dec);\n                        }\n                        for (int k = 0; k < K; ++k)\n                            if (s_est[j][k] < 0) s_est[j][k] = 0;\n                    }\n                }\n            }\n\n            assigned_task[j] = -1;\n            start_day[j] = -1;\n            for (int v : out[task]) {\n                if (--rem_indeg[v] == 0)\n                    ready.push_back(v);\n            }\n        }\n\n        ++day;\n        if (day > 2000) break;\n        assignments = computeAssignments(day);\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nint X[2001];\nint Y[2001];\nint dist_mat[2001][2001];\ninline int D(int u, int v) { return dist_mat[u][v]; }\n\n/* ---------- insertion evaluation ---------- */\nvoid eval_insert(const vector<int>& route, int oid, int& best_delta, int& best_ip, int& best_id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    int L = (int)route.size();\n    best_delta = INT_MAX;\n    for (int ip = 0; ip < L - 1; ++ip) {\n        int cost_p = D(route[ip], p) + D(p, route[ip + 1]) - D(route[ip], route[ip + 1]);\n        int left = p;\n        for (int id = ip; id < L - 1; ++id) {\n            if (id > ip) left = route[id];\n            int cost_d = D(left, d) + D(d, route[id + 1]) - D(left, route[id + 1]);\n            int delta = cost_p + cost_d;\n            if (delta < best_delta) {\n                best_delta = delta;\n                best_ip = ip;\n                best_id = id;\n            }\n        }\n    }\n}\n\nvoid apply_insert(vector<int>& route, int oid, int ip, int id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() + 2);\n    for (int k = 0; k <= ip; ++k) res.push_back(route[k]);\n    res.push_back(p);\n    for (int k = ip + 1; k <= id; ++k) res.push_back(route[k]);\n    res.push_back(d);\n    for (int k = id + 1; k < (int)route.size(); ++k) res.push_back(route[k]);\n    route.swap(res);\n}\n\nvector<int> remove_order(const vector<int>& route, int oid) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() - 2);\n    for (int node : route) if (node != p && node != d) res.push_back(node);\n    return res;\n}\n\nint route_cost(const vector<int>& route) {\n    int sum = 0;\n    for (int i = 0; i + 1 < (int)route.size(); ++i) sum += D(route[i], route[i + 1]);\n    return sum;\n}\n\n/* ---------- route local search ---------- */\nbool optimize_pass(vector<int>& route, int& cost) {\n    int n = (int)route.size();\n    array<int, 2001> pos;\n    pos.fill(-1);\n    for (int i = 0; i < n; ++i) pos[route[i]] = i;\n    array<int, 2001> pp;\n    for (int i = 0; i < n; ++i) pp[i] = pos[route[i] ^ 1];\n\n    int best_delta = 0;\n    int best_type = -1;          // 0 swap, 1 2opt, 2 relocate\n    int b_i = 0, b_j = 0, b_l = 0, b_r = 0;\n\n    // 1. swap\n    for (int i = 1; i < n - 1; ++i) {\n        for (int j = i + 1; j < n - 1; ++j) {\n            int u = route[i], v = route[j];\n            if ((u ^ 1) == v) continue;               // same order\n            if ((u & 1) && pp[i] <= j) continue;       // u is pickup, partner not after j\n            if (!(v & 1) && pp[j] >= i) continue;      // v is delivery, partner not before i\n            int delta;\n            if (j == i + 1) {\n                delta = D(route[i - 1], v) + D(v, u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, v) - D(v, route[j + 1]);\n            } else {\n                delta = D(route[i - 1], v) + D(v, route[i + 1])\n                      + D(route[j - 1], u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, route[i + 1])\n                      - D(route[j - 1], v) - D(v, route[j + 1]);\n            }\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 0; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    // 2. 2-opt (segment reversal)\n    for (int l = 1; l < n - 1; ++l) {\n        for (int r = l + 1; r < n - 1; ++r) {\n            bool ok = true;\n            for (int k = l; k <= r; ++k) {\n                if (pp[k] >= l && pp[k] <= r) { ok = false; break; }\n            }\n            if (!ok) continue;\n            int delta = D(route[l - 1], route[r]) + D(route[l], route[r + 1])\n                      - D(route[l - 1], route[l]) - D(route[r], route[r + 1]);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 1; b_l = l; b_r = r;\n            }\n        }\n    }\n\n    // 3. relocate single node\n    for (int i = 1; i < n - 1; ++i) {\n        int u = route[i];\n        int A = route[i - 1], B = route[i + 1];\n        int delta_remove = D(A, B) - D(A, u) - D(u, B);\n        // move left: j < i\n        for (int j = 1; j < i; ++j) {\n            if (!(u & 1) && j <= pp[i]) continue; // delivery cannot pass its pickup\n            int left = route[j - 1], right = route[j];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n        // move right: j > i  (j is position in new route of size n-1, valid 1..n-2)\n        for (int j = i + 1; j < n - 1; ++j) {\n            if ((u & 1) && j >= pp[i]) continue; // pickup cannot pass its delivery\n            int left = route[j], right = route[j + 1];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    if (best_type == -1) return false;\n\n    if (best_type == 0) {\n        swap(route[b_i], route[b_j]);\n    } else if (best_type == 1) {\n        reverse(route.begin() + b_l, route.begin() + b_r + 1);\n    } else {\n        int u = route[b_i];\n        route.erase(route.begin() + b_i);\n        route.insert(route.begin() + b_j, u);\n    }\n    cost += best_delta;\n    return true;\n}\n\nvoid optimize_route(vector<int>& route, int& cost) {\n    int cnt = 0;\n    while (optimize_pass(route, cost)) {\n        if (++cnt > 2000) break; // safety break\n    }\n}\n\n/* ---------- greedy construction ---------- */\nstruct State {\n    vector<int> route;\n    vector<int> selected;\n    int cost;\n};\n\nState greedy_build(bool use_rand, int rand_k, mt19937& rng) {\n    State st;\n    st.route = {0, 0};\n    st.selected.reserve(50);\n    vector<char> used(1000, 0);\n    struct Cand { int delta, oid, ip, id; };\n    for (int step = 0; step < 50; ++step) {\n        vector<Cand> cands;\n        cands.reserve(1000);\n        for (int oid = 0; oid < 1000; ++oid) if (!used[oid]) {\n            int d, ip, id;\n            eval_insert(st.route, oid, d, ip, id);\n            cands.push_back({d, oid, ip, id});\n        }\n        sort(cands.begin(), cands.end(),\n             [](const Cand& a, const Cand& b){ return a.delta < b.delta; });\n        int pick = 0;\n        if (use_rand && rand_k > 1 && (int)cands.size() > 1) {\n            int k = min(rand_k, (int)cands.size());\n            pick = uniform_int_distribution<int>(0, k - 1)(rng);\n        }\n        const Cand& c = cands[pick];\n        apply_insert(st.route, c.oid, c.ip, c.id);\n        used[c.oid] = 1;\n        st.selected.push_back(c.oid);\n    }\n    st.cost = route_cost(st.route);\n    return st;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    vector<int> A(1000), B_(1000), C(1000), D_(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> A[i] >> B_[i] >> C[i] >> D_[i];\n    }\n\n    X[0] = Y[0] = 400;\n    for (int i = 0; i < 1000; ++i) {\n        X[2 * i + 1] = A[i]; Y[2 * i + 1] = B_[i];\n        X[2 * i + 2] = C[i]; Y[2 * i + 2] = D_[i];\n    }\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist_mat[i][j] = abs(X[i] - X[j]) + abs(Y[i] - Y[j]);\n\n    vector<int> standalone(1000);\n    for (int i = 0; i < 1000; ++i)\n        standalone[i] = D(0, 2 * i + 1) + D(2 * i + 1, 2 * i + 2) + D(2 * i + 2, 0);\n\n    vector<int> order_ids(1000);\n    iota(order_ids.begin(), order_ids.end(), 0);\n    sort(order_ids.begin(), order_ids.end(),\n         [&](int a, int b){ return standalone[a] < standalone[b]; });\n\n    mt19937 rng(42);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]()->double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n    const double TL = 1.95;\n\n    State best = greedy_build(false, 0, rng);\n    optimize_route(best.route, best.cost);\n\n    // ------- set improvement -------\n    while (elapsed() < TL * 0.70) {\n        vector<char> in_sel(1000, 0);\n        for (int oid : best.selected) in_sel[oid] = 1;\n        vector<int> cand_out;\n        for (int oid : order_ids) {\n            if (!in_sel[oid]) {\n                cand_out.push_back(oid);\n                if ((int)cand_out.size() >= 200) break;\n            }\n        }\n\n        int best_in = -1, best_out = -1, best_ip = -1, best_id = -1;\n        int best_new_cost = best.cost;\n\n        for (int oid_in : best.selected) {\n            if (elapsed() > TL * 0.70) break;\n            vector<int> tmp = remove_order(best.route, oid_in);\n            int tmp_cost = route_cost(tmp);\n            for (int oid_out : cand_out) {\n                int dlt, ip, id;\n                eval_insert(tmp, oid_out, dlt, ip, id);\n                int ncost = tmp_cost + dlt;\n                if (ncost < best_new_cost) {\n                    best_new_cost = ncost;\n                    best_in = oid_in;\n                    best_out = oid_out;\n                    best_ip = ip;\n                    best_id = id;\n                }\n            }\n        }\n\n        if (best_in == -1) break;\n\n        vector<int> new_route = remove_order(best.route, best_in);\n        apply_insert(new_route, best_out, best_ip, best_id);\n        best.route = move(new_route);\n        best.cost = best_new_cost;\n        for (int& oid : best.selected) if (oid == best_in) { oid = best_out; break; }\n\n        optimize_route(best.route, best.cost);\n    }\n\n    // ------- random restarts with remaining time -------\n    int restart = 0;\n    while (elapsed() < TL && restart < 4) {\n        ++restart;\n        State cand = greedy_build(true, 3, rng);\n        optimize_route(cand.route, cand.cost);\n        if (cand.cost < best.cost) best = move(cand);\n    }\n\n    // ------- output -------\n    cout << best.selected.size();\n    for (int oid : best.selected) cout << ' ' << (oid + 1);\n    cout << \"\\n\";\n    cout << best.route.size();\n    for (int node : best.route) cout << ' ' << X[node] << ' ' << Y[node];\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*** DSU ***/\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool same(int x, int y) { return find(x) == find(y); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (r[x] < r[y]) swap(x, y);\n        p[y] = x;\n        if (r[x] == r[y]) ++r[x];\n        return true;\n    }\n};\n\n/*** LCA with max edge weight on tree-0 ***/\nstruct LCA {\n    int n, LOG;\n    vector<vector<pair<int,long long>>> adj;\n    vector<vector<int>> up;\n    vector<vector<long long>> mx;\n    vector<int> dep;\n    LCA(int n = 0) { init(n); }\n    void init(int n_) {\n        n = n_;\n        LOG = 1;\n        while ((1 << LOG) <= n) ++LOG;\n        adj.assign(n, {});\n        up.assign(LOG, vector<int>(n, -1));\n        mx.assign(LOG, vector<long long>(n, 0));\n        dep.assign(n, 0);\n    }\n    void add_edge(int u, int v, long long w) {\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n    void dfs(int v, int p, int d) {\n        up[0][v] = p;\n        dep[v] = d;\n        for (auto [to, w] : adj[v]) {\n            if (to == p) continue;\n            mx[0][to] = w;\n            dfs(to, v, d + 1);\n        }\n    }\n    void build(int root = 0) {\n        dfs(root, -1, 0);\n        for (int k = 1; k < LOG; ++k) {\n            for (int v = 0; v < n; ++v) {\n                if (up[k-1][v] != -1) {\n                    up[k][v] = up[k-1][ up[k-1][v] ];\n                    mx[k][v] = max(mx[k-1][v], mx[k-1][ up[k-1][v] ]);\n                }\n            }\n        }\n    }\n    long long query(int u, int v) const {\n        if (u == v) return 0;\n        if (dep[u] < dep[v]) swap(u, v);\n        long long res = 0;\n        int diff = dep[u] - dep[v];\n        for (int k = 0; k < LOG; ++k) {\n            if (diff >> k & 1) {\n                res = max(res, mx[k][u]);\n                u = up[k][u];\n            }\n        }\n        if (u == v) return res;\n        for (int k = LOG - 1; k >= 0; --k) {\n            if (up[k][u] != -1 && up[k][u] != up[k][v]) {\n                res = max(res, mx[k][u]);\n                res = max(res, mx[k][v]);\n                u = up[k][u];\n                v = up[k][v];\n            }\n        }\n        res = max(res, mx[0][u]);\n        res = max(res, mx[0][v]);\n        return res;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n    vector<long long> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) cin >> U[i] >> V[i];\n    \n    vector<long long> d(M);\n    for (int i = 0; i < M; ++i) {\n        long long dx = xs[U[i]] - xs[V[i]];\n        long long dy = ys[U[i]] - ys[V[i]];\n        long long dist2 = dx * dx + dy * dy;\n        d[i] = llround(sqrt((double)dist2));\n    }\n    \n    /*--- assign tiers 0..4 by repeated Kruskal on d ---*/\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) { return d[a] < d[b]; });\n    \n    vector<char> used(M, 0);\n    vector<int> tier(M, -1);\n    for (int t = 0; t < 5; ++t) {\n        DSU dsu(N);\n        int cnt = 0;\n        for (int idx : order) {\n            if (used[idx]) continue;\n            if (dsu.unite(U[idx], V[idx])) {\n                used[idx] = 1;\n                tier[idx] = t;\n                ++cnt;\n                if (cnt == N - 1) break;\n            }\n        }\n    }\n    \n    /*--- LCA on tier-0 tree ---*/\n    LCA lca(N);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) {\n            lca.add_edge(U[i], V[i], d[i]);\n        }\n    }\n    lca.build(0);\n    \n    vector<long long> maxd_path(M, 0);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) {\n            maxd_path[i] = d[i];\n        } else {\n            maxd_path[i] = lca.query(U[i], V[i]);\n        }\n    }\n    \n    /*--- online processing ---*/\n    DSU dsu(N);\n    int comp = N;\n    \n    for (int i = 0; i < M; ++i) {\n        long long l;\n        cin >> l;\n        int u = U[i], v = V[i];\n        \n        if (dsu.same(u, v)) {\n            cout << 0 << '\\n' << flush;\n            continue;\n        }\n        \n        int need = comp - 1;\n        int remain_after = M - i - 1;\n        bool accept = false;\n        \n        if (need > remain_after) {\n            accept = true;\n        } else {\n            double slack = (double)remain_after / need;\n            if (slack <= 1.0) {\n                accept = true;\n            } else {\n                double t = 1.5 + 1.5 * max(0.0, min(1.0, (5.0 - slack) / 4.0));\n                double ratio = (double)l / (double)d[i];\n                double thr_rel = max(1.0, t + 0.5 - tier[i] * 0.3);\n                if (ratio <= thr_rel) {\n                    accept = true;\n                } else if (tier[i] > 0) {\n                    double thr_abs = (double)maxd_path[i] * (1.3 + 0.3 * t);\n                    if ((double)l <= thr_abs) accept = true;\n                }\n            }\n        }\n        \n        if (accept) {\n            cout << 1 << '\\n' << flush;\n            dsu.unite(u, v);\n            --comp;\n        } else {\n            cout << 0 << '\\n' << flush;\n        }\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int MAX_TURN = 300;\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char BUILD[4] = {'u', 'd', 'l', 'r'};\nconst char MOVE[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n};\n\nbool in_bounds(int x, int y) {\n    return x >= 0 && x < H && y >= 0 && y < W;\n}\n\n// build action from human position to adjacent wall position\nchar build_action(int hx, int hy, int wx, int wy) {\n    if (wx == hx - 1 && wy == hy) return 'u';\n    if (wx == hx + 1 && wy == hy) return 'd';\n    if (wx == hx && wy == hy - 1) return 'l';\n    if (wx == hx && wy == hy + 1) return 'r';\n    return '.';\n}\n\n// move action from human position to adjacent cell\nchar move_action(int hx, int hy, int nx, int ny) {\n    if (nx == hx - 1 && ny == hy) return 'U';\n    if (nx == hx + 1 && ny == hy) return 'D';\n    if (nx == hx && ny == hy - 1) return 'L';\n    if (nx == hx && ny == hy + 1) return 'R';\n    return '.';\n}\n\n// get the unique cell inside the rectangle adjacent to a wall cell\nPos get_build_pos(int wx, int wy, int r1, int c1, int r2, int c2) {\n    for (int d = 0; d < 4; ++d) {\n        int nx = wx + dx[d];\n        int ny = wy + dy[d];\n        if (nx >= r1 && nx <= r2 && ny >= c1 && ny <= c2) return {nx, ny};\n    }\n    return {-1, -1};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pos> pet_pos(N);\n    vector<int> pet_type(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].x >> pet_pos[i].y >> pet_type[i];\n        --pet_pos[i].x; --pet_pos[i].y;\n    }\n\n    int M;\n    cin >> M;\n    vector<Pos> human_pos(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].x >> human_pos[i].y;\n        --human_pos[i].x; --human_pos[i].y;\n    }\n\n    // grid state\n    vector<vector<bool>> passable(H, vector<bool>(W, true));\n    vector<vector<bool>> has_pet(H, vector<bool>(W, false));\n    vector<vector<bool>> has_human(H, vector<bool>(W, false));\n\n    auto update_occupancy = [&]() {\n        for (int i = 0; i < H; ++i)\n            fill(has_pet[i].begin(), has_pet[i].end(), false);\n        for (int i = 0; i < H; ++i)\n            fill(has_human[i].begin(), has_human[i].end(), false);\n        for (auto &p : pet_pos) has_pet[p.x][p.y] = true;\n        for (auto &h : human_pos) has_human[h.x][h.y] = true;\n    };\n    update_occupancy();\n\n    // prefix sum of pets (initial positions)\n    vector<vector<int>> pet_ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            pet_ps[i + 1][j + 1] = pet_ps[i][j + 1] + pet_ps[i + 1][j] - pet_ps[i][j] + (has_pet[i][j] ? 1 : 0);\n        }\n    }\n    auto rect_pet_cnt = [&](int r1, int c1, int r2, int c2) -> int {\n        return pet_ps[r2 + 1][c2 + 1] - pet_ps[r1][c2 + 1] - pet_ps[r2 + 1][c1] + pet_ps[r1][c1];\n    };\n\n    // find best empty rectangle\n    int best_r1 = 0, best_c1 = 0, best_r2 = 0, best_c2 = 0;\n    int best_score = -1e9;\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    if (rect_pet_cnt(r1, c1, r2, c2) != 0) continue;\n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    int walls = 0;\n                    if (r1 > 0) walls += (c2 - c1 + 1);\n                    if (r2 < H - 1) walls += (c2 - c1 + 1);\n                    if (c1 > 0) walls += (r2 - r1 + 1);\n                    if (c2 < W - 1) walls += (r2 - r1 + 1);\n                    int sumd = 0;\n                    for (auto &h : human_pos) {\n                        int d = 0;\n                        if (h.x < r1) d += r1 - h.x;\n                        else if (h.x > r2) d += h.x - r2;\n                        if (h.y < c1) d += c1 - h.y;\n                        else if (h.y > c2) d += h.y - c2;\n                        sumd += d;\n                    }\n                    int score = area * 10 - walls * 2 - sumd;\n                    int bound_bonus = 0;\n                    if (r1 == 0) bound_bonus += (c2 - c1 + 1);\n                    if (r2 == H - 1) bound_bonus += (c2 - c1 + 1);\n                    if (c1 == 0) bound_bonus += (r2 - r1 + 1);\n                    if (c2 == W - 1) bound_bonus += (r2 - r1 + 1);\n                    score += bound_bonus;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1; best_c1 = c1;\n                        best_r2 = r2; best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n\n    int R1 = best_r1, C1 = best_c1, R2 = best_r2, C2 = best_c2;\n\n    // generate wall cells (outside the rectangle)\n    vector<Pos> walls;\n    if (R1 > 0) for (int c = C1; c <= C2; ++c) walls.push_back({R1 - 1, c});\n    if (R2 < H - 1) for (int c = C1; c <= C2; ++c) walls.push_back({R2 + 1, c});\n    if (C1 > 0) for (int r = R1; r <= R2; ++r) walls.push_back({r, C1 - 1});\n    if (C2 < W - 1) for (int r = R1; r <= R2; ++r) walls.push_back({r, C2 + 1});\n\n    // choose gate: wall cell farthest from any initial pet\n    Pos gate = {-1, -1};\n    if (!walls.empty()) {\n        int best_gd = -1;\n        for (auto &w : walls) {\n            int mind = 1e9;\n            for (auto &p : pet_pos) mind = min(mind, abs(w.x - p.x) + abs(w.y - p.y));\n            if (mind > best_gd) {\n                best_gd = mind;\n                gate = w;\n            }\n        }\n    }\n\n    // build positions (inside rectangle adjacent to walls), deduped\n    vector<Pos> build_positions;\n    {\n        set<pair<int,int>> seen;\n        for (auto &w : walls) {\n            Pos bp = get_build_pos(w.x, w.y, R1, C1, R2, C2);\n            if (bp.x != -1 && !seen.count({bp.x, bp.y})) {\n                build_positions.push_back(bp);\n                seen.insert({bp.x, bp.y});\n            }\n        }\n    }\n\n    // assign each human a distinct target inside rectangle (prefer build positions)\n    vector<Pos> targets(M);\n    {\n        vector<bool> used_bp(build_positions.size(), false);\n        for (int i = 0; i < M; ++i) {\n            int best = -1, bestd = 1e9;\n            for (int j = 0; j < (int)build_positions.size(); ++j) if (!used_bp[j]) {\n                int d = abs(human_pos[i].x - build_positions[j].x) + abs(human_pos[i].y - build_positions[j].y);\n                if (d < bestd) {\n                    bestd = d;\n                    best = j;\n                }\n            }\n            if (best != -1) {\n                targets[i] = build_positions[best];\n                used_bp[best] = true;\n            } else {\n                targets[i] = {(R1 + R2) / 2, (C1 + C2) / 2};\n            }\n        }\n    }\n\n    bool mode = 0; // 0 = big rectangle, 1 = turtle fallback\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        update_occupancy();\n\n        // emergency switch\n        if (mode == 0 && turn >= 250) mode = 1;\n\n        string action(M, '.');\n\n        if (mode == 0) {\n            bool all_inside = true;\n            for (auto &h : human_pos) {\n                if (!(h.x >= R1 && h.x <= R2 && h.y >= C1 && h.y <= C2)) {\n                    all_inside = false;\n                    break;\n                }\n            }\n\n            if (!all_inside) {\n                // Phase A: move toward assigned target inside rectangle\n                for (int i = 0; i < M; ++i) {\n                    int hx = human_pos[i].x, hy = human_pos[i].y;\n                    int tx = targets[i].x, ty = targets[i].y;\n                    if (hx == tx && hy == ty) {\n                        action[i] = '.';\n                        continue;\n                    }\n                    if (hx < tx) action[i] = 'D';\n                    else if (hx > tx) action[i] = 'U';\n                    else if (hy < ty) action[i] = 'R';\n                    else if (hy > ty) action[i] = 'L';\n                }\n            } else {\n                // check pet intrusion\n                bool pet_inside = false;\n                for (auto &p : pet_pos) {\n                    if (p.x >= R1 && p.x <= R2 && p.y >= C1 && p.y <= C2) {\n                        pet_inside = true;\n                        break;\n                    }\n                }\n                if (pet_inside) {\n                    mode = 1;\n                } else {\n                    // Phase B: build walls\n                    vector<Pos> unbuilt;\n                    for (auto &w : walls) {\n                        if (passable[w.x][w.y]) unbuilt.push_back(w);\n                    }\n\n                    // can we close the gate?\n                    bool can_close_gate = false;\n                    if (gate.x != -1 && passable[gate.x][gate.y]) {\n                        bool ok = true;\n                        if (has_pet[gate.x][gate.y] || has_human[gate.x][gate.y]) ok = false;\n                        for (int d = 0; d < 4 && ok; ++d) {\n                            int ax = gate.x + dx[d], ay = gate.y + dy[d];\n                            if (in_bounds(ax, ay) && has_pet[ax][ay]) ok = false;\n                        }\n                        if (ok) can_close_gate = true;\n                    }\n\n                    set<pair<int,int>> blocked_this_turn;\n                    vector<bool> human_done(M, false);\n                    vector<bool> wall_taken(unbuilt.size(), false);\n\n                    // Step 1: humans adjacent to a buildable non-gate (or closable gate) wall build it\n                    for (int i = 0; i < M; ++i) {\n                        int hx = human_pos[i].x, hy = human_pos[i].y;\n                        for (int j = 0; j < (int)unbuilt.size(); ++j) {\n                            if (wall_taken[j]) continue;\n                            int wx = unbuilt[j].x, wy = unbuilt[j].y;\n                            if (wx == gate.x && wy == gate.y && !can_close_gate) continue;\n                            if (abs(hx - wx) + abs(hy - wy) != 1) continue;\n                            bool ok = true;\n                            if (has_pet[wx][wy] || has_human[wx][wy]) ok = false;\n                            for (int d = 0; d < 4 && ok; ++d) {\n                                int ax = wx + dx[d], ay = wy + dy[d];\n                                if (in_bounds(ax, ay) && has_pet[ax][ay]) ok = false;\n                            }\n                            if (!ok) continue;\n                            char act = build_action(hx, hy, wx, wy);\n                            if (act != '.') {\n                                action[i] = act;\n                                human_done[i] = true;\n                                wall_taken[j] = true;\n                                blocked_this_turn.insert({wx, wy});\n                                break;\n                            }\n                        }\n                    }\n\n                    // Step 2: remaining humans move toward nearest unbuilt wall's build position\n                    for (int i = 0; i < M; ++i) {\n                        if (human_done[i]) continue;\n                        int hx = human_pos[i].x, hy = human_pos[i].y;\n                        int best_dist = 1e9;\n                        Pos best_bp = {-1, -1};\n                        for (int j = 0; j < (int)unbuilt.size(); ++j) {\n                            if (wall_taken[j]) continue;\n                            if (unbuilt[j].x == gate.x && unbuilt[j].y == gate.y && !can_close_gate) continue;\n                            Pos bp = get_build_pos(unbuilt[j].x, unbuilt[j].y, R1, C1, R2, C2);\n                            if (bp.x == -1) continue;\n                            int d = abs(hx - bp.x) + abs(hy - bp.y);\n                            if (d < best_dist) {\n                                best_dist = d;\n                                best_bp = bp;\n                            }\n                        }\n                        if (best_bp.x != -1 && best_dist > 0) {\n                            if (hx < best_bp.x) action[i] = 'D';\n                            else if (hx > best_bp.x) action[i] = 'U';\n                            else if (hy < best_bp.y) action[i] = 'R';\n                            else if (hy > best_bp.y) action[i] = 'L';\n                        } else {\n                            action[i] = '.';\n                        }\n                    }\n                }\n            }\n        }\n\n        if (mode == 1) {\n            set<pair<int,int>> blocked_this_turn;\n            for (int i = 0; i < M; ++i) {\n                int hx = human_pos[i].x, hy = human_pos[i].y;\n                // BFS from human to see which pets are reachable\n                vector<vector<int>> dist(H, vector<int>(W, -1));\n                queue<pair<int,int>> q;\n                dist[hx][hy] = 0;\n                q.push({hx, hy});\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = x + dx[d], ny = y + dy[d];\n                        if (!in_bounds(nx, ny)) continue;\n                        if (!passable[nx][ny]) continue;\n                        if (dist[nx][ny] != -1) continue;\n                        dist[nx][ny] = dist[x][y] + 1;\n                        q.push({nx, ny});\n                    }\n                }\n                bool reachable_pet = false;\n                for (auto &p : pet_pos) if (dist[p.x][p.y] != -1) reachable_pet = true;\n                if (reachable_pet) {\n                    // nearest pet\n                    int nd = 1e9;\n                    Pos np = {-1, -1};\n                    for (auto &p : pet_pos) {\n                        if (dist[p.x][p.y] != -1 && dist[p.x][p.y] < nd) {\n                            nd = dist[p.x][p.y];\n                            np = p;\n                        }\n                    }\n                    vector<pair<int,char>> cand;\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = hx + dx[d], ny = hy + dy[d];\n                        if (!in_bounds(nx, ny)) continue;\n                        if (!passable[nx][ny]) continue;\n                        if (blocked_this_turn.count({nx, ny})) continue;\n                        bool ok = true;\n                        if (has_pet[nx][ny] || has_human[nx][ny]) ok = false;\n                        for (int d2 = 0; d2 < 4 && ok; ++d2) {\n                            int ax = nx + dx[d2], ay = ny + dy[d2];\n                            if (in_bounds(ax, ay) && has_pet[ax][ay]) ok = false;\n                        }\n                        if (!ok) continue;\n                        int pri = 1;\n                        if (np.x != -1) {\n                            if ((d == 0 && hx > np.x) || (d == 1 && hx < np.x) ||\n                                (d == 2 && hy > np.y) || (d == 3 && hy < np.y)) pri += 10;\n                        }\n                        cand.push_back({pri, BUILD[d]});\n                    }\n                    if (!cand.empty()) {\n                        sort(cand.rbegin(), cand.rend());\n                        action[i] = cand[0].second;\n                        int wx = hx, wy = hy;\n                        if (action[i] == 'u') wx--;\n                        else if (action[i] == 'd') wx++;\n                        else if (action[i] == 'l') wy--;\n                        else if (action[i] == 'r') wy++;\n                        blocked_this_turn.insert({wx, wy});\n                        continue;\n                    }\n                    // move away from nearest pet\n                    int best_md = -1;\n                    char best_a = '.';\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = hx + dx[d], ny = hy + dy[d];\n                        if (!in_bounds(nx, ny)) continue;\n                        if (!passable[nx][ny]) continue;\n                        if (blocked_this_turn.count({nx, ny})) continue;\n                        int md = 1e9;\n                        for (auto &p : pet_pos) md = min(md, abs(nx - p.x) + abs(ny - p.y));\n                        if (md > best_md) {\n                            best_md = md;\n                            best_a = MOVE[d];\n                        }\n                    }\n                    action[i] = best_a;\n                } else {\n                    // safe: try to wall off a neighbor if possible (optional, but helps keep safe)\n                    // Actually, to increase chance of staying safe, build any legal wall\n                    vector<pair<int,char>> cand;\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = hx + dx[d], ny = hy + dy[d];\n                        if (!in_bounds(nx, ny)) continue;\n                        if (!passable[nx][ny]) continue;\n                        if (blocked_this_turn.count({nx, ny})) continue;\n                        bool ok = true;\n                        if (has_pet[nx][ny] || has_human[nx][ny]) ok = false;\n                        for (int d2 = 0; d2 < 4 && ok; ++d2) {\n                            int ax = nx + dx[d2], ay = ny + dy[d2];\n                            if (in_bounds(ax, ay) && has_pet[ax][ay]) ok = false;\n                        }\n                        if (!ok) continue;\n                        cand.push_back({1, BUILD[d]});\n                    }\n                    if (!cand.empty()) {\n                        action[i] = cand[0].second;\n                        int wx = hx, wy = hy;\n                        if (action[i] == 'u') wx--;\n                        else if (action[i] == 'd') wx++;\n                        else if (action[i] == 'l') wy--;\n                        else if (action[i] == 'r') wy++;\n                        blocked_this_turn.insert({wx, wy});\n                    } else {\n                        action[i] = '.';\n                    }\n                }\n            }\n        }\n\n        // Output actions\n        cout << action << endl;\n\n        // Apply human actions to internal state\n        set<pair<int,int>> blocked_cells;\n        for (int i = 0; i < M; ++i) {\n            char c = action[i];\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int wx = hx, wy = hy;\n                if (c == 'u') wx--;\n                else if (c == 'd') wx++;\n                else if (c == 'l') wy--;\n                else if (c == 'r') wy++;\n                if (in_bounds(wx, wy)) {\n                    passable[wx][wy] = false;\n                    blocked_cells.insert({wx, wy});\n                }\n            } else if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int nx = hx, ny = hy;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny] && !blocked_cells.count({nx, ny})) {\n                    human_pos[i] = {nx, ny};\n                }\n            }\n        }\n\n        // Read pet movements\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            for (char c : s) {\n                int nx = pet_pos[i].x, ny = pet_pos[i].y;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    pet_pos[i] = {nx, ny};\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int H = 20;\nconst int W = 20;\nconst int N = H * W;\nconst int L = 200;\n\nint start_id, goal_id;\ndouble P, ONE_MINUS_P;\nint nxt_id[N][4];               // 0:U 1:D 2:L 3:R\nint dist_to_goal[N];\nchar DIRCHAR[4] = {'U', 'D', 'L', 'R'};\nint CMDMAP[256];\n\n// ------------------------------------------------------------\n// RNG\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> uniform01(0.0, 1.0);\n\n// ------------------------------------------------------------\n// full evaluation (standalone)\ndouble full_evaluate(const string& s) {\n    array<double, N> dp{}, ndp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    double score = 0.0;\n    for (int t = 0; t < (int)s.size(); ++t) {\n        int c = CMDMAP[(unsigned char)s[t]];\n        ndp.fill(0.0);\n        double imm = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            double stay = x * P;\n            double move = x * ONE_MINUS_P;\n            ndp[v] += stay;\n            int to = nxt_id[v][c];\n            if (to == goal_id) {\n                imm += move * (401 - (t + 1));\n            } else {\n                ndp[to] += move;\n            }\n        }\n        score += imm;\n        dp.swap(ndp);\n    }\n    return score;\n}\n\n// ------------------------------------------------------------\n// BFS shortest path on the underlying graph (ignoring forgetting)\nvector<char> bfs_shortest_path() {\n    queue<int> q;\n    vector<int> dist(N, -1), par(N, -1), pc(N, -1);\n    dist[start_id] = 0;\n    q.push(start_id);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == goal_id) break;\n        for (int d = 0; d < 4; ++d) {\n            int u = nxt_id[v][d];\n            if (u != v && dist[u] == -1) {\n                dist[u] = dist[v] + 1;\n                par[u] = v;\n                pc[u] = d;\n                q.push(u);\n            }\n        }\n    }\n    if (dist[goal_id] == -1) return {};\n    vector<char> path;\n    int cur = goal_id;\n    while (cur != start_id) {\n        path.push_back(DIRCHAR[pc[cur]]);\n        cur = par[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// monotone D/R path (only down and right)\nvector<char> monotone_path(const vector<string>& hwall,\n                           const vector<string>& vwall,\n                           int si, int sj, int ti, int tj) {\n    vector<vector<bool>> reach(H, vector<bool>(W, false));\n    vector<vector<char>> from(H, vector<char>(W, 0));\n    reach[si][sj] = true;\n    for (int i = si; i <= ti; ++i) {\n        for (int j = sj; j <= tj; ++j) {\n            if (!reach[i][j]) continue;\n            if (i < ti && vwall[i][j] == '0' && !reach[i + 1][j]) {\n                reach[i + 1][j] = true;\n                from[i + 1][j] = 'D';\n            }\n            if (j < tj && hwall[i][j] == '0' && !reach[i][j + 1]) {\n                reach[i][j + 1] = true;\n                from[i][j + 1] = 'R';\n            }\n        }\n    }\n    if (!reach[ti][tj]) return {};\n    vector<char> path;\n    int i = ti, j = tj;\n    while (i != si || j != sj) {\n        char c = from[i][j];\n        path.push_back(c);\n        if (c == 'D') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// greedy open-loop path (minimise expected remaining distance)\nstring greedy_path() {\n    array<double, N> dp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    string s;\n    s.reserve(L);\n    for (int t = 0; t < L; ++t) {\n        int best_c = 3;\n        double best_cost = 1e100;\n        for (int c = 0; c < 4; ++c) {\n            double cost = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = dp[v];\n                if (x == 0.0) continue;\n                int to = nxt_id[v][c];\n                double d = (to == goal_id) ? 0.0 : (double)dist_to_goal[to];\n                cost += x * (P * (double)dist_to_goal[v] + ONE_MINUS_P * d);\n            }\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_c = c;\n            }\n        }\n        s.push_back(DIRCHAR[best_c]);\n        array<double, N> ndp{};\n        ndp.fill(0.0);\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            ndp[v] += x * P;\n            int to = nxt_id[v][best_c];\n            if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n        }\n        dp.swap(ndp);\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Local search structure\nstruct Solver {\n    string cur;\n    double cur_score;\n    vector<array<double, N>> fw;   // size L+1\n    vector<array<double, N>> b;    // size L+1\n    vector<double> pref;           // size L+1\n\n    void init(const string& s) {\n        cur = s;\n        fw.assign(L + 1, {});\n        b.assign(L + 1, {});\n        pref.assign(L + 1, 0.0);\n        fw[0].fill(0.0);\n        fw[0][start_id] = 1.0;\n        for (int t = 0; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                if (x == 0.0) continue;\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        b[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n\n    // O(N) evaluation of changing position pos to command cmd (0..3)\n    double try_mutate(int pos, int cmd) const {\n        double reward = (401 - (pos + 1)) * ONE_MINUS_P;\n        double dot = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double val = P * b[pos + 1][v];\n            int to = nxt_id[v][cmd];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * b[pos + 1][to];\n            dot += fw[pos][v] * val;\n        }\n        return pref[pos] + dot;\n    }\n\n    // apply mutation and incrementally update tables\n    void apply_mutate(int pos, int cmd) {\n        cur[pos] = DIRCHAR[cmd];\n        // forward recompute from pos\n        for (int t = pos; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                if (x == 0.0) continue;\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        // backward recompute from pos down to 0\n        for (int t = pos; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n};\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    CMDMAP['U'] = 0; CMDMAP['D'] = 1; CMDMAP['L'] = 2; CMDMAP['R'] = 3;\n\n    int si, sj, ti, tj;\n    double p_input;\n    if (!(cin >> si >> sj >> ti >> tj >> p_input)) return 0;\n    P = p_input;\n    ONE_MINUS_P = 1.0 - P;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; ++i) cin >> hwall[i];\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; ++i) cin >> vwall[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    // precompute nxt_id\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int v = i * W + j;\n            // U\n            if (i > 0 && vwall[i - 1][j] == '0') nxt_id[v][0] = (i - 1) * W + j;\n            else nxt_id[v][0] = v;\n            // D\n            if (i + 1 < H && vwall[i][j] == '0') nxt_id[v][1] = (i + 1) * W + j;\n            else nxt_id[v][1] = v;\n            // L\n            if (j > 0 && hwall[i][j - 1] == '0') nxt_id[v][2] = i * W + (j - 1);\n            else nxt_id[v][2] = v;\n            // R\n            if (j + 1 < W && hwall[i][j] == '0') nxt_id[v][3] = i * W + (j + 1);\n            else nxt_id[v][3] = v;\n        }\n    }\n\n    // distances to goal (real graph distance)\n    {\n        queue<int> q;\n        vector<int> dist(N, -1);\n        dist[goal_id] = 0;\n        q.push(goal_id);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int u = nxt_id[v][d];\n                if (u != v && dist[u] == -1) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) dist_to_goal[i] = dist[i];\n    }\n\n    // ---------- generate candidates ----------\n    vector<string> candidates;\n\n    auto make_repeat = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        string s;\n        while ((int)s.size() < L) s += string(path.begin(), path.end());\n        s.resize(L);\n        return s;\n    };\n    auto make_stretch = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        int rep = max(1, L / (int)path.size());\n        string s;\n        for (char c : path) s += string(rep, c);\n        while ((int)s.size() < L) s.push_back(path[s.size() % path.size()]);\n        s.resize(L);\n        return s;\n    };\n\n    vector<char> sp = bfs_shortest_path();\n    if (!sp.empty()) {\n        candidates.push_back(make_repeat(sp));\n        candidates.push_back(make_stretch(sp));\n    }\n    vector<char> mono = monotone_path(hwall, vwall, si, sj, ti, tj);\n    if (!mono.empty()) {\n        candidates.push_back(make_repeat(mono));\n        candidates.push_back(make_stretch(mono));\n    }\n    candidates.push_back(greedy_path());\n\n    // some raw directional candidates\n    {\n        string s(L, 'D');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needD); ++i) s[i] = 'D';\n        for (; i < min(L, needD + needR); ++i) s[i] = 'R';\n        candidates.push_back(s);\n    }\n    {\n        string s(L, 'R');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needR); ++i) s[i] = 'R';\n        for (; i < min(L, needR + needD); ++i) s[i] = 'D';\n        candidates.push_back(s);\n    }\n    // random biased\n    for (int k = 0; k < 8; ++k) {\n        string s;\n        for (int i = 0; i < L; ++i) {\n            int r = rng() % 100;\n            if (r < 45) s += 'D';\n            else if (r < 90) s += 'R';\n            else if (r < 95) s += 'L';\n            else s += 'U';\n        }\n        candidates.push_back(s);\n    }\n\n    // evaluate and pick best initial\n    string best_str = string(L, 'R');\n    double best_score = -1.0;\n    for (auto& s : candidates) {\n        if ((int)s.size() != L) continue;\n        double sc = full_evaluate(s);\n        if (sc > best_score) {\n            best_score = sc;\n            best_str = s;\n        }\n    }\n\n    // ---------- local search ----------\n    Solver solver;\n    solver.init(best_str);\n    best_score = solver.cur_score;\n\n    // Hill climbing (coordinate ascent)\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < L; ++i) {\n            int cur_cmd = CMDMAP[(unsigned char)solver.cur[i]];\n            int best_cmd = cur_cmd;\n            double best_sc = solver.cur_score;\n            for (int d = 0; d < 3; ++d) {\n                int nc = (cur_cmd + 1 + d) & 3;\n                double sc = solver.try_mutate(i, nc);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    best_cmd = nc;\n                }\n            }\n            if (best_cmd != cur_cmd) {\n                solver.apply_mutate(i, best_cmd);\n                improved = true;\n                if (solver.cur_score > best_score) {\n                    best_score = solver.cur_score;\n                    best_str = solver.cur;\n                }\n            }\n        }\n    }\n\n    // Simulated Annealing\n    // sample diffs to set initial temperature\n    {\n        vector<double> diffs;\n        for (int k = 0; k < 1000; ++k) {\n            int pos = rng() % L;\n            int cur_cmd = CMDMAP[(unsigned char)solver.cur[pos]];\n            int nd = (cur_cmd + 1 + (rng() % 3)) & 3;\n            double sc = solver.try_mutate(pos, nd);\n            diffs.push_back(abs(sc - solver.cur_score));\n        }\n        sort(diffs.begin(), diffs.end());\n        double T0 = diffs[800];\n        if (T0 < 1e-9) T0 = 1.0;\n        const double T_end = 1e-4;\n        const int MAX_ITER = 300000;\n\n        auto start_time = chrono::steady_clock::now();\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            if (iter % 1000 == 0) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - start_time).count();\n                if (elapsed > 1.85) break;\n            }\n            double T = T0 * pow(T_end / T0, (double)iter / MAX_ITER);\n            int pos = rng() % L;\n            int cur_cmd = CMDMAP[(unsigned char)solver.cur[pos]];\n            int best_cmd = cur_cmd;\n            double best_mut_sc = solver.cur_score;\n            for (int d = 0; d < 3; ++d) {\n                int nc = (cur_cmd + 1 + d) & 3;\n                double sc = solver.try_mutate(pos, nc);\n                if (sc > best_mut_sc) {\n                    best_mut_sc = sc;\n                    best_cmd = nc;\n                }\n            }\n            if (best_cmd != cur_cmd) {\n                bool accept = false;\n                if (best_mut_sc >= solver.cur_score) {\n                    accept = true;\n                } else if (T > 1e-12) {\n                    double prob = exp((best_mut_sc - solver.cur_score) / T);\n                    if (uniform01(rng) < prob) accept = true;\n                }\n                if (accept) {\n                    solver.apply_mutate(pos, best_cmd);\n                    if (solver.cur_score > best_score) {\n                        best_score = solver.cur_score;\n                        best_str = solver.cur;\n                    }\n                }\n            }\n        }\n    }\n\n    cout << best_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static const int N = 30;\n    static const int V = N * N;          // 900\n    static const int S = V * 4;          // 3600\n\n    // input\n    int base[V];\n\n    // current and best rotation (0..3, but for types 4,5,6,7 only 0/1 are needed)\n    unsigned char cur_rot[V];\n    unsigned char best_rot[V];\n\n    // tables\n    int ft[8][4];                // final tile type after rotation\n    int8_t to[8][4];             // given in statement\n    int active_mask[8];          // bitmask of sides with to[t][d] != -1\n    int cell_i[V], cell_j[V];    // coordinates of each cell index\n\n    // random generator (splitmix64)\n    uint64_t rng;\n    uint64_t rand64() {\n        uint64_t z = (rng += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int rand_int(int m) { return (int)(rand64() % (uint64_t)m); }\n\n    // result of last evaluate()\n    int g_prod, g_sum;\n\n    // directions: left, up, right, down\n    const int di[4] = {0, -1, 0, 1};\n    const int dj[4] = {-1, 0, 1, 0};\n\n    // ------------------------------------------------------------\n    // evaluate current board; sets g_prod = L1*L2, g_sum = L1+L2\n    // ------------------------------------------------------------\n    inline void evaluate(const unsigned char* rot) {\n        alignas(64) int16_t nxt[S];\n        alignas(64) uint8_t vis[S];\n\n        // build successor array\n        for (int idx = 0; idx < V; ++idx) {\n            int t = ft[base[idx]][rot[idx]];\n            int bi = cell_i[idx];\n            int bj = cell_j[idx];\n            int id = idx * 4;\n\n            // d = 0\n            int d2 = to[t][0];\n            int16_t v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id] = v;\n\n            // d = 1\n            d2 = to[t][1];\n            v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id + 1] = v;\n\n            // d = 2\n            d2 = to[t][2];\n            v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id + 2] = v;\n\n            // d = 3\n            d2 = to[t][3];\n            v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id + 3] = v;\n        }\n\n        memset(vis, 0, S);\n        int best1 = 0, best2 = 0;\n\n        for (int s = 0; s < S; ++s) {\n            if (nxt[s] == -1 || vis[s]) continue;\n            int cur = s;\n            while (cur != -1 && !vis[cur]) {\n                vis[cur] = 1;\n                cur = nxt[cur];\n            }\n            if (cur != -1 && vis[cur] == 1) {\n                int len = 1;\n                int c = nxt[cur];\n                while (c != cur) {\n                    ++len;\n                    c = nxt[c];\n                }\n                if (len > best1) {\n                    best2 = best1;\n                    best1 = len;\n                } else if (len > best2) {\n                    best2 = len;\n                }\n            }\n            cur = s;\n            while (cur != -1 && vis[cur] == 1) {\n                vis[cur] = 2;\n                cur = nxt[cur];\n            }\n        }\n\n        g_prod = best1 * best2;\n        g_sum  = best1 + best2;\n    }\n\n    // ------------------------------------------------------------\n    // local greedy score: number of active sides matched with neighbours\n    // ------------------------------------------------------------\n    inline int local_score(int idx, int r, const unsigned char* rot) const {\n        int t = ft[base[idx]][r];\n        int bi = cell_i[idx];\n        int bj = cell_j[idx];\n        int mask = active_mask[t];\n        int sc = 0;\n        for (int d = 0; d < 4; ++d) if (mask >> d & 1) {\n            int ni = bi + di[d];\n            int nj = bj + dj[d];\n            if ((unsigned)ni >= 30u || (unsigned)nj >= 30u) continue;\n            int nidx = ni * N + nj;\n            int nt = ft[base[nidx]][rot[nidx]];\n            if (active_mask[nt] >> ((d + 2) & 3) & 1) ++sc;\n        }\n        return sc;\n    }\n\n    // ------------------------------------------------------------\n    void solve() {\n        // ----- read input -------------------------------------------------\n        for (int i = 0; i < N; ++i) {\n            string line;\n            cin >> line;\n            for (int j = 0; j < N; ++j) {\n                base[i * N + j] = line[j] - '0';\n            }\n        }\n\n        // ----- precomputations --------------------------------------------\n        for (int b = 0; b < 8; ++b) {\n            for (int r = 0; r < 4; ++r) {\n                if (b < 4) ft[b][r] = (b + r) & 3;\n                else if (b < 6) ft[b][r] = 4 + ((b - 4 + r) & 1);\n                else ft[b][r] = 6 + ((b - 6 + r) & 1);\n            }\n        }\n\n        const int8_t to_tbl[8][4] = {\n            { 1, 0,-1,-1},\n            { 3,-1,-1, 0},\n            {-1,-1, 3, 2},\n            {-1, 2, 1,-1},\n            { 1, 0, 3, 2},\n            { 3, 2, 1, 0},\n            { 2,-1, 0,-1},\n            {-1, 3,-1, 1}\n        };\n        memcpy(to, to_tbl, sizeof(to_tbl));\n\n        for (int t = 0; t < 8; ++t) {\n            int m = 0;\n            for (int d = 0; d < 4; ++d) if (to[t][d] != -1) m |= (1 << d);\n            active_mask[t] = m;\n        }\n\n        for (int idx = 0; idx < V; ++idx) {\n            cell_i[idx] = idx / N;\n            cell_j[idx] = idx % N;\n        }\n\n        rng = chrono::steady_clock::now().time_since_epoch().count();\n\n        // ----- random initialisation ---------------------------------------\n        for (int idx = 0; idx < V; ++idx) {\n            if (base[idx] < 4) cur_rot[idx] = (unsigned char)rand_int(4);\n            else               cur_rot[idx] = (unsigned char)rand_int(2);\n        }\n\n        // ----- quick greedy passes -----------------------------------------\n        for (int pass = 0; pass < 2; ++pass) {\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine((unsigned)rand64()));\n            for (int idx : order) {\n                int best_r = cur_rot[idx];\n                int best_sc = local_score(idx, best_r, cur_rot);\n                if (base[idx] < 4) {\n                    for (int d = 1; d < 4; ++d) {\n                        int nr = (best_r + d) & 3;\n                        int sc = local_score(idx, nr, cur_rot);\n                        if (sc > best_sc) {\n                            best_sc = sc;\n                            best_r = nr;\n                        }\n                    }\n                } else {\n                    int nr = best_r ^ 1;\n                    int sc = local_score(idx, nr, cur_rot);\n                    if (sc > best_sc) {\n                        best_sc = sc;\n                        best_r = nr;\n                    }\n                }\n                cur_rot[idx] = (unsigned char)best_r;\n            }\n        }\n\n        // ----- evaluate initial board --------------------------------------\n        evaluate(cur_rot);\n        int best_prod = g_prod;\n        memcpy(best_rot, cur_rot, V);\n\n        const double TIME_LIMIT = 1.9;\n        clock_t start_clock = clock();\n        auto elapsed = [&]() {\n            return double(clock() - start_clock) / CLOCKS_PER_SEC;\n        };\n\n        // ----- Simulated Annealing ----------------------------------------\n        double T_start = 50000.0;\n        double T_end   = 0.1;\n        double logT_start = log(T_start);\n        double logT_end   = log(T_end);\n\n        int cur_prod = g_prod;\n        int cur_sum  = g_sum;\n        int iter = 0;\n        double T = T_start;\n\n        while (elapsed() < TIME_LIMIT - 0.25) {   // leave 0.25s for hill climbing\n            if ((iter & 127) == 0) {\n                double p = elapsed() / (TIME_LIMIT - 0.25);\n                T = exp(logT_start + (logT_end - logT_start) * p);\n            }\n            ++iter;\n\n            int idx = rand_int(V);\n            int old_r = cur_rot[idx];\n            int new_r;\n            if (base[idx] < 4) {\n                new_r = (old_r + 1 + rand_int(3)) & 3;\n            } else {\n                new_r = old_r ^ 1;\n            }\n\n            cur_rot[idx] = (unsigned char)new_r;\n            evaluate(cur_rot);\n            int new_prod = g_prod;\n            int new_sum  = g_sum;\n\n            int64_t new_val = (int64_t)new_prod * 10000LL + new_sum;\n            int64_t old_val = (int64_t)cur_prod * 10000LL + cur_sum;\n            int64_t delta = new_val - old_val;\n\n            bool accept = false;\n            if (delta > 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / T);\n                double r = (rand64() >> 11) * (1.0 / (1ULL << 53));\n                if (r < prob) accept = true;\n            }\n\n            if (accept) {\n                cur_prod = new_prod;\n                cur_sum  = new_sum;\n                if (new_prod > best_prod) {\n                    best_prod = new_prod;\n                    memcpy(best_rot, cur_rot, V);\n                }\n            } else {\n                cur_rot[idx] = (unsigned char)old_r;\n            }\n        }\n\n        // ----- Hill climbing polish ---------------------------------------\n        memcpy(cur_rot, best_rot, V);\n        evaluate(cur_rot);\n        cur_prod = g_prod;\n        cur_sum  = g_sum;\n\n        bool improved = true;\n        while (improved && elapsed() < TIME_LIMIT) {\n            improved = false;\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine((unsigned)rand64()));\n\n            for (int idx : order) {\n                if (elapsed() >= TIME_LIMIT) break;\n                int saved_r = cur_rot[idx];\n                int best_r = saved_r;\n                int best_local_prod = cur_prod;\n                int best_local_sum  = cur_sum;\n\n                if (base[idx] < 4) {\n                    for (int d = 1; d < 4; ++d) {\n                        int nr = (saved_r + d) & 3;\n                        cur_rot[idx] = (unsigned char)nr;\n                        evaluate(cur_rot);\n                        if (g_prod > best_local_prod ||\n                            (g_prod == best_local_prod && g_sum > best_local_sum)) {\n                            best_local_prod = g_prod;\n                            best_local_sum  = g_sum;\n                            best_r = nr;\n                        }\n                    }\n                } else {\n                    int nr = saved_r ^ 1;\n                    cur_rot[idx] = (unsigned char)nr;\n                    evaluate(cur_rot);\n                    if (g_prod > best_local_prod ||\n                        (g_prod == best_local_prod && g_sum > best_local_sum)) {\n                        best_local_prod = g_prod;\n                        best_local_sum  = g_sum;\n                        best_r = nr;\n                    }\n                }\n\n                cur_rot[idx] = (unsigned char)best_r;\n                if (best_local_prod > cur_prod ||\n                    (best_local_prod == cur_prod && best_local_sum > cur_sum)) {\n                    cur_prod = best_local_prod;\n                    cur_sum  = best_local_sum;\n                    improved = true;\n                    if (cur_prod > best_prod) {\n                        best_prod = cur_prod;\n                        memcpy(best_rot, cur_rot, V);\n                    }\n                }\n            }\n        }\n\n        // ----- output -----------------------------------------------------\n        string out;\n        out.reserve(V);\n        for (int i = 0; i < V; ++i) out.push_back(char('0' + best_rot[i]));\n        cout << out << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nint target_score;                 // N*N - 2\nint SZ;                           // N*N\n\n// directions: 0=U, 1=D, 2=L, 3=R\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dc[4] = {'U', 'D', 'L', 'R'};\nconst int opp[4] = {1, 0, 3, 2};\n\ninline bool inside(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N;\n}\n\nstruct State {\n    array<uint8_t, 100> b;   // board cells, 0 = empty\n    int epos;                // empty cell index\n    int score;               // number of good edges\n};\n\n/* apply one legal slide; returns new state with updated score.\n   The caller guarantees the move is legal (adjacent cell inside board). */\nState apply_move(const State& s, int dir) {\n    State ns = s;\n    int ei = s.epos / N;\n    int ej = s.epos % N;\n    int ni = ei + di[dir];\n    int nj = ej + dj[dir];\n    int npos = ni * N + nj;          // cell that contains the tile being moved\n    int t = s.b[npos];               // tile value\n    int delta = 0;\n\n    // 1) remove edges that tile `t` had at its old position (npos)\n    //    skip the empty cell (s.epos) because it never contributed\n    // up\n    if (ni > 0) {\n        int nb = npos - N;\n        if (nb != s.epos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 2) && (nt & 8)) --delta;\n        }\n    }\n    // down\n    if (ni + 1 < N) {\n        int nb = npos + N;\n        if (nb != s.epos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 8) && (nt & 2)) --delta;\n        }\n    }\n    // left\n    if (nj > 0) {\n        int nb = npos - 1;\n        if (nb != s.epos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 1) && (nt & 4)) --delta;\n        }\n    }\n    // right\n    if (nj + 1 < N) {\n        int nb = npos + 1;\n        if (nb != s.epos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 4) && (nt & 1)) --delta;\n        }\n    }\n\n    // 2) add edges that tile `t` creates at the new position (old empty cell)\n    int ai = s.epos / N;\n    int aj = s.epos % N;\n    // up\n    if (ai > 0) {\n        int nb = s.epos - N;\n        if (nb != npos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 2) && (nt & 8)) ++delta;\n        }\n    }\n    // down\n    if (ai + 1 < N) {\n        int nb = s.epos + N;\n        if (nb != npos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 8) && (nt & 2)) ++delta;\n        }\n    }\n    // left\n    if (aj > 0) {\n        int nb = s.epos - 1;\n        if (nb != npos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 1) && (nt & 4)) ++delta;\n        }\n    }\n    // right\n    if (aj + 1 < N) {\n        int nb = s.epos + 1;\n        if (nb != npos) {\n            int nt = s.b[nb];\n            if (nt != 0 && (t & 4) && (nt & 1)) ++delta;\n        }\n    }\n\n    ns.b[s.epos] = static_cast<uint8_t>(t);\n    ns.b[npos] = 0;\n    ns.epos = npos;\n    ns.score = s.score + delta;\n    return ns;\n}\n\n/* depth\u2011limited DFS to escape a local maximum.\n   Returns the best strictly better score found and the path string.   */\nbool dfs_lookahead(const State& s, int depth, int start_score,\n                   int& best_score, string& cur_path, string& best_path) {\n    if (depth == 0) return false;\n\n    int last_dir = -1;\n    if (!cur_path.empty()) {\n        char lc = cur_path.back();\n        for (int d = 0; d < 4; ++d) if (dc[d] == lc) { last_dir = d; break; }\n    }\n\n    for (int d = 0; d < 4; ++d) {\n        int ei = s.epos / N, ej = s.epos % N;\n        int ni = ei + di[d], nj = ej + dj[d];\n        if (!inside(ni, nj)) continue;\n        if (last_dir != -1 && d == opp[last_dir]) continue;\n\n        State ns = apply_move(s, d);\n        if (ns.score > best_score) {\n            best_score = ns.score;\n            best_path = cur_path + dc[d];\n            if (best_score == target_score) return true;\n        }\n        // prune deep valleys\n        if (ns.score >= start_score - 3) {\n            cur_path.push_back(dc[d]);\n            if (dfs_lookahead(ns, depth - 1, start_score, best_score, cur_path, best_path))\n                return true;\n            cur_path.pop_back();\n        }\n    }\n    return false;\n}\n\n/* build a state from the input strings */\nState build_initial(const vector<string>& g, int& epos) {\n    State s;\n    s.score = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = g[i][j];\n            int v = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;\n            s.b[i * N + j] = static_cast<uint8_t>(v);\n            if (v == 0) epos = i * N + j;\n        }\n    }\n    s.epos = epos;\n\n    // compute initial score\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int idx = i * N + j;\n            int t = s.b[idx];\n            if (t == 0) continue;\n            if (j + 1 < N) {\n                int t2 = s.b[idx + 1];\n                if (t2 != 0 && (t & 4) && (t2 & 1)) ++s.score;\n            }\n            if (i + 1 < N) {\n                int t2 = s.b[idx + N];\n                if (t2 != 0 && (t & 8) && (t2 & 2)) ++s.score;\n            }\n        }\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    SZ = N * N;\n    target_score = SZ - 2;\n    int epos = -1;\n    State init_state = build_initial(grid, epos);\n\n    // best solution found so far\n    State best_state = init_state;\n    string best_path;\n\n    // current trajectory\n    State cur = init_state;\n    string cur_path;\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> kick_len_dist(5, 30);\n\n    const double TIME_LIMIT = 2.8; // seconds\n    auto start_t = chrono::steady_clock::now();\n\n    // Helper: restore cur to a given state\n    auto restore = [&](const State& st, const string& pth) {\n        cur = st;\n        cur_path = pth;\n    };\n\n    int iteration = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_t).count();\n        if (elapsed > TIME_LIMIT) break;\n        ++iteration;\n\n        /* -------- greedy hill climbing -------- */\n        bool improved = true;\n        while (improved && (int)cur_path.size() < T) {\n            improved = false;\n            int last_dir = -1;\n            if (!cur_path.empty()) {\n                char lc = cur_path.back();\n                for (int d = 0; d < 4; ++d) if (dc[d] == lc) { last_dir = d; break; }\n            }\n\n            int best_dir = -1;\n            int best_sc = -1;\n            vector<int> cand;\n\n            for (int d = 0; d < 4; ++d) {\n                int ei = cur.epos / N, ej = cur.epos % N;\n                int ni = ei + di[d], nj = ej + dj[d];\n                if (!inside(ni, nj)) continue;\n                if (last_dir != -1 && d == opp[last_dir]) continue;\n\n                State ns = apply_move(cur, d);\n                if (ns.score > best_sc) {\n                    best_sc = ns.score;\n                    cand.clear();\n                    cand.push_back(d);\n                } else if (ns.score == best_sc) {\n                    cand.push_back(d);\n                }\n            }\n\n            if (cand.empty()) break;\n\n            if (best_sc > cur.score) {\n                // accept the best improving move (random tie\u2011break)\n                int d = cand[uniform_int_distribution<int>(0, (int)cand.size() - 1)(rng)];\n                cur = apply_move(cur, d);\n                cur_path.push_back(dc[d]);\n\n                if (cur.score > best_state.score) {\n                    best_state = cur;\n                    best_path = cur_path;\n                    if (best_state.score == target_score) {\n                        cout << best_path << \"\\n\";\n                        return 0;\n                    }\n                }\n                improved = true;\n            } else {\n                break; // local maximum\n            }\n        }\n\n        /* -------- check time / success -------- */\n        if (best_state.score == target_score) {\n            cout << best_path << \"\\n\";\n            return 0;\n        }\n\n        /* -------- path too long \u2192 reset -------- */\n        if ((int)cur_path.size() >= T - 5) {\n            restore(best_state, best_path);\n            if ((int)cur_path.size() >= T - 5) {\n                restore(init_state, string());\n            }\n        }\n\n        /* -------- lookahead to escape shallow local optima -------- */\n        if (best_state.score >= target_score - 20) {\n            int dfs_best_sc = cur.score;\n            string dfs_cur_path, dfs_best_path;\n            if (dfs_lookahead(cur, 8, cur.score, dfs_best_sc, dfs_cur_path, dfs_best_path)) {\n                if (dfs_best_sc > cur.score) {\n                    for (char c : dfs_best_path) {\n                        int d = -1;\n                        for (int k = 0; k < 4; ++k) if (dc[k] == c) { d = k; break; }\n                        cur = apply_move(cur, d);\n                        cur_path.push_back(c);\n                    }\n                    if (cur.score > best_state.score) {\n                        best_state = cur;\n                        best_path = cur_path;\n                        if (best_state.score == target_score) {\n                            cout << best_path << \"\\n\";\n                            return 0;\n                        }\n                    }\n                    continue; // go back to greedy climbing\n                }\n            }\n        }\n\n        /* -------- kick (random walk) -------- */\n        // every few iterations return to the best known state before kicking\n        if (iteration % 5 == 0) {\n            restore(best_state, best_path);\n        }\n\n        int kick = kick_len_dist(rng);\n        if ((int)cur_path.size() + kick > T) {\n            restore(best_state, best_path);\n            if ((int)cur_path.size() + kick > T) {\n                restore(init_state, string());\n            }\n        }\n\n        for (int k = 0; k < kick && (int)cur_path.size() < T; ++k) {\n            int last_dir = -1;\n            if (!cur_path.empty()) {\n                char lc = cur_path.back();\n                for (int d = 0; d < 4; ++d) if (dc[d] == lc) { last_dir = d; break; }\n            }\n            vector<int> legal;\n            for (int d = 0; d < 4; ++d) {\n                int ei = cur.epos / N, ej = cur.epos % N;\n                int ni = ei + di[d], nj = ej + dj[d];\n                if (!inside(ni, nj)) continue;\n                if (last_dir != -1 && d == opp[last_dir]) continue;\n                legal.push_back(d);\n            }\n            if (legal.empty()) { // dead end, allow undo\n                for (int d = 0; d < 4; ++d) {\n                    int ei = cur.epos / N, ej = cur.epos % N;\n                    int ni = ei + di[d], nj = ej + dj[d];\n                    if (!inside(ni, nj)) continue;\n                    legal.push_back(d);\n                }\n            }\n            int d = legal[uniform_int_distribution<int>(0, (int)legal.size() - 1)(rng)];\n            cur = apply_move(cur, d);\n            cur_path.push_back(dc[d]);\n        }\n    }\n\n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ------------------------------------------------------------\n// Random\n// ------------------------------------------------------------\nuint64_t rng_seed() {\n    return chrono::steady_clock::now().time_since_epoch().count();\n}\nstruct xoshiro256ss {\n    uint64_t s[4];\n    xoshiro256ss(uint64_t seed) {\n        s[0] = splitmix64(seed);\n        s[1] = splitmix64(s[0]);\n        s[2] = splitmix64(s[1]);\n        s[3] = splitmix64(s[2]);\n    }\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;\n        return x ^ (x >> 31);\n    }\n    uint64_t operator()() {\n        uint64_t r = rotl(s[1] * 5, 7) * 9;\n        uint64_t t = s[1] << 17;\n        s[2] ^= s[0];\n        s[3] ^= s[1];\n        s[1] ^= s[2];\n        s[0] ^= s[3];\n        s[2] ^= t;\n        s[3] = rotl(s[3], 45);\n        return r;\n    }\n    static uint64_t rotl(uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n};\nxoshiro256ss rng(rng_seed());\n\nlong long rnd_ll(long long l, long long r) {\n    if (l >= r) return l;\n    return l + (long long)(rng() % (uint64_t)(r - l + 1));\n}\nint rnd_int(int l, int r) {\n    if (l >= r) return l;\n    return l + (int)(rng() % (uint64_t)(r - l + 1));\n}\n\n// ------------------------------------------------------------\n// Geometry / Line helpers\n// ------------------------------------------------------------\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C;          // Ax + By + C = 0\n};\n\nint N, K;\narray<int,11> need;\nvector<long long> xs, ys;\nint target_score;\n\nLine make_line_pts(long long px, long long py, long long qx, long long qy) {\n    Line L;\n    L.px = px; L.py = py; L.qx = qx; L.qy = qy;\n    L.A = qy - py;\n    L.B = px - qx;\n    L.C = qx*py - px*qy;\n    return L;\n}\n\nlong long egcd_positive(long long a, long long b, long long &x, long long &y) {\n    if (b == 0) {\n        x = 1; y = 0;\n        return a;\n    }\n    long long x1, y1;\n    long long g = egcd_positive(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\n// Find two integer points on Ax+By+C=0 with coordinates in [-1e9,1e9]\nbool get_two_points(long long A, long long B, long long C,\n                    long long &x1, long long &y1, long long &x2, long long &y2) {\n    const long long LIM = 1000000000LL;\n    if (B == 0) {\n        if (A == 0) return false;\n        if (C % A != 0) return false;\n        x1 = -C / A;\n        if (x1 < -LIM || x1 > LIM) return false;\n        y1 = 0;\n        x2 = x1; y2 = 1;\n        return true;\n    }\n    long long g = std::gcd(std::abs(A), std::abs(B));\n    if (C % g != 0) return false;\n    long long a = A / g;\n    long long b = B / g;\n    long long c = -C / g;               // a*x + b*y = c\n    long long mod = std::abs(b);\n    long long a_mod = ((a % mod) + mod) % mod;\n    long long c_mod = ((c % mod) + mod) % mod;\n    long long inv, tmp;\n    egcd_positive(a_mod, mod, inv, tmp);\n    inv = ((inv % mod) + mod) % mod;\n    long long x0 = (long long)((__int128)c_mod * inv % mod);\n\n    long long t = 0;\n    if (x0 < -LIM) t = (-LIM - x0 + mod - 1) / mod;\n    else if (x0 > LIM) t = -(x0 - LIM + mod - 1) / mod;\n\n    long long x = x0 + mod * t;\n    __int128 num = -(__int128)C - (__int128)A * x;\n    long long y = (long long)(num / B);\n\n    long long step_y = (b > 0) ? -a : a;   // change of y when x increases by mod\n    if (y < -LIM) {\n        long long need = -LIM - y;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need + abs_sy - 1) / abs_sy;\n            x += mod * dt;\n            y += step_y * dt;\n        }\n    } else if (y > LIM) {\n        long long need = y - LIM;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need + abs_sy - 1) / abs_sy;\n            x -= mod * dt;\n            y -= step_y * dt;\n        }\n    }\n    if (x < -LIM || x > LIM || y < -LIM || y > LIM) return false;\n\n    x1 = x; y1 = y;\n    x2 = x1 + mod;\n    if (x2 > LIM) x2 = x1 - mod;\n    __int128 num2 = -(__int128)C - (__int128)A * x2;\n    y2 = (long long)(num2 / B);\n    return true;\n}\n\nbool intersects_disk(const Line& L) {\n    __int128 c2 = (__int128)L.C * L.C;\n    __int128 ab2 = (__int128)L.A * L.A + (__int128)L.B * L.B;\n    return c2 < ab2 * 100000000LL;   // radius 1e4, squared 1e8\n}\n\nbool valid_line(const Line& L) {\n    if (!intersects_disk(L)) return false;\n    for (int i = 0; i < N; ++i) {\n        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n        if (v == 0) return false;\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// Candidate generators\n// ------------------------------------------------------------\nLine gen_random_line() {\n    const long long LIM = 200000;\n    while (true) {\n        long long x1 = rnd_ll(-LIM, LIM);\n        long long y1 = rnd_ll(-LIM, LIM);\n        long long x2 = rnd_ll(-LIM, LIM);\n        long long y2 = rnd_ll(-LIM, LIM);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n}\n\nLine gen_separator_line() {\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        int i = rnd_int(0, N - 1);\n        int j = rnd_int(0, N - 1);\n        if (i == j) continue;\n        long long xi = xs[i], yi = ys[i];\n        long long xj = xs[j], yj = ys[j];\n        long long A = xj - xi;\n        long long B = yj - yi;\n        if (A == 0 && B == 0) continue;\n        __int128 rhs = (__int128)xj*xj + (__int128)yj*yj - (__int128)xi*xi - (__int128)yi*yi;\n        long long T = (long long)(rhs / 2);\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        for (int d = -10; d <= 10; ++d) {\n            long long C = T + d;\n            if (C % g != 0) continue;\n            long long px, py, qx, qy;\n            if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\nLine gen_gap_line() {\n    static vector<long long> vals;\n    vals.assign(N, 0);\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        long long A = rnd_ll(-1000, 1000);\n        long long B = rnd_ll(-1000, 1000);\n        if (A == 0 && B == 0) continue;\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        A /= g; B /= g;\n        for (int i = 0; i < N; ++i) vals[i] = A * xs[i] + B * ys[i];\n        sort(vals.begin(), vals.end());\n        vector<long long> uniq;\n        for (long long v : vals) {\n            if (uniq.empty() || uniq.back() != v) uniq.push_back(v);\n        }\n        if (uniq.size() <= 1) continue;\n        int idx = rnd_int(0, (int)uniq.size() - 2);\n        long long lo = uniq[idx];\n        long long hi = uniq[idx + 1];\n        if (hi <= lo + 1) continue;\n        long long C;\n        if (hi - lo > 2000000) C = lo + 1 + rnd_ll(0, 2000000);\n        else C = lo + 1 + rnd_ll(0, hi - lo - 1);\n        long long px, py, qx, qy;\n        if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n        Line L = make_line_pts(px, py, qx, qy);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\nLine perturb_line(const Line& L0) {\n    const long long D = 5;\n    for (int attempt = 0; attempt < 10; ++attempt) {\n        long long x1 = L0.px + rnd_ll(-D, D);\n        long long y1 = L0.py + rnd_ll(-D, D);\n        long long x2 = L0.qx + rnd_ll(-D, D);\n        long long y2 = L0.qy + rnd_ll(-D, D);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\n// ------------------------------------------------------------\n// Fast hash table for signature counting (open addressing)\n// ------------------------------------------------------------\nstruct Sig {\n    uint64_t a, b;\n};\n\nstruct FastHT {\n    struct Node {\n        uint64_t a, b;\n        int cnt;\n    };\n    int n;\n    vector<Node> nodes;\n    vector<int> seen;\n    vector<int> occ;\n    int timer;\n    FastHT(int n_ = 1 << 14) {\n        n = n_;\n        nodes.resize(n);\n        seen.assign(n, 0);\n        timer = 1;\n    }\n    inline void next_timer() {\n        ++timer;\n        occ.clear();\n        if (timer > 2000000000) {\n            fill(seen.begin(), seen.end(), 0);\n            timer = 1;\n        }\n    }\n    inline void add(uint64_t a, uint64_t b) {\n        size_t h = a ^ (b * 11400714819323198485ull);\n        size_t idx = h & (n - 1);\n        while (seen[idx] == timer) {\n            if (nodes[idx].a == a && nodes[idx].b == b) {\n                ++nodes[idx].cnt;\n                return;\n            }\n            idx = (idx + 1) & (n - 1);\n        }\n        seen[idx] = timer;\n        nodes[idx].a = a;\n        nodes[idx].b = b;\n        nodes[idx].cnt = 1;\n        occ.push_back((int)idx);\n    }\n    inline int get_score(const array<int,11>& need) const {\n        int have[11] = {0};\n        for (int idx : occ) {\n            int c = nodes[idx].cnt;\n            if (c >= 1 && c <= 10) ++have[c];\n        }\n        int s = 0;\n        for (int d = 1; d <= 10; ++d) s += min(need[d], have[d]);\n        return s;\n    }\n};\n\nFastHT ht;\n\ninline int evaluate_sigs(const vector<Sig>& sigs) {\n    ht.next_timer();\n    for (const auto& s : sigs) ht.add(s.a, s.b);\n    return ht.get_score(need);\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> need[d];\n        target_score += need[d];\n    }\n    xs.resize(N); ys.resize(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    // ---------- Greedy construction ----------\n    vector<Line> lines;\n    vector<Sig> sig(N, {0, 0});\n    int cur_score = 0;\n    const int GREEDY_CANDS = 40;\n\n    vector<Sig> tmp(N), best_sig;\n\n    for (int step = 0; step < K; ++step) {\n        Line best_line;\n        int best_score = cur_score;\n\n        for (int cand = 0; cand < GREEDY_CANDS; ++cand) {\n            int type = rnd_int(0, 2);\n            Line L;\n            if (type == 0) L = gen_random_line();\n            else if (type == 1) L = gen_separator_line();\n            else L = gen_gap_line();\n            if (!valid_line(L)) continue;\n\n            int pj = step;\n            if (pj < 64) {\n                uint64_t mask = 1ULL << pj;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = (sig[i].a & ~mask) | (bit << pj);\n                    tmp[i].b = sig[i].b;\n                }\n            } else {\n                uint64_t mask = 1ULL << (pj - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = sig[i].a;\n                    tmp[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                }\n            }\n            int score = evaluate_sigs(tmp);\n            if (score > best_score) {\n                best_score = score;\n                best_line = L;\n                best_sig.swap(tmp);\n            }\n        }\n\n        if (best_score > cur_score) {\n            lines.push_back(best_line);\n            sig.swap(best_sig);\n            cur_score = best_score;\n        } else {\n            Line L = gen_random_line();\n            while (!valid_line(L)) L = gen_random_line();\n            lines.push_back(L);\n            int pj = step;\n            if (pj < 64) {\n                uint64_t mask = 1ULL << pj;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n                }\n            } else {\n                uint64_t mask = 1ULL << (pj - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                }\n            }\n            cur_score = evaluate_sigs(sig);\n        }\n        if (cur_score == target_score) break;\n    }\n\n    while ((int)lines.size() < K) {\n        Line L = gen_random_line();\n        lines.push_back(L);\n        int pj = (int)lines.size() - 1;\n        if (pj < 64) {\n            uint64_t mask = 1ULL << pj;\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n            }\n        } else {\n            uint64_t mask = 1ULL << (pj - 64);\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n            }\n        }\n    }\n    cur_score = evaluate_sigs(sig);\n\n    vector<Line> best_lines = lines;\n    vector<Sig> best_sig_overall = sig;\n    int best_score = cur_score;\n\n    // ---------- Local search ----------\n    const double TIME_LIMIT = 2.85;\n    while (elapsed() < TIME_LIMIT) {\n        for (int j = 0; j < K; ++j) {\n            if (elapsed() >= TIME_LIMIT) break;\n            Line best_local_line = lines[j];\n            int best_local_score = cur_score;\n            vector<Sig> best_local_sig;\n\n            const int LS_CANDS = 12;\n            for (int cand = 0; cand < LS_CANDS; ++cand) {\n                int type = rnd_int(0, 3);\n                Line L;\n                if (type == 0) L = gen_random_line();\n                else if (type == 1) L = gen_separator_line();\n                else if (type == 2) L = gen_gap_line();\n                else L = perturb_line(lines[j]);\n                if (!valid_line(L)) continue;\n\n                if (j < 64) {\n                    uint64_t mask = 1ULL << j;\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = (sig[i].a & ~mask) | (bit << j);\n                        tmp[i].b = sig[i].b;\n                    }\n                } else {\n                    uint64_t mask = 1ULL << (j - 64);\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = sig[i].a;\n                        tmp[i].b = (sig[i].b & ~mask) | (bit << (j - 64));\n                    }\n                }\n                int score = evaluate_sigs(tmp);\n                if (score > best_local_score) {\n                    best_local_score = score;\n                    best_local_line = L;\n                    best_local_sig.swap(tmp);\n                }\n            }\n\n            if (best_local_score > cur_score) {\n                lines[j] = best_local_line;\n                sig.swap(best_local_sig);\n                cur_score = best_local_score;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_lines = lines;\n                    best_sig_overall = sig;\n                }\n            }\n        }\n        if (best_score == target_score) break;\n    }\n\n    // ---------- Output ----------\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << best_lines[i].px << \" \" << best_lines[i].py << \" \"\n             << best_lines[i].qx << \" \" << best_lines[i].qy << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 64;\n\nint N, M;\nint cx;\nint wgt[MAXN][MAXN];\nbool dot[MAXN][MAXN];\nbool horiz[MAXN][MAXN]; // (x,y)-(x+1,y)\nbool vert[MAXN][MAXN];  // (x,y)-(x,y+1)\nbool diag1[MAXN][MAXN]; // (x,y)-(x+1,y+1)\nbool diag2[MAXN][MAXN]; // (x,y)-(x+1,y-1)\nbool inq[MAXN][MAXN];\n\nusing Record = array<int,8>; // x1,y1,x2,y2,x3,y3,x4,y4\n\n// ---------- edge utilities ----------\ninline bool check_edge(int x1, int y1, int x2, int y2) {\n    int dx = (x2 > x1) - (x2 < x1);\n    int dy = (y2 > y1) - (y2 < y1);\n    int x = x1, y = y1;\n    while (x != x2 || y != y2) {\n        int nx = x + dx;\n        int ny = y + dy;\n        if (nx != x2 || ny != y2) {\n            if (dot[nx][ny]) return false;\n        }\n        if (dx == 1 && dy == 0) { if (horiz[x][y]) return false; }\n        else if (dx == -1 && dy == 0) { if (horiz[x-1][y]) return false; }\n        else if (dx == 0 && dy == 1) { if (vert[x][y]) return false; }\n        else if (dx == 0 && dy == -1) { if (vert[x][y-1]) return false; }\n        else if (dx == 1 && dy == 1) { if (diag1[x][y]) return false; }\n        else if (dx == -1 && dy == -1) { if (diag1[x-1][y-1]) return false; }\n        else if (dx == 1 && dy == -1) { if (diag2[x][y]) return false; }\n        else if (dx == -1 && dy == 1) { if (diag2[x-1][y+1]) return false; }\n        x = nx; y = ny;\n    }\n    return true;\n}\n\ninline void draw_edge(int x1, int y1, int x2, int y2) {\n    int dx = (x2 > x1) - (x2 < x1);\n    int dy = (y2 > y1) - (y2 < y1);\n    int x = x1, y = y1;\n    while (x != x2 || y != y2) {\n        int nx = x + dx;\n        int ny = y + dy;\n        if (dx == 1 && dy == 0) horiz[x][y] = true;\n        else if (dx == -1 && dy == 0) horiz[x-1][y] = true;\n        else if (dx == 0 && dy == 1) vert[x][y] = true;\n        else if (dx == 0 && dy == -1) vert[x][y-1] = true;\n        else if (dx == 1 && dy == 1) diag1[x][y] = true;\n        else if (dx == -1 && dy == -1) diag1[x-1][y-1] = true;\n        else if (dx == 1 && dy == -1) diag2[x][y] = true;\n        else if (dx == -1 && dy == 1) diag2[x-1][y+1] = true;\n        x = nx; y = ny;\n    }\n}\n\n// check a concrete rectangle (order p1-p2-p3-p4)\ninline bool check_rect(int x1, int y1, int x2, int y2,\n                       int x3, int y3, int x4, int y4) {\n    if (dot[x1][y1]) return false;\n    if (!dot[x2][y2] || !dot[x3][y3] || !dot[x4][y4]) return false;\n    if (!check_edge(x1,y1,x2,y2)) return false;\n    if (!check_edge(x2,y2,x3,y3)) return false;\n    if (!check_edge(x3,y3,x4,y4)) return false;\n    if (!check_edge(x4,y4,x1,y1)) return false;\n    return true;\n}\n\ninline void draw_rect(const Record &r) {\n    draw_edge(r[0],r[1],r[2],r[3]);\n    draw_edge(r[2],r[3],r[4],r[5]);\n    draw_edge(r[4],r[5],r[6],r[7]);\n    draw_edge(r[6],r[7],r[0],r[1]);\n}\n\n// search any valid rectangle with p1 = (x,y); prefers smaller ones\nbool get_rect(int x, int y, Record &out) {\n    // axis-aligned, try small distances first\n    for (int dx = 1; dx < N; ++dx) {\n        for (int sx = -1; sx <= 1; sx += 2) {\n            int x2 = x + sx * dx;\n            if (x2 < 0 || x2 >= N) continue;\n            if (!dot[x2][y]) continue;\n            for (int dy = 1; dy < N; ++dy) {\n                for (int sy = -1; sy <= 1; sy += 2) {\n                    int y2 = y + sy * dy;\n                    if (y2 < 0 || y2 >= N) continue;\n                    if (!dot[x][y2]) continue;\n                    if (!dot[x2][y2]) continue;\n                    if (check_rect(x,y,x2,y,x2,y2,x,y2)) {\n                        out = {x,y,x2,y,x2,y2,x,y2};\n                        return true;\n                    }\n                }\n            }\n        }\n    }\n    // 45-degree\n    for (int da = 1; da < N; ++da) {\n        for (int sa = -1; sa <= 1; sa += 2) {\n            int x2 = x + sa * da;\n            int y2 = y + sa * da;\n            if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N) continue;\n            if (!dot[x2][y2]) continue;\n            for (int db = 1; db < N; ++db) {\n                for (int sb = -1; sb <= 1; sb += 2) {\n                    int x4 = x + sb * db;\n                    int y4 = y - sb * db;\n                    if (x4 < 0 || x4 >= N || y4 < 0 || y4 >= N) continue;\n                    if (!dot[x4][y4]) continue;\n                    int x3 = x2 + sb * db; // = x2 + x4 - x\n                    int y3 = y2 - sb * db; // = y2 + y4 - y\n                    if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                    if (!dot[x3][y3]) continue;\n                    if (check_rect(x,y,x2,y2,x3,y3,x4,y4)) {\n                        out = {x,y,x2,y2,x3,y3,x4,y4};\n                        return true;\n                    }\n                }\n            }\n        }\n    }\n    return false;\n}\n\n// ---------- heap ----------\nusing HeapItem = tuple<int,int,int>; // (-weight? no, default max-heap -> descending)\npriority_queue<HeapItem> pq;\n\ninline void try_push(int x, int y) {\n    if (dot[x][y]) return;\n    if (inq[x][y]) return;\n    inq[x][y] = true;\n    pq.emplace(wgt[x][y], x, y);\n}\n\n// when a new dot appears at (x,y), enumerate all rectangles that use it\n// as a corner and push the corresponding p1 cells\nvoid find_new_candidates(int x, int y) {\n    // ---- axis : p_new as adjacent (p2 or p4) ----\n    // p1 on same row\n    for (int x1 = 0; x1 < N; ++x1) if (!dot[x1][y]) {\n        for (int y1 = 0; y1 < N; ++y1) if (dot[x][y1] && dot[x1][y1]) {\n            if (check_rect(x1,y, x,y, x,y1, x1,y1))\n                try_push(x1, y);\n        }\n    }\n    // p1 on same column\n    for (int y1 = 0; y1 < N; ++y1) if (!dot[x][y1]) {\n        for (int x1 = 0; x1 < N; ++x1) if (dot[x1][y] && dot[x1][y1]) {\n            if (check_rect(x,y1, x1,y1, x1,y, x,y))\n                try_push(x, y1);\n        }\n    }\n\n    // ---- axis : p_new as opposite (p3) ----\n    for (int x1 = 0; x1 < N; ++x1) if (dot[x1][y]) {\n        for (int y1 = 0; y1 < N; ++y1) if (dot[x][y1]) {\n            if (!dot[x1][y1]) {\n                if (check_rect(x1,y1, x1,y, x,y, x,y1))\n                    try_push(x1, y1);\n            }\n        }\n    }\n\n    // ---- 45-deg : p_new as adjacent on diag+1 ----\n    for (int d = -min(x,y); d < N - max(x,y); ++d) if (d != 0) {\n        int x1 = x + d, y1 = y + d;\n        if (dot[x1][y1]) continue;\n        int s = x1 + y1;\n        for (int x4 = 0; x4 < N; ++x4) {\n            int y4 = s - x4;\n            if (y4 < 0 || y4 >= N) continue;\n            if (!dot[x4][y4]) continue;\n            int x3 = x + x4 - x1;\n            int y3 = y + y4 - y1;\n            if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n            if (!dot[x3][y3]) continue;\n            if (check_rect(x1,y1, x,y, x3,y3, x4,y4))\n                try_push(x1, y1);\n        }\n    }\n\n    // ---- 45-deg : p_new as adjacent on diag-1 ----\n    for (int d = max(-x, -(N-1-y)); d <= min(N-1-x, y); ++d) if (d != 0) {\n        int x1 = x + d, y1 = y - d;\n        if (dot[x1][y1]) continue;\n        int diff = x1 - y1;\n        for (int x4 = 0; x4 < N; ++x4) {\n            int y4 = x4 - diff;\n            if (y4 < 0 || y4 >= N) continue;\n            if (!dot[x4][y4]) continue;\n            int x3 = x + x4 - x1;\n            int y3 = y + y4 - y1;\n            if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n            if (!dot[x3][y3]) continue;\n            if (check_rect(x1,y1, x,y, x3,y3, x4,y4))\n                try_push(x1, y1);\n        }\n    }\n\n    // ---- 45-deg : p_new as opposite (p3) ----\n    for (int d = -min(x,y); d < N - max(x,y); ++d) if (d != 0) {\n        int x2 = x + d, y2 = y + d;\n        if (!dot[x2][y2]) continue;\n        for (int e = max(-x, -(N-1-y)); e <= min(N-1-x, y); ++e) if (e != 0) {\n            int x4 = x + e, y4 = y - e;\n            if (!dot[x4][y4]) continue;\n            int x1 = x2 + x4 - x;\n            int y1 = y2 + y4 - y;\n            if (x1 < 0 || x1 >= N || y1 < 0 || y1 >= N) continue;\n            if (dot[x1][y1]) continue;\n            if (check_rect(x1,y1, x2,y2, x,y, x4,y4))\n                try_push(x1, y1);\n        }\n    }\n}\n\n// ---------- main ----------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N >> M)) return 0;\n    cx = (N - 1) / 2;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            wgt[i][j] = (i - cx)*(i - cx) + (j - cx)*(j - cx) + 1;\n\n    memset(dot, 0, sizeof(dot));\n    for (int i = 0; i < M; ++i) {\n        int x, y; cin >> x >> y;\n        dot[x][y] = true;\n    }\n\n    memset(horiz, 0, sizeof(horiz));\n    memset(vert, 0, sizeof(vert));\n    memset(diag1, 0, sizeof(diag1));\n    memset(diag2, 0, sizeof(diag2));\n    memset(inq, 0, sizeof(inq));\n\n    // initial heap\n    Record rec;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y < N; ++y) if (!dot[x][y]) {\n            if (get_rect(x, y, rec)) {\n                inq[x][y] = true;\n                pq.emplace(wgt[x][y], x, y);\n            }\n        }\n    }\n\n    vector<Record> ops;\n\n    while (!pq.empty()) {\n        auto [W, x, y] = pq.top();\n        pq.pop();\n        inq[x][y] = false;\n        if (dot[x][y]) continue;\n        Record r;\n        if (!get_rect(x, y, r)) continue;\n        // perform move\n        dot[x][y] = true;\n        draw_rect(r);\n        ops.push_back(r);\n        find_new_candidates(x, y);\n    }\n\n    cout << ops.size() << \"\\n\";\n    for (auto &r : ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << r[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    array<int, 100> a;\n    State() { a.fill(0); }\n};\n\n/* tilt the whole box in one direction\n   0:F (up, row 0), 1:B (down, row 9), 2:L (left, col 0), 3:R (right, col 9) */\nState tilt(const State& s, int dir) {\n    State ns;\n    ns.a.fill(0);\n    if (dir == 0) {                 // Forward / Up\n        for (int c = 0; c < 10; ++c) {\n            int w = 0;\n            for (int r = 0; r < 10; ++r) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[w++ * 10 + c] = x;\n            }\n        }\n    } else if (dir == 1) {          // Backward / Down\n        for (int c = 0; c < 10; ++c) {\n            int w = 9;\n            for (int r = 9; r >= 0; --r) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[w-- * 10 + c] = x;\n            }\n        }\n    } else if (dir == 2) {          // Left\n        for (int r = 0; r < 10; ++r) {\n            int w = 0;\n            for (int c = 0; c < 10; ++c) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[r * 10 + w++] = x;\n            }\n        }\n    } else {                         // Right\n        for (int r = 0; r < 10; ++r) {\n            int w = 9;\n            for (int c = 9; c >= 0; --c) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[r * 10 + w--] = x;\n            }\n        }\n    }\n    return ns;\n}\n\n/* where does the candy currently at 'pos' end up after tilting 'dir'? */\nint new_pos_after_tilt(const State& s, int pos, int dir) {\n    int r = pos / 10;\n    int c = pos % 10;\n    if (dir == 0) {                 // F\n        int cnt = 0;\n        for (int i = 0; i < r; ++i) if (s.a[i * 10 + c] != 0) ++cnt;\n        return cnt * 10 + c;\n    } else if (dir == 1) {          // B\n        int cnt = 0;\n        for (int i = r + 1; i < 10; ++i) if (s.a[i * 10 + c] != 0) ++cnt;\n        return (9 - cnt) * 10 + c;\n    } else if (dir == 2) {          // L\n        int cnt = 0;\n        for (int i = 0; i < c; ++i) if (s.a[r * 10 + i] != 0) ++cnt;\n        return r * 10 + cnt;\n    } else {                         // R\n        int cnt = 0;\n        for (int i = c + 1; i < 10; ++i) if (s.a[r * 10 + i] != 0) ++cnt;\n        return r * 10 + (9 - cnt);\n    }\n}\n\n/* exact score = sum of n_i^2 */\nint evaluate(const State& s) {\n    bool vis[100] = {false};\n    int q[100];\n    int sum = 0;\n    for (int i = 0; i < 100; ++i) {\n        if (s.a[i] == 0 || vis[i]) continue;\n        int f = s.a[i];\n        int sz = 0;\n        int qh = 0, qt = 0;\n        q[qt++] = i;\n        vis[i] = true;\n        while (qh < qt) {\n            int u = q[qh++];\n            ++sz;\n            int r = u / 10;\n            int c = u % 10;\n            if (r > 0) {\n                int v = (r - 1) * 10 + c;\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (r < 9) {\n                int v = (r + 1) * 10 + c;\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (c > 0) {\n                int v = r * 10 + (c - 1);\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (c < 9) {\n                int v = r * 10 + (c + 1);\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n        }\n        sum += sz * sz;\n    }\n    return sum;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> flav(100);\n    for (int i = 0; i < 100; ++i) {\n        if (!(cin >> flav[i])) return 0;\n    }\n\n    const int K = 40;                     // rollouts per direction\n    const char dname[4] = {'F', 'B', 'L', 'R'};\n    State cur;\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        --p;                              // 0-based\n\n        /* place in the p-th empty cell (row-major = front-to-back, left-to-right) */\n        int pos = -1;\n        for (int i = 0; i < 100; ++i) {\n            if (cur.a[i] == 0) {\n                if (p == 0) { pos = i; break; }\n                --p;\n            }\n        }\n        cur.a[pos] = flav[t];\n\n        /* 100th placement fills the board; tilt does nothing */\n        if (t == 99) {\n            cout << \"F\\n\";\n            cout.flush();\n            break;\n        }\n\n        State base[4];\n        for (int d = 0; d < 4; ++d) base[d] = tilt(cur, d);\n\n        long long total[4] = {0, 0, 0, 0};\n\n        for (int k = 0; k < K; ++k) {\n            /* same random seed for all 4 directions -> variance reduction */\n            unsigned seed = 123456789u + t * 10007u + k;\n            for (int d = 0; d < 4; ++d) {\n                mt19937 rng(seed);\n                State sim = base[d];\n\n                for (int s = t + 1; s < 100; ++s) {\n                    int empties[100];\n                    int ecnt = 0;\n                    for (int i = 0; i < 100; ++i)\n                        if (sim.a[i] == 0) empties[ecnt++] = i;\n\n                    if (ecnt == 0) break;\n                    int idx = empties[rng() % ecnt];\n                    int f = flav[s];\n                    sim.a[idx] = f;\n\n                    if (s == 99) break;   // last candy, no tilt follows\n\n                    /* local greedy: maximize same-flavor neighbours of the new candy */\n                    int best_dir = 0;\n                    int best_sc = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int np = new_pos_after_tilt(sim, idx, d2);\n                        State ns = tilt(sim, d2);\n                        int sc = 0;\n                        int r = np / 10;\n                        int c = np % 10;\n                        if (r > 0 && ns.a[(r - 1) * 10 + c] == f) ++sc;\n                        if (r < 9 && ns.a[(r + 1) * 10 + c] == f) ++sc;\n                        if (c > 0 && ns.a[r * 10 + (c - 1)] == f) ++sc;\n                        if (c < 9 && ns.a[r * 10 + (c + 1)] == f) ++sc;\n                        if (sc > best_sc) {\n                            best_sc = sc;\n                            best_dir = d2;\n                        }\n                    }\n                    sim = tilt(sim, best_dir);\n                }\n                total[d] += evaluate(sim);\n            }\n        }\n\n        int best = 0;\n        for (int d = 1; d < 4; ++d)\n            if (total[d] > total[best]) best = d;\n\n        cur = tilt(cur, best);\n        cout << dname[best] << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ULL = unsigned long long;\nusing ll = long long;\n\nint M;\ndouble eps;\nint N;\nint L; // N*(N-1)/2\nmt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Graph {\n    ULL a[64];\n    void clear(int n) { for (int i = 0; i < n; ++i) a[i] = 0; }\n};\n\nusing Feature = vector<double>;\n\n// ------------------------------------------------------------\n// Feature extraction\n// ------------------------------------------------------------\nFeature extract(const Graph &g, int n) {\n    int deg[64] = {};\n    int common[64][64] = {};\n    for (int i = 0; i < n; ++i) {\n        deg[i] = __builtin_popcountll(g.a[i]);\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            int c = __builtin_popcountll(g.a[i] & g.a[j]);\n            common[i][j] = common[j][i] = c;\n        }\n    }\n\n    double m = 0; // edges\n    for (int i = 0; i < n; ++i) m += deg[i];\n    m *= 0.5;\n\n    double t = 0; // triangles\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) if ((g.a[i] >> j) & 1ULL) {\n            t += common[i][j];\n        }\n    }\n    t /= 3.0;\n\n    // triangles per vertex\n    double tv[64] = {};\n    for (int i = 0; i < n; ++i) {\n        double s = 0;\n        for (int j = 0; j < n; ++j) if ((g.a[i] >> j) & 1ULL) {\n            s += common[i][j];\n        }\n        tv[i] = s * 0.5;\n    }\n\n    // 4-cliques\n    double c4 = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) if ((g.a[i] >> j) & 1ULL) {\n            ULL mask = g.a[i] & g.a[j];\n            mask >>= (j + 1);\n            while (mask) {\n                int k = __builtin_ctzll(mask) + j + 1;\n                ULL m2 = g.a[i] & g.a[j] & g.a[k];\n                m2 >>= (k + 1);\n                c4 += __builtin_popcountll(m2);\n                mask &= mask - 1;\n            }\n        }\n    }\n\n    // sum of C(common,2)  -> 4-cycles with diagonal\n    double q = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            q += (double)common[i][j] * (common[i][j] - 1) * 0.5;\n        }\n    }\n\n    // paths of length 2\n    double p2 = 0;\n    for (int i = 0; i < n; ++i) {\n        p2 += (double)deg[i] * (deg[i] - 1) * 0.5;\n    }\n\n    double m2 = 0, m3 = 0;\n    for (int i = 0; i < n; ++i) {\n        double d = deg[i];\n        m2 += d * d;\n        m3 += d * d * d;\n    }\n\n    // A^2 matrix (as ints)\n    int A2[64][64] = {};\n    for (int i = 0; i < n; ++i) {\n        A2[i][i] = deg[i];\n        for (int j = i + 1; j < n; ++j) {\n            A2[i][j] = A2[j][i] = common[i][j];\n        }\n    }\n\n    // A^3 = A * A^2\n    int A3[64][64] = {};\n    for (int i = 0; i < n; ++i) {\n        for (int k = 0; k < n; ++k) if ((g.a[i] >> k) & 1ULL) {\n            for (int j = 0; j < n; ++j) {\n                A3[i][j] += A2[k][j];\n            }\n        }\n    }\n\n    double trace3 = 0;\n    for (int i = 0; i < n; ++i) trace3 += A3[i][i];\n\n    double w3[64] = {};\n    for (int i = 0; i < n; ++i) {\n        double s = 0;\n        for (int j = 0; j < n; ++j) s += A3[i][j];\n        w3[i] = s;\n    }\n\n    double w4[64] = {};\n    for (int i = 0; i < n; ++i) {\n        double s = 0;\n        for (int j = 0; j < n; ++j) s += (double)A2[i][j] * A2[i][j];\n        w4[i] = s;\n    }\n\n    double trace4 = 0;\n    for (int i = 0; i < n; ++i) trace4 += w4[i];\n\n    double darr[64], tvarr[64], w3arr[64], w4arr[64];\n    for (int i = 0; i < n; ++i) {\n        darr[i] = deg[i];\n        tvarr[i] = tv[i];\n        w3arr[i] = w3[i];\n        w4arr[i] = w4[i];\n    }\n    sort(darr, darr + n);\n    sort(tvarr, tvarr + n);\n    sort(w3arr, w3arr + n);\n    sort(w4arr, w4arr + n);\n\n    Feature f;\n    f.reserve(4 * n + 9);\n    f.push_back(m);\n    f.push_back(t);\n    f.push_back(c4);\n    f.push_back(q);\n    f.push_back(p2);\n    f.push_back(m2);\n    f.push_back(m3);\n    f.push_back(trace3);\n    f.push_back(trace4);\n    for (int i = 0; i < n; ++i) f.push_back(darr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(tvarr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(w3arr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(w4arr[i]);\n    return f;\n}\n\n// ------------------------------------------------------------\n// Noise generation (BSC + random permutation)\n// ------------------------------------------------------------\nGraph add_noise(const Graph &g, int n, double ep, mt19937_64 &gen) {\n    Graph h = g;\n    // apply permutation\n    vector<int> perm(n);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), gen);\n    Graph pg;\n    pg.clear(n);\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            int pi = perm[i];\n            int pj = perm[j];\n            bool has = (g.a[pi] >> pj) & 1ULL;\n            if (has) {\n                pg.a[i] |= (1ULL << j);\n                pg.a[j] |= (1ULL << i);\n            }\n        }\n    }\n    // BSC noise\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            if (uni(gen) < ep) {\n                if ((pg.a[i] >> j) & 1ULL) {\n                    pg.a[i] &= ~(1ULL << j);\n                    pg.a[j] &= ~(1ULL << i);\n                } else {\n                    pg.a[i] |= (1ULL << j);\n                    pg.a[j] |= (1ULL << i);\n                }\n            }\n        }\n    }\n    return pg;\n}\n\n// ------------------------------------------------------------\n// Nearest-neighbor decoder\n// ------------------------------------------------------------\nint predict(const Feature &f, const vector<Feature> &F, const vector<double> &w) {\n    int bestk = 0;\n    double best = 1e300;\n    int D = (int)f.size();\n    for (int k = 0; k < M; ++k) {\n        double d = 0;\n        for (int i = 0; i < D; ++i) {\n            double diff = f[i] - F[k][i];\n            d += diff * diff * w[i];\n        }\n        if (d < best) {\n            best = d;\n            bestk = k;\n        }\n    }\n    return bestk;\n}\n\n// ------------------------------------------------------------\n// Evaluate error count on a batch\n// ------------------------------------------------------------\nint evaluate_batch(const vector<Graph> &Gs, const vector<Feature> &F,\n                   const vector<double> &w, double ep, int batch, int n) {\n    int err = 0;\n    uniform_int_distribution<int> sdist(0, M - 1);\n    for (int b = 0; b < batch; ++b) {\n        int s = sdist(rng);\n        Graph h = add_noise(Gs[s], n, ep, rng);\n        Feature f = extract(h, n);\n        int pred = predict(f, F, w);\n        if (pred != s) ++err;\n    }\n    return err;\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> M >> eps)) return 0;\n\n    // Candidate N values\n    vector<int> Ncands = {12, 14, 18, 22};\n    int bestN = 18;\n    double bestScoreEst = 1e100;\n\n    // Quick selection of N\n    for (int n : Ncands) {\n        int l = n * (n - 1) / 2;\n        // init random codebook with spaced edge counts\n        vector<Graph> Gs(M);\n        vector<pair<int,int>> edges;\n        for (int i = 0; i < n; ++i)\n            for (int j = i + 1; j < n; ++j)\n                edges.emplace_back(i, j);\n        for (int k = 0; k < M; ++k) {\n            Gs[k].clear(n);\n            int want = (int)((k + 0.5) * (double)l / M);\n            want = min(want, l);\n            shuffle(edges.begin(), edges.end(), rng);\n            for (int e = 0; e < want; ++e) {\n                auto [u, v] = edges[e];\n                Gs[k].a[u] |= (1ULL << v);\n                Gs[k].a[v] |= (1ULL << u);\n            }\n        }\n        vector<Feature> F(M);\n        for (int k = 0; k < M; ++k) F[k] = extract(Gs[k], n);\n        int D = F[0].size();\n        // uniform weights for quick test\n        vector<double> w(D, 1.0);\n        int err = evaluate_batch(Gs, F, w, eps, 100, n);\n        double scoreEst = (double)err; // lower is better\n        if (scoreEst < bestScoreEst) {\n            bestScoreEst = scoreEst;\n            bestN = n;\n        }\n    }\n\n    N = bestN;\n    L = N * (N - 1) / 2;\n\n    // Initialize codebook for chosen N\n    vector<Graph> Gs(M);\n    vector<pair<int,int>> edges;\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            edges.emplace_back(i, j);\n\n    for (int k = 0; k < M; ++k) {\n        Gs[k].clear(N);\n        int want = (int)((k + 0.5) * (double)L / M);\n        want = min(want, L);\n        shuffle(edges.begin(), edges.end(), rng);\n        for (int e = 0; e < want; ++e) {\n            auto [u, v] = edges[e];\n            Gs[k].a[u] |= (1ULL << v);\n            Gs[k].a[v] |= (1ULL << u);\n        }\n    }\n\n    vector<Feature> F(M);\n    for (int k = 0; k < M; ++k) F[k] = extract(Gs[k], N);\n    int D = F[0].size();\n\n    // Compute data-driven weights by sampling noise\n    vector<double> w(D, 1.0);\n    {\n        vector<double> var(D, 0.0);\n        int S = 200;\n        uniform_int_distribution<int> sdist(0, M - 1);\n        for (int b = 0; b < S; ++b) {\n            int s = sdist(rng);\n            Graph h = add_noise(Gs[s], N, eps, rng);\n            Feature f = extract(h, N);\n            for (int i = 0; i < D; ++i) {\n                double diff = f[i] - F[s][i];\n                var[i] += diff * diff;\n            }\n        }\n        for (int i = 0; i < D; ++i) {\n            var[i] /= S;\n            w[i] = 1.0 / (var[i] + 1e-6);\n        }\n    }\n\n    // Simulated Annealing\n    int BATCH = 25;\n    int ITER = 3000;\n    int cur_obj = evaluate_batch(Gs, F, w, eps, BATCH, N);\n    uniform_int_distribution<int> kdist(0, M - 1);\n    uniform_int_distribution<int> vdist(0, N - 1);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    // Precompute pairs\n    vector<pair<int,int>> allEdges = edges;\n\n    for (int it = 0; it < ITER; ++it) {\n        double T = 1.0 * (ITER - it) / ITER;\n        if (T < 0.001) T = 0.001;\n\n        int k = kdist(rng);\n        int u = vdist(rng);\n        int v = vdist(rng);\n        if (u == v) continue;\n        if (u > v) swap(u, v);\n\n        bool had = (Gs[k].a[u] >> v) & 1ULL;\n        // flip\n        if (had) {\n            Gs[k].a[u] &= ~(1ULL << v);\n            Gs[k].a[v] &= ~(1ULL << u);\n        } else {\n            Gs[k].a[u] |= (1ULL << v);\n            Gs[k].a[v] |= (1ULL << u);\n        }\n\n        Feature oldF = F[k];\n        F[k] = extract(Gs[k], N);\n        int new_obj = evaluate_batch(Gs, F, w, eps, BATCH, N);\n\n        int delta = new_obj - cur_obj;\n        if (delta < 0 || prob(rng) < exp(-delta / T)) {\n            cur_obj = new_obj;\n        } else {\n            // revert\n            if (had) {\n                Gs[k].a[u] |= (1ULL << v);\n                Gs[k].a[v] |= (1ULL << u);\n            } else {\n                Gs[k].a[u] &= ~(1ULL << v);\n                Gs[k].a[v] &= ~(1ULL << u);\n            }\n            F[k] = oldF;\n        }\n    }\n\n    // Output graphs\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; ++k) {\n        string s;\n        s.reserve(L);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                s.push_back( (Gs[k].a[i] >> j) & 1ULL ? '1' : '0' );\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // Answer queries\n    for (int q = 0; q < 100; ++q) {\n        string hs;\n        cin >> hs;\n        Graph h;\n        h.clear(N);\n        int pos = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (hs[pos++] == '1') {\n                    h.a[i] |= (1ULL << j);\n                    h.a[j] |= (1ULL << i);\n                }\n            }\n        }\n        Feature f = extract(h, N);\n        int ans = predict(f, F, w);\n        cout << ans << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst int INF_INT = 1000000000;\nconst ll INF_LL = (1LL<<60);\n\nstruct SimpleHeap {\n    static const int MAXN = 10005;\n    pair<int,int> a[MAXN];\n    int n;\n    void clear(){ n=0; }\n    void push(pair<int,int> x){\n        int i=n++;\n        while(i>0){\n            int p=(i-1)>>1;\n            if(a[p].first <= x.first) break;\n            a[i]=a[p];\n            i=p;\n        }\n        a[i]=x;\n    }\n    pair<int,int> top() const { return a[0]; }\n    void pop(){\n        pair<int,int> x = a[--n];\n        int i=0;\n        while(true){\n            int l=(i<<1)|1;\n            if(l>=n) break;\n            int r=l+1, c=l;\n            if(r<n && a[r].first < a[l].first) c=r;\n            if(x.first <= a[c].first) break;\n            a[i]=a[c];\n            i=c;\n        }\n        a[i]=x;\n    }\n    bool empty() const { return n==0; }\n};\n\nint N, M, D, K;\nstruct Edge {int u, v, w;};\nvector<Edge> edges;\nvector<vector<tuple<int,int,int>>> adj;\nvector<int> rem_stamp;\nint cur_stamp = 1;\n\ninline pair<int,ll> dijkstra(int s, int stamp, vector<int>& dist, SimpleHeap& pq){\n    fill(dist.begin(), dist.end(), INF_INT);\n    dist[s] = 0;\n    pq.clear();\n    pq.push({0, s});\n    ll sum = 0;\n    int visited = 0;\n    while(!pq.empty()){\n        auto [d,u] = pq.top(); pq.pop();\n        if(d != dist[u]) continue;\n        visited++;\n        sum += d;\n        for(const auto& [v,w,eid] : adj[u]){\n            if(rem_stamp[eid] == stamp) continue;\n            if(dist[v] > d + w){\n                dist[v] = d + w;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {visited, sum};\n}\n\n// Evaluate proxy score of a day. exact=false -> INF if disconnected. exact=true -> add penalty.\nll eval_day(int day, int out_eid, int in_eid, const vector<int>& samples,\n            const vector<vector<int>>& day_edges,\n            vector<int>& dist, SimpleHeap& pq, bool exact=false){\n    int stamp = cur_stamp++;\n    for(int eid : day_edges[day]){\n        if(eid == out_eid) continue;\n        rem_stamp[eid] = stamp;\n    }\n    if(in_eid != -1) rem_stamp[in_eid] = stamp;\n    ll total = 0;\n    for(int s : samples){\n        auto [vis, sum] = dijkstra(s, stamp, dist, pq);\n        if(vis < N){\n            if(!exact) return INF_LL;\n            total += sum + (ll)(N - vis) * INF_INT;\n        } else {\n            total += sum;\n        }\n    }\n    return total;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    cin >> N >> M >> D >> K;\n    edges.resize(M);\n    adj.assign(N, {});\n    vector<int> xs(N), ys(N);\n    for(int i=0;i<M;i++){\n        int u,v,w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u,v,w};\n        adj[u].push_back({v,w,i});\n        adj[v].push_back({u,w,i});\n    }\n    for(int i=0;i<N;i++) cin >> xs[i] >> ys[i];\n\n    rem_stamp.assign(M, 0);\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // ----- approximate edge importance (shortest path tree usage) -----\n    vector<int> imp(M, 0);\n    vector<int> dist0(N);\n    vector<int> parent(N);\n    SimpleHeap pq0;\n    for(int it=0; it<100; it++){\n        int s = rng() % N;\n        fill(dist0.begin(), dist0.end(), INF_INT);\n        dist0[s] = 0;\n        fill(parent.begin(), parent.end(), -1);\n        pq0.clear();\n        pq0.push({0, s});\n        while(!pq0.empty()){\n            auto [d,u] = pq0.top(); pq0.pop();\n            if(d != dist0[u]) continue;\n            for(const auto& [v,w,eid] : adj[u]){\n                if(dist0[v] > d + w){\n                    dist0[v] = d + w;\n                    parent[v] = eid;\n                    pq0.push({dist0[v], v});\n                }\n            }\n        }\n        for(int v=0; v<N; v++){\n            if(v != s && parent[v] != -1) imp[parent[v]]++;\n        }\n    }\n\n    // ----- greedy initialization (balance importance) -----\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        if(imp[a] != imp[b]) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    vector<int> edge_day(M);\n    vector<vector<int>> day_edges(D);\n    vector<ll> day_imp_sum(D, 0);\n    vector<int> day_load(D, 0);\n    for(int eid : order){\n        int best_d = -1;\n        ll best_val = INF_LL;\n        for(int d=0; d<D; d++){\n            if(day_load[d] >= K) continue;\n            if(day_imp_sum[d] < best_val){\n                best_val = day_imp_sum[d];\n                best_d = d;\n            }\n        }\n        if(best_d == -1){\n            for(int d=0; d<D; d++) if(day_load[d] < K){ best_d = d; break; }\n        }\n        edge_day[eid] = best_d;\n        day_edges[best_d].push_back(eid);\n        day_load[best_d]++;\n        day_imp_sum[best_d] += imp[eid];\n    }\n\n    // ----- ensure every day is connected -----\n    vector<int> dist(N);\n    SimpleHeap pq;\n    auto is_conn = [&](int d)->bool{\n        static vector<int> dummy = {0};\n        return eval_day(d, -1, -1, dummy, day_edges, dist, pq) < INF_LL;\n    };\n\n    for(int d=0; d<D; d++){\n        int attempts = 0;\n        while(!is_conn(d)){\n            int d2 = rng() % D;\n            if(d2 == d) continue;\n            if(day_edges[d].empty() || day_edges[d2].empty()) continue;\n            int i1 = rng() % (int)day_edges[d].size();\n            int i2 = rng() % (int)day_edges[d2].size();\n            int e1 = day_edges[d][i1];\n            int e2 = day_edges[d2][i2];\n            swap(day_edges[d][i1], day_edges[d2][i2]);\n            edge_day[e1] = d2;\n            edge_day[e2] = d;\n            if(is_conn(d) && is_conn(d2)){\n                // keep swap\n            } else {\n                swap(day_edges[d][i1], day_edges[d2][i2]);\n                edge_day[e1] = d;\n                edge_day[e2] = d2;\n            }\n            if(++attempts > 20000) break;\n        }\n    }\n\n    // ----- stratified sample sources -----\n    vector<pair<int,int>> nodes_by_x;\n    for(int i=0;i<N;i++) nodes_by_x.push_back({xs[i], i});\n    sort(nodes_by_x.begin(), nodes_by_x.end());\n    const int NS = 20;\n    vector<int> samples;\n    for(int i=0;i<NS;i++){\n        int L = i * N / NS;\n        int R = (i+1) * N / NS;\n        if(L >= R) continue;\n        int idx = L + (int)(rng() % (R - L));\n        samples.push_back(nodes_by_x[idx].second);\n    }\n    while((int)samples.size() < NS) samples.push_back(rng() % N);\n\n    // ----- compute initial proxy scores -----\n    vector<ll> day_score(D);\n    auto recompute_day = [&](int d){\n        day_score[d] = eval_day(d, -1, -1, samples, day_edges, dist, pq);\n    };\n    for(int d=0; d<D; d++) recompute_day(d);\n    ll cur_total = 0;\n    for(ll v : day_score) cur_total += v;\n\n    vector<int> best_edge_day = edge_day;\n    vector<vector<int>> best_day_edges = day_edges;\n    ll best_total = cur_total;\n\n    const double TIME_LIMIT = 5.4;\n    int stagnant = 0;\n\n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if(elapsed > TIME_LIMIT) break;\n\n        int d1 = rng() % D;\n        int d2 = rng() % D;\n        if(d1 == d2) continue;\n        if(day_edges[d1].empty() || day_edges[d2].empty()) continue;\n        int i1 = rng() % (int)day_edges[d1].size();\n        int i2 = rng() % (int)day_edges[d2].size();\n        int e1 = day_edges[d1][i1];\n        int e2 = day_edges[d2][i2];\n\n        ll s1 = eval_day(d1, e1, e2, samples, day_edges, dist, pq);\n        if(s1 >= INF_LL) continue;\n        ll s2 = eval_day(d2, e2, e1, samples, day_edges, dist, pq);\n        if(s2 >= INF_LL) continue;\n\n        ll new_total = cur_total - day_score[d1] - day_score[d2] + s1 + s2;\n        if(new_total < cur_total){\n            edge_day[e1] = d2;\n            edge_day[e2] = d1;\n            day_edges[d1][i1] = e2;\n            day_edges[d2][i2] = e1;\n            day_score[d1] = s1;\n            day_score[d2] = s2;\n            cur_total = new_total;\n            stagnant = 0;\n            if(cur_total < best_total){\n                best_total = cur_total;\n                best_edge_day = edge_day;\n                best_day_edges = day_edges;\n            }\n        } else {\n            stagnant++;\n            if(stagnant > 300){\n                // perturb from best and continue\n                bool ok = false;\n                for(int attempt=0; attempt<10; attempt++){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                    int num_swaps = 10 + (int)(rng() % 10);\n                    for(int k=0; k<num_swaps; k++){\n                        int a = rng() % D;\n                        int b = rng() % D;\n                        if(a == b) continue;\n                        if(day_edges[a].empty() || day_edges[b].empty()) continue;\n                        int ai = rng() % (int)day_edges[a].size();\n                        int bi = rng() % (int)day_edges[b].size();\n                        int ae = day_edges[a][ai];\n                        int be = day_edges[b][bi];\n                        swap(day_edges[a][ai], day_edges[b][bi]);\n                        edge_day[ae] = b;\n                        edge_day[be] = a;\n                    }\n                    bool all_conn = true;\n                    for(int d=0; d<D; d++){\n                        if(!is_conn(d)){\n                            all_conn = false;\n                            break;\n                        }\n                    }\n                    if(all_conn){\n                        ok = true;\n                        break;\n                    }\n                }\n                if(!ok){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                }\n                for(int d=0; d<D; d++) recompute_day(d);\n                cur_total = 0;\n                for(ll v : day_score) cur_total += v;\n                stagnant = 0;\n                if(cur_total < best_total){\n                    best_total = cur_total;\n                    best_edge_day = edge_day;\n                    best_day_edges = day_edges;\n                }\n            }\n        }\n    }\n\n    for(int i=0;i<M;i++){\n        if(i) cout << ' ';\n        cout << best_edge_day[i] + 1;\n    }\n    cout << '\\n';\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nvector<string> F[2], R[2];\n\n// bitset for one z-layer (x*D + y)\nusing BS = bitset<196>;\nBS validMask[2][16];\nBS occ[2][16];\nbool needF[2][16][16];\nbool needR[2][16][16];\n\n// rect_mask[dx][dy][x][y]\nBS rectMask[16][16][16][16];\n\nstruct SharedBlock {\n    int id;\n    int x1, y1, z1, dx1, dy1, dz1;\n    int x2, y2, z2, dx2, dy2, dz2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto tStart = chrono::steady_clock::now();\n    \n    // ---------- input ----------\n    if (!(cin >> D)) return 0;\n    for (int i = 0; i < 2; ++i) {\n        F[i].resize(D);\n        R[i].resize(D);\n        for (int z = 0; z < D; ++z) cin >> F[i][z];\n        for (int z = 0; z < D; ++z) cin >> R[i][z];\n    }\n    \n    // ---------- precompute valid masks and needs ----------\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            for (int x = 0; x < D; ++x) {\n                needF[i][z][x] = (F[i][z][x] == '1');\n                for (int y = 0; y < D; ++y) {\n                    bool ok = (F[i][z][x] == '1' && R[i][z][y] == '1');\n                    if (ok) validMask[i][z].set(x * D + y);\n                    needR[i][z][y] = (R[i][z][y] == '1');\n                }\n            }\n        }\n    }\n    \n    // ---------- precompute rectangle bitsets ----------\n    for (int dx = 1; dx <= D; ++dx)\n        for (int dy = 1; dy <= D; ++dy)\n            for (int x = 0; x + dx <= D; ++x)\n                for (int y = 0; y + dy <= D; ++y) {\n                    BS m;\n                    for (int i = x; i < x + dx; ++i)\n                        for (int j = y; j < y + dy; ++j)\n                            m.set(i * D + j);\n                    rectMask[dx][dy][x][y] = m;\n                }\n    \n    // ---------- canonical box sizes ----------\n    vector<array<int,3>> canSizes;\n    for (int a = 1; a <= D; ++a)\n        for (int b = a; b <= D; ++b)\n            for (int c = b; c <= D; ++c)\n                if (a * b * c >= 2)\n                    canSizes.push_back({a, b, c});\n    sort(canSizes.begin(), canSizes.end(),\n         [](const auto& p, const auto& q) {\n             return p[0]*p[1]*p[2] > q[0]*q[1]*q[2];\n         });\n    \n    // permutations for each canonical size\n    vector<vector<array<int,3>>> perms(canSizes.size());\n    for (size_t i = 0; i < canSizes.size(); ++i) {\n        int d[3] = {canSizes[i][0], canSizes[i][1], canSizes[i][2]};\n        sort(d, d + 3);\n        do {\n            perms[i].push_back({d[0], d[1], d[2]});\n        } while (next_permutation(d, d + 3));\n        sort(perms[i].begin(), perms[i].end());\n        perms[i].erase(unique(perms[i].begin(), perms[i].end()), perms[i].end());\n    }\n    \n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    vector<SharedBlock> shared;\n    int nextId = 1;\n    const double TIME_LIMIT = 4.8;\n    \n    // ---------- main greedy loop ----------\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - tStart).count();\n        if (elapsed > TIME_LIMIT) break;\n        \n        int bestTotal = 0;\n        int bestVol = 0;\n        int bx1=0, by1=0, bz1=0, bdx1=0, bdy1=0, bdz1=0;\n        int bx2=0, by2=0, bz2=0, bdx2=0, bdy2=0, bdz2=0;\n        \n        int limitSizes = min((int)canSizes.size(), 40);\n        for (int si = 0; si < limitSizes; ++si) {\n            int a = canSizes[si][0], b = canSizes[si][1], c = canSizes[si][2];\n            int vol = a * b * c;\n            const auto& plist = perms[si];\n            \n            for (auto [dx, dy, dz] : plist) {\n                if (dx > D || dy > D || dz > D) continue;\n                int maxX = D - dx;\n                int maxY = D - dy;\n                int maxZ = D - dz;\n                for (int x1 = 0; x1 <= maxX; ++x1) {\n                    for (int y1 = 0; y1 <= maxY; ++y1) {\n                        const BS& m1base = rectMask[dx][dy][x1][y1];\n                        for (int z1 = 0; z1 <= maxZ; ++z1) {\n                            // fit in obj1 ?\n                            bool ok1 = true;\n                            for (int k = 0; k < dz; ++k) {\n                                if ((occ[0][z1 + k] & m1base).any()) { ok1 = false; break; }\n                                if ((validMask[0][z1 + k] & m1base) != m1base) { ok1 = false; break; }\n                            }\n                            if (!ok1) continue;\n                            \n                            int ben1 = 0;\n                            for (int k = 0; k < dz; ++k) {\n                                for (int i = 0; i < dx; ++i) if (needF[0][z1 + k][x1 + i]) ++ben1;\n                                for (int j = 0; j < dy; ++j) if (needR[0][z1 + k][y1 + j]) ++ben1;\n                            }\n                            if (ben1 == 0) continue;\n                            \n                            // sample obj2\n                            int attempts = 0;\n                            int found = 0;\n                            while (attempts < 150 && found < 25) {\n                                ++attempts;\n                                int pi = (int)(rng() % plist.size());\n                                int dx2 = plist[pi][0];\n                                int dy2 = plist[pi][1];\n                                int dz2 = plist[pi][2];\n                                if (dx2 > D || dy2 > D || dz2 > D) continue;\n                                int x2 = (int)(rng() % (D - dx2 + 1));\n                                int y2 = (int)(rng() % (D - dy2 + 1));\n                                int z2 = (int)(rng() % (D - dz2 + 1));\n                                const BS& m2base = rectMask[dx2][dy2][x2][y2];\n                                bool ok2 = true;\n                                for (int k = 0; k < dz2; ++k) {\n                                    if ((occ[1][z2 + k] & m2base).any()) { ok2 = false; break; }\n                                    if ((validMask[1][z2 + k] & m2base) != m2base) { ok2 = false; break; }\n                                }\n                                if (!ok2) continue;\n                                ++found;\n                                \n                                int ben2 = 0;\n                                for (int k = 0; k < dz2; ++k) {\n                                    for (int i = 0; i < dx2; ++i) if (needF[1][z2 + k][x2 + i]) ++ben2;\n                                    for (int j = 0; j < dy2; ++j) if (needR[1][z2 + k][y2 + j]) ++ben2;\n                                }\n                                if (ben2 == 0) continue;\n                                \n                                int total = ben1 + ben2;\n                                if (total > bestTotal || (total == bestTotal && vol > bestVol)) {\n                                    bestTotal = total;\n                                    bestVol = vol;\n                                    bx1 = x1; by1 = y1; bz1 = z1; bdx1 = dx; bdy1 = dy; bdz1 = dz;\n                                    bx2 = x2; by2 = y2; bz2 = z2; bdx2 = dx2; bdy2 = dy2; bdz2 = dz2;\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        \n        if (bestTotal > 0) {\n            // place shared block\n            int id = nextId++;\n            for (int k = 0; k < bdz1; ++k) {\n                const BS& m = rectMask[bdx1][bdy1][bx1][by1];\n                occ[0][bz1 + k] |= m;\n                for (int i = 0; i < bdx1; ++i) needF[0][bz1 + k][bx1 + i] = false;\n                for (int j = 0; j < bdy1; ++j) needR[0][bz1 + k][by1 + j] = false;\n            }\n            for (int k = 0; k < bdz2; ++k) {\n                const BS& m = rectMask[bdx2][bdy2][bx2][by2];\n                occ[1][bz2 + k] |= m;\n                for (int i = 0; i < bdx2; ++i) needF[1][bz2 + k][bx2 + i] = false;\n                for (int j = 0; j < bdy2; ++j) needR[1][bz2 + k][by2 + j] = false;\n            }\n            shared.push_back({id, bx1, by1, bz1, bdx1, bdy1, bdz1,\n                              bx2, by2, bz2, bdx2, bdy2, bdz2});\n        } else {\n            break;\n        }\n    }\n    \n    // ---------- fill remaining needs with unit cubes ----------\n    vector<int> b0(D * D * D, 0), b1(D * D * D, 0);\n    int curId = nextId;\n    \n    auto placeUnique = [&](int idx, vector<int>& arr) {\n        for (int z = 0; z < D; ++z) {\n            for (int x = 0; x < D; ++x) {\n                if (needF[idx][z][x]) {\n                    for (int y = 0; y < D; ++y) {\n                        int cell = x * D + y;\n                        if (validMask[idx][z].test(cell) && !occ[idx][z].test(cell)) {\n                            occ[idx][z].set(cell);\n                            arr[x * D * D + y * D + z] = curId++;\n                            needF[idx][z][x] = false;\n                            needR[idx][z][y] = false;\n                            break;\n                        }\n                    }\n                }\n            }\n            for (int y = 0; y < D; ++y) {\n                if (needR[idx][z][y]) {\n                    for (int x = 0; x < D; ++x) {\n                        int cell = x * D + y;\n                        if (validMask[idx][z].test(cell) && !occ[idx][z].test(cell)) {\n                            occ[idx][z].set(cell);\n                            arr[x * D * D + y * D + z] = curId++;\n                            needF[idx][z][x] = false;\n                            needR[idx][z][y] = false;\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    };\n    \n    placeUnique(0, b0);\n    placeUnique(1, b1);\n    \n    // write shared blocks into arrays\n    for (const auto& bl : shared) {\n        for (int k = 0; k < bl.dz1; ++k)\n            for (int i = 0; i < bl.dx1; ++i)\n                for (int j = 0; j < bl.dy1; ++j)\n                    b0[(bl.x1 + i) * D * D + (bl.y1 + j) * D + (bl.z1 + k)] = bl.id;\n        for (int k = 0; k < bl.dz2; ++k)\n            for (int i = 0; i < bl.dx2; ++i)\n                for (int j = 0; j < bl.dy2; ++j)\n                    b1[(bl.x2 + i) * D * D + (bl.y2 + j) * D + (bl.z2 + k)] = bl.id;\n    }\n    \n    int n = curId - 1;\n    cout << n << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b0[i];\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b1[i];\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = (1LL << 60);\n\nint N, M, K;\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nvector<Edge> edges;\nvector<Edge> edges_sorted;\nvector<vector<pair<int,int>>> adj;          // (to, edge_id)\nvector<vector<int>> need;                   // [vertex][resident]\nvector<vector<pair<int,int>>> res_sorted;   // [resident] -> (need, vertex) sorted\nvector<vector<int>> edge_id_mat;\n\n// ---------- integer sqrt : ceil(sqrt(x)) ----------\nint isqrt_ceil(long long x) {\n    if (x <= 0) return 0;\n    int r = (int)std::sqrt((double)x);\n    while (1LL * r * r < x) ++r;\n    while (1LL * r * r > x) --r;\n    return (1LL * r * r == x) ? r : r + 1;\n}\n\n// ---------- DSU (static size, no allocation) ----------\nstruct DSU {\n    int p[100];\n    int rnk[100];\n    void init(int n) {\n        for (int i = 0; i < n; ++i) {\n            p[i] = i;\n            rnk[i] = 0;\n        }\n    }\n    int find(int x) {\n        return p[x] == x ? x : p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a, b);\n        p[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n};\n\n// ---------- MST cost for a given active set ----------\nlong long calc_mst(const vector<char>& inV, vector<pair<int,int>>& te) {\n    te.clear();\n    int nV = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) ++nV;\n    if (nV == 0) return INF;\n    if (nV == 1) return 0;\n\n    DSU dsu;\n    dsu.init(N);\n    long long cost = 0;\n    int used = 0;\n    for (const auto& e : edges_sorted) {\n        if (!inV[e.u] || !inV[e.v]) continue;\n        if (dsu.unite(e.u, e.v)) {\n            te.emplace_back(e.u, e.v);\n            cost += e.w;\n            if (++used == nV - 1) break;\n        }\n    }\n    if (used != nV - 1) return INF;\n    return cost;\n}\n\n// ---------- Power cost for a given active set ----------\nlong long calc_power(const vector<char>& inV, vector<int>& P) {\n    P.assign(N, 0);\n    for (int k = 0; k < K; ++k) {\n        int best_v = -1;\n        int best_need = INT_MAX;\n        for (auto& [nd, v] : res_sorted[k]) {\n            if (inV[v]) {\n                best_v = v;\n                best_need = nd;\n                break;\n            }\n        }\n        if (best_v == -1 || best_need > 5000) return INF;\n        if (best_need > P[best_v]) P[best_v] = best_need;\n    }\n    long long cost = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) cost += 1LL * P[i] * P[i];\n    return cost;\n}\n\n// ---------- helpers for local search ----------\nvector<int> get_leaves(const vector<pair<int,int>>& te, const vector<char>& inV) {\n    vector<int> deg(N, 0);\n    for (auto& [u, v] : te) {\n        ++deg[u]; ++deg[v];\n    }\n    vector<int> res;\n    for (int i = 1; i < N; ++i)\n        if (inV[i] && deg[i] == 1) res.push_back(i);\n    return res;\n}\n\nvector<int> get_candidates(const vector<char>& inV) {\n    vector<char> seen(N, 0);\n    vector<int> res;\n    for (int i = 0; i < N; ++i) if (inV[i]) {\n        for (auto& [to, id] : adj[i]) {\n            if (!inV[to] && !seen[to]) {\n                seen[to] = 1;\n                res.push_back(to);\n            }\n        }\n    }\n    return res;\n}\n\n// ---------- local search (add / remove / swap) ----------\nvoid local_search(vector<char>& inV, vector<pair<int,int>>& te, vector<int>& P, long long& total_cost) {\n    while (true) {\n        long long best_cost = total_cost;\n        vector<char> best_inV = inV;\n        vector<pair<int,int>> best_te = te;\n        vector<int> best_P = P;\n        bool improved = false;\n\n        // --- remove leaf ---\n        vector<int> leaves = get_leaves(te, inV);\n        for (int u : leaves) {\n            vector<char> inV2 = inV;\n            inV2[u] = 0;\n            vector<pair<int,int>> te2;\n            long long ec = calc_mst(inV2, te2);\n            if (ec >= INF) continue;\n            vector<int> P2;\n            long long pc = calc_power(inV2, P2);\n            if (pc >= INF) continue;\n            long long tot = ec + pc;\n            if (tot < best_cost) {\n                best_cost = tot;\n                best_inV = inV2;\n                best_te = te2;\n                best_P = P2;\n                improved = true;\n            }\n        }\n\n        // --- add neighbour ---\n        vector<int> cands = get_candidates(inV);\n        for (int v : cands) {\n            vector<char> inV2 = inV;\n            inV2[v] = 1;\n            vector<pair<int,int>> te2;\n            long long ec = calc_mst(inV2, te2);\n            if (ec >= INF) continue;\n            vector<int> P2;\n            long long pc = calc_power(inV2, P2);\n            if (pc >= INF) continue;\n            long long tot = ec + pc;\n            if (tot < best_cost) {\n                best_cost = tot;\n                best_inV = inV2;\n                best_te = te2;\n                best_P = P2;\n                improved = true;\n            }\n        }\n\n        if (improved) {\n            inV = best_inV;\n            te = best_te;\n            P = best_P;\n            total_cost = best_cost;\n            continue;\n        }\n\n        // --- swap leaf <-> outside vertex ---\n        vector<int> non_active;\n        for (int i = 0; i < N; ++i) if (!inV[i]) non_active.push_back(i);\n        for (int u : leaves) {\n            for (int v : non_active) {\n                if (v == u) continue;\n                vector<char> inV2 = inV;\n                inV2[u] = 0;\n                inV2[v] = 1;\n                vector<pair<int,int>> te2;\n                long long ec = calc_mst(inV2, te2);\n                if (ec >= INF) continue;\n                vector<int> P2;\n                long long pc = calc_power(inV2, P2);\n                if (pc >= INF) continue;\n                long long tot = ec + pc;\n                if (tot < best_cost) {\n                    best_cost = tot;\n                    best_inV = inV2;\n                    best_te = te2;\n                    best_P = P2;\n                    improved = true;\n                }\n            }\n        }\n\n        if (improved) {\n            inV = best_inV;\n            te = best_te;\n            P = best_P;\n            total_cost = best_cost;\n        } else {\n            break;\n        }\n    }\n}\n\n// ---------- try an initial state and update global best ----------\nlong long global_best_cost = INF;\nvector<char> global_best_inV;\nvector<pair<int,int>> global_best_te;\nvector<int> global_best_P;\n\nvoid try_state(vector<char> init_inV) {\n    vector<pair<int,int>> te;\n    long long ec = calc_mst(init_inV, te);\n    if (ec >= INF) return;\n    vector<int> P;\n    long long pc = calc_power(init_inV, P);\n    if (pc >= INF) return;\n    long long tot = ec + pc;\n    local_search(init_inV, te, P, tot);\n    if (tot < global_best_cost) {\n        global_best_cost = tot;\n        global_best_inV = init_inV;\n        global_best_te = te;\n        global_best_P = P;\n    }\n}\n\n// ---------- random restart generator ----------\nvector<char> random_init(mt19937& rng) {\n    vector<char> inV(N, 1);\n    int steps = (int)(rng() % (N / 2 + 1)) + 1;\n    for (int s = 0; s < steps; ++s) {\n        vector<pair<int,int>> te;\n        if (calc_mst(inV, te) >= INF) break;\n        vector<int> leaves = get_leaves(te, inV);\n        if (leaves.empty()) break;\n        uniform_int_distribution<int> dist(0, (int)leaves.size() - 1);\n        inV[leaves[dist(rng)]] = 0;\n    }\n    vector<pair<int,int>> te;\n    if (calc_mst(inV, te) >= INF) {\n        inV.assign(N, 1);\n    }\n    return inV;\n}\n\n// ============================================================\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    clock_t start_clock = clock();\n    const double TL = 1.9;          // seconds\n\n    cin >> N >> M >> K;\n    vector<long long> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    edges.resize(M);\n    adj.assign(N, {});\n    edge_id_mat.assign(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w, j};\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n        edge_id_mat[u][v] = edge_id_mat[v][u] = j;\n    }\n\n    vector<long long> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // precompute need[i][k]\n    need.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            long long dx = xs[i] - a[k];\n            long long dy = ys[i] - b[k];\n            long long sq = dx * dx + dy * dy;\n            need[i][k] = isqrt_ceil(sq);\n        }\n    }\n\n    // precompute sorted vertex lists per resident\n    res_sorted.assign(K, {});\n    for (int k = 0; k < K; ++k) {\n        res_sorted[k].resize(N);\n        for (int i = 0; i < N; ++i) res_sorted[k][i] = {need[i][k], i};\n        sort(res_sorted[k].begin(), res_sorted[k].end());\n    }\n\n    edges_sorted = edges;\n    sort(edges_sorted.begin(), edges_sorted.end(),\n         [](const Edge& a, const Edge& b){ return a.w < b.w; });\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // 1) deterministic start from all vertices\n    {\n        vector<char> allV(N, 1);\n        try_state(allV);\n    }\n\n    // 2) random restarts until time limit\n    int restart = 0;\n    while ((double)(clock() - start_clock) / CLOCKS_PER_SEC < TL) {\n        ++restart;\n        vector<char> init = random_init(rng);\n        try_state(init);\n    }\n\n    // ---------- output ----------\n    vector<int> P_out(N, 0);\n    for (int i = 0; i < N; ++i)\n        if (global_best_inV[i]) P_out[i] = global_best_P[i];\n\n    vector<int> B(M, 0);\n    for (auto& [u, v] : global_best_te) {\n        B[edge_id_mat[u][v]] = 1;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << P_out[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << B[j];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    const int N = 30;\n    const int TOTAL = N * (N + 1) / 2;          // 465\n    \n    /* ---------- read input ---------- */\n    vector<int> val(TOTAL);                     // value in each cell\n    vector<int> pos(TOTAL);                     // position (id) of each value\n    auto ID = [&](int x, int y) { return x * (x + 1) / 2 + y; };\n    \n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v; \n            cin >> v;\n            int id = ID(x, y);\n            val[id] = v;\n            pos[v] = id;\n        }\n    }\n    \n    /* ---------- target layer of each value ---------- */\n    vector<int> target(TOTAL);\n    for (int x = 0; x < N; ++x) {\n        int L = x * (x + 1) / 2;\n        int R = (x + 1) * (x + 2) / 2;\n        for (int v = L; v < R; ++v) target[v] = x;\n    }\n    \n    /* ---------- coordinates and adjacency ---------- */\n    vector<pair<int,int>> coord(TOTAL);\n    for (int x = 0; x < N; ++x)\n        for (int y = 0; y <= x; ++y)\n            coord[ID(x, y)] = {x, y};\n    \n    vector<vector<int>> adj(TOTAL);\n    const int dx[6] = {-1,-1,0,0,1,1};\n    const int dy[6] = {-1,0,-1,1,0,1};\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int u = ID(x, y);\n            for (int dir = 0; dir < 6; ++dir) {\n                int nx = x + dx[dir];\n                int ny = y + dy[dir];\n                if (nx < 0 || nx >= N) continue;\n                if (ny < 0 || ny > nx) continue;\n                int v = ID(nx, ny);\n                adj[u].push_back(v);\n            }\n        }\n    }\n    \n    /* ---------- algorithm ---------- */\n    vector<char> fixed(TOTAL, 0);\n    struct Op { int x1, y1, x2, y2; };\n    vector<Op> ops;\n    ops.reserve(10000);\n    \n    static int seen[TOTAL];\n    static int src[TOTAL];\n    static int parent_arr[TOTAL];\n    int bfs_id = 0;\n    \n    for (int x = 0; x < N; ++x) {\n        vector<int> remaining;\n        remaining.reserve(x + 1);\n        for (int y = 0; y <= x; ++y) remaining.push_back(ID(x, y));\n        \n        while (!remaining.empty()) {\n            ++bfs_id;\n            queue<int> q;\n            for (int s : remaining) {\n                seen[s] = bfs_id;\n                src[s] = s;\n                parent_arr[s] = -1;\n                q.push(s);\n            }\n            \n            int found_ball = -1;\n            int found_src  = -1;\n            while (!q.empty() && found_ball == -1) {\n                int u = q.front(); q.pop();\n                if (target[val[u]] == x) {\n                    found_ball = u;\n                    found_src  = src[u];\n                    break;\n                }\n                for (int v : adj[u]) {\n                    if (fixed[v]) continue;\n                    if (seen[v] == bfs_id) continue;\n                    seen[v] = bfs_id;\n                    src[v] = src[u];\n                    parent_arr[v] = u;\n                    q.push(v);\n                }\n            }\n            \n            // reconstruct path from found_src to found_ball\n            vector<int> path;\n            int cur = found_ball;\n            while (cur != -1) {\n                path.push_back(cur);\n                if (cur == found_src) break;\n                cur = parent_arr[cur];\n            }\n            reverse(path.begin(), path.end());\n            \n            // rotate the ball along the path\n            for (int i = (int)path.size() - 1; i >= 1; --i) {\n                int a = path[i - 1];\n                int b = path[i];\n                auto [x1, y1] = coord[a];\n                auto [x2, y2] = coord[b];\n                ops.push_back({x1, y1, x2, y2});\n                int va = val[a];\n                int vb = val[b];\n                swap(val[a], val[b]);\n                pos[va] = b;\n                pos[vb] = a;\n            }\n            \n            fixed[found_src] = 1;\n            vector<int> nxt;\n            nxt.reserve(remaining.size() - 1);\n            for (int idc : remaining)\n                if (idc != found_src) nxt.push_back(idc);\n            remaining.swap(nxt);\n        }\n    }\n    \n    /* ---------- output ---------- */\n    cout << ops.size() << '\\n';\n    for (auto &op : ops) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c; cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    int si = 0;\n    int sj = (D - 1) / 2;               // entrance\n\n    /*--- BFS distances from entrance (obstacles only) ---*/\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n    dist[si][sj] = 0;\n    q.push({si, sj});\n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obstacle[ni][nj]) continue;\n            if (dist[ni][nj] != -1) continue;\n            dist[ni][nj] = dist[i][j] + 1;\n            q.push({ni, nj});\n        }\n    }\n\n    /*--- collect storage cells, sort by (dist, i, j) ---*/\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            if (!(i == si && j == sj) && !obstacle[i][j])\n                cells.push_back({i, j});\n\n    int M = (int)cells.size();\n    sort(cells.begin(), cells.end(),\n        [&](const pair<int,int>& a, const pair<int,int>& b) {\n            if (dist[a.first][a.second] != dist[b.first][b.second])\n                return dist[a.first][a.second] < dist[b.first][b.second];\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n\n    vector<vector<int>> idx(D, vector<int>(D, -1));\n    for (int k = 0; k < M; ++k) idx[cells[k].first][cells[k].second] = k;\n\n    int max_dist = 0;\n    for (auto &c : cells) max_dist = max(max_dist, dist[c.first][c.second]);\n\n    vector<int> cap(max_dist + 1, 0);\n    for (auto &c : cells) ++cap[dist[c.first][c.second]];\n\n    vector<int> layer_start(max_dist + 2, 0);          // layer_start[d] = first index of layer d\n    for (int d = 1; d <= max_dist; ++d) layer_start[d + 1] = layer_start[d] + cap[d];\n\n    vector<int> ideal_layer(M);\n    for (int t = 0; t < M; ++t) {\n        for (int d = 1; d <= max_dist; ++d) {\n            if (layer_start[d] <= t && t < layer_start[d + 1]) {\n                ideal_layer[t] = d;\n                break;\n            }\n        }\n    }\n\n    /*--- state for placement ---*/\n    vector<vector<bool>> filled(D, vector<bool>(D, false));\n    vector<vector<int>>  label_at(D, vector<int>(D, -1));\n    vector<int> rem_cap = cap;\n    vector<int> rem_labels = cap;\n\n    auto traversable = [&](int i, int j) -> bool {\n        if (i == si && j == sj) return true;\n        if (i < 0 || i >= D || j < 0 || j >= D) return false;\n        return !obstacle[i][j] && !filled[i][j];\n    };\n\n    /*--- online placement ---*/\n    for (int step = 0; step < M; ++step) {\n        int t; cin >> t;\n        int d_ideal = ideal_layer[t];\n        --rem_labels[d_ideal];\n\n        /* find articulation points of the current empty graph */\n        int disc[9][9];\n        int low[9][9];\n        bool ap[9][9] = {};\n        bool vis[9][9] = {};\n        int timer = 0;\n        function<void(int,int,int,int)> dfs = [&](int i, int j, int pi, int pj) {\n            vis[i][j] = true;\n            disc[i][j] = low[i][j] = ++timer;\n            int child_cnt = 0;\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                if (!traversable(ni, nj)) continue;\n                if (ni == pi && nj == pj) continue;\n                if (!vis[ni][nj]) {\n                    ++child_cnt;\n                    dfs(ni, nj, i, j);\n                    low[i][j] = min(low[i][j], low[ni][nj]);\n                    if (pi != -1 && low[ni][nj] >= disc[i][j]) ap[i][j] = true;\n                } else {\n                    low[i][j] = min(low[i][j], disc[ni][nj]);\n                }\n            }\n            if (pi == -1 && child_cnt > 1) ap[i][j] = true;\n        };\n        dfs(si, sj, -1, -1);\n\n        vector<pair<int,int>> safe;\n        for (auto &c : cells) {\n            int i = c.first, j = c.second;\n            if (filled[i][j]) continue;\n            if (vis[i][j] && !ap[i][j]) safe.push_back({i, j});\n        }\n\n        vector<pair<int,int>> candidates;\n        for (auto &c : safe) {\n            int d = dist[c.first][c.second];\n            bool ok = (d == d_ideal) || (rem_cap[d] > rem_labels[d]);\n            if (ok) candidates.push_back(c);\n        }\n\n        int best_i = -1, best_j = -1;\n        int best_score = INT_MIN;\n\n        auto consider = [&](int i, int j, bool is_ideal) {\n            int d = dist[i][j];\n            int diff_layer = abs(d - d_ideal);\n            int diff_pos   = abs(idx[i][j] - t);\n            int deg = 0;\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                if (traversable(ni, nj)) ++deg;\n            }\n            int score = (is_ideal ? 2000000 : 0)\n                      - diff_layer * 10000\n                      - diff_pos   * 100\n                      - deg;\n            if (score > best_score) {\n                best_score = score;\n                best_i = i; best_j = j;\n            }\n        };\n\n        if (!candidates.empty()) {\n            for (auto &c : candidates)\n                consider(c.first, c.second, dist[c.first][c.second] == d_ideal);\n        } else {\n            for (auto &c : safe)\n                consider(c.first, c.second, false);\n\n            if (best_i == -1) {                 // emergency fallback\n                bool vis2[9][9] = {};\n                queue<pair<int,int>> qq;\n                vis2[si][sj] = true;\n                qq.push({si, sj});\n                while (!qq.empty()) {\n                    auto [i, j] = qq.front(); qq.pop();\n                    for (int dir = 0; dir < 4; ++dir) {\n                        int ni = i + di[dir], nj = j + dj[dir];\n                        if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                        if (vis2[ni][nj]) continue;\n                        if (!traversable(ni, nj)) continue;\n                        vis2[ni][nj] = true;\n                        qq.push({ni, nj});\n                    }\n                }\n                for (int i = 0; i < D; ++i)\n                    for (int j = 0; j < D; ++j)\n                        if (!filled[i][j] && !(i == si && j == sj) && vis2[i][j])\n                            consider(i, j, false);\n            }\n        }\n\n        filled[best_i][best_j] = true;\n        label_at[best_i][best_j] = t;\n        --rem_cap[dist[best_i][best_j]];\n        cout << best_i << ' ' << best_j << '\\n' << flush;\n    }\n\n    /*--- optimal greedy removal ---*/\n    vector<vector<bool>> is_empty(D, vector<bool>(D, false));\n    is_empty[si][sj] = true;\n\n    using State = tuple<int,int,int>;               // (label, i, j)\n    priority_queue<State, vector<State>, greater<State>> pq;\n    bool in_pq[9][9] = {};\n\n    auto add_nei = [&](int i, int j) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obstacle[ni][nj]) continue;\n            if (is_empty[ni][nj]) continue;\n            if (in_pq[ni][nj]) continue;\n            pq.emplace(label_at[ni][nj], ni, nj);\n            in_pq[ni][nj] = true;\n        }\n    };\n    add_nei(si, sj);\n\n    vector<pair<int,int>> out_order;\n    while (!pq.empty()) {\n        auto [lab, i, j] = pq.top(); pq.pop();\n        out_order.emplace_back(i, j);\n        is_empty[i][j] = true;\n        add_nei(i, j);\n    }\n\n    for (auto &p : out_order) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    cout << flush;\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    vector<vector<int>> g(n, vector<int>(n));\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> g[i][j];\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    auto inside = [&](int i, int j) {\n        return i >= 0 && i < n && j >= 0 && j < n;\n    };\n\n    /* boundary colours : must stay adjacent to 0 */\n    vector<char> isB(m + 1, 0);\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1)\n                isB[g[i][j]] = 1;\n\n    /* required adjacencies among non\u2011zero colours */\n    vector<vector<char>> need(m + 1, vector<char>(m + 1, 0));\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j) {\n            int c = g[i][j];\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (!inside(ni, nj)) continue;\n                int d = g[ni][nj];\n                if (c != d) need[c][d] = 1;\n            }\n        }\n\n    /* current adjacency counters and region sizes */\n    static int adjCnt[101][101];\n    memset(adjCnt, 0, sizeof(adjCnt));\n    vector<int> sz(m + 1, 0);\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j) {\n            int c = g[i][j];\n            ++sz[c];\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (!inside(ni, nj)) continue;\n                int d = g[ni][nj];\n                if (c != d) ++adjCnt[c][d];\n            }\n        }\n\n    static int vis[50][50];\n    int visToken = 1;\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        vector<pair<int,int>> cand;\n        cand.reserve(n * n);\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                if (g[i][j] > 0 && isB[g[i][j]])\n                    cand.emplace_back(i, j);\n\n        shuffle(cand.begin(), cand.end(), rng);\n\n        for (auto [i, j] : cand) {\n            int c = g[i][j];\n            if (c == 0) continue;\n            if (!isB[c]) continue;\n            if (sz[c] <= 1) continue;\n\n            bool ok = true;\n            int contrib[101] = {};\n            bool hasZero = (i == 0 || i == n - 1 || j == 0 || j == n - 1);\n\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n                if (!inside(ni, nj)) continue;          // outside = 0\n                int d = g[ni][nj];\n                if (d > 0 && !isB[d]) {                 // would expose a non\u2011B colour to 0\n                    ok = false; break;\n                }\n                if (d == 0) hasZero = true;\n                if (d > 0) ++contrib[d];\n            }\n            if (!ok) continue;\n            if (!hasZero) continue;                      // would create an enclosed 0\u2011cell\n\n            /* connectivity test */\n            int si = -1, sj = -1;\n            for (int x = 0; x < n && si == -1; ++x)\n                for (int y = 0; y < n; ++y)\n                    if (g[x][y] == c && !(x == i && y == j)) {\n                        si = x; sj = y; break;\n                    }\n            if (si == -1) continue;                      // size was 1\n\n            int cnt = 1;\n            queue<pair<int,int>> q;\n            q.emplace(si, sj);\n            vis[si][sj] = visToken;\n            while (!q.empty()) {\n                auto [x, y] = q.front(); q.pop();\n                for (int dir = 0; dir < 4; ++dir) {\n                    int nx = x + di[dir];\n                    int ny = y + dj[dir];\n                    if (!inside(nx, ny)) continue;\n                    if (g[nx][ny] != c) continue;\n                    if (nx == i && ny == j) continue;\n                    if (vis[nx][ny] == visToken) continue;\n                    vis[nx][ny] = visToken;\n                    ++cnt;\n                    q.emplace(nx, ny);\n                }\n            }\n            ++visToken;\n            if (cnt != sz[c] - 1) continue;              // would disconnect the colour\n\n            /* preserve required adjacencies */\n            for (int d = 1; d <= m; ++d) {\n                if (contrib[d] == 0) continue;\n                if (need[c][d] && adjCnt[c][d] <= contrib[d]) {\n                    ok = false; break;\n                }\n            }\n            if (!ok) continue;\n\n            /* perform deletion */\n            g[i][j] = 0;\n            --sz[c];\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n                if (!inside(ni, nj)) continue;\n                int d = g[ni][nj];\n                if (d > 0) {\n                    --adjCnt[c][d];\n                    --adjCnt[d][c];\n                }\n            }\n            changed = true;\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << g[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    if (!(cin >> N >> D >> Q)) return 0;\n    \n    vector<vector<char>> cmp(N, vector<char>(N, 0)); // -1:i<j, 0:unknown, 1:i>j, 2:equal\n    vector<vector<char>> done(N, vector<char>(N, 0));\n    vector<int> deg(N, 0);\n    vector<int> score(N, 0);\n    \n    for (int q = 0; q < Q; ++q) {\n        // pick item i with minimum degree\n        int i = -1;\n        for (int v = 0; v < N; ++v) {\n            if (i == -1 || deg[v] < deg[i]) i = v;\n        }\n        // pick peer j not yet compared with i, preferring close score then min degree\n        int j = -1;\n        int bestDiff = INT_MAX;\n        for (int v = 0; v < N; ++v) {\n            if (v == i || done[i][v]) continue;\n            int diff = abs(score[i] - score[v]);\n            if (j == -1 || diff < bestDiff || (diff == bestDiff && deg[v] < deg[j])) {\n                bestDiff = diff;\n                j = v;\n            }\n        }\n        if (j == -1) {\n            // fallback: any undone pair with smallest total degree\n            int bestDeg = INT_MAX;\n            for (int a = 0; a < N; ++a) {\n                for (int b = a + 1; b < N; ++b) {\n                    if (done[a][b]) continue;\n                    int d = deg[a] + deg[b];\n                    if (d < bestDeg) {\n                        bestDeg = d;\n                        i = a; j = b;\n                    }\n                }\n            }\n            if (j == -1) {\n                i = 0; j = 1; // dummy when everything is already compared\n            }\n        }\n        cout << \"1 1 \" << i << \" \" << j << endl;\n        string res;\n        cin >> res;\n        done[i][j] = done[j][i] = 1;\n        deg[i]++; deg[j]++;\n        if (res == \">\") {\n            cmp[i][j] = 1; cmp[j][i] = -1;\n            score[i]++; score[j]--;\n        } else if (res == \"<\") {\n            cmp[i][j] = -1; cmp[j][i] = 1;\n            score[i]--; score[j]++;\n        } else {\n            cmp[i][j] = cmp[j][i] = 2;\n        }\n    }\n    \n    // transitive closure to exploit indirect comparisons\n    for (int k = 0; k < N; ++k)\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j) {\n                if (cmp[i][k] == 1 && cmp[k][j] == 1) {\n                    cmp[i][j] = 1; cmp[j][i] = -1;\n                } else if (cmp[i][k] == -1 && cmp[k][j] == -1) {\n                    cmp[i][j] = -1; cmp[j][i] = 1;\n                } else if (cmp[i][k] == 2 && cmp[k][j] == 2) {\n                    cmp[i][j] = 2; cmp[j][i] = 2;\n                } else if (cmp[i][k] == 1 && cmp[k][j] == 2) {\n                    cmp[i][j] = 1; cmp[j][i] = -1;\n                } else if (cmp[i][k] == 2 && cmp[k][j] == 1) {\n                    cmp[i][j] = 1; cmp[j][i] = -1;\n                } else if (cmp[i][k] == -1 && cmp[k][j] == 2) {\n                    cmp[i][j] = -1; cmp[j][i] = 1;\n                } else if (cmp[i][k] == 2 && cmp[k][j] == -1) {\n                    cmp[i][j] = -1; cmp[j][i] = 1;\n                }\n            }\n    \n    vector<int> rankScore(N, 0);\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (cmp[i][j] == 1) rankScore[i]++;\n            else if (cmp[i][j] == -1) rankScore[i]--;\n        }\n    }\n    \n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (rankScore[a] != rankScore[b]) return rankScore[a] > rankScore[b];\n        if (cmp[a][b] == 1) return true;\n        if (cmp[a][b] == -1) return false;\n        return a < b;\n    });\n    \n    vector<int> pos(N);\n    for (int idx = 0; idx < N; ++idx) pos[ord[idx]] = idx; // 0 = lightest\n    \n    // expected order statistics of exponential(1e-5)\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0 / i;\n    const double LAMBDA = 1e-5;\n    vector<long long> ew(N);\n    for (int i = 0; i < N; ++i) {\n        int r = pos[i];\n        double val = (H[N] - H[N - 1 - r]) / LAMBDA;\n        ew[i] = max(1LL, (long long)llround(val));\n    }\n    \n    // LPT initial assignment\n    vector<int> assign(N, -1);\n    vector<long long> gsum(D, 0);\n    vector<vector<int>> groups(D);\n    vector<int> lptOrd(N);\n    iota(lptOrd.begin(), lptOrd.end(), 0);\n    sort(lptOrd.begin(), lptOrd.end(), [&](int a, int b){ return ew[a] > ew[b]; });\n    \n    for (int idx : lptOrd) {\n        int best = 0;\n        for (int g = 1; g < D; ++g) {\n            if (gsum[g] < gsum[best]) best = g;\n        }\n        assign[idx] = best;\n        gsum[best] += ew[idx];\n        groups[best].push_back(idx);\n    }\n    \n    auto calc_obj = [&](const vector<long long>& s) -> long long {\n        long long o = 0;\n        for (long long x : s) o += x * x;\n        return o;\n    };\n    \n    long long bestObj = calc_obj(gsum);\n    vector<int> bestAssign = assign;\n    vector<long long> bestGsum = gsum;\n    vector<vector<int>> bestGroups = groups;\n    \n    auto improve = [&]() -> bool {\n        long long bestDelta = 0;\n        int best_i = -1, best_from = -1, best_to = -1, best_j = -1;\n        for (int i = 0; i < N; ++i) {\n            int a = assign[i];\n            for (int b = 0; b < D; ++b) {\n                if (a == b) continue;\n                long long sa = gsum[a];\n                long long sb = gsum[b];\n                long long wi = ew[i];\n                // move i from a to b\n                long long nsa = sa - wi;\n                long long nsb = sb + wi;\n                long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    best_i = i; best_from = a; best_to = b; best_j = -1;\n                }\n                // swap i with j in b\n                for (int j : groups[b]) {\n                    long long wj = ew[j];\n                    long long nsa2 = sa - wi + wj;\n                    long long nsb2 = sb - wj + wi;\n                    long long delta2 = (nsa2 * nsa2 + nsb2 * nsb2) - (sa * sa + sb * sb);\n                    if (delta2 < bestDelta) {\n                        bestDelta = delta2;\n                        best_i = i; best_from = a; best_to = b; best_j = j;\n                    }\n                }\n            }\n        }\n        if (bestDelta >= 0) return false;\n        if (best_j == -1) {\n            int i = best_i, a = best_from, b = best_to;\n            assign[i] = b;\n            gsum[a] -= ew[i];\n            gsum[b] += ew[i];\n            auto& va = groups[a];\n            auto it = find(va.begin(), va.end(), i);\n            if (it != va.end()) va.erase(it);\n            groups[b].push_back(i);\n        } else {\n            int i = best_i, j = best_j, a = best_from, b = best_to;\n            assign[i] = b;\n            assign[j] = a;\n            gsum[a] = gsum[a] - ew[i] + ew[j];\n            gsum[b] = gsum[b] - ew[j] + ew[i];\n            auto& va = groups[a];\n            auto it = find(va.begin(), va.end(), i);\n            if (it != va.end()) va.erase(it);\n            auto& vb = groups[b];\n            auto it2 = find(vb.begin(), vb.end(), j);\n            if (it2 != vb.end()) vb.erase(it2);\n            va.push_back(j);\n            vb.push_back(i);\n        }\n        return true;\n    };\n    \n    while (improve()) {\n        long long curObj = calc_obj(gsum);\n        if (curObj < bestObj) {\n            bestObj = curObj;\n            bestAssign = assign;\n            bestGsum = gsum;\n            bestGroups = groups;\n        }\n    }\n    \n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int rep = 0; rep < 50; ++rep) {\n        assign = bestAssign;\n        gsum = bestGsum;\n        groups = bestGroups;\n        int perturb = max(1, N / 10);\n        for (int k = 0; k < perturb; ++k) {\n            int i = uniform_int_distribution<int>(0, N - 1)(rng);\n            int b = uniform_int_distribution<int>(0, D - 1)(rng);\n            int a = assign[i];\n            if (a == b) continue;\n            assign[i] = b;\n            gsum[a] -= ew[i];\n            gsum[b] += ew[i];\n            auto it = find(groups[a].begin(), groups[a].end(), i);\n            if (it != groups[a].end()) groups[a].erase(it);\n            groups[b].push_back(i);\n        }\n        while (improve()) {}\n        long long curObj = calc_obj(gsum);\n        if (curObj < bestObj) {\n            bestObj = curObj;\n            bestAssign = assign;\n            bestGsum = gsum;\n            bestGroups = groups;\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestAssign[i];\n    }\n    cout << endl;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    const int h = n / m;\n    vector<vector<int>> st(m);\n    vector<int> pos(n + 1, -1);\n    vector<int> mn(m, INT_MAX);\n    \n    for (int i = 0; i < m; ++i) {\n        st[i].resize(h);\n        for (int j = 0; j < h; ++j) {\n            cin >> st[i][j];\n            pos[st[i][j]] = i;\n        }\n        mn[i] = *min_element(st[i].begin(), st[i].end());\n    }\n    \n    vector<pair<int,int>> ops;\n    const int INF = 1e9;\n    \n    auto recompute_mn = [&](int idx) {\n        if (st[idx].empty()) mn[idx] = INF;\n        else mn[idx] = *min_element(st[idx].begin(), st[idx].end());\n    };\n    \n    for (int v = 1; v <= n; ++v) {\n        int s = pos[v];\n        int hpos = 0;\n        while (hpos < (int)st[s].size() && st[s][hpos] != v) ++hpos;\n        int k = (int)st[s].size() - hpos - 1;   // number of boxes above v\n        \n        if (k == 0) {\n            // operation 2\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n            pos[v] = -1;\n            recompute_mn(s);\n        } else {\n            vector<int> T(st[s].begin() + hpos + 1, st[s].end());\n            int mxT = *max_element(T.begin(), T.end());\n            \n            tuple<int,int,int> best_score = {INF, INF, INF};\n            int best_d = -1;\n            for (int d = 0; d < m; ++d) if (d != s) {\n                tuple<int,int,int> score;\n                if (st[d].empty()) {\n                    score = {1, 0, 0};                     // empty: second choice\n                } else if (mn[d] >= mxT) {\n                    score = {0, st[d].back(), 0};           // safe non\u2011empty: first choice, best\u2011fit top\n                } else {\n                    int inv = 0;\n                    for (int t : T)\n                        for (int x : st[d])\n                            if (t > x) ++inv;\n                    score = {2, inv, -mn[d]};               // unsafe: minimize inversions, then maximize minimum\n                }\n                if (score < best_score) {\n                    best_score = score;\n                    best_d = d;\n                }\n            }\n            \n            int w = st[s][hpos + 1];            // box directly above v\n            ops.emplace_back(w, best_d + 1);     // destination stack is 1-indexed\n            \n            // move tail T from s to best_d\n            for (int x : T) {\n                st[best_d].push_back(x);\n                pos[x] = best_d;\n            }\n            st[s].resize(hpos + 1);              // keep v on top of s\n            \n            // carry out v\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n            pos[v] = -1;\n            \n            recompute_mn(s);\n            recompute_mn(best_d);\n        }\n    }\n    \n    for (auto [v, i] : ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n};\n\nstruct HeapItem {\n    double score;\n    int eid;\n    long long ku, kv;\n    bool operator<(const HeapItem& other) const {\n        return score < other.score; // max-heap\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    if(!(cin >> N)) return 0;\n    vector<string> h(N - 1);\n    vector<string> vwall(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> vwall[i];\n    vector<vector<int>> dmat(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> dmat[i][j];\n    \n    const int V = N * N;\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto geti = [&](int v) { return v / N; };\n    auto getj = [&](int v) { return v % N; };\n    \n    vector<int> dval(V);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dval[id(i, j)] = dmat[i][j];\n    \n    // Build graph\n    vector<Edge> edges;\n    vector<vector<pair<int,int>>> adj(V); // (neighbor, edge_id)\n    auto add_edge = [&](int u, int v) {\n        int eid = (int)edges.size();\n        edges.push_back({u, v});\n        adj[u].push_back({v, eid});\n        adj[v].push_back({u, eid});\n    };\n    \n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] == '0')\n                add_edge(id(i, j), id(i + 1, j));\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            if (vwall[i][j] == '0')\n                add_edge(id(i, j), id(i, j + 1));\n        }\n    }\n    const int E = (int)edges.size();\n    \n    // Spanning tree by BFS\n    vector<int> parent(V, -1);\n    vector<char> vis(V, 0);\n    queue<int> q;\n    vis[0] = 1;\n    q.push(0);\n    vector<char> is_tree_edge(E, 0);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [v, eid] : adj[u]) {\n            if (!vis[v]) {\n                vis[v] = 1;\n                parent[v] = u;\n                is_tree_edge[eid] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Multiplicity of each undirected edge (number of traversals)\n    // We keep multiplicities even. Tree edges start with 2.\n    vector<int> mult(E, 0);\n    vector<long long> k(V, 0); // visit count = half degree = sum_{e incident} mult[e]/2, but here mult counts traversals. Actually k[v] = sum_{e incident} mult[e] / 2.\n    // To avoid fractions, we define mult[e] as number of traversals (always even), and k[v] = degree/2.\n    for (int eid = 0; eid < E; ++eid) {\n        if (is_tree_edge[eid]) {\n            mult[eid] = 2;\n            k[edges[eid].u]++;\n            k[edges[eid].v]++;\n        }\n    }\n    long long L = 0;\n    for (int i = 0; i < V; ++i) L += k[i];\n    \n    const long long L_MAX = 100000;\n    \n    auto edge_score = [&](int eid) -> double {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n        return (double)dval[u] / ((double)k[u] * (k[u] + 1.0))\n             + (double)dval[v] / ((double)k[v] * (k[v] + 1.0));\n    };\n    \n    priority_queue<HeapItem> pq;\n    for (int eid = 0; eid < E; ++eid) {\n        double sc = edge_score(eid);\n        pq.push({sc, eid, k[edges[eid].u], k[edges[eid].v]});\n    }\n    \n    while (L + 2 <= L_MAX) {\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int eid = cur.eid;\n            int u = edges[eid].u;\n            int v = edges[eid].v;\n            if (k[u] != cur.ku || k[v] != cur.kv) continue; // stale\n            // apply\n            mult[eid] += 2;\n            k[u]++; k[v]++;\n            L += 2;\n            // push neighbors of u and v\n            for (auto [w, eid2] : adj[u]) {\n                double sc = edge_score(eid2);\n                pq.push({sc, eid2, k[edges[eid2].u], k[edges[eid2].v]});\n            }\n            for (auto [w, eid2] : adj[v]) {\n                double sc = edge_score(eid2);\n                pq.push({sc, eid2, k[edges[eid2].u], k[edges[eid2].v]});\n            }\n            break;\n        }\n        if (pq.empty()) break;\n    }\n    \n    // Helper: get move character between adjacent cells\n    auto move_char = [&](int u, int v) -> char {\n        int i1 = geti(u), j1 = getj(u);\n        int i2 = geti(v), j2 = getj(v);\n        if (i2 == i1 - 1) return 'U';\n        if (i2 == i1 + 1) return 'D';\n        if (j2 == j1 - 1) return 'L';\n        return 'R';\n    };\n    \n    // Build an Eulerian tour on the multigraph.\n    auto build_tour = [&](mt19937& rng, bool use_random) -> vector<int> {\n        vector<int> mcur = mult;\n        vector<int> path;\n        path.reserve((size_t)L + 1);\n        vector<int> stk;\n        stk.reserve((size_t)L + 1);\n        stk.push_back(0);\n        vector<int> last_from(V, -1);\n        vector<int> rr_idx(V, 0);\n        \n        while (!stk.empty()) {\n            int u = stk.back();\n            int total = 0;\n            for (auto [v2, eid2] : adj[u]) total += mcur[eid2];\n            if (total == 0) {\n                path.push_back(u);\n                stk.pop_back();\n                continue;\n            }\n            int picked_eid = -1;\n            int picked_v = -1;\n            if (use_random) {\n                vector<int> cand_eid;\n                vector<int> cand_v;\n                int back_eid = -1, back_v = -1;\n                for (auto [v2, eid2] : adj[u]) {\n                    if (mcur[eid2] == 0) continue;\n                    if (v2 == last_from[u]) {\n                        back_eid = eid2;\n                        back_v = v2;\n                    } else {\n                        cand_eid.push_back(eid2);\n                        cand_v.push_back(v2);\n                    }\n                }\n                if (!cand_eid.empty()) {\n                    int idx = (int)(rng() % cand_eid.size());\n                    picked_eid = cand_eid[idx];\n                    picked_v = cand_v[idx];\n                } else {\n                    picked_eid = back_eid;\n                    picked_v = back_v;\n                }\n            } else {\n                // round-robin, avoid immediate backtrack if possible\n                int deg = (int)adj[u].size();\n                for (int iter = 0; iter < deg; ++iter) {\n                    int idx = (rr_idx[u] + iter) % deg;\n                    int eid2 = adj[u][idx].second;\n                    int v2 = adj[u][idx].first;\n                    if (mcur[eid2] == 0) continue;\n                    if (v2 == last_from[u] && total > mcur[eid2]) continue;\n                    picked_eid = eid2;\n                    picked_v = v2;\n                    rr_idx[u] = (idx + 1) % deg;\n                    break;\n                }\n                if (picked_eid == -1) {\n                    for (int iter = 0; iter < deg; ++iter) {\n                        int idx = (rr_idx[u] + iter) % deg;\n                        int eid2 = adj[u][idx].second;\n                        int v2 = adj[u][idx].first;\n                        if (mcur[eid2] > 0) {\n                            picked_eid = eid2;\n                            picked_v = v2;\n                            rr_idx[u] = (idx + 1) % deg;\n                            break;\n                        }\n                    }\n                }\n            }\n            mcur[picked_eid]--;\n            last_from[picked_v] = u;\n            stk.push_back(picked_v);\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    auto eval_cost = [&](const vector<int>& path) -> long long {\n        // path[0] = start, path.back() = start, length = L+1\n        int T = (int)path.size() - 1; // number of moves\n        vector<int> first_pos(V, -1);\n        vector<int> last_pos(V, -1);\n        vector<long long> sumsq(V, 0);\n        for (int t = 0; t < T; ++t) {\n            int cell = path[t + 1];\n            if (last_pos[cell] != -1) {\n                int gap = (t + 1) - last_pos[cell];\n                sumsq[cell] += 1LL * gap * gap;\n            } else {\n                first_pos[cell] = t + 1;\n            }\n            last_pos[cell] = t + 1;\n        }\n        long long cost = 0;\n        for (int v = 0; v < V; ++v) {\n            if (first_pos[v] != -1) {\n                int gap = T - last_pos[v] + first_pos[v];\n                sumsq[v] += 1LL * gap * gap;\n                cost += 1LL * dval[v] * sumsq[v];\n            }\n        }\n        return cost;\n    };\n    \n    long long best_cost = LLONG_MAX;\n    string best_route;\n    best_route.reserve((size_t)L);\n    \n    // fallback base DFS traversal of the spanning tree (double walk)\n    {\n        vector<vector<pair<int,char>>> children(V);\n        for (int v = 1; v < V; ++v) {\n            int p = parent[v];\n            // determine direction char from p to v\n            char c = move_char(p, v);\n            children[p].push_back({v, c});\n        }\n        string fallback;\n        function<void(int)> dfs = [&](int u) {\n            for (auto [v, c] : children[u]) {\n                fallback.push_back(c);\n                dfs(v);\n                // opposite direction\n                if (c == 'U') fallback.push_back('D');\n                else if (c == 'D') fallback.push_back('U');\n                else if (c == 'L') fallback.push_back('R');\n                else fallback.push_back('L');\n            }\n        };\n        dfs(0);\n        // ensure it returns to 0 and visits all\n        if ((int)fallback.size() <= 100000) {\n            best_route = fallback;\n            // we could eval it, but we will replace with better ones\n        }\n    }\n    \n    // Try many random seeds and heuristics\n    vector<uint32_t> seeds;\n    for (int s = 0; s < 20; ++s) seeds.push_back((uint32_t)s);\n    seeds.push_back((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (uint32_t seed : seeds) {\n        mt19937 rng(seed);\n        for (int trial = 0; trial < 15; ++trial) {\n            bool use_random = (trial % 3 != 0); // mix random and round-robin\n            auto path = build_tour(rng, use_random);\n            if ((int)path.size() != L + 1) continue;\n            long long c = eval_cost(path);\n            if (c < best_cost) {\n                best_cost = c;\n                best_route.clear();\n                for (int i = 0; i < L; ++i)\n                    best_route.push_back(move_char(path[i], path[i + 1]));\n            }\n        }\n    }\n    \n    cout << best_route << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_M = 200;\nconst int MAX_C = 225;          // 15*15\n\nint N, M;\nint start_cell;\nint C;                          // N*N\nvector<int> pos[26];\nint dist_arr[MAX_C][MAX_C];\n\nint layer_sz[MAX_M][5];\nint layer_cell[MAX_M][5][MAX_C];\n\n/* cost_end[t][c][e] : type target t starting from cell c,\n   end at e-th cell of the last layer (layer 4).               */\nint16_t cost_end[MAX_M][MAX_C][MAX_C];\nint16_t best_cost[MAX_M][MAX_C];   // min over e of cost_end\n\nstring targets[MAX_M];\n\n/*---------------------------------------------------------------*/\n/* Evaluate a full permutation (exact cost, optimal end cells)   */\nint evaluate_order(const vector<int>& order) {\n    int t0 = order[0];\n    int sz0 = layer_sz[t0][4];\n    int dp_prev[225];\n    for (int i = 0; i < sz0; ++i) dp_prev[i] = cost_end[t0][start_cell][i];\n\n    for (int idx = 1; idx < M; ++idx) {\n        int prev = order[idx - 1];\n        int cur  = order[idx];\n        int sz_prev = layer_sz[prev][4];\n        int sz_cur  = layer_sz[cur][4];\n        int dp_cur[225];\n        for (int j = 0; j < sz_cur; ++j) {\n            int best = INT_MAX;\n            for (int i = 0; i < sz_prev; ++i) {\n                int c = layer_cell[prev][4][i];\n                int v = dp_prev[i] + cost_end[cur][c][j];\n                if (v < best) best = v;\n            }\n            dp_cur[j] = best;\n        }\n        for (int j = 0; j < sz_cur; ++j) dp_prev[j] = dp_cur[j];\n    }\n    int last = order[M - 1];\n    int sz_last = layer_sz[last][4];\n    int best = INT_MAX;\n    for (int i = 0; i < sz_last; ++i) best = min(best, dp_prev[i]);\n    return best;\n}\n\n/*---------------------------------------------------------------*/\n/* Reconstruct the full path of cells for the best order         */\nvector<pair<int,int>> reconstruct(const vector<int>& order) {\n    vector<pair<int,int>> ans;\n\n    /* forward DP with back-pointers for end cells */\n    int t0 = order[0];\n    int sz0 = layer_sz[t0][4];\n    vector<int> dp_prev(sz0);\n    vector<vector<int>> prev_idx(M);\n    for (int i = 0; i < sz0; ++i) dp_prev[i] = cost_end[t0][start_cell][i];\n\n    for (int idx = 1; idx < M; ++idx) {\n        int prev = order[idx - 1];\n        int cur  = order[idx];\n        int sz_prev = layer_sz[prev][4];\n        int sz_cur  = layer_sz[cur][4];\n        vector<int> dp_cur(sz_cur, INT_MAX);\n        vector<int> pi(sz_cur);\n        for (int j = 0; j < sz_cur; ++j) {\n            int best = INT_MAX, best_i = -1;\n            for (int i = 0; i < sz_prev; ++i) {\n                int c = layer_cell[prev][4][i];\n                int v = dp_prev[i] + cost_end[cur][c][j];\n                if (v < best) { best = v; best_i = i; }\n            }\n            dp_cur[j] = best;\n            pi[j] = best_i;\n        }\n        prev_idx[idx] = move(pi);\n        dp_prev.swap(dp_cur);\n    }\n\n    /* backtrack chosen end cells */\n    vector<int> end_idx(M);\n    int last = order[M - 1];\n    int sz_last = layer_sz[last][4];\n    int best_i = 0;\n    for (int i = 1; i < sz_last; ++i)\n        if (dp_prev[i] < dp_prev[best_i]) best_i = i;\n    end_idx[M - 1] = best_i;\n    for (int idx = M - 1; idx >= 1; --idx)\n        end_idx[idx - 1] = prev_idx[idx][end_idx[idx]];\n\n    /* reconstruct internal 5-cell path for every target */\n    int cur_cell = start_cell;\n    for (int idx = 0; idx < M; ++idx) {\n        int t = order[idx];\n        int start_c = cur_cell;\n        int end_e   = end_idx[idx];\n\n        int dp_p[225], dp_c[225];\n        uint8_t par[5][225];\n\n        int sz_l0 = layer_sz[t][0];\n        for (int i = 0; i < sz_l0; ++i)\n            dp_p[i] = dist_arr[start_c][layer_cell[t][0][i]];\n\n        for (int l = 1; l < 5; ++l) {\n            int sz_pr = layer_sz[t][l - 1];\n            int sz_cu = layer_sz[t][l];\n            for (int j = 0; j < sz_cu; ++j) {\n                int v = layer_cell[t][l][j];\n                int best = INT_MAX;\n                uint8_t best_i = 0;\n                for (int i = 0; i < sz_pr; ++i) {\n                    int u = layer_cell[t][l - 1][i];\n                    int val = dp_p[i] + dist_arr[u][v];\n                    if (val < best) { best = val; best_i = (uint8_t)i; }\n                }\n                dp_c[j] = best;\n                par[l][j] = best_i;\n            }\n            for (int j = 0; j < sz_cu; ++j) dp_p[j] = dp_c[j];\n        }\n\n        int i4 = end_e;\n        int i3 = par[4][i4];\n        int i2 = par[3][i3];\n        int i1 = par[2][i2];\n        int i0 = par[1][i1];\n        int cells[5];\n        cells[0] = layer_cell[t][0][i0];\n        cells[1] = layer_cell[t][1][i1];\n        cells[2] = layer_cell[t][2][i2];\n        cells[3] = layer_cell[t][3][i3];\n        cells[4] = layer_cell[t][4][i4];\n\n        for (int k = 0; k < 5; ++k) {\n            int id = cells[k];\n            ans.emplace_back(id / N, id % N);\n        }\n        cur_cell = cells[4];\n    }\n    return ans;\n}\n\n/*---------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    start_cell = si * N + sj;\n    C = N * N;\n\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            pos[s[j] - 'A'].push_back(id);\n        }\n    }\n    for (int k = 0; k < M; ++k) cin >> targets[k];\n\n    /* Manhattan distances */\n    for (int i = 0; i < C; ++i) {\n        int i1 = i / N, j1 = i % N;\n        for (int j = 0; j < C; ++j) {\n            int i2 = j / N, j2 = j % N;\n            dist_arr[i][j] = abs(i1 - i2) + abs(j1 - j2);\n        }\n    }\n\n    /* Precompute target DPs */\n    for (int t = 0; t < M; ++t) {\n        for (int k = 0; k < 5; ++k) {\n            char ch = targets[t][k];\n            layer_sz[t][k] = (int)pos[ch - 'A'].size();\n            for (int idx = 0; idx < layer_sz[t][k]; ++idx)\n                layer_cell[t][k][idx] = pos[ch - 'A'][idx];\n        }\n        for (int c = 0; c < C; ++c) {\n            int dp_prev[225], dp_cur[225];\n            int sz0 = layer_sz[t][0];\n            for (int i = 0; i < sz0; ++i) {\n                int v = layer_cell[t][0][i];\n                dp_prev[i] = dist_arr[c][v];\n            }\n            for (int l = 1; l < 5; ++l) {\n                int sz_prev = layer_sz[t][l - 1];\n                int sz_cur  = layer_sz[t][l];\n                for (int j = 0; j < sz_cur; ++j) {\n                    int v = layer_cell[t][l][j];\n                    int best = INT_MAX;\n                    for (int i = 0; i < sz_prev; ++i) {\n                        int u = layer_cell[t][l - 1][i];\n                        int val = dp_prev[i] + dist_arr[u][v];\n                        if (val < best) best = val;\n                    }\n                    dp_cur[j] = best;\n                }\n                for (int j = 0; j < sz_cur; ++j) dp_prev[j] = dp_cur[j];\n            }\n            int sz4 = layer_sz[t][4];\n            int best = INT_MAX;\n            for (int j = 0; j < sz4; ++j) {\n                int val = dp_prev[j] + 5;\n                cost_end[t][c][j] = (int16_t)val;\n                if (val < best) best = val;\n            }\n            best_cost[t][c] = (int16_t)best;\n        }\n    }\n\n    /*--- Greedy initial order (one-step lookahead) ---------------*/\n    vector<int> init_order;\n    {\n        vector<char> used(M, 0);\n        init_order.reserve(M);\n        int cur = start_cell;\n        for (int step = 0; step < M; ++step) {\n            static int16_t b1c[225];\n            static int  b1t[225];\n            static int16_t b2c[225];\n            for (int d = 0; d < C; ++d) {\n                b1c[d] = INT16_MAX; b1t[d] = -1; b2c[d] = INT16_MAX;\n            }\n            for (int t = 0; t < M; ++t) if (!used[t]) {\n                for (int d = 0; d < C; ++d) {\n                    int16_t c = best_cost[t][d];\n                    if (c < b1c[d]) {\n                        b2c[d] = b1c[d];\n                        b1c[d] = c;\n                        b1t[d] = t;\n                    } else if (c < b2c[d]) {\n                        b2c[d] = c;\n                    }\n                }\n            }\n            int best_total = INT_MAX;\n            int chosen_t = -1, chosen_e = -1;\n            for (int t = 0; t < M; ++t) if (!used[t]) {\n                int sz4 = layer_sz[t][4];\n                for (int e = 0; e < sz4; ++e) {\n                    int d = layer_cell[t][4][e];\n                    int here   = cost_end[t][cur][e];\n                    int future = (step == M - 1) ? 0\n                                 : ((b1t[d] == t) ? b2c[d] : b1c[d]);\n                    int total = here + future;\n                    if (total < best_total) {\n                        best_total = total;\n                        chosen_t = t;\n                        chosen_e = e;\n                    }\n                }\n            }\n            init_order.push_back(chosen_t);\n            used[chosen_t] = 1;\n            cur = layer_cell[chosen_t][4][chosen_e];\n        }\n    }\n\n    /*--- Local search (iterated hill climbing) -------------------*/\n    vector<int> best_order = init_order;\n    int best_cost_val = evaluate_order(best_order);\n    vector<int> cur_order = init_order;\n    int cur_cost = best_cost_val;\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    int iter = 0, last_improve = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.90) break;\n\n        ++iter;\n        int type = rng() % 3;\n        int i = rng() % M;\n        int j = rng() % M;\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<int> nxt = cur_order;\n        if (type == 0) {\n            swap(nxt[i], nxt[j]);\n        } else if (type == 1) {\n            int v = nxt[i];\n            nxt.erase(nxt.begin() + i);\n            nxt.insert(nxt.begin() + j, v);\n        } else {\n            reverse(nxt.begin() + i, nxt.begin() + j + 1);\n        }\n\n        int nxt_cost = evaluate_order(nxt);\n        if (nxt_cost <= cur_cost) {\n            cur_order = move(nxt);\n            cur_cost = nxt_cost;\n            last_improve = iter;\n            if (cur_cost < best_cost_val) {\n                best_cost_val = cur_cost;\n                best_order = cur_order;\n            }\n        } else if (iter - last_improve > 5000) {\n            /* perturb to escape local optimum */\n            for (int k = 0; k < 5; ++k) {\n                int a = rng() % M, b = rng() % M;\n                if (a != b) swap(cur_order[a], cur_order[b]);\n            }\n            cur_cost = evaluate_order(cur_order);\n            last_improve = iter;\n        }\n    }\n\n    /*--- Output --------------------------------------------------*/\n    vector<pair<int,int>> ans = reconstruct(best_order);\n    for (auto &p : ans) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\ndouble eps;\nconst int MAXC = 400;          // max cells\nconst int MAXT = 400;          // max translations per field\n\n/* global data */\nvector<vector<bitset<MAXC>>> masks;                 // masks[k][t]\nvector<vector<bitset<MAXT>>> trans_cover_cell;      // cover[k][p]  (translations)\nvector<vector<bitset<MAXT>>> not_cover_cell;        // ~cover , masked to valid ones\nvector<bitset<MAXT>> all_valid;                     // all translations of field k\nvector<int> drilled_val;                            // -1 = unknown\nvector<int> drilled_cells;\nmt19937 rng;\n\n/* --------------------------------------------------------------- */\nstruct Sol {\n    bitset<MAXC> uni;\n    vector<int> assigned;\n};\n\nstruct State {\n    vector<int> assigned;\n    array<short, MAXC> sum;\n    int depth;\n};\n\n/* safe fixed\u2011point propagation, never removes a true translation */\nvoid global_propagate(vector<bitset<MAXT>>& cand) {\n    bool changed = true;\n    int it = 0;\n    while (changed && it++ < 20) {\n        changed = false;\n        vector<vector<char>> any(M, vector<char>(N * N, 0));\n        vector<vector<char>> all(M, vector<char>(N * N, 0));\n        vector<int> tot_any(N * N, 0), tot_all(N * N, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (!cand[k].any()) return;               // contradiction \u2013 should not happen\n            for (int p : drilled_cells) {\n                bool a = (cand[k] & trans_cover_cell[k][p]).any();\n                bool b = false;\n                if (cand[k].any())\n                    b = (cand[k] & not_cover_cell[k][p]).none();\n                any[k][p] = a;  all[k][p] = b;\n                if (a) tot_any[p]++;\n                if (b) tot_all[p]++;\n            }\n        }\n\n        for (int k = 0; k < M; k++) {\n            for (int t = 0; t < (int)masks[k].size(); t++) if (cand[k].test(t)) {\n                bool ok = true;\n                for (int p : drilled_cells) {\n                    int need = drilled_val[p] - (masks[k][t].test(p) ? 1 : 0);\n                    int minRem = tot_all[p] - (all[k][p] ? 1 : 0);\n                    int maxRem = tot_any[p] - (any[k][p] ? 1 : 0);\n                    if (need < minRem || need > maxRem) { ok = false; break; }\n                }\n                if (!ok) {\n                    cand[k].reset(t);\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\n/* --------------------------------------------------------------- */\nstruct DFSHelper {\n    const vector<bitset<MAXT>>& cand;\n    int limit_sol, limit_node;\n    int nodes;\n    vector<Sol> sols;\n\n    DFSHelper(const vector<bitset<MAXT>>& c, int ls, int ln)\n        : cand(c), limit_sol(ls), limit_node(ln), nodes(0) {}\n\n    void run() {\n        State init;\n        init.assigned.assign(M, -1);\n        init.sum.fill(0);\n        init.depth = 0;\n        rec(init);\n    }\n\n    void rec(State st) {\n        if ((int)sols.size() >= limit_sol || nodes >= limit_node) return;\n        ++nodes;\n        if (st.depth == M) {\n            bitset<MAXC> uni;\n            for (int k = 0; k < M; k++) uni |= masks[k][st.assigned[k]];\n            sols.push_back({uni, st.assigned});\n            return;\n        }\n        vector<int> fields;\n        for (int i = 0; i < M; i++) if (st.assigned[i] == -1) fields.push_back(i);\n        sort(fields.begin(), fields.end(),\n             [&](int a, int b) { return cand[a].count() < cand[b].count(); });\n\n        int pick = min((int)fields.size(), max(1, (int)fields.size() / 2 + 1));\n        int k = fields[rng() % pick];\n\n        vector<int> ts;\n        for (int t = 0; t < (int)masks[k].size(); t++)\n            if (cand[k].test(t)) ts.push_back(t);\n        shuffle(ts.begin(), ts.end(), rng);\n\n        for (int t : ts) {\n            State nst = st;\n            nst.assigned[k] = t;\n            ++nst.depth;\n            bool ok = true;\n            for (int p : drilled_cells) {\n                if (masks[k][t].test(p)) ++nst.sum[p];\n                int rem = M - nst.depth;\n                int need = drilled_val[p] - nst.sum[p];\n                if (need < 0 || need > rem) { ok = false; break; }\n            }\n            if (!ok) continue;\n            rec(nst);\n        }\n    }\n};\n\n/* --------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    if (!(cin >> N >> M >> eps)) return 0;\n    vector<vector<pair<int,int>>> shapes(M);\n    for (int k = 0; k < M; k++) {\n        int d; cin >> d;\n        shapes[k].resize(d);\n        for (int i = 0; i < d; i++) cin >> shapes[k][i].first >> shapes[k][i].second;\n    }\n\n    /* pre\u2011compute translations */\n    masks.assign(M, {});\n    all_valid.assign(M, {});\n    for (int k = 0; k < M; k++) {\n        int hi = 0, hj = 0;\n        for (auto &c : shapes[k]) {\n            hi = max(hi, c.first);\n            hj = max(hj, c.second);\n        }\n        int h = hi + 1, w = hj + 1;\n        for (int di = 0; di + h <= N; di++) {\n            for (int dj = 0; dj + w <= N; dj++) {\n                bitset<MAXC> bs;\n                for (auto &c : shapes[k]) {\n                    int i = di + c.first;\n                    int j = dj + c.second;\n                    bs.set(i * N + j);\n                }\n                masks[k].push_back(bs);\n            }\n        }\n        for (int t = 0; t < (int)masks[k].size(); t++) all_valid[k].set(t);\n    }\n\n    trans_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    not_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    for (int k = 0; k < M; k++) {\n        for (int p = 0; p < N * N; p++) {\n            for (int t = 0; t < (int)masks[k].size(); t++)\n                if (masks[k][t].test(p)) trans_cover_cell[k][p].set(t);\n            not_cover_cell[k][p] = all_valid[k] & ~trans_cover_cell[k][p];\n        }\n    }\n\n    drilled_val.assign(N * N, -1);\n    rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<bitset<MAXT>> cand(M);\n    for (int k = 0; k < M; k++) cand[k] = all_valid[k];\n\n    const int MAX_OPS = 2 * N * N;\n    int ops = 0;\n\n    auto do_drill = [&](int p) {\n        int i = p / N, j = p % N;\n        cout << \"q 1 \" << i << ' ' << j << endl;\n        int v; \n        if (!(cin >> v)) exit(0);\n        ++ops;\n        drilled_val[p] = v;\n        drilled_cells.push_back(p);\n        if (v == 0) {\n            for (int k = 0; k < M; k++) cand[k] &= not_cover_cell[k][p];\n        } else if (v == M) {\n            for (int k = 0; k < M; k++) cand[k] &= trans_cover_cell[k][p];\n        }\n        global_propagate(cand);\n    };\n\n    auto do_guess = [&](const bitset<MAXC>& uni) -> bool {\n        vector<pair<int,int>> ans;\n        for (int p = 0; p < N * N; p++)\n            if (uni.test(p)) ans.emplace_back(p / N, p % N);\n        cout << \"a \" << ans.size();\n        for (auto &pr : ans) cout << ' ' << pr.first << ' ' << pr.second;\n        cout << endl;\n        int resp; \n        if (!(cin >> resp)) exit(0);\n        ++ops;\n        return resp == 1;\n    };\n\n    vector<int> cell_order(N * N);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    shuffle(cell_order.begin(), cell_order.end(), rng);\n    int nxt = 0;\n\n    auto pick_random_undrilled = [&]() -> int {\n        while (nxt < N * N && drilled_val[cell_order[nxt]] != -1) ++nxt;\n        if (nxt < N * N) return cell_order[nxt++];\n        for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) return p;\n        return -1;\n    };\n\n    /* initial random drilling */\n    int init_drills = min(N * N, max(N, 4));\n    for (int i = 0; i < init_drills && ops < MAX_OPS - 5; i++) {\n        int p = pick_random_undrilled();\n        if (p == -1) break;\n        do_drill(p);\n    }\n\n    const int LIMIT_SOL = 12;\n    const int LIMIT_NODE = 60000;\n\n    while (ops < MAX_OPS - 2) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 2.6) {                     // emergency\n            bitset<MAXC> all;\n            for (int p = 0; p < N * N; p++) all.set(p);\n            do_guess(all);\n            return 0;\n        }\n\n        int undrilled = N * N - (int)drilled_cells.size();\n        if (undrilled <= 8 && ops + undrilled + 1 <= MAX_OPS) {\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) do_drill(p);\n            bitset<MAXC> exact;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            if (do_guess(exact)) return 0;\n            break;\n        }\n\n        vector<bitset<MAXC>> sol_unions;\n\n        int total_cand = 0;\n        for (int k = 0; k < M; k++) total_cand += (int)cand[k].count();\n\n        if (total_cand <= 4000) {\n            for (int trial = 0; trial < 2 && (int)sol_unions.size() < LIMIT_SOL; ++trial) {\n                DFSHelper h(cand, LIMIT_SOL - (int)sol_unions.size(), LIMIT_NODE);\n                h.run();\n                for (auto &s : h.sols) {\n                    bool seen = false;\n                    for (auto &u : sol_unions) if (u == s.uni) { seen = true; break; }\n                    if (!seen) sol_unions.push_back(s.uni);\n                }\n            }\n        }\n\n        if (sol_unions.empty()) {\n            int p = pick_random_undrilled();\n            if (p == -1) {\n                bitset<MAXC> all;\n                for (int c = 0; c < N * N; c++) all.set(c);\n                do_guess(all);\n                return 0;\n            }\n            do_drill(p);\n        } else {\n            bool agree = true;\n            for (size_t i = 1; i < sol_unions.size(); i++)\n                if (sol_unions[i] != sol_unions[0]) { agree = false; break; }\n\n            if (agree) {\n                if (do_guess(sol_unions[0])) return 0;\n                /* wrong guess \u2013 force one more drill */\n                int p = pick_random_undrilled();\n                if (p != -1) do_drill(p);\n            } else {\n                int S = (int)sol_unions.size();\n                vector<int> cnt(N * N, 0);\n                for (auto &u : sol_unions)\n                    for (int p = 0; p < N * N; p++) if (u.test(p)) ++cnt[p];\n\n                int best = -1, best_score = -1;\n                for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) {\n                    int score = min(cnt[p], S - cnt[p]);\n                    if (score > best_score) {\n                        best_score = score;\n                        best = p;\n                    }\n                }\n                if (best == -1) best = pick_random_undrilled();\n                do_drill(best);\n            }\n        }\n    }\n\n    /* final fallback */\n    bitset<MAXC> all;\n    for (int c = 0; c < N * N; c++) all.set(c);\n    do_guess(all);\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int x, y;   // top-left (y = row/i, x = col/j)\n    int w, h;   // width (horizontal), height (vertical)\n};\n\nstruct FRect {\n    int x, y, w, h;\n};\n\nstatic int W, D, N;\nstatic vector<vector<long long>> a;\n\nstatic bool intersect(const FRect& A, const FRect& B) {\n    return !(A.x + A.w <= B.x || B.x + B.w <= A.x ||\n             A.y + A.h <= B.y || B.y + B.h <= A.y);\n}\n\n/* ------------------------------------------------------------------ */\n/*  Maximal Rectangles greedy packer                                   */\n/* ------------------------------------------------------------------ */\nstatic vector<Rect> pack_areas(const vector<long long>& area, int maxTrial) {\n    int n = (int)area.size();\n    vector<Rect> best;\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    for (int trial = 0; trial < maxTrial; ++trial) {\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n\n        vector<pair<int,int>> dim(n);\n        for (int idx : ord) {\n            long long A = area[idx];\n            int w, h;\n            int mode = trial % 5;\n            if (mode == 0) {\n                w = max(1, (int)std::sqrt((double)A));\n                h = (int)((A + w - 1) / w);\n            } else if (mode == 1) {\n                h = max(1, (int)std::sqrt((double)A));\n                w = (int)((A + h - 1) / h);\n            } else if (mode == 2) {\n                w = (int)max(1LL, (A + W - 1) / W);\n                h = (int)((A + w - 1) / w);\n            } else if (mode == 3) {\n                h = (int)max(1LL, (A + W - 1) / W);\n                w = (int)((A + h - 1) / h);\n            } else {\n                long long lo = max(1LL, (A + W - 1) / W);\n                long long hi = min((long long)W, A);\n                if (lo >= hi) w = (int)lo;\n                else w = uniform_int_distribution<int>((int)lo, (int)hi)(rng);\n                h = (int)((A + w - 1) / w);\n            }\n            if (h > W) { h = W; w = (int)((A + h - 1) / h); }\n            if (w > W) { w = W; h = (int)((A + w - 1) / w); }\n            if (w < 1) w = 1;\n            if (h < 1) h = 1;\n            dim[idx] = {w, h};\n        }\n\n        vector<Rect> cur(n);\n        vector<FRect> freeList;\n        freeList.reserve(500);\n        freeList.push_back({0, 0, W, W});\n        bool ok = true;\n\n        for (int idx : ord) {\n            int w = dim[idx].first;\n            int h = dim[idx].second;\n            int bestPos = -1;\n            long long bestScore = (1LL<<60);\n            int bw = w, bh = h;\n\n            for (int i = 0; i < (int)freeList.size(); ++i) {\n                const FRect& f = freeList[i];\n                if (f.w >= w && f.h >= h) {\n                    long long sc = 1LL * (f.w - w) * (f.h - h);\n                    if (sc < bestScore) {\n                        bestScore = sc; bestPos = i; bw = w; bh = h;\n                    }\n                }\n                if (f.w >= h && f.h >= w) {\n                    long long sc = 1LL * (f.w - h) * (f.h - w);\n                    if (sc < bestScore) {\n                        bestScore = sc; bestPos = i; bw = h; bh = w;\n                    }\n                }\n            }\n            if (bestPos == -1) { ok = false; break; }\n\n            FRect fr = freeList[bestPos];\n            cur[idx] = {fr.x, fr.y, bw, bh};\n            freeList.erase(freeList.begin() + bestPos);\n\n            if (fr.w > bw) freeList.push_back({fr.x + bw, fr.y, fr.w - bw, fr.h});\n            if (fr.h > bh) freeList.push_back({fr.x, fr.y + bh, fr.w, fr.h - bh});\n\n            vector<FRect> nxt;\n            nxt.reserve(freeList.size() * 2);\n            for (auto& f : freeList) {\n                if (!intersect(f, {fr.x, fr.y, bw, bh})) {\n                    nxt.push_back(f);\n                    continue;\n                }\n                if (f.x >= fr.x && f.y >= fr.y &&\n                    f.x + f.w <= fr.x + bw && f.y + f.h <= fr.y + bh) continue;\n\n                if (fr.x > f.x) nxt.push_back({f.x, f.y, fr.x - f.x, f.h});\n                if (fr.x + bw < f.x + f.w)\n                    nxt.push_back({fr.x + bw, f.y, f.x + f.w - fr.x - bw, f.h});\n                if (fr.y > f.y) nxt.push_back({f.x, f.y, f.w, fr.y - f.y});\n                if (fr.y + bh < f.y + f.h)\n                    nxt.push_back({f.x, fr.y + bh, f.w, f.y + f.h - fr.y - bh});\n            }\n            freeList.swap(nxt);\n\n            vector<FRect> pruned;\n            for (auto& f : freeList) {\n                if (f.w <= 0 || f.h <= 0) continue;\n                bool inside = false;\n                for (auto& g : freeList) {\n                    if (&f == &g) continue;\n                    if (g.x <= f.x && g.y <= f.y &&\n                        g.x + g.w >= f.x + f.w && g.y + g.h >= f.y + f.h) {\n                        if (g.x < f.x || g.y < f.y ||\n                            g.x + g.w > f.x + f.w || g.y + g.h > f.y + f.h ||\n                            &g < &f) {\n                            inside = true; break;\n                        }\n                    }\n                }\n                if (!inside) pruned.push_back(f);\n            }\n            freeList.swap(pruned);\n        }\n\n        if (ok) return cur;\n    }\n    return {};\n}\n\n/* ------------------------------------------------------------------ */\n/*  Fallback shelf (guaranteed to fit, used only in last resort)       */\n/* ------------------------------------------------------------------ */\nstatic vector<Rect> shelf_fallback(const vector<long long>& area) {\n    int n = (int)area.size();\n    vector<Rect> res(n);\n    int x = 0, y = 0, shelf_h = 0;\n    for (int i = 0; i < n; ++i) {\n        long long A = area[i];\n        int w = max(1, (int)std::sqrt((double)A));\n        int h = (int)((A + w - 1) / w);\n        if (h > W) { h = W; w = (int)((A + h - 1) / h); }\n        if (w > W) { w = W; h = (int)((A + w - 1) / w); }\n\n        if (x + w > W) {\n            y += shelf_h;\n            x = 0;\n            shelf_h = 0;\n        }\n        if (y + h > W) {\n            w = W - x;\n            h = W - y;\n        }\n        res[i] = {x, y, w, h};\n        x += w;\n        shelf_h = max(shelf_h, h);\n    }\n    return res;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Main                                                               */\n/* ------------------------------------------------------------------ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> W >> D >> N)) return 0;\n    a.assign(D, vector<long long>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    vector<long long> b(N, 0);\n    for (int k = 0; k < N; ++k)\n        for (int d = 0; d < D; ++d)\n            b[k] = max(b[k], a[d][k]);\n\n    long long S = accumulate(b.begin(), b.end(), 0LL);\n\n    vector<vector<Rect>> ans(D, vector<Rect>(N));\n    bool fixed_used = false;\n    vector<Rect> fixed;\n\n    if (S <= 1LL * W * W) {\n        fixed = pack_areas(b, 2000);          // try hard to find a fixed packing\n    }\n\n    if (!fixed.empty()) {\n        for (int d = 0; d < D; ++d)\n            for (int k = 0; k < N; ++k)\n                ans[d][k] = fixed[k];\n        fixed_used = true;\n    }\n\n    if (!fixed_used) {\n        // ---- try vertical strip fallback ----\n        vector<long long> wmin(N);\n        long long sum_wmin = 0;\n        for (int k = 0; k < N; ++k) {\n            wmin[k] = max(1LL, (b[k] + W - 1) / W);\n            sum_wmin += wmin[k];\n        }\n\n        if (sum_wmin <= W) {\n            mt19937 rng(1234567);\n            vector<long long> best_w;\n            long long best_cost = (1LL<<60);\n\n            auto eval = [&](const vector<long long>& w)->long long {\n                vector<vector<int>> h(D, vector<int>(N));\n                for (int d = 0; d < D; ++d)\n                    for (int k = 0; k < N; ++k) {\n                        h[d][k] = (int)((a[d][k] + w[k] - 1) / w[k]);\n                        if (h[d][k] > W) h[d][k] = W;\n                    }\n                long long cost = 0;\n                for (int d = 1; d < D; ++d) {\n                    for (int k = 0; k < N; ++k) {\n                        bool e1 = (h[d-1][k] < W);\n                        bool e2 = (h[d][k] < W);\n                        if (e1 && e2 && h[d-1][k] != h[d][k]) cost += 2LL * w[k];\n                        else if (e1 != e2) cost += w[k];\n                    }\n                    for (int k = 0; k < N-1; ++k) {\n                        int M1 = max(h[d-1][k], h[d-1][k+1]);\n                        int M2 = max(h[d][k], h[d][k+1]);\n                        cost += abs(M2 - M1);\n                    }\n                    // last right edge touches boundary because we fill width W\n                }\n                return cost;\n            };\n\n            // deterministic base: proportional to b\n            for (int attempt = 0; attempt < 6000; ++attempt) {\n                vector<long long> w = wmin;\n                long long rem = W - sum_wmin;\n                if (attempt == 0) {\n                    // proportional to b\n                    for (int k = 0; k < N; ++k) {\n                        long long add = rem * b[k] / S;\n                        w[k] += add;\n                        rem -= add;\n                    }\n                    // distribute remainder to last items\n                    for (int k = N-1; k >= 0 && rem > 0; --k) {\n                        ++w[k]; --rem;\n                    }\n                } else {\n                    vector<int> ord(N);\n                    iota(ord.begin(), ord.end(), 0);\n                    shuffle(ord.begin(), ord.end(), rng);\n                    for (int i = 0; i < N && rem > 0; ++i) {\n                        long long give = (i == N-1) ? rem : (rng() % (rem + 1));\n                        w[ord[i]] += give;\n                        rem -= give;\n                    }\n                }\n                long long c = eval(w);\n                if (c < best_cost) {\n                    best_cost = c;\n                    best_w = w;\n                }\n            }\n\n            vector<long long> pref(N+1, 0);\n            for (int k = 0; k < N; ++k) pref[k+1] = pref[k] + best_w[k];\n            for (int d = 0; d < D; ++d)\n                for (int k = 0; k < N; ++k) {\n                    int h = (int)((a[d][k] + best_w[k] - 1) / best_w[k]);\n                    if (h > W) h = W;\n                    ans[d][k] = {(int)pref[k], 0, (int)best_w[k], h};\n                }\n        } else {\n            // ---- last resort: pack each day independently ----\n            for (int d = 0; d < D; ++d) {\n                auto v = pack_areas(a[d], 200);\n                if (v.empty()) v = shelf_fallback(a[d]);\n                for (int k = 0; k < N; ++k) ans[d][k] = v[k];\n            }\n        }\n    }\n\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const Rect& r = ans[d][k];\n            cout << r.y << ' ' << r.x << ' '\n                 << r.y + r.h << ' ' << r.x + r.w << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nconst int N = 9;\nconst int M = 20;\nconst int K = 81;\nconst int POS = (N - 2) * (N - 2);          // 49\nconst int TOTAL_OPS = M * POS;               // 980\nconst int CELLS = N * N;                     // 81\nconst int MOD = 998244353;\n\nstruct Operation {\n    uint8_t cell[9];\n    uint32_t val[9];\n};\n\nOperation ops[TOTAL_OPS];\nvector<int> overlap_list[TOTAL_OPS];         // ops whose 3x3 block overlaps\n\n// ---------------------------------------------------------------------\ninline ll delta_add(const uint32_t board[], int op_id) {\n    ll d = 0;\n    const auto &op = ops[op_id];\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[op.cell[i]];\n        uint32_t s = op.val[i];\n        if (v >= MOD - s) d += (ll)s - MOD;\n        else              d += s;\n    }\n    return d;\n}\n\ninline ll delta_remove(const uint32_t board[], int op_id) {\n    ll d = 0;\n    const auto &op = ops[op_id];\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[op.cell[i]];\n        uint32_t s = op.val[i];\n        if (v < s) d += (ll)MOD - s;\n        else       d -= s;\n    }\n    return d;\n}\n\ninline void apply_add(uint32_t board[], int op_id) {\n    const auto &op = ops[op_id];\n    for (int i = 0; i < 9; ++i) {\n        int c = op.cell[i];\n        uint32_t v = board[c] + op.val[i];\n        if (v >= MOD) v -= MOD;\n        board[c] = v;\n    }\n}\n\ninline void apply_remove(uint32_t board[], int op_id) {\n    const auto &op = ops[op_id];\n    for (int i = 0; i < 9; ++i) {\n        int c = op.cell[i];\n        uint32_t v = board[c];\n        uint32_t s = op.val[i];\n        if (v < s) v += MOD - s;\n        else       v -= s;\n        board[c] = v;\n    }\n}\n\n// ---------------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m, k;\n    if (!(cin >> n >> m >> k)) return 0;\n    \n    vector<uint32_t> init_board(CELLS);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            uint32_t x; cin >> x;\n            init_board[i * N + j] = x;\n        }\n    \n    vector<vector<vector<uint32_t>>> stamp(M, vector<vector<uint32_t>>(3, vector<uint32_t>(3)));\n    for (int s = 0; s < M; ++s)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamp[s][i][j];\n    \n    // precompute operations\n    int id = 0;\n    for (int s = 0; s < M; ++s)\n        for (int p = 0; p <= N - 3; ++p)\n            for (int q = 0; q <= N - 3; ++q) {\n                int idx = 0;\n                for (int di = 0; di < 3; ++di)\n                    for (int dj = 0; dj < 3; ++dj) {\n                        ops[id].cell[idx] = (p + di) * N + (q + dj);\n                        ops[id].val[idx] = stamp[s][di][dj];\n                        ++idx;\n                    }\n                ++id;\n            }\n    \n    // precompute overlap lists (based on positions only)\n    vector<int> pos_of(TOTAL_OPS);\n    for (int op = 0; op < TOTAL_OPS; ++op) {\n        int m_id = op / POS;\n        int rest = op % POS;\n        int p = rest / 7;\n        int q = rest % 7;\n        pos_of[op] = rest; // 0..48, ignoring stamp type\n    }\n    for (int u = 0; u < TOTAL_OPS; ++u) {\n        int pu = (pos_of[u] / 7);\n        int qu = (pos_of[u] % 7);\n        for (int v = 0; v < TOTAL_OPS; ++v) {\n            int pv = (pos_of[v] / 7);\n            int qv = (pos_of[v] % 7);\n            if (abs(pu - pv) <= 2 && abs(qu - qv) <= 2)\n                overlap_list[u].push_back(v);\n        }\n    }\n    \n    ll initial_score = 0;\n    for (int i = 0; i < CELLS; ++i) initial_score += init_board[i];\n    \n    ll best_score = initial_score;\n    vector<int> best_ops;\n    best_ops.reserve(K);\n    \n    auto start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.85;\n    \n    static bool is_overlap[TOTAL_OPS];\n    \n    auto solve_one = [&](int type, uint64_t seed) {\n        mt19937_64 rng(seed);\n        vector<uint32_t> board = init_board;\n        vector<int> cur_ops;\n        cur_ops.reserve(K);\n        ll score = initial_score;\n        \n        // ----- initial construction -----\n        if (type == 0) {                     // deterministic greedy\n            for (int step = 0; step < K; ++step) {\n                int best_op = -1;\n                ll best_d = 0;\n                for (int op = 0; op < TOTAL_OPS; ++op) {\n                    ll d = delta_add(board.data(), op);\n                    if (d > best_d) {\n                        best_d = d;\n                        best_op = op;\n                    }\n                }\n                if (best_op == -1) break;\n                apply_add(board.data(), best_op);\n                cur_ops.push_back(best_op);\n                score += best_d;\n            }\n        } else if (type == 1) {              // randomized greedy\n            for (int step = 0; step < K; ++step) {\n                vector<pair<ll,int>> cand;\n                cand.reserve(TOTAL_OPS);\n                for (int op = 0; op < TOTAL_OPS; ++op) {\n                    ll d = delta_add(board.data(), op);\n                    if (d > 0) cand.emplace_back(d, op);\n                }\n                if (cand.empty()) {\n                    if ((int)cur_ops.size() < K && (rng() & 1u)) {\n                        int op = (int)(rng() % TOTAL_OPS);\n                        ll d = delta_add(board.data(), op);\n                        apply_add(board.data(), op);\n                        cur_ops.push_back(op);\n                        score += d;\n                        continue;\n                    }\n                    break;\n                }\n                sort(cand.begin(), cand.end(),\n                     [](const auto& a, const auto& b){ return a.first > b.first; });\n                int top = min(5, (int)cand.size());\n                int idx = (int)(rng() % top);\n                int op = cand[idx].second;\n                ll d = cand[idx].first;\n                apply_add(board.data(), op);\n                cur_ops.push_back(op);\n                score += d;\n            }\n        } else if (type == 2) {              // random init\n            for (int step = 0; step < K; ++step) {\n                int op = (int)(rng() % TOTAL_OPS);\n                ll d = delta_add(board.data(), op);\n                apply_add(board.data(), op);\n                cur_ops.push_back(op);\n                score += d;\n            }\n        } else {                             // forced greedy (fill to K)\n            for (int step = 0; step < K; ++step) {\n                int best_op = 0;\n                ll best_d = LLONG_MIN;\n                for (int op = 0; op < TOTAL_OPS; ++op) {\n                    ll d = delta_add(board.data(), op);\n                    if (d > best_d) {\n                        best_d = d;\n                        best_op = op;\n                    }\n                }\n                apply_add(board.data(), best_op);\n                cur_ops.push_back(best_op);\n                score += best_d;\n            }\n        }\n        \n        // ----- local search -----\n        for (int iter = 0; iter < 40; ++iter) {\n            // precompute add deltas\n            ll add_d[TOTAL_OPS];\n            for (int op = 0; op < TOTAL_OPS; ++op)\n                add_d[op] = delta_add(board.data(), op);\n            \n            int order[TOTAL_OPS];\n            iota(order, order + TOTAL_OPS, 0);\n            sort(order, order + TOTAL_OPS,\n                 [&](int a, int b){ return add_d[a] > add_d[b]; });\n            \n            int best_type = -1; // 0 add, 1 remove, 2 swap\n            int best_u = -1, best_a = -1;\n            ll best_d = 0;\n            \n            // add\n            if ((int)cur_ops.size() < K) {\n                ll d = add_d[order[0]];\n                if (d > best_d) {\n                    best_d = d;\n                    best_type = 0;\n                    best_a = order[0];\n                }\n            }\n            \n            // remove\n            if (!cur_ops.empty()) {\n                int bidx = -1;\n                ll bd = 0;\n                for (int idx = 0; idx < (int)cur_ops.size(); ++idx) {\n                    ll d = delta_remove(board.data(), cur_ops[idx]);\n                    if (d > bd) {\n                        bd = d;\n                        bidx = idx;\n                    }\n                }\n                if (bd > best_d) {\n                    best_d = bd;\n                    best_type = 1;\n                    best_u = bidx;\n                }\n            }\n            \n            // swap\n            if (!cur_ops.empty()) {\n                for (int idx = 0; idx < (int)cur_ops.size(); ++idx) {\n                    int u = cur_ops[idx];\n                    ll d_rem = delta_remove(board.data(), u);\n                    apply_remove(board.data(), u);\n                    \n                    for (int op : overlap_list[u]) is_overlap[op] = true;\n                    \n                    int best_non_ov = -1;\n                    for (int j = 0; j < TOTAL_OPS; ++j) {\n                        int op = order[j];\n                        if (!is_overlap[op]) {\n                            best_non_ov = op;\n                            break;\n                        }\n                    }\n                    ll cand_d = add_d[best_non_ov];\n                    int cand_op = best_non_ov;\n                    \n                    for (int op : overlap_list[u]) {\n                        ll d = delta_add(board.data(), op);\n                        if (d > cand_d) {\n                            cand_d = d;\n                            cand_op = op;\n                        }\n                    }\n                    \n                    for (int op : overlap_list[u]) is_overlap[op] = false;\n                    \n                    ll total = d_rem + cand_d;\n                    if (total > best_d) {\n                        best_d = total;\n                        best_type = 2;\n                        best_u = idx;\n                        best_a = cand_op;\n                    }\n                    \n                    apply_add(board.data(), u);\n                }\n            }\n            \n            if (best_d <= 0) break;\n            \n            if (best_type == 0) {\n                apply_add(board.data(), best_a);\n                cur_ops.push_back(best_a);\n                score += best_d;\n            } else if (best_type == 1) {\n                int u = cur_ops[best_u];\n                apply_remove(board.data(), u);\n                cur_ops[best_u] = cur_ops.back();\n                cur_ops.pop_back();\n                score += best_d;\n            } else {\n                int u = cur_ops[best_u];\n                apply_remove(board.data(), u);\n                cur_ops[best_u] = cur_ops.back();\n                cur_ops.pop_back();\n                apply_add(board.data(), best_a);\n                cur_ops.push_back(best_a);\n                score += best_d;\n            }\n        }\n        \n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur_ops;\n        }\n    };\n    \n    // deterministic run\n    solve_one(0, 0);\n    \n    for (uint64_t seed = 1; ; ++seed) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > TIME_LIMIT) break;\n        int type;\n        uint64_t s = seed;\n        if (seed % 5 == 0) type = 2;       // random init\n        else if (seed % 7 == 0) type = 3;  // forced greedy\n        else type = 1;                     // randomized greedy\n        solve_one(type, s);\n    }\n    \n    cout << best_ops.size() << '\\n';\n    for (int op : best_ops) {\n        int m = op / POS;\n        int rest = op % POS;\n        int p = rest / 7;\n        int q = rest % 7;\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Mission {\n    int stage = -1;          // -1 none, 0 go pickup, 1 go drop\n    int pr = 0, pc = 0;      // pickup\n    int dr = 0, dc = 0;      // drop\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    int A[5][5];\n    for (int i = 0; i < 5; ++i)\n        for (int j = 0; j < 5; ++j)\n            cin >> A[i][j];\n\n    int grid[5][5];\n    memset(grid, -1, sizeof(grid));\n\n    int cr[5], cc[5];\n    int hold[5];\n    int dispatched[5];\n    int next_in[5];\n    for (int i = 0; i < 5; ++i) {\n        cr[i] = i; cc[i] = 0;\n        hold[i] = -1;\n        dispatched[i] = 0;\n        next_in[i] = 0;\n    }\n    cr[0] = 0; cc[0] = 0;   // large crane\n\n    Mission lc;\n    vector<string> ops(5);\n    const int MAX_TURN = 10000;\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        /* ---- step 1 : receiving ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (next_in[i] < 5 && grid[i][0] == -1) {\n                bool holding = false;\n                for (int k = 0; k < 5; ++k)\n                    if (cr[k] == i && cc[k] == 0 && hold[k] != -1)\n                        holding = true;\n                if (!holding) {\n                    grid[i][0] = A[i][next_in[i]++];\n                }\n            }\n        }\n\n        vector<char> act(5, '.');\n\n        /* ---- row cranes 1..4 ---- */\n        for (int k = 1; k < 5; ++k) {\n            int i = k;\n            int r = cr[k], c = cc[k];\n            int h = hold[k];\n            if (h == -1) {\n                if (r == i && c == 0) {\n                    act[k] = (grid[i][0] != -1) ? 'P' : '.';\n                } else if (r == i && c == 1) {\n                    act[k] = 'L';\n                } else {\n                    if (c > 0) act[k] = 'L';\n                    else if (r > i) act[k] = 'U';\n                    else if (r < i) act[k] = 'D';\n                    else act[k] = '.';\n                }\n            } else {\n                if (r == i && c == 0) {\n                    bool blocked = (grid[i][1] != -1) || (cr[0] == i && cc[0] == 1);\n                    act[k] = blocked ? '.' : 'R';\n                } else if (r == i && c == 1) {\n                    act[k] = 'Q';\n                } else {\n                    if (c < 1) act[k] = 'R';\n                    else if (c > 1) act[k] = 'L';\n                    else if (r > i) act[k] = 'U';\n                    else if (r < i) act[k] = 'D';\n                    else act[k] = '.';\n                }\n            }\n        }\n\n        /* ---- helper: next positions of row cranes ---- */\n        int ncr[5], ncc[5];\n        for (int k = 1; k < 5; ++k) {\n            ncr[k] = cr[k]; ncc[k] = cc[k];\n            char a = act[k];\n            if (a == 'U') --ncr[k];\n            else if (a == 'D') ++ncr[k];\n            else if (a == 'L') --ncc[k];\n            else if (a == 'R') ++ncc[k];\n        }\n\n        auto can_move_lc = [&](int r, int c, int nr, int nc) -> bool {\n            if (nr < 0 || nr >= 5 || nc < 0 || nc >= 5) return false;\n            for (int k = 1; k < 5; ++k)\n                if (ncr[k] == nr && ncc[k] == nc) return false;\n            for (int k = 1; k < 5; ++k)\n                if (cr[k] == nr && cc[k] == nc && ncr[k] == r && ncc[k] == c) return false;\n            return true;\n        };\n\n        auto find_buffer = [&]() -> pair<int,int> {\n            for (int c = 2; c <= 3; ++c)\n                for (int r = 0; r < 5; ++r)\n                    if (grid[r][c] == -1) return {r, c};\n            return {-1, -1};\n        };\n\n        auto move_lc_to = [&](int tr, int tc) -> char {\n            int r = cr[0], c = cc[0];\n            if (r == tr && c == tc) return '.';\n            vector<pair<int,int>> cand;\n            if (tc >= 2) {\n                if (r != tr) cand.emplace_back(r + (tr > r ? 1 : -1), c);\n                if (c != tc) cand.emplace_back(r, c + (tc > c ? 1 : -1));\n            } else if (tc == 1) {\n                if (c > 2) cand.emplace_back(r, c - 1);\n                else if (c == 2) {\n                    if (r != tr) cand.emplace_back(r + (tr > r ? 1 : -1), c);\n                    else cand.emplace_back(r, 1);\n                } else if (c < 2) {\n                    cand.emplace_back(r, c + 1);\n                }\n            } else { // tc == 0\n                if (c > 2) cand.emplace_back(r, c - 1);\n                else if (c == 2) cand.emplace_back(r, 1);\n                else if (c == 1) cand.emplace_back(r, 0);\n                else {\n                    if (r != tr) cand.emplace_back(r + (tr > r ? 1 : -1), c);\n                }\n            }\n            for (auto [nr, nc] : cand) {\n                if (can_move_lc(r, c, nr, nc)) {\n                    if (nr == r - 1) return 'U';\n                    if (nr == r + 1) return 'D';\n                    if (nc == c - 1) return 'L';\n                    if (nc == c + 1) return 'R';\n                }\n            }\n            return '.';\n        };\n\n        auto assign_lc = [&]() {\n            lc.stage = -1;\n            int best = 1e9;\n            // 1) deliver a needed container\n            for (int row = 0; row < 5; ++row) {\n                int need = 5 * row + dispatched[row];\n                if (need >= 5 * (row + 1)) continue;\n                vector<pair<int,int>> locs;\n                if (grid[0][0] == need) locs.emplace_back(0, 0);\n                for (int i = 1; i < 5; ++i)\n                    if (grid[i][1] == need) locs.emplace_back(i, 1);\n                for (int i = 0; i < 5; ++i)\n                    for (int j = 2; j <= 3; ++j)\n                        if (grid[i][j] == need) locs.emplace_back(i, j);\n                for (auto [pr, pc] : locs) {\n                    int d = abs(cr[0] - pr) + abs(cc[0] - pc);\n                    if (d < best) {\n                        best = d;\n                        lc = Mission{0, pr, pc, row, 4};\n                    }\n                }\n            }\n            if (lc.stage != -1) return;\n\n            // 2) fetch any dropoff container\n            vector<pair<int,int>> drops;\n            if (grid[0][0] != -1) drops.emplace_back(0, 0);\n            for (int i = 1; i < 5; ++i)\n                if (grid[i][1] != -1) drops.emplace_back(i, 1);\n\n            for (auto [pr, pc] : drops) {\n                int d = abs(cr[0] - pr) + abs(cc[0] - pc);\n                if (d < best) {\n                    best = d;\n                    int cont = grid[pr][pc];\n                    int row = cont / 5;\n                    int need = 5 * row + dispatched[row];\n                    if (cont == need) {\n                        lc = Mission{0, pr, pc, row, 4};\n                    } else {\n                        auto buf = find_buffer();\n                        if (buf.first != -1)\n                            lc = Mission{0, pr, pc, buf.first, buf.second};\n                    }\n                }\n            }\n        };\n\n        /* ---- large crane logic ---- */\n        if (lc.stage == -1) assign_lc();\n\n        if (lc.stage != -1) {\n            if (lc.stage == 0) {\n                if (cr[0] == lc.pr && cc[0] == lc.pc) {\n                    if (grid[cr[0]][cc[0]] == -1) {\n                        lc.stage = -1; // abort\n                        act[0] = '.';\n                    } else {\n                        int cont = grid[lc.pr][lc.pc];\n                        int row = cont / 5;\n                        int need = 5 * row + dispatched[row];\n                        if (cont == need) {\n                            lc.dr = row; lc.dc = 4;\n                        } else {\n                            auto buf = find_buffer();\n                            lc.dr = buf.first; lc.dc = buf.second;\n                        }\n                        lc.stage = 1;\n                        act[0] = 'P';\n                    }\n                } else {\n                    act[0] = move_lc_to(lc.pr, lc.pc);\n                }\n            } else if (lc.stage == 1) {\n                // recompute if container became needed while travelling\n                if (hold[0] != -1) {\n                    int row = hold[0] / 5;\n                    int need = 5 * row + dispatched[row];\n                    if (hold[0] == need) {\n                        lc.dr = row; lc.dc = 4;\n                    }\n                }\n                if (cr[0] == lc.dr && cc[0] == lc.dc) {\n                    if (grid[cr[0]][cc[0]] != -1) {\n                        act[0] = '.'; // wait until dispatch clears the square\n                    } else {\n                        lc.stage = -1;\n                        act[0] = 'Q';\n                    }\n                } else {\n                    act[0] = move_lc_to(lc.dr, lc.dc);\n                }\n            }\n        } else {\n            act[0] = '.';\n        }\n\n        /* ---- validate & apply ---- */\n        int nnr[5], nnc[5];\n        int nhold[5];\n        int ngrid[5][5];\n        memcpy(ngrid, grid, sizeof(grid));\n        for (int k = 0; k < 5; ++k) {\n            nnr[k] = cr[k]; nnc[k] = cc[k]; nhold[k] = hold[k];\n            char a = act[k];\n            if (a == 'U') --nnr[k];\n            else if (a == 'D') ++nnr[k];\n            else if (a == 'L') --nnc[k];\n            else if (a == 'R') ++nnc[k];\n        }\n\n        bool ok = true;\n        for (int k = 0; k < 5 && ok; ++k)\n            if (nnr[k] < 0 || nnr[k] >= 5 || nnc[k] < 0 || nnc[k] >= 5)\n                ok = false;\n\n        for (int k = 0; k < 5 && ok; ++k)\n            for (int l = k + 1; l < 5; ++l) {\n                if (nnr[k] == nnr[l] && nnc[k] == nnc[l]) ok = false;\n                if (cr[k] == nnr[l] && cc[k] == nnc[l] && cr[l] == nnr[k] && cc[l] == nnc[k]) ok = false;\n            }\n\n        for (int k = 0; k < 5 && ok; ++k) {\n            char a = act[k];\n            if (a == 'P') {\n                if (hold[k] != -1 || grid[cr[k]][cc[k]] == -1) ok = false;\n                nhold[k] = grid[cr[k]][cc[k]];\n                ngrid[cr[k]][cc[k]] = -1;\n            } else if (a == 'Q') {\n                if (hold[k] == -1 || grid[cr[k]][cc[k]] != -1) ok = false;\n                ngrid[cr[k]][cc[k]] = hold[k];\n                nhold[k] = -1;\n            } else if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                if (k > 0 && hold[k] != -1 && grid[nnr[k]][nnc[k]] != -1) ok = false;\n            }\n        }\n\n        if (!ok) {\n            // safety fallback: do nothing this turn\n            for (int k = 0; k < 5; ++k) {\n                nnr[k] = cr[k]; nnc[k] = cc[k]; nhold[k] = hold[k];\n                act[k] = '.';\n            }\n            memcpy(ngrid, grid, sizeof(grid));\n        }\n\n        for (int k = 0; k < 5; ++k) {\n            cr[k] = nnr[k]; cc[k] = nnc[k]; hold[k] = nhold[k];\n        }\n        memcpy(grid, ngrid, sizeof(grid));\n\n        /* ---- step 3 : dispatch ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (grid[i][4] != -1) {\n                ++dispatched[i];\n                grid[i][4] = -1;\n            }\n        }\n\n        for (int k = 0; k < 5; ++k) ops[k].push_back(act[k]);\n\n        bool done = true;\n        for (int i = 0; i < 5; ++i)\n            if (dispatched[i] < 5) done = false;\n        if (done) break;\n    }\n\n    size_t mx = 0;\n    for (auto &s : ops) mx = max(mx, s.size());\n    for (auto &s : ops) {\n        while (s.size() < mx) s.push_back('.');\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Result {\n    long long cost = 0;\n    vector<string> ops;\n    bool valid = false;\n};\n\n/* -------------------------------------------------------------\n   Helper: simulate a walk defined by `order`.\n   The truck starts at (0,0) and follows the cells in `order`.\n   After the walk it greedily visits remaining negative cells.\n   ------------------------------------------------------------- */\nResult solve_snake(const vector<vector<int>>& h,\n                   const vector<pair<int,int>>& order)\n{\n    int N = (int)h.size();\n    auto need = h;                 // remaining work: >0 must be loaded, <0 must be unloaded\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    int r = 0, c = 0;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n            }\n        }\n    };\n\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);                 // opportunistic load / unload\n        }\n    };\n\n    process(r, c);                         // (0,0)\n\n    for (auto [tr, tc] : order) {\n        move_to(tr, tc);\n        process(r, c);\n    }\n\n    /* remaining demands */\n    while (load > 0) {\n        int tr = -1, tc = -1, best = 1e9;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] < 0) {\n                    int d = abs(r - i) + abs(c - j);\n                    if (d < best || (d == best && (i < tr || (i == tr && j < tc)))) {\n                        best = d; tr = i; tc = j;\n                    }\n                }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n\n    if (ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* -------------------------------------------------------------\n   Greedy nearest neighbour.\n   Empty -> nearest source, Loaded -> nearest sink.\n   Opportunistic processing during every move.\n   ------------------------------------------------------------- */\nResult solve_greedy(const vector<vector<int>>& h)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    int r = 0, c = 0;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n            }\n        }\n    };\n\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n\n    process(r, c);                         // (0,0)\n\n    while (true) {\n        bool has_pos = false, has_neg = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j) {\n                if (need[i][j] > 0) has_pos = true;\n                if (need[i][j] < 0) has_neg = true;\n            }\n        if (!has_pos && load == 0) break;\n\n        if (load == 0) {\n            int tr = -1, tc = -1, best = 1e9;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best || (d == best && (i < tr || (i == tr && j < tc)))) {\n                            best = d; tr = i; tc = j;\n                        }\n                    }\n            if (tr == -1) break;          // should not happen\n            move_to(tr, tc);\n        } else {\n            int tr = -1, tc = -1, best = 1e9;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best || (d == best && (i < tr || (i == tr && j < tc)))) {\n                            best = d; tr = i; tc = j;\n                        }\n                    }\n            if (tr == -1) break;          // should not happen\n            move_to(tr, tc);\n        }\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n\n    if (ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* ------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    vector<Result> cand;\n\n    /* --- row forward --- */\n    vector<pair<int,int>> ord;\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0)\n            for (int j = 0; j < N; ++j)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n        else\n            for (int j = N - 1; j >= 0; --j)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n    }\n    cand.push_back(solve_snake(h, ord));\n\n    /* --- row backward --- */\n    ord.clear();\n    for (int i = N - 1; i >= 0; --i) {\n        if ((N - 1 - i) % 2 == 0)\n            for (int j = 0; j < N; ++j)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n        else\n            for (int j = N - 1; j >= 0; --j)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n    }\n    cand.push_back(solve_snake(h, ord));\n\n    /* --- column forward --- */\n    ord.clear();\n    for (int j = 0; j < N; ++j) {\n        if (j % 2 == 0)\n            for (int i = 0; i < N; ++i)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n        else\n            for (int i = N - 1; i >= 0; --i)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n    }\n    cand.push_back(solve_snake(h, ord));\n\n    /* --- column backward --- */\n    ord.clear();\n    for (int j = N - 1; j >= 0; --j) {\n        if ((N - 1 - j) % 2 == 0)\n            for (int i = 0; i < N; ++i)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n        else\n            for (int i = N - 1; i >= 0; --i)\n                if (i != 0 || j != 0) ord.emplace_back(i, j);\n    }\n    cand.push_back(solve_snake(h, ord));\n\n    /* --- greedy --- */\n    cand.push_back(solve_greedy(h));\n\n    /* pick the best valid candidate */\n    Result best;\n    best.valid = false;\n    best.cost = (1LL << 62);\n    for (auto &res : cand) {\n        if (res.valid && res.cost < best.cost) best = res;\n    }\n\n    if (!best.valid) best = solve_greedy(h);   // safety fallback\n\n    for (auto &s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 6;\n    constexpr int M = 15;\n    constexpr int SEED_CNT = 2 * N * (N - 1); // 60\n    constexpr int PLANT = N * N;               // 36\n\n    // ----- pre\u2011compute grid topology -----\n    array<array<int, 4>, PLANT> nbr{};\n    array<int, PLANT> nbr_cnt{};\n    array<int, PLANT> deg{};\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            int k = 0;\n            if (r > 0)     nbr[id][k++] = (r - 1) * N + c;\n            if (r < N - 1) nbr[id][k++] = (r + 1) * N + c;\n            if (c > 0)     nbr[id][k++] = r * N + (c - 1);\n            if (c < N - 1) nbr[id][k++] = r * N + (c + 1);\n            nbr_cnt[id] = k;\n            deg[id] = k;\n        }\n    }\n\n    int N_in, M_in, T;\n    // The judge feeds multiple test cases sequentially; stop at EOF.\n    while (cin >> N_in >> M_in >> T) {\n        array<array<int, M>, SEED_CNT> seeds{};\n        for (int i = 0; i < SEED_CNT; ++i)\n            for (int j = 0; j < M; ++j)\n                cin >> seeds[i][j];\n\n        for (int turn = 0; turn < T; ++turn) {\n            // ---- 1. values and current per\u2011coordinate maxima ----\n            array<int, SEED_CNT> V{};\n            array<int, M> cur_max{};\n            cur_max.fill(0);\n            for (int i = 0; i < SEED_CNT; ++i) {\n                int s = 0;\n                for (int j = 0; j < M; ++j) {\n                    s += seeds[i][j];\n                    if (seeds[i][j] > cur_max[j]) cur_max[j] = seeds[i][j];\n                }\n                V[i] = s;\n            }\n\n            array<int, M> cnt_max{};\n            cnt_max.fill(0);\n            for (int i = 0; i < SEED_CNT; ++i)\n                for (int j = 0; j < M; ++j)\n                    if (seeds[i][j] == cur_max[j]) ++cnt_max[j];\n\n            array<bool, SEED_CNT> forced{};\n            forced.fill(false);\n            for (int i = 0; i < SEED_CNT; ++i) {\n                for (int j = 0; j < M; ++j) {\n                    if (seeds[i][j] == cur_max[j] && cnt_max[j] == 1) {\n                        forced[i] = true;\n                        break;\n                    }\n                }\n            }\n\n            // ---- 2. select 36 seeds ----\n            vector<int> selected;\n            selected.reserve(PLANT);\n            vector<pair<int,int>> cand; // (V, id)\n            for (int i = 0; i < SEED_CNT; ++i) {\n                if (forced[i]) selected.push_back(i);\n                else cand.emplace_back(V[i], i);\n            }\n            sort(cand.begin(), cand.end(),\n                 [](const auto& a, const auto& b){ return a.first > b.first; });\n            int need = PLANT - (int)selected.size();\n            for (int i = 0; i < need; ++i) selected.push_back(cand[i].second);\n\n            // copy selected data for fast access\n            int sel_val[PLANT];\n            int sel_id[PLANT];\n            int sel_vec[PLANT][M];\n            for (int i = 0; i < PLANT; ++i) {\n                int sid = selected[i];\n                sel_id[i] = sid;\n                sel_val[i] = V[sid];\n                for (int j = 0; j < M; ++j) sel_vec[i][j] = seeds[sid][j];\n            }\n\n            // ---- 3. potential matrix ----\n            static int pot[PLANT][PLANT];\n            for (int i = 0; i < PLANT; ++i) {\n                for (int j = i + 1; j < PLANT; ++j) {\n                    int s = 0;\n                    for (int l = 0; l < M; ++l)\n                        s += max(sel_vec[i][l], sel_vec[j][l]);\n                    pot[i][j] = pot[j][i] = s;\n                }\n            }\n\n            // ---- 4. initial placement (degree desc \u00d7 value desc) ----\n            array<int, PLANT> pos2idx; // cell -> index in selected[]\n            {\n                vector<int> cells(PLANT), idxs(PLANT);\n                iota(cells.begin(), cells.end(), 0);\n                iota(idxs.begin(), idxs.end(), 0);\n                sort(cells.begin(), cells.end(),\n                     [&](int a, int b){ return deg[a] > deg[b]; });\n                sort(idxs.begin(), idxs.end(),\n                     [&](int a, int b){ return sel_val[a] > sel_val[b]; });\n                for (int i = 0; i < PLANT; ++i) pos2idx[cells[i]] = idxs[i];\n            }\n\n            // ---- 5. local search (hill climbing) ----\n            for (int pass = 0; pass < 200; ++pass) {\n                int best_delta = 0;\n                int best_u = -1, best_v = -1;\n                for (int u = 0; u < PLANT; ++u) {\n                    int iu = pos2idx[u];\n                    for (int v = u + 1; v < PLANT; ++v) {\n                        int iv = pos2idx[v];\n                        int delta = 0;\n                        for (int k = 0; k < nbr_cnt[u]; ++k) {\n                            int w = nbr[u][k];\n                            if (w == v) continue;\n                            int iw = pos2idx[w];\n                            delta += pot[iv][iw] - pot[iu][iw];\n                        }\n                        for (int k = 0; k < nbr_cnt[v]; ++k) {\n                            int w = nbr[v][k];\n                            if (w == u) continue;\n                            int iw = pos2idx[w];\n                            delta += pot[iu][iw] - pot[iv][iw];\n                        }\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_u = u;\n                            best_v = v;\n                        }\n                    }\n                }\n                if (best_delta > 0) {\n                    swap(pos2idx[best_u], pos2idx[best_v]);\n                } else {\n                    break;\n                }\n            }\n\n            // ---- 6. output ----\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (c) cout << ' ';\n                    int cell = r * N + c;\n                    cout << sel_id[pos2idx[cell]];\n                }\n                cout << '\\n';\n            }\n            cout.flush();\n\n            // ---- 7. read next generation ----\n            for (int i = 0; i < SEED_CNT; ++i)\n                for (int j = 0; j < M; ++j)\n                    cin >> seeds[i][j];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<vector<char>> has_source, need_target;\nvector<int> len;                     // edge length of each vertex\nvector<int> cur_dir;                 // absolute direction of edge (parent -> i)\nvector<char> is_holding;\nint cur_r, cur_c;\nvector<string> ans;\nint holding_cnt = 0;\nint rem_source_cnt = 0;\nint rem_target_cnt = 0;\n\n// 0:right, 1:down, 2:left, 3:up   (dr,dc correspond to (row,col))\nconst int dr[4] = {0, 1, 0, -1};\nconst int dc[4] = {1, 0, -1, 0};\n\ninline int rot_steps(int a, int b) {\n    int d = abs(a - b);\n    return min(d, 4 - d);\n}\ninline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\n/*------------------------------------------------------------*/\n/*  bipartite matching for a fixed root cell (r,c)            */\n/*------------------------------------------------------------*/\nint compute_matching(int r, int c, const vector<int>& active, bool is_pickup,\n                     vector<int>& out_dir, vector<pair<int,int>>& out_cell,\n                     bool fill_assignment) {\n    int k = (int)active.size();\n    vector<vector<pair<int,int>>> edges(k);          // (cell_id, dir)\n    for (int idx = 0; idx < k; ++idx) {\n        int i = active[idx];\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d] * len[i];\n            int nc = c + dc[d] * len[i];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (is_pickup ? has_source[nr][nc] : need_target[nr][nc]) {\n                edges[idx].push_back({nr * N + nc, d});\n            }\n        }\n    }\n\n    // maximum matching size on the whole graph\n    vector<int> matchR(N * N, -1);\n    vector<char> seen(N * N);\n    function<bool(int)> dfs = [&](int idx) -> bool {\n        for (auto [cid, d] : edges[idx]) {\n            if (seen[cid]) continue;\n            seen[cid] = 1;\n            if (matchR[cid] == -1 || dfs(matchR[cid])) {\n                matchR[cid] = idx;\n                return true;\n            }\n        }\n        return false;\n    };\n    int overall_max = 0;\n    for (int idx = 0; idx < k; ++idx) {\n        fill(seen.begin(), seen.end(), 0);\n        if (dfs(idx)) ++overall_max;\n    }\n\n    if (overall_max == 0) {\n        if (fill_assignment) {\n            fill(out_dir.begin(), out_dir.end(), -1);\n            fill(out_cell.begin(), out_cell.end(), make_pair(-1, -1));\n        }\n        return 0;\n    }\n\n    // smallest rotation limit that still yields overall_max\n    for (int limit = 0; limit <= 2; ++limit) {\n        vector<vector<pair<int,int>>> lim_edges(k);\n        for (int idx = 0; idx < k; ++idx) {\n            int i = active[idx];\n            for (auto [cid, d] : edges[idx]) {\n                if (rot_steps(cur_dir[i], d) <= limit)\n                    lim_edges[idx].push_back({cid, d});\n            }\n        }\n        fill(matchR.begin(), matchR.end(), -1);\n        vector<int> match_dir(N * N, -1);\n        function<bool(int)> dfs2 = [&](int idx) -> bool {\n            for (auto [cid, d] : lim_edges[idx]) {\n                if (seen[cid]) continue;\n                seen[cid] = 1;\n                if (matchR[cid] == -1 || dfs2(matchR[cid])) {\n                    matchR[cid] = idx;\n                    match_dir[cid] = d;\n                    return true;\n                }\n            }\n            return false;\n        };\n        int sz = 0;\n        for (int idx = 0; idx < k; ++idx) {\n            fill(seen.begin(), seen.end(), 0);\n            if (dfs2(idx)) ++sz;\n        }\n        if (sz == overall_max) {\n            if (fill_assignment) {\n                fill(out_dir.begin(), out_dir.end(), -1);\n                fill(out_cell.begin(), out_cell.end(), make_pair(-1, -1));\n                for (int cid = 0; cid < N * N; ++cid) if (matchR[cid] != -1) {\n                    int idx = matchR[cid];\n                    int i   = active[idx];\n                    int d   = match_dir[cid];\n                    out_dir[i] = d;\n                    out_cell[i] = {cid / N, cid % N};\n                }\n            }\n            return sz;\n        }\n    }\n    return overall_max;   // never reached\n}\n\n/*------------------------------------------------------------*/\n/*  best batch for a set of active fingertips                 */\n/*------------------------------------------------------------*/\nstruct Batch {\n    int size = 0, dist = 0;\n    int r = -1, c = -1;\n    vector<int> assign_dir;\n    vector<pair<int,int>> assign_cell;\n};\n\nBatch find_batch(const vector<int>& active, bool is_pickup) {\n    Batch best;\n    best.assign_dir.assign(V, -1);\n    best.assign_cell.assign(V, {-1, -1});\n    int best_size = -1;\n    int best_dist = 1e9;\n\n    vector<int> tmp_dir(V);\n    vector<pair<int,int>> tmp_cell(V);\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int sz = compute_matching(r, c, active, is_pickup,\n                                      tmp_dir, tmp_cell, true);\n            if (sz == 0) continue;\n            int d = manhattan(cur_r, cur_c, r, c);\n            if (sz > best_size || (sz == best_size && d < best_dist)) {\n                best_size = sz;\n                best_dist = d;\n                best.size = sz;\n                best.dist = d;\n                best.r = r;  best.c = c;\n                best.assign_dir = tmp_dir;\n                best.assign_cell = tmp_cell;\n            }\n        }\n    }\n    return best;\n}\n\n/*------------------------------------------------------------*/\n/*  physically execute one batch                              */\n/*------------------------------------------------------------*/\nvoid execute_batch(const Batch& batch, bool is_pickup) {\n    if (batch.size <= 0) return;\n\n    vector<int> matched;\n    for (int i = 1; i < V; ++i)\n        if (batch.assign_dir[i] != -1) matched.push_back(i);\n\n    int max_rot = 0;\n    for (int i : matched)\n        max_rot = max(max_rot, rot_steps(cur_dir[i], batch.assign_dir[i]));\n\n    int dist = manhattan(cur_r, cur_c, batch.r, batch.c);\n    int travel = max(dist, max_rot);\n\n    for (int step = 0; step < travel; ++step) {\n        char move = '.';\n        if (cur_r < batch.r)       { move = 'D'; ++cur_r; }\n        else if (cur_r > batch.r)  { move = 'U'; --cur_r; }\n        else if (cur_c < batch.c)  { move = 'R'; ++cur_c; }\n        else if (cur_c > batch.c)  { move = 'L'; --cur_c; }\n\n        string S(2 * V, '.');\n        S[0] = move;\n\n        for (int i : matched) {\n            if (cur_dir[i] == batch.assign_dir[i]) continue;\n            int diff = (batch.assign_dir[i] - cur_dir[i] + 4) % 4;\n            if (diff == 1) {\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            } else if (diff == 3) {\n                S[i] = 'L';\n                cur_dir[i] = (cur_dir[i] + 3) & 3;\n            } else { // diff == 2\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            }\n        }\n\n        if (step == travel - 1) {\n            for (int i : matched) {\n                S[V + i] = 'P';\n                auto [cr, cc] = batch.assign_cell[i];\n                if (is_pickup) {\n                    has_source[cr][cc] = 0;\n                    is_holding[i] = 1;\n                    ++holding_cnt;\n                    --rem_source_cnt;\n                } else {\n                    need_target[cr][cc] = 0;\n                    is_holding[i] = 0;\n                    --holding_cnt;\n                    --rem_target_cnt;\n                }\n            }\n        }\n        ans.push_back(S);\n    }\n}\n\n/*------------------------------------------------------------*/\n/*  main                                                       */\n/*------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n    for (int i = 0; i < N; ++i) cin >> t[i];\n\n    has_source.assign(N, vector<char>(N, 0));\n    need_target.assign(N, vector<char>(N, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s[i][j] == '1' && t[i][j] == '1') {\n                // already satisfied\n            } else if (s[i][j] == '1') {\n                has_source[i][j] = 1;\n                ++rem_source_cnt;\n            } else if (t[i][j] == '1') {\n                need_target[i][j] = 1;\n                ++rem_target_cnt;\n            }\n        }\n    }\n\n    /*--- design the arm (star) ---*/\n    cout << V << '\\n';\n    len.assign(V, 0);\n    for (int u = 1; u < V; ++u) {\n        int L = u;\n        if (L > N - 1) L = N - 1;\n        len[u] = L;\n        cout << 0 << ' ' << L << '\\n';\n    }\n    cur_r = N / 2;\n    cur_c = N / 2;\n    cout << cur_r << ' ' << cur_c << '\\n';\n\n    cur_dir.assign(V, 0);\n    is_holding.assign(V, 0);\n\n    /*--- main greedy loop ---*/\n    while (rem_source_cnt > 0 || holding_cnt > 0) {\n        vector<int> free_active, hold_active;\n        for (int i = 1; i < V; ++i) {\n            if (is_holding[i]) hold_active.push_back(i);\n            else               free_active.push_back(i);\n        }\n\n        Batch pick = find_batch(free_active, true);\n        Batch del  = find_batch(hold_active, false);\n\n        bool do_pick;\n        if (del.size == 0) do_pick = true;\n        else if (pick.size == 0) do_pick = false;\n        else if (pick.size > del.size) do_pick = true;\n        else if (pick.size < del.size) do_pick = false;\n        else do_pick = (pick.dist <= del.dist);\n\n        if (do_pick) {\n            if (pick.size == 0) {          // emergency (should not happen)\n                int tr = -1, tc = -1, best = 1e9;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        if (has_source[i][j]) {\n                            int d = manhattan(cur_r, cur_c, i, j);\n                            if (d < best) { best = d; tr = i; tc = j; }\n                        }\n                if (tr != -1) {\n                    char move = '.';\n                    if (cur_r < tr) { move = 'D'; ++cur_r; }\n                    else if (cur_r > tr) { move = 'U'; --cur_r; }\n                    else if (cur_c < tc) { move = 'R'; ++cur_c; }\n                    else if (cur_c > tc) { move = 'L'; --cur_c; }\n                    string S(2 * V, '.');\n                    S[0] = move;\n                    ans.push_back(S);\n                }\n            } else {\n                execute_batch(pick, true);\n            }\n        } else {\n            if (del.size == 0) {           // emergency (should not happen)\n                int tr = -1, tc = -1, best = 1e9;\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        if (need_target[i][j]) {\n                            int d = manhattan(cur_r, cur_c, i, j);\n                            if (d < best) { best = d; tr = i; tc = j; }\n                        }\n                if (tr != -1) {\n                    char move = '.';\n                    if (cur_r < tr) { move = 'D'; ++cur_r; }\n                    else if (cur_r > tr) { move = 'U'; --cur_r; }\n                    else if (cur_c < tc) { move = 'R'; ++cur_c; }\n                    else if (cur_c > tc) { move = 'L'; --cur_c; }\n                    string S(2 * V, '.');\n                    S[0] = move;\n                    ans.push_back(S);\n                }\n            } else {\n                execute_batch(del, false);\n            }\n        }\n    }\n\n    for (const string& s : ans) cout << s << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    int w; // +1 = mackerel, -1 = sardine\n};\n\nstruct Rect {\n    int x1, y1, x2, y2; // inclusive\n    int perimeter() const {\n        return 2 * ((x2 - x1) + (y2 - y1));\n    }\n};\n\n/*------------------------------------------------------------*/\n/*  segment tree for max sub\u2011array (non\u2011empty) with point add */\nstruct SegTree {\n    int n = 0, sz = 0;\n    vector<int> sum, pref, suff, ans;\n    vector<int> base;\n    void init(int n_) {\n        n = n_;\n        sz = 1;\n        while (sz < n) sz <<= 1;\n        sum.assign(2 * sz, 0);\n        pref.assign(2 * sz, 0);\n        suff.assign(2 * sz, 0);\n        ans.assign(2 * sz, 0);\n        base.assign(n, 0);\n    }\n    void clear() {\n        fill(base.begin(), base.end(), 0);\n        fill(sum.begin(), sum.end(), 0);\n        fill(pref.begin(), pref.end(), 0);\n        fill(suff.begin(), suff.end(), 0);\n        fill(ans.begin(), ans.end(), 0);\n    }\n    inline void pull(int idx) {\n        int l = idx << 1;\n        int r = l | 1;\n        sum[idx] = sum[l] + sum[r];\n        pref[idx] = max(pref[l], sum[l] + pref[r]);\n        suff[idx] = max(suff[r], sum[r] + suff[l]);\n        ans[idx] = max({ans[l], ans[r], suff[l] + pref[r]});\n    }\n    void add(int pos, int delta) {\n        base[pos] += delta;\n        int idx = pos + sz;\n        sum[idx] = pref[idx] = suff[idx] = ans[idx] = base[pos];\n        for (idx >>= 1; idx; idx >>= 1) pull(idx);\n    }\n    int query() const { return ans[1]; }\n};\n\n/*------------------------------------------------------------*/\n/*  exact best rectangle on a subset of points                */\nRect solve_exact(const vector<Point> &sub, int &best_score) {\n    best_score = 0;\n    if (sub.empty()) return {0, 0, 0, 0};\n\n    vector<int> xs, ys;\n    xs.reserve(sub.size());\n    ys.reserve(sub.size());\n    for (auto &p : sub) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    int X = (int)xs.size();\n    int Y = (int)ys.size();\n    vector<vector<pair<int,int>>> rows(Y);\n    for (auto &p : sub) {\n        int cx = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int cy = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        rows[cy].push_back({cx, p.w});\n    }\n\n    SegTree st;\n    st.init(X);\n    int best_val = 0;\n    int best_i = -1, best_j = -1;\n\n    for (int i = 0; i < Y; ++i) {\n        st.clear();\n        for (int j = i; j < Y; ++j) {\n            for (auto &pw : rows[j]) st.add(pw.first, pw.second);\n            int cur = st.query();\n            if (cur > best_val) {\n                best_val = cur;\n                best_i = i;\n                best_j = j;\n            }\n        }\n    }\n\n    if (best_val <= 0) {\n        return {0, 0, 0, 0}; // nothing positive in this subset\n    }\n\n    // recover x interval by a linear Kadane pass\n    vector<int> arr(X, 0);\n    for (int j = best_i; j <= best_j; ++j)\n        for (auto &pw : rows[j])\n            arr[pw.first] += pw.second;\n\n    int cur_sum = arr[0], cur_l = 0;\n    int best_sum = arr[0], best_l = 0, best_r = 0;\n    for (int r = 1; r < X; ++r) {\n        if (cur_sum + arr[r] < arr[r]) {\n            cur_sum = arr[r];\n            cur_l = r;\n        } else {\n            cur_sum += arr[r];\n        }\n        if (cur_sum > best_sum) {\n            best_sum = cur_sum;\n            best_l = cur_l;\n            best_r = r;\n        }\n    }\n\n    best_score = best_val;\n    return {xs[best_l], ys[best_i], xs[best_r], ys[best_j]};\n}\n\n/*------------------------------------------------------------*/\n/*  grid seeding                                               */\nusing Seed = tuple<int,int,int,int,int>; // S, gy1, gy2, gx1, gx2\n\nvector<Seed> grid_search(const vector<Point> &pts, int S, int K) {\n    const int MAXC = 100000;\n    int G = (MAXC + S) / S;\n    if (G > 400) G = 400;\n    vector<vector<int>> grid(G, vector<int>(G, 0));\n    for (auto &p : pts) {\n        int cx = min(p.x / S, G - 1);\n        int cy = min(p.y / S, G - 1);\n        grid[cy][cx] += p.w;\n    }\n\n    using Item = tuple<int,int,int,int,int>; // val, y1, y2, x1, x2\n    priority_queue<Item, vector<Item>, greater<Item>> pq;\n\n    for (int y1 = 0; y1 < G; ++y1) {\n        vector<int> col(G, 0);\n        for (int y2 = y1; y2 < G; ++y2) {\n            for (int x = 0; x < G; ++x) col[x] += grid[y2][x];\n\n            // Kadane (non\u2011empty)\n            int cur = col[0], cur_l = 0;\n            int best = col[0], best_l = 0, best_r = 0;\n            for (int x = 1; x < G; ++x) {\n                if (cur + col[x] < col[x]) {\n                    cur = col[x];\n                    cur_l = x;\n                } else {\n                    cur += col[x];\n                }\n                if (cur > best) {\n                    best = cur;\n                    best_l = cur_l;\n                    best_r = x;\n                }\n            }\n\n            if ((int)pq.size() < K) {\n                pq.emplace(best, y1, y2, best_l, best_r);\n            } else if (best > get<0>(pq.top())) {\n                pq.pop();\n                pq.emplace(best, y1, y2, best_l, best_r);\n            }\n        }\n    }\n\n    vector<Seed> res;\n    while (!pq.empty()) {\n        auto t = pq.top(); pq.pop();\n        int val, y1, y2, x1, x2;\n        tie(val, y1, y2, x1, x2) = t;\n        res.emplace_back(S, y1, y2, x1, x2);\n    }\n    return res;\n}\n\n/*------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<Point> pts;\n    pts.reserve(2 * N);\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, +1});\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, -1});\n    }\n\n    // try to find a tiny empty rectangle as safe fallback\n    Rect best_rect{0, 0, 0, 0};\n    int best_score = 0;          // a - b\n    int best_a = 0, best_b = 0;\n\n    auto consider = [&](const Rect &r) {\n        int a = 0, b = 0;\n        for (auto &p : pts) {\n            if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) {\n                if (p.w == 1) ++a; else ++b;\n            }\n        }\n        int sc = a - b;\n        if (sc > best_score || (sc == best_score && r.perimeter() < best_rect.perimeter())) {\n            best_score = sc;\n            best_rect = r;\n            best_a = a;\n            best_b = b;\n        }\n    };\n\n    // safe default: random tiny empty rectangle\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    for (int attempt = 0; attempt < 20000; ++attempt) {\n        int x = uniform_int_distribution<int>(0, 99998)(rng);\n        int y = uniform_int_distribution<int>(0, 99998)(rng);\n        Rect r{x, y, x + 1, y + 1};\n        bool ok = true;\n        for (auto &p : pts) {\n            if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) {\n                ok = false; break;\n            }\n        }\n        if (ok) {\n            consider(r);\n            break;\n        }\n    }\n\n    // collect seeds from two scales\n    vector<Seed> seeds;\n    for (int S : {500, 1000}) {\n        auto v = grid_search(pts, S, 10);\n        seeds.insert(seeds.end(), v.begin(), v.end());\n    }\n\n    const int MAXC = 100000;\n    for (auto &sd : seeds) {\n        int S, gy1, gy2, gx1, gx2;\n        tie(S, gy1, gy2, gx1, gx2) = sd;\n        int margin = S * 4;\n        int wx1 = max(0, gx1 * S - margin);\n        int wx2 = min(MAXC, (gx2 + 1) * S + margin);\n        int wy1 = max(0, gy1 * S - margin);\n        int wy2 = min(MAXC, (gy2 + 1) * S + margin);\n\n        vector<Point> sub;\n        sub.reserve(pts.size());\n        for (auto &p : pts) {\n            if (p.x >= wx1 && p.x <= wx2 && p.y >= wy1 && p.y <= wy2)\n                sub.push_back(p);\n        }\n\n        int sc;\n        Rect r = solve_exact(sub, sc);\n        if (sc > 0) consider(r);\n    }\n\n    // output the rectangle as a polygon (counter\u2011clockwise)\n    cout << 4 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y2 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y2 << \"\\n\";\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    long long x, y, w, h;\n};\n\nstruct Seq {\n    vector<int> r;\n    vector<char> d;\n    vector<int> b;\n};\n\nint N, T;\nlong long sigma;\nvector<long long> Wobs, Hobs;          // observed (noisy) sizes\n\n/*------------------------------------------------------------*/\n/*  simulate a fixed sequence, filling rects[start..N-1]      */\nlong long simulate_fixed(const Seq& seq, vector<Rect>& rects, int start = 0) {\n    long long W = 0, H = 0;\n    if (start > 0) {\n        for (int j = 0; j < start; ++j) {\n            W = max(W, rects[j].x + rects[j].w);\n            H = max(H, rects[j].y + rects[j].h);\n        }\n    }\n    for (int i = start; i < N; ++i) {\n        long long wi = seq.r[i] ? Hobs[i] : Wobs[i];\n        long long hi = seq.r[i] ? Wobs[i] : Hobs[i];\n        long long x, y;\n        if (seq.d[i] == 'U') {\n            x = (seq.b[i] == -1) ? 0LL : rects[seq.b[i]].x + rects[seq.b[i]].w;\n            y = 0;\n            for (int j = 0; j < i; ++j) {\n                if (x < rects[j].x + rects[j].w && rects[j].x < x + wi)\n                    y = max(y, rects[j].y + rects[j].h);\n            }\n        } else {\n            y = (seq.b[i] == -1) ? 0LL : rects[seq.b[i]].y + rects[seq.b[i]].h;\n            x = 0;\n            for (int j = 0; j < i; ++j) {\n                if (y < rects[j].y + rects[j].h && rects[j].y < y + hi)\n                    x = max(x, rects[j].x + rects[j].w);\n            }\n        }\n        rects[i] = {x, y, wi, hi};\n        W = max(W, x + wi);\n        H = max(H, y + hi);\n    }\n    return W + H;\n}\n\n/*------------------------------------------------------------*/\n/*  greedy construction / rebuild from position `start`        */\nlong long build_greedy(Seq& seq, vector<Rect>& rects,\n                       int objective, bool stochastic,\n                       mt19937& rng, int start = 0) {\n    long long W = 0, H = 0;\n    if (start > 0) {\n        for (int j = 0; j < start; ++j) {\n            W = max(W, rects[j].x + rects[j].w);\n            H = max(H, rects[j].y + rects[j].h);\n        }\n    }\n\n    struct Cand {\n        int r; char d; int b;\n        long long x, y, w, h, score;\n    };\n\n    for (int i = start; i < N; ++i) {\n        Cand cands[404];\n        int cand_cnt = 0;\n        for (int rot = 0; rot < 2; ++rot) {\n            long long wi = rot ? Hobs[i] : Wobs[i];\n            long long hi = rot ? Wobs[i] : Hobs[i];\n            for (int di = 0; di < 2; ++di) {\n                char d = di ? 'L' : 'U';\n                for (int bval = -1; bval < i; ++bval) {\n                    long long x, y;\n                    if (d == 'U') {\n                        x = (bval == -1) ? 0LL : rects[bval].x + rects[bval].w;\n                        y = 0;\n                        for (int j = 0; j < i; ++j) {\n                            if (x < rects[j].x + rects[j].w && rects[j].x < x + wi)\n                                y = max(y, rects[j].y + rects[j].h);\n                        }\n                    } else {\n                        y = (bval == -1) ? 0LL : rects[bval].y + rects[bval].h;\n                        x = 0;\n                        for (int j = 0; j < i; ++j) {\n                            if (y < rects[j].y + rects[j].h && rects[j].y < y + hi)\n                                x = max(x, rects[j].x + rects[j].w);\n                        }\n                    }\n                    long long nW = max(W, x + wi);\n                    long long nH = max(H, y + hi);\n                    long long score;\n                    if (objective == 0) score = nW + nH;\n                    else if (objective == 1) score = max(nW, nH);\n                    else if (objective == 2) score = nW * nH;\n                    else score = nW + nH + (nW > nH ? nW - nH : nH - nW) / 10;\n                    cands[cand_cnt++] = {rot, d, bval, x, y, wi, hi, score};\n                }\n            }\n        }\n\n        long long best_score = cands[0].score;\n        for (int k = 1; k < cand_cnt; ++k)\n            if (cands[k].score < best_score) best_score = cands[k].score;\n\n        int idx = 0;\n        if (stochastic) {\n            long long thr = best_score + max(1LL, best_score / 50);\n            int good[404], gcnt = 0;\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].score <= thr) good[gcnt++] = k;\n            idx = good[rng() % gcnt];\n        } else {\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].score == best_score) { idx = k; break; }\n        }\n\n        const Cand& c = cands[idx];\n        seq.r[i] = c.r; seq.d[i] = c.d; seq.b[i] = c.b;\n        rects[i] = {c.x, c.y, c.w, c.h};\n        W = max(W, c.x + c.w);\n        H = max(H, c.y + c.h);\n    }\n    return W + H;\n}\n\n/*------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T >> sigma;\n    Wobs.resize(N);\n    Hobs.resize(N);\n    for (int i = 0; i < N; ++i) cin >> Wobs[i] >> Hobs[i];\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    /*--- initial deterministic packings ---------------------*/\n    vector<Seq> det(4);\n    vector<vector<Rect>> detR(4);\n    vector<long long> detSc(4, LLONG_MAX);\n    for (int obj = 0; obj < 4; ++obj) {\n        det[obj].r.resize(N);\n        det[obj].d.resize(N);\n        det[obj].b.resize(N);\n        detR[obj].resize(N);\n        detSc[obj] = build_greedy(det[obj], detR[obj], obj, false, rng, 0);\n    }\n\n    Seq best_seq;\n    vector<Rect> best_rects;\n    long long best_est = LLONG_MAX;\n    for (int obj = 0; obj < 4; ++obj) {\n        if (detSc[obj] < best_est) {\n            best_est = detSc[obj];\n            best_seq = det[obj];\n            best_rects = detR[obj];\n        }\n    }\n\n    long long best_observed = LLONG_MAX;\n\n    const double TIME_LIMIT = 2.8;\n    auto start_clock = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_clock).count();\n    };\n\n    for (int turn = 0; turn < T; ++turn) {\n        auto turn_start = chrono::steady_clock::now();\n        double remain = TIME_LIMIT - elapsed();\n        double per_turn = remain / (T - turn);\n        auto deadline = turn_start + chrono::duration<double>(per_turn * 0.9);\n\n        /* prefix of current best (for fast mutations) */\n        vector<long long> prefW(N + 1, 0), prefH(N + 1, 0);\n        for (int i = 0; i < N; ++i) {\n            prefW[i + 1] = max(prefW[i], best_rects[i].x + best_rects[i].w);\n            prefH[i + 1] = max(prefH[i], best_rects[i].y + best_rects[i].h);\n        }\n\n        Seq cand_seq = best_seq;\n        long long cand_est = best_est;\n\n        /* a few stochastic full greedies */\n        int n_stoch = 0;\n        if (turn < 5) n_stoch = 2;\n        else if (turn < 20) n_stoch = 1;\n        else if ((rng() & 3) == 0) n_stoch = 1;\n\n        for (int s = 0; s < n_stoch; ++s) {\n            Seq seq; seq.r.resize(N); seq.d.resize(N); seq.b.resize(N);\n            vector<Rect> rects(N);\n            int obj = rng() % 4;\n            long long est = build_greedy(seq, rects, obj, true, rng, 0);\n            if (est < cand_est) {\n                cand_est = est;\n                cand_seq = seq;\n            }\n        }\n\n        /* fast mutation / rebuild loop */\n        vector<Rect> work(N);\n        while (chrono::steady_clock::now() < deadline) {\n            int type = rng() & 3;               // 0,1: pure mutation, 2: rebuild, 3: stochastic greedy\n            if (type < 2) {\n                int i = rng() % N;\n                Seq seq = best_seq;\n                seq.r[i] = rng() & 1;\n                seq.d[i] = (rng() & 1) ? 'U' : 'L';\n                seq.b[i] = (int)(rng() % (i + 1)) - 1;\n                work = best_rects;\n                long long est = simulate_fixed(seq, work, i);\n                if (est < cand_est) {\n                    cand_est = est;\n                    cand_seq = seq;\n                }\n            } else if (type == 2) {\n                int i = rng() % N;\n                Seq seq = best_seq;\n                work = best_rects;\n                long long est = build_greedy(seq, work, rng() % 4, (rng() & 1), rng, i);\n                if (est < cand_est) {\n                    cand_est = est;\n                    cand_seq = seq;\n                }\n            } else {\n                Seq seq; seq.r.resize(N); seq.d.resize(N); seq.b.resize(N);\n                work.assign(N, {});\n                long long est = build_greedy(seq, work, rng() % 4, true, rng, 0);\n                if (est < cand_est) {\n                    cand_est = est;\n                    cand_seq = seq;\n                }\n            }\n        }\n\n        /* output */\n        cout << N << '\\n';\n        for (int i = 0; i < N; ++i) {\n            cout << i << ' ' << cand_seq.r[i] << ' ' << cand_seq.d[i] << ' ' << cand_seq.b[i] << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        long long obs = Wp + Hp;\n        if (obs < best_observed) {\n            best_observed = obs;\n            best_seq = cand_seq;\n            best_rects.assign(N, {});\n            best_est = simulate_fixed(best_seq, best_rects, 0);\n        }\n    }\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, H;\nvector<int> A;\nvector<vector<int>> adj;\n\n// current forest\nvector<int> parent_;\nvector<vector<int>> children;\n\n// data recomputed from parent_\nvector<int> depth_;\nvector<int> comp;      // root id of the tree\nvector<int> tin, tout;\nvector<long long> sz;  // sum of A in subtree\nvector<int> ht;        // height of subtree (max distance to a descendant)\nint timer_ = 0;\nlong long current_score = 0;\n\nlong long best_score = 0;\nvector<int> best_parent;\n\nmt19937 rng;\n\n/* recompute depths, sz, ht, Euler tour and current_score from parent_ */\nvoid recompute() {\n    for (int i = 0; i < N; ++i) children[i].clear();\n    for (int i = 0; i < N; ++i) {\n        if (parent_[i] != -1) children[parent_[i]].push_back(i);\n    }\n    timer_ = 0;\n    long long sc = 0;\n    for (int i = 0; i < N; ++i) {\n        if (parent_[i] == -1) {\n            vector<pair<int,int>> st;\n            st.reserve(N);\n            st.emplace_back(i, 0);\n            depth_[i] = 0;\n            comp[i] = i;\n            while (!st.empty()) {\n                auto [v, state] = st.back();\n                st.pop_back();\n                if (state == 0) {\n                    tin[v] = ++timer_;\n                    sz[v] = A[v];\n                    ht[v] = 0;\n                    st.emplace_back(v, 1);\n                    for (int c : children[v]) {\n                        depth_[c] = depth_[v] + 1;\n                        comp[c] = i;\n                        st.emplace_back(c, 0);\n                    }\n                } else {\n                    for (int c : children[v]) {\n                        sz[v] += sz[c];\n                        ht[v] = max(ht[v], 1 + ht[c]);\n                    }\n                    tout[v] = timer_;\n                    sc += 1LL * (depth_[v] + 1) * A[v];\n                }\n            }\n        }\n    }\n    current_score = sc;\n}\n\n/* one steepest\u2011ascent step; returns true if a move was applied */\nbool improve() {\n    recompute();\n    long long best_gain = 0;\n    int best_v = -1, best_u = -1;\n\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int v : order) {\n        for (int u : adj[v]) {\n            if (u == parent_[v]) continue;\n            if (depth_[u] >= H) continue;\n\n            bool bad = false;\n            if (parent_[v] == -1) {\n                // v is root \u2192 u must belong to a different tree\n                if (comp[u] == comp[v]) bad = true;\n            } else {\n                // same tree \u2192 u must not lie inside v's subtree\n                if (comp[u] == comp[v]) {\n                    if (tin[v] <= tin[u] && tin[u] <= tout[v]) bad = true;\n                }\n            }\n            if (bad) continue;\n\n            int delta = depth_[u] + 1 - depth_[v];\n            if (delta <= 0) continue;\n            if (depth_[v] + ht[v] + delta > H) continue;\n\n            long long gain = 1LL * delta * sz[v];\n            if (gain > best_gain) {\n                best_gain = gain;\n                best_v = v;\n                best_u = u;\n            }\n        }\n    }\n\n    if (best_gain > 0) {\n        parent_[best_v] = best_u;\n        return true;\n    }\n    return false;\n}\n\n/* hill climb from a given starting parent array */\nvoid solve_trial(const vector<int>& init) {\n    parent_ = init;\n    while (improve()) {}\n    if (current_score > best_score) {\n        best_score = current_score;\n        best_parent = parent_;\n    }\n}\n\n/* ---------- initial forest generators ---------- */\n\nvector<int> init_all_roots() {\n    return vector<int>(N, -1);\n}\n\n/* type 1 = ascending A, type 2 = random order; attach to deepest valid earlier neighbour */\nvector<int> generate_initial_deepest(int type) {\n    vector<int> p(N, -1);\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    if (type == 1) {\n        sort(ord.begin(), ord.end(),\n             [&](int a, int b) { return A[a] < A[b]; });\n    } else {\n        shuffle(ord.begin(), ord.end(), rng);\n    }\n    vector<int> pos(N);\n    for (int i = 0; i < N; ++i) pos[ord[i]] = i;\n    vector<int> d(N, 0);\n    for (int v : ord) {\n        int best_u = -1, best_d = -1;\n        for (int u : adj[v]) {\n            if (pos[u] < pos[v] && d[u] < H && d[u] > best_d) {\n                best_d = d[u];\n                best_u = u;\n            }\n        }\n        if (best_u != -1) {\n            p[v] = best_u;\n            d[v] = best_d + 1;\n        }\n    }\n    return p;\n}\n\n/* random order, attach to a random valid earlier neighbour */\nvector<int> generate_initial_random_choice() {\n    vector<int> p(N, -1);\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    shuffle(ord.begin(), ord.end(), rng);\n    vector<int> pos(N);\n    for (int i = 0; i < N; ++i) pos[ord[i]] = i;\n    vector<int> d(N, 0);\n    for (int v : ord) {\n        vector<int> cand;\n        for (int u : adj[v]) {\n            if (pos[u] < pos[v] && d[u] < H) cand.push_back(u);\n        }\n        if (!cand.empty()) {\n            int u = cand[rng() % cand.size()];\n            p[v] = u;\n            d[v] = d[u] + 1;\n        }\n    }\n    return p;\n}\n\n/* -------------------------------------------- */\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n\n    if (!(cin >> N >> M >> H)) return 0;\n    A.resize(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    adj.assign(N, {});\n    for (int i = 0; i < M; ++i) {\n        int u, v;\n        cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // coordinates are irrelevant for the algorithm\n    for (int i = 0; i < N; ++i) {\n        int x, y;\n        cin >> x >> y;\n    }\n\n    children.assign(N, {});\n    depth_.resize(N);\n    comp.resize(N);\n    tin.resize(N);\n    tout.resize(N);\n    sz.assign(N, 0);\n    ht.assign(N, 0);\n\n    best_parent.assign(N, -1);\n    best_score = 0;\n    for (int i = 0; i < N; ++i) best_score += A[i];   // all roots baseline\n\n    const clock_t START = clock();\n    auto elapsed = [&]() {\n        return double(clock() - START) / CLOCKS_PER_SEC;\n    };\n\n    int trial = 0;\n    while (elapsed() < 1.8) {\n        if (trial == 0) {\n            solve_trial(init_all_roots());\n        } else if (trial == 1) {\n            solve_trial(generate_initial_deepest(1));   // ascending A\n        } else if (trial % 3 == 2) {\n            solve_trial(generate_initial_deepest(2));   // random order, deepest\n        } else {\n            solve_trial(generate_initial_random_choice());\n        }\n        ++trial;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << best_parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    uint64_t mask = 0;   // which Oni are removed\n    int cost = 0;        // 2 * k\n    char dir = 0;        // 'L','R','U','D'\n    int idx = 0;         // row or column index\n    int k = 0;           // number of shifts in the first direction\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> B(N);\n    for (int i = 0; i < N; ++i) cin >> B[i];\n\n    // positions of Oni\n    vector<pair<int,int>> oni;               // (r,c)\n    vector<vector<int>> oni_id(N, vector<int>(N, -1));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (B[i][j] == 'x') {\n                oni_id[i][j] = (int)oni.size();\n                oni.emplace_back(i, j);\n            }\n    const int M = (int)oni.size();           // = 2N = 40\n\n    vector<Op> ops;\n\n    // ----- row operations -----\n    for (int i = 0; i < N; ++i) {\n        vector<int> fcols;\n        for (int j = 0; j < N; ++j) if (B[i][j] == 'o') fcols.push_back(j);\n        sort(fcols.begin(), fcols.end());\n        int L = fcols.empty() ? N : fcols.front();\n        int R = fcols.empty() ? -1 : fcols.back();\n\n        // left part : cols < L\n        vector<pair<int,int>> left; // (col, oni_id)\n        for (int j = 0; j < N; ++j)\n            if (B[i][j] == 'x' && j < L) left.emplace_back(j, oni_id[i][j]);\n        sort(left.begin(), left.end());\n        for (int t = 0; t < (int)left.size(); ++t) {\n            int j = left[t].first;\n            uint64_t mask = 0;\n            for (int s = 0; s <= t; ++s) mask |= 1ULL << left[s].second;\n            ops.push_back({mask, 2 * (j + 1), 'L', i, j + 1});\n        }\n\n        // right part : cols > R\n        vector<pair<int,int>> right;\n        for (int j = 0; j < N; ++j)\n            if (B[i][j] == 'x' && j > R) right.emplace_back(j, oni_id[i][j]);\n        sort(right.begin(), right.end(), greater<pair<int,int>>());\n        for (int t = 0; t < (int)right.size(); ++t) {\n            int j = right[t].first;\n            uint64_t mask = 0;\n            for (int s = 0; s <= t; ++s) mask |= 1ULL << right[s].second;\n            ops.push_back({mask, 2 * (N - j), 'R', i, N - j});\n        }\n    }\n\n    // ----- column operations -----\n    for (int j = 0; j < N; ++j) {\n        vector<int> frows;\n        for (int i = 0; i < N; ++i) if (B[i][j] == 'o') frows.push_back(i);\n        sort(frows.begin(), frows.end());\n        int T = frows.empty() ? N : frows.front();\n        int Bot = frows.empty() ? -1 : frows.back();\n\n        // top part : rows < T\n        vector<pair<int,int>> top; // (row, oni_id)\n        for (int i = 0; i < N; ++i)\n            if (B[i][j] == 'x' && i < T) top.emplace_back(i, oni_id[i][j]);\n        sort(top.begin(), top.end());\n        for (int t = 0; t < (int)top.size(); ++t) {\n            int i = top[t].first;\n            uint64_t mask = 0;\n            for (int s = 0; s <= t; ++s) mask |= 1ULL << top[s].second;\n            ops.push_back({mask, 2 * (i + 1), 'U', j, i + 1});\n        }\n\n        // bottom part : rows > Bot\n        vector<pair<int,int>> bot;\n        for (int i = 0; i < N; ++i)\n            if (B[i][j] == 'x' && i > Bot) bot.emplace_back(i, oni_id[i][j]);\n        sort(bot.begin(), bot.end(), greater<pair<int,int>>());\n        for (int t = 0; t < (int)bot.size(); ++t) {\n            int i = bot[t].first;\n            uint64_t mask = 0;\n            for (int s = 0; s <= t; ++s) mask |= 1ULL << bot[s].second;\n            ops.push_back({mask, 2 * (N - i), 'D', j, N - i});\n        }\n    }\n\n    // ----- prune dominated ops -----\n    vector<Op> pruned;\n    for (auto &op : ops) {\n        if (op.mask == 0) continue;\n        bool dominated = false;\n        for (auto &p : pruned) {\n            if ( (p.mask | op.mask) == p.mask && p.cost <= op.cost ) {\n                dominated = true; break;\n            }\n        }\n        if (dominated) continue;\n        vector<Op> nxt;\n        for (auto &p : pruned) {\n            if ( !((op.mask | p.mask) == op.mask && op.cost <= p.cost) )\n                nxt.push_back(p);\n        }\n        nxt.push_back(op);\n        pruned.swap(nxt);\n    }\n    ops.swap(pruned);\n    const int S = (int)ops.size();\n\n    // ----- which ops cover each Oni -----\n    vector<vector<int>> oni_covers(M);\n    for (int i = 0; i < S; ++i) {\n        uint64_t m = ops[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            oni_covers[b].push_back(i);\n            m &= m - 1;\n        }\n    }\n\n    const uint64_t FULL = (M == 64) ? ~0ULL : ((1ULL << M) - 1ULL);\n\n    // ----- greedy initial solution -----\n    int greedy_cost = 0;\n    uint64_t uncovered_g = FULL;\n    vector<int> greedy_sol;\n    while (uncovered_g) {\n        int best_op = -1;\n        double best_ratio = 1e300;\n        for (int i = 0; i < S; ++i) {\n            uint64_t nw = ops[i].mask & uncovered_g;\n            int cnt = __builtin_popcountll(nw);\n            if (cnt == 0) continue;\n            double ratio = (double)ops[i].cost / cnt;\n            if (ratio < best_ratio) {\n                best_ratio = ratio;\n                best_op = i;\n            }\n        }\n        if (best_op == -1) break; // should never happen\n        greedy_sol.push_back(best_op);\n        greedy_cost += ops[best_op].cost;\n        uncovered_g &= ~ops[best_op].mask;\n    }\n\n    int best_cost = greedy_cost;\n    vector<int> best_sol = greedy_sol;\n\n    unordered_map<uint64_t, int> memo;\n    memo.reserve(100000);\n\n    function<void(uint64_t,int,vector<int>&)> dfs = [&](uint64_t uncovered, int cur_cost, vector<int> &cur) {\n        if (uncovered == 0) {\n            if (cur_cost < best_cost) {\n                best_cost = cur_cost;\n                best_sol = cur;\n            }\n            return;\n        }\n        if (cur_cost >= best_cost) return;\n        auto it = memo.find(uncovered);\n        if (it != memo.end() && it->second <= cur_cost) return;\n        memo[uncovered] = cur_cost;\n\n        // lower bound : sum of cheapest covering candidate per uncovered Oni\n        int lb = cur_cost;\n        uint64_t tmp = uncovered;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int minc = INT_MAX;\n            for (int op_idx : oni_covers[o]) {\n                if (ops[op_idx].mask & uncovered)\n                    minc = min(minc, ops[op_idx].cost);\n            }\n            if (minc == INT_MAX) return; // dead end\n            lb += minc;\n            if (lb >= best_cost) return;\n            tmp &= tmp - 1;\n        }\n\n        // choose uncovered Oni with smallest degree\n        int target_o = -1, min_deg = INT_MAX;\n        tmp = uncovered;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int deg = 0;\n            for (int op_idx : oni_covers[o])\n                if (ops[op_idx].mask & uncovered) ++deg;\n            if (deg < min_deg) {\n                min_deg = deg;\n                target_o = o;\n            }\n            tmp &= tmp - 1;\n        }\n\n        vector<pair<int,int>> cands; // (cost, op_idx)\n        for (int op_idx : oni_covers[target_o]) {\n            if (ops[op_idx].mask & uncovered)\n                cands.emplace_back(ops[op_idx].cost, op_idx);\n        }\n        sort(cands.begin(), cands.end());\n        for (auto &[c, op_idx] : cands) {\n            if (cur_cost + c >= best_cost) continue;\n            cur.push_back(op_idx);\n            dfs(uncovered & ~ops[op_idx].mask, cur_cost + c, cur);\n            cur.pop_back();\n        }\n    };\n\n    vector<int> cur;\n    dfs(FULL, 0, cur);\n\n    // ----- remove redundant ops (optional safety) -----\n    vector<int> sol = best_sol;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < sol.size(); ++i) {\n            uint64_t union_mask = 0;\n            for (size_t j = 0; j < sol.size(); ++j)\n                if (j != i) union_mask |= ops[sol[j]].mask;\n            if ( (union_mask & FULL) == FULL ) {\n                sol.erase(sol.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    // ----- output -----\n    for (int id : sol) {\n        const Op &op = ops[id];\n        for (int t = 0; t < op.k; ++t)\n            cout << op.dir << ' ' << op.idx << '\\n';\n        char rev = 0;\n        if (op.dir == 'L') rev = 'R';\n        else if (op.dir == 'R') rev = 'L';\n        else if (op.dir == 'U') rev = 'D';\n        else rev = 'U';\n        for (int t = 0; t < op.k; ++t)\n            cout << rev << ' ' << op.idx << '\\n';\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) return 0;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    vector<double> p(N);\n    for (int i = 0; i < N; ++i) p[i] = (double)T[i] / (double)L;\n\n    /*------------------------------------------------------------\n        Phase 1 : greedy init + fast proxy local search\n      ------------------------------------------------------------*/\n    vector<int> a(N), b(N);\n    vector<double> in(N, 0.0);\n\n    auto pick_best_deficit = [&]() {\n        int best = 0;\n        double bestDef = -1e100;\n        for (int i = 0; i < N; ++i) {\n            double def = p[i] - in[i];\n            if (def > bestDef) {\n                bestDef = def;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (int j = 0; j < N; ++j) {\n        int u = pick_best_deficit();\n        a[j] = u;\n        in[u] += p[j] * 0.5;\n        int v = pick_best_deficit();\n        b[j] = v;\n        in[v] += p[j] * 0.5;\n    }\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto proxy_delta = [&](int j, int typ, int newv) -> double {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return 0.0;\n        double d = 0.0;\n        double afterOld = in[oldv] - p[j] * 0.5;\n        d += fabs(afterOld - p[oldv]) - fabs(in[oldv] - p[oldv]);\n        double afterNew = in[newv] + p[j] * 0.5;\n        d += fabs(afterNew - p[newv]) - fabs(in[newv] - p[newv]);\n        return d;\n    };\n\n    auto apply_proxy = [&](int j, int typ, int newv) {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return;\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ) b[j] = newv;\n        else     a[j] = newv;\n    };\n\n    for (int iter = 0; iter < 500000; ++iter) {\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int newv = (int)(rng() % N);\n        double d = proxy_delta(j, typ, newv);\n        if (d < -1e-12) {\n            apply_proxy(j, typ, newv);\n        }\n    }\n\n    /*------------------------------------------------------------\n        Phase 2 : simulation + SA with proxy-guided neighbours\n      ------------------------------------------------------------*/\n    vector<array<uint8_t,2>> nxt(N);\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = (uint8_t)b[i];\n        nxt[i][1] = (uint8_t)a[i];\n    }\n\n    vector<int> simCnt(N);\n    auto simulate_fill = [&]() -> int {\n        fill(simCnt.begin(), simCnt.end(), 0);\n        uint8_t cur = 0;\n        simCnt[0] = 1;\n        for (int step = 1; step < L; ++step) {\n            cur = nxt[cur][simCnt[cur] & 1];\n            ++simCnt[cur];\n        }\n        int err = 0;\n        for (int i = 0; i < N; ++i) err += abs(simCnt[i] - T[i]);\n        return err;\n    };\n\n    int bestE = simulate_fill();\n    vector<int> bestA = a, bestB = b;\n    int curE = bestE;\n\n    vector<int> diff(N);\n    for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n\n    double temp = max(100.0, (double)bestE * 0.2);\n    const double COOL = 0.9995;\n    int iter = 0, lastBestIter = 0;\n\n    auto curTime = [&]() {\n        return (double)clock() / (double)CLOCKS_PER_SEC;\n    };\n\n    while (curTime() < 1.85) {\n        ++iter;\n\n        /*--- kick when stuck ------------------------------------*/\n        if (iter - lastBestIter > 150) {\n            a = bestA; b = bestB;\n            fill(in.begin(), in.end(), 0.0);\n            for (int j = 0; j < N; ++j) {\n                in[a[j]] += p[j] * 0.5;\n                in[b[j]] += p[j] * 0.5;\n            }\n            for (int k = 0; k < 5; ++k) {\n                int jj = (int)(rng() % N);\n                int tt = (int)(rng() % 2);\n                int nv = (int)(rng() % N);\n                apply_proxy(jj, tt, nv);\n            }\n            for (int i = 0; i < N; ++i) {\n                nxt[i][0] = (uint8_t)b[i];\n                nxt[i][1] = (uint8_t)a[i];\n            }\n            curE = simulate_fill();\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n            if (curE < bestE) {\n                bestE = curE;\n                bestA = a; bestB = b;\n                lastBestIter = iter;\n            }\n            temp = max(100.0, (double)curE * 0.2);\n            continue;\n        }\n\n        /*--- choose a neighbour ---------------------------------*/\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int oldv = typ ? b[j] : a[j];\n        int newv = oldv;\n\n        int mode = (int)(rng() % 4);\n        if (mode < 2) {                     // exploitation : best proxy\n            double bestD = 1e100;\n            for (int v = 0; v < N; ++v) {\n                if (v == oldv) continue;\n                double d = proxy_delta(j, typ, v);\n                if (d < bestD) {\n                    bestD = d;\n                    newv = v;\n                }\n            }\n            if (newv == oldv) continue;\n        } else if (mode == 2) {             // pure random\n            newv = (int)(rng() % N);\n            if (newv == oldv) continue;\n        } else {                            // targeted by diff\n            vector<int> over, under;\n            for (int i = 0; i < N; ++i) {\n                if (diff[i] > 0) over.push_back(i);\n                else if (diff[i] < 0) under.push_back(i);\n            }\n            if (over.empty() || under.empty()) {\n                newv = (int)(rng() % N);\n                if (newv == oldv) continue;\n            } else {\n                int to = over[(int)(rng() % over.size())];\n                vector<pair<int,int>> preds;\n                for (int x = 0; x < N; ++x) {\n                    if (a[x] == to) preds.emplace_back(x, 0);\n                    if (b[x] == to) preds.emplace_back(x, 1);\n                }\n                if (preds.empty()) {\n                    newv = (int)(rng() % N);\n                    if (newv == oldv) continue;\n                } else {\n                    auto pr = preds[(int)(rng() % preds.size())];\n                    j = pr.first;\n                    typ = pr.second;\n                    oldv = typ ? b[j] : a[j];\n                    newv = under[(int)(rng() % under.size())];\n                    if (newv == oldv) continue;\n                }\n            }\n        }\n\n        /*--- apply and simulate ---------------------------------*/\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ == 0) {\n            a[j] = newv;\n            nxt[j][1] = (uint8_t)newv;\n        } else {\n            b[j] = newv;\n            nxt[j][0] = (uint8_t)newv;\n        }\n\n        int newE = simulate_fill();\n        bool accept = false;\n\n        if (newE < bestE) {\n            bestE = newE;\n            bestA = a; bestB = b;\n            lastBestIter = iter;\n            accept = true;\n        }\n        if (!accept) {\n            int dE = newE - curE;\n            if (dE <= 0) {\n                accept = true;\n            } else {\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < exp(-dE / temp)) accept = true;\n            }\n        }\n\n        if (accept) {\n            curE = newE;\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n        } else {\n            // revert\n            in[newv] -= p[j] * 0.5;\n            in[oldv] += p[j] * 0.5;\n            if (typ == 0) {\n                a[j] = oldv;\n                nxt[j][1] = (uint8_t)oldv;\n            } else {\n                b[j] = oldv;\n                nxt[j][0] = (uint8_t)oldv;\n            }\n        }\n        temp *= COOL;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n/* ---------- Morton key for 2\u2011D locality ---------- */\nstatic uint64_t expand_bits(uint32_t x) {\n    uint64_t z = 0;\n    for (int i = 0; i < 15; ++i)                 // x \u2264 20000 < 2^15\n        z |= ((uint64_t)((x >> i) & 1U)) << (2 * i);\n    return z;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    /* estimated centres */\n    vector<double> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) * 0.5;\n        cy[i] = (ly[i] + ry[i]) * 0.5;\n    }\n\n    /* estimated distances */\n    vector<vector<double>> est(N, vector<double>(N));\n    for (int i = 0; i < N; ++i) {\n        est[i][i] = 0.0;\n        for (int j = i + 1; j < N; ++j) {\n            double dx = cx[i] - cx[j];\n            double dy = cy[i] - cy[j];\n            double d = sqrt(dx * dx + dy * dy);\n            est[i][j] = est[j][i] = d;\n        }\n    }\n\n    auto morton = [&](int v) -> uint64_t {\n        uint32_t x = (uint32_t)(lx[v] + rx[v]);\n        uint32_t y = (uint32_t)(ly[v] + ry[v]);\n        return expand_bits(x) | (expand_bits(y) << 1);\n    };\n\n    /* -------------------------------------------------\n       4. build a compact partition\n       ------------------------------------------------- */\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) {\n             if (G[a] != G[b]) return G[a] > G[b];\n             return a < b;\n         });\n\n    vector<vector<int>> group_nodes(M);\n    vector<char> assigned(N, 0);\n    vector<int> unassigned;\n    unassigned.reserve(N);\n    for (int i = 0; i < N; ++i) unassigned.push_back(i);\n\n    auto mst_cost = [&](const vector<int> &nodes) -> double {\n        int g = (int)nodes.size();\n        if (g <= 1) return 0.0;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        double total = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            total += mincost[v];\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) mincost[i] = d;\n            }\n        }\n        return total;\n    };\n\n    /* large groups (size >= 3) */\n    for (int idx : order) {\n        int g = G[idx];\n        if (g < 3) continue;\n        int U = (int)unassigned.size();\n        int K = min(20, U);\n        vector<int> best_cluster;\n        double best_cost = 1e100;\n        for (int s = 0; s < K; ++s) {\n            int seed = unassigned[s * U / K];\n            vector<int> cluster;\n            cluster.reserve(g);\n            cluster.push_back(seed);\n            vector<char> in_cluster(N, 0);\n            in_cluster[seed] = 1;\n            vector<double> d(N, 1e100);\n            for (int v : unassigned) if (v != seed) d[v] = est[seed][v];\n            while ((int)cluster.size() < g) {\n                int best_u = -1;\n                double best_du = 1e100;\n                for (int v : unassigned) {\n                    if (in_cluster[v]) continue;\n                    if (d[v] < best_du) {\n                        best_du = d[v];\n                        best_u = v;\n                    }\n                }\n                cluster.push_back(best_u);\n                in_cluster[best_u] = 1;\n                for (int v : unassigned) if (!in_cluster[v]) {\n                    double nd = est[best_u][v];\n                    if (nd < d[v]) d[v] = nd;\n                }\n            }\n            double cost = mst_cost(cluster);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_cluster = move(cluster);\n            }\n        }\n        group_nodes[idx] = best_cluster;\n        for (int v : best_cluster) assigned[v] = 1;\n        vector<int> nxt;\n        nxt.reserve(unassigned.size() - g);\n        for (int v : unassigned) if (!assigned[v]) nxt.push_back(v);\n        unassigned.swap(nxt);\n    }\n\n    /* pairs (size == 2) */\n    vector<int> pair_idx;\n    for (int idx : order) if (G[idx] == 2) pair_idx.push_back(idx);\n    for (int idx : pair_idx) {\n        int U = (int)unassigned.size();\n        double best_d = 1e100;\n        int best_a = -1, best_b = -1;\n        for (int i = 0; i < U; ++i)\n            for (int j = i + 1; j < U; ++j) {\n                double d = est[unassigned[i]][unassigned[j]];\n                if (d < best_d) {\n                    best_d = d;\n                    best_a = i;\n                    best_b = j;\n                }\n            }\n        int a = unassigned[best_a];\n        int b = unassigned[best_b];\n        group_nodes[idx] = {a, b};\n        assigned[a] = assigned[b] = 1;\n        vector<int> nxt;\n        nxt.reserve(U - 2);\n        for (int i = 0; i < U; ++i)\n            if (i != best_a && i != best_b) nxt.push_back(unassigned[i]);\n        unassigned.swap(nxt);\n    }\n\n    /* singles (size == 1) */\n    vector<int> single_idx;\n    for (int idx : order) if (G[idx] == 1) single_idx.push_back(idx);\n    for (int idx : single_idx) {\n        int v = unassigned.back(); unassigned.pop_back();\n        group_nodes[idx] = {v};\n        assigned[v] = 1;\n    }\n\n    /* -------------------------------------------------\n       5. query allocation\n       ------------------------------------------------- */\n    vector<int> alloc(M, 0);\n    int sum_alloc = 0;\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (g > L) alloc[k] = (g - 1 + L - 2) / (L - 1);   // ceil((g-1)/(L-1))\n        else if (g >= 3) alloc[k] = 1;\n        else alloc[k] = 0;\n        sum_alloc += alloc[k];\n    }\n    int surplus = Q - sum_alloc;\n    if (surplus > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) if (G[k] > L) large.push_back(k);\n        sort(large.begin(), large.end(),\n             [&](int a, int b) { return G[a] > G[b]; });\n        while (surplus > 0) {\n            bool changed = false;\n            for (int k : large) {\n                int max_q = G[k] - L + 1;\n                if (alloc[k] < max_q) {\n                    ++alloc[k];\n                    --surplus;\n                    changed = true;\n                    if (surplus == 0) break;\n                }\n            }\n            if (!changed) break;\n        }\n    }\n\n    /* helper: reorder a group by a DFS walk of its estimated MST */\n    auto mst_order = [&](const vector<int> &nodes) -> vector<int> {\n        int g = (int)nodes.size();\n        if (g <= 1) return nodes;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<int> parent(g, -1);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) {\n                    mincost[i] = d;\n                    parent[i] = v;\n                }\n            }\n        }\n        vector<vector<int>> adj(g);\n        for (int i = 1; i < g; ++i) {\n            adj[i].push_back(parent[i]);\n            adj[parent[i]].push_back(i);\n        }\n        vector<int> ord;\n        ord.reserve(g);\n        stack<int> st;\n        st.push(0);\n        vector<char> vis(g, 0);\n        vis[0] = 1;\n        while (!st.empty()) {\n            int u = st.top(); st.pop();\n            ord.push_back(nodes[u]);\n            for (int v : adj[u]) if (!vis[v]) {\n                vis[v] = 1;\n                st.push(v);\n            }\n        }\n        return ord;\n    };\n\n    /* -------------------------------------------------\n       6. perform queries\n       ------------------------------------------------- */\n    vector<vector<pair<int,int>>> raw_edges(M);\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (alloc[k] == 0) continue;\n        auto &nodes = group_nodes[k];\n        if (g > L) {\n            nodes = mst_order(nodes);               // locality ordering\n            int q = alloc[k];\n            for (int i = 0; i < q; ++i) {\n                int start = (int)((long long)i * (g - L) / (q - 1));\n                cout << \"? \" << L;\n                for (int j = 0; j < L; ++j) cout << ' ' << nodes[start + j];\n                cout << '\\n' << flush;\n                for (int j = 0; j < L - 1; ++j) {\n                    int a, b;  cin >> a >> b;\n                    raw_edges[k].push_back({a, b});\n                }\n            }\n        } else {\n            // 3 <= g <= L\n            cout << \"? \" << g;\n            for (int v : nodes) cout << ' ' << v;\n            cout << '\\n' << flush;\n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;  cin >> a >> b;\n                raw_edges[k].push_back({a, b});\n            }\n        }\n    }\n\n    /* -------------------------------------------------\n       7. output answer\n       ------------------------------------------------- */\n    cout << \"!\\n\";\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        const auto &nodes = group_nodes[k];\n        for (int i = 0; i < g; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n\n        if (g <= 1) {\n            continue;\n        } else if (g == 2) {\n            cout << nodes[0] << ' ' << nodes[1] << '\\n';\n        } else if (g <= L) {\n            for (auto &e : raw_edges[k])\n                cout << e.first << ' ' << e.second << '\\n';\n        } else {\n            // build graph from queried edges\n            vector<int> pos(N, -1);\n            for (int i = 0; i < g; ++i) pos[nodes[i]] = i;\n            vector<vector<int>> adj(g);\n            set<pair<int,int>> seen;\n            for (auto &e : raw_edges[k]) {\n                int u = e.first, v = e.second;\n                if (u > v) swap(u, v);\n                if (!seen.insert({u, v}).second) continue;\n                int iu = pos[u], iv = pos[v];\n                if (iu == -1 || iv == -1) continue;\n                adj[iu].push_back(iv);\n                adj[iv].push_back(iu);\n            }\n            vector<char> vis(g, 0);\n            vector<pair<int,int>> tree;\n            stack<int> st;\n            st.push(0);  vis[0] = 1;\n            while (!st.empty()) {\n                int u = st.top(); st.pop();\n                for (int v : adj[u]) if (!vis[v]) {\n                    vis[v] = 1;\n                    tree.push_back({nodes[u], nodes[v]});\n                    st.push(v);\n                }\n            }\n            if ((int)tree.size() != g - 1) {\n                // fallback: estimated MST\n                tree.clear();\n                const double INF = 1e100;\n                vector<double> mincost(g, INF);\n                vector<int> parent(g, -1);\n                vector<char> used(g, 0);\n                mincost[0] = 0.0;\n                for (int it = 0; it < g; ++it) {\n                    int v = -1;\n                    for (int i = 0; i < g; ++i)\n                        if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n                    used[v] = 1;\n                    if (parent[v] != -1)\n                        tree.push_back({nodes[parent[v]], nodes[v]});\n                    for (int i = 0; i < g; ++i) if (!used[i]) {\n                        double d = est[nodes[v]][nodes[i]];\n                        if (d < mincost[i]) {\n                            mincost[i] = d;\n                            parent[i] = v;\n                        }\n                    }\n                }\n            }\n            for (auto &e : tree)\n                cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\nconst int MAXN = 20;\n\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dname[4] = {'U', 'D', 'L', 'R'};\n\ninline int opp(int d) { return d ^ 1; }\n\nint N, M;\nvector<pair<int,int>> pts;\nvector<vector<bool>> blocks;\nvector<pair<char,char>> ans;\n\n// BFS on (r,c) graph with Move and Slide edges.\n// Fills dist, parent, action, dir.\n// If stop_at_goal, returns distance to goal as soon as it is reached.\nint bfs(int sr, int sc, int gr, int gc,\n        const vector<vector<bool>>& blk,\n        array<array<int,MAXN>,MAXN>& dist,\n        array<array<pair<int,int>,MAXN>,MAXN>& par,\n        array<array<char,MAXN>,MAXN>& act,\n        array<array<char,MAXN>,MAXN>& dirc,\n        bool stop_at_goal)\n{\n    for (int i=0;i<N;i++) for(int j=0;j<N;j++) dist[i][j] = INF;\n    queue<pair<int,int>> q;\n    dist[sr][sc] = 0;\n    par[sr][sc] = {-1,-1};\n    act[sr][sc] = 0;\n    dirc[sr][sc] = 0;\n    q.push({sr,sc});\n    \n    while(!q.empty()){\n        auto [r,c] = q.front(); q.pop();\n        if(stop_at_goal && r==gr && c==gc) return dist[r][c];\n        \n        // Move edges\n        for(int d=0;d<4;d++){\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            if(nr<0 || nr>=N || nc<0 || nc>=N) continue;\n            if(blk[nr][nc]) continue;\n            if(dist[nr][nc] > dist[r][c] + 1){\n                dist[nr][nc] = dist[r][c] + 1;\n                par[nr][nc] = {r,c};\n                act[nr][nc] = 'M';\n                dirc[nr][nc] = dname[d];\n                q.push({nr,nc});\n            }\n        }\n        \n        // Slide edges\n        for(int d=0;d<4;d++){\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            while(nr>=0 && nr<N && nc>=0 && nc<N && !blk[nr][nc]){\n                nr += dr[d];\n                nc += dc[d];\n            }\n            int tr = nr - dr[d];\n            int tc = nc - dc[d];\n            if(tr==r && tc==c) continue; // adjacent block, no movement\n            if(dist[tr][tc] > dist[r][c] + 1){\n                dist[tr][tc] = dist[r][c] + 1;\n                par[tr][tc] = {r,c};\n                act[tr][tc] = 'S';\n                dirc[tr][tc] = dname[d];\n                q.push({tr,tc});\n            }\n        }\n    }\n    return INF;\n}\n\n// Reconstruct action sequence from start to goal using BFS parent tables.\nvector<pair<char,char>> reconstruct(int sr, int sc, int gr, int gc,\n                                    const array<array<pair<int,int>,MAXN>,MAXN>& par,\n                                    const array<array<char,MAXN>,MAXN>& act,\n                                    const array<array<char,MAXN>,MAXN>& dirc)\n{\n    vector<pair<char,char>> res;\n    int r=gr, c=gc;\n    while(r!=sr || c!=sc){\n        res.push_back({act[r][c], dirc[r][c]});\n        auto [pr,pc] = par[r][c];\n        r = pr; c = pc;\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    if(!(cin>>N>>M)) return 0;\n    pts.resize(M);\n    for(int i=0;i<M;i++) cin>>pts[i].first>>pts[i].second;\n    \n    blocks.assign(N, vector<bool>(N, false));\n    ans.clear();\n    \n    // Precompute target set for quick lookup\n    // We need to know if a cell is a future target.\n    auto is_future_target = [&](int r, int c, int idx)->bool{\n        for(int k=idx;k<M;k++){\n            if(pts[k].first==r && pts[k].second==c) return true;\n        }\n        return false;\n    };\n    \n    int cur_r = pts[0].first;\n    int cur_c = pts[0].second;\n    \n    for(int t=1; t<M; t++){\n        int tr = pts[t].first;\n        int tc = pts[t].second;\n        \n        // Baseline BFS with current blocks\n        array<array<int,MAXN>,MAXN> dist1;\n        array<array<pair<int,int>,MAXN>,MAXN> par1;\n        array<array<char,MAXN>,MAXN> act1, dirc1;\n        int base_cost = bfs(cur_r, cur_c, tr, tc, blocks, dist1, par1, act1, dirc1, true);\n        \n        vector<pair<char,char>> best_path;\n        int best_cost = base_cost;\n        bool use_candidate = false;\n        int best_sr=-1, best_sc=-1;\n        int best_pr=-1, best_pc=-1;\n        char best_alter_dir = 0;\n        \n        if(base_cost < INF){\n            best_path = reconstruct(cur_r, cur_c, tr, tc, par1, act1, dirc1);\n        }\n        \n        // Try placing a stopper in each direction to enable a final slide into target\n        for(int d=0; d<4; d++){\n            int ar = tr + dr[opp(d)];\n            int ac = tc + dc[opp(d)];\n            if(ar<0 || ar>=N || ac<0 || ac>=N) continue; // approach cell out of bounds\n            if(blocks[ar][ac]) continue; // approach cell blocked, can't slide from here\n            \n            int sr = tr + dr[d];\n            int sc = tc + dc[d];\n            bool stopper_exists = false;\n            if(sr<0 || sr>=N || sc<0 || sc>=N) stopper_exists = true;\n            else if(blocks[sr][sc]) stopper_exists = true;\n            \n            if(stopper_exists) continue; // already handled by baseline BFS\n            \n            // Do not permanently block a future target\n            if(is_future_target(sr, sc, t)) continue;\n            \n            // Try each neighbor P of (sr,sc) as the cell from which we Alter\n            for(int pd=0; pd<4; pd++){\n                int pr = sr + dr[pd];\n                int pc = sc + dc[pd];\n                if(pr<0 || pr>=N || pc<0 || pc>=N) continue;\n                if(pr==tr && pc==tc) continue; // can't stand on target to place block\n                if(dist1[pr][pc] >= INF) continue; // unreachable in current grid\n                \n                // Create temporary block map with new stopper\n                vector<vector<bool>> blk2 = blocks;\n                blk2[sr][sc] = true;\n                \n                array<array<int,MAXN>,MAXN> dist2;\n                array<array<pair<int,int>,MAXN>,MAXN> par2;\n                array<array<char,MAXN>,MAXN> act2, dirc2;\n                int d2 = bfs(pr, pc, tr, tc, blk2, dist2, par2, act2, dirc2, true);\n                if(d2 >= INF) continue;\n                \n                int cost = dist1[pr][pc] + 1 + d2;\n                if(cost < best_cost){\n                    best_cost = cost;\n                    use_candidate = true;\n                    best_sr = sr; best_sc = sc;\n                    best_pr = pr; best_pc = pc;\n                    // direction from P to stopper is opposite of pd\n                    best_alter_dir = dname[opp(pd)];\n                }\n            }\n        }\n        \n        if(use_candidate){\n            // Reconstruct path S -> P\n            best_path = reconstruct(cur_r, cur_c, best_pr, best_pc, par1, act1, dirc1);\n            // Alter action\n            best_path.push_back({'A', best_alter_dir});\n            // Reconstruct path P -> T with the extra block\n            vector<vector<bool>> blk2 = blocks;\n            blk2[best_sr][best_sc] = true;\n            array<array<int,MAXN>,MAXN> dist2;\n            array<array<pair<int,int>,MAXN>,MAXN> par2;\n            array<array<char,MAXN>,MAXN> act2, dirc2;\n            bfs(best_pr, best_pc, tr, tc, blk2, dist2, par2, act2, dirc2, true);\n            auto path2 = reconstruct(best_pr, best_pc, tr, tc, par2, act2, dirc2);\n            best_path.insert(best_path.end(), path2.begin(), path2.end());\n            \n            // Permanently place the stopper\n            blocks[best_sr][best_sc] = true;\n        }\n        // else baseline path is already in best_path\n        \n        // Append to global answer\n        for(auto &ac : best_path){\n            ans.push_back(ac);\n        }\n        \n        cur_r = tr;\n        cur_c = tc;\n    }\n    \n    // Output\n    for(auto &ac : ans){\n        cout << ac.first << ' ' << ac.second << \"\\n\";\n    }\n    \n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nint n;\nvector<int> X, Y, R;\nvector<int> a, b, c, d;\nvector<ll> area;\nvector<double> pval;\ndouble score = 0.0;\n\ndouble calc_p(int idx, ll s) {\n    if (s <= 0) return 0.0;\n    double t;\n    if (s < R[idx]) t = (double)s / (double)R[idx];\n    else t = (double)R[idx] / (double)s;\n    return 1.0 - (1.0 - t) * (1.0 - t);\n}\n\n// side: 0=a, 1=c, 2=b, 3=d\npair<int,int> get_range(int i, int side) {\n    int L, Rv;\n    if (side == 0) {\n        L = 0;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) {\n                L = max(L, c[j]);\n            }\n        }\n        Rv = X[i];\n    } else if (side == 1) {\n        L = X[i] + 1;\n        Rv = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) {\n                Rv = min(Rv, a[j]);\n            }\n        }\n    } else if (side == 2) {\n        L = 0;\n        Rv = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) {\n                L = max(L, d[j]);\n            }\n        }\n    } else {\n        L = Y[i] + 1;\n        Rv = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) {\n                Rv = min(Rv, b[j]);\n            }\n        }\n    }\n    return {L, Rv};\n}\n\n// compute optimal integer value for side in [L,Rv] to bring area closest to R[i]\nint get_optimal(int i, int side, int L, int Rv) {\n    int opt;\n    if (side == 0) {\n        ll h = d[i] - b[i];\n        int best_w = (int)round((double)R[i] / (double)h);\n        if (best_w < 1) best_w = 1;\n        opt = c[i] - best_w;\n    } else if (side == 1) {\n        ll h = d[i] - b[i];\n        int best_w = (int)round((double)R[i] / (double)h);\n        if (best_w < 1) best_w = 1;\n        opt = a[i] + best_w;\n    } else if (side == 2) {\n        ll w = c[i] - a[i];\n        int best_h = (int)round((double)R[i] / (double)w);\n        if (best_h < 1) best_h = 1;\n        opt = d[i] - best_h;\n    } else {\n        ll w = c[i] - a[i];\n        int best_h = (int)round((double)R[i] / (double)w);\n        if (best_h < 1) best_h = 1;\n        opt = b[i] + best_h;\n    }\n    if (opt < L) opt = L;\n    if (opt > Rv) opt = Rv;\n    return opt;\n}\n\nvoid apply_move(int i, int side, int nv) {\n    if (side == 0) a[i] = nv;\n    else if (side == 1) c[i] = nv;\n    else if (side == 2) b[i] = nv;\n    else d[i] = nv;\n    ll new_area = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n    area[i] = new_area;\n    double new_p = calc_p(i, new_area);\n    score += new_p - pval[i];\n    pval[i] = new_p;\n}\n\nvoid greedy_pass(mt19937_64& rng) {\n    vector<int> order(n);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int idx = 0; idx < n; ++idx) {\n        int i = order[idx];\n        double best_delta = 1e-12;\n        int best_side = -1;\n        int best_val = -1;\n        for (int side = 0; side < 4; ++side) {\n            auto [L, Rv] = get_range(i, side);\n            int cur = (side == 0 ? a[i] : (side == 1 ? c[i] : (side == 2 ? b[i] : d[i])));\n            int opt = get_optimal(i, side, L, Rv);\n            if (opt == cur) continue;\n            ll new_area;\n            if (side == 0) new_area = 1LL * (c[i] - opt) * (d[i] - b[i]);\n            else if (side == 1) new_area = 1LL * (opt - a[i]) * (d[i] - b[i]);\n            else if (side == 2) new_area = 1LL * (c[i] - a[i]) * (d[i] - opt);\n            else new_area = 1LL * (c[i] - a[i]) * (opt - b[i]);\n            double new_p = calc_p(i, new_area);\n            double delta = new_p - pval[i];\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_side = side;\n                best_val = opt;\n            }\n        }\n        if (best_side != -1) {\n            apply_move(i, best_side, best_val);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    cin >> n;\n    X.resize(n);\n    Y.resize(n);\n    R.resize(n);\n    for (int i = 0; i < n; ++i) {\n        cin >> X[i] >> Y[i] >> R[i];\n    }\n    \n    a.resize(n);\n    b.resize(n);\n    c.resize(n);\n    d.resize(n);\n    area.resize(n);\n    pval.resize(n);\n    \n    // initial 1x1 cells\n    for (int i = 0; i < n; ++i) {\n        a[i] = X[i];\n        b[i] = Y[i];\n        c[i] = X[i] + 1;\n        d[i] = Y[i] + 1;\n        area[i] = 1;\n        pval[i] = calc_p(i, 1);\n        score += pval[i];\n    }\n    \n    mt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_n(0, n - 1);\n    uniform_int_distribution<int> dist_side(0, 3);\n    uniform_real_distribution<double> dist_01(0.0, 1.0);\n    \n    // --- Greedy initialization ---\n    for (int pass = 0; pass < 100; ++pass) {\n        double old_score = score;\n        greedy_pass(rng);\n        if (score <= old_score + 1e-9) break;\n    }\n    \n    double best_score = score;\n    vector<int> best_a = a, best_b = b, best_c = c, best_d = d;\n    \n    // --- Simulated Annealing ---\n    auto start = chrono::steady_clock::now();\n    const double TL = 4.85; // seconds\n    \n    long long iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 2047) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > TL) break;\n        }\n        \n        int i = dist_n(rng);\n        int side = dist_side(rng);\n        auto [L, Rv] = get_range(i, side);\n        int cur = (side == 0 ? a[i] : (side == 1 ? c[i] : (side == 2 ? b[i] : d[i])));\n        if (L >= Rv) continue;\n        \n        int opt = get_optimal(i, side, L, Rv);\n        int nv;\n        double r = dist_01(rng);\n        if (r < 0.5) {\n            nv = opt;\n        } else if (r < 0.8) {\n            int delta = (int)(dist_01(rng) * 201) - 100;\n            nv = opt + delta;\n        } else {\n            nv = L + (int)(dist_01(rng) * (Rv - L + 1));\n        }\n        if (nv < L) nv = L;\n        if (nv > Rv) nv = Rv;\n        if (nv == cur) continue;\n        \n        ll new_area;\n        if (side == 0) new_area = 1LL * (c[i] - nv) * (d[i] - b[i]);\n        else if (side == 1) new_area = 1LL * (nv - a[i]) * (d[i] - b[i]);\n        else if (side == 2) new_area = 1LL * (c[i] - a[i]) * (d[i] - nv);\n        else new_area = 1LL * (c[i] - a[i]) * (nv - b[i]);\n        \n        double new_p = calc_p(i, new_area);\n        double delta = new_p - pval[i];\n        \n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        double T = 0.05 * pow(1e-5 / 0.05, elapsed / TL);\n        \n        if (delta > 0.0 || dist_01(rng) < exp(delta / T)) {\n            apply_move(i, side, nv);\n            if (score > best_score) {\n                best_score = score;\n                best_a = a; best_b = b; best_c = c; best_d = d;\n            }\n        }\n    }\n    \n    // restore best and final greedy polish\n    a = best_a; b = best_b; c = best_c; d = best_d;\n    score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        area[i] = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n        pval[i] = calc_p(i, area[i]);\n        score += pval[i];\n    }\n    for (int pass = 0; pass < 30; ++pass) {\n        double old_score = score;\n        greedy_pass(rng);\n        if (score <= old_score + 1e-9) break;\n    }\n    \n    // output\n    for (int i = 0; i < n; ++i) {\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    const int H = 50, W = 50, N = 2500;\n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    \n    static int tile[N];\n    static int val[N];\n    int M = 0;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int x; cin >> x;\n            tile[i * W + j] = x;\n            M = max(M, x + 1);\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> val[i * W + j];\n        }\n    }\n    \n    // pre\u2011compute 4 neighbours for every cell (-1 = outside)\n    static int nxt[N][4];\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            nxt[id][0] = (i > 0)     ? id - W : -1; // U\n            nxt[id][1] = (i + 1 < H) ? id + W : -1; // D\n            nxt[id][2] = (j > 0)     ? id - 1 : -1; // L\n            nxt[id][3] = (j + 1 < W) ? id + 1 : -1; // R\n        }\n    }\n    \n    const char dch[4] = {'U', 'D', 'L', 'R'};\n    \n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<char> used(M, 0);\n    string best_path;\n    int best_score = -1;\n    \n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    // fast rollout simulation from `start_pos` assuming its tile is NOT yet marked in `used`\n    auto simulate = [&](int start_pos, vector<char>& used, int mode, mt19937& rng, int max_depth) -> int {\n        int stack[2500];\n        int sp = 0;\n        int t0 = tile[start_pos];\n        if (used[t0]) return -1000000000;\n        used[t0] = 1;\n        stack[sp++] = t0;\n        \n        int cur = start_pos;\n        int gain = 0;\n        int depth = 0;\n        \n        while (true) {\n            if (max_depth >= 0 && depth >= max_depth) break;\n            \n            int best_nxt = -1;\n            int best_pri = -1000000000;\n            \n            for (int d = 0; d < 4; ++d) {\n                int npos = nxt[cur][d];\n                if (npos == -1) continue;\n                int t = tile[npos];\n                if (used[t]) continue;\n                \n                // onward degree of npos\n                int deg = 0;\n                for (int d2 = 0; d2 < 4; ++d2) {\n                    int n2 = nxt[npos][d2];\n                    if (n2 != -1 && !used[tile[n2]]) ++deg;\n                }\n                \n                int pri;\n                if (mode == 0) {               // strongly avoid dead ends\n                    pri = -deg * 1000 + val[npos];\n                } else if (mode == 1) {        // value oriented\n                    pri = val[npos] * 10 - deg;\n                } else {                        // balanced + noise\n                    pri = val[npos] * 5 - deg * 100 + (int)(rng() & 127);\n                }\n                \n                if (pri > best_pri) {\n                    best_pri = pri;\n                    best_nxt = npos;\n                }\n            }\n            \n            if (best_nxt == -1) break;\n            \n            int nt = tile[best_nxt];\n            used[nt] = 1;\n            stack[sp++] = nt;\n            gain += val[best_nxt];\n            cur = best_nxt;\n            ++depth;\n        }\n        \n        while (sp > 0) {\n            used[stack[--sp]] = 0;\n        }\n        return gain;\n    };\n    \n    bool first_iter = true;\n    while (elapsed() < 1.90) {\n        int mode;\n        int noise_range;\n        int max_depth;\n        \n        if (first_iter) {\n            mode = 0;          // deterministic, dead-end avoiding\n            noise_range = 0;\n            max_depth = -1;    // unlimited\n            first_iter = false;\n        } else {\n            mode = (int)(rng() % 3);\n            noise_range = 200;\n            max_depth = -1;\n        }\n        \n        fill(used.begin(), used.end(), 0);\n        int pos = si * W + sj;\n        used[tile[pos]] = 1;\n        int cur_score = val[pos];\n        string path;\n        path.reserve(2500);\n        \n        while (true) {\n            int cand[4];\n            int cand_dir[4];\n            int cand_cnt = 0;\n            for (int d = 0; d < 4; ++d) {\n                int npos = nxt[pos][d];\n                if (npos != -1 && !used[tile[npos]]) {\n                    cand[cand_cnt] = npos;\n                    cand_dir[cand_cnt] = d;\n                    ++cand_cnt;\n                }\n            }\n            if (cand_cnt == 0) break;\n            \n            int best_idx = 0;\n            if (cand_cnt > 1) {\n                int best_eval = -1;\n                for (int i = 0; i < cand_cnt; ++i) {\n                    int future = simulate(cand[i], used, mode, rng, max_depth);\n                    int eval = val[cand[i]] + future;\n                    if (noise_range > 0) eval += (int)(rng() % noise_range);\n                    if (eval > best_eval) {\n                        best_eval = eval;\n                        best_idx = i;\n                    }\n                }\n            }\n            \n            int npos = cand[best_idx];\n            int nd = cand_dir[best_idx];\n            used[tile[npos]] = 1;\n            cur_score += val[npos];\n            path.push_back(dch[nd]);\n            pos = npos;\n        }\n        \n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_path = path;\n        }\n    }\n    \n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const double MINW = 1000.0;\n    const double MAXW = 9000.0;\n    const double LR   = 0.5;\n\n    // observed estimates and visit counts\n    vector<vector<double>> est_h(N, vector<double>(N - 1, 5000.0));\n    vector<vector<double>> est_v(N - 1, vector<double>(N, 5000.0));\n    vector<vector<int>>    cnt_h(N, vector<int>(N - 1, 0));\n    vector<vector<int>>    cnt_v(N - 1, vector<int>(N, 0));\n\n    double global_mean = 5000.0;\n\n    struct SegInfo {\n        bool has_obs = false;\n        bool use_split = false;\n        int split = -1;\n        double mean_single = 0.0;\n        double mean_l = 0.0;\n        double mean_r = 0.0;\n    };\n    vector<SegInfo> row_info(N);\n    vector<SegInfo> col_info(N);\n\n    for (int query = 0; query < 1000; ++query) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        // ----- exploration schedule (tighter because priors are good) -----\n        double explore = 0.0;\n        if      (query < 100) explore = 0.35;\n        else if (query < 300) explore = 0.20;\n        else if (query < 600) explore = 0.08;\n\n        // ----- recompute row segment info -----\n        for (int i = 0; i < N; ++i) {\n            SegInfo &ri = row_info[i];\n            double sum = 0.0;\n            int c = 0;\n            for (int j = 0; j < N - 1; ++j) {\n                if (cnt_h[i][j] > 0) { sum += est_h[i][j]; ++c; }\n            }\n            ri.has_obs = (c > 0);\n            if (!ri.has_obs) { ri.use_split = false; continue; }\n\n            ri.mean_single = sum / c;\n            double var_single = 0.0;\n            for (int j = 0; j < N - 1; ++j) if (cnt_h[i][j] > 0) {\n                double d = est_h[i][j] - ri.mean_single;\n                var_single += d * d;\n            }\n\n            double best_var = 1e100;\n            int best_split = -1;\n            double best_l = 0.0, best_r = 0.0;\n            for (int s = 1; s < N - 1; ++s) {\n                double sum_l = 0.0, sum_r = 0.0;\n                int c_l = 0, c_r = 0;\n                for (int j = 0; j < s; ++j) if (cnt_h[i][j] > 0) { sum_l += est_h[i][j]; ++c_l; }\n                for (int j = s; j < N - 1; ++j) if (cnt_h[i][j] > 0) { sum_r += est_h[i][j]; ++c_r; }\n                if (c_l < 2 || c_r < 2) continue;\n                double m_l = sum_l / c_l;\n                double m_r = sum_r / c_r;\n                double var = 0.0;\n                for (int j = 0; j < s; ++j) if (cnt_h[i][j] > 0) {\n                    double d = est_h[i][j] - m_l; var += d * d;\n                }\n                for (int j = s; j < N - 1; ++j) if (cnt_h[i][j] > 0) {\n                    double d = est_h[i][j] - m_r; var += d * d;\n                }\n                if (var < best_var) {\n                    best_var = var; best_split = s; best_l = m_l; best_r = m_r;\n                }\n            }\n            if (best_split != -1 && best_var < var_single * 0.7) {\n                ri.use_split = true;\n                ri.split = best_split;\n                ri.mean_l = best_l;\n                ri.mean_r = best_r;\n            } else {\n                ri.use_split = false;\n            }\n        }\n\n        // ----- recompute column segment info -----\n        for (int j = 0; j < N; ++j) {\n            SegInfo &ci = col_info[j];\n            double sum = 0.0;\n            int c = 0;\n            for (int i = 0; i < N - 1; ++i) {\n                if (cnt_v[i][j] > 0) { sum += est_v[i][j]; ++c; }\n            }\n            ci.has_obs = (c > 0);\n            if (!ci.has_obs) { ci.use_split = false; continue; }\n\n            ci.mean_single = sum / c;\n            double var_single = 0.0;\n            for (int i = 0; i < N - 1; ++i) if (cnt_v[i][j] > 0) {\n                double d = est_v[i][j] - ci.mean_single;\n                var_single += d * d;\n            }\n\n            double best_var = 1e100;\n            int best_split = -1;\n            double best_l = 0.0, best_r = 0.0;\n            for (int s = 1; s < N - 1; ++s) {\n                double sum_l = 0.0, sum_r = 0.0;\n                int c_l = 0, c_r = 0;\n                for (int i = 0; i < s; ++i) if (cnt_v[i][j] > 0) { sum_l += est_v[i][j]; ++c_l; }\n                for (int i = s; i < N - 1; ++i) if (cnt_v[i][j] > 0) { sum_r += est_v[i][j]; ++c_r; }\n                if (c_l < 2 || c_r < 2) continue;\n                double m_l = sum_l / c_l;\n                double m_r = sum_r / c_r;\n                double var = 0.0;\n                for (int i = 0; i < s; ++i) if (cnt_v[i][j] > 0) {\n                    double d = est_v[i][j] - m_l; var += d * d;\n                }\n                for (int i = s; i < N - 1; ++i) if (cnt_v[i][j] > 0) {\n                    double d = est_v[i][j] - m_r; var += d * d;\n                }\n                if (var < best_var) {\n                    best_var = var; best_split = s; best_l = m_l; best_r = m_r;\n                }\n            }\n            if (best_split != -1 && best_var < var_single * 0.7) {\n                ci.use_split = true;\n                ci.split = best_split;\n                ci.mean_l = best_l;\n                ci.mean_r = best_r;\n            } else {\n                ci.use_split = false;\n            }\n        }\n\n        // ----- helpers to get base cost (prior for unseen edges) -----\n        auto base_h = [&](int i, int j) -> double {\n            if (cnt_h[i][j] > 0) return est_h[i][j];\n            const SegInfo &ri = row_info[i];\n            if (!ri.has_obs) return global_mean;\n            if (ri.use_split) return (j < ri.split) ? ri.mean_l : ri.mean_r;\n            return ri.mean_single;\n        };\n        auto base_v = [&](int i, int j) -> double {\n            if (cnt_v[i][j] > 0) return est_v[i][j];\n            const SegInfo &ci = col_info[j];\n            if (!ci.has_obs) return global_mean;\n            if (ci.use_split) return (i < ci.split) ? ci.mean_l : ci.mean_r;\n            return ci.mean_single;\n        };\n\n        // ----- Dijkstra with optimistic exploration -----\n        int S = si * N + sj;\n        int T = ti * N + tj;\n        const int V = N * N;\n        const double INF = 1e100;\n        vector<double> dist(V, INF);\n        vector<pair<int,char>> prv(V, {-1, 0});\n        using State = pair<double,int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[S] = 0.0;\n        pq.emplace(0.0, S);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d > dist[v] + 1e-9) continue;\n            if (v == T) break;\n            int i = v / N;\n            int j = v % N;\n\n            auto relax = [&](int ni, int nj, bool is_h, int ei, int ej, char dir) {\n                int u = ni * N + nj;\n                double b = is_h ? base_h(ei, ej) : base_v(ei, ej);\n                int c  = is_h ? cnt_h[ei][ej] : cnt_v[ei][ej];\n                double w = b * (1.0 - explore / sqrt((double)c + 1.0));\n                if (w < MINW) w = MINW;                 // never cheaper than physically possible\n                if (dist[u] > d + w) {\n                    dist[u] = d + w;\n                    prv[u] = {v, dir};\n                    pq.emplace(dist[u], u);\n                }\n            };\n\n            if (i > 0)     relax(i - 1, j,     false, i - 1, j,     'U');\n            if (i + 1 < N) relax(i + 1, j,     false, i,     j,     'D');\n            if (j > 0)     relax(i,     j - 1, true,  i,     j - 1, 'L');\n            if (j + 1 < N) relax(i,     j + 1, true,  i,     j,     'R');\n        }\n\n        // ----- reconstruct path -----\n        string path;\n        int cur = T;\n        while (cur != S) {\n            auto [p, c] = prv[cur];\n            path.push_back(c);\n            cur = p;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << '\\n' << flush;\n\n        // ----- read noisy observation -----\n        long long y;\n        cin >> y;\n        int L = (int)path.size();\n        if (L == 0) continue;\n\n        // ----- update global fallback mean -----\n        double avg_step = (double)y / (double)L;\n        global_mean = global_mean * 0.9 + avg_step * 0.1;\n        if (global_mean < MINW) global_mean = MINW;\n        if (global_mean > MAXW) global_mean = MAXW;\n\n        // ----- compute predicted length using the same priors -----\n        struct Eref { bool h; int i, j; };\n        vector<Eref> edges;\n        edges.reserve(L);\n        double pred = 0.0;\n        int ci = si, cj = sj;\n        for (char c : path) {\n            if (c == 'U') {\n                edges.push_back({false, ci - 1, cj});\n                pred += base_v(ci - 1, cj);\n                --ci;\n            } else if (c == 'D') {\n                edges.push_back({false, ci, cj});\n                pred += base_v(ci, cj);\n                ++ci;\n            } else if (c == 'L') {\n                edges.push_back({true, ci, cj - 1});\n                pred += base_h(ci, cj - 1);\n                --cj;\n            } else if (c == 'R') {\n                edges.push_back({true, ci, cj});\n                pred += base_h(ci, cj);\n                ++cj;\n            }\n        }\n\n        // ----- LMS-style update weighted by inverse visit count -----\n        double diff = (double)y - pred;\n        double total_inv = 0.0;\n        for (auto &e : edges) {\n            int c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            total_inv += 1.0 / ((double)c + 1.0);\n        }\n\n        for (auto &e : edges) {\n            int &c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            double &est = e.h ? est_h[e.i][e.j] : est_v[e.i][e.j];\n            double w = (1.0 / ((double)c + 1.0)) / total_inv;\n            est += diff * w * LR;\n            if (est < MINW) est = MINW;\n            if (est > MAXW) est = MAXW;\n            ++c;\n        }\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nvector<string> S;\nvector<uint8_t> s_len;\n\n/* ---------- placement data ---------- */\nvector<int> pid_sid;          // string id of placement\nvector<uint8_t> pid_len;      // length of placement\nvector<int> pid_off;          // offset in flat_cells\nvector<uint16_t> flat_cells;  // cells of each placement (concatenated)\n\n/* incidence: for each cell and each required char, list of (pid<<8 | off) */\nvector<uint32_t> cell_inc_by_char[400][8];\n\n/* ---------- current state ---------- */\nvector<int> pid_match_cnt;    // how many cells of the placement match cur\nvector<int> sid_match_cnt;    // how many fully matched placements each string has\nvector<uint8_t> cur;          // current board, 0..7 = A..H, 8 = '.'\nint total_matched;\nint total_dots;\n\n/* temporaries for eval_move */\nint tmp_delta[800];\nint vis[800];\nint vis_token = 1;\n\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n/* evaluate changing one cell to new_char (does NOT modify state) */\ninline int eval_move(int cell, uint8_t new_char) {\n    uint8_t old_char = cur[cell];\n    if (old_char == new_char) return 0;\n    int delta = 0;\n    int affected[800];\n    int aff_cnt = 0;\n\n    if (old_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][old_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt == len) {                 // was fully matched, now loses one\n                int sid = pid_sid[pid];\n                if (vis[sid] != vis_token) {\n                    vis[sid] = vis_token;\n                    tmp_delta[sid] = 0;\n                    affected[aff_cnt++] = sid;\n                }\n                --tmp_delta[sid];\n            }\n        }\n    }\n\n    if (new_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][new_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt + 1 == len) {             // becomes fully matched\n                int sid = pid_sid[pid];\n                if (vis[sid] != vis_token) {\n                    vis[sid] = vis_token;\n                    tmp_delta[sid] = 0;\n                    affected[aff_cnt++] = sid;\n                }\n                ++tmp_delta[sid];\n            }\n        }\n    }\n\n    for (int i = 0; i < aff_cnt; ++i) {\n        int sid = affected[i];\n        int old_scnt = sid_match_cnt[sid];\n        int new_scnt = old_scnt + tmp_delta[sid];\n        if (old_scnt == 0 && new_scnt > 0) ++delta;\n        else if (old_scnt > 0 && new_scnt == 0) --delta;\n    }\n    ++vis_token;\n    return delta;\n}\n\n/* apply a move (mutates state) */\ninline void apply_move(int cell, uint8_t new_char) {\n    uint8_t old_char = cur[cell];\n    if (old_char == new_char) return;\n    cur[cell] = new_char;\n\n    if (old_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][old_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt == len) {\n                --sid_match_cnt[pid_sid[pid]];\n            }\n            pid_match_cnt[pid] = old_cnt - 1;\n        }\n    }\n\n    if (new_char < 8) {\n        for (uint32_t inc : cell_inc_by_char[cell][new_char]) {\n            int pid = inc >> 8;\n            uint8_t len = pid_len[pid];\n            int old_cnt = pid_match_cnt[pid];\n            if (old_cnt + 1 == len) {\n                ++sid_match_cnt[pid_sid[pid]];\n            }\n            pid_match_cnt[pid] = old_cnt + 1;\n        }\n    }\n\n    if (old_char == 8) --total_dots;\n    if (new_char == 8) ++total_dots;\n}\n\n/* recompute all counts from scratch (fast, ~5M operations) */\nvoid recompute_state(const vector<uint8_t>& mat) {\n    cur = mat;\n    total_dots = 0;\n    for (int i = 0; i < 400; ++i) if (cur[i] == 8) ++total_dots;\n\n    fill(pid_match_cnt.begin(), pid_match_cnt.end(), 0);\n    for (int cell = 0; cell < 400; ++cell) {\n        uint8_t ch = cur[cell];\n        if (ch < 8) {\n            for (uint32_t inc : cell_inc_by_char[cell][ch]) {\n                ++pid_match_cnt[inc >> 8];\n            }\n        }\n    }\n\n    fill(sid_match_cnt.begin(), sid_match_cnt.end(), 0);\n    int P = (int)pid_sid.size();\n    for (int pid = 0; pid < P; ++pid) {\n        if (pid_match_cnt[pid] == pid_len[pid]) {\n            ++sid_match_cnt[pid_sid[pid]];\n        }\n    }\n\n    total_matched = 0;\n    for (int i = 0; i < M; ++i)\n        if (sid_match_cnt[i] > 0) ++total_matched;\n}\n\n/* hill climb on letters only, return best board found in this run */\nvoid hill_climb() {\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        vector<int> order(400);\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        for (int cell : order) {\n            int best_delta = 0;\n            int best_char = cur[cell];\n            for (int ch = 0; ch < 8; ++ch) {\n                if (ch == cur[cell]) continue;\n                int d = eval_move(cell, ch);\n                if (d > best_delta) {\n                    best_delta = d;\n                    best_char = ch;\n                }\n            }\n            if (best_delta > 0) {\n                apply_move(cell, best_char);\n                total_matched += best_delta;\n                improved = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N_in, M_in;\n    if (!(cin >> N_in >> M_in)) return 0;\n    N = N_in; M = M_in;\n\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n    s_len.resize(M);\n    for (int i = 0; i < M; ++i) s_len[i] = (uint8_t)S[i].size();\n\n    /* ----- build all placements ----- */\n    pid_sid.reserve(M * 2 * N * N);\n    pid_len.reserve(M * 2 * N * N);\n    pid_off.reserve(M * 2 * N * N + 1);\n    pid_off.push_back(0);\n    flat_cells.reserve(M * 2 * N * N * 12);\n\n    for (int sid = 0; sid < M; ++sid) {\n        int len = s_len[sid];\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    int pid = (int)pid_sid.size();\n                    pid_sid.push_back(sid);\n                    pid_len.push_back((uint8_t)len);\n                    for (int p = 0; p < len; ++p) {\n                        int rr = (dir == 0) ? r : (r + p) % N;\n                        int cc = (dir == 0) ? (c + p) % N : c;\n                        int cell = rr * N + cc;\n                        uint8_t req = (uint8_t)(S[sid][p] - 'A');\n                        flat_cells.push_back((uint16_t)cell);\n                        cell_inc_by_char[cell][req].push_back(((uint32_t)pid << 8) | (uint32_t)p);\n                    }\n                    pid_off.push_back((int)flat_cells.size());\n                }\n            }\n        }\n    }\n\n    int P = (int)pid_sid.size();\n    pid_match_cnt.assign(P, 0);\n    sid_match_cnt.assign(M, 0);\n    cur.resize(400);\n\n    /* ----- initial board: majority vote ----- */\n    vector<uint8_t> init_cur(400);\n    for (int cell = 0; cell < 400; ++cell) {\n        int best_ch = 0;\n        int best_cnt = (int)cell_inc_by_char[cell][0].size();\n        for (int ch = 1; ch < 8; ++ch) {\n            int cnt = (int)cell_inc_by_char[cell][ch].size();\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_ch = ch;\n            }\n        }\n        vector<int> tops;\n        for (int ch = 0; ch < 8; ++ch)\n            if ((int)cell_inc_by_char[cell][ch].size() == best_cnt) tops.push_back(ch);\n        init_cur[cell] = (uint8_t)tops[rng() % tops.size()];\n    }\n\n    auto start = chrono::steady_clock::now();\n\n    vector<uint8_t> best_cur = init_cur;\n    int best_matched = -1;\n\n    auto accept_best = [&]() {\n        if (total_matched > best_matched) {\n            best_matched = total_matched;\n            best_cur = cur;\n        }\n    };\n\n    /* ----- phase 1: hill climb from majority vote ----- */\n    recompute_state(init_cur);\n    hill_climb();\n    accept_best();\n\n    /* ----- phase 2: iterated local search (perturb + hill climb) ----- */\n    while (best_matched < M) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() > 1.8) break;\n\n        recompute_state(best_cur);\n        /* perturb */\n        for (int i = 0; i < 30; ++i) {\n            int cell = rng() % 400;\n            int ch = rng() % 8;\n            if (ch == cur[cell]) continue;\n            int d = eval_move(cell, ch);\n            apply_move(cell, ch);\n            total_matched += d;\n        }\n        hill_climb();\n        accept_best();\n    }\n\n    /* ----- phase 3: pure random restarts if still not perfect ----- */\n    while (best_matched < M) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() > 2.0) break;\n\n        vector<uint8_t> rcur(400);\n        for (int i = 0; i < 400; ++i) rcur[i] = (uint8_t)(rng() % 8);\n        recompute_state(rcur);\n        hill_climb();\n        accept_best();\n    }\n\n    /* restore best solution */\n    recompute_state(best_cur);\n\n    vector<string> ans(N, string(N, '.'));\n\n    /* ----- phase 4: dotting by placement selection ----- */\n    if (total_matched == M) {\n        vector<vector<int>> matched_pids(M);\n        for (int pid = 0; pid < P; ++pid) {\n            if (pid_match_cnt[pid] == pid_len[pid])\n                matched_pids[pid_sid[pid]].push_back(pid);\n        }\n\n        int best_kept = 400;\n        vector<char> best_keep(400, 1);\n        vector<int> cell_ref(400);\n        vector<int> sel(M);\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 2.95) break;\n\n            fill(cell_ref.begin(), cell_ref.end(), 0);\n            int kept = 0;\n            for (int sid = 0; sid < M; ++sid) {\n                const auto& v = matched_pids[sid];\n                int pid = v[rng() % v.size()];\n                sel[sid] = pid;\n                int off = pid_off[pid];\n                int len = pid_len[pid];\n                for (int i = 0; i < len; ++i) {\n                    int cell = flat_cells[off + i];\n                    if (cell_ref[cell] == 0) ++kept;\n                    ++cell_ref[cell];\n                }\n            }\n\n            bool improved = true;\n            while (improved) {\n                improved = false;\n                shuffle(order.begin(), order.end(), rng);\n                for (int sid : order) {\n                    if (matched_pids[sid].size() <= 1) continue;\n                    int cur_pid = sel[sid];\n                    int cur_off = pid_off[cur_pid];\n                    int cur_len = pid_len[cur_pid];\n                    int best_delta = 0;\n                    int best_pid = cur_pid;\n                    for (int pid : matched_pids[sid]) {\n                        if (pid == cur_pid) continue;\n                        int delta = 0;\n                        int off = pid_off[pid];\n                        int len = pid_len[pid];\n                        for (int i = 0; i < cur_len; ++i) {\n                            int cell = flat_cells[cur_off + i];\n                            if (cell_ref[cell] == 1) --delta;\n                        }\n                        for (int i = 0; i < len; ++i) {\n                            int cell = flat_cells[off + i];\n                            if (cell_ref[cell] == 0) ++delta;\n                        }\n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_pid = pid;\n                        }\n                    }\n                    if (best_delta < 0) {\n                        for (int i = 0; i < cur_len; ++i) {\n                            int cell = flat_cells[cur_off + i];\n                            --cell_ref[cell];\n                            if (cell_ref[cell] == 0) --kept;\n                        }\n                        int new_off = pid_off[best_pid];\n                        int new_len = pid_len[best_pid];\n                        for (int i = 0; i < new_len; ++i) {\n                            int cell = flat_cells[new_off + i];\n                            if (cell_ref[cell] == 0) ++kept;\n                            ++cell_ref[cell];\n                        }\n                        sel[sid] = best_pid;\n                        improved = true;\n                    }\n                }\n            }\n\n            if (kept < best_kept) {\n                best_kept = kept;\n                for (int i = 0; i < 400; ++i) best_keep[i] = (cell_ref[i] > 0);\n            }\n        }\n\n        for (int r = 0; r < N; ++r)\n            for (int c = 0; c < N; ++c) {\n                int cell = r * N + c;\n                if (best_keep[cell]) ans[r][c] = char('A' + cur[cell]);\n            }\n    } else {\n        for (int r = 0; r < N; ++r)\n            for (int c = 0; c < N; ++c)\n                ans[r][c] = char('A' + cur[r * N + c]);\n    }\n\n    for (int r = 0; r < N; ++r)\n        cout << ans[r] << '\\n';\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, si, sj;\n    vector<string> g;\n    vector<vector<int>> w;\n    vector<int> ui, uj;\n    vector<vector<int>> adj;\n    vector< bitset<1024> > cellMask;\n    int Hreq = 0, Vreq = 0, R = 0, S = -1;\n    mt19937 rng;\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    inline int dirMove(int u, int v) const {\n        int i1 = ui[u], j1 = uj[u];\n        int i2 = ui[v], j2 = uj[v];\n        if (i2 == i1 - 1) return 0;\n        if (i2 == i1 + 1) return 1;\n        if (j2 == j1 - 1) return 2;\n        return 3;\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n        rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n\n        // ----- input -----\n        if (!(cin >> N >> si >> sj)) return;\n        g.resize(N);\n        for (int i = 0; i < N; ++i) cin >> g[i];\n        w.assign(N, vector<int>(N, 0));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (g[i][j] != '#') w[i][j] = g[i][j] - '0';\n\n        // ----- build road graph (BFS from start) -----\n        vector<vector<int>> id(N, vector<int>(N, -1));\n        queue<pair<int,int>> q;\n        q.emplace(si, sj);\n        id[si][sj] = 0;\n        ui.push_back(si); uj.push_back(sj);\n        while (!q.empty()) {\n            auto [i, j] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (g[ni][nj] == '#') continue;\n                if (id[ni][nj] == -1) {\n                    id[ni][nj] = (int)ui.size();\n                    ui.push_back(ni);\n                    uj.push_back(nj);\n                    q.emplace(ni, nj);\n                }\n            }\n        }\n        int V = (int)ui.size();\n        S = id[si][sj];\n        adj.assign(V, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1) {\n                    adj[u].push_back(id[ni][nj]);\n                }\n            }\n        }\n\n        // ----- identify long segments -----\n        vector<vector<int>> hId(N, vector<int>(N, -1));\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ) {\n                if (g[i][j] == '#') { ++j; continue; }\n                int j0 = j;\n                while (j < N && g[i][j] != '#') ++j;\n                if (j - j0 >= 2) {\n                    for (int k = j0; k < j; ++k) hId[i][k] = Hreq;\n                    ++Hreq;\n                }\n            }\n        }\n        vector<vector<int>> vId(N, vector<int>(N, -1));\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ) {\n                if (g[i][j] == '#') { ++i; continue; }\n                int i0 = i;\n                while (i < N && g[i][j] != '#') ++i;\n                if (i - i0 >= 2) {\n                    for (int k = i0; k < i; ++k) vId[k][j] = Vreq;\n                    ++Vreq;\n                }\n            }\n        }\n        R = Hreq + Vreq;\n        cellMask.assign(V, bitset<1024>());\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            if (hId[i][j] != -1) cellMask[u].set(hId[i][j]);\n            if (vId[i][j] != -1) cellMask[u].set(Hreq + vId[i][j]);\n        }\n        bitset<1024> allReq;\n        for (int i = 0; i < R; ++i) allReq.set(i);\n\n        // ----- fallback: Dijkstra spanning tree of whole component -----\n        string bestTour;\n        long long bestCost = (1LL << 60);\n        {\n            const int INF = 1e9;\n            vector<int> fd(V, INF), fp(V, -1);\n            using P = pair<int,int>;\n            priority_queue<P, vector<P>, greater<P>> pq;\n            fd[S] = 0; pq.emplace(0, S);\n            while (!pq.empty()) {\n                auto [d, u] = pq.top(); pq.pop();\n                if (d != fd[u]) continue;\n                for (int v : adj[u]) {\n                    int nd = d + w[ui[v]][uj[v]];\n                    if (nd < fd[v]) {\n                        fd[v] = nd;\n                        fp[v] = u;\n                        pq.emplace(nd, v);\n                    }\n                }\n            }\n            vector<vector<int>> fadj(V);\n            for (int u = 0; u < V; ++u) if (fp[u] != -1) {\n                int p = fp[u];\n                fadj[u].push_back(p);\n                fadj[p].push_back(u);\n            }\n            function<void(int,int)> dfs = [&](int u, int p) {\n                for (int v : fadj[u]) if (v != p) {\n                    bestTour.push_back(dc[dirMove(u, v)]);\n                    bestCost += w[ui[v]][uj[v]];\n                    dfs(v, u);\n                    bestTour.push_back(dc[dirMove(v, u)]);\n                    bestCost += w[ui[u]][uj[u]];\n                }\n            };\n            dfs(S, -1);\n        }\n\n        if (R == 0) {\n            cout << \"\\n\";\n            return;\n        }\n\n        const int MAX_ITER = 60;\n\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            vector<char> inTree(V, 0);\n            vector<vector<int>> treeAdj(V);\n            bitset<1024> covered;\n            inTree[S] = 1;\n            covered = cellMask[S];\n            bool bad = false;\n\n            while (covered != allReq) {\n                const int INF = 1e9;\n                vector<int> dist(V, INF);\n                vector<int> parent(V, -1);\n                vector< bitset<1024> > pathMask(V);\n                using P = pair<int,int>;\n                priority_queue<P, vector<P>, greater<P>> pq;\n\n                for (int u = 0; u < V; ++u) {\n                    if (inTree[u]) {\n                        dist[u] = 0;\n                        pq.emplace(0, u);\n                        pathMask[u].reset();\n                    }\n                }\n\n                while (!pq.empty()) {\n                    auto [d, u] = pq.top(); pq.pop();\n                    if (d != dist[u]) continue;\n                    for (int v : adj[u]) {\n                        int nd = d + w[ui[v]][uj[v]];\n                        if (nd < dist[v]) {\n                            dist[v] = nd;\n                            parent[v] = u;\n                            if (inTree[u]) pathMask[v] = cellMask[v];\n                            else {\n                                pathMask[v] = pathMask[u];\n                                pathMask[v] |= cellMask[v];\n                            }\n                            pq.emplace(nd, v);\n                        }\n                    }\n                }\n\n                struct Cand { int v, d, g; };\n                vector<Cand> cands;\n                for (int u = 0; u < V; ++u) {\n                    if (inTree[u]) continue;\n                    bitset<1024> add = pathMask[u] & ~covered;\n                    int gain = (int)add.count();\n                    if (gain > 0) cands.push_back({u, dist[u], gain});\n                }\n                if (cands.empty()) { bad = true; break; }\n\n                int bestV = -1;\n                if (iter % 3 == 0) {\n                    sort(cands.begin(), cands.end(),\n                        [](const Cand& a, const Cand& b) {\n                            return (long long)a.d * b.g < (long long)b.d * a.g;\n                        });\n                    int K = min(3, (int)cands.size());\n                    bestV = cands[rng() % K].v;\n                } else if (iter % 3 == 1) {\n                    sort(cands.begin(), cands.end(),\n                        [](const Cand& a, const Cand& b) {\n                            if (a.g != b.g) return a.g > b.g;\n                            return a.d < b.d;\n                        });\n                    bestV = cands[0].v;\n                } else {\n                    // random uncovered group\n                    vector<int> urg;\n                    for (int r = 0; r < R; ++r)\n                        if (!covered.test(r)) urg.push_back(r);\n                    int rg = urg[rng() % urg.size()];\n                    vector<Cand> rc;\n                    for (auto &c : cands)\n                        if (pathMask[c.v].test(rg)) rc.push_back(c);\n                    if (!rc.empty()) {\n                        sort(rc.begin(), rc.end(),\n                            [](const Cand& a, const Cand& b) { return a.d < b.d; });\n                        int K = min(3, (int)rc.size());\n                        bestV = rc[rng() % K].v;\n                    } else {\n                        bestV = cands[0].v;\n                    }\n                }\n\n                int cur = bestV;\n                while (!inTree[cur]) {\n                    int p = parent[cur];\n                    treeAdj[cur].push_back(p);\n                    treeAdj[p].push_back(cur);\n                    inTree[cur] = 1;\n                    covered |= cellMask[cur];\n                    cur = p;\n                }\n            }\n\n            if (bad || covered != allReq) continue;\n\n            // ---------- prune unnecessary leaves (with proper coverCnt update) ----------\n            vector<char> alive(V, 0);\n            vector<int> deg(V, 0);\n            for (int u = 0; u < V; ++u) {\n                if (inTree[u]) {\n                    alive[u] = 1;\n                    deg[u] = (int)treeAdj[u].size();\n                }\n            }\n            vector<int> coverCnt(R, 0);\n            for (int u = 0; u < V; ++u) if (alive[u]) {\n                for (int r = 0; r < R; ++r)\n                    if (cellMask[u].test(r)) ++coverCnt[r];\n            }\n            queue<int> qq;\n            for (int u = 0; u < V; ++u)\n                if (alive[u] && deg[u] == 1 && u != S) qq.push(u);\n\n            while (!qq.empty()) {\n                int u = qq.front(); qq.pop();\n                if (!alive[u] || deg[u] != 1 || u == S) continue;\n                bool ok = true;\n                for (int r = 0; r < R; ++r) {\n                    if (cellMask[u].test(r) && coverCnt[r] <= 1) { ok = false; break; }\n                }\n                if (!ok) continue;\n                alive[u] = 0;\n                deg[u] = 0;\n                for (int r = 0; r < R; ++r)\n                    if (cellMask[u].test(r)) --coverCnt[r];\n                for (int v : treeAdj[u]) {\n                    if (!alive[v]) continue;\n                    if (--deg[v] == 1 && v != S) qq.push(v);\n                }\n            }\n\n            // ---------- compute cost of the pruned tree ----------\n            vector<vector<int>> prunedAdj(V);\n            for (int u = 0; u < V; ++u) if (alive[u]) {\n                for (int v : treeAdj[u]) if (alive[v] && u < v) {\n                    prunedAdj[u].push_back(v);\n                    prunedAdj[v].push_back(u);\n                }\n            }\n\n            long long treeCost = 0;\n            for (int u = 0; u < V; ++u) {\n                for (int v : prunedAdj[u]) {\n                    if (u < v) treeCost += w[ui[u]][uj[u]] + w[ui[v]][uj[v]];\n                }\n            }\n\n            if (treeCost < bestCost) {\n                bestCost = treeCost;\n                string tour;\n                function<void(int,int)> dfs = [&](int u, int p) {\n                    for (int v : prunedAdj[u]) if (v != p) {\n                        tour.push_back(dc[dirMove(u, v)]);\n                        dfs(v, u);\n                        tour.push_back(dc[dirMove(v, u)]);\n                    }\n                };\n                dfs(S, -1);\n                bestTour = tour;\n            }\n        }\n\n        cout << bestTour << \"\\n\";\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.run();\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\n/* ---------- global data ---------- */\nint N, M, K, R;\nvector<vector<int>> d;          // task difficulties\nvector<vector<int>> out;        // adjacency list of the DAG\nvector<int> crit;               // longest path to sink (number of tasks)\nvector<int> wait_;              // how many days a ready task has been waiting\nvector<vector<double>> s_est;   // estimated skill vectors\nvector<vector<pair<int,int>>> obs; // per worker: (task_id , duration)\nvector<int> tasks_done;         // how many tasks a worker has finished\nvector<int> assigned_task;      // -1 = idle, else running task id\nvector<int> start_day;          // day the current task was started\nvector<int> rem_indeg;          // remaining indegree\nvector<int> ready;              // currently ready tasks\nmt19937 rng(42);\n\n/* predicted cost of assigning task -> worker */\ninline double compute_cost(int task, int worker)\n{\n    double w = 0.0;\n    const vector<int> &dt = d[task];\n    const vector<double> &s = s_est[worker];\n    for (int k = 0; k < K; ++k) {\n        if (dt[k] > s[k]) w += dt[k] - s[k];\n    }\n    double dur = (w < 1.0) ? 1.0 : w;\n    // critical tasks are slightly preferred,\n    // tasks that have waited long are strongly preferred\n    return dur - 0.02 * crit[task] - 0.1 * wait_[task];\n}\n\n/* assign tasks for the coming day */\nvector<pair<int,int>> computeAssignments(int day)\n{\n    vector<pair<int,int>> result;\n    vector<int> idle;\n    idle.reserve(M);\n    for (int j = 0; j < M; ++j)\n        if (assigned_task[j] == -1) idle.push_back(j);\n\n    if (idle.empty() || ready.empty()) return result;\n\n    vector<int> exploring, exploiting;\n    for (int j : idle) {\n        if (tasks_done[j] < 2) exploring.push_back(j);\n        else exploiting.push_back(j);\n    }\n\n    vector<int> avail = ready;\n    shuffle(avail.begin(), avail.end(), rng);\n\n    /* exploration: random tasks for inexperienced workers */\n    for (int j : exploring) {\n        if (avail.empty()) break;\n        int task = avail.back(); avail.pop_back();\n        result.emplace_back(j, task);\n        assigned_task[j] = task;\n        start_day[j] = day;\n    }\n\n    /* exploitation: regret based greedy matching */\n    if (!exploiting.empty() && !avail.empty()) {\n        struct Cand {\n            double score;\n            double best_val;\n            int task;\n            int best_j;\n        };\n        vector<Cand> cands;\n        cands.reserve(avail.size());\n\n        for (int task : avail) {\n            double best_val = 1e100, second_val = 1e100;\n            int best_j = -1;\n            for (int j : exploiting) {\n                double val = compute_cost(task, j);\n                if (val < best_val) {\n                    second_val = best_val;\n                    best_val = val;\n                    best_j = j;\n                } else if (val < second_val) {\n                    second_val = val;\n                }\n            }\n            if (best_j == -1) continue;\n            double regret = (second_val > 1e99/2) ? 1e100 : second_val - best_val;\n            double score = regret - best_val;          // high regret or very low cost\n            score += uniform_real_distribution<double>(0.0, 1e-9)(rng);\n            cands.push_back({score, best_val, task, best_j});\n        }\n\n        sort(cands.begin(), cands.end(),\n             [](const Cand& a, const Cand& b){ return a.score > b.score; });\n\n        vector<char> used(M, 0);\n        for (auto &c : cands) {\n            int j = c.best_j;\n            if (used[j]) {\n                double best2 = 1e100;\n                int j2 = -1;\n                for (int jj : exploiting) {\n                    if (used[jj]) continue;\n                    double v = compute_cost(c.task, jj);\n                    if (v < best2) { best2 = v; j2 = jj; }\n                }\n                if (j2 == -1) continue;\n                j = j2;\n            }\n            if (used[j]) continue;\n            used[j] = 1;\n            result.emplace_back(j, c.task);\n            assigned_task[j] = c.task;\n            start_day[j] = day;\n        }\n    }\n\n    /* erase assigned tasks from the global ready list */\n    vector<char> is_assigned(N, 0);\n    for (auto &p : result) is_assigned[p.second] = 1;\n    vector<int> new_ready;\n    new_ready.reserve(ready.size());\n    for (int task : ready)\n        if (!is_assigned[task]) new_ready.push_back(task);\n    ready.swap(new_ready);\n    return result;\n}\n\n/* ---------- main ---------- */\nint main()\n{\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n    d.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            cin >> d[i][k];\n\n    out.assign(N, {});\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v; cin >> u >> v; --u; --v;\n        out[u].push_back(v);\n        ++indeg[v];\n    }\n\n    crit.assign(N, 1);\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int v : out[i]) best = max(best, crit[v]);\n        crit[i] = best + 1;\n    }\n\n    wait_.assign(N, 0);\n    s_est.assign(M, vector<double>(K, 0.0));\n    obs.assign(M, {});\n    tasks_done.assign(M, 0);\n    assigned_task.assign(M, -1);\n    start_day.assign(M, -1);\n    rem_indeg = indeg;\n    ready.clear();\n    for (int i = 0; i < N; ++i)\n        if (rem_indeg[i] == 0) ready.push_back(i);\n\n    int day = 1;\n    vector<pair<int,int>> assignments = computeAssignments(day);\n\n    while (true) {\n        cout << assignments.size();\n        for (auto &p : assignments)\n            cout << ' ' << p.first + 1 << ' ' << p.second + 1;\n        cout << '\\n';\n        cout.flush();\n\n        int n;  cin >> n;\n        if (n == -1) break;\n        vector<int> completed(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> completed[i];\n            --completed[i];\n        }\n\n        /* tasks that stayed ready and unassigned waited one more day */\n        for (int task : ready) ++wait_[task];\n\n        for (int j : completed) {\n            int task = assigned_task[j];\n            int t = day - start_day[j] + 1;\n\n            obs[j].emplace_back(task, t);\n            ++tasks_done[j];\n\n            const double LR  = 0.2;\n            const double LR2 = 0.01;\n            const int EPOCHS = 3;\n            auto &obsj = obs[j];\n\n            for (int ep = 0; ep < EPOCHS; ++ep) {\n                shuffle(obsj.begin(), obsj.end(), rng);\n                for (const auto &ob : obsj) {\n                    int tid = ob.first;\n                    int dur = ob.second;\n                    const vector<int> &dt = d[tid];\n\n                    double w_pred = 0.0;\n                    vector<int> active;\n                    active.reserve(K);\n                    for (int k = 0; k < K; ++k) {\n                        if (dt[k] > s_est[j][k] + 1e-12) {\n                            w_pred += dt[k] - s_est[j][k];\n                            active.push_back(k);\n                        }\n                    }\n\n                    double target = (dur == 1) ? 1.0 : (double)dur;\n                    double e = w_pred - target;\n                    if (dur == 1) e *= 0.5;\n\n                    if (fabs(e) > 1e-12) {\n                        if (!active.empty()) {\n                            double delta = LR * e / active.size();\n                            if (delta >  3.0) delta =  3.0;\n                            if (delta < -3.0) delta = -3.0;\n                            for (int k : active) s_est[j][k] += delta;\n                        } else if (e < 0) {\n                            double dec = LR2 * (-e) / K;\n                            for (int k = 0; k < K; ++k)\n                                s_est[j][k] = max(0.0, s_est[j][k] - dec);\n                        }\n                        for (int k = 0; k < K; ++k)\n                            if (s_est[j][k] < 0) s_est[j][k] = 0;\n                    }\n                }\n            }\n\n            assigned_task[j] = -1;\n            start_day[j] = -1;\n            for (int v : out[task]) {\n                if (--rem_indeg[v] == 0)\n                    ready.push_back(v);\n            }\n        }\n\n        ++day;\n        if (day > 2000) break;\n        assignments = computeAssignments(day);\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nint X[2001];\nint Y[2001];\nint dist_mat[2001][2001];\ninline int D(int u, int v) { return dist_mat[u][v]; }\n\n/* ---------- insertion evaluation ---------- */\nvoid eval_insert(const vector<int>& route, int oid, int& best_delta, int& best_ip, int& best_id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    int L = (int)route.size();\n    best_delta = INT_MAX;\n    for (int ip = 0; ip < L - 1; ++ip) {\n        int cost_p = D(route[ip], p) + D(p, route[ip + 1]) - D(route[ip], route[ip + 1]);\n        int left = p;\n        for (int id = ip; id < L - 1; ++id) {\n            if (id > ip) left = route[id];\n            int cost_d = D(left, d) + D(d, route[id + 1]) - D(left, route[id + 1]);\n            int delta = cost_p + cost_d;\n            if (delta < best_delta) {\n                best_delta = delta;\n                best_ip = ip;\n                best_id = id;\n            }\n        }\n    }\n}\n\nvoid apply_insert(vector<int>& route, int oid, int ip, int id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() + 2);\n    for (int k = 0; k <= ip; ++k) res.push_back(route[k]);\n    res.push_back(p);\n    for (int k = ip + 1; k <= id; ++k) res.push_back(route[k]);\n    res.push_back(d);\n    for (int k = id + 1; k < (int)route.size(); ++k) res.push_back(route[k]);\n    route.swap(res);\n}\n\nvector<int> remove_order(const vector<int>& route, int oid) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() - 2);\n    for (int node : route) if (node != p && node != d) res.push_back(node);\n    return res;\n}\n\nint route_cost(const vector<int>& route) {\n    int sum = 0;\n    for (int i = 0; i + 1 < (int)route.size(); ++i) sum += D(route[i], route[i + 1]);\n    return sum;\n}\n\n/* ---------- route local search ---------- */\nbool optimize_pass(vector<int>& route, int& cost) {\n    int n = (int)route.size();\n    array<int, 2001> pos;\n    pos.fill(-1);\n    for (int i = 0; i < n; ++i) pos[route[i]] = i;\n    array<int, 2001> pp;\n    for (int i = 0; i < n; ++i) pp[i] = pos[route[i] ^ 1];\n\n    int best_delta = 0;\n    int best_type = -1;          // 0 swap, 1 2opt, 2 relocate\n    int b_i = 0, b_j = 0, b_l = 0, b_r = 0;\n\n    // 1. swap\n    for (int i = 1; i < n - 1; ++i) {\n        for (int j = i + 1; j < n - 1; ++j) {\n            int u = route[i], v = route[j];\n            if ((u ^ 1) == v) continue;               // same order\n            if ((u & 1) && pp[i] <= j) continue;       // u is pickup, partner not after j\n            if (!(v & 1) && pp[j] >= i) continue;      // v is delivery, partner not before i\n            int delta;\n            if (j == i + 1) {\n                delta = D(route[i - 1], v) + D(v, u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, v) - D(v, route[j + 1]);\n            } else {\n                delta = D(route[i - 1], v) + D(v, route[i + 1])\n                      + D(route[j - 1], u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, route[i + 1])\n                      - D(route[j - 1], v) - D(v, route[j + 1]);\n            }\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 0; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    // 2. 2-opt (segment reversal)\n    for (int l = 1; l < n - 1; ++l) {\n        for (int r = l + 1; r < n - 1; ++r) {\n            bool ok = true;\n            for (int k = l; k <= r; ++k) {\n                if (pp[k] >= l && pp[k] <= r) { ok = false; break; }\n            }\n            if (!ok) continue;\n            int delta = D(route[l - 1], route[r]) + D(route[l], route[r + 1])\n                      - D(route[l - 1], route[l]) - D(route[r], route[r + 1]);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 1; b_l = l; b_r = r;\n            }\n        }\n    }\n\n    // 3. relocate single node\n    for (int i = 1; i < n - 1; ++i) {\n        int u = route[i];\n        int A = route[i - 1], B = route[i + 1];\n        int delta_remove = D(A, B) - D(A, u) - D(u, B);\n        // move left: j < i\n        for (int j = 1; j < i; ++j) {\n            if (!(u & 1) && j <= pp[i]) continue; // delivery cannot pass its pickup\n            int left = route[j - 1], right = route[j];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n        // move right: j > i  (j is position in new route of size n-1, valid 1..n-2)\n        for (int j = i + 1; j < n - 1; ++j) {\n            if ((u & 1) && j >= pp[i]) continue; // pickup cannot pass its delivery\n            int left = route[j], right = route[j + 1];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    if (best_type == -1) return false;\n\n    if (best_type == 0) {\n        swap(route[b_i], route[b_j]);\n    } else if (best_type == 1) {\n        reverse(route.begin() + b_l, route.begin() + b_r + 1);\n    } else {\n        int u = route[b_i];\n        route.erase(route.begin() + b_i);\n        route.insert(route.begin() + b_j, u);\n    }\n    cost += best_delta;\n    return true;\n}\n\nvoid optimize_route(vector<int>& route, int& cost) {\n    int cnt = 0;\n    while (optimize_pass(route, cost)) {\n        if (++cnt > 2000) break; // safety break\n    }\n}\n\n/* ---------- greedy construction ---------- */\nstruct State {\n    vector<int> route;\n    vector<int> selected;\n    int cost;\n};\n\nState greedy_build(bool use_rand, int rand_k, mt19937& rng) {\n    State st;\n    st.route = {0, 0};\n    st.selected.reserve(50);\n    vector<char> used(1000, 0);\n    struct Cand { int delta, oid, ip, id; };\n    for (int step = 0; step < 50; ++step) {\n        vector<Cand> cands;\n        cands.reserve(1000);\n        for (int oid = 0; oid < 1000; ++oid) if (!used[oid]) {\n            int d, ip, id;\n            eval_insert(st.route, oid, d, ip, id);\n            cands.push_back({d, oid, ip, id});\n        }\n        sort(cands.begin(), cands.end(),\n             [](const Cand& a, const Cand& b){ return a.delta < b.delta; });\n        int pick = 0;\n        if (use_rand && rand_k > 1 && (int)cands.size() > 1) {\n            int k = min(rand_k, (int)cands.size());\n            pick = uniform_int_distribution<int>(0, k - 1)(rng);\n        }\n        const Cand& c = cands[pick];\n        apply_insert(st.route, c.oid, c.ip, c.id);\n        used[c.oid] = 1;\n        st.selected.push_back(c.oid);\n    }\n    st.cost = route_cost(st.route);\n    return st;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    vector<int> A(1000), B_(1000), C(1000), D_(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> A[i] >> B_[i] >> C[i] >> D_[i];\n    }\n\n    X[0] = Y[0] = 400;\n    for (int i = 0; i < 1000; ++i) {\n        X[2 * i + 1] = A[i]; Y[2 * i + 1] = B_[i];\n        X[2 * i + 2] = C[i]; Y[2 * i + 2] = D_[i];\n    }\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist_mat[i][j] = abs(X[i] - X[j]) + abs(Y[i] - Y[j]);\n\n    vector<int> standalone(1000);\n    for (int i = 0; i < 1000; ++i)\n        standalone[i] = D(0, 2 * i + 1) + D(2 * i + 1, 2 * i + 2) + D(2 * i + 2, 0);\n\n    vector<int> order_ids(1000);\n    iota(order_ids.begin(), order_ids.end(), 0);\n    sort(order_ids.begin(), order_ids.end(),\n         [&](int a, int b){ return standalone[a] < standalone[b]; });\n\n    mt19937 rng(42);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]()->double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n    const double TL = 1.95;\n\n    State best = greedy_build(false, 0, rng);\n    optimize_route(best.route, best.cost);\n\n    // ------- set improvement -------\n    while (elapsed() < TL * 0.70) {\n        vector<char> in_sel(1000, 0);\n        for (int oid : best.selected) in_sel[oid] = 1;\n        vector<int> cand_out;\n        for (int oid : order_ids) {\n            if (!in_sel[oid]) {\n                cand_out.push_back(oid);\n                if ((int)cand_out.size() >= 200) break;\n            }\n        }\n\n        int best_in = -1, best_out = -1, best_ip = -1, best_id = -1;\n        int best_new_cost = best.cost;\n\n        for (int oid_in : best.selected) {\n            if (elapsed() > TL * 0.70) break;\n            vector<int> tmp = remove_order(best.route, oid_in);\n            int tmp_cost = route_cost(tmp);\n            for (int oid_out : cand_out) {\n                int dlt, ip, id;\n                eval_insert(tmp, oid_out, dlt, ip, id);\n                int ncost = tmp_cost + dlt;\n                if (ncost < best_new_cost) {\n                    best_new_cost = ncost;\n                    best_in = oid_in;\n                    best_out = oid_out;\n                    best_ip = ip;\n                    best_id = id;\n                }\n            }\n        }\n\n        if (best_in == -1) break;\n\n        vector<int> new_route = remove_order(best.route, best_in);\n        apply_insert(new_route, best_out, best_ip, best_id);\n        best.route = move(new_route);\n        best.cost = best_new_cost;\n        for (int& oid : best.selected) if (oid == best_in) { oid = best_out; break; }\n\n        optimize_route(best.route, best.cost);\n    }\n\n    // ------- random restarts with remaining time -------\n    int restart = 0;\n    while (elapsed() < TL && restart < 4) {\n        ++restart;\n        State cand = greedy_build(true, 3, rng);\n        optimize_route(cand.route, cand.cost);\n        if (cand.cost < best.cost) best = move(cand);\n    }\n\n    // ------- output -------\n    cout << best.selected.size();\n    for (int oid : best.selected) cout << ' ' << (oid + 1);\n    cout << \"\\n\";\n    cout << best.route.size();\n    for (int node : best.route) cout << ' ' << X[node] << ' ' << Y[node];\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*** DSU ***/\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool same(int x, int y) { return find(x) == find(y); }\n    bool unite(int x, int y) {\n        x = find(x); y = find(y);\n        if (x == y) return false;\n        if (r[x] < r[y]) swap(x, y);\n        p[y] = x;\n        if (r[x] == r[y]) ++r[x];\n        return true;\n    }\n};\n\n/*** LCA on tier-0 tree to obtain max d on the tree path ***/\nstruct LCA {\n    int n, LOG;\n    vector<vector<pair<int,long long>>> adj;\n    vector<vector<int>> up;\n    vector<vector<long long>> mx;\n    vector<int> dep;\n    LCA(int n = 0) { init(n); }\n    void init(int n_) {\n        n = n_;\n        LOG = 1;\n        while ((1 << LOG) <= n) ++LOG;\n        adj.assign(n, {});\n        up.assign(LOG, vector<int>(n, -1));\n        mx.assign(LOG, vector<long long>(n, 0));\n        dep.assign(n, 0);\n    }\n    void add_edge(int u, int v, long long w) {\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n    void dfs(int v, int p, int d) {\n        up[0][v] = p;\n        dep[v] = d;\n        for (auto [to, w] : adj[v]) {\n            if (to == p) continue;\n            mx[0][to] = w;\n            dfs(to, v, d + 1);\n        }\n    }\n    void build(int root = 0) {\n        dfs(root, -1, 0);\n        for (int k = 1; k < LOG; ++k) {\n            for (int v = 0; v < n; ++v) {\n                if (up[k-1][v] != -1) {\n                    up[k][v] = up[k-1][ up[k-1][v] ];\n                    mx[k][v] = max(mx[k-1][v], mx[k-1][ up[k-1][v] ]);\n                }\n            }\n        }\n    }\n    long long query(int u, int v) const {\n        if (u == v) return 0;\n        if (dep[u] < dep[v]) swap(u, v);\n        long long res = 0;\n        int diff = dep[u] - dep[v];\n        for (int k = 0; k < LOG; ++k) {\n            if (diff >> k & 1) {\n                res = max(res, mx[k][u]);\n                u = up[k][u];\n            }\n        }\n        if (u == v) return res;\n        for (int k = LOG - 1; k >= 0; --k) {\n            if (up[k][u] != -1 && up[k][u] != up[k][v]) {\n                res = max(res, mx[k][u]);\n                res = max(res, mx[k][v]);\n                u = up[k][u];\n                v = up[k][v];\n            }\n        }\n        res = max(res, mx[0][u]);\n        res = max(res, mx[0][v]);\n        return res;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<long long> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) cin >> U[i] >> V[i];\n\n    vector<long long> d(M);\n    for (int i = 0; i < M; ++i) {\n        long long dx = xs[U[i]] - xs[V[i]];\n        long long dy = ys[U[i]] - ys[V[i]];\n        long long dist2 = dx * dx + dy * dy;\n        d[i] = llround(sqrt((double)dist2));\n    }\n\n    /*--- assign tiers 0..4 by repeated Kruskal on the rounded distances ---*/\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) { return d[a] < d[b]; });\n\n    vector<char> used(M, 0);\n    vector<int> tier(M, -1);\n    for (int t = 0; t < 5; ++t) {\n        DSU dsu(N);\n        int cnt = 0;\n        for (int idx : order) {\n            if (used[idx]) continue;\n            if (dsu.unite(U[idx], V[idx])) {\n                used[idx] = 1;\n                tier[idx] = t;\n                ++cnt;\n                if (cnt == N - 1) break;\n            }\n        }\n    }\n\n    /*--- LCA structure on tier-0 tree (the d-MST) ---*/\n    LCA lca(N);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) lca.add_edge(U[i], V[i], d[i]);\n    }\n    lca.build(0);\n\n    vector<long long> maxd_path(M, 0);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) maxd_path[i] = d[i];\n        else               maxd_path[i] = lca.query(U[i], V[i]);\n    }\n\n    DSU dsu(N);\n    int comp = N;\n\n    for (int i = 0; i < M; ++i) {\n        long long l;\n        cin >> l;\n        int u = U[i], v = V[i];\n\n        /* already connected -> useless */\n        if (dsu.same(u, v)) {\n            cout << 0 << '\\n' << flush;\n            continue;\n        }\n\n        /* \n         * Check whether edge i is a bridge in the remaining graph\n         * (adopted edges + all future edges).  \n         * Also count how many future edges still connect different components.\n         */\n        DSU tmp = dsu;\n        int future_useful = 0;\n        for (int j = i + 1; j < M; ++j) {\n            if (!dsu.same(U[j], V[j])) {\n                ++future_useful;\n                tmp.unite(U[j], V[j]);\n            }\n        }\n        bool forced = !tmp.same(u, v);   // no alternative path -> must take\n        bool accept = false;\n\n        if (forced) {\n            accept = true;\n        } else {\n            int need = comp - 1;          // merges still required\n            double slack = (double)future_useful / need; // >= 1 because graph stays connected\n\n            // threshold tightens when slack shrinks (few alternatives left)\n            double t = 1.5 + 1.5 * max(0.0, min(1.0, (5.0 - slack) / 4.0));\n            double ratio = (double)l / (double)d[i];\n\n            // tier-0 edges (smallest d) get the largest bonus, tier-4 the smallest\n            double thr_rel = max(1.0, t + 0.5 - tier[i] * 0.3);\n            if (ratio <= thr_rel) {\n                accept = true;\n            } else if (tier[i] > 0) {\n                // compare with the best alternative path in the d-MST\n                double thr_abs = (double)maxd_path[i] * (1.3 + 0.3 * t);\n                if ((double)l <= thr_abs) accept = true;\n            }\n        }\n\n        if (accept) {\n            cout << 1 << '\\n' << flush;\n            dsu.unite(u, v);\n            --comp;\n        } else {\n            cout << 0 << '\\n' << flush;\n        }\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int MAX_TURN = 300;\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char BUILD[4] = {'u', 'd', 'l', 'r'};\nconst char MOVE[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n};\n\nbool in_bounds(int x, int y) {\n    return x >= 0 && x < H && y >= 0 && y < W;\n}\n\nchar build_action(int hx, int hy, int wx, int wy) {\n    if (wx == hx - 1 && wy == hy) return 'u';\n    if (wx == hx + 1 && wy == hy) return 'd';\n    if (wx == hx && wy == hy - 1) return 'l';\n    if (wx == hx && wy == hy + 1) return 'r';\n    return '.';\n}\n\nchar move_action(int hx, int hy, int nx, int ny) {\n    if (nx == hx - 1 && ny == hy) return 'U';\n    if (nx == hx + 1 && ny == hy) return 'D';\n    if (nx == hx && ny == hy - 1) return 'L';\n    if (nx == hx && ny == hy + 1) return 'R';\n    return '.';\n}\n\nPos get_inside_build_pos(int wx, int wy, int r1, int c1, int r2, int c2) {\n    for (int d = 0; d < 4; ++d) {\n        int nx = wx + dx[d], ny = wy + dy[d];\n        if (nx >= r1 && nx <= r2 && ny >= c1 && ny <= c2) return {nx, ny};\n    }\n    return {-1, -1};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pos> pet_pos(N);\n    vector<int> pet_type(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].x >> pet_pos[i].y >> pet_type[i];\n        --pet_pos[i].x; --pet_pos[i].y;\n    }\n\n    int M;\n    cin >> M;\n    vector<Pos> human_pos(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].x >> human_pos[i].y;\n        --human_pos[i].x; --human_pos[i].y;\n    }\n\n    vector<vector<bool>> passable(H, vector<bool>(W, true));\n    vector<vector<bool>> has_pet(H, vector<bool>(W, false));\n    vector<vector<bool>> has_human(H, vector<bool>(W, false));\n\n    auto update_occupancy = [&]() {\n        for (int i = 0; i < H; ++i) {\n            fill(has_pet[i].begin(), has_pet[i].end(), false);\n            fill(has_human[i].begin(), has_human[i].end(), false);\n        }\n        for (auto &p : pet_pos) has_pet[p.x][p.y] = true;\n        for (auto &h : human_pos) has_human[h.x][h.y] = true;\n    };\n    update_occupancy();\n\n    // Prefix sum of initial pets for fast rectangle queries\n    vector<vector<int>> pet_ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            pet_ps[i + 1][j + 1] = pet_ps[i][j + 1] + pet_ps[i + 1][j] - pet_ps[i][j] + (has_pet[i][j] ? 1 : 0);\n        }\n    }\n    auto rect_pet_cnt = [&](int r1, int c1, int r2, int c2) -> int {\n        if (r1 > r2 || c1 > c2) return 0;\n        return pet_ps[r2 + 1][c2 + 1] - pet_ps[r1][c2 + 1] - pet_ps[r2 + 1][c1] + pet_ps[r1][c1];\n    };\n\n    // Find best rectangle (strongly prefer corners / edges for fewer walls)\n    int best_r1 = 0, best_c1 = 0, best_r2 = 0, best_c2 = 0;\n    int best_score = -1e9;\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    int petcnt = rect_pet_cnt(r1, c1, r2, c2);\n                    if (petcnt > 2) continue; // accept 0-2 initial pets\n\n                    int walls = 0;\n                    if (r1 > 0) walls += (c2 - c1 + 1);\n                    if (r2 < H - 1) walls += (c2 - c1 + 1);\n                    if (c1 > 0) walls += (r2 - r1 + 1);\n                    if (c2 < W - 1) walls += (r2 - r1 + 1);\n\n                    int corner_bonus = 0;\n                    bool is_corner = ((r1 == 0 && c1 == 0) || (r1 == 0 && c2 == W - 1) ||\n                                      (r2 == H - 1 && c1 == 0) || (r2 == H - 1 && c2 == W - 1));\n                    if (is_corner) corner_bonus = 5000;\n                    else if (r1 == 0 || r2 == H - 1 || c1 == 0 || c2 == W - 1) corner_bonus = 1000;\n\n                    int sumd = 0;\n                    for (auto &h : human_pos) {\n                        int tx = max(r1, min(h.x, r2));\n                        int ty = max(c1, min(h.y, c2));\n                        sumd += abs(h.x - tx) + abs(h.y - ty);\n                    }\n\n                    int score = area * 10 - walls * 8 - sumd * 2 - petcnt * 200 + corner_bonus;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1; best_c1 = c1;\n                        best_r2 = r2; best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n\n    int R1 = best_r1, C1 = best_c1, R2 = best_r2, C2 = best_c2;\n\n    // Generate wall cells (cells just outside the rectangle)\n    vector<Pos> all_walls;\n    if (R1 > 0) for (int c = C1; c <= C2; ++c) all_walls.push_back({R1 - 1, c});\n    if (R2 < H - 1) for (int c = C1; c <= C2; ++c) all_walls.push_back({R2 + 1, c});\n    if (C1 > 0) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C1 - 1});\n    if (C2 < W - 1) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C2 + 1});\n\n    // Choose gate: prefer a wall cell that touches the board edge (only 1 outside neighbor after pre-walls)\n    Pos gate = {-1, -1};\n    if (!all_walls.empty()) {\n        vector<Pos> candidates;\n        // Ends of walls that lie on the board boundary are ideal gates\n        if (R2 < H - 1 && C1 == 0) candidates.push_back({R2 + 1, C1});\n        if (R1 == 0 && C2 < W - 1) candidates.push_back({R1, C2 + 1});\n        if (R1 > 0 && C1 == 0) candidates.push_back({R1 - 1, C1});\n        if (R2 == H - 1 && C2 < W - 1) candidates.push_back({R2, C2 + 1});\n        if (R1 == 0 && C1 > 0) candidates.push_back({R1, C1 - 1});\n        if (R2 < H - 1 && C2 == W - 1) candidates.push_back({R2 + 1, C2});\n        if (R1 > 0 && C2 == W - 1) candidates.push_back({R1 - 1, C2});\n        if (R2 == H - 1 && C1 > 0) candidates.push_back({R2, C1 - 1});\n\n        set<pair<int,int>> wall_set;\n        for (auto &w : all_walls) wall_set.insert({w.x, w.y});\n        vector<Pos> valid;\n        for (auto &c : candidates) if (wall_set.count({c.x, c.y})) valid.push_back(c);\n\n        if (!valid.empty()) {\n            int best = -1;\n            for (auto &c : valid) {\n                int mind = 1e9;\n                for (auto &p : pet_pos) mind = min(mind, abs(c.x - p.x) + abs(c.y - p.y));\n                if (mind > best) {\n                    best = mind;\n                    gate = c;\n                }\n            }\n        } else {\n            // fallback: farthest from any initial pet\n            int best = -1;\n            for (auto &w : all_walls) {\n                int mind = 1e9;\n                for (auto &p : pet_pos) mind = min(mind, abs(w.x - p.x) + abs(w.y - p.y));\n                if (mind > best) {\n                    best = mind;\n                    gate = w;\n                }\n            }\n        }\n    }\n\n    // Pre-walls are everything except the gate\n    vector<Pos> pre_walls;\n    set<pair<int,int>> gate_set;\n    if (gate.x != -1) gate_set.insert({gate.x, gate.y});\n    for (auto &w : all_walls) {\n        if (!gate_set.count({w.x, w.y})) pre_walls.push_back(w);\n    }\n\n    // Pre-walls adjacent to the gate are highest priority (they eliminate pet camping spots)\n    vector<bool> prewall_adj_gate(pre_walls.size(), false);\n    if (gate.x != -1) {\n        for (int i = 0; i < (int)pre_walls.size(); ++i) {\n            if (abs(pre_walls[i].x - gate.x) + abs(pre_walls[i].y - gate.y) == 1)\n                prewall_adj_gate[i] = true;\n        }\n    }\n\n    auto can_build = [&](int wx, int wy) -> bool {\n        if (!passable[wx][wy]) return false;\n        if (has_pet[wx][wy] || has_human[wx][wy]) return false;\n        for (int d = 0; d < 4; ++d) {\n            int ax = wx + dx[d], ay = wy + dy[d];\n            if (in_bounds(ax, ay) && has_pet[ax][ay]) return false;\n        }\n        return true;\n    };\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        update_occupancy();\n\n        string action(M, '.');\n        vector<vector<bool>> move_blocked(H, vector<bool>(W));\n        for (int x = 0; x < H; ++x)\n            for (int y = 0; y < W; ++y)\n                move_blocked[x][y] = !passable[x][y];\n\n        bool all_inside = true;\n        for (auto &h : human_pos) {\n            if (!(h.x >= R1 && h.x <= R2 && h.y >= C1 && h.y <= C2)) {\n                all_inside = false;\n                break;\n            }\n        }\n\n        vector<bool> prewall_built(pre_walls.size());\n        for (int i = 0; i < (int)pre_walls.size(); ++i)\n            prewall_built[i] = !passable[pre_walls[i].x][pre_walls[i].y];\n        bool all_prewalls_built = true;\n        for (bool b : prewall_built) if (!b) { all_prewalls_built = false; break; }\n\n        vector<bool> human_acted(M, false);\n\n        // 1) Close the gate if everybody is inside and all pre-walls are done\n        if (all_inside && all_prewalls_built && gate.x != -1 && passable[gate.x][gate.y]) {\n            for (int i = 0; i < M; ++i) {\n                if (abs(human_pos[i].x - gate.x) + abs(human_pos[i].y - gate.y) != 1) continue;\n                if (!can_build(gate.x, gate.y)) continue;\n                action[i] = build_action(human_pos[i].x, human_pos[i].y, gate.x, gate.y);\n                human_acted[i] = true;\n                move_blocked[gate.x][gate.y] = true; // becomes impassable this turn\n                break;\n            }\n        }\n\n        // 2) Build pre-walls (prioritize gate-adjacent walls to remove camping spots)\n        vector<bool> prewall_assigned(pre_walls.size(), false);\n        for (int i = 0; i < M; ++i) {\n            if (human_acted[i]) continue;\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n            int best_j = -1, best_pri = -1;\n            for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                if (prewall_built[j] || prewall_assigned[j]) continue;\n                int wx = pre_walls[j].x, wy = pre_walls[j].y;\n                if (abs(hx - wx) + abs(hy - wy) != 1) continue;\n                if (!can_build(wx, wy)) continue;\n                int pri = prewall_adj_gate[j] ? 1000 : 0;\n                if (pri > best_pri) {\n                    best_pri = pri;\n                    best_j = j;\n                }\n            }\n            if (best_j != -1) {\n                int wx = pre_walls[best_j].x, wy = pre_walls[best_j].y;\n                action[i] = build_action(hx, hy, wx, wy);\n                human_acted[i] = true;\n                prewall_assigned[best_j] = true;\n                move_blocked[wx][wy] = true;\n            }\n        }\n\n        // 3) Move remaining humans\n        for (int i = 0; i < M; ++i) {\n            if (human_acted[i]) continue;\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n            bool inside = (hx >= R1 && hx <= R2 && hy >= C1 && hy <= C2);\n\n            Pos target = {-1, -1};\n            if (!inside) {\n                // Head toward the nearest cell inside the rectangle\n                target = {max(R1, min(hx, R2)), max(C1, min(hy, C2))};\n            } else {\n                // Inside: go build any remaining pre-wall\n                int bestd = 1e9;\n                for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                    if (prewall_built[j] || prewall_assigned[j]) continue;\n                    Pos bp = get_inside_build_pos(pre_walls[j].x, pre_walls[j].y, R1, C1, R2, C2);\n                    if (bp.x == -1) continue;\n                    int d = abs(hx - bp.x) + abs(hy - bp.y);\n                    if (d < bestd) {\n                        bestd = d;\n                        target = bp;\n                    }\n                }\n                // Nothing left to build: camp on the gate's inside build position\n                if (target.x == -1 && gate.x != -1 && passable[gate.x][gate.y]) {\n                    Pos bp = get_inside_build_pos(gate.x, gate.y, R1, C1, R2, C2);\n                    if (bp.x != -1) target = bp;\n                }\n            }\n\n            if (target.x != -1) {\n                vector<vector<int>> dist(H, vector<int>(W, -1));\n                vector<vector<pair<int,int>>> parent(H, vector<pair<int,int>>(W, {-1,-1}));\n                queue<pair<int,int>> q;\n                dist[hx][hy] = 0;\n                q.push({hx, hy});\n                while (!q.empty()) {\n                    auto [x, y] = q.front(); q.pop();\n                    if (x == target.x && y == target.y) break;\n                    for (int d = 0; d < 4; ++d) {\n                        int nx = x + dx[d], ny = y + dy[d];\n                        if (!in_bounds(nx, ny)) continue;\n                        if (move_blocked[nx][ny]) continue;\n                        if (dist[nx][ny] != -1) continue;\n                        dist[nx][ny] = dist[x][y] + 1;\n                        parent[nx][ny] = {x, y};\n                        q.push({nx, ny});\n                    }\n                }\n                if (dist[target.x][target.y] > 0) {\n                    int cx = target.x, cy = target.y;\n                    while (parent[cx][cy] != make_pair(hx, hy)) {\n                        auto p = parent[cx][cy];\n                        cx = p.first; cy = p.second;\n                    }\n                    action[i] = move_action(hx, hy, cx, cy);\n                } else {\n                    action[i] = '.';\n                }\n            } else {\n                action[i] = '.';\n            }\n        }\n\n        cout << action << endl;\n\n        // Apply human actions to our internal state\n        for (int i = 0; i < M; ++i) {\n            char c = action[i];\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int wx = hx, wy = hy;\n                if (c == 'u') wx--;\n                else if (c == 'd') wx++;\n                else if (c == 'l') wy--;\n                else if (c == 'r') wy++;\n                if (in_bounds(wx, wy)) passable[wx][wy] = false;\n            } else if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int nx = hx, ny = hy;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    human_pos[i] = {nx, ny};\n                }\n            }\n        }\n\n        // Read pet movements\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            for (char c : s) {\n                int nx = pet_pos[i].x, ny = pet_pos[i].y;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    pet_pos[i] = {nx, ny};\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int H = 20;\nconst int W = 20;\nconst int N = H * W;\nconst int L = 200;\n\nint start_id, goal_id;\ndouble P, ONE_MINUS_P;\nint nxt_id[N][4];               // 0:U 1:D 2:L 3:R\nint dist_to_goal[N];\nchar DIRCHAR[4] = {'U', 'D', 'L', 'R'};\nint CMDMAP[256];\n\n// ------------------------------------------------------------\n// RNG\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> uniform01(0.0, 1.0);\n\n// ------------------------------------------------------------\n// full evaluation (standalone)\ndouble full_evaluate(const string& s) {\n    array<double, N> dp{}, ndp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    double score = 0.0;\n    for (int t = 0; t < (int)s.size(); ++t) {\n        int c = CMDMAP[(unsigned char)s[t]];\n        ndp.fill(0.0);\n        double imm = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            double stay = x * P;\n            double move = x * ONE_MINUS_P;\n            ndp[v] += stay;\n            int to = nxt_id[v][c];\n            if (to == goal_id) {\n                imm += move * (401 - (t + 1));\n            } else {\n                ndp[to] += move;\n            }\n        }\n        score += imm;\n        dp.swap(ndp);\n    }\n    return score;\n}\n\n// ------------------------------------------------------------\n// BFS shortest path on the underlying graph (ignoring forgetting)\nvector<char> bfs_shortest_path() {\n    queue<int> q;\n    vector<int> dist(N, -1), par(N, -1), pc(N, -1);\n    dist[start_id] = 0;\n    q.push(start_id);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == goal_id) break;\n        for (int d = 0; d < 4; ++d) {\n            int u = nxt_id[v][d];\n            if (u != v && dist[u] == -1) {\n                dist[u] = dist[v] + 1;\n                par[u] = v;\n                pc[u] = d;\n                q.push(u);\n            }\n        }\n    }\n    if (dist[goal_id] == -1) return {};\n    vector<char> path;\n    int cur = goal_id;\n    while (cur != start_id) {\n        path.push_back(DIRCHAR[pc[cur]]);\n        cur = par[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// monotone D/R path (only down and right)\nvector<char> monotone_path(const vector<string>& hwall,\n                           const vector<string>& vwall,\n                           int si, int sj, int ti, int tj) {\n    vector<vector<bool>> reach(H, vector<bool>(W, false));\n    vector<vector<char>> from(H, vector<char>(W, 0));\n    reach[si][sj] = true;\n    for (int i = si; i <= ti; ++i) {\n        for (int j = sj; j <= tj; ++j) {\n            if (!reach[i][j]) continue;\n            if (i < ti && vwall[i][j] == '0' && !reach[i + 1][j]) {\n                reach[i + 1][j] = true;\n                from[i + 1][j] = 'D';\n            }\n            if (j < tj && hwall[i][j] == '0' && !reach[i][j + 1]) {\n                reach[i][j + 1] = true;\n                from[i][j + 1] = 'R';\n            }\n        }\n    }\n    if (!reach[ti][tj]) return {};\n    vector<char> path;\n    int i = ti, j = tj;\n    while (i != si || j != sj) {\n        char c = from[i][j];\n        path.push_back(c);\n        if (c == 'D') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// greedy open-loop path (minimise expected remaining distance)\nstring greedy_path() {\n    array<double, N> dp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    string s;\n    s.reserve(L);\n    for (int t = 0; t < L; ++t) {\n        int best_c = 3;\n        double best_cost = 1e100;\n        for (int c = 0; c < 4; ++c) {\n            double cost = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = dp[v];\n                if (x == 0.0) continue;\n                int to = nxt_id[v][c];\n                double d = (to == goal_id) ? 0.0 : (double)dist_to_goal[to];\n                cost += x * (P * (double)dist_to_goal[v] + ONE_MINUS_P * d);\n            }\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_c = c;\n            }\n        }\n        s.push_back(DIRCHAR[best_c]);\n        array<double, N> ndp{};\n        ndp.fill(0.0);\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            ndp[v] += x * P;\n            int to = nxt_id[v][best_c];\n            if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n        }\n        dp.swap(ndp);\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Local search structure\nstruct Solver {\n    string cur;\n    double cur_score;\n    vector<array<double, N>> fw;   // size L+1\n    vector<array<double, N>> b;    // size L+1\n    vector<double> pref;           // size L+1\n\n    void init(const string& s) {\n        cur = s;\n        fw.assign(L + 1, {});\n        b.assign(L + 1, {});\n        pref.assign(L + 1, 0.0);\n        fw[0].fill(0.0);\n        fw[0][start_id] = 1.0;\n        for (int t = 0; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                if (x == 0.0) continue;\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        b[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n\n    // O(N) evaluation of changing position pos to command cmd (0..3)\n    double try_mutate(int pos, int cmd) const {\n        double reward = (401 - (pos + 1)) * ONE_MINUS_P;\n        double dot = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double val = P * b[pos + 1][v];\n            int to = nxt_id[v][cmd];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * b[pos + 1][to];\n            dot += fw[pos][v] * val;\n        }\n        return pref[pos] + dot;\n    }\n\n    // apply mutation and incrementally update tables\n    void apply_mutate(int pos, int cmd) {\n        cur[pos] = DIRCHAR[cmd];\n        // forward recompute from pos\n        for (int t = pos; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                if (x == 0.0) continue;\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        // backward recompute from pos down to 0\n        for (int t = pos; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n};\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    CMDMAP['U'] = 0; CMDMAP['D'] = 1; CMDMAP['L'] = 2; CMDMAP['R'] = 3;\n\n    int si, sj, ti, tj;\n    double p_input;\n    if (!(cin >> si >> sj >> ti >> tj >> p_input)) return 0;\n    P = p_input;\n    ONE_MINUS_P = 1.0 - P;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; ++i) cin >> hwall[i];\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; ++i) cin >> vwall[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    // precompute nxt_id\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int v = i * W + j;\n            // U\n            if (i > 0 && vwall[i - 1][j] == '0') nxt_id[v][0] = (i - 1) * W + j;\n            else nxt_id[v][0] = v;\n            // D\n            if (i + 1 < H && vwall[i][j] == '0') nxt_id[v][1] = (i + 1) * W + j;\n            else nxt_id[v][1] = v;\n            // L\n            if (j > 0 && hwall[i][j - 1] == '0') nxt_id[v][2] = i * W + (j - 1);\n            else nxt_id[v][2] = v;\n            // R\n            if (j + 1 < W && hwall[i][j] == '0') nxt_id[v][3] = i * W + (j + 1);\n            else nxt_id[v][3] = v;\n        }\n    }\n\n    // distances to goal (real graph distance)\n    {\n        queue<int> q;\n        vector<int> dist(N, -1);\n        dist[goal_id] = 0;\n        q.push(goal_id);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int u = nxt_id[v][d];\n                if (u != v && dist[u] == -1) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) dist_to_goal[i] = dist[i];\n    }\n\n    // ---------- generate candidates ----------\n    vector<string> candidates;\n\n    auto make_repeat = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        string s;\n        while ((int)s.size() < L) s += string(path.begin(), path.end());\n        s.resize(L);\n        return s;\n    };\n    auto make_stretch = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        int rep = max(1, L / (int)path.size());\n        string s;\n        for (char c : path) s += string(rep, c);\n        while ((int)s.size() < L) s.push_back(path[s.size() % path.size()]);\n        s.resize(L);\n        return s;\n    };\n\n    vector<char> sp = bfs_shortest_path();\n    if (!sp.empty()) {\n        candidates.push_back(make_repeat(sp));\n        candidates.push_back(make_stretch(sp));\n    }\n    vector<char> mono = monotone_path(hwall, vwall, si, sj, ti, tj);\n    if (!mono.empty()) {\n        candidates.push_back(make_repeat(mono));\n        candidates.push_back(make_stretch(mono));\n    }\n    candidates.push_back(greedy_path());\n\n    // some raw directional candidates\n    {\n        string s(L, 'D');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needD); ++i) s[i] = 'D';\n        for (; i < min(L, needD + needR); ++i) s[i] = 'R';\n        candidates.push_back(s);\n    }\n    {\n        string s(L, 'R');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needR); ++i) s[i] = 'R';\n        for (; i < min(L, needR + needD); ++i) s[i] = 'D';\n        candidates.push_back(s);\n    }\n    // random biased\n    for (int k = 0; k < 8; ++k) {\n        string s;\n        for (int i = 0; i < L; ++i) {\n            int r = rng() % 100;\n            if (r < 45) s += 'D';\n            else if (r < 90) s += 'R';\n            else if (r < 95) s += 'L';\n            else s += 'U';\n        }\n        candidates.push_back(s);\n    }\n\n    // evaluate and pick best initial\n    string best_str = string(L, 'R');\n    double best_score = -1.0;\n    for (auto& s : candidates) {\n        if ((int)s.size() != L) continue;\n        double sc = full_evaluate(s);\n        if (sc > best_score) {\n            best_score = sc;\n            best_str = s;\n        }\n    }\n\n    // ---------- local search ----------\n    Solver solver;\n    solver.init(best_str);\n    best_score = solver.cur_score;\n\n    // Hill climbing (coordinate ascent)\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < L; ++i) {\n            int cur_cmd = CMDMAP[(unsigned char)solver.cur[i]];\n            int best_cmd = cur_cmd;\n            double best_sc = solver.cur_score;\n            for (int d = 0; d < 3; ++d) {\n                int nc = (cur_cmd + 1 + d) & 3;\n                double sc = solver.try_mutate(i, nc);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    best_cmd = nc;\n                }\n            }\n            if (best_cmd != cur_cmd) {\n                solver.apply_mutate(i, best_cmd);\n                improved = true;\n                if (solver.cur_score > best_score) {\n                    best_score = solver.cur_score;\n                    best_str = solver.cur;\n                }\n            }\n        }\n    }\n\n    // Simulated Annealing\n    // sample diffs to set initial temperature\n    {\n        vector<double> diffs;\n        for (int k = 0; k < 1000; ++k) {\n            int pos = rng() % L;\n            int cur_cmd = CMDMAP[(unsigned char)solver.cur[pos]];\n            int nd = (cur_cmd + 1 + (rng() % 3)) & 3;\n            double sc = solver.try_mutate(pos, nd);\n            diffs.push_back(abs(sc - solver.cur_score));\n        }\n        sort(diffs.begin(), diffs.end());\n        double T0 = diffs[800];\n        if (T0 < 1e-9) T0 = 1.0;\n        const double T_end = 1e-4;\n        const int MAX_ITER = 300000;\n\n        auto start_time = chrono::steady_clock::now();\n        for (int iter = 0; iter < MAX_ITER; ++iter) {\n            if (iter % 1000 == 0) {\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - start_time).count();\n                if (elapsed > 1.85) break;\n            }\n            double T = T0 * pow(T_end / T0, (double)iter / MAX_ITER);\n            int pos = rng() % L;\n            int cur_cmd = CMDMAP[(unsigned char)solver.cur[pos]];\n            int best_cmd = cur_cmd;\n            double best_mut_sc = solver.cur_score;\n            for (int d = 0; d < 3; ++d) {\n                int nc = (cur_cmd + 1 + d) & 3;\n                double sc = solver.try_mutate(pos, nc);\n                if (sc > best_mut_sc) {\n                    best_mut_sc = sc;\n                    best_cmd = nc;\n                }\n            }\n            if (best_cmd != cur_cmd) {\n                bool accept = false;\n                if (best_mut_sc >= solver.cur_score) {\n                    accept = true;\n                } else if (T > 1e-12) {\n                    double prob = exp((best_mut_sc - solver.cur_score) / T);\n                    if (uniform01(rng) < prob) accept = true;\n                }\n                if (accept) {\n                    solver.apply_mutate(pos, best_cmd);\n                    if (solver.cur_score > best_score) {\n                        best_score = solver.cur_score;\n                        best_str = solver.cur;\n                    }\n                }\n            }\n        }\n    }\n\n    cout << best_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static const int N = 30;\n    static const int V = N * N;          // 900\n    static const int S = V * 4;          // 3600\n\n    // input\n    int base[V];\n\n    // current and best rotation (0..3, but for types 4,5,6,7 only 0/1 are needed)\n    unsigned char cur_rot[V];\n    unsigned char best_rot[V];\n\n    // tables\n    int ft[8][4];                // final tile type after rotation\n    int8_t to[8][4];             // given in statement\n    int active_mask[8];          // bitmask of sides with to[t][d] != -1\n    int cell_i[V], cell_j[V];    // coordinates of each cell index\n\n    // random generator (splitmix64)\n    uint64_t rng;\n    uint64_t rand64() {\n        uint64_t z = (rng += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int rand_int(int m) { return (int)(rand64() % (uint64_t)m); }\n\n    // result of last evaluate()\n    int g_prod, g_sum;\n\n    // directions: left, up, right, down\n    const int di[4] = {0, -1, 0, 1};\n    const int dj[4] = {-1, 0, 1, 0};\n\n    // ------------------------------------------------------------\n    // evaluate current board; sets g_prod = L1*L2, g_sum = L1+L2\n    // ------------------------------------------------------------\n    inline void evaluate(const unsigned char* rot) {\n        alignas(64) int16_t nxt[S];\n        alignas(64) uint8_t vis[S];\n\n        // build successor array\n        for (int idx = 0; idx < V; ++idx) {\n            int t = ft[base[idx]][rot[idx]];\n            int bi = cell_i[idx];\n            int bj = cell_j[idx];\n            int id = idx * 4;\n\n            // d = 0\n            int d2 = to[t][0];\n            int16_t v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id] = v;\n\n            // d = 1\n            d2 = to[t][1];\n            v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id + 1] = v;\n\n            // d = 2\n            d2 = to[t][2];\n            v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id + 2] = v;\n\n            // d = 3\n            d2 = to[t][3];\n            v = -1;\n            if (d2 != -1) {\n                int ni = bi + di[d2];\n                int nj = bj + dj[d2];\n                if ((unsigned)ni < 30u && (unsigned)nj < 30u) {\n                    v = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                }\n            }\n            nxt[id + 3] = v;\n        }\n\n        memset(vis, 0, S);\n        int best1 = 0, best2 = 0;\n\n        for (int s = 0; s < S; ++s) {\n            if (nxt[s] == -1 || vis[s]) continue;\n            int cur = s;\n            while (cur != -1 && !vis[cur]) {\n                vis[cur] = 1;\n                cur = nxt[cur];\n            }\n            if (cur != -1 && vis[cur] == 1) {\n                int len = 1;\n                int c = nxt[cur];\n                while (c != cur) {\n                    ++len;\n                    c = nxt[c];\n                }\n                if (len > best1) {\n                    best2 = best1;\n                    best1 = len;\n                } else if (len > best2) {\n                    best2 = len;\n                }\n            }\n            cur = s;\n            while (cur != -1 && vis[cur] == 1) {\n                vis[cur] = 2;\n                cur = nxt[cur];\n            }\n        }\n\n        g_prod = best1 * best2;\n        g_sum  = best1 + best2;\n    }\n\n    // ------------------------------------------------------------\n    // local greedy score: number of active sides matched with neighbours\n    // ------------------------------------------------------------\n    inline int local_score(int idx, int r, const unsigned char* rot) const {\n        int t = ft[base[idx]][r];\n        int bi = cell_i[idx];\n        int bj = cell_j[idx];\n        int mask = active_mask[t];\n        int sc = 0;\n        for (int d = 0; d < 4; ++d) if (mask >> d & 1) {\n            int ni = bi + di[d];\n            int nj = bj + dj[d];\n            if ((unsigned)ni >= 30u || (unsigned)nj >= 30u) continue;\n            int nidx = ni * N + nj;\n            int nt = ft[base[nidx]][rot[nidx]];\n            if (active_mask[nt] >> ((d + 2) & 3) & 1) ++sc;\n        }\n        return sc;\n    }\n\n    // ------------------------------------------------------------\n    void solve() {\n        // ----- read input -------------------------------------------------\n        for (int i = 0; i < N; ++i) {\n            string line;\n            cin >> line;\n            for (int j = 0; j < N; ++j) {\n                base[i * N + j] = line[j] - '0';\n            }\n        }\n\n        // ----- precomputations --------------------------------------------\n        for (int b = 0; b < 8; ++b) {\n            for (int r = 0; r < 4; ++r) {\n                if (b < 4) ft[b][r] = (b + r) & 3;\n                else if (b < 6) ft[b][r] = 4 + ((b - 4 + r) & 1);\n                else ft[b][r] = 6 + ((b - 6 + r) & 1);\n            }\n        }\n\n        const int8_t to_tbl[8][4] = {\n            { 1, 0,-1,-1},\n            { 3,-1,-1, 0},\n            {-1,-1, 3, 2},\n            {-1, 2, 1,-1},\n            { 1, 0, 3, 2},\n            { 3, 2, 1, 0},\n            { 2,-1, 0,-1},\n            {-1, 3,-1, 1}\n        };\n        memcpy(to, to_tbl, sizeof(to_tbl));\n\n        for (int t = 0; t < 8; ++t) {\n            int m = 0;\n            for (int d = 0; d < 4; ++d) if (to[t][d] != -1) m |= (1 << d);\n            active_mask[t] = m;\n        }\n\n        for (int idx = 0; idx < V; ++idx) {\n            cell_i[idx] = idx / N;\n            cell_j[idx] = idx % N;\n        }\n\n        rng = chrono::steady_clock::now().time_since_epoch().count();\n\n        // ----- random initialisation ---------------------------------------\n        for (int idx = 0; idx < V; ++idx) {\n            if (base[idx] < 4) cur_rot[idx] = (unsigned char)rand_int(4);\n            else               cur_rot[idx] = (unsigned char)rand_int(2);\n        }\n\n        // ----- quick greedy passes -----------------------------------------\n        for (int pass = 0; pass < 2; ++pass) {\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine((unsigned)rand64()));\n            for (int idx : order) {\n                int best_r = cur_rot[idx];\n                int best_sc = local_score(idx, best_r, cur_rot);\n                if (base[idx] < 4) {\n                    for (int d = 1; d < 4; ++d) {\n                        int nr = (best_r + d) & 3;\n                        int sc = local_score(idx, nr, cur_rot);\n                        if (sc > best_sc) {\n                            best_sc = sc;\n                            best_r = nr;\n                        }\n                    }\n                } else {\n                    int nr = best_r ^ 1;\n                    int sc = local_score(idx, nr, cur_rot);\n                    if (sc > best_sc) {\n                        best_sc = sc;\n                        best_r = nr;\n                    }\n                }\n                cur_rot[idx] = (unsigned char)best_r;\n            }\n        }\n\n        // ----- evaluate initial board --------------------------------------\n        evaluate(cur_rot);\n        int best_prod = g_prod;\n        memcpy(best_rot, cur_rot, V);\n\n        const double TIME_LIMIT = 1.9;\n        clock_t start_clock = clock();\n        auto elapsed = [&]() {\n            return double(clock() - start_clock) / CLOCKS_PER_SEC;\n        };\n\n        // ----- Simulated Annealing ----------------------------------------\n        double T_start = 50000.0;\n        double T_end   = 0.1;\n        double logT_start = log(T_start);\n        double logT_end   = log(T_end);\n\n        int cur_prod = g_prod;\n        int cur_sum  = g_sum;\n        int iter = 0;\n        double T = T_start;\n\n        while (elapsed() < TIME_LIMIT - 0.25) {   // leave 0.25s for hill climbing\n            if ((iter & 127) == 0) {\n                double p = elapsed() / (TIME_LIMIT - 0.25);\n                T = exp(logT_start + (logT_end - logT_start) * p);\n            }\n            ++iter;\n\n            int idx = rand_int(V);\n            int old_r = cur_rot[idx];\n            int new_r;\n            if (base[idx] < 4) {\n                new_r = (old_r + 1 + rand_int(3)) & 3;\n            } else {\n                new_r = old_r ^ 1;\n            }\n\n            cur_rot[idx] = (unsigned char)new_r;\n            evaluate(cur_rot);\n            int new_prod = g_prod;\n            int new_sum  = g_sum;\n\n            int64_t new_val = (int64_t)new_prod * 10000LL + new_sum;\n            int64_t old_val = (int64_t)cur_prod * 10000LL + cur_sum;\n            int64_t delta = new_val - old_val;\n\n            bool accept = false;\n            if (delta > 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)delta / T);\n                double r = (rand64() >> 11) * (1.0 / (1ULL << 53));\n                if (r < prob) accept = true;\n            }\n\n            if (accept) {\n                cur_prod = new_prod;\n                cur_sum  = new_sum;\n                if (new_prod > best_prod) {\n                    best_prod = new_prod;\n                    memcpy(best_rot, cur_rot, V);\n                }\n            } else {\n                cur_rot[idx] = (unsigned char)old_r;\n            }\n        }\n\n        // ----- Hill climbing polish ---------------------------------------\n        memcpy(cur_rot, best_rot, V);\n        evaluate(cur_rot);\n        cur_prod = g_prod;\n        cur_sum  = g_sum;\n\n        bool improved = true;\n        while (improved && elapsed() < TIME_LIMIT) {\n            improved = false;\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine((unsigned)rand64()));\n\n            for (int idx : order) {\n                if (elapsed() >= TIME_LIMIT) break;\n                int saved_r = cur_rot[idx];\n                int best_r = saved_r;\n                int best_local_prod = cur_prod;\n                int best_local_sum  = cur_sum;\n\n                if (base[idx] < 4) {\n                    for (int d = 1; d < 4; ++d) {\n                        int nr = (saved_r + d) & 3;\n                        cur_rot[idx] = (unsigned char)nr;\n                        evaluate(cur_rot);\n                        if (g_prod > best_local_prod ||\n                            (g_prod == best_local_prod && g_sum > best_local_sum)) {\n                            best_local_prod = g_prod;\n                            best_local_sum  = g_sum;\n                            best_r = nr;\n                        }\n                    }\n                } else {\n                    int nr = saved_r ^ 1;\n                    cur_rot[idx] = (unsigned char)nr;\n                    evaluate(cur_rot);\n                    if (g_prod > best_local_prod ||\n                        (g_prod == best_local_prod && g_sum > best_local_sum)) {\n                        best_local_prod = g_prod;\n                        best_local_sum  = g_sum;\n                        best_r = nr;\n                    }\n                }\n\n                cur_rot[idx] = (unsigned char)best_r;\n                if (best_local_prod > cur_prod ||\n                    (best_local_prod == cur_prod && best_local_sum > cur_sum)) {\n                    cur_prod = best_local_prod;\n                    cur_sum  = best_local_sum;\n                    improved = true;\n                    if (cur_prod > best_prod) {\n                        best_prod = cur_prod;\n                        memcpy(best_rot, cur_rot, V);\n                    }\n                }\n            }\n        }\n\n        // ----- output -----------------------------------------------------\n        string out;\n        out.reserve(V);\n        for (int i = 0; i < V; ++i) out.push_back(char('0' + best_rot[i]));\n        cout << out << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T, SZ, TARGET;\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dc[4] = {'U', 'D', 'L', 'R'};\nconst int opp[4] = {1, 0, 3, 2};\n\ninline bool inside(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N;\n}\n\nstruct State {\n    array<uint8_t, 100> b;\n    int epos;\n};\n\n/* Evaluate the true objective: size of the largest tree component */\nint evaluate(const array<uint8_t, 100>& b) {\n    bool vis[100] = {};\n    int best = 0;\n    for (int idx = 0; idx < SZ; ++idx) {\n        if (b[idx] == 0 || vis[idx]) continue;\n        int q[100];\n        int qs = 0, qe = 0;\n        q[qe++] = idx;\n        vis[idx] = true;\n        int vcnt = 0;\n        int cells[100];\n        while (qs < qe) {\n            int u = q[qs++];\n            cells[vcnt++] = u;\n            int ui = u / N;\n            int uj = u % N;\n            int t = b[u];\n            // up\n            if (ui > 0) {\n                int v = u - N;\n                if (!vis[v] && b[v] != 0 && (t & 2) && (b[v] & 8)) {\n                    vis[v] = true;\n                    q[qe++] = v;\n                }\n            }\n            // down\n            if (ui + 1 < N) {\n                int v = u + N;\n                if (!vis[v] && b[v] != 0 && (t & 8) && (b[v] & 2)) {\n                    vis[v] = true;\n                    q[qe++] = v;\n                }\n            }\n            // left\n            if (uj > 0) {\n                int v = u - 1;\n                if (!vis[v] && b[v] != 0 && (t & 1) && (b[v] & 4)) {\n                    vis[v] = true;\n                    q[qe++] = v;\n                }\n            }\n            // right\n            if (uj + 1 < N) {\n                int v = u + 1;\n                if (!vis[v] && b[v] != 0 && (t & 4) && (b[v] & 1)) {\n                    vis[v] = true;\n                    q[qe++] = v;\n                }\n            }\n        }\n        int ecnt = 0;\n        for (int k = 0; k < vcnt; ++k) {\n            int u = cells[k];\n            int ui = u / N;\n            int uj = u % N;\n            int t = b[u];\n            if (uj + 1 < N) {\n                int v = u + 1;\n                if (b[v] != 0 && (t & 4) && (b[v] & 1)) ++ecnt;\n            }\n            if (ui + 1 < N) {\n                int v = u + N;\n                if (b[v] != 0 && (t & 8) && (b[v] & 2)) ++ecnt;\n            }\n        }\n        if (ecnt == vcnt - 1) {\n            if (vcnt > best) best = vcnt;\n        }\n    }\n    return best;\n}\n\nState apply_move(const State& s, int d) {\n    State ns = s;\n    int ei = s.epos / N;\n    int ej = s.epos % N;\n    int ni = ei + di[d];\n    int nj = ej + dj[d];\n    int npos = ni * N + nj;\n    ns.b[s.epos] = s.b[npos];\n    ns.b[npos] = 0;\n    ns.epos = npos;\n    return ns;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Local search by depth-limited DFS (depth up to 6)                */\n/* ------------------------------------------------------------------ */\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\nint g_ls_best_score;\nstring g_ls_best_seq;\nint g_ls_max_depth;\nint g_ls_target;\n\nvoid dfs_ls(const State& s, int depth, int last_dir, string& seq) {\n    if (depth == g_ls_max_depth) return;\n    if (g_ls_best_score == g_ls_target) return;\n\n    int ei = s.epos / N;\n    int ej = s.epos % N;\n    int order[4] = {0, 1, 2, 3};\n    for (int i = 3; i > 0; --i) {\n        int j = rng() % (i + 1);\n        swap(order[i], order[j]);\n    }\n\n    for (int idx = 0; idx < 4; ++idx) {\n        int d = order[idx];\n        int ni = ei + di[d];\n        int nj = ej + dj[d];\n        if (!inside(ni, nj)) continue;\n        if (last_dir != -1 && d == opp[last_dir]) continue;\n\n        State ns = apply_move(s, d);\n        int sc = evaluate(ns.b);\n        seq.push_back(dc[d]);\n\n        if (sc > g_ls_best_score) {\n            g_ls_best_score = sc;\n            g_ls_best_seq = seq;\n        } else if (sc == g_ls_best_score && !g_ls_best_seq.empty() && seq.size() < g_ls_best_seq.size()) {\n            g_ls_best_seq = seq;\n        }\n\n        dfs_ls(ns, depth + 1, d, seq);\n        seq.pop_back();\n        if (g_ls_best_score == g_ls_target) return;\n    }\n}\n\n/* Search all paths of length 1..max_depth, return best score and path */\npair<int, string> local_search(const State& s, int cur_score, int last_dir, int max_depth) {\n    g_ls_best_score = cur_score;\n    g_ls_best_seq.clear();\n    g_ls_max_depth = max_depth;\n    g_ls_target = TARGET;\n    string seq;\n    dfs_ls(s, 0, last_dir, seq);\n    return {g_ls_best_score, g_ls_best_seq};\n}\n\n/* ------------------------------------------------------------------ */\n/*  Main driver                                                       */\n/* ------------------------------------------------------------------ */\ninline int char2dir(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3; // 'R'\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    SZ = N * N;\n    TARGET = SZ - 1;\n\n    State init{};\n    init.epos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int v = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;\n            init.b[i * N + j] = static_cast<uint8_t>(v);\n            if (v == 0) init.epos = i * N + j;\n        }\n    }\n\n    int init_score = evaluate(init.b);\n    State best_state = init;\n    string best_path;\n    int best_score = init_score;\n\n    if (best_score == TARGET) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    auto start = chrono::steady_clock::now();\n    auto time_left = [&]() {\n        return 2.8 - chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    auto apply_seq = [&](State& st, string& pth, const string& seq) {\n        for (char c : seq) {\n            st = apply_move(st, char2dir(c));\n            pth.push_back(c);\n        }\n    };\n\n    uniform_int_distribution<int> kick_dist(5, 60);\n    int iteration = 0;\n\n    while (time_left() > 0.0) {\n        ++iteration;\n        if (best_score == TARGET) break;\n\n        State cur;\n        string path;\n        int score;\n\n        /* Decide start point: mostly restart from best, sometimes from init */\n        bool use_best = false;\n        if (!best_path.empty() && (int)best_path.size() + 60 <= T) {\n            use_best = (iteration % 4 != 0); // 3/4 from best, 1/4 from init\n        }\n\n        if (use_best) {\n            cur = best_state;\n            path = best_path;\n            score = best_score;\n        } else {\n            cur = init;\n            path = \"\";\n            score = init_score;\n        }\n\n        /* --- random kick to diversify --- */\n        int kick_len = kick_dist(rng);\n        if ((int)path.size() + kick_len > T) {\n            kick_len = max(0, T - (int)path.size());\n        }\n        for (int k = 0; k < kick_len; ++k) {\n            int ld = path.empty() ? -1 : char2dir(path.back());\n            int ei = cur.epos / N;\n            int ej = cur.epos % N;\n            int order[4] = {0, 1, 2, 3};\n            for (int i = 3; i > 0; --i) {\n                int j = rng() % (i + 1);\n                swap(order[i], order[j]);\n            }\n            bool moved = false;\n            for (int idx = 0; idx < 4; ++idx) {\n                int d = order[idx];\n                if (!inside(ei + di[d], ej + dj[d])) continue;\n                if (ld != -1 && d == opp[ld]) continue;\n                cur = apply_move(cur, d);\n                path.push_back(dc[d]);\n                moved = true;\n                break;\n            }\n            if (!moved) { // cornered: allow undo\n                for (int d = 0; d < 4; ++d) {\n                    if (!inside(ei + di[d], ej + dj[d])) continue;\n                    cur = apply_move(cur, d);\n                    path.push_back(dc[d]);\n                    break;\n                }\n            }\n        }\n        score = evaluate(cur.b);\n        if (score > best_score) {\n            best_score = score;\n            best_state = cur;\n            best_path = path;\n            if (best_score == TARGET) break;\n        }\n\n        /* --- VND climb with depth-limited search --- */\n        while ((int)path.size() < T && time_left() > 0.0) {\n            int ld = path.empty() ? -1 : char2dir(path.back());\n            int max_depth = min(6, T - (int)path.size());\n            auto [bs, bseq] = local_search(cur, score, ld, max_depth);\n            if (bs > score) {\n                apply_seq(cur, path, bseq);\n                score = bs;\n                if (score > best_score) {\n                    best_score = score;\n                    best_state = cur;\n                    best_path = path;\n                    if (best_score == TARGET) break;\n                }\n            } else {\n                break; // local optimum of this neighborhood\n            }\n        }\n    }\n\n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ------------------------------------------------------------\n// Random\n// ------------------------------------------------------------\nuint64_t rng_seed() {\n    return chrono::steady_clock::now().time_since_epoch().count();\n}\nstruct xoshiro256ss {\n    uint64_t s[4];\n    xoshiro256ss(uint64_t seed) {\n        s[0] = splitmix64(seed);\n        s[1] = splitmix64(s[0]);\n        s[2] = splitmix64(s[1]);\n        s[3] = splitmix64(s[2]);\n    }\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;\n        return x ^ (x >> 31);\n    }\n    uint64_t operator()() {\n        uint64_t r = rotl(s[1] * 5, 7) * 9;\n        uint64_t t = s[1] << 17;\n        s[2] ^= s[0];\n        s[3] ^= s[1];\n        s[1] ^= s[2];\n        s[0] ^= s[3];\n        s[2] ^= t;\n        s[3] = rotl(s[3], 45);\n        return r;\n    }\n    static uint64_t rotl(uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n};\nxoshiro256ss rng(rng_seed());\n\nlong long rnd_ll(long long l, long long r) {\n    if (l >= r) return l;\n    return l + (long long)(rng() % (uint64_t)(r - l + 1));\n}\nint rnd_int(int l, int r) {\n    if (l >= r) return l;\n    return l + (int)(rng() % (uint64_t)(r - l + 1));\n}\n\n// ------------------------------------------------------------\n// Geometry / Line helpers\n// ------------------------------------------------------------\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C;          // Ax + By + C = 0\n};\n\nint N, K;\narray<int,11> need{};\nvector<long long> xs, ys;\nint target_score = 0;\n\nLine make_line_pts(long long px, long long py, long long qx, long long qy) {\n    Line L;\n    L.px = px; L.py = py; L.qx = qx; L.qy = qy;\n    L.A = qy - py;\n    L.B = px - qx;\n    L.C = qx*py - px*qy;\n    return L;\n}\n\nlong long egcd_positive(long long a, long long b, long long &x, long long &y) {\n    if (b == 0) {\n        x = 1; y = 0;\n        return a;\n    }\n    long long x1, y1;\n    long long g = egcd_positive(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\n// Find two integer points on Ax+By+C=0 with coordinates in [-1e9,1e9]\nbool get_two_points(long long A, long long B, long long C,\n                    long long &x1, long long &y1, long long &x2, long long &y2) {\n    const long long LIM = 1000000000LL;\n    if (B == 0) {\n        if (A == 0) return false;\n        if (C % A != 0) return false;\n        x1 = -C / A;\n        if (x1 < -LIM || x1 > LIM) return false;\n        y1 = 0;\n        x2 = x1;\n        y2 = 1;\n        if (y2 < -LIM || y2 > LIM) return false;\n        return true;\n    }\n    long long g = std::gcd(std::abs(A), std::abs(B));\n    if (C % g != 0) return false;\n    long long a = A / g;\n    long long b = B / g;\n    long long c = -C / g;               // a*x + b*y = c\n    long long mod = std::abs(b);\n    long long a_mod = ((a % mod) + mod) % mod;\n    long long c_mod = ((c % mod) + mod) % mod;\n    long long inv, tmp;\n    egcd_positive(a_mod, mod, inv, tmp);\n    inv = ((inv % mod) + mod) % mod;\n    long long x0 = (long long)((__int128)c_mod * inv % mod);\n\n    long long t = 0;\n    if (x0 < -LIM) t = (-LIM - x0 + mod - 1) / mod;\n    else if (x0 > LIM) t = -(x0 - LIM + mod - 1) / mod;\n\n    long long x = x0 + mod * t;\n    __int128 num = -(__int128)C - (__int128)A * x;\n    long long y = (long long)(num / B);\n\n    long long step_y = (b > 0) ? -a : a;   // change of y when x increases by mod\n    if (y < -LIM) {\n        long long need_up = -LIM - y;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need_up + abs_sy - 1) / abs_sy;\n            x += mod * dt;\n            y += step_y * dt;\n        }\n    } else if (y > LIM) {\n        long long need_down = y - LIM;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need_down + abs_sy - 1) / abs_sy;\n            x -= mod * dt;\n            y -= step_y * dt;\n        }\n    }\n    if (x < -LIM || x > LIM || y < -LIM || y > LIM) return false;\n\n    x1 = x; y1 = y;\n    x2 = x1 + mod;\n    if (x2 > LIM) x2 = x1 - mod;\n    __int128 num2 = -(__int128)C - (__int128)A * x2;\n    y2 = (long long)(num2 / B);\n\n    // *** fix: second point must also be inside the allowed square ***\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) return false;\n    if (x1 == x2 && y1 == y2) return false;\n    return true;\n}\n\nbool intersects_disk(const Line& L) {\n    __int128 c2 = (__int128)L.C * L.C;\n    __int128 ab2 = (__int128)L.A * L.A + (__int128)L.B * L.B;\n    return c2 < ab2 * 100000000LL;   // radius 1e4, squared 1e8\n}\n\nbool valid_line(const Line& L) {\n    const long long LIM = 1000000000LL;\n    if (L.px < -LIM || L.px > LIM || L.py < -LIM || L.py > LIM) return false;\n    if (L.qx < -LIM || L.qx > LIM || L.qy < -LIM || L.qy > LIM) return false;\n    if (L.px == L.qx && L.py == L.qy) return false;\n    if (!intersects_disk(L)) return false;\n    for (int i = 0; i < N; ++i) {\n        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n        if (v == 0) return false;\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// Candidate generators\n// ------------------------------------------------------------\nLine gen_random_line() {\n    const long long LIM = 200000;\n    while (true) {\n        long long x1 = rnd_ll(-LIM, LIM);\n        long long y1 = rnd_ll(-LIM, LIM);\n        long long x2 = rnd_ll(-LIM, LIM);\n        long long y2 = rnd_ll(-LIM, LIM);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n}\n\nLine gen_separator_line() {\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        int i = rnd_int(0, N - 1);\n        int j = rnd_int(0, N - 1);\n        if (i == j) continue;\n        long long xi = xs[i], yi = ys[i];\n        long long xj = xs[j], yj = ys[j];\n        long long A = xj - xi;\n        long long B = yj - yi;\n        if (A == 0 && B == 0) continue;\n        __int128 rhs = (__int128)xj*xj + (__int128)yj*yj - (__int128)xi*xi - (__int128)yi*yi;\n        long long T = (long long)(rhs / 2);\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        for (int d = -10; d <= 10; ++d) {\n            long long C = T + d;\n            if (C % g != 0) continue;\n            long long px, py, qx, qy;\n            if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\nLine gen_gap_line() {\n    static vector<long long> vals;\n    vals.assign(N, 0);\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        long long A = rnd_ll(-1000, 1000);\n        long long B = rnd_ll(-1000, 1000);\n        if (A == 0 && B == 0) continue;\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        A /= g; B /= g;\n        for (int i = 0; i < N; ++i) vals[i] = A * xs[i] + B * ys[i];\n        sort(vals.begin(), vals.end());\n        vector<long long> uniq;\n        for (long long v : vals) {\n            if (uniq.empty() || uniq.back() != v) uniq.push_back(v);\n        }\n        if (uniq.size() <= 1) continue;\n        int idx = rnd_int(0, (int)uniq.size() - 2);\n        long long lo = uniq[idx];\n        long long hi = uniq[idx + 1];\n        if (hi <= lo + 1) continue;\n        long long C;\n        if (hi - lo > 2000000) C = lo + 1 + rnd_ll(0, 2000000);\n        else C = lo + 1 + rnd_ll(0, hi - lo - 1);\n        long long px, py, qx, qy;\n        if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n        Line L = make_line_pts(px, py, qx, qy);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\nLine perturb_line(const Line& L0) {\n    const long long D = 5;\n    for (int attempt = 0; attempt < 10; ++attempt) {\n        long long x1 = L0.px + rnd_ll(-D, D);\n        long long y1 = L0.py + rnd_ll(-D, D);\n        long long x2 = L0.qx + rnd_ll(-D, D);\n        long long y2 = L0.qy + rnd_ll(-D, D);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\n// ------------------------------------------------------------\n// Fast hash table for signature counting (open addressing)\n// ------------------------------------------------------------\nstruct Sig {\n    uint64_t a, b;\n};\n\nstruct FastHT {\n    struct Node {\n        uint64_t a, b;\n        int cnt;\n    };\n    int n;\n    vector<Node> nodes;\n    vector<int> seen;\n    vector<int> occ;\n    int timer;\n    FastHT(int n_ = 1 << 14) {\n        n = n_;\n        nodes.resize(n);\n        seen.assign(n, 0);\n        timer = 1;\n    }\n    inline void next_timer() {\n        ++timer;\n        occ.clear();\n        if (timer > 2000000000) {\n            fill(seen.begin(), seen.end(), 0);\n            timer = 1;\n        }\n    }\n    inline void add(uint64_t a, uint64_t b) {\n        size_t h = a ^ (b * 11400714819323198485ull);\n        size_t idx = h & (n - 1);\n        while (seen[idx] == timer) {\n            if (nodes[idx].a == a && nodes[idx].b == b) {\n                ++nodes[idx].cnt;\n                return;\n            }\n            idx = (idx + 1) & (n - 1);\n        }\n        seen[idx] = timer;\n        nodes[idx].a = a;\n        nodes[idx].b = b;\n        nodes[idx].cnt = 1;\n        occ.push_back((int)idx);\n    }\n    inline int get_score(const array<int,11>& need) const {\n        int have[11] = {0};\n        for (int idx : occ) {\n            int c = nodes[idx].cnt;\n            if (c >= 1 && c <= 10) ++have[c];\n        }\n        int s = 0;\n        for (int d = 1; d <= 10; ++d) s += min(need[d], have[d]);\n        return s;\n    }\n};\n\nFastHT ht;\n\ninline int evaluate_sigs(const vector<Sig>& sigs) {\n    ht.next_timer();\n    for (const auto& s : sigs) ht.add(s.a, s.b);\n    return ht.get_score(need);\n}\n\n// recompute signatures from scratch (safety net)\nvector<Sig> recompute_sigs(const vector<Line>& ls) {\n    vector<Sig> s(N, {0, 0});\n    for (int j = 0; j < (int)ls.size(); ++j) {\n        uint64_t mask = (j < 64) ? (1ULL << j) : (1ULL << (j - 64));\n        for (int i = 0; i < N; ++i) {\n            __int128 v = (__int128)ls[j].A * xs[i] + (__int128)ls[j].B * ys[i] + (__int128)ls[j].C;\n            uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n            if (j < 64) {\n                s[i].a = (s[i].a & ~mask) | (bit << j);\n            } else {\n                s[i].b = (s[i].b & ~mask) | (bit << (j - 64));\n            }\n        }\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> need[d];\n        target_score += need[d];\n    }\n    xs.resize(N); ys.resize(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    // ---------- Greedy construction ----------\n    vector<Line> lines;\n    vector<Sig> sig(N, {0, 0});\n    int cur_score = 0;\n    const int GREEDY_CANDS = 40;\n\n    vector<Sig> tmp(N), best_sig;\n\n    for (int step = 0; step < K; ++step) {\n        Line best_line;\n        int best_score = cur_score;\n\n        for (int cand = 0; cand < GREEDY_CANDS; ++cand) {\n            int type = rnd_int(0, 2);\n            Line L;\n            if (type == 0) L = gen_random_line();\n            else if (type == 1) L = gen_separator_line();\n            else L = gen_gap_line();\n            if (!valid_line(L)) continue;\n\n            int pj = step;\n            if (pj < 64) {\n                uint64_t mask = 1ULL << pj;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = (sig[i].a & ~mask) | (bit << pj);\n                    tmp[i].b = sig[i].b;\n                }\n            } else {\n                uint64_t mask = 1ULL << (pj - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = sig[i].a;\n                    tmp[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                }\n            }\n            int score = evaluate_sigs(tmp);\n            if (score > best_score) {\n                best_score = score;\n                best_line = L;\n                best_sig = tmp;          // copy instead of swap (tmp must stay size N)\n            }\n        }\n\n        if (best_score > cur_score) {\n            lines.push_back(best_line);\n            sig.swap(best_sig);\n            cur_score = best_score;\n        } else {\n            Line L = gen_random_line();\n            while (!valid_line(L)) L = gen_random_line();\n            lines.push_back(L);\n            int pj = step;\n            if (pj < 64) {\n                uint64_t mask = 1ULL << pj;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n                }\n            } else {\n                uint64_t mask = 1ULL << (pj - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                }\n            }\n            cur_score = evaluate_sigs(sig);\n        }\n        if (cur_score == target_score) break;\n    }\n\n    while ((int)lines.size() < K) {\n        Line L = gen_random_line();\n        lines.push_back(L);\n        int pj = (int)lines.size() - 1;\n        if (pj < 64) {\n            uint64_t mask = 1ULL << pj;\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n            }\n        } else {\n            uint64_t mask = 1ULL << (pj - 64);\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n            }\n        }\n    }\n    cur_score = evaluate_sigs(sig);\n\n    vector<Line> best_lines = lines;\n    vector<Sig> best_sig_overall = sig;\n    int best_score = cur_score;\n\n    // ---------- Local search ----------\n    const double TIME_LIMIT = 2.85;\n    while (elapsed() < TIME_LIMIT) {\n        for (int j = 0; j < K; ++j) {\n            if (elapsed() >= TIME_LIMIT) break;\n            Line best_local_line = lines[j];\n            int best_local_score = cur_score;\n            vector<Sig> best_local_sig;\n\n            const int LS_CANDS = 12;\n            for (int cand = 0; cand < LS_CANDS; ++cand) {\n                int type = rnd_int(0, 3);\n                Line L;\n                if (type == 0) L = gen_random_line();\n                else if (type == 1) L = gen_separator_line();\n                else if (type == 2) L = gen_gap_line();\n                else L = perturb_line(lines[j]);\n                if (!valid_line(L)) continue;\n\n                if (j < 64) {\n                    uint64_t mask = 1ULL << j;\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = (sig[i].a & ~mask) | (bit << j);\n                        tmp[i].b = sig[i].b;\n                    }\n                } else {\n                    uint64_t mask = 1ULL << (j - 64);\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = sig[i].a;\n                        tmp[i].b = (sig[i].b & ~mask) | (bit << (j - 64));\n                    }\n                }\n                int score = evaluate_sigs(tmp);\n                if (score > best_local_score) {\n                    best_local_score = score;\n                    best_local_line = L;\n                    best_local_sig = tmp;   // copy instead of swap\n                }\n            }\n\n            if (best_local_score > cur_score) {\n                lines[j] = best_local_line;\n                sig.swap(best_local_sig);\n                cur_score = best_local_score;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_lines = lines;\n                    best_sig_overall = sig;\n                }\n            }\n        }\n        if (best_score == target_score) break;\n    }\n\n    // ---------- Final safety validation ----------\n    for (int j = 0; j < K; ++j) {\n        if (!valid_line(best_lines[j])) {\n            best_lines[j] = gen_random_line();\n        }\n    }\n    best_sig_overall = recompute_sigs(best_lines);\n    best_score = evaluate_sigs(best_sig_overall);\n    (void)best_score; // unused, but ensures consistency\n\n    // ---------- Output ----------\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << best_lines[i].px << \" \" << best_lines[i].py << \" \"\n             << best_lines[i].qx << \" \" << best_lines[i].qy << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 64;\n\nusing Record = array<int,8>;\n\nstruct Solver {\n    int N, M;\n    int cx;\n    int wgt[MAXN][MAXN];\n    bool init_dot[MAXN][MAXN];\n    long long init_sum = 0;\n\n    // per-run state\n    bool dot[MAXN][MAXN];\n    bool horiz[MAXN][MAXN];\n    bool vert[MAXN][MAXN];\n    bool diag1[MAXN][MAXN];\n    bool diag2[MAXN][MAXN];\n    bool inq[MAXN][MAXN];\n    priority_queue<tuple<int,int,int>> pq;\n    mt19937 rng;\n    int mode;               // heuristic mode for this run\n\n    // ---------- geometry helpers ----------\n    bool check_edge(int x1, int y1, int x2, int y2) const {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int x = x1, y = y1;\n        while (x != x2 || y != y2) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (nx != x2 || ny != y2) {\n                if (dot[nx][ny]) return false;\n            }\n            if (dx == 1 && dy == 0) { if (horiz[x][y]) return false; }\n            else if (dx == -1 && dy == 0) { if (horiz[x-1][y]) return false; }\n            else if (dx == 0 && dy == 1) { if (vert[x][y]) return false; }\n            else if (dx == 0 && dy == -1) { if (vert[x][y-1]) return false; }\n            else if (dx == 1 && dy == 1) { if (diag1[x][y]) return false; }\n            else if (dx == -1 && dy == -1) { if (diag1[x-1][y-1]) return false; }\n            else if (dx == 1 && dy == -1) { if (diag2[x][y]) return false; }\n            else if (dx == -1 && dy == 1) { if (diag2[x-1][y+1]) return false; }\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void draw_edge(int x1, int y1, int x2, int y2) {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int x = x1, y = y1;\n        while (x != x2 || y != y2) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (dx == 1 && dy == 0) horiz[x][y] = true;\n            else if (dx == -1 && dy == 0) horiz[x-1][y] = true;\n            else if (dx == 0 && dy == 1) vert[x][y] = true;\n            else if (dx == 0 && dy == -1) vert[x][y-1] = true;\n            else if (dx == 1 && dy == 1) diag1[x][y] = true;\n            else if (dx == -1 && dy == -1) diag1[x-1][y-1] = true;\n            else if (dx == 1 && dy == -1) diag2[x][y] = true;\n            else if (dx == -1 && dy == 1) diag2[x-1][y+1] = true;\n            x = nx; y = ny;\n        }\n    }\n\n    bool check_rect(int x1, int y1, int x2, int y2,\n                    int x3, int y3, int x4, int y4) const {\n        if (dot[x1][y1]) return false;\n        if (!dot[x2][y2] || !dot[x3][y3] || !dot[x4][y4]) return false;\n        if (!check_edge(x1,y1,x2,y2)) return false;\n        if (!check_edge(x2,y2,x3,y3)) return false;\n        if (!check_edge(x3,y3,x4,y4)) return false;\n        if (!check_edge(x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void draw_rect(const Record &r) {\n        draw_edge(r[0],r[1],r[2],r[3]);\n        draw_edge(r[2],r[3],r[4],r[5]);\n        draw_edge(r[4],r[5],r[6],r[7]);\n        draw_edge(r[6],r[7],r[0],r[1]);\n    }\n\n    // enumerate all valid rectangles for p1=(x,y) and pick one by 'mode'\n    bool choose_rect(int x, int y, Record &out) {\n        bool found = false;\n        int best_pri = 0, best_sec = 0;\n        Record best;\n        int tie_cnt = 0;\n\n        auto consider = [&](const Record &r, int peri, int sec) {\n            if (!found) {\n                found = true;\n                best = r;\n                best_pri = peri;\n                best_sec = sec;\n                tie_cnt = 1;\n                return;\n            }\n            bool upd = false;\n            if (mode == 0) { // min perimeter, max sec tie\n                if (peri < best_pri || (peri == best_pri && sec > best_sec)) upd = true;\n            } else if (mode == 1) { // max perimeter, max sec tie\n                if (peri > best_pri || (peri == best_pri && sec > best_sec)) upd = true;\n            } else if (mode == 2) { // random among all\n                tie_cnt++;\n                if ((int)(rng() % tie_cnt) == 0) upd = true;\n            } else if (mode == 3) { // max sec, min peri tie\n                if (sec > best_sec || (sec == best_sec && peri < best_pri)) upd = true;\n            } else if (mode == 4) { // min perimeter, random tie\n                if (peri < best_pri) {\n                    upd = true;\n                    tie_cnt = 1;\n                } else if (peri == best_pri) {\n                    tie_cnt++;\n                    if ((int)(rng() % tie_cnt) == 0) upd = true;\n                }\n            }\n            if (upd) {\n                best = r;\n                best_pri = peri;\n                best_sec = sec;\n            }\n        };\n\n        // axis-aligned\n        for (int x2 = 0; x2 < N; ++x2) if (dot[x2][y]) {\n            for (int y2 = 0; y2 < N; ++y2) if (dot[x][y2] && dot[x2][y2]) {\n                Record r = {x,y,x2,y,x2,y2,x,y2};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                int peri = 2 * (abs(x2 - x) + abs(y2 - y));\n                int sec = wgt[x2][y] + wgt[x2][y2] + wgt[x][y2];\n                consider(r, peri, sec);\n            }\n        }\n\n        // 45-degree\n        for (int d = -min(x,y); d < N - max(x,y); ++d) if (d != 0) {\n            int x2 = x + d, y2 = y + d;\n            if (!dot[x2][y2]) continue;\n            for (int e = max(-x, -(N-1-y)); e <= min(N-1-x, y); ++e) if (e != 0) {\n                int x4 = x + e, y4 = y - e;\n                if (!dot[x4][y4]) continue;\n                int x3 = x2 + x4 - x;\n                int y3 = y2 + y4 - y;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                Record r = {x,y,x2,y2,x3,y3,x4,y4};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                int peri = 2 * (abs(d) + abs(e));\n                int sec = wgt[x2][y2] + wgt[x3][y3] + wgt[x4][y4];\n                consider(r, peri, sec);\n            }\n        }\n\n        if (found) out = best;\n        return found;\n    }\n\n    void try_push(int x, int y) {\n        if (dot[x][y]) return;\n        if (inq[x][y]) return;\n        inq[x][y] = true;\n        pq.emplace(wgt[x][y], x, y);\n    }\n\n    // incremental candidate generation after placing a dot at (x,y)\n    void find_new_candidates(int x, int y) {\n        // axis: p_new as p2, p1 on same row\n        for (int x1 = 0; x1 < N; ++x1) if (!dot[x1][y]) {\n            for (int y1 = 0; y1 < N; ++y1) if (dot[x][y1] && dot[x1][y1]) {\n                if (check_rect(x1,y, x,y, x,y1, x1,y1))\n                    try_push(x1, y);\n            }\n        }\n        // axis: p_new as p4, p1 on same column\n        for (int y1 = 0; y1 < N; ++y1) if (!dot[x][y1]) {\n            for (int x1 = 0; x1 < N; ++x1) if (dot[x1][y] && dot[x1][y1]) {\n                if (check_rect(x,y1, x1,y1, x1,y, x,y))\n                    try_push(x, y1);\n            }\n        }\n        // axis: p_new as p3 (opposite)\n        for (int x1 = 0; x1 < N; ++x1) if (dot[x1][y]) {\n            for (int y1 = 0; y1 < N; ++y1) if (dot[x][y1]) {\n                if (!dot[x1][y1]) {\n                    if (check_rect(x1,y1, x1,y, x,y, x,y1))\n                        try_push(x1, y1);\n                }\n            }\n        }\n        // 45: p_new as p2 on diag+1\n        for (int d = -min(x,y); d < N - max(x,y); ++d) if (d != 0) {\n            int x1 = x + d, y1 = y + d;\n            if (dot[x1][y1]) continue;\n            int s = x1 + y1;\n            for (int x4 = 0; x4 < N; ++x4) {\n                int y4 = s - x4;\n                if (y4 < 0 || y4 >= N) continue;\n                if (!dot[x4][y4]) continue;\n                int x3 = x + x4 - x1;\n                int y3 = y + y4 - y1;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                if (check_rect(x1,y1, x,y, x3,y3, x4,y4))\n                    try_push(x1, y1);\n            }\n        }\n        // 45: p_new as p4 on diag-1\n        for (int d = max(-x, -(N-1-y)); d <= min(N-1-x, y); ++d) if (d != 0) {\n            int x1 = x + d, y1 = y - d;\n            if (dot[x1][y1]) continue;\n            int diff = x1 - y1;\n            for (int x4 = 0; x4 < N; ++x4) {\n                int y4 = x4 - diff;\n                if (y4 < 0 || y4 >= N) continue;\n                if (!dot[x4][y4]) continue;\n                int x3 = x + x4 - x1;\n                int y3 = y + y4 - y1;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                if (check_rect(x1,y1, x,y, x3,y3, x4,y4))\n                    try_push(x1, y1);\n            }\n        }\n        // 45: p_new as p3 (opposite)\n        for (int d = -min(x,y); d < N - max(x,y); ++d) if (d != 0) {\n            int x2 = x + d, y2 = y + d;\n            if (!dot[x2][y2]) continue;\n            for (int e = max(-x, -(N-1-y)); e <= min(N-1-x, y); ++e) if (e != 0) {\n                int x4 = x + e, y4 = y - e;\n                if (!dot[x4][y4]) continue;\n                int x1 = x2 + x4 - x;\n                int y1 = y2 + y4 - y;\n                if (x1 < 0 || x1 >= N || y1 < 0 || y1 >= N) continue;\n                if (dot[x1][y1]) continue;\n                if (check_rect(x1,y1, x2,y2, x,y, x4,y4))\n                    try_push(x1, y1);\n            }\n        }\n    }\n\n    pair<long long, vector<Record>> solve_run(int mode_, int seed) {\n        mode = mode_;\n        rng.seed(seed);\n        memcpy(dot, init_dot, sizeof(dot));\n        memset(horiz, 0, sizeof(horiz));\n        memset(vert, 0, sizeof(vert));\n        memset(diag1, 0, sizeof(diag1));\n        memset(diag2, 0, sizeof(diag2));\n        memset(inq, 0, sizeof(inq));\n        while (!pq.empty()) pq.pop();\n\n        Record rec;\n        for (int x = 0; x < N; ++x) {\n            for (int y = 0; y < N; ++y) if (!dot[x][y]) {\n                if (choose_rect(x, y, rec)) {\n                    inq[x][y] = true;\n                    pq.emplace(wgt[x][y], x, y);\n                }\n            }\n        }\n\n        long long cur_sum = init_sum;\n        vector<Record> ops;\n        ops.reserve(N * N);\n\n        while (!pq.empty()) {\n            auto [W, x, y] = pq.top();\n            pq.pop();\n            inq[x][y] = false;\n            if (dot[x][y]) continue;\n            Record r;\n            if (!choose_rect(x, y, r)) continue;\n            dot[x][y] = true;\n            cur_sum += wgt[x][y];\n            draw_rect(r);\n            ops.push_back(r);\n            find_new_candidates(x, y);\n        }\n        return {cur_sum, ops};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n\n    Solver sol;\n    sol.N = N;\n    sol.M = M;\n    sol.cx = (N - 1) / 2;\n    memset(sol.init_dot, 0, sizeof(sol.init_dot));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            sol.wgt[i][j] = (i - sol.cx)*(i - sol.cx) + (j - sol.cx)*(j - sol.cx) + 1;\n        }\n    }\n    for (int i = 0; i < M; ++i) {\n        int x, y;\n        cin >> x >> y;\n        sol.init_dot[x][y] = true;\n        sol.init_sum += sol.wgt[x][y];\n    }\n\n    const double TIME_LIMIT = 4.5;\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    long long best_score = -1;\n    vector<Record> best_ops;\n\n    // deterministic heuristics first\n    vector<int> modes = {0, 3, 4, 1};\n    vector<int> seeds = {0, 0, 0, 0};\n\n    for (size_t i = 0; i < modes.size(); ++i) {\n        if (elapsed() > TIME_LIMIT) break;\n        auto [sc, ops] = sol.solve_run(modes[i], seeds[i]);\n        if (sc > best_score) {\n            best_score = sc;\n            best_ops = std::move(ops);\n        }\n    }\n\n    // then random restarts while time remains\n    for (int seed = 1; ; ++seed) {\n        if (elapsed() > TIME_LIMIT) break;\n        auto [sc, ops] = sol.solve_run(2, seed);\n        if (sc > best_score) {\n            best_score = sc;\n            best_ops = std::move(ops);\n        }\n    }\n\n    cout << best_ops.size() << \"\\n\";\n    for (auto &r : best_ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << r[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    array<int, 100> a;\n    State() { a.fill(0); }\n};\n\n/* tilt the whole box in one direction\n   0:F (up, row 0), 1:B (down, row 9), 2:L (left, col 0), 3:R (right, col 9) */\nState tilt(const State& s, int dir) {\n    State ns;\n    ns.a.fill(0);\n    if (dir == 0) {                 // Forward / Up\n        for (int c = 0; c < 10; ++c) {\n            int w = 0;\n            for (int r = 0; r < 10; ++r) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[w++ * 10 + c] = x;\n            }\n        }\n    } else if (dir == 1) {          // Backward / Down\n        for (int c = 0; c < 10; ++c) {\n            int w = 9;\n            for (int r = 9; r >= 0; --r) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[w-- * 10 + c] = x;\n            }\n        }\n    } else if (dir == 2) {          // Left\n        for (int r = 0; r < 10; ++r) {\n            int w = 0;\n            for (int c = 0; c < 10; ++c) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[r * 10 + w++] = x;\n            }\n        }\n    } else {                         // Right\n        for (int r = 0; r < 10; ++r) {\n            int w = 9;\n            for (int c = 9; c >= 0; --c) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[r * 10 + w--] = x;\n            }\n        }\n    }\n    return ns;\n}\n\n/* where does the candy currently at 'pos' end up after tilting 'dir'? */\nint new_pos_after_tilt(const State& s, int pos, int dir) {\n    int r = pos / 10;\n    int c = pos % 10;\n    if (dir == 0) {                 // F\n        int cnt = 0;\n        for (int i = 0; i < r; ++i) if (s.a[i * 10 + c] != 0) ++cnt;\n        return cnt * 10 + c;\n    } else if (dir == 1) {          // B\n        int cnt = 0;\n        for (int i = r + 1; i < 10; ++i) if (s.a[i * 10 + c] != 0) ++cnt;\n        return (9 - cnt) * 10 + c;\n    } else if (dir == 2) {          // L\n        int cnt = 0;\n        for (int i = 0; i < c; ++i) if (s.a[r * 10 + i] != 0) ++cnt;\n        return r * 10 + cnt;\n    } else {                         // R\n        int cnt = 0;\n        for (int i = c + 1; i < 10; ++i) if (s.a[r * 10 + i] != 0) ++cnt;\n        return r * 10 + (9 - cnt);\n    }\n}\n\n/* exact score = sum of n_i^2 */\nint evaluate(const State& s) {\n    bool vis[100] = {false};\n    int q[100];\n    int sum = 0;\n    for (int i = 0; i < 100; ++i) {\n        if (s.a[i] == 0 || vis[i]) continue;\n        int f = s.a[i];\n        int sz = 0;\n        int qh = 0, qt = 0;\n        q[qt++] = i;\n        vis[i] = true;\n        while (qh < qt) {\n            int u = q[qh++];\n            ++sz;\n            int r = u / 10;\n            int c = u % 10;\n            if (r > 0) {\n                int v = (r - 1) * 10 + c;\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (r < 9) {\n                int v = (r + 1) * 10 + c;\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (c > 0) {\n                int v = r * 10 + (c - 1);\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (c < 9) {\n                int v = r * 10 + (c + 1);\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n        }\n        sum += sz * sz;\n    }\n    return sum;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> flav(100);\n    for (int i = 0; i < 100; ++i) {\n        if (!(cin >> flav[i])) return 0;\n    }\n\n    const int K = 40;                     // rollouts per direction\n    const char dname[4] = {'F', 'B', 'L', 'R'};\n    State cur;\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        --p;                              // 0-based\n\n        /* place in the p-th empty cell (row-major = front-to-back, left-to-right) */\n        int pos = -1;\n        for (int i = 0; i < 100; ++i) {\n            if (cur.a[i] == 0) {\n                if (p == 0) { pos = i; break; }\n                --p;\n            }\n        }\n        cur.a[pos] = flav[t];\n\n        /* 100th placement fills the board; tilt does nothing */\n        if (t == 99) {\n            cout << \"F\\n\";\n            cout.flush();\n            break;\n        }\n\n        State base[4];\n        for (int d = 0; d < 4; ++d) base[d] = tilt(cur, d);\n\n        long long total[4] = {0, 0, 0, 0};\n\n        for (int k = 0; k < K; ++k) {\n            /* same random seed for all 4 directions -> variance reduction */\n            unsigned seed = 123456789u + t * 10007u + k;\n            for (int d = 0; d < 4; ++d) {\n                mt19937 rng(seed);\n                State sim = base[d];\n\n                for (int s = t + 1; s < 100; ++s) {\n                    int empties[100];\n                    int ecnt = 0;\n                    for (int i = 0; i < 100; ++i)\n                        if (sim.a[i] == 0) empties[ecnt++] = i;\n\n                    if (ecnt == 0) break;\n                    int idx = empties[rng() % ecnt];\n                    int f = flav[s];\n                    sim.a[idx] = f;\n\n                    if (s == 99) break;   // last candy, no tilt follows\n\n                    /* local greedy: maximize same-flavor neighbours of the new candy */\n                    int best_dir = 0;\n                    int best_sc = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int np = new_pos_after_tilt(sim, idx, d2);\n                        State ns = tilt(sim, d2);\n                        int sc = 0;\n                        int r = np / 10;\n                        int c = np % 10;\n                        if (r > 0 && ns.a[(r - 1) * 10 + c] == f) ++sc;\n                        if (r < 9 && ns.a[(r + 1) * 10 + c] == f) ++sc;\n                        if (c > 0 && ns.a[r * 10 + (c - 1)] == f) ++sc;\n                        if (c < 9 && ns.a[r * 10 + (c + 1)] == f) ++sc;\n                        if (sc > best_sc) {\n                            best_sc = sc;\n                            best_dir = d2;\n                        }\n                    }\n                    sim = tilt(sim, best_dir);\n                }\n                total[d] += evaluate(sim);\n            }\n        }\n\n        int best = 0;\n        for (int d = 1; d < 4; ++d)\n            if (total[d] > total[best]) best = d;\n\n        cur = tilt(cur, best);\n        cout << dname[best] << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ULL = unsigned long long;\nusing ll = long long;\n\nint M;\ndouble eps;\nint N;\nint L; // N*(N-1)/2\nmt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\nstruct Graph {\n    ULL a[64];\n    void clear(int n) { for (int i = 0; i < n; ++i) a[i] = 0; }\n};\n\nusing Feature = vector<double>;\n\n// ------------------------------------------------------------\n// Feature extraction\n// ------------------------------------------------------------\nFeature extract(const Graph &g, int n) {\n    int deg[64] = {};\n    int common[64][64] = {};\n    for (int i = 0; i < n; ++i) {\n        deg[i] = __builtin_popcountll(g.a[i]);\n    }\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            int c = __builtin_popcountll(g.a[i] & g.a[j]);\n            common[i][j] = common[j][i] = c;\n        }\n    }\n\n    double m = 0; // edges\n    for (int i = 0; i < n; ++i) m += deg[i];\n    m *= 0.5;\n\n    double t = 0; // triangles\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) if ((g.a[i] >> j) & 1ULL) {\n            t += common[i][j];\n        }\n    }\n    t /= 3.0;\n\n    // triangles per vertex\n    double tv[64] = {};\n    for (int i = 0; i < n; ++i) {\n        double s = 0;\n        for (int j = 0; j < n; ++j) if ((g.a[i] >> j) & 1ULL) {\n            s += common[i][j];\n        }\n        tv[i] = s * 0.5;\n    }\n\n    // 4-cliques\n    double c4 = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) if ((g.a[i] >> j) & 1ULL) {\n            ULL mask = g.a[i] & g.a[j];\n            mask >>= (j + 1);\n            while (mask) {\n                int k = __builtin_ctzll(mask) + j + 1;\n                ULL m2 = g.a[i] & g.a[j] & g.a[k];\n                m2 >>= (k + 1);\n                c4 += __builtin_popcountll(m2);\n                mask &= mask - 1;\n            }\n        }\n    }\n\n    // sum of C(common,2)  -> 4-cycles with diagonal\n    double q = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            q += (double)common[i][j] * (common[i][j] - 1) * 0.5;\n        }\n    }\n\n    // paths of length 2\n    double p2 = 0;\n    for (int i = 0; i < n; ++i) {\n        p2 += (double)deg[i] * (deg[i] - 1) * 0.5;\n    }\n\n    double m2 = 0, m3 = 0;\n    for (int i = 0; i < n; ++i) {\n        double d = deg[i];\n        m2 += d * d;\n        m3 += d * d * d;\n    }\n\n    // A^2 matrix (as ints)\n    int A2[64][64] = {};\n    for (int i = 0; i < n; ++i) {\n        A2[i][i] = deg[i];\n        for (int j = i + 1; j < n; ++j) {\n            A2[i][j] = A2[j][i] = common[i][j];\n        }\n    }\n\n    // A^3 = A * A^2\n    int A3[64][64] = {};\n    for (int i = 0; i < n; ++i) {\n        for (int k = 0; k < n; ++k) if ((g.a[i] >> k) & 1ULL) {\n            for (int j = 0; j < n; ++j) {\n                A3[i][j] += A2[k][j];\n            }\n        }\n    }\n\n    double trace3 = 0;\n    for (int i = 0; i < n; ++i) trace3 += A3[i][i];\n\n    double w3[64] = {};\n    for (int i = 0; i < n; ++i) {\n        double s = 0;\n        for (int j = 0; j < n; ++j) s += A3[i][j];\n        w3[i] = s;\n    }\n\n    double w4[64] = {};\n    for (int i = 0; i < n; ++i) {\n        double s = 0;\n        for (int j = 0; j < n; ++j) s += (double)A2[i][j] * A2[i][j];\n        w4[i] = s;\n    }\n\n    double trace4 = 0;\n    for (int i = 0; i < n; ++i) trace4 += w4[i];\n\n    double darr[64], tvarr[64], w3arr[64], w4arr[64];\n    for (int i = 0; i < n; ++i) {\n        darr[i] = deg[i];\n        tvarr[i] = tv[i];\n        w3arr[i] = w3[i];\n        w4arr[i] = w4[i];\n    }\n    sort(darr, darr + n);\n    sort(tvarr, tvarr + n);\n    sort(w3arr, w3arr + n);\n    sort(w4arr, w4arr + n);\n\n    Feature f;\n    f.reserve(4 * n + 9);\n    f.push_back(m);\n    f.push_back(t);\n    f.push_back(c4);\n    f.push_back(q);\n    f.push_back(p2);\n    f.push_back(m2);\n    f.push_back(m3);\n    f.push_back(trace3);\n    f.push_back(trace4);\n    for (int i = 0; i < n; ++i) f.push_back(darr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(tvarr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(w3arr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(w4arr[i]);\n    return f;\n}\n\n// ------------------------------------------------------------\n// Noise generation (BSC + random permutation)\n// ------------------------------------------------------------\nGraph add_noise(const Graph &g, int n, double ep, mt19937_64 &gen) {\n    Graph h = g;\n    // apply permutation\n    vector<int> perm(n);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), gen);\n    Graph pg;\n    pg.clear(n);\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            int pi = perm[i];\n            int pj = perm[j];\n            bool has = (g.a[pi] >> pj) & 1ULL;\n            if (has) {\n                pg.a[i] |= (1ULL << j);\n                pg.a[j] |= (1ULL << i);\n            }\n        }\n    }\n    // BSC noise\n    uniform_real_distribution<double> uni(0.0, 1.0);\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            if (uni(gen) < ep) {\n                if ((pg.a[i] >> j) & 1ULL) {\n                    pg.a[i] &= ~(1ULL << j);\n                    pg.a[j] &= ~(1ULL << i);\n                } else {\n                    pg.a[i] |= (1ULL << j);\n                    pg.a[j] |= (1ULL << i);\n                }\n            }\n        }\n    }\n    return pg;\n}\n\n// ------------------------------------------------------------\n// Nearest-neighbor decoder\n// ------------------------------------------------------------\nint predict(const Feature &f, const vector<Feature> &F, const vector<double> &w) {\n    int bestk = 0;\n    double best = 1e300;\n    int D = (int)f.size();\n    for (int k = 0; k < M; ++k) {\n        double d = 0;\n        for (int i = 0; i < D; ++i) {\n            double diff = f[i] - F[k][i];\n            d += diff * diff * w[i];\n        }\n        if (d < best) {\n            best = d;\n            bestk = k;\n        }\n    }\n    return bestk;\n}\n\n// ------------------------------------------------------------\n// Evaluate error count on a batch\n// ------------------------------------------------------------\nint evaluate_batch(const vector<Graph> &Gs, const vector<Feature> &F,\n                   const vector<double> &w, double ep, int batch, int n) {\n    int err = 0;\n    uniform_int_distribution<int> sdist(0, M - 1);\n    for (int b = 0; b < batch; ++b) {\n        int s = sdist(rng);\n        Graph h = add_noise(Gs[s], n, ep, rng);\n        Feature f = extract(h, n);\n        int pred = predict(f, F, w);\n        if (pred != s) ++err;\n    }\n    return err;\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> M >> eps)) return 0;\n\n    // Candidate N values\n    vector<int> Ncands = {12, 14, 18, 22};\n    int bestN = 18;\n    double bestScoreEst = 1e100;\n\n    // Quick selection of N\n    for (int n : Ncands) {\n        int l = n * (n - 1) / 2;\n        // init random codebook with spaced edge counts\n        vector<Graph> Gs(M);\n        vector<pair<int,int>> edges;\n        for (int i = 0; i < n; ++i)\n            for (int j = i + 1; j < n; ++j)\n                edges.emplace_back(i, j);\n        for (int k = 0; k < M; ++k) {\n            Gs[k].clear(n);\n            int want = (int)((k + 0.5) * (double)l / M);\n            want = min(want, l);\n            shuffle(edges.begin(), edges.end(), rng);\n            for (int e = 0; e < want; ++e) {\n                auto [u, v] = edges[e];\n                Gs[k].a[u] |= (1ULL << v);\n                Gs[k].a[v] |= (1ULL << u);\n            }\n        }\n        vector<Feature> F(M);\n        for (int k = 0; k < M; ++k) F[k] = extract(Gs[k], n);\n        int D = F[0].size();\n        // uniform weights for quick test\n        vector<double> w(D, 1.0);\n        int err = evaluate_batch(Gs, F, w, eps, 100, n);\n        double scoreEst = (double)err; // lower is better\n        if (scoreEst < bestScoreEst) {\n            bestScoreEst = scoreEst;\n            bestN = n;\n        }\n    }\n\n    N = bestN;\n    L = N * (N - 1) / 2;\n\n    // Initialize codebook for chosen N\n    vector<Graph> Gs(M);\n    vector<pair<int,int>> edges;\n    for (int i = 0; i < N; ++i)\n        for (int j = i + 1; j < N; ++j)\n            edges.emplace_back(i, j);\n\n    for (int k = 0; k < M; ++k) {\n        Gs[k].clear(N);\n        int want = (int)((k + 0.5) * (double)L / M);\n        want = min(want, L);\n        shuffle(edges.begin(), edges.end(), rng);\n        for (int e = 0; e < want; ++e) {\n            auto [u, v] = edges[e];\n            Gs[k].a[u] |= (1ULL << v);\n            Gs[k].a[v] |= (1ULL << u);\n        }\n    }\n\n    vector<Feature> F(M);\n    for (int k = 0; k < M; ++k) F[k] = extract(Gs[k], N);\n    int D = F[0].size();\n\n    // Compute data-driven weights by sampling noise\n    vector<double> w(D, 1.0);\n    {\n        vector<double> var(D, 0.0);\n        int S = 200;\n        uniform_int_distribution<int> sdist(0, M - 1);\n        for (int b = 0; b < S; ++b) {\n            int s = sdist(rng);\n            Graph h = add_noise(Gs[s], N, eps, rng);\n            Feature f = extract(h, N);\n            for (int i = 0; i < D; ++i) {\n                double diff = f[i] - F[s][i];\n                var[i] += diff * diff;\n            }\n        }\n        for (int i = 0; i < D; ++i) {\n            var[i] /= S;\n            w[i] = 1.0 / (var[i] + 1e-6);\n        }\n    }\n\n    // Simulated Annealing\n    int BATCH = 25;\n    int ITER = 3000;\n    int cur_obj = evaluate_batch(Gs, F, w, eps, BATCH, N);\n    uniform_int_distribution<int> kdist(0, M - 1);\n    uniform_int_distribution<int> vdist(0, N - 1);\n    uniform_real_distribution<double> prob(0.0, 1.0);\n\n    // Precompute pairs\n    vector<pair<int,int>> allEdges = edges;\n\n    for (int it = 0; it < ITER; ++it) {\n        double T = 1.0 * (ITER - it) / ITER;\n        if (T < 0.001) T = 0.001;\n\n        int k = kdist(rng);\n        int u = vdist(rng);\n        int v = vdist(rng);\n        if (u == v) continue;\n        if (u > v) swap(u, v);\n\n        bool had = (Gs[k].a[u] >> v) & 1ULL;\n        // flip\n        if (had) {\n            Gs[k].a[u] &= ~(1ULL << v);\n            Gs[k].a[v] &= ~(1ULL << u);\n        } else {\n            Gs[k].a[u] |= (1ULL << v);\n            Gs[k].a[v] |= (1ULL << u);\n        }\n\n        Feature oldF = F[k];\n        F[k] = extract(Gs[k], N);\n        int new_obj = evaluate_batch(Gs, F, w, eps, BATCH, N);\n\n        int delta = new_obj - cur_obj;\n        if (delta < 0 || prob(rng) < exp(-delta / T)) {\n            cur_obj = new_obj;\n        } else {\n            // revert\n            if (had) {\n                Gs[k].a[u] |= (1ULL << v);\n                Gs[k].a[v] |= (1ULL << u);\n            } else {\n                Gs[k].a[u] &= ~(1ULL << v);\n                Gs[k].a[v] &= ~(1ULL << u);\n            }\n            F[k] = oldF;\n        }\n    }\n\n    // Output graphs\n    cout << N << \"\\n\";\n    for (int k = 0; k < M; ++k) {\n        string s;\n        s.reserve(L);\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                s.push_back( (Gs[k].a[i] >> j) & 1ULL ? '1' : '0' );\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // Answer queries\n    for (int q = 0; q < 100; ++q) {\n        string hs;\n        cin >> hs;\n        Graph h;\n        h.clear(N);\n        int pos = 0;\n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (hs[pos++] == '1') {\n                    h.a[i] |= (1ULL << j);\n                    h.a[j] |= (1ULL << i);\n                }\n            }\n        }\n        Feature f = extract(h, N);\n        int ans = predict(f, F, w);\n        cout << ans << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst int INF_INT = 1000000000;\nconst ll INF_LL = (1LL<<60);\n\nstruct SimpleHeap {\n    static const int MAXN = 10005;\n    pair<int,int> a[MAXN];\n    int n;\n    void clear(){ n=0; }\n    void push(pair<int,int> x){\n        int i=n++;\n        while(i>0){\n            int p=(i-1)>>1;\n            if(a[p].first <= x.first) break;\n            a[i]=a[p];\n            i=p;\n        }\n        a[i]=x;\n    }\n    pair<int,int> top() const { return a[0]; }\n    void pop(){\n        pair<int,int> x = a[--n];\n        int i=0;\n        while(true){\n            int l=(i<<1)|1;\n            if(l>=n) break;\n            int r=l+1, c=l;\n            if(r<n && a[r].first < a[l].first) c=r;\n            if(x.first <= a[c].first) break;\n            a[i]=a[c];\n            i=c;\n        }\n        a[i]=x;\n    }\n    bool empty() const { return n==0; }\n};\n\nint N, M, D, K;\nstruct Edge {int u, v, w;};\nvector<Edge> edges;\nvector<vector<tuple<int,int,int>>> adj;\nvector<int> rem_stamp;\nint cur_stamp = 1;\n\ninline pair<int,ll> dijkstra(int s, int stamp, vector<int>& dist, SimpleHeap& pq){\n    fill(dist.begin(), dist.end(), INF_INT);\n    dist[s] = 0;\n    pq.clear();\n    pq.push({0, s});\n    ll sum = 0;\n    int visited = 0;\n    while(!pq.empty()){\n        auto [d,u] = pq.top(); pq.pop();\n        if(d != dist[u]) continue;\n        visited++;\n        sum += d;\n        for(const auto& [v,w,eid] : adj[u]){\n            if(rem_stamp[eid] == stamp) continue;\n            if(dist[v] > d + w){\n                dist[v] = d + w;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {visited, sum};\n}\n\n// Evaluate proxy score of a day. exact=false -> INF if disconnected. exact=true -> add penalty.\nll eval_day(int day, int out_eid, int in_eid, const vector<int>& samples,\n            const vector<vector<int>>& day_edges,\n            vector<int>& dist, SimpleHeap& pq, bool exact=false){\n    int stamp = cur_stamp++;\n    for(int eid : day_edges[day]){\n        if(eid == out_eid) continue;\n        rem_stamp[eid] = stamp;\n    }\n    if(in_eid != -1) rem_stamp[in_eid] = stamp;\n    ll total = 0;\n    for(int s : samples){\n        auto [vis, sum] = dijkstra(s, stamp, dist, pq);\n        if(vis < N){\n            if(!exact) return INF_LL;\n            total += sum + (ll)(N - vis) * INF_INT;\n        } else {\n            total += sum;\n        }\n    }\n    return total;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    cin >> N >> M >> D >> K;\n    edges.resize(M);\n    adj.assign(N, {});\n    vector<int> xs(N), ys(N);\n    for(int i=0;i<M;i++){\n        int u,v,w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u,v,w};\n        adj[u].push_back({v,w,i});\n        adj[v].push_back({u,w,i});\n    }\n    for(int i=0;i<N;i++) cin >> xs[i] >> ys[i];\n\n    rem_stamp.assign(M, 0);\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // ----- approximate edge importance (shortest path tree usage) -----\n    vector<int> imp(M, 0);\n    vector<int> dist0(N);\n    vector<int> parent(N);\n    SimpleHeap pq0;\n    for(int it=0; it<100; it++){\n        int s = rng() % N;\n        fill(dist0.begin(), dist0.end(), INF_INT);\n        dist0[s] = 0;\n        fill(parent.begin(), parent.end(), -1);\n        pq0.clear();\n        pq0.push({0, s});\n        while(!pq0.empty()){\n            auto [d,u] = pq0.top(); pq0.pop();\n            if(d != dist0[u]) continue;\n            for(const auto& [v,w,eid] : adj[u]){\n                if(dist0[v] > d + w){\n                    dist0[v] = d + w;\n                    parent[v] = eid;\n                    pq0.push({dist0[v], v});\n                }\n            }\n        }\n        for(int v=0; v<N; v++){\n            if(v != s && parent[v] != -1) imp[parent[v]]++;\n        }\n    }\n\n    // ----- greedy initialization (balance importance) -----\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        if(imp[a] != imp[b]) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    vector<int> edge_day(M);\n    vector<vector<int>> day_edges(D);\n    vector<ll> day_imp_sum(D, 0);\n    vector<int> day_load(D, 0);\n    for(int eid : order){\n        int best_d = -1;\n        ll best_val = INF_LL;\n        for(int d=0; d<D; d++){\n            if(day_load[d] >= K) continue;\n            if(day_imp_sum[d] < best_val){\n                best_val = day_imp_sum[d];\n                best_d = d;\n            }\n        }\n        if(best_d == -1){\n            for(int d=0; d<D; d++) if(day_load[d] < K){ best_d = d; break; }\n        }\n        edge_day[eid] = best_d;\n        day_edges[best_d].push_back(eid);\n        day_load[best_d]++;\n        day_imp_sum[best_d] += imp[eid];\n    }\n\n    // ----- ensure every day is connected -----\n    vector<int> dist(N);\n    SimpleHeap pq;\n    auto is_conn = [&](int d)->bool{\n        static vector<int> dummy = {0};\n        return eval_day(d, -1, -1, dummy, day_edges, dist, pq) < INF_LL;\n    };\n\n    for(int d=0; d<D; d++){\n        int attempts = 0;\n        while(!is_conn(d)){\n            int d2 = rng() % D;\n            if(d2 == d) continue;\n            if(day_edges[d].empty() || day_edges[d2].empty()) continue;\n            int i1 = rng() % (int)day_edges[d].size();\n            int i2 = rng() % (int)day_edges[d2].size();\n            int e1 = day_edges[d][i1];\n            int e2 = day_edges[d2][i2];\n            swap(day_edges[d][i1], day_edges[d2][i2]);\n            edge_day[e1] = d2;\n            edge_day[e2] = d;\n            if(is_conn(d) && is_conn(d2)){\n                // keep swap\n            } else {\n                swap(day_edges[d][i1], day_edges[d2][i2]);\n                edge_day[e1] = d;\n                edge_day[e2] = d2;\n            }\n            if(++attempts > 20000) break;\n        }\n    }\n\n    // ----- stratified sample sources -----\n    vector<pair<int,int>> nodes_by_x;\n    for(int i=0;i<N;i++) nodes_by_x.push_back({xs[i], i});\n    sort(nodes_by_x.begin(), nodes_by_x.end());\n    const int NS = 20;\n    vector<int> samples;\n    for(int i=0;i<NS;i++){\n        int L = i * N / NS;\n        int R = (i+1) * N / NS;\n        if(L >= R) continue;\n        int idx = L + (int)(rng() % (R - L));\n        samples.push_back(nodes_by_x[idx].second);\n    }\n    while((int)samples.size() < NS) samples.push_back(rng() % N);\n\n    // ----- compute initial proxy scores -----\n    vector<ll> day_score(D);\n    auto recompute_day = [&](int d){\n        day_score[d] = eval_day(d, -1, -1, samples, day_edges, dist, pq);\n    };\n    for(int d=0; d<D; d++) recompute_day(d);\n    ll cur_total = 0;\n    for(ll v : day_score) cur_total += v;\n\n    vector<int> best_edge_day = edge_day;\n    vector<vector<int>> best_day_edges = day_edges;\n    ll best_total = cur_total;\n\n    const double TIME_LIMIT = 5.4;\n    int stagnant = 0;\n\n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if(elapsed > TIME_LIMIT) break;\n\n        int d1 = rng() % D;\n        int d2 = rng() % D;\n        if(d1 == d2) continue;\n        if(day_edges[d1].empty() || day_edges[d2].empty()) continue;\n        int i1 = rng() % (int)day_edges[d1].size();\n        int i2 = rng() % (int)day_edges[d2].size();\n        int e1 = day_edges[d1][i1];\n        int e2 = day_edges[d2][i2];\n\n        ll s1 = eval_day(d1, e1, e2, samples, day_edges, dist, pq);\n        if(s1 >= INF_LL) continue;\n        ll s2 = eval_day(d2, e2, e1, samples, day_edges, dist, pq);\n        if(s2 >= INF_LL) continue;\n\n        ll new_total = cur_total - day_score[d1] - day_score[d2] + s1 + s2;\n        if(new_total < cur_total){\n            edge_day[e1] = d2;\n            edge_day[e2] = d1;\n            day_edges[d1][i1] = e2;\n            day_edges[d2][i2] = e1;\n            day_score[d1] = s1;\n            day_score[d2] = s2;\n            cur_total = new_total;\n            stagnant = 0;\n            if(cur_total < best_total){\n                best_total = cur_total;\n                best_edge_day = edge_day;\n                best_day_edges = day_edges;\n            }\n        } else {\n            stagnant++;\n            if(stagnant > 300){\n                // perturb from best and continue\n                bool ok = false;\n                for(int attempt=0; attempt<10; attempt++){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                    int num_swaps = 10 + (int)(rng() % 10);\n                    for(int k=0; k<num_swaps; k++){\n                        int a = rng() % D;\n                        int b = rng() % D;\n                        if(a == b) continue;\n                        if(day_edges[a].empty() || day_edges[b].empty()) continue;\n                        int ai = rng() % (int)day_edges[a].size();\n                        int bi = rng() % (int)day_edges[b].size();\n                        int ae = day_edges[a][ai];\n                        int be = day_edges[b][bi];\n                        swap(day_edges[a][ai], day_edges[b][bi]);\n                        edge_day[ae] = b;\n                        edge_day[be] = a;\n                    }\n                    bool all_conn = true;\n                    for(int d=0; d<D; d++){\n                        if(!is_conn(d)){\n                            all_conn = false;\n                            break;\n                        }\n                    }\n                    if(all_conn){\n                        ok = true;\n                        break;\n                    }\n                }\n                if(!ok){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                }\n                for(int d=0; d<D; d++) recompute_day(d);\n                cur_total = 0;\n                for(ll v : day_score) cur_total += v;\n                stagnant = 0;\n                if(cur_total < best_total){\n                    best_total = cur_total;\n                    best_edge_day = edge_day;\n                    best_day_edges = day_edges;\n                }\n            }\n        }\n    }\n\n    for(int i=0;i<M;i++){\n        if(i) cout << ' ';\n        cout << best_edge_day[i] + 1;\n    }\n    cout << '\\n';\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nvector<string> F[2], R[2];\nusing BS = bitset<196>;\nBS validMask[2][16];\nBS occ[2][16];\nbool needF[2][16][16];\nbool needR[2][16][16];\nBS rectMask[16][16][16][16];\n\nstruct Block {\n    int id;\n    vector<array<int,3>> cells[2];\n};\n\nvector<Block> blocks;\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nchrono::steady_clock::time_point startT;\n\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startT).count();\n}\n\n// 24 proper rotations (determinant +1)\nvector<array<array<int,3>,3>> genRotations() {\n    vector<array<array<int,3>,3>> res;\n    array<int,3> p = {0,1,2};\n    do {\n        int signPerm = ((p[0]==0 && p[1]==1 && p[2]==2) ||\n                        (p[0]==1 && p[1]==2 && p[2]==0) ||\n                        (p[0]==2 && p[1]==0 && p[2]==1)) ? 1 : -1;\n        for (int sx : {1,-1}) {\n            for (int sy : {1,-1}) {\n                int sz = sx * sy * signPerm;\n                array<array<int,3>,3> m = {};\n                m[0][p[0]] = sx;\n                m[1][p[1]] = sy;\n                m[2][p[2]] = sz;\n                res.push_back(m);\n            }\n        }\n    } while (next_permutation(p.begin(), p.end()));\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    startT = chrono::steady_clock::now();\n\n    // ---------- input ----------\n    if (!(cin >> D)) return 0;\n    for (int i = 0; i < 2; ++i) {\n        F[i].resize(D); R[i].resize(D);\n        for (int z = 0; z < D; ++z) cin >> F[i][z];\n        for (int z = 0; z < D; ++z) cin >> R[i][z];\n    }\n\n    auto rots = genRotations();\n\n    // ---------- precompute valid masks and needs ----------\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            for (int x = 0; x < D; ++x) {\n                needF[i][z][x] = (F[i][z][x] == '1');\n                for (int y = 0; y < D; ++y) {\n                    bool ok = (F[i][z][x] == '1' && R[i][z][y] == '1');\n                    if (ok) validMask[i][z].set(x * D + y);\n                    needR[i][z][y] = (R[i][z][y] == '1');\n                }\n            }\n        }\n    }\n\n    // ---------- precompute rectangle bitsets ----------\n    for (int dx = 1; dx <= D; ++dx)\n        for (int dy = 1; dy <= D; ++dy)\n            for (int x = 0; x + dx <= D; ++x)\n                for (int y = 0; y + dy <= D; ++y) {\n                    BS m;\n                    for (int i = x; i < x + dx; ++i)\n                        for (int j = y; j < y + dy; ++j)\n                            m.set(i * D + j);\n                    rectMask[dx][dy][x][y] = m;\n                }\n\n    int nextId = 1;\n\n    // ---------- helper: place a block ----------\n    auto placeBlock = [&](const vector<array<int,3>>& c1,\n                          const vector<array<int,3>>& c2) {\n        int id = nextId++;\n        for (auto [x,y,z] : c1) {\n            occ[0][z].set(x * D + y);\n            needF[0][z][x] = false;\n            needR[0][z][y] = false;\n        }\n        for (auto [x,y,z] : c2) {\n            occ[1][z].set(x * D + y);\n            needF[1][z][x] = false;\n            needR[1][z][y] = false;\n        }\n        blocks.push_back({id, c1, c2});\n    };\n\n    // ---------- BOX PHASE ----------\n    const double BOX_TIME_LIMIT = 3.0;\n    for (int round = 0; ; ++round) {\n        if (elapsed() > BOX_TIME_LIMIT) break;\n\n        long long bestScore = -1;\n        int best_dx=0,best_dy=0,best_dz=0;\n        int best_x1=0,best_y1=0,best_z1=0;\n        int best_x2=0,best_y2=0,best_z2=0;\n\n        for (int dx = 1; dx <= D; ++dx) {\n            for (int dy = 1; dy <= D; ++dy) {\n                for (int dz = 1; dz <= D; ++dz) {\n                    int vol = dx * dy * dz;\n                    if (vol < 2) continue;\n\n                    // list of valid positions in object 2 for this box shape\n                    vector<array<int,3>> l2;\n                    l2.reserve(1024);\n                    for (int x2 = 0; x2 + dx <= D; ++x2)\n                        for (int y2 = 0; y2 + dy <= D; ++y2) {\n                            const BS& m = rectMask[dx][dy][x2][y2];\n                            for (int z2 = 0; z2 + dz <= D; ++z2) {\n                                bool ok = true;\n                                for (int k = 0; k < dz; ++k) {\n                                    if ((occ[1][z2 + k] & m).any() ||\n                                        (validMask[1][z2 + k] & m) != m) {\n                                        ok = false; break;\n                                    }\n                                }\n                                if (ok) l2.push_back({x2, y2, z2});\n                            }\n                        }\n                    if (l2.empty()) continue;\n\n                    for (int x1 = 0; x1 + dx <= D; ++x1)\n                        for (int y1 = 0; y1 + dy <= D; ++y1) {\n                            const BS& m1 = rectMask[dx][dy][x1][y1];\n                            for (int z1 = 0; z1 + dz <= D; ++z1) {\n                                bool ok = true;\n                                for (int k = 0; k < dz; ++k) {\n                                    if ((occ[0][z1 + k] & m1).any() ||\n                                        (validMask[0][z1 + k] & m1) != m1) {\n                                        ok = false; break;\n                                    }\n                                }\n                                if (!ok) continue;\n\n                                int np1 = 0;\n                                for (int k = 0; k < dz; ++k) {\n                                    for (int i = 0; i < dx; ++i)\n                                        if (needF[0][z1 + k][x1 + i]) ++np1;\n                                    for (int j = 0; j < dy; ++j)\n                                        if (needR[0][z1 + k][y1 + j]) ++np1;\n                                }\n\n                                int samples = min((int)l2.size(), 25);\n                                for (int s = 0; s < samples; ++s) {\n                                    int idx = (int)(rng() % l2.size());\n                                    auto [x2, y2, z2] = l2[idx];\n                                    int np2 = 0;\n                                    for (int k = 0; k < dz; ++k) {\n                                        for (int i = 0; i < dx; ++i)\n                                            if (needF[1][z2 + k][x2 + i]) ++np2;\n                                        for (int j = 0; j < dy; ++j)\n                                            if (needR[1][z2 + k][y2 + j]) ++np2;\n                                    }\n                                    if (np1 + np2 == 0) continue;\n                                    long long score = (long long)(np1 + np2) * 1000LL + vol;\n                                    if (score > bestScore) {\n                                        bestScore = score;\n                                        best_dx = dx; best_dy = dy; best_dz = dz;\n                                        best_x1 = x1; best_y1 = y1; best_z1 = z1;\n                                        best_x2 = x2; best_y2 = y2; best_z2 = z2;\n                                    }\n                                }\n                            }\n                        }\n                }\n            }\n        }\n\n        if (bestScore <= 0) break;\n\n        vector<array<int,3>> c1, c2;\n        c1.reserve(best_dx * best_dy * best_dz);\n        c2.reserve(best_dx * best_dy * best_dz);\n        for (int k = 0; k < best_dz; ++k)\n            for (int i = 0; i < best_dx; ++i)\n                for (int j = 0; j < best_dy; ++j)\n                    c1.push_back({best_x1 + i, best_y1 + j, best_z1 + k});\n        for (int k = 0; k < best_dz; ++k)\n            for (int i = 0; i < best_dx; ++i)\n                for (int j = 0; j < best_dy; ++j)\n                    c2.push_back({best_x2 + i, best_y2 + j, best_z2 + k});\n        placeBlock(c1, c2);\n    }\n\n    // ---------- RANDOMIZED POLYCUBE PHASE ----------\n    const double TIME_LIMIT = 5.8;\n    const int MAX_VOL = 30;\n    const int BATCH_ITERS = 4000;\n\n    while (elapsed() < TIME_LIMIT) {\n        long long bestScore = -1;\n        vector<array<int,3>> bestC1, bestC2;\n\n        for (int it = 0; it < BATCH_ITERS; ++it) {\n            // pick random free-valid seed in obj1\n            int x1, y1, z1;\n            int attempts = 0;\n            bool ok1 = false;\n            while (attempts < 30) {\n                x1 = (int)(rng() % D);\n                y1 = (int)(rng() % D);\n                z1 = (int)(rng() % D);\n                int c = x1 * D + y1;\n                if (validMask[0][z1].test(c) && !occ[0][z1].test(c)) {\n                    ok1 = true; break;\n                }\n                ++attempts;\n            }\n            if (!ok1) continue;\n\n            // pick random free-valid seed in obj2\n            int x2, y2, z2;\n            bool ok2 = false;\n            attempts = 0;\n            while (attempts < 30) {\n                x2 = (int)(rng() % D);\n                y2 = (int)(rng() % D);\n                z2 = (int)(rng() % D);\n                int c = x2 * D + y2;\n                if (validMask[1][z2].test(c) && !occ[1][z2].test(c)) {\n                    ok2 = true; break;\n                }\n                ++attempts;\n            }\n            if (!ok2) continue;\n\n            // try a few random rotations\n            int rotCnt = 3;\n            for (int rc = 0; rc < rotCnt; ++rc) {\n                const auto& rot = rots[rng() % rots.size()];\n\n                vector<array<int,3>> shape;\n                shape.reserve(MAX_VOL);\n                shape.push_back({0,0,0});\n                vector<array<int,3>> q = {{0,0,0}};\n\n                while (!q.empty() && (int)shape.size() < MAX_VOL) {\n                    int qi = (int)(rng() % q.size());\n                    auto cur = q[qi];\n                    q[qi] = q.back();\n                    q.pop_back();\n\n                    array<int,6> order = {0,1,2,3,4,5};\n                    shuffle(order.begin(), order.end(), rng);\n                    const int d6[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};\n\n                    for (int dirIdx : order) {\n                        int nx = cur[0] + d6[dirIdx][0];\n                        int ny = cur[1] + d6[dirIdx][1];\n                        int nz = cur[2] + d6[dirIdx][2];\n\n                        bool dup = false;\n                        for (auto &s : shape) {\n                            if (s[0]==nx && s[1]==ny && s[2]==nz) { dup=true; break; }\n                        }\n                        if (dup) continue;\n\n                        int ax1 = x1 + nx;\n                        int ay1 = y1 + ny;\n                        int az1 = z1 + nz;\n                        if (ax1 < 0 || ax1 >= D || ay1 < 0 || ay1 >= D || az1 < 0 || az1 >= D) continue;\n                        int c1 = ax1 * D + ay1;\n                        if (!validMask[0][az1].test(c1) || occ[0][az1].test(c1)) continue;\n\n                        int rx = rot[0][0]*nx + rot[0][1]*ny + rot[0][2]*nz;\n                        int ry = rot[1][0]*nx + rot[1][1]*ny + rot[1][2]*nz;\n                        int rz = rot[2][0]*nx + rot[2][1]*ny + rot[2][2]*nz;\n                        int ax2 = x2 + rx;\n                        int ay2 = y2 + ry;\n                        int az2 = z2 + rz;\n                        if (ax2 < 0 || ax2 >= D || ay2 < 0 || ay2 >= D || az2 < 0 || az2 >= D) continue;\n                        int c2 = ax2 * D + ay2;\n                        if (!validMask[1][az2].test(c2) || occ[1][az2].test(c2)) continue;\n\n                        shape.push_back({nx, ny, nz});\n                        q.push_back({nx, ny, nz});\n                        if ((int)shape.size() >= MAX_VOL) break;\n                    }\n                }\n\n                if ((int)shape.size() < 2) continue;\n\n                // compute benefit\n                bool seenF1[16][16] = {}, seenR1[16][16] = {};\n                int np1 = 0;\n                for (auto &rel : shape) {\n                    int ax = x1 + rel[0];\n                    int ay = y1 + rel[1];\n                    int az = z1 + rel[2];\n                    if (!seenF1[az][ax] && needF[0][az][ax]) {\n                        seenF1[az][ax] = true; ++np1;\n                    }\n                    if (!seenR1[az][ay] && needR[0][az][ay]) {\n                        seenR1[az][ay] = true; ++np1;\n                    }\n                }\n\n                bool seenF2[16][16] = {}, seenR2[16][16] = {};\n                int np2 = 0;\n                for (auto &rel : shape) {\n                    int rx = rot[0][0]*rel[0] + rot[0][1]*rel[1] + rot[0][2]*rel[2];\n                    int ry = rot[1][0]*rel[0] + rot[1][1]*rel[1] + rot[1][2]*rel[2];\n                    int rz = rot[2][0]*rel[0] + rot[2][1]*rel[1] + rot[2][2]*rel[2];\n                    int ax = x2 + rx;\n                    int ay = y2 + ry;\n                    int az = z2 + rz;\n                    if (!seenF2[az][ax] && needF[1][az][ax]) {\n                        seenF2[az][ax] = true; ++np2;\n                    }\n                    if (!seenR2[az][ay] && needR[1][az][ay]) {\n                        seenR2[az][ay] = true; ++np2;\n                    }\n                }\n\n                if (np1 + np2 == 0) continue;\n                long long score = (long long)(np1 + np2) * 1000LL + (int)shape.size();\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestC1.clear(); bestC2.clear();\n                    bestC1.reserve(shape.size());\n                    bestC2.reserve(shape.size());\n                    for (auto &rel : shape) {\n                        bestC1.push_back({x1 + rel[0], y1 + rel[1], z1 + rel[2]});\n                        int rx = rot[0][0]*rel[0] + rot[0][1]*rel[1] + rot[0][2]*rel[2];\n                        int ry = rot[1][0]*rel[0] + rot[1][1]*rel[1] + rot[1][2]*rel[2];\n                        int rz = rot[2][0]*rel[0] + rot[2][1]*rel[1] + rot[2][2]*rel[2];\n                        bestC2.push_back({x2 + rx, y2 + ry, z2 + rz});\n                    }\n                }\n            }\n        }\n\n        if (bestScore > 0) {\n            placeBlock(bestC1, bestC2);\n        } else {\n            // no improving candidate in this batch; try a few more then give up\n            static int emptyBatches = 0;\n            ++emptyBatches;\n            if (emptyBatches >= 3) break;\n        }\n    }\n\n    // ---------- FILL REMAINING WITH UNIT CUBES ----------\n    vector<array<int,3>> fill[2];\n    for (int idx = 0; idx < 2; ++idx) {\n        // cover remaining F pixels\n        for (int z = 0; z < D; ++z) {\n            for (int x = 0; x < D; ++x) {\n                if (!needF[idx][z][x]) continue;\n                for (int y = 0; y < D; ++y) {\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                        occ[idx][z].set(c);\n                        fill[idx].push_back({x, y, z});\n                        needF[idx][z][x] = false;\n                        needR[idx][z][y] = false;\n                        break;\n                    }\n                }\n            }\n        }\n        // cover remaining R pixels\n        for (int z = 0; z < D; ++z) {\n            for (int y = 0; y < D; ++y) {\n                if (!needR[idx][z][y]) continue;\n                for (int x = 0; x < D; ++x) {\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                        occ[idx][z].set(c);\n                        fill[idx].push_back({x, y, z});\n                        needF[idx][z][x] = false;\n                        needR[idx][z][y] = false;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    // Pair up unit cubes between objects as shared unit cubes\n    int common = min((int)fill[0].size(), (int)fill[1].size());\n    vector<int> id0(fill[0].size()), id1(fill[1].size());\n    int curId = 1;\n    for (auto &bl : blocks) bl.id = curId++;\n    for (int i = 0; i < common; ++i) {\n        id0[i] = curId;\n        id1[i] = curId;\n        ++curId;\n    }\n    for (int i = common; i < (int)fill[0].size(); ++i) id0[i] = curId++;\n    for (int i = common; i < (int)fill[1].size(); ++i) id1[i] = curId++;\n\n    vector<int> b0(D * D * D, 0), b1(D * D * D, 0);\n    for (auto &bl : blocks) {\n        for (auto [x,y,z] : bl.cells[0])\n            b0[x * D * D + y * D + z] = bl.id;\n        for (auto [x,y,z] : bl.cells[1])\n            b1[x * D * D + y * D + z] = bl.id;\n    }\n    for (int i = 0; i < (int)fill[0].size(); ++i) {\n        auto [x,y,z] = fill[0][i];\n        b0[x * D * D + y * D + z] = id0[i];\n    }\n    for (int i = 0; i < (int)fill[1].size(); ++i) {\n        auto [x,y,z] = fill[1][i];\n        b1[x * D * D + y * D + z] = id1[i];\n    }\n\n    int n = curId - 1;\n    cout << n << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b0[i];\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b1[i];\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = (1LL << 60);\n\nint N, M, K;\n\nstruct Edge {\n    int u, v;\n    long long w;\n    int id;\n};\n\nvector<Edge> edges;\nvector<Edge> edges_sorted;\nvector<vector<pair<int,int>>> adj;          // (to, edge_id)\nvector<vector<int>> need;                   // [vertex][resident]\nvector<vector<pair<int,int>>> res_sorted;   // [resident] -> (need, vertex) sorted\nvector<vector<int>> edge_id_mat;\n\n// ---------- integer sqrt : ceil(sqrt(x)) ----------\nint isqrt_ceil(long long x) {\n    if (x <= 0) return 0;\n    int r = (int)std::sqrt((double)x);\n    while (1LL * r * r < x) ++r;\n    while (1LL * r * r > x) --r;\n    return (1LL * r * r == x) ? r : r + 1;\n}\n\n// ---------- DSU (static size, no allocation) ----------\nstruct DSU {\n    int p[100];\n    int rnk[100];\n    void init(int n) {\n        for (int i = 0; i < n; ++i) {\n            p[i] = i;\n            rnk[i] = 0;\n        }\n    }\n    int find(int x) {\n        return p[x] == x ? x : p[x] = find(p[x]);\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a, b);\n        p[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n};\n\n// ---------- MST cost for a given active set ----------\nlong long calc_mst(const vector<char>& inV, vector<pair<int,int>>& te) {\n    te.clear();\n    int nV = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) ++nV;\n    if (nV == 0) return INF;\n    if (nV == 1) return 0;\n\n    DSU dsu;\n    dsu.init(N);\n    long long cost = 0;\n    int used = 0;\n    for (const auto& e : edges_sorted) {\n        if (!inV[e.u] || !inV[e.v]) continue;\n        if (dsu.unite(e.u, e.v)) {\n            te.emplace_back(e.u, e.v);\n            cost += e.w;\n            if (++used == nV - 1) break;\n        }\n    }\n    if (used != nV - 1) return INF;\n    return cost;\n}\n\n// ---------- Power cost for a given active set ----------\nlong long calc_power(const vector<char>& inV, vector<int>& P) {\n    P.assign(N, 0);\n    for (int k = 0; k < K; ++k) {\n        int best_v = -1;\n        int best_need = INT_MAX;\n        for (auto& [nd, v] : res_sorted[k]) {\n            if (inV[v]) {\n                best_v = v;\n                best_need = nd;\n                break;\n            }\n        }\n        if (best_v == -1 || best_need > 5000) return INF;\n        if (best_need > P[best_v]) P[best_v] = best_need;\n    }\n    long long cost = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) cost += 1LL * P[i] * P[i];\n    return cost;\n}\n\n// ---------- helpers for local search ----------\nvector<int> get_leaves(const vector<pair<int,int>>& te, const vector<char>& inV) {\n    vector<int> deg(N, 0);\n    for (auto& [u, v] : te) {\n        ++deg[u]; ++deg[v];\n    }\n    vector<int> res;\n    for (int i = 1; i < N; ++i)\n        if (inV[i] && deg[i] == 1) res.push_back(i);\n    return res;\n}\n\nvector<int> get_candidates(const vector<char>& inV) {\n    vector<char> seen(N, 0);\n    vector<int> res;\n    for (int i = 0; i < N; ++i) if (inV[i]) {\n        for (auto& [to, id] : adj[i]) {\n            if (!inV[to] && !seen[to]) {\n                seen[to] = 1;\n                res.push_back(to);\n            }\n        }\n    }\n    return res;\n}\n\n// ---------- local search (add / remove / swap) ----------\nvoid local_search(vector<char>& inV, vector<pair<int,int>>& te, vector<int>& P, long long& total_cost) {\n    while (true) {\n        long long best_cost = total_cost;\n        vector<char> best_inV = inV;\n        vector<pair<int,int>> best_te = te;\n        vector<int> best_P = P;\n        bool improved = false;\n\n        // --- remove leaf ---\n        vector<int> leaves = get_leaves(te, inV);\n        for (int u : leaves) {\n            vector<char> inV2 = inV;\n            inV2[u] = 0;\n            vector<pair<int,int>> te2;\n            long long ec = calc_mst(inV2, te2);\n            if (ec >= INF) continue;\n            vector<int> P2;\n            long long pc = calc_power(inV2, P2);\n            if (pc >= INF) continue;\n            long long tot = ec + pc;\n            if (tot < best_cost) {\n                best_cost = tot;\n                best_inV = inV2;\n                best_te = te2;\n                best_P = P2;\n                improved = true;\n            }\n        }\n\n        // --- add neighbour ---\n        vector<int> cands = get_candidates(inV);\n        for (int v : cands) {\n            vector<char> inV2 = inV;\n            inV2[v] = 1;\n            vector<pair<int,int>> te2;\n            long long ec = calc_mst(inV2, te2);\n            if (ec >= INF) continue;\n            vector<int> P2;\n            long long pc = calc_power(inV2, P2);\n            if (pc >= INF) continue;\n            long long tot = ec + pc;\n            if (tot < best_cost) {\n                best_cost = tot;\n                best_inV = inV2;\n                best_te = te2;\n                best_P = P2;\n                improved = true;\n            }\n        }\n\n        if (improved) {\n            inV = best_inV;\n            te = best_te;\n            P = best_P;\n            total_cost = best_cost;\n            continue;\n        }\n\n        // --- swap leaf <-> outside vertex ---\n        vector<int> non_active;\n        for (int i = 0; i < N; ++i) if (!inV[i]) non_active.push_back(i);\n        for (int u : leaves) {\n            for (int v : non_active) {\n                if (v == u) continue;\n                vector<char> inV2 = inV;\n                inV2[u] = 0;\n                inV2[v] = 1;\n                vector<pair<int,int>> te2;\n                long long ec = calc_mst(inV2, te2);\n                if (ec >= INF) continue;\n                vector<int> P2;\n                long long pc = calc_power(inV2, P2);\n                if (pc >= INF) continue;\n                long long tot = ec + pc;\n                if (tot < best_cost) {\n                    best_cost = tot;\n                    best_inV = inV2;\n                    best_te = te2;\n                    best_P = P2;\n                    improved = true;\n                }\n            }\n        }\n\n        if (improved) {\n            inV = best_inV;\n            te = best_te;\n            P = best_P;\n            total_cost = best_cost;\n        } else {\n            break;\n        }\n    }\n}\n\n// ---------- try an initial state and update global best ----------\nlong long global_best_cost = INF;\nvector<char> global_best_inV;\nvector<pair<int,int>> global_best_te;\nvector<int> global_best_P;\n\nvoid try_state(vector<char> init_inV) {\n    vector<pair<int,int>> te;\n    long long ec = calc_mst(init_inV, te);\n    if (ec >= INF) return;\n    vector<int> P;\n    long long pc = calc_power(init_inV, P);\n    if (pc >= INF) return;\n    long long tot = ec + pc;\n    local_search(init_inV, te, P, tot);\n    if (tot < global_best_cost) {\n        global_best_cost = tot;\n        global_best_inV = init_inV;\n        global_best_te = te;\n        global_best_P = P;\n    }\n}\n\n// ---------- random restart generator ----------\nvector<char> random_init(mt19937& rng) {\n    vector<char> inV(N, 1);\n    int steps = (int)(rng() % (N / 2 + 1)) + 1;\n    for (int s = 0; s < steps; ++s) {\n        vector<pair<int,int>> te;\n        if (calc_mst(inV, te) >= INF) break;\n        vector<int> leaves = get_leaves(te, inV);\n        if (leaves.empty()) break;\n        uniform_int_distribution<int> dist(0, (int)leaves.size() - 1);\n        inV[leaves[dist(rng)]] = 0;\n    }\n    vector<pair<int,int>> te;\n    if (calc_mst(inV, te) >= INF) {\n        inV.assign(N, 1);\n    }\n    return inV;\n}\n\n// ============================================================\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    clock_t start_clock = clock();\n    const double TL = 1.9;          // seconds\n\n    cin >> N >> M >> K;\n    vector<long long> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    edges.resize(M);\n    adj.assign(N, {});\n    edge_id_mat.assign(N, vector<int>(N, -1));\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w, j};\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n        edge_id_mat[u][v] = edge_id_mat[v][u] = j;\n    }\n\n    vector<long long> a(K), b(K);\n    for (int k = 0; k < K; ++k) cin >> a[k] >> b[k];\n\n    // precompute need[i][k]\n    need.assign(N, vector<int>(K));\n    for (int i = 0; i < N; ++i) {\n        for (int k = 0; k < K; ++k) {\n            long long dx = xs[i] - a[k];\n            long long dy = ys[i] - b[k];\n            long long sq = dx * dx + dy * dy;\n            need[i][k] = isqrt_ceil(sq);\n        }\n    }\n\n    // precompute sorted vertex lists per resident\n    res_sorted.assign(K, {});\n    for (int k = 0; k < K; ++k) {\n        res_sorted[k].resize(N);\n        for (int i = 0; i < N; ++i) res_sorted[k][i] = {need[i][k], i};\n        sort(res_sorted[k].begin(), res_sorted[k].end());\n    }\n\n    edges_sorted = edges;\n    sort(edges_sorted.begin(), edges_sorted.end(),\n         [](const Edge& a, const Edge& b){ return a.w < b.w; });\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // 1) deterministic start from all vertices\n    {\n        vector<char> allV(N, 1);\n        try_state(allV);\n    }\n\n    // 2) random restarts until time limit\n    int restart = 0;\n    while ((double)(clock() - start_clock) / CLOCKS_PER_SEC < TL) {\n        ++restart;\n        vector<char> init = random_init(rng);\n        try_state(init);\n    }\n\n    // ---------- output ----------\n    vector<int> P_out(N, 0);\n    for (int i = 0; i < N; ++i)\n        if (global_best_inV[i]) P_out[i] = global_best_P[i];\n\n    vector<int> B(M, 0);\n    for (auto& [u, v] : global_best_te) {\n        B[edge_id_mat[u][v]] = 1;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << P_out[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << B[j];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    int x1, y1, x2, y2;\n};\n\nstruct Solver {\n    static constexpr int N = 30;\n    static constexpr int TOTAL = N * (N + 1) / 2; // 465\n\n    // convert (x,y) -> id, and back\n    static int ID(int x, int y) { return x * (x + 1) / 2 + y; }\n\n    vector<pair<int,int>> coord;\n    vector<vector<int>> adj;\n    vector<int> target;          // target layer of each value\n    vector<int> init_val, init_pos;\n\n    Solver() {\n        coord.resize(TOTAL);\n        for (int x = 0; x < N; ++x)\n            for (int y = 0; y <= x; ++y)\n                coord[ID(x, y)] = {x, y};\n\n        adj.resize(TOTAL);\n        const int dx[6] = {-1,-1,0,0,1,1};\n        const int dy[6] = {-1,0,-1,1,0,1};\n        for (int x = 0; x < N; ++x) {\n            for (int y = 0; y <= x; ++y) {\n                int u = ID(x, y);\n                for (int dir = 0; dir < 6; ++dir) {\n                    int nx = x + dx[dir];\n                    int ny = y + dy[dir];\n                    if (nx < 0 || nx >= N) continue;\n                    if (ny < 0 || ny > nx) continue;\n                    int v = ID(nx, ny);\n                    adj[u].push_back(v);\n                }\n            }\n        }\n\n        target.resize(TOTAL);\n        for (int x = 0; x < N; ++x) {\n            int L = x * (x + 1) / 2;\n            int R = (x + 1) * (x + 2) / 2;\n            for (int v = L; v < R; ++v) target[v] = x;\n        }\n    }\n\n    // Hungarian for minimum cost assignment (square matrix)\n    vector<int> hungarian(const vector<vector<int>>& a) {\n        int n = (int)a.size();\n        if (n == 0) return {};\n        vector<int> u(n + 1), v(n + 1), p(n + 1), way(n + 1);\n        for (int i = 1; i <= n; ++i) {\n            p[0] = i;\n            int j0 = 0;\n            vector<int> minv(n + 1, INT_MAX);\n            vector<char> used(n + 1, false);\n            do {\n                used[j0] = true;\n                int i0 = p[j0], delta = INT_MAX, j1 = 0;\n                for (int j = 1; j <= n; ++j) if (!used[j]) {\n                    int cur = a[i0 - 1][j - 1] - u[i0] - v[j];\n                    if (cur < minv[j]) {\n                        minv[j] = cur;\n                        way[j] = j0;\n                    }\n                    if (minv[j] < delta) {\n                        delta = minv[j];\n                        j1 = j;\n                    }\n                }\n                for (int j = 0; j <= n; ++j) {\n                    if (used[j]) {\n                        u[p[j]] += delta;\n                        v[j] -= delta;\n                    } else {\n                        minv[j] -= delta;\n                    }\n                }\n                j0 = j1;\n            } while (p[j0] != 0);\n            do {\n                int j1 = way[j0];\n                p[j0] = p[j1];\n                j0 = j1;\n            } while (j0);\n        }\n        vector<int> ans(n);\n        for (int j = 1; j <= n; ++j) {\n            if (p[j] != 0) ans[p[j] - 1] = j - 1;\n        }\n        return ans;\n    }\n\n    // strategy: 0 = execute cheapest matched pair first, 1 = execute most expensive first\n    vector<Operation> solve(int strategy) {\n        vector<int> val = init_val;\n        vector<int> pos = init_pos;\n        vector<char> fixed(TOTAL, 0);\n        vector<Operation> ops;\n        ops.reserve(8000);\n\n        for (int layer = 0; layer < N; ++layer) {\n            vector<int> remaining;\n            remaining.reserve(layer + 1);\n            for (int y = 0; y <= layer; ++y) remaining.push_back(ID(layer, y));\n\n            while (!remaining.empty()) {\n                int m = (int)remaining.size();\n\n                // collect positions of balls whose target is this layer\n                vector<int> balls;\n                balls.reserve(m);\n                for (int id = 0; id < TOTAL; ++id) {\n                    if (fixed[id]) continue;\n                    if (target[val[id]] == layer) balls.push_back(id);\n                }\n\n                // compute shortest path distances from every ball to every remaining cell\n                vector<vector<int>> cost(m, vector<int>(m, -1));\n                for (int j = 0; j < m; ++j) {\n                    int start = balls[j];\n                    vector<int> dist(TOTAL, -1);\n                    queue<int> q;\n                    dist[start] = 0;\n                    q.push(start);\n                    while (!q.empty()) {\n                        int u = q.front(); q.pop();\n                        for (int v : adj[u]) {\n                            if (fixed[v]) continue;\n                            if (dist[v] == -1) {\n                                dist[v] = dist[u] + 1;\n                                q.push(v);\n                            }\n                        }\n                    }\n                    for (int i = 0; i < m; ++i) {\n                        cost[i][j] = dist[remaining[i]];\n                    }\n                }\n\n                // global min-cost matching\n                vector<int> match = hungarian(cost); // match[i] = ball index for cell i\n\n                // choose which matched pair to execute now\n                int best_i = 0;\n                if (strategy == 0) { // cheapest first\n                    for (int i = 1; i < m; ++i) {\n                        if (cost[i][match[i]] < cost[best_i][match[best_i]]) best_i = i;\n                    }\n                } else { // most expensive first\n                    for (int i = 1; i < m; ++i) {\n                        if (cost[i][match[i]] > cost[best_i][match[best_i]]) best_i = i;\n                    }\n                }\n                int best_j = match[best_i];\n                int s = remaining[best_i];\n                int b = balls[best_j];\n\n                if (b != s) {\n                    // Dijkstra with tie-breaking:\n                    // primary   = number of swaps (edge weight 1000)\n                    // secondary = number of other layer-balls we disturb\n                    const int BIG = 1000; // > max possible path length\n                    vector<int> d(TOTAL, INT_MAX);\n                    vector<int> parent(TOTAL, -1);\n                    using State = pair<int,int>;\n                    priority_queue<State, vector<State>, greater<State>> pq;\n                    d[b] = 0;\n                    pq.emplace(0, b);\n                    while (!pq.empty()) {\n                        auto [du, u] = pq.top(); pq.pop();\n                        if (du != d[u]) continue;\n                        if (u == s) break;\n                        for (int v : adj[u]) {\n                            if (fixed[v]) continue;\n                            int w = BIG + (target[val[v]] == layer ? 1 : 0);\n                            if (d[v] > du + w) {\n                                d[v] = du + w;\n                                parent[v] = u;\n                                pq.emplace(d[v], v);\n                            }\n                        }\n                    }\n\n                    // reconstruct path b -> ... -> s\n                    vector<int> path;\n                    int cur = s;\n                    while (cur != -1) {\n                        path.push_back(cur);\n                        if (cur == b) break;\n                        cur = parent[cur];\n                    }\n                    reverse(path.begin(), path.end());\n\n                    // execute swaps along the path\n                    for (int k = 1; k < (int)path.size(); ++k) {\n                        int u = path[k - 1];\n                        int v = path[k];\n                        auto [x1, y1] = coord[u];\n                        auto [x2, y2] = coord[v];\n                        ops.push_back({x1, y1, x2, y2});\n                        int va = val[u];\n                        int vb = val[v];\n                        swap(val[u], val[v]);\n                        pos[va] = v;\n                        pos[vb] = u;\n                    }\n                }\n\n                fixed[s] = 1;\n                vector<int> nxt;\n                nxt.reserve(m - 1);\n                for (int id : remaining) if (id != s) nxt.push_back(id);\n                remaining.swap(nxt);\n            }\n        }\n        return ops;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 30;\n    constexpr int TOTAL = N * (N + 1) / 2;\n\n    Solver solver;\n    solver.init_val.resize(TOTAL);\n    solver.init_pos.resize(TOTAL);\n    auto ID = [&](int x, int y) { return x * (x + 1) / 2 + y; };\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v; \n            cin >> v;\n            int id = ID(x, y);\n            solver.init_val[id] = v;\n            solver.init_pos[v] = id;\n        }\n    }\n\n    // run two strategies and keep the shorter sequence\n    auto ops1 = solver.solve(0);\n    auto ops2 = solver.solve(1);\n    const auto& ops = (ops1.size() <= ops2.size()) ? ops1 : ops2;\n\n    cout << ops.size() << '\\n';\n    for (const auto& op : ops) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c; cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    int si = 0;\n    int sj = (D - 1) / 2;               // entrance\n\n    /*--- BFS distances from entrance (obstacles only) ---*/\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n    dist[si][sj] = 0;\n    q.push({si, sj});\n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obstacle[ni][nj]) continue;\n            if (dist[ni][nj] != -1) continue;\n            dist[ni][nj] = dist[i][j] + 1;\n            q.push({ni, nj});\n        }\n    }\n\n    /*--- collect storage cells, sort by (dist, i, j) ---*/\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            if (!(i == si && j == sj) && !obstacle[i][j])\n                cells.push_back({i, j});\n\n    int M = (int)cells.size();\n    sort(cells.begin(), cells.end(),\n        [&](const pair<int,int>& a, const pair<int,int>& b) {\n            if (dist[a.first][a.second] != dist[b.first][b.second])\n                return dist[a.first][a.second] < dist[b.first][b.second];\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n\n    vector<vector<int>> idx(D, vector<int>(D, -1));\n    for (int k = 0; k < M; ++k) idx[cells[k].first][cells[k].second] = k;\n\n    int max_dist = 0;\n    for (auto &c : cells) max_dist = max(max_dist, dist[c.first][c.second]);\n\n    vector<int> cap(max_dist + 1, 0);\n    for (auto &c : cells) ++cap[dist[c.first][c.second]];\n\n    vector<int> layer_start(max_dist + 2, 0);          // layer_start[d] = first index of layer d\n    for (int d = 1; d <= max_dist; ++d) layer_start[d + 1] = layer_start[d] + cap[d];\n\n    vector<int> ideal_layer(M);\n    for (int t = 0; t < M; ++t) {\n        for (int d = 1; d <= max_dist; ++d) {\n            if (layer_start[d] <= t && t < layer_start[d + 1]) {\n                ideal_layer[t] = d;\n                break;\n            }\n        }\n    }\n\n    /*--- state for placement ---*/\n    vector<vector<bool>> filled(D, vector<bool>(D, false));\n    vector<vector<int>>  label_at(D, vector<int>(D, -1));\n    vector<int> rem_cap = cap;\n    vector<int> rem_labels = cap;\n\n    auto traversable = [&](int i, int j) -> bool {\n        if (i == si && j == sj) return true;\n        if (i < 0 || i >= D || j < 0 || j >= D) return false;\n        return !obstacle[i][j] && !filled[i][j];\n    };\n\n    /*--- online placement ---*/\n    for (int step = 0; step < M; ++step) {\n        int t; cin >> t;\n        int d_ideal = ideal_layer[t];\n        --rem_labels[d_ideal];\n\n        /* find articulation points of the current empty graph */\n        int disc[9][9] = {};\n        int low[9][9] = {};\n        bool ap[9][9] = {};\n        bool vis[9][9] = {};\n        int timer = 0;\n        function<void(int,int,int,int)> dfs = [&](int i, int j, int pi, int pj) {\n            vis[i][j] = true;\n            disc[i][j] = low[i][j] = ++timer;\n            int child_cnt = 0;\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                if (!traversable(ni, nj)) continue;\n                if (ni == pi && nj == pj) continue;\n                if (!vis[ni][nj]) {\n                    ++child_cnt;\n                    dfs(ni, nj, i, j);\n                    low[i][j] = min(low[i][j], low[ni][nj]);\n                    if (pi != -1 && low[ni][nj] >= disc[i][j]) ap[i][j] = true;\n                } else {\n                    low[i][j] = min(low[i][j], disc[ni][nj]);\n                }\n            }\n            if (pi == -1 && child_cnt > 1) ap[i][j] = true;\n        };\n        dfs(si, sj, -1, -1);\n\n        vector<pair<int,int>> safe;\n        for (auto &c : cells) {\n            int i = c.first, j = c.second;\n            if (filled[i][j]) continue;\n            if (vis[i][j] && !ap[i][j]) safe.push_back({i, j});\n        }\n\n        vector<int> safe_cnt(max_dist + 1, 0);\n        for (auto &c : safe) {\n            ++safe_cnt[dist[c.first][c.second]];\n        }\n\n        vector<pair<int,int>> candidates;\n        for (auto &c : safe) {\n            int d = dist[c.first][c.second];\n            bool ok = (d == d_ideal) || (safe_cnt[d] > rem_labels[d]);\n            if (ok) candidates.push_back(c);\n        }\n\n        int best_i = -1, best_j = -1;\n        int best_score = INT_MIN;\n\n        auto consider = [&](int i, int j, bool is_ideal) {\n            int d = dist[i][j];\n            int diff_layer = abs(d - d_ideal);\n            int diff_pos   = abs(idx[i][j] - t);\n            int deg = 0;\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                if (traversable(ni, nj)) ++deg;\n            }\n            int surplus = safe_cnt[d] - rem_labels[d];\n            int score = (is_ideal ? 2000000 : 0)\n                      - diff_layer * 10000\n                      + surplus * 10\n                      - diff_pos   * 100\n                      - deg;\n            if (score > best_score) {\n                best_score = score;\n                best_i = i; best_j = j;\n            }\n        };\n\n        if (!candidates.empty()) {\n            for (auto &c : candidates)\n                consider(c.first, c.second, dist[c.first][c.second] == d_ideal);\n        } else {\n            for (auto &c : safe)\n                consider(c.first, c.second, false);\n\n            if (best_i == -1) {                 // emergency fallback\n                bool vis2[9][9] = {};\n                queue<pair<int,int>> qq;\n                vis2[si][sj] = true;\n                qq.push({si, sj});\n                while (!qq.empty()) {\n                    auto [i, j] = qq.front(); qq.pop();\n                    for (int dir = 0; dir < 4; ++dir) {\n                        int ni = i + di[dir], nj = j + dj[dir];\n                        if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n                        if (vis2[ni][nj]) continue;\n                        if (!traversable(ni, nj)) continue;\n                        vis2[ni][nj] = true;\n                        qq.push({ni, nj});\n                    }\n                }\n                for (int i = 0; i < D; ++i)\n                    for (int j = 0; j < D; ++j)\n                        if (!filled[i][j] && !(i == si && j == sj) && vis2[i][j])\n                            consider(i, j, false);\n            }\n        }\n\n        filled[best_i][best_j] = true;\n        label_at[best_i][best_j] = t;\n        --rem_cap[dist[best_i][best_j]];\n        cout << best_i << ' ' << best_j << '\\n' << flush;\n    }\n\n    /*--- optimal greedy removal ---*/\n    vector<vector<bool>> is_empty(D, vector<bool>(D, false));\n    is_empty[si][sj] = true;\n\n    using State = tuple<int,int,int>;               // (label, i, j)\n    priority_queue<State, vector<State>, greater<State>> pq;\n    bool in_pq[9][9] = {};\n\n    auto add_nei = [&](int i, int j) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obstacle[ni][nj]) continue;\n            if (is_empty[ni][nj]) continue;\n            if (in_pq[ni][nj]) continue;\n            pq.emplace(label_at[ni][nj], ni, nj);\n            in_pq[ni][nj] = true;\n        }\n    };\n    add_nei(si, sj);\n\n    vector<pair<int,int>> out_order;\n    while (!pq.empty()) {\n        auto [lab, i, j] = pq.top(); pq.pop();\n        out_order.emplace_back(i, j);\n        is_empty[i][j] = true;\n        add_nei(i, j);\n    }\n\n    for (auto &p : out_order) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    cout << flush;\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nint n, m;\nint orig_g[50][50];\nint need[101][101];\nbool isB[101];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\ninline bool inside(int i, int j) { return i >= 0 && i < n && j >= 0 && j < n; }\n\nstruct State {\n    int g[50][50];\n    int sz[101];\n    int adjCnt[101][101];\n    int vis[50][50];\n    int visToken;\n    mt19937 rng;\n\n    State(unsigned seed) : visToken(1), rng(seed) {\n        memset(vis, 0, sizeof(vis));\n    }\n\n    bool connectedWithout(int i, int j, int c, int szc) {\n        // szc > 1 is guaranteed by the caller\n        int si = -1, sj = -1;\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (inside(ni, nj) && g[ni][nj] == c) {\n                si = ni; sj = nj; break;\n            }\n        }\n        if (si == -1) return false; // should not happen for sz>1 connected region\n        queue<pair<int,int>> q;\n        q.emplace(si, sj);\n        vis[si][sj] = visToken;\n        int cnt = 1;\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + di[dir], ny = y + dj[dir];\n                if (!inside(nx, ny)) continue;\n                if (g[nx][ny] != c) continue;\n                if (nx == i && ny == j) continue;\n                if (vis[nx][ny] == visToken) continue;\n                vis[nx][ny] = visToken;\n                ++cnt;\n                q.emplace(nx, ny);\n            }\n        }\n        ++visToken;\n        return cnt == szc - 1;\n    }\n\n    // d may be 0 (delete) or >0 (recolor)\n    bool canRecolor(int i, int j, int d) {\n        int c = g[i][j];\n        if (c == d) return false;\n        if (sz[c] <= 1) return false;\n\n        int neigh[4];\n        int same_c = 0;\n        int contrib_c[101] = {};\n        bool hasDneighbor = false;\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            int e = inside(ni, nj) ? g[ni][nj] : 0;\n            neigh[dir] = e;\n            if (e == c) ++same_c;\n            else ++contrib_c[e];\n            if (e == d) hasDneighbor = true;\n        }\n\n        if (d > 0) {\n            if (!hasDneighbor) return false;\n            for (int k = 0; k < 4; ++k) {\n                int e = neigh[k];\n                if (e == d) continue;\n                if (!need[d][e]) return false;\n            }\n        } else { // d == 0\n            bool hasZero = (i == 0 || i == n - 1 || j == 0 || j == n - 1);\n            for (int k = 0; k < 4; ++k) if (neigh[k] == 0) hasZero = true;\n            if (!hasZero) return false;\n            for (int k = 0; k < 4; ++k) {\n                int e = neigh[k];\n                if (e > 0 && !isB[e]) return false;\n            }\n        }\n\n        if (!connectedWithout(i, j, c, sz[c])) return false;\n\n        for (int e = 0; e <= m; ++e) {\n            if (contrib_c[e] == 0) continue;\n            if (!need[c][e]) continue;\n            int rem = adjCnt[c][e] - contrib_c[e];\n            if (e == d) rem += same_c; // c gains same_c adjacencies to d\n            if (rem <= 0) return false;\n        }\n        return true;\n    }\n\n    void applyRecolor(int i, int j, int d) {\n        int c = g[i][j];\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            int e = inside(ni, nj) ? g[ni][nj] : 0;\n            if (e != c) {\n                --adjCnt[c][e];\n                --adjCnt[e][c];\n            }\n            if (e != d) {\n                ++adjCnt[d][e];\n                ++adjCnt[e][d];\n            }\n        }\n        g[i][j] = d;\n        --sz[c];\n        ++sz[d];\n    }\n\n    int solve() {\n        for (int iter = 0; iter < 200; ++iter) {\n            bool changed = false;\n            vector<pair<int,int>> order;\n            order.reserve(n * n);\n            for (int i = 0; i < n; ++i)\n                for (int j = 0; j < n; ++j)\n                    if (g[i][j] > 0) order.emplace_back(i, j);\n\n            shuffle(order.begin(), order.end(), rng);\n\n            for (auto [i, j] : order) {\n                int c = g[i][j];\n                if (c == 0) continue;\n\n                // try delete\n                if (canRecolor(i, j, 0)) {\n                    applyRecolor(i, j, 0);\n                    changed = true;\n                    continue;\n                }\n\n                // try recolor to a neighboring color\n                int bestD = -1;\n                int bestSz = INT_MAX;\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    if (!inside(ni, nj)) continue;\n                    int d = g[ni][nj];\n                    if (d == 0 || d == c) continue;\n                    if (!canRecolor(i, j, d)) continue;\n                    if (sz[d] < bestSz) {\n                        bestSz = sz[d];\n                        bestD = d;\n                    }\n                }\n                if (bestD != -1) {\n                    applyRecolor(i, j, bestD);\n                    changed = true;\n                }\n            }\n            if (!changed) break;\n        }\n        return sz[0];\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig_g[i][j];\n\n    memset(need, 0, sizeof(need));\n    memset(isB, 0, sizeof(isB));\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = orig_g[i][j];\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (inside(ni, nj)) {\n                    int d = orig_g[ni][nj];\n                    if (c != d) need[c][d] = 1;\n                } else {\n                    need[c][0] = 1;\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) isB[c] = need[c][0];\n    for (int c = 1; c <= m; ++c) need[0][c] = isB[c];\n\n    vector<vector<int>> best_grid(n, vector<int>(n));\n    int best_zero = -1;\n    unsigned seed_base = chrono::steady_clock::now().time_since_epoch().count();\n\n    const int TRIALS = 7;\n    for (int t = 0; t < TRIALS; ++t) {\n        State S(seed_base + t);\n        // copy original grid\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                S.g[i][j] = orig_g[i][j];\n\n        // init sz\n        memset(S.sz, 0, sizeof(S.sz));\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                ++S.sz[S.g[i][j]];\n\n        // init adjCnt\n        memset(S.adjCnt, 0, sizeof(S.adjCnt));\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                int c = S.g[i][j];\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    if (inside(ni, nj)) {\n                        int d = S.g[ni][nj];\n                        if (c != d) ++S.adjCnt[c][d];\n                    } else {\n                        ++S.adjCnt[c][0];\n                    }\n                }\n            }\n        }\n\n        int zeros = S.solve();\n        if (zeros > best_zero) {\n            best_zero = zeros;\n            for (int i = 0; i < n; ++i)\n                for (int j = 0; j < n; ++j)\n                    best_grid[i][j] = S.g[i][j];\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p;\n    DSU(int n = 0) { init(n); }\n    void init(int n) { p.resize(n); iota(p.begin(), p.end(), 0); }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a != b) p[a] = b;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    if (!(cin >> N >> D >> Q)) return 0;\n    \n    // cmp: 1 = i heavier than j, -1 = i lighter, 2 = equal, 0 = unknown\n    vector<vector<char>> cmp(N, vector<char>(N, 0));\n    vector<vector<char>> done(N, vector<char>(N, 0));\n    vector<int> deg(N, 0);\n    vector<int> score(N, 0);\n    \n    for (int q = 0; q < Q; ++q) {\n        // pick item with smallest degree\n        int i = -1;\n        for (int v = 0; v < N; ++v) {\n            if (i == -1 || deg[v] < deg[i]) i = v;\n        }\n        // pick peer with closest score, then smallest degree\n        int j = -1;\n        int bestDiff = INT_MAX;\n        for (int v = 0; v < N; ++v) {\n            if (v == i || done[i][v]) continue;\n            int diff = abs(score[i] - score[v]);\n            if (j == -1 || diff < bestDiff || (diff == bestDiff && deg[v] < deg[j])) {\n                bestDiff = diff;\n                j = v;\n            }\n        }\n        if (j == -1) {\n            // fallback: any undone pair with minimum total degree\n            int bestDeg = INT_MAX;\n            for (int a = 0; a < N; ++a) {\n                for (int b = a + 1; b < N; ++b) {\n                    if (done[a][b]) continue;\n                    int d = deg[a] + deg[b];\n                    if (d < bestDeg) {\n                        bestDeg = d;\n                        i = a; j = b;\n                    }\n                }\n            }\n            if (j == -1) {\n                // all pairs exhausted (rare); reuse a pair\n                i = 0; j = 1;\n            }\n        }\n        \n        cout << \"1 1 \" << i << \" \" << j << '\\n' << flush;\n        string res;\n        cin >> res;\n        if (!done[i][j]) {\n            done[i][j] = done[j][i] = 1;\n            deg[i]++; deg[j]++;\n            if (res == \">\") {\n                cmp[i][j] = 1; cmp[j][i] = -1;\n                score[i]++; score[j]--;\n            } else if (res == \"<\") {\n                cmp[i][j] = -1; cmp[j][i] = 1;\n                score[i]--; score[j]++;\n            } else {\n                cmp[i][j] = cmp[j][i] = 2;\n            }\n        }\n    }\n    \n    // Full transitive closure (Floyd-Warshall style, one pass is enough for N=100)\n    for (int k = 0; k < N; ++k) {\n        for (int i = 0; i < N; ++i) if (done[i][k]) {\n            for (int j = 0; j < N; ++j) if (done[k][j] && !done[i][j]) {\n                if (cmp[i][k] == 2 && cmp[k][j] == 2) {\n                    cmp[i][j] = cmp[j][i] = 2;\n                    done[i][j] = done[j][i] = 1;\n                } else if ((cmp[i][k] == 1 || cmp[i][k] == 2) && (cmp[k][j] == 1 || cmp[k][j] == 2)) {\n                    if (cmp[i][k] == 1 || cmp[k][j] == 1) {\n                        cmp[i][j] = 1; cmp[j][i] = -1;\n                        done[i][j] = done[j][i] = 1;\n                    }\n                } else if ((cmp[i][k] == -1 || cmp[i][k] == 2) && (cmp[k][j] == -1 || cmp[k][j] == 2)) {\n                    if (cmp[i][k] == -1 || cmp[k][j] == -1) {\n                        cmp[i][j] = -1; cmp[j][i] = 1;\n                        done[i][j] = done[j][i] = 1;\n                    }\n                }\n            }\n        }\n    }\n    \n    // Contract equality components\n    DSU dsu(N);\n    for (int i = 0; i < N; ++i) {\n        for (int j = i + 1; j < N; ++j) {\n            if (cmp[i][j] == 2) dsu.unite(i, j);\n        }\n    }\n    vector<int> comp_id(N, -1);\n    vector<vector<int>> comps;\n    for (int i = 0; i < N; ++i) {\n        if (dsu.find(i) == i) {\n            comp_id[i] = comps.size();\n            comps.push_back({i});\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        if (comp_id[i] == -1) {\n            int r = dsu.find(i);\n            comp_id[i] = comp_id[r];\n            comps[comp_id[i]].push_back(i);\n        }\n    }\n    int C = comps.size();\n    \n    // Build DAG of components\n    vector<vector<int>> adj(C);\n    vector<int> indeg(C, 0);\n    vector<vector<char>> cdone(C, vector<char>(C, 0));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (cmp[i][j] == 1) {\n                int ci = comp_id[i], cj = comp_id[j];\n                if (ci != cj && !cdone[ci][cj]) {\n                    cdone[ci][cj] = 1;\n                    adj[ci].push_back(cj);\n                    indeg[cj]++;\n                }\n            }\n        }\n    }\n    \n    // Component score for tiebreaking (higher = probably heavier)\n    vector<int> comp_score(C, 0);\n    for (int i = 0; i < N; ++i) {\n        int ci = comp_id[i];\n        for (int j = 0; j < N; ++j) {\n            int cj = comp_id[j];\n            if (ci == cj) continue;\n            if (cmp[i][j] == 1) comp_score[ci]++;\n            else if (cmp[i][j] == -1) comp_score[ci]--;\n        }\n    }\n    \n    // Kahn's topological sort: always pick a heaviest available component\n    priority_queue<pair<int, int>> pq; // (score, id)\n    for (int c = 0; c < C; ++c) {\n        if (indeg[c] == 0) pq.emplace(comp_score[c], c);\n    }\n    vector<int> order;\n    while (!pq.empty()) {\n        auto [sc, c] = pq.top(); pq.pop();\n        for (int item : comps[c]) order.push_back(item);\n        for (int d : adj[c]) {\n            if (--indeg[d] == 0) pq.emplace(comp_score[d], d);\n        }\n    }\n    if ((int)order.size() < N) {\n        vector<char> used(N, 0);\n        for (int x : order) used[x] = 1;\n        for (int i = 0; i < N; ++i) if (!used[i]) order.push_back(i);\n    }\n    \n    // pos[i] = position in order (0 = heaviest, N-1 = lightest)\n    vector<int> pos(N);\n    for (int idx = 0; idx < N; ++idx) pos[order[idx]] = idx;\n    \n    // Estimate weights using exponential order statistics (mean), capped at M\n    const double LAMBDA = 1e-5;\n    double M = 100000.0 * N / D;\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0 / i;\n    vector<long long> ew(N);\n    for (int i = 0; i < N; ++i) {\n        int r = pos[i]; // 0 = heaviest\n        double val = (H[N] - H[r]) / LAMBDA;\n        if (val > M) val = M;\n        ew[i] = max(1LL, (long long)llround(val));\n    }\n    \n    // LPT initial assignment (descending weight)\n    vector<int> assign(N, -1);\n    vector<long long> gsum(D, 0);\n    vector<vector<int>> groups(D);\n    vector<int> ord_idx(N);\n    iota(ord_idx.begin(), ord_idx.end(), 0);\n    sort(ord_idx.begin(), ord_idx.end(), [&](int a, int b) { return ew[a] > ew[b]; });\n    for (int idx : ord_idx) {\n        int best = 0;\n        for (int g = 1; g < D; ++g) {\n            if (gsum[g] < gsum[best]) best = g;\n        }\n        assign[idx] = best;\n        gsum[best] += ew[idx];\n        groups[best].push_back(idx);\n    }\n    \n    auto calc_obj = [&](const vector<long long>& s) -> long long {\n        long long o = 0;\n        for (long long x : s) o += x * x;\n        return o;\n    };\n    \n    // Greedy local search (single moves and swaps)\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        long long bestDelta = 0;\n        int best_i = -1, best_a = -1, best_b = -1, best_j = -1;\n        for (int i = 0; i < N; ++i) {\n            int a = assign[i];\n            for (int b = 0; b < D; ++b) {\n                if (a == b) continue;\n                long long sa = gsum[a], sb = gsum[b], wi = ew[i];\n                long long nsa = sa - wi, nsb = sb + wi;\n                long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                if (delta < bestDelta) {\n                    bestDelta = delta;\n                    best_i = i; best_a = a; best_b = b; best_j = -1;\n                }\n                for (int j : groups[b]) {\n                    long long wj = ew[j];\n                    long long nsa2 = sa - wi + wj;\n                    long long nsb2 = sb - wj + wi;\n                    long long delta2 = (nsa2 * nsa2 + nsb2 * nsb2) - (sa * sa + sb * sb);\n                    if (delta2 < bestDelta) {\n                        bestDelta = delta2;\n                        best_i = i; best_a = a; best_b = b; best_j = j;\n                    }\n                }\n            }\n        }\n        if (bestDelta < 0) {\n            improved = true;\n            if (best_j == -1) {\n                int i = best_i, a = best_a, b = best_b;\n                assign[i] = b;\n                gsum[a] -= ew[i];\n                gsum[b] += ew[i];\n                auto& ga = groups[a];\n                for (size_t k = 0; k < ga.size(); ++k) {\n                    if (ga[k] == i) {\n                        ga[k] = ga.back();\n                        ga.pop_back();\n                        break;\n                    }\n                }\n                groups[b].push_back(i);\n            } else {\n                int i = best_i, j = best_j, a = best_a, b = best_b;\n                assign[i] = b;\n                assign[j] = a;\n                gsum[a] = gsum[a] - ew[i] + ew[j];\n                gsum[b] = gsum[b] - ew[j] + ew[i];\n                auto& ga = groups[a];\n                for (size_t k = 0; k < ga.size(); ++k) if (ga[k] == i) { ga[k] = j; break; }\n                auto& gb = groups[b];\n                for (size_t k = 0; k < gb.size(); ++k) if (gb[k] == j) { gb[k] = i; break; }\n            }\n        }\n    }\n    \n    long long bestObj = calc_obj(gsum);\n    vector<int> bestAssign = assign;\n    vector<long long> bestGsum = gsum;\n    vector<vector<int>> bestGroups = groups;\n    \n    // Simulated annealing\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    double T = 1e12;\n    for (int iter = 0; iter < 200000; ++iter) {\n        T *= 0.99997;\n        int type = uniform_int_distribution<int>(0, 1)(rng);\n        int a = uniform_int_distribution<int>(0, D - 1)(rng);\n        int b = uniform_int_distribution<int>(0, D - 1)(rng);\n        if (a == b) continue;\n        \n        if (type == 0 && !groups[a].empty()) {\n            int idx = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n            int i = groups[a][idx];\n            long long sa = gsum[a], sb = gsum[b];\n            long long wi = ew[i];\n            long long nsa = sa - wi, nsb = sb + wi;\n            long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n            bool accept = (delta < 0);\n            if (!accept) {\n                double prob = exp(-(double)delta / T);\n                if (uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) accept = true;\n            }\n            if (accept) {\n                gsum[a] = nsa; gsum[b] = nsb;\n                groups[a][idx] = groups[a].back();\n                groups[a].pop_back();\n                groups[b].push_back(i);\n                assign[i] = b;\n                long long curObj = calc_obj(gsum);\n                if (curObj < bestObj) {\n                    bestObj = curObj;\n                    bestAssign = assign;\n                    bestGsum = gsum;\n                    bestGroups = groups;\n                }\n            }\n        } else if (type == 1 && !groups[a].empty() && !groups[b].empty()) {\n            int idx1 = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, (int)groups[b].size() - 1)(rng);\n            int i = groups[a][idx1], j = groups[b][idx2];\n            long long sa = gsum[a], sb = gsum[b];\n            long long wi = ew[i], wj = ew[j];\n            long long nsa = sa - wi + wj, nsb = sb - wj + wi;\n            long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n            bool accept = (delta < 0);\n            if (!accept) {\n                double prob = exp(-(double)delta / T);\n                if (uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) accept = true;\n            }\n            if (accept) {\n                gsum[a] = nsa; gsum[b] = nsb;\n                swap(groups[a][idx1], groups[b][idx2]);\n                assign[i] = b; assign[j] = a;\n                long long curObj = calc_obj(gsum);\n                if (curObj < bestObj) {\n                    bestObj = curObj;\n                    bestAssign = assign;\n                    bestGsum = gsum;\n                    bestGroups = groups;\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestAssign[i];\n    }\n    cout << endl;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SimResult {\n    long long energy;\n    vector<pair<int,int>> ops;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    const int h = n / m;\n    vector<vector<int>> init(m, vector<int>(h));\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < h; ++j)\n            cin >> init[i][j];\n    \n    const int INF = 1e9;\n    \n    auto simulate = [&](int variant) -> SimResult {\n        vector<vector<int>> st = init;\n        vector<int> pos(n + 1, -1);\n        for (int i = 0; i < m; ++i)\n            for (int x : st[i]) pos[x] = i;\n        \n        vector<int> mn(m, INF);\n        for (int i = 0; i < m; ++i)\n            if (!st[i].empty())\n                mn[i] = *min_element(st[i].begin(), st[i].end());\n        \n        long long energy = 0;\n        vector<pair<int,int>> ops;\n        ops.reserve(5000);\n        \n        auto recompute = [&](int idx) {\n            if (st[idx].empty()) mn[idx] = INF;\n            else {\n                mn[idx] = INF;\n                for (int x : st[idx]) mn[idx] = min(mn[idx], x);\n            }\n        };\n        \n        for (int v = 1; v <= n; ) {\n            int s = pos[v];\n            // free removal if v is on top\n            if (!st[s].empty() && st[s].back() == v) {\n                ops.emplace_back(v, 0);\n                st[s].pop_back();\n                pos[v] = -1;\n                recompute(s);\n                ++v;\n                continue;\n            }\n            \n            // v is buried: locate it\n            int hpos = 0;\n            while (hpos < (int)st[s].size() && st[s][hpos] != v) ++hpos;\n            int k = (int)st[s].size() - hpos - 1;           // number of boxes above v\n            vector<int> T(st[s].begin() + hpos + 1, st[s].end());\n            int mxT = *max_element(T.begin(), T.end());\n            int minT = *min_element(T.begin(), T.end());\n            int w = T[0];                                    // box directly above v\n            \n            int best_d = -1;\n            tuple<int,int,int,int> best_score;\n            bool first = true;\n            \n            for (int d = 0; d < m; ++d) if (d != s) {\n                tuple<int,int,int,int> sc;\n                bool empty = st[d].empty();\n                bool safe = !empty && mn[d] >= mxT;\n                \n                if (empty) {\n                    if (variant == 2) sc = make_tuple(0, 0, 0, 0);   // prefer empty\n                    else               sc = make_tuple(1, 0, 0, 0);   // empty second\n                } else if (safe) {\n                    if (variant == 0) {               // original: best\u2011fit by top\n                        sc = make_tuple(0, st[d].back(), 0, 0);\n                    } else if (variant == 5) {        // prefer smallest host size\n                        sc = make_tuple(0, (int)st[d].size(), mn[d], 0);\n                    } else {                          // best\u2011fit by minimum\n                        sc = make_tuple(0, mn[d], 0, 0);\n                    }\n                } else {\n                    int inv = 0;\n                    int blockers = 0;\n                    for (int t : T) {\n                        if (t > mn[d]) ++blockers;\n                        for (int x : st[d])\n                            if (t > x) ++inv;\n                    }\n                    if (variant == 3) {               // blockers first\n                        sc = make_tuple(2, blockers, -mn[d], 0);\n                    } else if (variant == 4) {        // blockers, then inversions\n                        sc = make_tuple(2, blockers, inv, -mn[d]);\n                    } else {                          // original unsafe metric\n                        sc = make_tuple(2, inv, -mn[d], 0);\n                    }\n                }\n                \n                if (first || sc < best_score) {\n                    best_score = sc;\n                    best_d = d;\n                    first = false;\n                }\n            }\n            \n            // execute operation 1\n            ops.emplace_back(w, best_d + 1);\n            energy += k + 1;\n            for (int x : T) {\n                st[best_d].push_back(x);\n                pos[x] = best_d;\n            }\n            mn[best_d] = min(mn[best_d], minT);\n            st[s].resize(hpos + 1);          // keep v on top of s\n            \n            // execute operation 2\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n            pos[v] = -1;\n            recompute(s);\n            ++v;\n        }\n        return {energy, ops};\n    };\n    \n    long long best_energy = (1LL << 60);\n    vector<pair<int,int>> best_ops;\n    \n    for (int var = 0; var < 6; ++var) {\n        SimResult res = simulate(var);\n        if (res.ops.size() <= 5000 && res.energy < best_energy) {\n            best_energy = res.energy;\n            best_ops = std::move(res.ops);\n        }\n    }\n    \n    for (auto &p : best_ops)\n        cout << p.first << ' ' << p.second << '\\n';\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n};\n\nstruct HeapItem {\n    double score;\n    int eid;\n    long long ku, kv;\n    bool operator<(const HeapItem& other) const {\n        return score < other.score; // max-heap\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    if(!(cin >> N)) return 0;\n    vector<string> h(N - 1);\n    vector<string> vwall(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> vwall[i];\n    vector<vector<int>> dmat(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> dmat[i][j];\n    \n    const int V = N * N;\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto geti = [&](int v) { return v / N; };\n    auto getj = [&](int v) { return v % N; };\n    \n    vector<int> dval(V);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dval[id(i, j)] = dmat[i][j];\n    \n    // Build graph\n    vector<Edge> edges;\n    vector<vector<pair<int,int>>> adj(V); // (neighbor, edge_id)\n    auto add_edge = [&](int u, int v) {\n        int eid = (int)edges.size();\n        edges.push_back({u, v});\n        adj[u].push_back({v, eid});\n        adj[v].push_back({u, eid});\n    };\n    \n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] == '0')\n                add_edge(id(i, j), id(i + 1, j));\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            if (vwall[i][j] == '0')\n                add_edge(id(i, j), id(i, j + 1));\n        }\n    }\n    const int E = (int)edges.size();\n    \n    // Spanning tree by BFS\n    vector<int> parent(V, -1);\n    vector<char> vis(V, 0);\n    queue<int> q;\n    vis[0] = 1;\n    q.push(0);\n    vector<char> is_tree_edge(E, 0);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [v, eid] : adj[u]) {\n            if (!vis[v]) {\n                vis[v] = 1;\n                parent[v] = u;\n                is_tree_edge[eid] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Multiplicity of each undirected edge (number of traversals)\n    // We keep multiplicities even. Tree edges start with 2.\n    vector<int> mult(E, 0);\n    vector<long long> k(V, 0); // visit count = half degree = sum_{e incident} mult[e]/2, but here mult counts traversals. Actually k[v] = sum_{e incident} mult[e] / 2.\n    // To avoid fractions, we define mult[e] as number of traversals (always even), and k[v] = degree/2.\n    for (int eid = 0; eid < E; ++eid) {\n        if (is_tree_edge[eid]) {\n            mult[eid] = 2;\n            k[edges[eid].u]++;\n            k[edges[eid].v]++;\n        }\n    }\n    long long L = 0;\n    for (int i = 0; i < V; ++i) L += k[i];\n    \n    const long long L_MAX = 100000;\n    \n    auto edge_score = [&](int eid) -> double {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n        return (double)dval[u] / ((double)k[u] * (k[u] + 1.0))\n             + (double)dval[v] / ((double)k[v] * (k[v] + 1.0));\n    };\n    \n    priority_queue<HeapItem> pq;\n    for (int eid = 0; eid < E; ++eid) {\n        double sc = edge_score(eid);\n        pq.push({sc, eid, k[edges[eid].u], k[edges[eid].v]});\n    }\n    \n    while (L + 2 <= L_MAX) {\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int eid = cur.eid;\n            int u = edges[eid].u;\n            int v = edges[eid].v;\n            if (k[u] != cur.ku || k[v] != cur.kv) continue; // stale\n            // apply\n            mult[eid] += 2;\n            k[u]++; k[v]++;\n            L += 2;\n            // push neighbors of u and v\n            for (auto [w, eid2] : adj[u]) {\n                double sc = edge_score(eid2);\n                pq.push({sc, eid2, k[edges[eid2].u], k[edges[eid2].v]});\n            }\n            for (auto [w, eid2] : adj[v]) {\n                double sc = edge_score(eid2);\n                pq.push({sc, eid2, k[edges[eid2].u], k[edges[eid2].v]});\n            }\n            break;\n        }\n        if (pq.empty()) break;\n    }\n    \n    // Helper: get move character between adjacent cells\n    auto move_char = [&](int u, int v) -> char {\n        int i1 = geti(u), j1 = getj(u);\n        int i2 = geti(v), j2 = getj(v);\n        if (i2 == i1 - 1) return 'U';\n        if (i2 == i1 + 1) return 'D';\n        if (j2 == j1 - 1) return 'L';\n        return 'R';\n    };\n    \n    // Build an Eulerian tour on the multigraph.\n    auto build_tour = [&](mt19937& rng, bool use_random) -> vector<int> {\n        vector<int> mcur = mult;\n        vector<int> path;\n        path.reserve((size_t)L + 1);\n        vector<int> stk;\n        stk.reserve((size_t)L + 1);\n        stk.push_back(0);\n        vector<int> last_from(V, -1);\n        vector<int> rr_idx(V, 0);\n        \n        while (!stk.empty()) {\n            int u = stk.back();\n            int total = 0;\n            for (auto [v2, eid2] : adj[u]) total += mcur[eid2];\n            if (total == 0) {\n                path.push_back(u);\n                stk.pop_back();\n                continue;\n            }\n            int picked_eid = -1;\n            int picked_v = -1;\n            if (use_random) {\n                vector<int> cand_eid;\n                vector<int> cand_v;\n                int back_eid = -1, back_v = -1;\n                for (auto [v2, eid2] : adj[u]) {\n                    if (mcur[eid2] == 0) continue;\n                    if (v2 == last_from[u]) {\n                        back_eid = eid2;\n                        back_v = v2;\n                    } else {\n                        cand_eid.push_back(eid2);\n                        cand_v.push_back(v2);\n                    }\n                }\n                if (!cand_eid.empty()) {\n                    int idx = (int)(rng() % cand_eid.size());\n                    picked_eid = cand_eid[idx];\n                    picked_v = cand_v[idx];\n                } else {\n                    picked_eid = back_eid;\n                    picked_v = back_v;\n                }\n            } else {\n                // round-robin, avoid immediate backtrack if possible\n                int deg = (int)adj[u].size();\n                for (int iter = 0; iter < deg; ++iter) {\n                    int idx = (rr_idx[u] + iter) % deg;\n                    int eid2 = adj[u][idx].second;\n                    int v2 = adj[u][idx].first;\n                    if (mcur[eid2] == 0) continue;\n                    if (v2 == last_from[u] && total > mcur[eid2]) continue;\n                    picked_eid = eid2;\n                    picked_v = v2;\n                    rr_idx[u] = (idx + 1) % deg;\n                    break;\n                }\n                if (picked_eid == -1) {\n                    for (int iter = 0; iter < deg; ++iter) {\n                        int idx = (rr_idx[u] + iter) % deg;\n                        int eid2 = adj[u][idx].second;\n                        int v2 = adj[u][idx].first;\n                        if (mcur[eid2] > 0) {\n                            picked_eid = eid2;\n                            picked_v = v2;\n                            rr_idx[u] = (idx + 1) % deg;\n                            break;\n                        }\n                    }\n                }\n            }\n            mcur[picked_eid]--;\n            last_from[picked_v] = u;\n            stk.push_back(picked_v);\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    auto eval_cost = [&](const vector<int>& path) -> long long {\n        // path[0] = start, path.back() = start, length = L+1\n        int T = (int)path.size() - 1; // number of moves\n        vector<int> first_pos(V, -1);\n        vector<int> last_pos(V, -1);\n        vector<long long> sumsq(V, 0);\n        for (int t = 0; t < T; ++t) {\n            int cell = path[t + 1];\n            if (last_pos[cell] != -1) {\n                int gap = (t + 1) - last_pos[cell];\n                sumsq[cell] += 1LL * gap * gap;\n            } else {\n                first_pos[cell] = t + 1;\n            }\n            last_pos[cell] = t + 1;\n        }\n        long long cost = 0;\n        for (int v = 0; v < V; ++v) {\n            if (first_pos[v] != -1) {\n                int gap = T - last_pos[v] + first_pos[v];\n                sumsq[v] += 1LL * gap * gap;\n                cost += 1LL * dval[v] * sumsq[v];\n            }\n        }\n        return cost;\n    };\n    \n    long long best_cost = LLONG_MAX;\n    string best_route;\n    best_route.reserve((size_t)L);\n    \n    // fallback base DFS traversal of the spanning tree (double walk)\n    {\n        vector<vector<pair<int,char>>> children(V);\n        for (int v = 1; v < V; ++v) {\n            int p = parent[v];\n            // determine direction char from p to v\n            char c = move_char(p, v);\n            children[p].push_back({v, c});\n        }\n        string fallback;\n        function<void(int)> dfs = [&](int u) {\n            for (auto [v, c] : children[u]) {\n                fallback.push_back(c);\n                dfs(v);\n                // opposite direction\n                if (c == 'U') fallback.push_back('D');\n                else if (c == 'D') fallback.push_back('U');\n                else if (c == 'L') fallback.push_back('R');\n                else fallback.push_back('L');\n            }\n        };\n        dfs(0);\n        // ensure it returns to 0 and visits all\n        if ((int)fallback.size() <= 100000) {\n            best_route = fallback;\n            // we could eval it, but we will replace with better ones\n        }\n    }\n    \n    // Try many random seeds and heuristics\n    vector<uint32_t> seeds;\n    for (int s = 0; s < 20; ++s) seeds.push_back((uint32_t)s);\n    seeds.push_back((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (uint32_t seed : seeds) {\n        mt19937 rng(seed);\n        for (int trial = 0; trial < 15; ++trial) {\n            bool use_random = (trial % 3 != 0); // mix random and round-robin\n            auto path = build_tour(rng, use_random);\n            if ((int)path.size() != L + 1) continue;\n            long long c = eval_cost(path);\n            if (c < best_cost) {\n                best_cost = c;\n                best_route.clear();\n                for (int i = 0; i < L; ++i)\n                    best_route.push_back(move_char(path[i], path[i + 1]));\n            }\n        }\n    }\n    \n    cout << best_route << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAX_M = 200;\nconst int MAX_C = 225;          // 15*15\n\nint N, M;\nint start_cell;\nint C;                          // N*N\nvector<int> pos[26];\nint dist_arr[MAX_C][MAX_C];\n\nint layer_sz[MAX_M][5];\nint layer_cell[MAX_M][5][MAX_C];\n\n/* cost_end[t][c][e] : type target t starting from cell c,\n   end at e-th cell of the last layer (layer 4).               */\nint16_t cost_end[MAX_M][MAX_C][MAX_C];\nint16_t best_cost[MAX_M][MAX_C];   // min over e of cost_end\n\nstring targets[MAX_M];\n\n/*---------------------------------------------------------------*/\n/* Evaluate a full permutation (exact cost, optimal end cells)   */\nint evaluate_order(const vector<int>& order) {\n    int t0 = order[0];\n    int sz0 = layer_sz[t0][4];\n    int dp_prev[225];\n    for (int i = 0; i < sz0; ++i) dp_prev[i] = cost_end[t0][start_cell][i];\n\n    for (int idx = 1; idx < M; ++idx) {\n        int prev = order[idx - 1];\n        int cur  = order[idx];\n        int sz_prev = layer_sz[prev][4];\n        int sz_cur  = layer_sz[cur][4];\n        int dp_cur[225];\n        for (int j = 0; j < sz_cur; ++j) {\n            int best = INT_MAX;\n            for (int i = 0; i < sz_prev; ++i) {\n                int c = layer_cell[prev][4][i];\n                int v = dp_prev[i] + cost_end[cur][c][j];\n                if (v < best) best = v;\n            }\n            dp_cur[j] = best;\n        }\n        for (int j = 0; j < sz_cur; ++j) dp_prev[j] = dp_cur[j];\n    }\n    int last = order[M - 1];\n    int sz_last = layer_sz[last][4];\n    int best = INT_MAX;\n    for (int i = 0; i < sz_last; ++i) best = min(best, dp_prev[i]);\n    return best;\n}\n\n/*---------------------------------------------------------------*/\n/* Reconstruct the full path of cells for the best order         */\nvector<pair<int,int>> reconstruct(const vector<int>& order) {\n    vector<pair<int,int>> ans;\n\n    /* forward DP with back-pointers for end cells */\n    int t0 = order[0];\n    int sz0 = layer_sz[t0][4];\n    vector<int> dp_prev(sz0);\n    vector<vector<int>> prev_idx(M);\n    for (int i = 0; i < sz0; ++i) dp_prev[i] = cost_end[t0][start_cell][i];\n\n    for (int idx = 1; idx < M; ++idx) {\n        int prev = order[idx - 1];\n        int cur  = order[idx];\n        int sz_prev = layer_sz[prev][4];\n        int sz_cur  = layer_sz[cur][4];\n        vector<int> dp_cur(sz_cur, INT_MAX);\n        vector<int> pi(sz_cur);\n        for (int j = 0; j < sz_cur; ++j) {\n            int best = INT_MAX, best_i = -1;\n            for (int i = 0; i < sz_prev; ++i) {\n                int c = layer_cell[prev][4][i];\n                int v = dp_prev[i] + cost_end[cur][c][j];\n                if (v < best) { best = v; best_i = i; }\n            }\n            dp_cur[j] = best;\n            pi[j] = best_i;\n        }\n        prev_idx[idx] = move(pi);\n        dp_prev.swap(dp_cur);\n    }\n\n    /* backtrack chosen end cells */\n    vector<int> end_idx(M);\n    int last = order[M - 1];\n    int sz_last = layer_sz[last][4];\n    int best_i = 0;\n    for (int i = 1; i < sz_last; ++i)\n        if (dp_prev[i] < dp_prev[best_i]) best_i = i;\n    end_idx[M - 1] = best_i;\n    for (int idx = M - 1; idx >= 1; --idx)\n        end_idx[idx - 1] = prev_idx[idx][end_idx[idx]];\n\n    /* reconstruct internal 5-cell path for every target */\n    int cur_cell = start_cell;\n    for (int idx = 0; idx < M; ++idx) {\n        int t = order[idx];\n        int start_c = cur_cell;\n        int end_e   = end_idx[idx];\n\n        int dp_p[225], dp_c[225];\n        uint8_t par[5][225];\n\n        int sz_l0 = layer_sz[t][0];\n        for (int i = 0; i < sz_l0; ++i)\n            dp_p[i] = dist_arr[start_c][layer_cell[t][0][i]];\n\n        for (int l = 1; l < 5; ++l) {\n            int sz_pr = layer_sz[t][l - 1];\n            int sz_cu = layer_sz[t][l];\n            for (int j = 0; j < sz_cu; ++j) {\n                int v = layer_cell[t][l][j];\n                int best = INT_MAX;\n                uint8_t best_i = 0;\n                for (int i = 0; i < sz_pr; ++i) {\n                    int u = layer_cell[t][l - 1][i];\n                    int val = dp_p[i] + dist_arr[u][v];\n                    if (val < best) { best = val; best_i = (uint8_t)i; }\n                }\n                dp_c[j] = best;\n                par[l][j] = best_i;\n            }\n            for (int j = 0; j < sz_cu; ++j) dp_p[j] = dp_c[j];\n        }\n\n        int i4 = end_e;\n        int i3 = par[4][i4];\n        int i2 = par[3][i3];\n        int i1 = par[2][i2];\n        int i0 = par[1][i1];\n        int cells[5];\n        cells[0] = layer_cell[t][0][i0];\n        cells[1] = layer_cell[t][1][i1];\n        cells[2] = layer_cell[t][2][i2];\n        cells[3] = layer_cell[t][3][i3];\n        cells[4] = layer_cell[t][4][i4];\n\n        for (int k = 0; k < 5; ++k) {\n            int id = cells[k];\n            ans.emplace_back(id / N, id % N);\n        }\n        cur_cell = cells[4];\n    }\n    return ans;\n}\n\n/*---------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    start_cell = si * N + sj;\n    C = N * N;\n\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            pos[s[j] - 'A'].push_back(id);\n        }\n    }\n    for (int k = 0; k < M; ++k) cin >> targets[k];\n\n    /* Manhattan distances */\n    for (int i = 0; i < C; ++i) {\n        int i1 = i / N, j1 = i % N;\n        for (int j = 0; j < C; ++j) {\n            int i2 = j / N, j2 = j % N;\n            dist_arr[i][j] = abs(i1 - i2) + abs(j1 - j2);\n        }\n    }\n\n    /* Precompute target DPs */\n    for (int t = 0; t < M; ++t) {\n        for (int k = 0; k < 5; ++k) {\n            char ch = targets[t][k];\n            layer_sz[t][k] = (int)pos[ch - 'A'].size();\n            for (int idx = 0; idx < layer_sz[t][k]; ++idx)\n                layer_cell[t][k][idx] = pos[ch - 'A'][idx];\n        }\n        for (int c = 0; c < C; ++c) {\n            int dp_prev[225], dp_cur[225];\n            int sz0 = layer_sz[t][0];\n            for (int i = 0; i < sz0; ++i) {\n                int v = layer_cell[t][0][i];\n                dp_prev[i] = dist_arr[c][v];\n            }\n            for (int l = 1; l < 5; ++l) {\n                int sz_prev = layer_sz[t][l - 1];\n                int sz_cur  = layer_sz[t][l];\n                for (int j = 0; j < sz_cur; ++j) {\n                    int v = layer_cell[t][l][j];\n                    int best = INT_MAX;\n                    for (int i = 0; i < sz_prev; ++i) {\n                        int u = layer_cell[t][l - 1][i];\n                        int val = dp_prev[i] + dist_arr[u][v];\n                        if (val < best) best = val;\n                    }\n                    dp_cur[j] = best;\n                }\n                for (int j = 0; j < sz_cur; ++j) dp_prev[j] = dp_cur[j];\n            }\n            int sz4 = layer_sz[t][4];\n            int best = INT_MAX;\n            for (int j = 0; j < sz4; ++j) {\n                int val = dp_prev[j] + 5;\n                cost_end[t][c][j] = (int16_t)val;\n                if (val < best) best = val;\n            }\n            best_cost[t][c] = (int16_t)best;\n        }\n    }\n\n    /*--- Greedy initial order (one-step lookahead) ---------------*/\n    vector<int> init_order;\n    {\n        vector<char> used(M, 0);\n        init_order.reserve(M);\n        int cur = start_cell;\n        for (int step = 0; step < M; ++step) {\n            static int16_t b1c[225];\n            static int  b1t[225];\n            static int16_t b2c[225];\n            for (int d = 0; d < C; ++d) {\n                b1c[d] = INT16_MAX; b1t[d] = -1; b2c[d] = INT16_MAX;\n            }\n            for (int t = 0; t < M; ++t) if (!used[t]) {\n                for (int d = 0; d < C; ++d) {\n                    int16_t c = best_cost[t][d];\n                    if (c < b1c[d]) {\n                        b2c[d] = b1c[d];\n                        b1c[d] = c;\n                        b1t[d] = t;\n                    } else if (c < b2c[d]) {\n                        b2c[d] = c;\n                    }\n                }\n            }\n            int best_total = INT_MAX;\n            int chosen_t = -1, chosen_e = -1;\n            for (int t = 0; t < M; ++t) if (!used[t]) {\n                int sz4 = layer_sz[t][4];\n                for (int e = 0; e < sz4; ++e) {\n                    int d = layer_cell[t][4][e];\n                    int here   = cost_end[t][cur][e];\n                    int future = (step == M - 1) ? 0\n                                 : ((b1t[d] == t) ? b2c[d] : b1c[d]);\n                    int total = here + future;\n                    if (total < best_total) {\n                        best_total = total;\n                        chosen_t = t;\n                        chosen_e = e;\n                    }\n                }\n            }\n            init_order.push_back(chosen_t);\n            used[chosen_t] = 1;\n            cur = layer_cell[chosen_t][4][chosen_e];\n        }\n    }\n\n    /*--- Local search (iterated hill climbing) -------------------*/\n    vector<int> best_order = init_order;\n    int best_cost_val = evaluate_order(best_order);\n    vector<int> cur_order = init_order;\n    int cur_cost = best_cost_val;\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    int iter = 0, last_improve = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.90) break;\n\n        ++iter;\n        int type = rng() % 3;\n        int i = rng() % M;\n        int j = rng() % M;\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<int> nxt = cur_order;\n        if (type == 0) {\n            swap(nxt[i], nxt[j]);\n        } else if (type == 1) {\n            int v = nxt[i];\n            nxt.erase(nxt.begin() + i);\n            nxt.insert(nxt.begin() + j, v);\n        } else {\n            reverse(nxt.begin() + i, nxt.begin() + j + 1);\n        }\n\n        int nxt_cost = evaluate_order(nxt);\n        if (nxt_cost <= cur_cost) {\n            cur_order = move(nxt);\n            cur_cost = nxt_cost;\n            last_improve = iter;\n            if (cur_cost < best_cost_val) {\n                best_cost_val = cur_cost;\n                best_order = cur_order;\n            }\n        } else if (iter - last_improve > 5000) {\n            /* perturb to escape local optimum */\n            for (int k = 0; k < 5; ++k) {\n                int a = rng() % M, b = rng() % M;\n                if (a != b) swap(cur_order[a], cur_order[b]);\n            }\n            cur_cost = evaluate_order(cur_order);\n            last_improve = iter;\n        }\n    }\n\n    /*--- Output --------------------------------------------------*/\n    vector<pair<int,int>> ans = reconstruct(best_order);\n    for (auto &p : ans) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\ndouble eps;\nconst int MAXC = 400;          // max cells\nconst int MAXT = 400;          // max translations per field\n\n/* global data */\nvector<vector<bitset<MAXC>>> masks;                 // masks[k][t]\nvector<vector<bitset<MAXT>>> trans_cover_cell;      // cover[k][p]  (translations)\nvector<vector<bitset<MAXT>>> not_cover_cell;        // ~cover , masked to valid ones\nvector<bitset<MAXT>> all_valid;                     // all translations of field k\nvector<int> drilled_val;                            // -1 = unknown\nvector<int> drilled_cells;\nmt19937 rng;\n\n/* --------------------------------------------------------------- */\nstruct Sol {\n    bitset<MAXC> uni;\n    vector<int> assigned;\n};\n\nstruct State {\n    vector<int> assigned;\n    array<short, MAXC> sum;\n    int depth;\n};\n\n/* safe fixed\u2011point propagation, never removes a true translation */\nvoid global_propagate(vector<bitset<MAXT>>& cand) {\n    bool changed = true;\n    int it = 0;\n    while (changed && it++ < 20) {\n        changed = false;\n        vector<vector<char>> any(M, vector<char>(N * N, 0));\n        vector<vector<char>> all(M, vector<char>(N * N, 0));\n        vector<int> tot_any(N * N, 0), tot_all(N * N, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (!cand[k].any()) return;               // contradiction \u2013 should not happen\n            for (int p : drilled_cells) {\n                bool a = (cand[k] & trans_cover_cell[k][p]).any();\n                bool b = false;\n                if (cand[k].any())\n                    b = (cand[k] & not_cover_cell[k][p]).none();\n                any[k][p] = a;  all[k][p] = b;\n                if (a) tot_any[p]++;\n                if (b) tot_all[p]++;\n            }\n        }\n\n        for (int k = 0; k < M; k++) {\n            for (int t = 0; t < (int)masks[k].size(); t++) if (cand[k].test(t)) {\n                bool ok = true;\n                for (int p : drilled_cells) {\n                    int need = drilled_val[p] - (masks[k][t].test(p) ? 1 : 0);\n                    int minRem = tot_all[p] - (all[k][p] ? 1 : 0);\n                    int maxRem = tot_any[p] - (any[k][p] ? 1 : 0);\n                    if (need < minRem || need > maxRem) { ok = false; break; }\n                }\n                if (!ok) {\n                    cand[k].reset(t);\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\n/* --------------------------------------------------------------- */\nstruct DFSHelper {\n    const vector<bitset<MAXT>>& cand;\n    int limit_sol, limit_node;\n    int nodes;\n    vector<Sol> sols;\n\n    DFSHelper(const vector<bitset<MAXT>>& c, int ls, int ln)\n        : cand(c), limit_sol(ls), limit_node(ln), nodes(0) {}\n\n    void run() {\n        State init;\n        init.assigned.assign(M, -1);\n        init.sum.fill(0);\n        init.depth = 0;\n        rec(init);\n    }\n\n    void rec(State st) {\n        if ((int)sols.size() >= limit_sol || nodes >= limit_node) return;\n        ++nodes;\n        if (st.depth == M) {\n            bitset<MAXC> uni;\n            for (int k = 0; k < M; k++) uni |= masks[k][st.assigned[k]];\n            sols.push_back({uni, st.assigned});\n            return;\n        }\n        vector<int> fields;\n        for (int i = 0; i < M; i++) if (st.assigned[i] == -1) fields.push_back(i);\n        sort(fields.begin(), fields.end(),\n             [&](int a, int b) { return cand[a].count() < cand[b].count(); });\n\n        int pick = min((int)fields.size(), max(1, (int)fields.size() / 2 + 1));\n        int k = fields[rng() % pick];\n\n        vector<int> ts;\n        for (int t = 0; t < (int)masks[k].size(); t++)\n            if (cand[k].test(t)) ts.push_back(t);\n        shuffle(ts.begin(), ts.end(), rng);\n\n        for (int t : ts) {\n            State nst = st;\n            nst.assigned[k] = t;\n            ++nst.depth;\n            bool ok = true;\n            for (int p : drilled_cells) {\n                if (masks[k][t].test(p)) ++nst.sum[p];\n                int rem = M - nst.depth;\n                int need = drilled_val[p] - nst.sum[p];\n                if (need < 0 || need > rem) { ok = false; break; }\n            }\n            if (!ok) continue;\n            rec(nst);\n        }\n    }\n};\n\n/* --------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    if (!(cin >> N >> M >> eps)) return 0;\n    vector<vector<pair<int,int>>> shapes(M);\n    for (int k = 0; k < M; k++) {\n        int d; cin >> d;\n        shapes[k].resize(d);\n        for (int i = 0; i < d; i++) cin >> shapes[k][i].first >> shapes[k][i].second;\n    }\n\n    /* pre\u2011compute translations */\n    masks.assign(M, {});\n    all_valid.assign(M, {});\n    for (int k = 0; k < M; k++) {\n        int hi = 0, hj = 0;\n        for (auto &c : shapes[k]) {\n            hi = max(hi, c.first);\n            hj = max(hj, c.second);\n        }\n        int h = hi + 1, w = hj + 1;\n        for (int di = 0; di + h <= N; di++) {\n            for (int dj = 0; dj + w <= N; dj++) {\n                bitset<MAXC> bs;\n                for (auto &c : shapes[k]) {\n                    int i = di + c.first;\n                    int j = dj + c.second;\n                    bs.set(i * N + j);\n                }\n                masks[k].push_back(bs);\n            }\n        }\n        for (int t = 0; t < (int)masks[k].size(); t++) all_valid[k].set(t);\n    }\n\n    trans_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    not_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    for (int k = 0; k < M; k++) {\n        for (int p = 0; p < N * N; p++) {\n            for (int t = 0; t < (int)masks[k].size(); t++)\n                if (masks[k][t].test(p)) trans_cover_cell[k][p].set(t);\n            not_cover_cell[k][p] = all_valid[k] & ~trans_cover_cell[k][p];\n        }\n    }\n\n    drilled_val.assign(N * N, -1);\n    rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<bitset<MAXT>> cand(M);\n    for (int k = 0; k < M; k++) cand[k] = all_valid[k];\n\n    const int MAX_OPS = 2 * N * N;\n    int ops = 0;\n\n    auto do_drill = [&](int p) {\n        int i = p / N, j = p % N;\n        cout << \"q 1 \" << i << ' ' << j << endl;\n        int v; \n        if (!(cin >> v)) exit(0);\n        ++ops;\n        drilled_val[p] = v;\n        drilled_cells.push_back(p);\n        if (v == 0) {\n            for (int k = 0; k < M; k++) cand[k] &= not_cover_cell[k][p];\n        } else if (v == M) {\n            for (int k = 0; k < M; k++) cand[k] &= trans_cover_cell[k][p];\n        }\n        global_propagate(cand);\n    };\n\n    auto do_guess = [&](const bitset<MAXC>& uni) -> bool {\n        vector<pair<int,int>> ans;\n        for (int p = 0; p < N * N; p++)\n            if (uni.test(p)) ans.emplace_back(p / N, p % N);\n        cout << \"a \" << ans.size();\n        for (auto &pr : ans) cout << ' ' << pr.first << ' ' << pr.second;\n        cout << endl;\n        int resp; \n        if (!(cin >> resp)) exit(0);\n        ++ops;\n        return resp == 1;\n    };\n\n    vector<int> cell_order(N * N);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    shuffle(cell_order.begin(), cell_order.end(), rng);\n    int nxt = 0;\n\n    auto pick_random_undrilled = [&]() -> int {\n        while (nxt < N * N && drilled_val[cell_order[nxt]] != -1) ++nxt;\n        if (nxt < N * N) return cell_order[nxt++];\n        for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) return p;\n        return -1;\n    };\n\n    /* initial random drilling */\n    int init_drills = min(N * N, max(N, 4));\n    for (int i = 0; i < init_drills && ops < MAX_OPS - 5; i++) {\n        int p = pick_random_undrilled();\n        if (p == -1) break;\n        do_drill(p);\n    }\n\n    const int LIMIT_SOL = 12;\n    const int LIMIT_NODE = 60000;\n\n    while (ops < MAX_OPS - 2) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 2.6) {                     // emergency\n            bitset<MAXC> all;\n            for (int p = 0; p < N * N; p++) all.set(p);\n            do_guess(all);\n            return 0;\n        }\n\n        int undrilled = N * N - (int)drilled_cells.size();\n        if (undrilled <= 8 && ops + undrilled + 1 <= MAX_OPS) {\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) do_drill(p);\n            bitset<MAXC> exact;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            if (do_guess(exact)) return 0;\n            break;\n        }\n\n        vector<bitset<MAXC>> sol_unions;\n\n        int total_cand = 0;\n        for (int k = 0; k < M; k++) total_cand += (int)cand[k].count();\n\n        if (total_cand <= 4000) {\n            for (int trial = 0; trial < 2 && (int)sol_unions.size() < LIMIT_SOL; ++trial) {\n                DFSHelper h(cand, LIMIT_SOL - (int)sol_unions.size(), LIMIT_NODE);\n                h.run();\n                for (auto &s : h.sols) {\n                    bool seen = false;\n                    for (auto &u : sol_unions) if (u == s.uni) { seen = true; break; }\n                    if (!seen) sol_unions.push_back(s.uni);\n                }\n            }\n        }\n\n        if (sol_unions.empty()) {\n            int p = pick_random_undrilled();\n            if (p == -1) {\n                bitset<MAXC> all;\n                for (int c = 0; c < N * N; c++) all.set(c);\n                do_guess(all);\n                return 0;\n            }\n            do_drill(p);\n        } else {\n            bool agree = true;\n            for (size_t i = 1; i < sol_unions.size(); i++)\n                if (sol_unions[i] != sol_unions[0]) { agree = false; break; }\n\n            if (agree) {\n                if (do_guess(sol_unions[0])) return 0;\n                /* wrong guess \u2013 force one more drill */\n                int p = pick_random_undrilled();\n                if (p != -1) do_drill(p);\n            } else {\n                int S = (int)sol_unions.size();\n                vector<int> cnt(N * N, 0);\n                for (auto &u : sol_unions)\n                    for (int p = 0; p < N * N; p++) if (u.test(p)) ++cnt[p];\n\n                int best = -1, best_score = -1;\n                for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) {\n                    int score = min(cnt[p], S - cnt[p]);\n                    if (score > best_score) {\n                        best_score = score;\n                        best = p;\n                    }\n                }\n                if (best == -1) best = pick_random_undrilled();\n                do_drill(best);\n            }\n        }\n    }\n\n    /* final fallback */\n    bitset<MAXC> all;\n    for (int c = 0; c < N * N; c++) all.set(c);\n    do_guess(all);\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int x, y;   // top-left (x = column/j, y = row/i)\n    int w, h;   // width (horizontal), height (vertical)\n};\n\nstruct FRect {\n    int x, y, w, h;\n};\n\nstatic int W, D, N;\nstatic vector<vector<long long>> a;\n\nstatic bool intersect(const FRect& A, const FRect& B) {\n    return !(A.x + A.w <= B.x || B.x + B.w <= A.x ||\n             A.y + A.h <= B.y || B.y + B.h <= A.y);\n}\n\nstatic bool overlapRect(const Rect& A, const Rect& B) {\n    return !(A.x + A.w <= B.x || B.x + B.w <= A.x ||\n             A.y + A.h <= B.y || B.y + B.h <= A.y);\n}\n\n/* ------------------------------------------------------------------ */\n/*  Maximal Rectangles greedy packer                                   */\n/* ------------------------------------------------------------------ */\nstatic vector<Rect> pack_areas(const vector<long long>& area, int maxTrial) {\n    int n = (int)area.size();\n    vector<Rect> best;\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    for (int trial = 0; trial < maxTrial; ++trial) {\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n\n        vector<pair<int,int>> dim(n);\n        for (int idx : ord) {\n            long long A = area[idx];\n            int w, h;\n            int mode = trial % 5;\n            if (mode == 0) {\n                w = max(1, (int)std::sqrt((double)A));\n                h = (int)((A + w - 1) / w);\n            } else if (mode == 1) {\n                h = max(1, (int)std::sqrt((double)A));\n                w = (int)((A + h - 1) / h);\n            } else if (mode == 2) {\n                w = (int)max(1LL, (A + W - 1) / W);\n                h = (int)((A + w - 1) / w);\n            } else if (mode == 3) {\n                h = (int)max(1LL, (A + W - 1) / W);\n                w = (int)((A + h - 1) / h);\n            } else {\n                long long lo = max(1LL, (A + W - 1) / W);\n                long long hi = min((long long)W, A);\n                if (lo >= hi) w = (int)lo;\n                else w = uniform_int_distribution<int>((int)lo, (int)hi)(rng);\n                h = (int)((A + w - 1) / w);\n            }\n            if (h > W) { h = W; w = (int)((A + h - 1) / h); }\n            if (w > W) { w = W; h = (int)((A + w - 1) / w); }\n            if (w < 1) w = 1;\n            if (h < 1) h = 1;\n            dim[idx] = {w, h};\n        }\n\n        vector<Rect> cur(n);\n        vector<FRect> freeList;\n        freeList.reserve(500);\n        freeList.push_back({0, 0, W, W});\n        bool ok = true;\n\n        for (int idx : ord) {\n            int w = dim[idx].first;\n            int h = dim[idx].second;\n            int bestPos = -1;\n            long long bestScore = (1LL<<60);\n            int bw = w, bh = h;\n\n            for (int i = 0; i < (int)freeList.size(); ++i) {\n                const FRect& f = freeList[i];\n                if (f.w >= w && f.h >= h) {\n                    long long sc = 1LL * (f.w - w) * (f.h - h);\n                    if (sc < bestScore) {\n                        bestScore = sc; bestPos = i; bw = w; bh = h;\n                    }\n                }\n                if (f.w >= h && f.h >= w) {\n                    long long sc = 1LL * (f.w - h) * (f.h - w);\n                    if (sc < bestScore) {\n                        bestScore = sc; bestPos = i; bw = h; bh = w;\n                    }\n                }\n            }\n            if (bestPos == -1) { ok = false; break; }\n\n            FRect fr = freeList[bestPos];\n            cur[idx] = {fr.x, fr.y, bw, bh};\n            freeList.erase(freeList.begin() + bestPos);\n\n            if (fr.w > bw) freeList.push_back({fr.x + bw, fr.y, fr.w - bw, fr.h});\n            if (fr.h > bh) freeList.push_back({fr.x, fr.y + bh, fr.w, fr.h - bh});\n\n            vector<FRect> nxt;\n            nxt.reserve(freeList.size() * 2);\n            for (auto& f : freeList) {\n                if (!intersect(f, {fr.x, fr.y, bw, bh})) {\n                    nxt.push_back(f);\n                    continue;\n                }\n                if (f.x >= fr.x && f.y >= fr.y &&\n                    f.x + f.w <= fr.x + bw && f.y + f.h <= fr.y + bh) continue;\n\n                if (fr.x > f.x) nxt.push_back({f.x, f.y, fr.x - f.x, f.h});\n                if (fr.x + bw < f.x + f.w)\n                    nxt.push_back({fr.x + bw, f.y, f.x + f.w - fr.x - bw, f.h});\n                if (fr.y > f.y) nxt.push_back({f.x, f.y, f.w, fr.y - f.y});\n                if (fr.y + bh < f.y + f.h)\n                    nxt.push_back({f.x, fr.y + bh, f.w, f.y + f.h - fr.y - bh});\n            }\n            freeList.swap(nxt);\n\n            vector<FRect> pruned;\n            for (auto& f : freeList) {\n                if (f.w <= 0 || f.h <= 0) continue;\n                bool inside = false;\n                for (auto& g : freeList) {\n                    if (&f == &g) continue;\n                    if (g.x <= f.x && g.y <= f.y &&\n                        g.x + g.w >= f.x + f.w && g.y + g.h >= f.y + f.h) {\n                        if (g.x < f.x || g.y < f.y ||\n                            g.x + g.w > f.x + f.w || g.y + g.h > f.y + f.h ||\n                            &g < &f) {\n                            inside = true; break;\n                        }\n                    }\n                }\n                if (!inside) pruned.push_back(f);\n            }\n            freeList.swap(pruned);\n        }\n\n        if (ok) return cur;\n    }\n    return {};\n}\n\n/* ------------------------------------------------------------------ */\n/*  Safe fallback: equal vertical strips, always valid                */\n/* ------------------------------------------------------------------ */\nstatic vector<Rect> safe_fallback(const vector<long long>& area) {\n    int n = (int)area.size();\n    vector<Rect> res(n);\n    int w = max(1, W / n);\n    int x = 0;\n    for (int i = 0; i < n; ++i) {\n        long long A = area[i];\n        int h = (int)((A + w - 1) / w);\n        if (h > W) h = W;\n        if (h < 1) h = 1;\n        // Ensure we don't exceed horizontal boundary\n        if (x + w > W) {\n            x = W - w;\n            if (x < 0) x = 0;\n        }\n        res[i] = {x, 0, w, h};\n        x += w;\n    }\n    return res;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Validation for a single day                                       */\n/* ------------------------------------------------------------------ */\nstatic bool valid_day(const vector<Rect>& rects) {\n    for (const auto& r : rects) {\n        if (r.x < 0 || r.y < 0 || r.w <= 0 || r.h <= 0) return false;\n        if (r.x + r.w > W || r.y + r.h > W) return false;\n    }\n    for (int i = 0; i < (int)rects.size(); ++i)\n        for (int j = i + 1; j < (int)rects.size(); ++j)\n            if (overlapRect(rects[i], rects[j])) return false;\n    return true;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Main                                                               */\n/* ------------------------------------------------------------------ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> W >> D >> N)) return 0;\n    a.assign(D, vector<long long>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    vector<long long> b(N, 0);\n    for (int k = 0; k < N; ++k)\n        for (int d = 0; d < D; ++d)\n            b[k] = max(b[k], a[d][k]);\n\n    long long S = accumulate(b.begin(), b.end(), 0LL);\n\n    vector<vector<Rect>> ans(D, vector<Rect>(N));\n    bool fixed_used = false;\n    vector<Rect> fixed;\n\n    if (S <= 1LL * W * W) {\n        fixed = pack_areas(b, 2000);\n    }\n\n    if (!fixed.empty()) {\n        for (int d = 0; d < D; ++d)\n            for (int k = 0; k < N; ++k)\n                ans[d][k] = fixed[k];\n        fixed_used = true;\n    }\n\n    if (!fixed_used) {\n        // ---- try vertical strip fallback for all days ----\n        vector<long long> wmin(N);\n        long long sum_wmin = 0;\n        for (int k = 0; k < N; ++k) {\n            wmin[k] = max(1LL, (b[k] + W - 1) / W);\n            sum_wmin += wmin[k];\n        }\n\n        if (sum_wmin <= W) {\n            mt19937 rng(1234567);\n            vector<long long> best_w;\n            long long best_cost = (1LL<<60);\n\n            auto eval = [&](const vector<long long>& w)->long long {\n                vector<vector<int>> h(D, vector<int>(N));\n                for (int d = 0; d < D; ++d)\n                    for (int k = 0; k < N; ++k) {\n                        h[d][k] = (int)((a[d][k] + w[k] - 1) / w[k]);\n                        if (h[d][k] > W) h[d][k] = W;\n                    }\n                long long cost = 0;\n                for (int d = 1; d < D; ++d) {\n                    for (int k = 0; k < N; ++k) {\n                        bool e1 = (h[d-1][k] < W);\n                        bool e2 = (h[d][k] < W);\n                        if (e1 && e2 && h[d-1][k] != h[d][k]) cost += 2LL * w[k];\n                        else if (e1 != e2) cost += w[k];\n                    }\n                    for (int k = 0; k < N-1; ++k) {\n                        int M1 = max(h[d-1][k], h[d-1][k+1]);\n                        int M2 = max(h[d][k], h[d][k+1]);\n                        cost += abs(M2 - M1);\n                    }\n                }\n                return cost;\n            };\n\n            for (int attempt = 0; attempt < 6000; ++attempt) {\n                vector<long long> w = wmin;\n                long long rem = W - sum_wmin;\n                if (attempt == 0) {\n                    for (int k = 0; k < N; ++k) {\n                        long long add = rem * b[k] / S;\n                        w[k] += add;\n                        rem -= add;\n                    }\n                    for (int k = N-1; k >= 0 && rem > 0; --k) {\n                        ++w[k]; --rem;\n                    }\n                } else {\n                    vector<int> ord(N);\n                    iota(ord.begin(), ord.end(), 0);\n                    shuffle(ord.begin(), ord.end(), rng);\n                    for (int i = 0; i < N && rem > 0; ++i) {\n                        long long give = (i == N-1) ? rem : (rng() % (rem + 1));\n                        w[ord[i]] += give;\n                        rem -= give;\n                    }\n                }\n                long long c = eval(w);\n                if (c < best_cost) {\n                    best_cost = c;\n                    best_w = w;\n                }\n            }\n\n            vector<long long> pref(N+1, 0);\n            for (int k = 0; k < N; ++k) pref[k+1] = pref[k] + best_w[k];\n            for (int d = 0; d < D; ++d)\n                for (int k = 0; k < N; ++k) {\n                    int h = (int)((a[d][k] + best_w[k] - 1) / best_w[k]);\n                    if (h > W) h = W;\n                    ans[d][k] = {(int)pref[k], 0, (int)best_w[k], h};\n                }\n        } else {\n            // ---- pack each day independently ----\n            for (int d = 0; d < D; ++d) {\n                auto v = pack_areas(a[d], 2000);\n                if (v.empty()) v = safe_fallback(a[d]);\n                for (int k = 0; k < N; ++k) ans[d][k] = v[k];\n            }\n        }\n    }\n\n    // Final safety net: validate every day\n    for (int d = 0; d < D; ++d) {\n        if (!valid_day(ans[d])) {\n            auto v = safe_fallback(a[d]);\n            for (int k = 0; k < N; ++k) ans[d][k] = v[k];\n        }\n    }\n\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const Rect& r = ans[d][k];\n            cout << r.y << ' ' << r.x << ' '\n                 << r.y + r.h << ' ' << r.x + r.w << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr int POS = (N - 2) * (N - 2);          // 49\nconstexpr int TOTAL_OPS = M * POS;               // 980\nconstexpr int CELLS = N * N;                     // 81\nconstexpr int MOD = 998244353;\nconstexpr int NOP = TOTAL_OPS;                   // sentinel for \u201cno operation\u201d\n\nstruct Operation {\n    uint8_t cell[9];\n    uint32_t val[9];\n};\n\nOperation ops[TOTAL_OPS];\nint op_val_idx[TOTAL_OPS][CELLS];\n\n// ------------------------------------------------------------------\ninline ll delta_add(const uint32_t *board, int op) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[ops[op].cell[i]];\n        uint32_t s = ops[op].val[i];\n        d += (v >= MOD - s) ? (ll)s - MOD : s;\n    }\n    return d;\n}\n\ninline ll delta_remove(const uint32_t *board, int op) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[ops[op].cell[i]];\n        uint32_t s = ops[op].val[i];\n        d += (v < s) ? (ll)MOD - s : -(ll)s;\n    }\n    return d;\n}\n\n// delta of adding new_op on a board where old_op has already been removed\ninline ll delta_add_after_remove(int old_op, int new_op, const uint32_t *board) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        int c = ops[new_op].cell[i];\n        uint32_t v = board[c];\n        int idx = op_val_idx[old_op][c];\n        if (idx != -1) {\n            uint32_t so = ops[old_op].val[idx];\n            v = (v >= so) ? v - so : v + MOD - so;\n        }\n        uint32_t s = ops[new_op].val[i];\n        d += (v >= MOD - s) ? (ll)s - MOD : s;\n    }\n    return d;\n}\n\n// exact delta of changing old_op -> new_op, board unchanged\ninline ll eval_replace(int old_op, int new_op, const uint32_t *board) {\n    if (old_op == new_op) return 0;\n    if (old_op == NOP) return delta_add(board, new_op);\n    if (new_op == NOP) return delta_remove(board, old_op);\n    return delta_remove(board, old_op) + delta_add_after_remove(old_op, new_op, board);\n}\n\n// apply the replacement to board (old_op is updated by reference)\ninline void apply_replace(int &old_op, int new_op, uint32_t *board) {\n    if (old_op == new_op) return;\n    if (old_op != NOP) {\n        for (int i = 0; i < 9; ++i) {\n            int c = ops[old_op].cell[i];\n            uint32_t v = board[c];\n            uint32_t s = ops[old_op].val[i];\n            board[c] = (v >= s) ? v - s : v + MOD - s;\n        }\n    }\n    if (new_op != NOP) {\n        for (int i = 0; i < 9; ++i) {\n            int c = ops[new_op].cell[i];\n            uint32_t v = board[c] + ops[new_op].val[i];\n            if (v >= MOD) v -= MOD;\n            board[c] = v;\n        }\n    }\n    old_op = new_op;\n}\n\n// ------------------------------------------------------------------\nusing Board = array<uint32_t, CELLS>;\nusing OpsArr = array<int, K>;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k_input;\n    if (!(cin >> n >> m >> k_input)) return 0;\n\n    Board init_board{};\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            uint32_t x; cin >> x;\n            init_board[i * N + j] = x;\n        }\n\n    vector<vector<vector<uint32_t>>> stamp(M, vector<vector<uint32_t>>(3, vector<uint32_t>(3)));\n    for (int s = 0; s < M; ++s)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamp[s][i][j];\n\n    // precompute operations\n    int id = 0;\n    for (int s = 0; s < M; ++s)\n        for (int p = 0; p <= N - 3; ++p)\n            for (int q = 0; q <= N - 3; ++q) {\n                int t = 0;\n                for (int di = 0; di < 3; ++di)\n                    for (int dj = 0; dj < 3; ++dj) {\n                        ops[id].cell[t] = (p + di) * N + (q + dj);\n                        ops[id].val[t] = stamp[s][di][dj];\n                        ++t;\n                    }\n                ++id;\n            }\n\n    // op_val_idx[op][cell] = which of the 9 positions covers this cell, or -1\n    memset(op_val_idx, -1, sizeof(op_val_idx));\n    for (int op = 0; op < TOTAL_OPS; ++op)\n        for (int i = 0; i < 9; ++i)\n            op_val_idx[op][ops[op].cell[i]] = i;\n\n    ll initial_score = 0;\n    for (int i = 0; i < CELLS; ++i) initial_score += init_board[i];\n\n    // best solution found so far\n    ll best_score = initial_score;\n    OpsArr best_ops; best_ops.fill(NOP);\n    Board best_board = init_board;\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    auto hill_climb = [&](OpsArr &cur, Board &board, ll &score) {\n        while (true) {\n            int best_i = -1, best_a = -1;\n            ll best_d = 0;\n            for (int i = 0; i < K; ++i) {\n                int old = cur[i];\n                for (int a = 0; a <= TOTAL_OPS; ++a) {\n                    if (a == old) continue;\n                    ll d = eval_replace(old, a, board.data());\n                    if (d > best_d) {\n                        best_d = d;\n                        best_i = i;\n                        best_a = a;\n                    }\n                }\n            }\n            if (best_d <= 0) break;\n            apply_replace(cur[best_i], best_a, board.data());\n            score += best_d;\n        }\n    };\n\n    auto start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.95;\n\n    // -------- deterministic greedy + hill climb ----------\n    {\n        OpsArr cur; cur.fill(NOP);\n        Board board = init_board;\n        ll score = initial_score;\n        for (int step = 0; step < K; ++step) {\n            int best_op = -1;\n            ll best_d = 0;\n            for (int a = 0; a < TOTAL_OPS; ++a) {\n                ll d = delta_add(board.data(), a);\n                if (d > best_d) {\n                    best_d = d;\n                    best_op = a;\n                }\n            }\n            if (best_op == -1) break;\n            apply_replace(cur[step], best_op, board.data());\n            score += best_d;\n        }\n        hill_climb(cur, board, score);\n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur;\n            best_board = board;\n        }\n    }\n\n    int iteration = 0;\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        OpsArr cur;\n        Board board;\n        ll score;\n\n        int mode = rng() % 10;\n        if (mode < 4) {\n            // ----- randomized greedy construction -----\n            cur.fill(NOP);\n            board = init_board;\n            score = initial_score;\n            for (int step = 0; step < K; ++step) {\n                // gather positive candidates\n                static pair<ll,int> cand[1000];\n                int cand_n = 0;\n                for (int a = 0; a < TOTAL_OPS; ++a) {\n                    ll d = delta_add(board.data(), a);\n                    if (d > 0) cand[cand_n++] = {d, a};\n                }\n                int a;\n                if (cand_n > 0) {\n                    sort(cand, cand + cand_n,\n                         [](const auto &x, const auto &y){ return x.first > y.first; });\n                    int t = min(5, cand_n);\n                    a = cand[rng() % t].second;\n                } else {\n                    a = (int)(rng() % TOTAL_OPS);\n                }\n                ll d = delta_add(board.data(), a);\n                apply_replace(cur[step], a, board.data());\n                score += d;\n            }\n        } else if (mode < 6) {\n            // ----- pure random fill -----\n            cur.fill(NOP);\n            board = init_board;\n            score = initial_score;\n            for (int i = 0; i < K; ++i) {\n                int a = (int)(rng() % TOTAL_OPS);\n                ll d = delta_add(board.data(), a);\n                apply_replace(cur[i], a, board.data());\n                score += d;\n            }\n        } else {\n            // ----- kick from best -----\n            cur = best_ops;\n            board = best_board;\n            score = best_score;\n            int kick = (iteration % 20 == 0) ? (8 + (int)(rng() % 8)) : (1 + (int)(rng() % 4));\n            for (int t = 0; t < kick; ++t) {\n                int i = (int)(rng() % K);\n                int a = (int)(rng() % (TOTAL_OPS + 1));\n                if (cur[i] == a) continue;\n                ll d = eval_replace(cur[i], a, board.data());\n                apply_replace(cur[i], a, board.data());\n                score += d;\n            }\n        }\n\n        hill_climb(cur, board, score);\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur;\n            best_board = board;\n        }\n        ++iteration;\n    }\n\n    // final polish on the absolute best\n    {\n        OpsArr cur = best_ops;\n        Board board = best_board;\n        ll score = best_score;\n        hill_climb(cur, board, score);\n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur;\n        }\n    }\n\n    // output\n    int L = 0;\n    for (int i = 0; i < K; ++i) if (best_ops[i] != NOP) ++L;\n    cout << L << '\\n';\n    for (int i = 0; i < K; ++i) {\n        if (best_ops[i] == NOP) continue;\n        int op = best_ops[i];\n        int m = op / POS;\n        int rest = op % POS;\n        int p = rest / 7;\n        int q = rest % 7;\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    int A[5][5];\n    for (int i = 0; i < 5; ++i)\n        for (int j = 0; j < 5; ++j)\n            cin >> A[i][j];\n\n    int grid[5][5];\n    memset(grid, -1, sizeof(grid));\n\n    int cr[5], cc[5];\n    int hold[5];\n    int dispatched[5];\n    int next_in[5];\n    for (int i = 0; i < 5; ++i) {\n        cr[i] = i; cc[i] = 0;\n        hold[i] = -1;\n        dispatched[i] = 0;\n        next_in[i] = 0;\n    }\n    cr[0] = 0; cc[0] = 0;   // large crane\n\n    struct Mission { int stage = -1, pr = 0, pc = 0, dr = 0, dc = 0; };\n    Mission lc;\n    vector<string> ops(5);\n    const int MAX_TURN = 10000;\n\n    auto find_buffer = [&]() -> pair<int,int> {\n        for (int c = 2; c <= 3; ++c)\n            for (int r = 0; r < 5; ++r)\n                if (grid[r][c] == -1) return {r, c};\n        return {-1, -1};\n    };\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        /* ---- step 1 : receiving ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (next_in[i] < 5 && grid[i][0] == -1) {\n                bool holding = false;\n                for (int k = 0; k < 5; ++k)\n                    if (cr[k] == i && cc[k] == 0 && hold[k] != -1)\n                        holding = true;\n                if (!holding) {\n                    grid[i][0] = A[i][next_in[i]++];\n                }\n            }\n        }\n\n        vector<char> act(5, '.');\n\n        /* ---- small cranes 1..4 (throttled) ---- */\n        for (int k = 1; k < 5; ++k) {\n            int i = k;\n            int r = cr[k], c = cc[k];\n            int h = hold[k];\n            if (h == -1) {\n                if (r == i && c == 0) {\n                    bool can_pick = (grid[i][0] != -1) &&\n                                    (grid[i][1] == -1) &&\n                                    !(cr[0] == i && cc[0] == 1);\n                    act[k] = can_pick ? 'P' : '.';\n                } else if (r == i && c == 1) {\n                    act[k] = 'L';\n                } else {\n                    if (c > 0) act[k] = 'L';\n                    else if (r > i) act[k] = 'U';\n                    else if (r < i) act[k] = 'D';\n                    else act[k] = '.';\n                }\n            } else {\n                if (r == i && c == 0) {\n                    bool can_move = (grid[i][1] == -1) &&\n                                    !(cr[0] == i && cc[0] == 1);\n                    act[k] = can_move ? 'R' : '.';\n                } else if (r == i && c == 1) {\n                    act[k] = 'Q';\n                } else {\n                    if (c < 1) act[k] = 'R';\n                    else if (c > 1) act[k] = 'L';\n                    else if (r > i) act[k] = 'U';\n                    else if (r < i) act[k] = 'D';\n                    else act[k] = '.';\n                }\n            }\n        }\n\n        /* ---- pre\u2011compute small\u2011crane destinations ---- */\n        int ncr[5], ncc[5];\n        for (int k = 1; k < 5; ++k) {\n            ncr[k] = cr[k]; ncc[k] = cc[k];\n            char a = act[k];\n            if (a == 'U') --ncr[k];\n            else if (a == 'D') ++ncr[k];\n            else if (a == 'L') --ncc[k];\n            else if (a == 'R') ++ncc[k];\n        }\n\n        auto can_move_lc = [&](int r, int c, int nr, int nc) -> bool {\n            if (nr < 0 || nr >= 5 || nc < 0 || nc >= 5) return false;\n            for (int k = 1; k < 5; ++k)\n                if (ncr[k] == nr && ncc[k] == nc) return false;\n            for (int k = 1; k < 5; ++k)\n                if (cr[k] == nr && cc[k] == nc && ncr[k] == r && ncc[k] == c) return false;\n            return true;\n        };\n\n        auto move_lc_to = [&](int tr, int tc) -> char {\n            int r = cr[0], c = cc[0];\n            if (r == tr && c == tc) return '.';\n            vector<pair<pair<int,int>, char>> cand;\n            auto add = [&](int nr, int nc, char d) {\n                if (0 <= nr && nr < 5 && 0 <= nc && nc < 5)\n                    cand.push_back({{nr, nc}, d});\n            };\n            if (tc >= 2) {\n                if (r != tr) add(r + (tr > r ? 1 : -1), c, (tr > r ? 'D' : 'U'));\n                if (c != tc) add(r, c + (tc > c ? 1 : -1), (tc > c ? 'R' : 'L'));\n            } else if (tc == 1) {\n                if (c > 2) add(r, c - 1, 'L');\n                else if (c == 2) {\n                    if (r != tr) add(r + (tr > r ? 1 : -1), c, (tr > r ? 'D' : 'U'));\n                    else add(r, 1, 'L');\n                } else {\n                    if (r != tr) add(r + (tr > r ? 1 : -1), c, (tr > r ? 'D' : 'U'));\n                    else add(r, c + 1, 'R');\n                }\n            } else { // tc == 0\n                if (c > 2) add(r, c - 1, 'L');\n                else if (c == 2) add(r, 1, 'L');\n                else if (c == 1) add(r, 0, 'L');\n                else {\n                    if (r != tr) add(r + (tr > r ? 1 : -1), c, (tr > r ? 'D' : 'U'));\n                }\n            }\n            for (auto &p : cand) {\n                int nr = p.first.first, nc = p.first.second;\n                char d = p.second;\n                if (can_move_lc(r, c, nr, nc)) return d;\n            }\n            return '.';\n        };\n\n        /* ---- large crane mission assignment ---- */\n        auto assign_lc = [&]() {\n            lc.stage = -1;\n\n            // 1. Deliver a needed container from anywhere\n            for (int row = 0; row < 5; ++row) {\n                int need = 5 * row + dispatched[row];\n                if (need >= 5 * (row + 1)) continue;\n                if (grid[0][0] == need) { lc = {0, 0, 0, row, 4}; return; }\n                for (int i = 1; i < 5; ++i)\n                    if (grid[i][1] == need) { lc = {0, i, 1, row, 4}; return; }\n                for (int i = 0; i < 5; ++i)\n                    for (int j = 2; j <= 3; ++j)\n                        if (grid[i][j] == need) { lc = {0, i, j, row, 4}; return; }\n            }\n\n            auto try_clear = [&](int pr, int pc) -> bool {\n                int cont = grid[pr][pc];\n                int row = cont / 5;\n                int need = 5 * row + dispatched[row];\n                if (cont == need) {\n                    lc = {0, pr, pc, row, 4};\n                    return true;\n                }\n                auto buf = find_buffer();\n                if (buf.first != -1) {\n                    lc = {0, pr, pc, buf.first, buf.second};\n                    return true;\n                }\n                // No buffer left: free one by delivering a needed container from buffers\n                for (int r = 0; r < 5; ++r) {\n                    int n = 5 * r + dispatched[r];\n                    if (n >= 5 * (r + 1)) continue;\n                    for (int i = 0; i < 5; ++i)\n                        for (int j = 2; j <= 3; ++j)\n                            if (grid[i][j] == n) {\n                                lc = {0, i, j, r, 4};\n                                return true;\n                            }\n                }\n                return false;\n            };\n\n            // 2. Stalled row i>=1: (i,0) and (i,1) both occupied, small crane waiting\n            for (int i = 1; i < 5; ++i) {\n                if (grid[i][1] == -1) continue;\n                if (grid[i][0] != -1 && cr[i] == i && cc[i] == 0 && hold[i] == -1) {\n                    if (try_clear(i, 1)) return;\n                }\n            }\n\n            // 3. Stalled row 0: (0,0) occupied while more containers are still queued\n            if (grid[0][0] != -1 && next_in[0] < 5) {\n                if (try_clear(0, 0)) return;\n            }\n\n            // 4. Proactive fetch only when buffer space is plenty\n            int free_buf = 0;\n            for (int i = 0; i < 5; ++i)\n                for (int j = 2; j <= 3; ++j)\n                    if (grid[i][j] == -1) ++free_buf;\n\n            if (free_buf >= 3) {\n                int best = 1e9;\n                int bp = -1, bpc = -1, bdr = -1, bdc = -1;\n                for (int i = 0; i < 5; ++i) {\n                    int pc = (i == 0 ? 0 : 1);\n                    if (grid[i][pc] == -1) continue;\n                    int d = abs(cr[0] - i) + abs(cc[0] - pc);\n                    if (d >= best) continue;\n                    int cont = grid[i][pc];\n                    int row = cont / 5;\n                    int need = 5 * row + dispatched[row];\n                    if (cont == need) {\n                        bp = i; bpc = pc; bdr = row; bdc = 4; best = d;\n                    } else {\n                        auto buf = find_buffer();\n                        if (buf.first != -1) {\n                            bp = i; bpc = pc; bdr = buf.first; bdc = buf.second; best = d;\n                        }\n                    }\n                }\n                if (bp != -1) {\n                    lc = {0, bp, bpc, bdr, bdc};\n                    return;\n                }\n            }\n        };\n\n        /* ---- large crane action ---- */\n        if (lc.stage == -1) assign_lc();\n\n        if (lc.stage != -1) {\n            if (lc.stage == 0) {\n                if (cr[0] == lc.pr && cc[0] == lc.pc) {\n                    if (grid[cr[0]][cc[0]] == -1) {\n                        lc.stage = -1;          // container vanished \u2013 abort\n                        act[0] = '.';\n                    } else {\n                        int cont = grid[lc.pr][lc.pc];\n                        int row = cont / 5;\n                        int need = 5 * row + dispatched[row];\n                        if (cont == need) {\n                            lc.dr = row; lc.dc = 4;\n                        } else {\n                            auto buf = find_buffer();\n                            lc.dr = buf.first; lc.dc = buf.second;\n                        }\n                        lc.stage = 1;\n                        act[0] = 'P';\n                    }\n                } else {\n                    act[0] = move_lc_to(lc.pr, lc.pc);\n                }\n            } else if (lc.stage == 1) {\n                if (hold[0] != -1) {\n                    int row = hold[0] / 5;\n                    int need = 5 * row + dispatched[row];\n                    if (hold[0] == need) {\n                        lc.dr = row; lc.dc = 4;\n                    }\n                }\n                if (cr[0] == lc.dr && cc[0] == lc.dc) {\n                    if (grid[cr[0]][cc[0]] != -1) {\n                        act[0] = '.';           // wait for dispatch gate to empty\n                    } else {\n                        lc.stage = -1;\n                        act[0] = 'Q';\n                    }\n                } else {\n                    act[0] = move_lc_to(lc.dr, lc.dc);\n                }\n            }\n        } else {\n            act[0] = '.';\n        }\n\n        /* ---- validate and apply ---- */\n        int nnr[5], nnc[5], nhold[5];\n        int ngrid[5][5];\n        memcpy(ngrid, grid, sizeof(grid));\n        for (int k = 0; k < 5; ++k) {\n            nnr[k] = cr[k]; nnc[k] = cc[k]; nhold[k] = hold[k];\n            char a = act[k];\n            if (a == 'U') --nnr[k];\n            else if (a == 'D') ++nnr[k];\n            else if (a == 'L') --nnc[k];\n            else if (a == 'R') ++nnc[k];\n        }\n\n        bool ok = true;\n        for (int k = 0; k < 5 && ok; ++k)\n            if (nnr[k] < 0 || nnr[k] >= 5 || nnc[k] < 0 || nnc[k] >= 5)\n                ok = false;\n\n        for (int k = 0; k < 5 && ok; ++k)\n            for (int l = k + 1; l < 5; ++l) {\n                if (nnr[k] == nnr[l] && nnc[k] == nnc[l]) ok = false;\n                if (cr[k] == nnr[l] && cc[k] == nnc[l] && cr[l] == nnr[k] && cc[l] == nnc[k]) ok = false;\n            }\n\n        for (int k = 0; k < 5 && ok; ++k) {\n            char a = act[k];\n            if (a == 'P') {\n                if (hold[k] != -1 || grid[cr[k]][cc[k]] == -1) ok = false;\n                nhold[k] = grid[cr[k]][cc[k]];\n                ngrid[cr[k]][cc[k]] = -1;\n            } else if (a == 'Q') {\n                if (hold[k] == -1 || grid[cr[k]][cc[k]] != -1) ok = false;\n                ngrid[cr[k]][cc[k]] = hold[k];\n                nhold[k] = -1;\n            } else if (a == 'U' || a == 'D' || a == 'L' || a == 'R') {\n                if (k > 0 && hold[k] != -1 && grid[nnr[k]][nnc[k]] != -1) ok = false;\n            }\n        }\n\n        if (!ok) {\n            for (int k = 0; k < 5; ++k) {\n                nnr[k] = cr[k]; nnc[k] = cc[k]; nhold[k] = hold[k];\n                act[k] = '.';\n            }\n            memcpy(ngrid, grid, sizeof(grid));\n        }\n\n        for (int k = 0; k < 5; ++k) {\n            cr[k] = nnr[k]; cc[k] = nnc[k]; hold[k] = nhold[k];\n        }\n        memcpy(grid, ngrid, sizeof(grid));\n\n        /* ---- step 3 : dispatch ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (grid[i][4] != -1) {\n                ++dispatched[i];\n                grid[i][4] = -1;\n            }\n        }\n\n        for (int k = 0; k < 5; ++k) ops[k].push_back(act[k]);\n\n        bool done = true;\n        for (int i = 0; i < 5; ++i)\n            if (dispatched[i] < 5) done = false;\n        if (done) break;\n    }\n\n    size_t mx = 0;\n    for (auto &s : ops) mx = max(mx, s.size());\n    for (auto &s : ops) {\n        while (s.size() < mx) s.push_back('.');\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Result {\n    long long cost = 0;\n    vector<string> ops;\n    bool valid = false;\n};\n\n/* -------------------------------------------------------------\n   Simulate a given visitation order (move along shortest paths,\n   process every cell passed opportunistically).\n   ------------------------------------------------------------- */\nResult solve_given_order(const vector<vector<int>>& h,\n                         const vector<pair<int,int>>& order)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(100000);\n    int r = 0, c = 0;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n            }\n        }\n    };\n\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n\n    process(r, c);                         // (0,0)\n\n    for (auto [tr, tc] : order) {\n        if (r == tr && c == tc) continue; // already here (processed)\n        move_to(tr, tc);\n    }\n\n    /* deliver anything that is still loaded */\n    while (load > 0) {\n        int tr = -1, tc = -1, best = 1e9;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] < 0) {\n                    int d = abs(r - i) + abs(c - j);\n                    if (d < best) { best = d; tr = i; tc = j; }\n                }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* -------------------------------------------------------------\n   Deterministic nearest\u2011neighbour greedy (original)\n   ------------------------------------------------------------- */\nResult solve_greedy(const vector<vector<int>>& h) {\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(100000);\n    int r = 0, c = 0;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n            }\n        }\n    };\n\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false, has_neg = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j) {\n                if (need[i][j] > 0) has_pos = true;\n                if (need[i][j] < 0) has_neg = true;\n            }\n        if (!has_pos && load == 0) break;\n\n        int tr = -1, tc = -1, best = 1e9;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* -------------------------------------------------------------\n   Path generators\n   ------------------------------------------------------------- */\nvector<pair<int,int>> spiral_snake(int N, bool row_first) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    int r = 0, c = 0;\n    int dr = row_first ? 0 : 1;\n    int dc = row_first ? 1 : 0;\n    for (int step = 0; step < N * N; ++step) {\n        res.emplace_back(r, c);\n        vis[r][c] = true;\n        int nr = r + dr;\n        int nc = c + dc;\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N || vis[nr][nc]) {\n            int ndr, ndc;\n            if (row_first) { ndr = dc; ndc = -dr; }\n            else           { ndr = -dc; ndc = dr; }\n            dr = ndr; dc = ndc;\n            nr = r + dr; nc = c + dc;\n        }\n        r = nr; c = nc;\n    }\n    return res;\n}\n\nvector<pair<int,int>> diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int s = 0; s <= 2 * (N - 1); ++s) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = s - i;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        bool reverse = (s % 2 == (rev ? 0 : 1));\n        if (reverse) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nvector<pair<int,int>> anti_diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int d = -(N - 1); d <= N - 1; ++d) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = i - d;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        int parity = d & 1; // 0 = even, 1 = odd\n        bool reverse = (parity == (rev ? 1 : 0));\n        if (reverse) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nvector<pair<int,int>> block_row_snake(int N, int block_h, bool block_rev) {\n    vector<pair<int,int>> res;\n    int num_blocks = N / block_h;\n    for (int b = 0; b < num_blocks; ++b) {\n        int bi = block_rev ? (num_blocks - 1 - b) : b;\n        int base_r = bi * block_h;\n        bool snake_rev = (b % 2 == 1);\n        for (int col = 0; col < N; ++col) {\n            int c = snake_rev ? (N - 1 - col) : col;\n            if (col % 2 == 0) {\n                for (int dr = 0; dr < block_h; ++dr)\n                    res.emplace_back(base_r + dr, c);\n            } else {\n                for (int dr = block_h - 1; dr >= 0; --dr)\n                    res.emplace_back(base_r + dr, c);\n            }\n        }\n    }\n    return res;\n}\n\n/* -------------------------------------------------------------\n   Randomised greedy \u2013 evaluation only (no strings stored)\n   ------------------------------------------------------------- */\nlong long eval_random_greedy(const vector<vector<int>>& h,\n                             const vector<vector<int>>& nearest_src,\n                             const vector<vector<int>>& nearest_snk,\n                             uint64_t seed,\n                             double temp_empty,\n                             double temp_loaded,\n                             double pot_w)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    int r = 0, c = 0;\n    int steps = 0;\n    mt19937_64 rng(seed);\n\n    int rem_pos = 0, rem_neg = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (h[i][j] > 0) ++rem_pos;\n            else if (h[i][j] < 0) ++rem_neg;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n            --rem_pos;\n            ++steps;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n                if (need[cr][cc] == 0) --rem_neg;\n                ++steps;\n            }\n        }\n    };\n\n    auto move_step = [&](int dr, int dc) {\n        r += dr; c += dc;\n        cost += 100 + load;\n        ++steps;\n        process(r, c);\n    };\n\n    auto choose_target = [&](const vector<pair<int,int>>& cand,\n                             const vector<double>& w) -> pair<int,int> {\n        double sum = 0.0;\n        for (double x : w) sum += x;\n        if (sum <= 0) return {-1, -1};\n        double x = uniform_real_distribution<double>(0.0, sum)(rng);\n        for (size_t i = 0; i < cand.size(); ++i) {\n            x -= w[i];\n            if (x <= 0) return cand[i];\n        }\n        return cand.back();\n    };\n\n    process(r, c);\n    if (steps > 100000) return LLONG_MAX;\n\n    while (true) {\n        if (rem_pos == 0 && load == 0) break;\n        if (steps > 100000) return LLONG_MAX;\n\n        vector<pair<int,int>> cand;\n        vector<double> w;\n        if (load == 0) {\n            if (rem_pos == 0) return LLONG_MAX;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = need[i][j] * exp(-d / temp_empty);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_snk[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        } else {\n            if (rem_neg == 0) return LLONG_MAX;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = -need[i][j] * exp(-d / temp_loaded);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_src[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        }\n        if (cand.empty()) return LLONG_MAX;\n        auto [tr, tc] = choose_target(cand, w);\n        if (tr < 0) return LLONG_MAX;\n\n        while (r != tr || c != tc) {\n            if (steps > 100000) return LLONG_MAX;\n            vector<pair<int,int>> dirs;\n            if (r < tr) dirs.emplace_back(1, 0);\n            else if (r > tr) dirs.emplace_back(-1, 0);\n            if (c < tc) dirs.emplace_back(0, 1);\n            else if (c > tc) dirs.emplace_back(0, -1);\n            int idx = uniform_int_distribution<int>(0, (int)dirs.size() - 1)(rng);\n            auto [dr, dc] = dirs[idx];\n            move_step(dr, dc);\n        }\n    }\n\n    if (load != 0) return LLONG_MAX;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (need[i][j] != 0) return LLONG_MAX;\n    if (steps > 100000) return LLONG_MAX;\n    return cost;\n}\n\n/* -------------------------------------------------------------\n   Randomised greedy \u2013 build full operation list\n   ------------------------------------------------------------- */\nResult build_random_greedy(const vector<vector<int>>& h,\n                           const vector<vector<int>>& nearest_src,\n                           const vector<vector<int>>& nearest_snk,\n                           uint64_t seed,\n                           double temp_empty,\n                           double temp_loaded,\n                           double pot_w)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(100000);\n    int r = 0, c = 0;\n    int steps = 0;\n    mt19937_64 rng(seed);\n\n    int rem_pos = 0, rem_neg = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (h[i][j] > 0) ++rem_pos;\n            else if (h[i][j] < 0) ++rem_neg;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n            --rem_pos;\n            ++steps;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n                if (need[cr][cc] == 0) --rem_neg;\n                ++steps;\n            }\n        }\n    };\n\n    auto move_step = [&](int dr, int dc) {\n        r += dr; c += dc;\n        ops.emplace_back(1, (dr == 1 ? 'D' : (dr == -1 ? 'U' : (dc == 1 ? 'R' : 'L'))));\n        cost += 100 + load;\n        ++steps;\n        process(r, c);\n    };\n\n    auto choose_target = [&](const vector<pair<int,int>>& cand,\n                             const vector<double>& w) -> pair<int,int> {\n        double sum = 0.0;\n        for (double x : w) sum += x;\n        if (sum <= 0) return {-1, -1};\n        double x = uniform_real_distribution<double>(0.0, sum)(rng);\n        for (size_t i = 0; i < cand.size(); ++i) {\n            x -= w[i];\n            if (x <= 0) return cand[i];\n        }\n        return cand.back();\n    };\n\n    process(r, c);\n    if (steps > 100000) return {0, {}, false};\n\n    while (true) {\n        if (rem_pos == 0 && load == 0) break;\n        if (steps > 100000) return {0, {}, false};\n\n        vector<pair<int,int>> cand;\n        vector<double> w;\n        if (load == 0) {\n            if (rem_pos == 0) return {0, {}, false};\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = need[i][j] * exp(-d / temp_empty);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_snk[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        } else {\n            if (rem_neg == 0) return {0, {}, false};\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = -need[i][j] * exp(-d / temp_loaded);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_src[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        }\n        if (cand.empty()) return {0, {}, false};\n        auto [tr, tc] = choose_target(cand, w);\n        if (tr < 0) return {0, {}, false};\n\n        while (r != tr || c != tc) {\n            if (steps > 100000) return {0, {}, false};\n            vector<pair<int,int>> dirs;\n            if (r < tr) dirs.emplace_back(1, 0);\n            else if (r > tr) dirs.emplace_back(-1, 0);\n            if (c < tc) dirs.emplace_back(0, 1);\n            else if (c > tc) dirs.emplace_back(0, -1);\n            int idx = uniform_int_distribution<int>(0, (int)dirs.size() - 1)(rng);\n            auto [dr, dc] = dirs[idx];\n            move_step(dr, dc);\n        }\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* ------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    /* pre\u2011compute static Manhattan potentials */\n    vector<vector<int>> nearest_src(N, vector<int>(N, INT_MAX));\n    vector<vector<int>> nearest_snk(N, vector<int>(N, INT_MAX));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] > 0) {\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < N; ++y)\n                        nearest_src[x][y] = min(nearest_src[x][y], abs(x - i) + abs(y - j));\n            } else if (h[i][j] < 0) {\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < N; ++y)\n                        nearest_snk[x][y] = min(nearest_snk[x][y], abs(x - i) + abs(y - j));\n            }\n        }\n    }\n\n    vector<Result> candidates;\n\n    auto add_order = [&](const vector<pair<int,int>>& order) {\n        candidates.push_back(solve_given_order(h, order));\n    };\n\n    /* pure row / column snakes */\n    vector<pair<int,int>> ord;\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else            for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    ord.clear();\n    for (int i = N - 1; i >= 0; --i) {\n        if ((N - 1 - i) % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else                      for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    ord.clear();\n    for (int j = 0; j < N; ++j) {\n        if (j % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else            for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    ord.clear();\n    for (int j = N - 1; j >= 0; --j) {\n        if ((N - 1 - j) % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else                      for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    /* spirals */\n    add_order(spiral_snake(N, true));\n    add_order(spiral_snake(N, false));\n\n    /* diagonal snakes */\n    add_order(diagonal_snake(N, false));\n    add_order(diagonal_snake(N, true));\n\n    /* anti\u2011diagonal snakes */\n    add_order(anti_diagonal_snake(N, false));\n    add_order(anti_diagonal_snake(N, true));\n\n    /* block row snakes */\n    for (int bh : {2, 4, 5}) {\n        add_order(block_row_snake(N, bh, false));\n        add_order(block_row_snake(N, bh, true));\n    }\n\n    /* deterministic greedy */\n    candidates.push_back(solve_greedy(h));\n\n    /* -------- randomised greedy : evaluate many seeds -------- */\n    const vector<tuple<double,double,double>> param_sets = {\n        {1.0,  1.0,  0.0},\n        {3.0,  3.0,  0.0},\n        {5.0,  5.0,  0.0},\n        {10.0, 10.0, 0.0},\n        {20.0, 20.0, 0.0},\n        {1.0,  1.0,  0.05},\n        {3.0,  3.0,  0.05},\n        {5.0,  5.0,  0.1},\n        {10.0, 5.0,  0.0},\n        {5.0,  10.0, 0.0},\n    };\n    const int REPS = 200;\n\n    long long best_rand_cost = LLONG_MAX;\n    uint64_t best_seed = 0;\n    int best_pidx = 0;\n\n    for (int pidx = 0; pidx < (int)param_sets.size(); ++pidx) {\n        auto [te, tl, pw] = param_sets[pidx];\n        for (int r = 0; r < REPS; ++r) {\n            uint64_t seed = (uint64_t)pidx * 1000000ULL + (uint64_t)r;\n            long long c = eval_random_greedy(h, nearest_src, nearest_snk,\n                                             seed, te, tl, pw);\n            if (c < best_rand_cost) {\n                best_rand_cost = c;\n                best_seed = seed;\n                best_pidx = pidx;\n            }\n        }\n    }\n\n    if (best_rand_cost != LLONG_MAX) {\n        auto [te, tl, pw] = param_sets[best_pidx];\n        candidates.push_back(build_random_greedy(h, nearest_src, nearest_snk,\n                                                best_seed, te, tl, pw));\n    }\n\n    /* -------- choose the best valid candidate -------- */\n    Result best; best.valid = false; best.cost = LLONG_MAX;\n    for (auto &res : candidates) {\n        if (res.valid && res.cost < best.cost) best = res;\n    }\n\n    if (!best.valid) best = solve_greedy(h); // ultimate fallback\n\n    for (auto &s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ---------- fast scanner ----------\nstatic inline int readInt() {\n    int c = getchar_unlocked();\n    if (c == EOF) return -1;\n    while (c != EOF && (c < '0' || c > '9')) {\n        c = getchar_unlocked();\n        if (c == EOF) return -1;\n    }\n    int x = 0;\n    while (c >= '0' && c <= '9') {\n        x = x * 10 + (c - '0');\n        c = getchar_unlocked();\n    }\n    return x;\n}\n\n// ---------- constants ----------\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int SEED_CNT = 2 * N * (N - 1); // 60\nconstexpr int PLANT = N * N;               // 36\nconstexpr int EDGE_CNT = 2 * N * (N - 1); // 60\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // pre\u2011compute grid topology\n    int nbr[PLANT][4];\n    int nbr_cnt[PLANT];\n    int deg[PLANT];\n    bool is_corner[PLANT];\n    int edge_u[EDGE_CNT];\n    int edge_v[EDGE_CNT];\n    int ecnt = 0;\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            int k = 0;\n            if (r > 0)     nbr[id][k++] = (r - 1) * N + c;\n            if (r < N - 1) nbr[id][k++] = (r + 1) * N + c;\n            if (c > 0)     nbr[id][k++] = r * N + (c - 1);\n            if (c < N - 1) nbr[id][k++] = r * N + (c + 1);\n            nbr_cnt[id] = k;\n            deg[id] = k;\n            is_corner[id] = (k == 2);\n        }\n    }\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N - 1; ++c) {\n            int u = r * N + c;\n            int v = r * N + (c + 1);\n            edge_u[ecnt] = u; edge_v[ecnt] = v; ++ecnt;\n        }\n    }\n    for (int r = 0; r < N - 1; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int u = r * N + c;\n            int v = (r + 1) * N + c;\n            edge_u[ecnt] = u; edge_v[ecnt] = v; ++ecnt;\n        }\n    }\n\n    // cells sorted by degree (descending)\n    int cells_by_deg[PLANT];\n    iota(cells_by_deg, cells_by_deg + PLANT, 0);\n    sort(cells_by_deg, cells_by_deg + PLANT,\n         [&](int a, int b){ return deg[a] > deg[b]; });\n\n    int X[SEED_CNT][M];\n\n    while (true) {\n        int N_in = readInt();\n        if (N_in == -1) break;\n        int M_in = readInt();\n        int T = readInt();\n\n        for (int i = 0; i < SEED_CNT; ++i)\n            for (int l = 0; l < M_in; ++l)\n                X[i][l] = readInt();\n\n        for (int turn = 0; turn < T; ++turn) {\n            // ---- 1. statistics ----\n            int V[SEED_CNT];\n            int cur_max[M];\n            fill(begin(cur_max), end(cur_max), 0);\n            for (int i = 0; i < SEED_CNT; ++i) {\n                int s = 0;\n                for (int l = 0; l < M_in; ++l) {\n                    s += X[i][l];\n                    if (X[i][l] > cur_max[l]) cur_max[l] = X[i][l];\n                }\n                V[i] = s;\n            }\n\n            int ach_mask[SEED_CNT];\n            for (int i = 0; i < SEED_CNT; ++i) {\n                int m = 0;\n                for (int l = 0; l < M_in; ++l)\n                    if (X[i][l] == cur_max[l]) m |= (1 << l);\n                ach_mask[i] = m;\n            }\n\n            // ---- 2. mandatory cover set (hit every coordinate max) ----\n            bool in_sel[SEED_CNT] = {false};\n            int selected[PLANT];\n            int sel_cnt = 0;\n\n            int need_cover = (1 << M_in) - 1;\n            int cover_mask = 0;\n            while (cover_mask != need_cover) {\n                int best_i = -1, best_new = -1, best_V = -1;\n                for (int i = 0; i < SEED_CNT; ++i) if (!in_sel[i]) {\n                    int newb = __builtin_popcount(ach_mask[i] & ~cover_mask);\n                    if (newb > best_new || (newb == best_new && V[i] > best_V)) {\n                        best_new = newb; best_V = V[i]; best_i = i;\n                    }\n                }\n                in_sel[best_i] = true;\n                selected[sel_cnt++] = best_i;\n                cover_mask |= ach_mask[best_i];\n            }\n            int cover_size = sel_cnt;\n\n            // ---- 3. fill remaining slots, strongly preferring max\u2011achievers ----\n            int rem[SEED_CNT];\n            int rem_cnt = 0;\n            for (int i = 0; i < SEED_CNT; ++i)\n                if (!in_sel[i]) rem[rem_cnt++] = i;\n\n            sort(rem, rem + rem_cnt,\n                 [&](int a, int b){\n                     int pa = V[a] + 10000 * __builtin_popcount(ach_mask[a]);\n                     int pb = V[b] + 10000 * __builtin_popcount(ach_mask[b]);\n                     if (pa != pb) return pa > pb;\n                     return V[a] > V[b];\n                 });\n\n            int need = PLANT - sel_cnt;\n            for (int i = 0; i < need; ++i) selected[sel_cnt++] = rem[i];\n\n            bool is_cover_idx[PLANT];\n            for (int i = 0; i < PLANT; ++i) is_cover_idx[i] = (i < cover_size);\n\n            // ---- 4. potential matrix ----\n            static int pot[PLANT][PLANT];\n            for (int i = 0; i < PLANT; ++i) {\n                for (int j = i + 1; j < PLANT; ++j) {\n                    int a = selected[i];\n                    int b = selected[j];\n                    int s = 0;\n                    for (int l = 0; l < M_in; ++l)\n                        s += max(X[a][l], X[b][l]);\n                    pot[i][j] = pot[j][i] = s;\n                }\n            }\n\n            // ---- 5. initial placement ----\n            int pos2idx[PLANT];\n\n            // cover seeds -> highest degree cells (all interior, deg 4)\n            int ord_cover[PLANT];\n            for (int i = 0; i < cover_size; ++i) ord_cover[i] = i;\n            sort(ord_cover, ord_cover + cover_size,\n                 [&](int a, int b){ return V[selected[a]] > V[selected[b]]; });\n\n            int other_size = PLANT - cover_size;\n            int ord_other[PLANT];\n            for (int i = 0; i < other_size; ++i) ord_other[i] = cover_size + i;\n            sort(ord_other, ord_other + other_size,\n                 [&](int a, int b){ return V[selected[a]] > V[selected[b]]; });\n\n            for (int i = 0; i < cover_size; ++i)\n                pos2idx[cells_by_deg[i]] = ord_cover[i];\n            for (int i = 0; i < other_size; ++i)\n                pos2idx[cells_by_deg[cover_size + i]] = ord_other[i];\n\n            // ---- 6. local search (hill climbing on sum of edge potentials) ----\n            for (int pass = 0; pass < 200; ++pass) {\n                int best_delta = 0;\n                int best_u = -1, best_v = -1;\n                for (int u = 0; u < PLANT; ++u) {\n                    int iu = pos2idx[u];\n                    for (int v = u + 1; v < PLANT; ++v) {\n                        int iv = pos2idx[v];\n                        // forbid moving a cover seed into a corner\n                        if (is_cover_idx[iu] && is_corner[v]) continue;\n                        if (is_cover_idx[iv] && is_corner[u]) continue;\n\n                        int delta = 0;\n                        for (int k = 0; k < nbr_cnt[u]; ++k) {\n                            int w = nbr[u][k];\n                            if (w == v) continue;\n                            int iw = pos2idx[w];\n                            delta += pot[iv][iw] - pot[iu][iw];\n                        }\n                        for (int k = 0; k < nbr_cnt[v]; ++k) {\n                            int w = nbr[v][k];\n                            if (w == u) continue;\n                            int iw = pos2idx[w];\n                            delta += pot[iu][iw] - pot[iv][iw];\n                        }\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_u = u;\n                            best_v = v;\n                        }\n                    }\n                }\n                if (best_delta > 0) {\n                    swap(pos2idx[best_u], pos2idx[best_v]);\n                } else {\n                    break;\n                }\n            }\n\n            // ---- 7. output ----\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (c) putchar_unlocked(' ');\n                    int cell = r * N + c;\n                    int idx = pos2idx[cell];\n                    int id = selected[idx];\n                    // print id (0..59)\n                    if (id == 0) {\n                        putchar_unlocked('0');\n                    } else {\n                        char buf[8];\n                        int n = 0;\n                        while (id > 0) {\n                            buf[n++] = char('0' + (id % 10));\n                            id /= 10;\n                        }\n                        while (n--) putchar_unlocked(buf[n]);\n                    }\n                }\n                putchar_unlocked('\\n');\n            }\n            fflush(stdout);\n\n            // ---- 8. read next generation ----\n            for (int i = 0; i < SEED_CNT; ++i)\n                for (int l = 0; l < M_in; ++l)\n                    X[i][l] = readInt();\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<vector<char>> has_source, need_target;\nvector<int> len;                     // edge length of each vertex\nvector<int> cur_dir;                 // absolute direction of edge (parent -> i)\nvector<char> is_holding;\nint cur_r, cur_c;\nvector<string> ans;\nint holding_cnt = 0;\nint rem_source_cnt = 0;\nint rem_target_cnt = 0;\n\n// 0:right, 1:down, 2:left, 3:up   (dr,dc correspond to (row,col))\nconst int dr[4] = {0, 1, 0, -1};\nconst int dc[4] = {1, 0, -1, 0};\n\ninline int rot_steps(int a, int b) {\n    int d = abs(a - b);\n    return min(d, 4 - d);\n}\ninline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstruct Batch {\n    int size = 0;\n    int r = -1, c = -1;\n    int max_rot = 0;\n    vector<int> dir;\n    vector<pair<int,int>> cell;\n    Batch(int v = 0) {\n        dir.assign(v, -1);\n        cell.assign(v, {-1, -1});\n    }\n};\n\n/*------------------------------------------------------------*/\n/*  find best batch for a set of active fingertips            */\n/*------------------------------------------------------------*/\nBatch find_batch(const vector<int>& active, bool is_pickup) {\n    Batch best(V);\n    int best_size = 0;\n    int best_turns = INT_MAX;\n    int best_maxrot = INT_MAX;\n\n    int dirs[15];\n    pair<int,int> cells[15];\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            for (int i = 1; i < V; ++i) {\n                dirs[i] = -1;\n                cells[i] = {-1, -1};\n            }\n            int sz = 0;\n            int max_rot = 0;\n            for (int idx = 0; idx < (int)active.size(); ++idx) {\n                int i = active[idx];\n                int best_cost = 100;\n                int best_d = -1;\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d] * len[i];\n                    int nc = c + dc[d] * len[i];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (is_pickup ? has_source[nr][nc] : need_target[nr][nc]) {\n                        int cost = rot_steps(cur_dir[i], d);\n                        if (cost < best_cost) {\n                            best_cost = cost;\n                            best_d = d;\n                        }\n                    }\n                }\n                if (best_d != -1) {\n                    ++sz;\n                    max_rot = max(max_rot, best_cost);\n                    dirs[i] = best_d;\n                    cells[i] = {r + dr[best_d] * len[i], c + dc[best_d] * len[i]};\n                }\n            }\n            if (sz == 0) continue;\n            int dist = manhattan(cur_r, cur_c, r, c);\n            int turns = max(dist, max_rot);\n            if (sz > best_size ||\n                (sz == best_size && turns < best_turns) ||\n                (sz == best_size && turns == best_turns && max_rot < best_maxrot)) {\n                best_size = sz;\n                best_turns = turns;\n                best_maxrot = max_rot;\n                best.size = sz;\n                best.r = r;\n                best.c = c;\n                best.max_rot = max_rot;\n                for (int i = 1; i < V; ++i) {\n                    best.dir[i] = dirs[i];\n                    best.cell[i] = cells[i];\n                }\n            }\n        }\n    }\n    return best;\n}\n\n/*------------------------------------------------------------*/\n/*  physically execute one batch                              */\n/*------------------------------------------------------------*/\nvoid execute_batch(const Batch& batch, bool is_pickup) {\n    if (batch.size <= 0) return;\n\n    vector<int> matched;\n    for (int i = 1; i < V; ++i)\n        if (batch.dir[i] != -1) matched.push_back(i);\n\n    int max_rot = 0;\n    for (int i : matched)\n        max_rot = max(max_rot, rot_steps(cur_dir[i], batch.dir[i]));\n\n    int dist = manhattan(cur_r, cur_c, batch.r, batch.c);\n    int travel = max(dist, max_rot);\n    if (travel == 0) travel = 1; // need at least one turn to P\n\n    for (int step = 0; step < travel; ++step) {\n        char move = '.';\n        if (cur_r < batch.r)       { move = 'D'; ++cur_r; }\n        else if (cur_r > batch.r)  { move = 'U'; --cur_r; }\n        else if (cur_c < batch.c)  { move = 'R'; ++cur_c; }\n        else if (cur_c > batch.c)  { move = 'L'; --cur_c; }\n\n        string S(2 * V, '.');\n        S[0] = move;\n        for (int i : matched) {\n            if (cur_dir[i] == batch.dir[i]) continue;\n            int diff = (batch.dir[i] - cur_dir[i] + 4) % 4;\n            if (diff == 1) {\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            } else if (diff == 3) {\n                S[i] = 'L';\n                cur_dir[i] = (cur_dir[i] + 3) & 3;\n            } else { // diff == 2\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            }\n        }\n        if (step == travel - 1) {\n            for (int i : matched) {\n                S[V + i] = 'P';\n                auto [tr, tc] = batch.cell[i];\n                if (is_pickup) {\n                    has_source[tr][tc] = 0;\n                    is_holding[i] = 1;\n                    ++holding_cnt;\n                    --rem_source_cnt;\n                } else {\n                    need_target[tr][tc] = 0;\n                    is_holding[i] = 0;\n                    --holding_cnt;\n                    --rem_target_cnt;\n                }\n            }\n        }\n        ans.push_back(S);\n    }\n}\n\n/*------------------------------------------------------------*/\n/*  main                                                       */\n/*------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n    for (int i = 0; i < N; ++i) cin >> t[i];\n\n    has_source.assign(N, vector<char>(N, 0));\n    need_target.assign(N, vector<char>(N, 0));\n    long long sumr = 0, sumc = 0, work = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s[i][j] == '1' && t[i][j] == '1') {\n                // already satisfied\n            } else if (s[i][j] == '1') {\n                has_source[i][j] = 1;\n                ++rem_source_cnt;\n                sumr += i; sumc += j; ++work;\n            } else if (t[i][j] == '1') {\n                need_target[i][j] = 1;\n                ++rem_target_cnt;\n                sumr += i; sumc += j; ++work;\n            }\n        }\n    }\n\n    /*--- design the arm (star with distinct lengths) ---*/\n    cout << V << '\\n';\n    len.assign(V, 0);\n    for (int u = 1; u < V; ++u) {\n        int L = u;\n        if (L > N - 1) L = N - 1;\n        len[u] = L;\n        cout << 0 << ' ' << L << '\\n';\n    }\n    if (work > 0) {\n        cur_r = (int)(sumr / work);\n        cur_c = (int)(sumc / work);\n    } else {\n        cur_r = N / 2;\n        cur_c = N / 2;\n    }\n    cout << cur_r << ' ' << cur_c << '\\n';\n\n    cur_dir.assign(V, 0);\n    is_holding.assign(V, 0);\n\n    /*--- main greedy loop ---*/\n    while (rem_source_cnt > 0 || holding_cnt > 0) {\n        vector<int> free_active, hold_active;\n        for (int i = 1; i < V; ++i) {\n            if (is_holding[i]) hold_active.push_back(i);\n            else               free_active.push_back(i);\n        }\n\n        Batch pick, del;\n        if (!free_active.empty()) pick = find_batch(free_active, true);\n        if (!hold_active.empty()) del  = find_batch(hold_active, false);\n\n        int pick_cost = (pick.size == 0) ? INT_MAX : max(manhattan(cur_r, cur_c, pick.r, pick.c), pick.max_rot);\n        int del_cost  = (del.size  == 0) ? INT_MAX : max(manhattan(cur_r, cur_c, del.r,  del.c),  del.max_rot);\n\n        if (pick.size == 0 && del.size == 0) {\n            // emergency: should not happen, but move towards nearest work cell\n            int tr = -1, tc = -1, bestd = 1e9;\n            if (rem_source_cnt > 0) {\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        if (has_source[i][j]) {\n                            int d = manhattan(cur_r, cur_c, i, j);\n                            if (d < bestd) { bestd = d; tr = i; tc = j; }\n                        }\n            } else {\n                for (int i = 0; i < N; ++i)\n                    for (int j = 0; j < N; ++j)\n                        if (need_target[i][j]) {\n                            int d = manhattan(cur_r, cur_c, i, j);\n                            if (d < bestd) { bestd = d; tr = i; tc = j; }\n                        }\n            }\n            if (tr != -1) {\n                char move = '.';\n                if (cur_r < tr) { move = 'D'; ++cur_r; }\n                else if (cur_r > tr) { move = 'U'; --cur_r; }\n                else if (cur_c < tc) { move = 'R'; ++cur_c; }\n                else if (cur_c > tc) { move = 'L'; --cur_c; }\n                string S(2 * V, '.');\n                S[0] = move;\n                ans.push_back(S);\n            }\n        } else if (pick.size > del.size || (pick.size == del.size && pick_cost <= del_cost)) {\n            execute_batch(pick, true);\n        } else {\n            execute_batch(del, false);\n        }\n    }\n\n    for (const string& s : ans) cout << s << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    int w;          // +1 = mackerel, -1 = sardine\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\n/*------------------------------------------------------------*/\n/*  exact best rectangle on a small subset (M <= 2000)       */\n/*------------------------------------------------------------*/\nRect solve_exact(const vector<Point> &sub, int &best_score) {\n    best_score = 0;\n    if (sub.empty()) return {0, 0, 0, 0};\n\n    vector<int> xs, ys;\n    xs.reserve(sub.size());\n    ys.reserve(sub.size());\n    for (const auto &p : sub) {\n        xs.push_back(p.x);\n        ys.push_back(p.y);\n    }\n    sort(xs.begin(), xs.end());\n    xs.erase(unique(xs.begin(), xs.end()), xs.end());\n    sort(ys.begin(), ys.end());\n    ys.erase(unique(ys.begin(), ys.end()), ys.end());\n\n    const int X = (int)xs.size();\n    const int Y = (int)ys.size();\n\n    vector<vector<pair<int,int>>> rows(Y);\n    for (const auto &p : sub) {\n        int ix = lower_bound(xs.begin(), xs.end(), p.x) - xs.begin();\n        int iy = lower_bound(ys.begin(), ys.end(), p.y) - ys.begin();\n        rows[iy].push_back({ix, p.w});\n    }\n\n    int sz = 1;\n    while (sz < X) sz <<= 1;\n\n    struct Node { int sum, pref, suff, best; };\n    vector<Node> seg(2 * sz);\n\n    int best_val = 0;\n    int best_i = -1, best_j = -1;\n\n    for (int i = 0; i < Y; ++i) {\n        memset(seg.data(), 0, sizeof(Node) * 2 * sz);\n        for (int j = i; j < Y; ++j) {\n            for (const auto &pr : rows[j]) {\n                int pos = pr.first + sz;\n                int v   = pr.second;\n                seg[pos].sum  += v;\n                seg[pos].pref += v;\n                seg[pos].suff += v;\n                seg[pos].best += v;\n                for (pos >>= 1; pos; pos >>= 1) {\n                    const Node &L = seg[pos << 1];\n                    const Node &R = seg[pos << 1 | 1];\n                    seg[pos].sum  = L.sum + R.sum;\n                    seg[pos].pref = max(L.pref, L.sum + R.pref);\n                    seg[pos].suff = max(R.suff, R.sum + L.suff);\n                    seg[pos].best = max({L.best, R.best, L.suff + R.pref});\n                }\n            }\n            int cur = seg[1].best;\n            if (cur > best_val) {\n                best_val = cur;\n                best_i = i;\n                best_j = j;\n            }\n        }\n    }\n\n    if (best_val <= 0) return {0, 0, 0, 0};\n\n    /* recover optimal x-interval by Kadane */\n    vector<int> arr(X, 0);\n    for (int j = best_i; j <= best_j; ++j)\n        for (const auto &pr : rows[j])\n            arr[pr.first] += pr.second;\n\n    int cur_sum = arr[0], cur_l = 0;\n    int best_sum = arr[0], best_l = 0, best_r = 0;\n    for (int r = 1; r < X; ++r) {\n        if (cur_sum + arr[r] < arr[r]) {\n            cur_sum = arr[r];\n            cur_l = r;\n        } else {\n            cur_sum += arr[r];\n        }\n        if (cur_sum > best_sum) {\n            best_sum = cur_sum;\n            best_l = cur_l;\n            best_r = r;\n        }\n    }\n\n    best_score = best_val;\n    return {xs[best_l], ys[best_i], xs[best_r], ys[best_j]};\n}\n\n/*------------------------------------------------------------*/\n/*  grid seeding                                               */\n/*------------------------------------------------------------*/\nusing Seed = tuple<int,int,int,int,int>; // S, gy1, gy2, gx1, gx2\n\nvector<Seed> grid_search(const vector<Point> &pts, int S, int K) {\n    const int MAXC = 100000;\n    int G = (MAXC + S) / S;\n    vector<vector<int>> grid(G, vector<int>(G, 0));\n    for (const auto &p : pts) {\n        int cx = min(p.x / S, G - 1);\n        int cy = min(p.y / S, G - 1);\n        grid[cy][cx] += p.w;\n    }\n\n    using Item = tuple<int,int,int,int,int>; // val, y1, y2, x1, x2\n    priority_queue<Item, vector<Item>, greater<Item>> pq;\n\n    for (int y1 = 0; y1 < G; ++y1) {\n        vector<int> col(G, 0);\n        for (int y2 = y1; y2 < G; ++y2) {\n            for (int x = 0; x < G; ++x) col[x] += grid[y2][x];\n\n            int cur = col[0], cur_l = 0;\n            int best = col[0], best_l = 0, best_r = 0;\n            for (int x = 1; x < G; ++x) {\n                if (cur + col[x] < col[x]) {\n                    cur = col[x];\n                    cur_l = x;\n                } else {\n                    cur += col[x];\n                }\n                if (cur > best) {\n                    best = cur;\n                    best_l = cur_l;\n                    best_r = x;\n                }\n            }\n\n            if ((int)pq.size() < K) {\n                pq.emplace(best, y1, y2, best_l, best_r);\n            } else if (best > get<0>(pq.top())) {\n                pq.pop();\n                pq.emplace(best, y1, y2, best_l, best_r);\n            }\n        }\n    }\n\n    vector<Seed> res;\n    while (!pq.empty()) {\n        auto t = pq.top(); pq.pop();\n        int val, y1, y2, x1, x2;\n        tie(val, y1, y2, x1, x2) = t;\n        res.emplace_back(S, y1, y2, x1, x2);\n    }\n    return res;\n}\n\n/*------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int MAXC = 100000;\n    const int MAX_SUBSET = 2000;\n\n    int N;\n    if (!(cin >> N)) return 0;\n\n    vector<Point> pts;\n    pts.reserve(2 * N);\n    unordered_set<unsigned long long> occupied;\n    occupied.reserve(2 * N * 2);\n\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, +1});\n        occupied.insert(((unsigned long long)x << 32) | (unsigned long long)y);\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n        pts.push_back({x, y, -1});\n        occupied.insert(((unsigned long long)x << 32) | (unsigned long long)y);\n    }\n\n    Rect best_rect{0, 0, 1, 1};\n    int best_score = 0;                 // a - b\n\n    auto consider = [&](const Rect &r) {\n        int a = 0, b = 0;\n        for (const auto &p : pts) {\n            if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) {\n                if (p.w == 1) ++a; else ++b;\n            }\n        }\n        int sc = a - b;\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = r;\n        }\n    };\n\n    /*--- empty unit square as safe fallback -------------------*/\n    mt19937 rng(123456789);\n    for (int attempt = 0; attempt < 20000; ++attempt) {\n        int x = uniform_int_distribution<int>(0, MAXC - 1)(rng);\n        int y = uniform_int_distribution<int>(0, MAXC - 1)(rng);\n        unsigned long long c1 = ((unsigned long long)x << 32) | (unsigned long long)y;\n        unsigned long long c2 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)y;\n        unsigned long long c3 = ((unsigned long long)x << 32) | (unsigned long long)(y + 1);\n        unsigned long long c4 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)(y + 1);\n        if (!occupied.count(c1) && !occupied.count(c2) &&\n            !occupied.count(c3) && !occupied.count(c4)) {\n            consider({x, y, x + 1, y + 1});\n            break;\n        }\n    }\n\n    /*--- collect coarse seeds --------------------------------*/\n    vector<Seed> seeds;\n    for (int S : {500, 1000, 2000}) {\n        auto v = grid_search(pts, S, 5);\n        seeds.insert(seeds.end(), v.begin(), v.end());\n    }\n\n    /*--- evaluate each seed ----------------------------------*/\n    for (const auto &sd : seeds) {\n        int S, gy1, gy2, gx1, gx2;\n        tie(S, gy1, gy2, gx1, gx2) = sd;\n\n        int x1 = gx1 * S;\n        int x2 = min(MAXC, (gx2 + 1) * S);\n        int y1 = gy1 * S;\n        int y2 = min(MAXC, (gy2 + 1) * S);\n\n        if (x1 >= x2) {\n            if (x1 > 0) --x1;\n            else ++x2;\n        }\n        if (y1 >= y2) {\n            if (y1 > 0) --y1;\n            else ++y2;\n        }\n\n        Rect rgrid{x1, y1, x2, y2};\n        consider(rgrid);\n\n        /* refine only when the window stays small */\n        int margin = S;\n        int wx1 = max(0, x1 - margin);\n        int wx2 = min(MAXC, x2 + margin);\n        int wy1 = max(0, y1 - margin);\n        int wy2 = min(MAXC, y2 + margin);\n\n        vector<Point> sub;\n        sub.reserve(pts.size());\n        for (const auto &p : pts) {\n            if (p.x >= wx1 && p.x <= wx2 && p.y >= wy1 && p.y <= wy2)\n                sub.push_back(p);\n        }\n\n        if ((int)sub.size() <= MAX_SUBSET) {\n            int sc;\n            Rect r = solve_exact(sub, sc);\n            if (sc > 0) {\n                /* fix zero width/height by expanding inside the window */\n                if (r.x1 == r.x2) {\n                    if (r.x2 < wx2) r.x2 = min(MAXC, r.x2 + 1);\n                    else r.x1 = max(0, r.x1 - 1);\n                }\n                if (r.y1 == r.y2) {\n                    if (r.y2 < wy2) r.y2 = min(MAXC, r.y2 + 1);\n                    else r.y1 = max(0, r.y1 - 1);\n                }\n                consider(r);\n            }\n        }\n    }\n\n    /*--- final safety check ----------------------------------*/\n    if (best_rect.x1 == best_rect.x2) {\n        if (best_rect.x2 < MAXC) ++best_rect.x2;\n        else --best_rect.x1;\n    }\n    if (best_rect.y1 == best_rect.y2) {\n        if (best_rect.y2 < MAXC) ++best_rect.y2;\n        else --best_rect.y1;\n    }\n\n    cout << 4 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y2 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y2 << \"\\n\";\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Seq {\n    int r[100];\n    char d[100];\n    int b[100];\n};\n\nint N, T;\nlong long SIGMA;\nlong long Wobs[100], Hobs[100];\n\n/*------------------------------------------------------------*/\n/*  simulate from position `start` (0 \u2264 start \u2264 N)             */\ninline long long simulate(const Seq& seq, int n,\n                          long long* xs, long long* ys,\n                          long long* ws, long long* hs,\n                          int start = 0) {\n    long long W = 0, H = 0;\n    for (int i = start; i < n; ++i) {\n        long long wi = seq.r[i] ? Hobs[i] : Wobs[i];\n        long long hi = seq.r[i] ? Wobs[i] : Hobs[i];\n        long long x, y;\n        if (seq.d[i] == 'U') {\n            x = (seq.b[i] == -1) ? 0LL : xs[seq.b[i]] + ws[seq.b[i]];\n            y = 0;\n            for (int j = 0; j < i; ++j) {\n                if (x < xs[j] + ws[j] && xs[j] < x + wi)\n                    y = max(y, ys[j] + hs[j]);\n            }\n        } else {\n            y = (seq.b[i] == -1) ? 0LL : ys[seq.b[i]] + hs[seq.b[i]];\n            x = 0;\n            for (int j = 0; j < i; ++j) {\n                if (y < ys[j] + hs[j] && ys[j] < y + hi)\n                    x = max(x, xs[j] + ws[j]);\n            }\n        }\n        xs[i] = x;  ys[i] = y;\n        ws[i] = wi; hs[i] = hi;\n        if (x + wi > W) W = x + wi;\n        if (y + hi > H) H = y + hi;\n    }\n    return W + H;\n}\n\n/*------------------------------------------------------------*/\n/*  greedy construction / rebuild from `start`                 */\nlong long greedy_build(Seq& seq, int n, int start,\n                       int objective, bool stochastic,\n                       mt19937& rng,\n                       long long* xs, long long* ys,\n                       long long* ws, long long* hs) {\n    long long W = 0, H = 0;\n    for (int j = 0; j < start; ++j) {\n        W = max(W, xs[j] + ws[j]);\n        H = max(H, ys[j] + hs[j]);\n    }\n\n    struct Cand {\n        int r, b; char d;\n        long long x, y, w, h, sc;\n    } cands[404];\n    int cand_cnt;\n\n    for (int i = start; i < n; ++i) {\n        cand_cnt = 0;\n        for (int rot = 0; rot < 2; ++rot) {\n            long long wi = rot ? Hobs[i] : Wobs[i];\n            long long hi = rot ? Wobs[i] : Hobs[i];\n            for (int di = 0; di < 2; ++di) {\n                char dd = di ? 'L' : 'U';\n                for (int bv = -1; bv < i; ++bv) {\n                    long long x, y;\n                    if (dd == 'U') {\n                        x = (bv == -1) ? 0LL : xs[bv] + ws[bv];\n                        y = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (x < xs[j] + ws[j] && xs[j] < x + wi)\n                                y = max(y, ys[j] + hs[j]);\n                    } else {\n                        y = (bv == -1) ? 0LL : ys[bv] + hs[bv];\n                        x = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (y < ys[j] + hs[j] && ys[j] < y + hi)\n                                x = max(x, xs[j] + ws[j]);\n                    }\n                    long long nW = max(W, x + wi);\n                    long long nH = max(H, y + hi);\n                    long long sc;\n                    if (objective == 0) sc = nW + nH;\n                    else if (objective == 1) sc = max(nW, nH);\n                    else if (objective == 2) sc = nW * nH;\n                    else sc = nW + nH + llabs(nW - nH) / 10;\n                    cands[cand_cnt++] = {rot, bv, dd, x, y, wi, hi, sc};\n                }\n            }\n        }\n\n        long long best_sc = cands[0].sc;\n        for (int k = 1; k < cand_cnt; ++k)\n            if (cands[k].sc < best_sc) best_sc = cands[k].sc;\n\n        int idx = 0;\n        if (stochastic) {\n            long long thr = best_sc + max(1LL, best_sc / 50);\n            int good[404], gcnt = 0;\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc <= thr) good[gcnt++] = k;\n            idx = good[rng() % gcnt];\n        } else {\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc == best_sc) { idx = k; break; }\n        }\n\n        const Cand& c = cands[idx];\n        seq.r[i] = c.r; seq.d[i] = c.d; seq.b[i] = c.b;\n        xs[i] = c.x; ys[i] = c.y; ws[i] = c.w; hs[i] = c.h;\n        W = max(W, c.x + c.w);\n        H = max(H, c.y + c.h);\n    }\n    return W + H;\n}\n\n/*------------------------------------------------------------*/\n/*  copy sequence                                              */\ninline void copy_seq(Seq& dst, const Seq& src, int n) {\n    memcpy(dst.r, src.r, n * sizeof(int));\n    memcpy(dst.d, src.d, n * sizeof(char));\n    memcpy(dst.b, src.b, n * sizeof(int));\n}\n\n/*------------------------------------------------------------*/\n/*  exhaustive steepest move at position i (always accepted)   */\ninline void exhaustive_move(Seq& seq, int n,\n                            long long* xs, long long* ys,\n                            long long* ws, long long* hs,\n                            int i, long long& score) {\n    int old_r = seq.r[i], old_b = seq.b[i];\n    char old_d = seq.d[i];\n\n    long long best_sc = score;\n    int best_r = old_r, best_b = old_b;\n    char best_d = old_d;\n\n    for (int rot = 0; rot < 2; ++rot) {\n        for (int di = 0; di < 2; ++di) {\n            char dd = di ? 'L' : 'U';\n            for (int bv = -1; bv < i; ++bv) {\n                seq.r[i] = rot; seq.d[i] = dd; seq.b[i] = bv;\n                long long sc = simulate(seq, n, xs, ys, ws, hs, i);\n                if (sc < best_sc) {\n                    best_sc = sc;\n                    best_r = rot; best_b = bv; best_d = dd;\n                }\n            }\n        }\n    }\n    seq.r[i] = best_r; seq.d[i] = best_d; seq.b[i] = best_b;\n    if (best_sc != score) {\n        score = best_sc;\n        simulate(seq, n, xs, ys, ws, hs, i);\n    }\n}\n\n/*------------------------------------------------------------*/\n/*  random mutation at i (accept only if improves, or rarely)  */\ninline void random_move(Seq& seq, int n,\n                        long long* xs, long long* ys,\n                        long long* ws, long long* hs,\n                        int i, long long& score, mt19937& rng) {\n    int old_r = seq.r[i], old_b = seq.b[i];\n    char old_d = seq.d[i];\n\n    seq.r[i] = rng() & 1;\n    seq.d[i] = (rng() & 1) ? 'L' : 'U';\n    seq.b[i] = (int)(rng() % (i + 1)) - 1;\n\n    long long sc = simulate(seq, n, xs, ys, ws, hs, i);\n    if (sc < score || (rng() & 255) < 3) {   // ~1% chance to accept worsening\n        score = sc;\n    } else {\n        seq.r[i] = old_r; seq.d[i] = old_d; seq.b[i] = old_b;\n    }\n}\n\n/*------------------------------------------------------------*/\n/*  kick: change several random positions                      */\ninline void kick_move(Seq& seq, int n,\n                      long long* xs, long long* ys,\n                      long long* ws, long long* hs,\n                      long long& score, mt19937& rng) {\n    int k = 2 + (int)(rng() % 4);   // change 2..5 positions\n    int min_i = n;\n    for (int t = 0; t < k; ++t) {\n        int i = (int)(rng() % n);\n        min_i = min(min_i, i);\n        seq.r[i] = rng() & 1;\n        seq.d[i] = (rng() & 1) ? 'L' : 'U';\n        seq.b[i] = (int)(rng() % (i + 1)) - 1;\n    }\n    score = simulate(seq, n, xs, ys, ws, hs, min_i);\n}\n\n/*------------------------------------------------------------*/\n/*  local search from `seq` / `score` for `limit_sec` seconds  */\nvoid local_search(Seq& seq, long long& score, double limit_sec,\n                  mt19937& rng) {\n    auto t0 = chrono::steady_clock::now();\n\n    long long xs[100], ys[100], ws[100], hs[100];\n    simulate(seq, N, xs, ys, ws, hs, 0);\n\n    Seq best = seq;\n    long long best_sc = score;\n\n    Seq cur = seq;\n    long long cur_sc = score;\n    long long cx[100], cy[100], cw[100], ch[100];\n    memcpy(cx, xs, sizeof(xs));\n    memcpy(cy, ys, sizeof(ys));\n    memcpy(cw, ws, sizeof(ws));\n    memcpy(ch, hs, sizeof(hs));\n\n    int iter = 0;\n    int no_improve = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed >= limit_sec) break;\n\n        int typ = (int)(rng() % 100);\n        if (no_improve > 80 && typ < 15) {\n            /* kick after long stagnation */\n            kick_move(cur, N, cx, cy, cw, ch, cur_sc, rng);\n            if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n            else no_improve = 0;   // reset because we jumped elsewhere\n        } else if (typ < 25) {\n            /* exhaustive steepest move */\n            int i = (int)(rng() % N);\n            exhaustive_move(cur, N, cx, cy, cw, ch, i, cur_sc);\n            if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n            else ++no_improve;\n        } else if (typ < 40) {\n            /* suffix rebuild */\n            int i = (int)(rng() % N);\n            Seq tmp;  copy_seq(tmp, cur, N);\n            long long tx[100], ty[100], tw[100], th[100];\n            memcpy(tx, cx, i * sizeof(long long));\n            memcpy(ty, cy, i * sizeof(long long));\n            memcpy(tw, cw, i * sizeof(long long));\n            memcpy(th, ch, i * sizeof(long long));\n            long long sc = greedy_build(tmp, N, i, (int)(rng() % 4),\n                                        (rng() & 1), rng, tx, ty, tw, th);\n            if (sc < cur_sc || (rng() & 255) < 5) {\n                copy_seq(cur, tmp, N);\n                cur_sc = sc;\n                memcpy(cx, tx, sizeof(tx));\n                memcpy(cy, ty, sizeof(ty));\n                memcpy(cw, tw, sizeof(tw));\n                memcpy(ch, th, sizeof(th));\n                if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n                else ++no_improve;\n            } else {\n                ++no_improve;\n            }\n        } else {\n            /* random mutation */\n            int i = (int)(rng() % N);\n            random_move(cur, N, cx, cy, cw, ch, i, cur_sc, rng);\n            if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n            else ++no_improve;\n        }\n        ++iter;\n    }\n    seq = best;\n    score = best_sc;\n}\n\n/*------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T >> SIGMA;\n    for (int i = 0; i < N; ++i) cin >> Wobs[i] >> Hobs[i];\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    const double TIME_LIMIT = 2.85;\n    auto start_clock = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_clock).count();\n    };\n\n    /*----- initial deterministic + randomized constructions -----*/\n    long long xs[100], ys[100], ws[100], hs[100];\n    Seq best_seq;\n    long long best_score = LLONG_MAX;\n\n    for (int obj = 0; obj < 4; ++obj) {\n        Seq seq;\n        long long sc = greedy_build(seq, N, 0, obj, false, rng, xs, ys, ws, hs);\n        if (sc < best_score) {\n            best_score = sc;\n            copy_seq(best_seq, seq, N);\n        }\n    }\n    for (int t = 0; t < 30; ++t) {\n        Seq seq;\n        long long sc = greedy_build(seq, N, 0, (int)(rng() % 4), true, rng, xs, ys, ws, hs);\n        if (sc < best_score) {\n            best_score = sc;\n            copy_seq(best_seq, seq, N);\n        }\n    }\n\n    /*----- intensify before first query -----------------------*/\n    double init_time = min(0.45, TIME_LIMIT * 0.15);\n    local_search(best_seq, best_score, init_time, rng);\n\n    long long best_observed = LLONG_MAX;\n    Seq global_best_seq = best_seq;\n\n    double remaining = TIME_LIMIT - elapsed();\n    double per_turn = remaining / max(1, T);\n\n    for (int turn = 0; turn < T; ++turn) {\n        auto turn_start = chrono::steady_clock::now();\n        double turn_budget = min(per_turn * 1.1,\n                                 (TIME_LIMIT - elapsed()) / max(1, T - turn));\n\n        /*-- start from global best and improve --*/\n        Seq cand = global_best_seq;\n        long long cand_sc;\n        {\n            long long tx[100], ty[100], tw[100], th[100];\n            cand_sc = simulate(cand, N, tx, ty, tw, th, 0);\n        }\n        local_search(cand, cand_sc, turn_budget, rng);\n\n        /*-- occasionally also try a fresh random greedy --*/\n        if (turn % 7 == 0) {\n            Seq rnd;\n            long long tx[100], ty[100], tw[100], th[100];\n            long long sc = greedy_build(rnd, N, 0, (int)(rng() % 4), true, rng, tx, ty, tw, th);\n            local_search(rnd, sc, turn_budget * 0.3, rng);\n            if (sc < cand_sc) {\n                cand = rnd;\n                cand_sc = sc;\n            }\n        }\n\n        /*-- output --*/\n        cout << N << '\\n';\n        for (int i = 0; i < N; ++i) {\n            cout << i << ' ' << cand.r[i] << ' ' << cand.d[i] << ' ' << cand.b[i] << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        long long obs = Wp + Hp;\n        if (obs < best_observed) {\n            best_observed = obs;\n            global_best_seq = cand;\n        }\n    }\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, M, H;\n    vector<int> A;\n    vector<vector<int>> adj;\n\n    // current depth state\n    vector<int> d;\n    // sup[v][k] = number of neighbours of v with depth k-1  (1 <= k <= H)\n    vector<array<int, 12>> sup;\n    long long score = 0;\n\n    vector<int> best_d;\n    long long best_score = 0;\n\n    mt19937 rng;\n\n    Solver() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void read_input() {\n        cin >> N >> M >> H;\n        A.resize(N);\n        for (int i = 0; i < N; ++i) cin >> A[i];\n        adj.assign(N, {});\n        for (int i = 0; i < M; ++i) {\n            int u, v; cin >> u >> v;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        // coordinates are irrelevant for the algorithm\n        for (int i = 0; i < N; ++i) {\n            int x, y; cin >> x >> y;\n        }\n        sup.assign(N, {});\n        best_d.resize(N);\n    }\n\n    // set all depths to 0 and compute sup / score\n    void init_state() {\n        d.assign(N, 0);\n        for (int i = 0; i < N; ++i) sup[i].fill(0);\n        for (int v = 0; v < N; ++v) {\n            for (int w : adj[v]) {\n                // w has depth 0, so it supports depth 1\n                sup[v][1]++;\n            }\n        }\n        score = 0;\n        for (int i = 0; i < N; ++i) score += A[i];\n    }\n\n    inline bool can_move(int v, int k) const {\n        if (k == d[v]) return false;\n        if (k > 0 && sup[v][k] == 0) return false;\n        int old = d[v];\n        if (old + 1 <= H) {\n            for (int w : adj[v]) {\n                if (d[w] == old + 1 && sup[w][old + 1] == 1) return false;\n            }\n        }\n        return true;\n    }\n\n    inline void apply_move(int v, int k) {\n        int old = d[v];\n        if (old == k) return;\n        for (int w : adj[v]) {\n            if (old + 1 <= H) sup[w][old + 1]--;\n            if (k + 1 <= H) sup[w][k + 1]++;\n        }\n        score += 1LL * (k - old) * A[v];\n        d[v] = k;\n    }\n\n    void set_state(const vector<int>& nd) {\n        d = nd;\n        score = 0;\n        for (int i = 0; i < N; ++i) {\n            score += 1LL * (d[i] + 1) * A[i];\n            sup[i].fill(0);\n        }\n        for (int v = 0; v < N; ++v) {\n            for (int w : adj[v]) {\n                if (d[w] + 1 <= H) sup[v][d[w] + 1]++;\n            }\n        }\n    }\n\n    inline void save_best() {\n        if (score > best_score) {\n            best_score = score;\n            best_d = d;\n        }\n    }\n\n    // Fast greedy ascent: raise each vertex as much as possible in random order\n    void randomized_ascent() {\n        bool improved = true;\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        while (improved) {\n            improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int v : ord) {\n                int old = d[v];\n                if (old == H) continue;\n                // check whether v is locked by a unique child at old+1\n                bool locked = false;\n                if (old + 1 <= H) {\n                    for (int w : adj[v]) {\n                        if (d[w] == old + 1 && sup[w][old + 1] == 1) {\n                            locked = true;\n                            break;\n                        }\n                    }\n                }\n                if (locked) continue;\n                // best improving move is the largest valid k > old\n                for (int k = H; k > old; --k) {\n                    if (sup[v][k] > 0) {\n                        apply_move(v, k);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    // Simulated annealing on the depth labeling\n    void sa_phase(double deadline, double T0) {\n        double T = T0;\n        const double alpha = 0.99995;\n        const double T_min = 0.01;\n        int last_improve = 0;\n\n        for (int iter = 0; ; ++iter) {\n            double now = (double)clock() / CLOCKS_PER_SEC;\n            if (now >= deadline) break;\n\n            int v = rng() % N;\n            if (adj[v].empty()) continue;\n\n            int k;\n            int r = (int)(rng() % 100);\n            if (r < 10) {\n                k = 0;\n            } else if (r < 30 && d[v] > 0) {\n                k = d[v] - 1;\n            } else {\n                int u = adj[v][rng() % adj[v].size()];\n                k = d[u] + 1;\n                if (k > H) {\n                    if (d[v] > 0) k = d[v] - 1;\n                    else k = 0;\n                }\n            }\n\n            if (!can_move(v, k)) continue;\n\n            long long gain = 1LL * (k - d[v]) * A[v];\n            bool accept = false;\n            if (gain > 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)gain / T);\n                double rnd = (rng() & 0x7FFFFFFF) / 2147483648.0;\n                accept = prob > rnd;\n            }\n\n            if (accept) {\n                apply_move(v, k);\n                if (score > best_score) {\n                    best_score = score;\n                    best_d = d;\n                    last_improve = iter;\n                }\n            }\n\n            T *= alpha;\n            if (T < T_min) T = T_min;\n\n            // reheat if no improvement for a long time\n            if (iter - last_improve > 100000) {\n                // quick polish of current state\n                randomized_ascent();\n                if (score > best_score) {\n                    best_score = score;\n                    best_d = d;\n                    last_improve = iter;\n                }\n                // revert to best known and reheat\n                if (score < best_score) {\n                    set_state(best_d);\n                }\n                T = T0;\n                last_improve = iter;\n            }\n        }\n    }\n\n    vector<int> reconstruct_parents(const vector<int>& depth) {\n        vector<int> parent(N, -1);\n        for (int v = 0; v < N; ++v) {\n            if (depth[v] > 0) {\n                for (int u : adj[v]) {\n                    if (depth[u] == depth[v] - 1) {\n                        parent[v] = u;\n                        break;\n                    }\n                }\n            }\n        }\n        return parent;\n    }\n\n    void solve() {\n        read_input();\n        double TL = 1.90; // leave a safety margin\n\n        // Try a few independent restarts + one long SA run\n        int trial = 0;\n        while ((double)clock() / CLOCKS_PER_SEC < TL) {\n            init_state();\n            randomized_ascent();\n            save_best();\n\n            // Run SA until a short time budget for this trial\n            double sub_deadline = min(TL, (double)clock() / CLOCKS_PER_SEC + 0.15);\n            double T0 = 1000.0; // fixed works well; could scale with best_score\n            sa_phase(sub_deadline, T0);\n\n            // Final polish\n            randomized_ascent();\n            save_best();\n\n            ++trial;\n            if (trial == 1) {\n                // After first trial we already have a decent best_d.\n                // Continue using the remaining time with more restarts.\n            }\n        }\n\n        vector<int> ans = reconstruct_parents(best_d);\n        for (int i = 0; i < N; ++i) {\n            if (i) cout << ' ';\n            cout << ans[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*** ---------- safe (restoring) block solver (exact set cover) ---------- ***/\nstruct SafeOp {\n    uint64_t mask = 0;\n    int cost = 0;          // 2 * k\n    char dir = 0;\n    int idx = 0;\n    int k = 0;\n};\n\nvector<pair<char,int>> solve_safe(const vector<string>& B) {\n    int N = (int)B.size();\n    vector<pair<int,int>> oni;\n    vector<vector<int>> oni_id(N, vector<int>(N, -1));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (B[i][j] == 'x') {\n                oni_id[i][j] = (int)oni.size();\n                oni.emplace_back(i, j);\n            }\n    const int M = (int)oni.size();\n    vector<SafeOp> ops;\n\n    auto add = [&](uint64_t mask, int cost, char d, int idx, int k) {\n        if (mask) ops.push_back({mask, cost, d, idx, k});\n    };\n\n    // rows\n    for (int i = 0; i < N; ++i) {\n        vector<int> fc;\n        for (int j = 0; j < N; ++j) if (B[i][j] == 'o') fc.push_back(j);\n        sort(fc.begin(), fc.end());\n        int L = fc.empty() ? N : fc.front();\n        int R = fc.empty() ? -1 : fc.back();\n\n        vector<pair<int,int>> left, right;\n        for (int j = 0; j < N; ++j) if (B[i][j] == 'x') {\n            if (j < L) left.emplace_back(j, oni_id[i][j]);\n            if (j > R) right.emplace_back(j, oni_id[i][j]);\n        }\n        sort(left.begin(), left.end());\n        sort(right.begin(), right.end(), greater<pair<int,int>>());\n        uint64_t m = 0;\n        for (int t = 0; t < (int)left.size(); ++t) {\n            m |= 1ULL << left[t].second;\n            add(m, 2 * (left[t].first + 1), 'L', i, left[t].first + 1);\n        }\n        m = 0;\n        for (int t = 0; t < (int)right.size(); ++t) {\n            m |= 1ULL << right[t].second;\n            add(m, 2 * (N - right[t].first), 'R', i, N - right[t].first);\n        }\n    }\n    // columns\n    for (int j = 0; j < N; ++j) {\n        vector<int> fr;\n        for (int i = 0; i < N; ++i) if (B[i][j] == 'o') fr.push_back(i);\n        sort(fr.begin(), fr.end());\n        int T = fr.empty() ? N : fr.front();\n        int Bot = fr.empty() ? -1 : fr.back();\n\n        vector<pair<int,int>> top, bot;\n        for (int i = 0; i < N; ++i) if (B[i][j] == 'x') {\n            if (i < T) top.emplace_back(i, oni_id[i][j]);\n            if (i > Bot) bot.emplace_back(i, oni_id[i][j]);\n        }\n        sort(top.begin(), top.end());\n        sort(bot.begin(), bot.end(), greater<pair<int,int>>());\n        uint64_t m = 0;\n        for (int t = 0; t < (int)top.size(); ++t) {\n            m |= 1ULL << top[t].second;\n            add(m, 2 * (top[t].first + 1), 'U', j, top[t].first + 1);\n        }\n        m = 0;\n        for (int t = 0; t < (int)bot.size(); ++t) {\n            m |= 1ULL << bot[t].second;\n            add(m, 2 * (N - bot[t].first), 'D', j, N - bot[t].first);\n        }\n    }\n\n    // dominance pruning\n    vector<SafeOp> pruned;\n    for (auto &op : ops) {\n        bool dominated = false;\n        for (auto &p : pruned) {\n            if ( (p.mask | op.mask) == p.mask && p.cost <= op.cost ) {\n                dominated = true; break;\n            }\n        }\n        if (dominated) continue;\n        vector<SafeOp> nxt;\n        for (auto &p : pruned) {\n            if ( !((op.mask | p.mask) == op.mask && op.cost <= p.cost) )\n                nxt.push_back(p);\n        }\n        nxt.push_back(op);\n        pruned.swap(nxt);\n    }\n    ops.swap(pruned);\n    int S = (int)ops.size();\n\n    vector<vector<int>> oni_covers(M);\n    for (int i = 0; i < S; ++i) {\n        uint64_t m = ops[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            oni_covers[b].push_back(i);\n            m &= m - 1;\n        }\n    }\n\n    const uint64_t FULL = (M == 64) ? ~0ULL : ((1ULL << M) - 1ULL);\n\n    // greedy upper bound\n    int greedy_cost = 0;\n    uint64_t uncovered_g = FULL;\n    vector<int> greedy_sol;\n    while (uncovered_g) {\n        int best = -1;\n        double best_r = 1e300;\n        for (int i = 0; i < S; ++i) {\n            uint64_t nw = ops[i].mask & uncovered_g;\n            int cnt = __builtin_popcountll(nw);\n            if (cnt == 0) continue;\n            double r = (double)ops[i].cost / cnt;\n            if (r < best_r) { best_r = r; best = i; }\n        }\n        if (best == -1) break;\n        greedy_sol.push_back(best);\n        greedy_cost += ops[best].cost;\n        uncovered_g &= ~ops[best].mask;\n    }\n\n    int best_cost = greedy_cost;\n    vector<int> best_sol = greedy_sol;\n    unordered_map<uint64_t, int> memo;\n    memo.reserve(200000);\n\n    function<void(uint64_t,int,vector<int>&)> dfs = [&](uint64_t uncovered, int cur, vector<int> &vec) {\n        if (uncovered == 0) {\n            if (cur < best_cost) {\n                best_cost = cur;\n                best_sol = vec;\n            }\n            return;\n        }\n        if (cur >= best_cost) return;\n        auto it = memo.find(uncovered);\n        if (it != memo.end() && it->second <= cur) return;\n        memo[uncovered] = cur;\n\n        int lb = cur;\n        uint64_t tmp = uncovered;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int mn = INT_MAX;\n            for (int id : oni_covers[o]) {\n                if (ops[id].mask & uncovered) mn = min(mn, ops[id].cost);\n            }\n            if (mn == INT_MAX) return;\n            lb += mn;\n            if (lb >= best_cost) return;\n            tmp &= tmp - 1;\n        }\n\n        int target = -1, mindeg = INT_MAX;\n        tmp = uncovered;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int deg = 0;\n            for (int id : oni_covers[o])\n                if (ops[id].mask & uncovered) ++deg;\n            if (deg < mindeg) { mindeg = deg; target = o; }\n            tmp &= tmp - 1;\n        }\n\n        vector<pair<int,int>> cands;\n        for (int id : oni_covers[target]) {\n            if (ops[id].mask & uncovered) cands.emplace_back(ops[id].cost, id);\n        }\n        sort(cands.begin(), cands.end());\n        for (auto &[c, id] : cands) {\n            if (cur + c >= best_cost) continue;\n            vec.push_back(id);\n            dfs(uncovered & ~ops[id].mask, cur + c, vec);\n            vec.pop_back();\n        }\n    };\n\n    vector<int> cur;\n    dfs(FULL, 0, cur);\n\n    // remove redundant ops\n    vector<int> sol = best_sol;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < sol.size(); ++i) {\n            uint64_t u = 0;\n            for (size_t j = 0; j < sol.size(); ++j)\n                if (j != i) u |= ops[sol[j]].mask;\n            if ( (u & FULL) == FULL ) {\n                sol.erase(sol.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    vector<pair<char,int>> moves;\n    for (int id : sol) {\n        const SafeOp &op = ops[id];\n        for (int t = 0; t < op.k; ++t) moves.emplace_back(op.dir, op.idx);\n        char rev = 0;\n        if (op.dir == 'L') rev = 'R';\n        else if (op.dir == 'R') rev = 'L';\n        else if (op.dir == 'U') rev = 'D';\n        else rev = 'U';\n        for (int t = 0; t < op.k; ++t) moves.emplace_back(rev, op.idx);\n    }\n    return moves;\n}\n\n/*** ---------- greedy non\u2011restoring sweep solver ---------- ***/\nstruct GOp { char d; int idx, k; };\n\nstruct Board {\n    int n;\n    array<unsigned int, 20> oni{}, fuku{};\n    array<unsigned int, 20> oni_col{}, fuku_col{};\n    int oni_cnt = 0;\n    void init(const vector<string> &s) {\n        n = (int)s.size();\n        oni.fill(0); fuku.fill(0); oni_col.fill(0); fuku_col.fill(0); oni_cnt = 0;\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j) {\n                if (s[i][j] == 'x') { oni[i] |= 1u << j; ++oni_cnt; }\n                else if (s[i][j] == 'o') fuku[i] |= 1u << j;\n            }\n        recompute_cols();\n    }\n    void recompute_cols() {\n        oni_col.fill(0); fuku_col.fill(0);\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j) {\n                if (oni[i] >> j & 1u) oni_col[j] |= 1u << i;\n                if (fuku[i] >> j & 1u) fuku_col[j] |= 1u << i;\n            }\n    }\n    bool row_left(int i, int k) {\n        unsigned int dm = (1u << k) - 1;\n        if (fuku[i] & dm) return false;\n        unsigned int dropped = oni[i] & dm;\n        oni_cnt -= __builtin_popcount(dropped);\n        oni[i] >>= k; fuku[i] >>= k;\n        recompute_cols(); return true;\n    }\n    bool row_right(int i, int k) {\n        unsigned int keep = (1u << (n - k)) - 1;\n        unsigned int dm = (~keep) & ((1u << n) - 1);\n        if (fuku[i] & dm) return false;\n        unsigned int dropped = oni[i] & dm;\n        oni_cnt -= __builtin_popcount(dropped);\n        oni[i] = (oni[i] & keep) << k;\n        fuku[i] = (fuku[i] & keep) << k;\n        recompute_cols(); return true;\n    }\n    bool col_up(int j, int k) {\n        unsigned int dm = (1u << k) - 1;\n        if (fuku_col[j] & dm) return false;\n        unsigned int dropped = oni_col[j] & dm;\n        oni_cnt -= __builtin_popcount(dropped);\n        oni_col[j] >>= k; fuku_col[j] >>= k;\n        for (int i = 0; i < n; ++i) {\n            oni[i] = (oni[i] & ~(1u << j)) | (((oni_col[j] >> i) & 1u) << j);\n            fuku[i] = (fuku[i] & ~(1u << j)) | (((fuku_col[j] >> i) & 1u) << j);\n        }\n        return true;\n    }\n    bool col_down(int j, int k) {\n        unsigned int keep = (1u << (n - k)) - 1;\n        unsigned int dm = (~keep) & ((1u << n) - 1);\n        if (fuku_col[j] & dm) return false;\n        unsigned int dropped = oni_col[j] & dm;\n        oni_cnt -= __builtin_popcount(dropped);\n        oni_col[j] = (oni_col[j] & keep) << k;\n        fuku_col[j] = (fuku_col[j] & keep) << k;\n        for (int i = 0; i < n; ++i) {\n            oni[i] = (oni[i] & ~(1u << j)) | (((oni_col[j] >> i) & 1u) << j);\n            fuku[i] = (fuku[i] & ~(1u << j)) | (((fuku_col[j] >> i) & 1u) << j);\n        }\n        return true;\n    }\n};\n\nvector<GOp> greedy_solve(const vector<string> &B, int type, bool rows_first, bool cols_first) {\n    Board b; b.init(B);\n    vector<GOp> ops;\n    const int N = b.n;\n\n    auto apply = [&](char d, int idx, int k)->bool{\n        if (d == 'L') return b.row_left(idx, k);\n        if (d == 'R') return b.row_right(idx, k);\n        if (d == 'U') return b.col_up(idx, k);\n        return b.col_down(idx, k);\n    };\n\n    while (b.oni_cnt > 0) {\n        struct Cand { char d; int idx, k, cnt; double sc; };\n        vector<Cand> cands;\n\n        auto add_rows = [&]() {\n            for (int i = 0; i < N; ++i) {\n                int lim = N;\n                if (b.fuku[i]) lim = __builtin_ctz(b.fuku[i]);\n                if (lim > 0) {\n                    unsigned int mask = b.oni[i] & ((1u << lim) - 1);\n                    unsigned int tmp = mask;\n                    while (tmp) {\n                        int c = __builtin_ctz(tmp);\n                        int k = c + 1;\n                        int cnt = __builtin_popcount(b.oni[i] & ((1u << k) - 1));\n                        if (cnt > 0) cands.push_back({'L', i, k, cnt, 0.0});\n                        tmp &= tmp - 1;\n                    }\n                }\n                int limr = -1;\n                if (b.fuku[i]) limr = 31 - __builtin_clz(b.fuku[i]);\n                if (limr < N - 1) {\n                    unsigned int mask = b.oni[i];\n                    if (limr >= 0) mask &= ~((1u << (limr + 1)) - 1);\n                    for (int c = N - 1; c > limr; --c) if (mask & (1u << c)) {\n                        int k = N - c;\n                        int cnt = __builtin_popcount(b.oni[i] >> c);\n                        if (cnt > 0) cands.push_back({'R', i, k, cnt, 0.0});\n                    }\n                }\n            }\n        };\n        auto add_cols = [&]() {\n            for (int j = 0; j < N; ++j) {\n                int lim = N;\n                if (b.fuku_col[j]) lim = __builtin_ctz(b.fuku_col[j]);\n                if (lim > 0) {\n                    unsigned int mask = b.oni_col[j] & ((1u << lim) - 1);\n                    unsigned int tmp = mask;\n                    while (tmp) {\n                        int r = __builtin_ctz(tmp);\n                        int k = r + 1;\n                        int cnt = __builtin_popcount(b.oni_col[j] & ((1u << k) - 1));\n                        if (cnt > 0) cands.push_back({'U', j, k, cnt, 0.0});\n                        tmp &= tmp - 1;\n                    }\n                }\n                int limr = -1;\n                if (b.fuku_col[j]) limr = 31 - __builtin_clz(b.fuku_col[j]);\n                if (limr < N - 1) {\n                    unsigned int mask = b.oni_col[j];\n                    if (limr >= 0) mask &= ~((1u << (limr + 1)) - 1);\n                    for (int r = N - 1; r > limr; --r) if (mask & (1u << r)) {\n                        int k = N - r;\n                        int cnt = __builtin_popcount(b.oni_col[j] >> r);\n                        if (cnt > 0) cands.push_back({'D', j, k, cnt, 0.0});\n                    }\n                }\n            }\n        };\n\n        if (rows_first) {\n            add_rows();\n            if (cands.empty()) add_cols();\n        } else if (cols_first) {\n            add_cols();\n            if (cands.empty()) add_rows();\n        } else {\n            add_rows();\n            add_cols();\n        }\n\n        if (cands.empty()) break; // stuck\n\n        for (auto &c : cands) {\n            if (type == 0) c.sc = c.cnt * 1e6 - c.k;\n            else if (type == 1) c.sc = (double)c.cnt / (double)c.k;\n            else if (type == 2) c.sc = (double)c.cnt - (double)c.k;\n            else c.sc = (double)c.cnt * (double)c.cnt / (double)c.k;\n        }\n        auto best = max_element(cands.begin(), cands.end(),\n                                [](const Cand&a, const Cand&b){ return a.sc < b.sc; });\n        if (!apply(best->d, best->idx, best->k)) break; // safety check (should pass)\n        ops.push_back({best->d, best->idx, best->k});\n    }\n\n    if (b.oni_cnt != 0) ops.clear(); // failure\n    return ops;\n}\n\n/*** ---------- main ---------- ***/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> B(N);\n    for (int i = 0; i < N; ++i) cin >> B[i];\n\n    vector<pair<char,int>> best;\n    int best_cost = INT_MAX;\n    const int LIMIT = 4 * N * N;\n\n    auto consider = [&](const vector<pair<char,int>> &moves) {\n        if ((int)moves.size() <= LIMIT && (int)moves.size() < best_cost) {\n            best_cost = (int)moves.size();\n            best = moves;\n        }\n    };\n\n    // safe restoring solution (always valid)\n    consider(solve_safe(B));\n\n    // greedy non\u2011restoring heuristics\n    for (int type = 0; type < 4; ++type) {\n        for (int mode = 0; mode < 3; ++mode) {\n            auto g = greedy_solve(B, type, mode == 1, mode == 2);\n            if (!g.empty()) {\n                vector<pair<char,int>> moves;\n                moves.reserve(200);\n                for (auto &op : g)\n                    for (int t = 0; t < op.k; ++t)\n                        moves.emplace_back(op.d, op.idx);\n                consider(moves);\n            }\n        }\n    }\n\n    for (auto &p : best) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) return 0;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    vector<double> p(N);\n    for (int i = 0; i < N; ++i) p[i] = (double)T[i] / (double)L;\n\n    /*------------------------------------------------------------\n        Phase 1 : greedy init + fast proxy local search\n      ------------------------------------------------------------*/\n    vector<int> a(N), b(N);\n    vector<double> in(N, 0.0);\n\n    auto pick_best_deficit = [&]() {\n        int best = 0;\n        double bestDef = -1e100;\n        for (int i = 0; i < N; ++i) {\n            double def = p[i] - in[i];\n            if (def > bestDef) {\n                bestDef = def;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (int j = 0; j < N; ++j) {\n        int u = pick_best_deficit();\n        a[j] = u;\n        in[u] += p[j] * 0.5;\n        int v = pick_best_deficit();\n        b[j] = v;\n        in[v] += p[j] * 0.5;\n    }\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto proxy_delta = [&](int j, int typ, int newv) -> double {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return 0.0;\n        double d = 0.0;\n        double afterOld = in[oldv] - p[j] * 0.5;\n        d += fabs(afterOld - p[oldv]) - fabs(in[oldv] - p[oldv]);\n        double afterNew = in[newv] + p[j] * 0.5;\n        d += fabs(afterNew - p[newv]) - fabs(in[newv] - p[newv]);\n        return d;\n    };\n\n    auto apply_proxy = [&](int j, int typ, int newv) {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return;\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ) b[j] = newv;\n        else     a[j] = newv;\n    };\n\n    for (int iter = 0; iter < 500000; ++iter) {\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int newv = (int)(rng() % N);\n        double d = proxy_delta(j, typ, newv);\n        if (d < -1e-12) {\n            apply_proxy(j, typ, newv);\n        }\n    }\n\n    /*------------------------------------------------------------\n        Phase 2 : simulation + SA with proxy-guided neighbours\n      ------------------------------------------------------------*/\n    vector<array<uint8_t,2>> nxt(N);\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = (uint8_t)b[i];\n        nxt[i][1] = (uint8_t)a[i];\n    }\n\n    vector<int> simCnt(N);\n    auto simulate_fill = [&]() -> int {\n        fill(simCnt.begin(), simCnt.end(), 0);\n        uint8_t cur = 0;\n        simCnt[0] = 1;\n        for (int step = 1; step < L; ++step) {\n            cur = nxt[cur][simCnt[cur] & 1];\n            ++simCnt[cur];\n        }\n        int err = 0;\n        for (int i = 0; i < N; ++i) err += abs(simCnt[i] - T[i]);\n        return err;\n    };\n\n    int bestE = simulate_fill();\n    vector<int> bestA = a, bestB = b;\n    int curE = bestE;\n\n    vector<int> diff(N);\n    for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n\n    double temp = max(100.0, (double)bestE * 0.2);\n    const double COOL = 0.9995;\n    int iter = 0, lastBestIter = 0;\n\n    auto curTime = [&]() {\n        return (double)clock() / (double)CLOCKS_PER_SEC;\n    };\n\n    while (curTime() < 1.85) {\n        ++iter;\n\n        /*--- kick when stuck ------------------------------------*/\n        if (iter - lastBestIter > 150) {\n            a = bestA; b = bestB;\n            fill(in.begin(), in.end(), 0.0);\n            for (int j = 0; j < N; ++j) {\n                in[a[j]] += p[j] * 0.5;\n                in[b[j]] += p[j] * 0.5;\n            }\n            for (int k = 0; k < 5; ++k) {\n                int jj = (int)(rng() % N);\n                int tt = (int)(rng() % 2);\n                int nv = (int)(rng() % N);\n                apply_proxy(jj, tt, nv);\n            }\n            for (int i = 0; i < N; ++i) {\n                nxt[i][0] = (uint8_t)b[i];\n                nxt[i][1] = (uint8_t)a[i];\n            }\n            curE = simulate_fill();\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n            if (curE < bestE) {\n                bestE = curE;\n                bestA = a; bestB = b;\n                lastBestIter = iter;\n            }\n            temp = max(100.0, (double)curE * 0.2);\n            continue;\n        }\n\n        /*--- choose a neighbour ---------------------------------*/\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int oldv = typ ? b[j] : a[j];\n        int newv = oldv;\n\n        int mode = (int)(rng() % 4);\n        if (mode < 2) {                     // exploitation : best proxy\n            double bestD = 1e100;\n            for (int v = 0; v < N; ++v) {\n                if (v == oldv) continue;\n                double d = proxy_delta(j, typ, v);\n                if (d < bestD) {\n                    bestD = d;\n                    newv = v;\n                }\n            }\n            if (newv == oldv) continue;\n        } else if (mode == 2) {             // pure random\n            newv = (int)(rng() % N);\n            if (newv == oldv) continue;\n        } else {                            // targeted by diff\n            vector<int> over, under;\n            for (int i = 0; i < N; ++i) {\n                if (diff[i] > 0) over.push_back(i);\n                else if (diff[i] < 0) under.push_back(i);\n            }\n            if (over.empty() || under.empty()) {\n                newv = (int)(rng() % N);\n                if (newv == oldv) continue;\n            } else {\n                int to = over[(int)(rng() % over.size())];\n                vector<pair<int,int>> preds;\n                for (int x = 0; x < N; ++x) {\n                    if (a[x] == to) preds.emplace_back(x, 0);\n                    if (b[x] == to) preds.emplace_back(x, 1);\n                }\n                if (preds.empty()) {\n                    newv = (int)(rng() % N);\n                    if (newv == oldv) continue;\n                } else {\n                    auto pr = preds[(int)(rng() % preds.size())];\n                    j = pr.first;\n                    typ = pr.second;\n                    oldv = typ ? b[j] : a[j];\n                    newv = under[(int)(rng() % under.size())];\n                    if (newv == oldv) continue;\n                }\n            }\n        }\n\n        /*--- apply and simulate ---------------------------------*/\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ == 0) {\n            a[j] = newv;\n            nxt[j][1] = (uint8_t)newv;\n        } else {\n            b[j] = newv;\n            nxt[j][0] = (uint8_t)newv;\n        }\n\n        int newE = simulate_fill();\n        bool accept = false;\n\n        if (newE < bestE) {\n            bestE = newE;\n            bestA = a; bestB = b;\n            lastBestIter = iter;\n            accept = true;\n        }\n        if (!accept) {\n            int dE = newE - curE;\n            if (dE <= 0) {\n                accept = true;\n            } else {\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < exp(-dE / temp)) accept = true;\n            }\n        }\n\n        if (accept) {\n            curE = newE;\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n        } else {\n            // revert\n            in[newv] -= p[j] * 0.5;\n            in[oldv] += p[j] * 0.5;\n            if (typ == 0) {\n                a[j] = oldv;\n                nxt[j][1] = (uint8_t)oldv;\n            } else {\n                b[j] = oldv;\n                nxt[j][0] = (uint8_t)oldv;\n            }\n        }\n        temp *= COOL;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n/* ---------- Morton key for 2\u2011D locality ---------- */\nstatic uint64_t expand_bits(uint32_t x) {\n    uint64_t z = 0;\n    for (int i = 0; i < 15; ++i)                 // x \u2264 20000 < 2^15\n        z |= ((uint64_t)((x >> i) & 1U)) << (2 * i);\n    return z;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    /* estimated centres */\n    vector<double> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) * 0.5;\n        cy[i] = (ly[i] + ry[i]) * 0.5;\n    }\n\n    /* estimated distances */\n    vector<vector<double>> est(N, vector<double>(N));\n    for (int i = 0; i < N; ++i) {\n        est[i][i] = 0.0;\n        for (int j = i + 1; j < N; ++j) {\n            double dx = cx[i] - cx[j];\n            double dy = cy[i] - cy[j];\n            double d = sqrt(dx * dx + dy * dy);\n            est[i][j] = est[j][i] = d;\n        }\n    }\n\n    auto morton = [&](int v) -> uint64_t {\n        uint32_t x = (uint32_t)(lx[v] + rx[v]);\n        uint32_t y = (uint32_t)(ly[v] + ry[v]);\n        return expand_bits(x) | (expand_bits(y) << 1);\n    };\n\n    /* -------------------------------------------------\n       4. build a compact partition\n       ------------------------------------------------- */\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) {\n             if (G[a] != G[b]) return G[a] > G[b];\n             return a < b;\n         });\n\n    vector<vector<int>> group_nodes(M);\n    vector<char> assigned(N, 0);\n    vector<int> unassigned;\n    unassigned.reserve(N);\n    for (int i = 0; i < N; ++i) unassigned.push_back(i);\n\n    auto mst_cost = [&](const vector<int> &nodes) -> double {\n        int g = (int)nodes.size();\n        if (g <= 1) return 0.0;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        double total = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            total += mincost[v];\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) mincost[i] = d;\n            }\n        }\n        return total;\n    };\n\n    /* large groups (size >= 3) */\n    for (int idx : order) {\n        int g = G[idx];\n        if (g < 3) continue;\n        int U = (int)unassigned.size();\n        int K = min(20, U);\n        vector<int> best_cluster;\n        double best_cost = 1e100;\n        for (int s = 0; s < K; ++s) {\n            int seed = unassigned[s * U / K];\n            vector<int> cluster;\n            cluster.reserve(g);\n            cluster.push_back(seed);\n            vector<char> in_cluster(N, 0);\n            in_cluster[seed] = 1;\n            vector<double> d(N, 1e100);\n            for (int v : unassigned) if (v != seed) d[v] = est[seed][v];\n            while ((int)cluster.size() < g) {\n                int best_u = -1;\n                double best_du = 1e100;\n                for (int v : unassigned) {\n                    if (in_cluster[v]) continue;\n                    if (d[v] < best_du) {\n                        best_du = d[v];\n                        best_u = v;\n                    }\n                }\n                cluster.push_back(best_u);\n                in_cluster[best_u] = 1;\n                for (int v : unassigned) if (!in_cluster[v]) {\n                    double nd = est[best_u][v];\n                    if (nd < d[v]) d[v] = nd;\n                }\n            }\n            double cost = mst_cost(cluster);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_cluster = move(cluster);\n            }\n        }\n        group_nodes[idx] = best_cluster;\n        for (int v : best_cluster) assigned[v] = 1;\n        vector<int> nxt;\n        nxt.reserve(unassigned.size() - g);\n        for (int v : unassigned) if (!assigned[v]) nxt.push_back(v);\n        unassigned.swap(nxt);\n    }\n\n    /* pairs (size == 2) */\n    vector<int> pair_idx;\n    for (int idx : order) if (G[idx] == 2) pair_idx.push_back(idx);\n    for (int idx : pair_idx) {\n        int U = (int)unassigned.size();\n        double best_d = 1e100;\n        int best_a = -1, best_b = -1;\n        for (int i = 0; i < U; ++i)\n            for (int j = i + 1; j < U; ++j) {\n                double d = est[unassigned[i]][unassigned[j]];\n                if (d < best_d) {\n                    best_d = d;\n                    best_a = i;\n                    best_b = j;\n                }\n            }\n        int a = unassigned[best_a];\n        int b = unassigned[best_b];\n        group_nodes[idx] = {a, b};\n        assigned[a] = assigned[b] = 1;\n        vector<int> nxt;\n        nxt.reserve(U - 2);\n        for (int i = 0; i < U; ++i)\n            if (i != best_a && i != best_b) nxt.push_back(unassigned[i]);\n        unassigned.swap(nxt);\n    }\n\n    /* singles (size == 1) */\n    vector<int> single_idx;\n    for (int idx : order) if (G[idx] == 1) single_idx.push_back(idx);\n    for (int idx : single_idx) {\n        int v = unassigned.back(); unassigned.pop_back();\n        group_nodes[idx] = {v};\n        assigned[v] = 1;\n    }\n\n    /* -------------------------------------------------\n       5. query allocation\n       ------------------------------------------------- */\n    vector<int> alloc(M, 0);\n    int sum_alloc = 0;\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (g > L) alloc[k] = (g - 1 + L - 2) / (L - 1);   // ceil((g-1)/(L-1))\n        else if (g >= 3) alloc[k] = 1;\n        else alloc[k] = 0;\n        sum_alloc += alloc[k];\n    }\n    int surplus = Q - sum_alloc;\n    if (surplus > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) if (G[k] > L) large.push_back(k);\n        sort(large.begin(), large.end(),\n             [&](int a, int b) { return G[a] > G[b]; });\n        while (surplus > 0) {\n            bool changed = false;\n            for (int k : large) {\n                int max_q = G[k] - L + 1;\n                if (alloc[k] < max_q) {\n                    ++alloc[k];\n                    --surplus;\n                    changed = true;\n                    if (surplus == 0) break;\n                }\n            }\n            if (!changed) break;\n        }\n    }\n\n    /* helper: reorder a group by a DFS walk of its estimated MST */\n    auto mst_order = [&](const vector<int> &nodes) -> vector<int> {\n        int g = (int)nodes.size();\n        if (g <= 1) return nodes;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<int> parent(g, -1);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) {\n                    mincost[i] = d;\n                    parent[i] = v;\n                }\n            }\n        }\n        vector<vector<int>> adj(g);\n        for (int i = 1; i < g; ++i) {\n            adj[i].push_back(parent[i]);\n            adj[parent[i]].push_back(i);\n        }\n        vector<int> ord;\n        ord.reserve(g);\n        stack<int> st;\n        st.push(0);\n        vector<char> vis(g, 0);\n        vis[0] = 1;\n        while (!st.empty()) {\n            int u = st.top(); st.pop();\n            ord.push_back(nodes[u]);\n            for (int v : adj[u]) if (!vis[v]) {\n                vis[v] = 1;\n                st.push(v);\n            }\n        }\n        return ord;\n    };\n\n    /* -------------------------------------------------\n       6. perform queries\n       ------------------------------------------------- */\n    vector<vector<pair<int,int>>> raw_edges(M);\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (alloc[k] == 0) continue;\n        auto &nodes = group_nodes[k];\n        if (g > L) {\n            nodes = mst_order(nodes);               // locality ordering\n            int q = alloc[k];\n            for (int i = 0; i < q; ++i) {\n                int start = (int)((long long)i * (g - L) / (q - 1));\n                cout << \"? \" << L;\n                for (int j = 0; j < L; ++j) cout << ' ' << nodes[start + j];\n                cout << '\\n' << flush;\n                for (int j = 0; j < L - 1; ++j) {\n                    int a, b;  cin >> a >> b;\n                    raw_edges[k].push_back({a, b});\n                }\n            }\n        } else {\n            // 3 <= g <= L\n            cout << \"? \" << g;\n            for (int v : nodes) cout << ' ' << v;\n            cout << '\\n' << flush;\n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;  cin >> a >> b;\n                raw_edges[k].push_back({a, b});\n            }\n        }\n    }\n\n    /* -------------------------------------------------\n       7. output answer\n       ------------------------------------------------- */\n    cout << \"!\\n\";\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        const auto &nodes = group_nodes[k];\n        for (int i = 0; i < g; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n\n        if (g <= 1) {\n            continue;\n        } else if (g == 2) {\n            cout << nodes[0] << ' ' << nodes[1] << '\\n';\n        } else if (g <= L) {\n            for (auto &e : raw_edges[k])\n                cout << e.first << ' ' << e.second << '\\n';\n        } else {\n            // build graph from queried edges\n            vector<int> pos(N, -1);\n            for (int i = 0; i < g; ++i) pos[nodes[i]] = i;\n            vector<vector<int>> adj(g);\n            set<pair<int,int>> seen;\n            for (auto &e : raw_edges[k]) {\n                int u = e.first, v = e.second;\n                if (u > v) swap(u, v);\n                if (!seen.insert({u, v}).second) continue;\n                int iu = pos[u], iv = pos[v];\n                if (iu == -1 || iv == -1) continue;\n                adj[iu].push_back(iv);\n                adj[iv].push_back(iu);\n            }\n            vector<char> vis(g, 0);\n            vector<pair<int,int>> tree;\n            stack<int> st;\n            st.push(0);  vis[0] = 1;\n            while (!st.empty()) {\n                int u = st.top(); st.pop();\n                for (int v : adj[u]) if (!vis[v]) {\n                    vis[v] = 1;\n                    tree.push_back({nodes[u], nodes[v]});\n                    st.push(v);\n                }\n            }\n            if ((int)tree.size() != g - 1) {\n                // fallback: estimated MST\n                tree.clear();\n                const double INF = 1e100;\n                vector<double> mincost(g, INF);\n                vector<int> parent(g, -1);\n                vector<char> used(g, 0);\n                mincost[0] = 0.0;\n                for (int it = 0; it < g; ++it) {\n                    int v = -1;\n                    for (int i = 0; i < g; ++i)\n                        if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n                    used[v] = 1;\n                    if (parent[v] != -1)\n                        tree.push_back({nodes[parent[v]], nodes[v]});\n                    for (int i = 0; i < g; ++i) if (!used[i]) {\n                        double d = est[nodes[v]][nodes[i]];\n                        if (d < mincost[i]) {\n                            mincost[i] = d;\n                            parent[i] = v;\n                        }\n                    }\n                }\n            }\n            for (auto &e : tree)\n                cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\nconst int MAXN = 20;\n\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dname[4] = {'U', 'D', 'L', 'R'};\n\ninline int opp(int d) { return d ^ 1; }\n\nint N, M;\nvector<pair<int,int>> pts;\nvector<vector<bool>> blocks;\nvector<pair<char,char>> ans;\n\n// BFS on (r,c) graph with Move and Slide edges.\n// Fills dist, parent, action, dir.\n// If stop_at_goal, returns distance to goal as soon as it is reached.\nint bfs(int sr, int sc, int gr, int gc,\n        const vector<vector<bool>>& blk,\n        array<array<int,MAXN>,MAXN>& dist,\n        array<array<pair<int,int>,MAXN>,MAXN>& par,\n        array<array<char,MAXN>,MAXN>& act,\n        array<array<char,MAXN>,MAXN>& dirc,\n        bool stop_at_goal)\n{\n    for (int i=0;i<N;i++) for(int j=0;j<N;j++) dist[i][j] = INF;\n    queue<pair<int,int>> q;\n    dist[sr][sc] = 0;\n    par[sr][sc] = {-1,-1};\n    act[sr][sc] = 0;\n    dirc[sr][sc] = 0;\n    q.push({sr,sc});\n    \n    while(!q.empty()){\n        auto [r,c] = q.front(); q.pop();\n        if(stop_at_goal && r==gr && c==gc) return dist[r][c];\n        \n        // Move edges\n        for(int d=0;d<4;d++){\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            if(nr<0 || nr>=N || nc<0 || nc>=N) continue;\n            if(blk[nr][nc]) continue;\n            if(dist[nr][nc] > dist[r][c] + 1){\n                dist[nr][nc] = dist[r][c] + 1;\n                par[nr][nc] = {r,c};\n                act[nr][nc] = 'M';\n                dirc[nr][nc] = dname[d];\n                q.push({nr,nc});\n            }\n        }\n        \n        // Slide edges\n        for(int d=0;d<4;d++){\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            while(nr>=0 && nr<N && nc>=0 && nc<N && !blk[nr][nc]){\n                nr += dr[d];\n                nc += dc[d];\n            }\n            int tr = nr - dr[d];\n            int tc = nc - dc[d];\n            if(tr==r && tc==c) continue; // adjacent block, no movement\n            if(dist[tr][tc] > dist[r][c] + 1){\n                dist[tr][tc] = dist[r][c] + 1;\n                par[tr][tc] = {r,c};\n                act[tr][tc] = 'S';\n                dirc[tr][tc] = dname[d];\n                q.push({tr,tc});\n            }\n        }\n    }\n    return INF;\n}\n\n// Reconstruct action sequence from start to goal using BFS parent tables.\nvector<pair<char,char>> reconstruct(int sr, int sc, int gr, int gc,\n                                    const array<array<pair<int,int>,MAXN>,MAXN>& par,\n                                    const array<array<char,MAXN>,MAXN>& act,\n                                    const array<array<char,MAXN>,MAXN>& dirc)\n{\n    vector<pair<char,char>> res;\n    int r=gr, c=gc;\n    while(r!=sr || c!=sc){\n        res.push_back({act[r][c], dirc[r][c]});\n        auto [pr,pc] = par[r][c];\n        r = pr; c = pc;\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    if(!(cin>>N>>M)) return 0;\n    pts.resize(M);\n    for(int i=0;i<M;i++) cin>>pts[i].first>>pts[i].second;\n    \n    blocks.assign(N, vector<bool>(N, false));\n    ans.clear();\n    \n    // Precompute target set for quick lookup\n    // We need to know if a cell is a future target.\n    auto is_future_target = [&](int r, int c, int idx)->bool{\n        for(int k=idx;k<M;k++){\n            if(pts[k].first==r && pts[k].second==c) return true;\n        }\n        return false;\n    };\n    \n    int cur_r = pts[0].first;\n    int cur_c = pts[0].second;\n    \n    for(int t=1; t<M; t++){\n        int tr = pts[t].first;\n        int tc = pts[t].second;\n        \n        // Baseline BFS with current blocks\n        array<array<int,MAXN>,MAXN> dist1;\n        array<array<pair<int,int>,MAXN>,MAXN> par1;\n        array<array<char,MAXN>,MAXN> act1, dirc1;\n        int base_cost = bfs(cur_r, cur_c, tr, tc, blocks, dist1, par1, act1, dirc1, true);\n        \n        vector<pair<char,char>> best_path;\n        int best_cost = base_cost;\n        bool use_candidate = false;\n        int best_sr=-1, best_sc=-1;\n        int best_pr=-1, best_pc=-1;\n        char best_alter_dir = 0;\n        \n        if(base_cost < INF){\n            best_path = reconstruct(cur_r, cur_c, tr, tc, par1, act1, dirc1);\n        }\n        \n        // Try placing a stopper in each direction to enable a final slide into target\n        for(int d=0; d<4; d++){\n            int ar = tr + dr[opp(d)];\n            int ac = tc + dc[opp(d)];\n            if(ar<0 || ar>=N || ac<0 || ac>=N) continue; // approach cell out of bounds\n            if(blocks[ar][ac]) continue; // approach cell blocked, can't slide from here\n            \n            int sr = tr + dr[d];\n            int sc = tc + dc[d];\n            bool stopper_exists = false;\n            if(sr<0 || sr>=N || sc<0 || sc>=N) stopper_exists = true;\n            else if(blocks[sr][sc]) stopper_exists = true;\n            \n            if(stopper_exists) continue; // already handled by baseline BFS\n            \n            // Do not permanently block a future target\n            if(is_future_target(sr, sc, t)) continue;\n            \n            // Try each neighbor P of (sr,sc) as the cell from which we Alter\n            for(int pd=0; pd<4; pd++){\n                int pr = sr + dr[pd];\n                int pc = sc + dc[pd];\n                if(pr<0 || pr>=N || pc<0 || pc>=N) continue;\n                if(pr==tr && pc==tc) continue; // can't stand on target to place block\n                if(dist1[pr][pc] >= INF) continue; // unreachable in current grid\n                \n                // Create temporary block map with new stopper\n                vector<vector<bool>> blk2 = blocks;\n                blk2[sr][sc] = true;\n                \n                array<array<int,MAXN>,MAXN> dist2;\n                array<array<pair<int,int>,MAXN>,MAXN> par2;\n                array<array<char,MAXN>,MAXN> act2, dirc2;\n                int d2 = bfs(pr, pc, tr, tc, blk2, dist2, par2, act2, dirc2, true);\n                if(d2 >= INF) continue;\n                \n                int cost = dist1[pr][pc] + 1 + d2;\n                if(cost < best_cost){\n                    best_cost = cost;\n                    use_candidate = true;\n                    best_sr = sr; best_sc = sc;\n                    best_pr = pr; best_pc = pc;\n                    // direction from P to stopper is opposite of pd\n                    best_alter_dir = dname[opp(pd)];\n                }\n            }\n        }\n        \n        if(use_candidate){\n            // Reconstruct path S -> P\n            best_path = reconstruct(cur_r, cur_c, best_pr, best_pc, par1, act1, dirc1);\n            // Alter action\n            best_path.push_back({'A', best_alter_dir});\n            // Reconstruct path P -> T with the extra block\n            vector<vector<bool>> blk2 = blocks;\n            blk2[best_sr][best_sc] = true;\n            array<array<int,MAXN>,MAXN> dist2;\n            array<array<pair<int,int>,MAXN>,MAXN> par2;\n            array<array<char,MAXN>,MAXN> act2, dirc2;\n            bfs(best_pr, best_pc, tr, tc, blk2, dist2, par2, act2, dirc2, true);\n            auto path2 = reconstruct(best_pr, best_pc, tr, tc, par2, act2, dirc2);\n            best_path.insert(best_path.end(), path2.begin(), path2.end());\n            \n            // Permanently place the stopper\n            blocks[best_sr][best_sc] = true;\n        }\n        // else baseline path is already in best_path\n        \n        // Append to global answer\n        for(auto &ac : best_path){\n            ans.push_back(ac);\n        }\n        \n        cur_r = tr;\n        cur_c = tc;\n    }\n    \n    // Output\n    for(auto &ac : ans){\n        cout << ac.first << ' ' << ac.second << \"\\n\";\n    }\n    \n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nint n;\nvector<int> X, Y, desiredR;\nvector<int> a, b, c, d;\nvector<ll> area;\nvector<double> pval;\ndouble cur_score = 0.0;\ndouble best_score = -1.0;\nvector<int> best_a, best_b, best_c, best_d;\n\nchrono::steady_clock::time_point g_start;\n\ninline double calc_p(int idx, ll s) {\n    if (s <= 0) return 0.0;\n    double t = (s < desiredR[idx]) ? (double)s / desiredR[idx] : (double)desiredR[idx] / s;\n    return 1.0 - (1.0 - t) * (1.0 - t);\n}\n\npair<int,int> get_range(int i, int side) {\n    int Lo = 0, Hi = 10000;\n    if (side == 0) {\n        Lo = 0;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) Lo = max(Lo, c[j]);\n        }\n        Hi = X[i];\n    } else if (side == 1) {\n        Lo = X[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) Hi = min(Hi, a[j]);\n        }\n    } else if (side == 2) {\n        Lo = 0;\n        Hi = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) Lo = max(Lo, d[j]);\n        }\n    } else {\n        Lo = Y[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) Hi = min(Hi, b[j]);\n        }\n    }\n    return {Lo, Hi};\n}\n\npair<int,int> get_range_ignore(int i, int side, int ign) {\n    int Lo = 0, Hi = 10000;\n    if (side == 0) {\n        Lo = 0;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) Lo = max(Lo, c[j]);\n        }\n        Hi = X[i];\n    } else if (side == 1) {\n        Lo = X[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) Hi = min(Hi, a[j]);\n        }\n    } else if (side == 2) {\n        Lo = 0;\n        Hi = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) Lo = max(Lo, d[j]);\n        }\n    } else {\n        Lo = Y[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) Hi = min(Hi, b[j]);\n        }\n    }\n    return {Lo, Hi};\n}\n\ninline int get_cur(int i, int side) {\n    return side == 0 ? a[i] : (side == 1 ? c[i] : (side == 2 ? b[i] : d[i]));\n}\n\ninline int get_opt1d(int i, int side, int Lo, int Hi) {\n    int opt;\n    if (side == 0) {\n        ll h = d[i] - b[i];\n        int w = max(1, (int)round((double)desiredR[i] / (double)h));\n        opt = c[i] - w;\n    } else if (side == 1) {\n        ll h = d[i] - b[i];\n        int w = max(1, (int)round((double)desiredR[i] / (double)h));\n        opt = a[i] + w;\n    } else if (side == 2) {\n        ll w = c[i] - a[i];\n        int h = max(1, (int)round((double)desiredR[i] / (double)w));\n        opt = d[i] - h;\n    } else {\n        ll w = c[i] - a[i];\n        int h = max(1, (int)round((double)desiredR[i] / (double)w));\n        opt = b[i] + h;\n    }\n    if (opt < Lo) opt = Lo;\n    if (opt > Hi) opt = Hi;\n    return opt;\n}\n\ninline void apply_single(int i, int side, int v) {\n    if (side == 0) a[i] = v;\n    else if (side == 1) c[i] = v;\n    else if (side == 2) b[i] = v;\n    else d[i] = v;\n    ll na = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np;\n    area[i] = na;\n}\n\nvoid save_best() {\n    if (cur_score > best_score) {\n        best_score = cur_score;\n        best_a = a; best_b = b; best_c = c; best_d = d;\n    }\n}\n\nvoid restore_best() {\n    a = best_a; b = best_b; c = best_c; d = best_d;\n    cur_score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        area[i] = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n        pval[i] = calc_p(i, area[i]);\n        cur_score += pval[i];\n    }\n}\n\nvoid reset_1x1() {\n    for (int i = 0; i < n; ++i) {\n        a[i] = X[i]; b[i] = Y[i]; c[i] = X[i] + 1; d[i] = Y[i] + 1;\n        area[i] = 1;\n        pval[i] = calc_p(i, 1);\n    }\n    cur_score = 0.0;\n    for (int i = 0; i < n; ++i) cur_score += pval[i];\n}\n\nvoid greedy_single_pass(mt19937_64& rng) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    shuffle(ord.begin(), ord.end(), rng);\n    for (int i : ord) {\n        double best_delta = 1e-12;\n        int best_side = -1, best_v = -1;\n        for (int side = 0; side < 4; ++side) {\n            auto [Lo, Hi] = get_range(i, side);\n            int cur = get_cur(i, side);\n            int opt = get_opt1d(i, side, Lo, Hi);\n            if (opt == cur) continue;\n            ll na;\n            if (side == 0) na = 1LL * (c[i] - opt) * (d[i] - b[i]);\n            else if (side == 1) na = 1LL * (opt - a[i]) * (d[i] - b[i]);\n            else if (side == 2) na = 1LL * (c[i] - a[i]) * (d[i] - opt);\n            else na = 1LL * (c[i] - a[i]) * (opt - b[i]);\n            double np = calc_p(i, na);\n            double delta = np - pval[i];\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_side = side;\n                best_v = opt;\n            }\n        }\n        if (best_side != -1) apply_single(i, best_side, best_v);\n    }\n}\n\nvoid greedy_init(mt19937_64& rng) {\n    for (int pass = 0; pass < 100; ++pass) {\n        double old = cur_score;\n        greedy_single_pass(rng);\n        if (cur_score <= old + 1e-9) break;\n    }\n}\n\nint find_neighbor(int i, int dir) {\n    int best = -1;\n    int best_gap = 100000;\n    for (int j = 0; j < n; ++j) if (j != i) {\n        bool xov = (a[j] < c[i] && c[j] > a[i]);\n        bool yov = (b[j] < d[i] && d[j] > b[i]);\n        if (dir == 0 && yov && c[j] <= a[i]) {\n            int gap = a[i] - c[j];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 1 && yov && a[j] >= c[i]) {\n            int gap = a[j] - c[i];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 2 && xov && d[j] <= b[i]) {\n            int gap = b[i] - d[j];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 3 && xov && b[j] >= d[i]) {\n            int gap = b[j] - d[i];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        }\n    }\n    return (best_gap == 0) ? best : -1;\n}\n\ntuple<double,int> eval_pair_wall(int i, int dir, int j) {\n    int Lo, Hi;\n    if (dir == 0) {\n        auto r1 = get_range_ignore(i, 0, j);\n        auto r2 = get_range_ignore(j, 1, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else if (dir == 1) {\n        auto r1 = get_range_ignore(i, 1, j);\n        auto r2 = get_range_ignore(j, 0, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else if (dir == 2) {\n        auto r1 = get_range_ignore(i, 2, j);\n        auto r2 = get_range_ignore(j, 3, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else {\n        auto r1 = get_range_ignore(i, 3, j);\n        auto r2 = get_range_ignore(j, 2, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    }\n    if (Lo > Hi) return {-1.0, Lo};\n    vector<int> cand = {Lo, Hi};\n    if (dir <= 1) {\n        int x1 = a[i] + (int)round((double)desiredR[i] / (double)(d[i] - b[i]));\n        int x2 = c[j] - (int)round((double)desiredR[j] / (double)(d[j] - b[j]));\n        cand.push_back(clamp(x1, Lo, Hi));\n        cand.push_back(clamp(x2, Lo, Hi));\n        cand.push_back((Lo + Hi) / 2);\n    } else {\n        int y1 = b[i] + (int)round((double)desiredR[i] / (double)(c[i] - a[i]));\n        int y2 = d[j] - (int)round((double)desiredR[j] / (double)(c[j] - a[j]));\n        cand.push_back(clamp(y1, Lo, Hi));\n        cand.push_back(clamp(y2, Lo, Hi));\n        cand.push_back((Lo + Hi) / 2);\n    }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    double best_sc = -1e300;\n    int best_coord = Lo;\n    for (int v : cand) {\n        double g = 0.0;\n        if (dir <= 1) {\n            ll ai = 1LL * ((dir==0 ? (c[i]-v) : (v-a[i]))) * (d[i]-b[i]);\n            ll aj = 1LL * ((dir==0 ? (v-a[j]) : (c[j]-v))) * (d[j]-b[j]);\n            g = calc_p(i, ai) + calc_p(j, aj);\n        } else {\n            ll ai = 1LL * (c[i]-a[i]) * ((dir==2 ? (d[i]-v) : (v-b[i])));\n            ll aj = 1LL * (c[j]-a[j]) * ((dir==2 ? (v-b[j]) : (d[j]-v)));\n            g = calc_p(i, ai) + calc_p(j, aj);\n        }\n        if (g > best_sc) {\n            best_sc = g;\n            best_coord = v;\n        }\n    }\n    double delta = best_sc - (pval[i] + pval[j]);\n    return {delta, best_coord};\n}\n\ninline void apply_pair_wall(int i, int dir, int j, int v) {\n    if (dir == 0) { a[i] = v; c[j] = v; }\n    else if (dir == 1) { c[i] = v; a[j] = v; }\n    else if (dir == 2) { b[i] = v; d[j] = v; }\n    else { d[i] = v; b[j] = v; }\n    ll na = 1LL * (c[i]-a[i]) * (d[i]-b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np; area[i] = na;\n    ll na2 = 1LL * (c[j]-a[j]) * (d[j]-b[j]);\n    double np2 = calc_p(j, na2);\n    cur_score += np2 - pval[j];\n    pval[j] = np2; area[j] = na2;\n}\n\nvoid greedy_pair_pass(mt19937_64& rng) {\n    vector<pair<int,int>> vec;\n    for (int i = 0; i < n; ++i) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int j = find_neighbor(i, dir);\n            if (j >= 0) vec.emplace_back(i, dir);\n        }\n    }\n    shuffle(vec.begin(), vec.end(), rng);\n    for (auto [i, dir] : vec) {\n        int j = find_neighbor(i, dir);\n        if (j < 0) continue;\n        auto [delta, v] = eval_pair_wall(i, dir, j);\n        if (delta > 1e-12) apply_pair_wall(i, dir, j, v);\n    }\n}\n\nvoid run_sa(mt19937_64& rng, double time_limit) {\n    uniform_real_distribution<double> dist01(0.0, 1.0);\n    long long iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 2047) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - g_start).count();\n            if (elapsed > time_limit) break;\n        }\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - g_start).count();\n        double T = 0.08 * pow(1e-5 / 0.08, elapsed / time_limit);\n\n        int i;\n        if (dist01(rng) < 0.25) {\n            vector<int> low;\n            for (int k = 0; k < n; ++k) if (pval[k] < 0.95) low.push_back(k);\n            if (low.empty()) i = (int)(rng() % n);\n            else i = low[(int)(rng() % low.size())];\n        } else {\n            i = (int)(rng() % n);\n        }\n\n        if ((int)(rng() % 100) < 75) {\n            int side = (int)(rng() % 4);\n            auto [Lo, Hi] = get_range(i, side);\n            if (Lo >= Hi) continue;\n            int cur = get_cur(i, side);\n            int opt = get_opt1d(i, side, Lo, Hi);\n            int nv;\n            double r = dist01(rng);\n            if (r < 0.5) nv = opt;\n            else if (r < 0.8) {\n                int delta = (int)(dist01(rng) * 201) - 100;\n                nv = opt + delta;\n            } else {\n                nv = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n            }\n            if (nv < Lo) nv = Lo;\n            if (nv > Hi) nv = Hi;\n            if (nv == cur) continue;\n            ll na;\n            if (side == 0) na = 1LL * (c[i] - nv) * (d[i] - b[i]);\n            else if (side == 1) na = 1LL * (nv - a[i]) * (d[i] - b[i]);\n            else if (side == 2) na = 1LL * (c[i] - a[i]) * (d[i] - nv);\n            else na = 1LL * (c[i] - a[i]) * (nv - b[i]);\n            double np = calc_p(i, na);\n            double delta = np - pval[i];\n            if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                apply_single(i, side, nv);\n                save_best();\n            }\n        } else {\n            int dir = (int)(rng() % 4);\n            int j = find_neighbor(i, dir);\n            if (j < 0) continue;\n            auto [delta, v] = eval_pair_wall(i, dir, j);\n            if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                apply_pair_wall(i, dir, j, v);\n                save_best();\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n;\n    X.resize(n); Y.resize(n); desiredR.resize(n);\n    for (int i = 0; i < n; ++i) cin >> X[i] >> Y[i] >> desiredR[i];\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n    area.resize(n); pval.resize(n);\n\n    mt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    g_start = chrono::steady_clock::now();\n\n    // --- Multi-start greedy initialization ---\n    best_score = -1.0;\n    for (int trial = 0; trial < 30; ++trial) {\n        reset_1x1();\n        greedy_init(rng);\n        save_best();\n    }\n    restore_best();\n\n    // --- Main SA (single long run) ---\n    run_sa(rng, 4.75);\n    restore_best();\n\n    // --- Final polish ---\n    for (int pass = 0; pass < 100; ++pass) {\n        double old = cur_score;\n        greedy_single_pass(rng);\n        greedy_pair_pass(rng);\n        if (cur_score <= old + 1e-9) break;\n    }\n    save_best();\n    restore_best();\n\n    for (int i = 0; i < n; ++i) {\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    const int H = 50, W = 50, N = 2500;\n    int si, sj;\n    if (!(cin >> si >> sj)) return 0;\n    \n    static int tile[N];\n    static int val[N];\n    int M = 0;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int x; cin >> x;\n            tile[i * W + j] = x;\n            M = max(M, x + 1);\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> val[i * W + j];\n        }\n    }\n    \n    // pre\u2011compute 4 neighbours for every cell (-1 = outside)\n    static int nxt[N][4];\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            nxt[id][0] = (i > 0)     ? id - W : -1; // U\n            nxt[id][1] = (i + 1 < H) ? id + W : -1; // D\n            nxt[id][2] = (j > 0)     ? id - 1 : -1; // L\n            nxt[id][3] = (j + 1 < W) ? id + 1 : -1; // R\n        }\n    }\n    \n    const char dch[4] = {'U', 'D', 'L', 'R'};\n    \n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<char> used(M, 0);\n    string best_path;\n    int best_score = -1;\n    \n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    // fast rollout simulation from `start_pos` assuming its tile is NOT yet marked in `used`\n    auto simulate = [&](int start_pos, vector<char>& used, int mode, mt19937& rng, int max_depth) -> int {\n        int stack[2500];\n        int sp = 0;\n        int t0 = tile[start_pos];\n        if (used[t0]) return -1000000000;\n        used[t0] = 1;\n        stack[sp++] = t0;\n        \n        int cur = start_pos;\n        int gain = 0;\n        int depth = 0;\n        \n        while (true) {\n            if (max_depth >= 0 && depth >= max_depth) break;\n            \n            int best_nxt = -1;\n            int best_pri = -1000000000;\n            \n            for (int d = 0; d < 4; ++d) {\n                int npos = nxt[cur][d];\n                if (npos == -1) continue;\n                int t = tile[npos];\n                if (used[t]) continue;\n                \n                // onward degree of npos\n                int deg = 0;\n                for (int d2 = 0; d2 < 4; ++d2) {\n                    int n2 = nxt[npos][d2];\n                    if (n2 != -1 && !used[tile[n2]]) ++deg;\n                }\n                \n                int pri;\n                if (mode == 0) {               // strongly avoid dead ends\n                    pri = -deg * 1000 + val[npos];\n                } else if (mode == 1) {        // value oriented\n                    pri = val[npos] * 10 - deg;\n                } else {                        // balanced + noise\n                    pri = val[npos] * 5 - deg * 100 + (int)(rng() & 127);\n                }\n                \n                if (pri > best_pri) {\n                    best_pri = pri;\n                    best_nxt = npos;\n                }\n            }\n            \n            if (best_nxt == -1) break;\n            \n            int nt = tile[best_nxt];\n            used[nt] = 1;\n            stack[sp++] = nt;\n            gain += val[best_nxt];\n            cur = best_nxt;\n            ++depth;\n        }\n        \n        while (sp > 0) {\n            used[stack[--sp]] = 0;\n        }\n        return gain;\n    };\n    \n    bool first_iter = true;\n    while (elapsed() < 1.90) {\n        int mode;\n        int noise_range;\n        int max_depth;\n        \n        if (first_iter) {\n            mode = 0;          // deterministic, dead-end avoiding\n            noise_range = 0;\n            max_depth = -1;    // unlimited\n            first_iter = false;\n        } else {\n            mode = (int)(rng() % 3);\n            noise_range = 200;\n            max_depth = -1;\n        }\n        \n        fill(used.begin(), used.end(), 0);\n        int pos = si * W + sj;\n        used[tile[pos]] = 1;\n        int cur_score = val[pos];\n        string path;\n        path.reserve(2500);\n        \n        while (true) {\n            int cand[4];\n            int cand_dir[4];\n            int cand_cnt = 0;\n            for (int d = 0; d < 4; ++d) {\n                int npos = nxt[pos][d];\n                if (npos != -1 && !used[tile[npos]]) {\n                    cand[cand_cnt] = npos;\n                    cand_dir[cand_cnt] = d;\n                    ++cand_cnt;\n                }\n            }\n            if (cand_cnt == 0) break;\n            \n            int best_idx = 0;\n            if (cand_cnt > 1) {\n                int best_eval = -1;\n                for (int i = 0; i < cand_cnt; ++i) {\n                    int future = simulate(cand[i], used, mode, rng, max_depth);\n                    int eval = val[cand[i]] + future;\n                    if (noise_range > 0) eval += (int)(rng() % noise_range);\n                    if (eval > best_eval) {\n                        best_eval = eval;\n                        best_idx = i;\n                    }\n                }\n            }\n            \n            int npos = cand[best_idx];\n            int nd = cand_dir[best_idx];\n            used[tile[npos]] = 1;\n            cur_score += val[npos];\n            path.push_back(dch[nd]);\n            pos = npos;\n        }\n        \n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_path = path;\n        }\n    }\n    \n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitInfo {\n    bool use = false;\n    int s = -1;\n    double ml = 0.0, mr = 0.0;\n    double mean_single = 0.0;\n    bool has_obs = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const double MINW = 1000.0;\n    const double MAXW = 9000.0;\n    const double LR   = 0.5;\n\n    vector<vector<double>> est_h(N, vector<double>(N - 1, 5000.0));\n    vector<vector<double>> est_v(N - 1, vector<double>(N, 5000.0));\n    vector<vector<int>>    cnt_h(N, vector<int>(N - 1, 0));\n    vector<vector<int>>    cnt_v(N - 1, vector<int>(N, 0));\n\n    double global_mean = 5000.0;\n    bool likely_m2 = false;\n\n    for (int query = 0; query < 1000; ++query) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        /* ---- exploration schedule ---- */\n        double explore = 0.0;\n        if      (query < 200) explore = 0.50;\n        else if (query < 400) explore = 0.25;\n        else if (query < 700) explore = 0.10;\n\n        /* ---- helper: fit a row/column with optional split ---- */\n        auto fit_split = [&](const vector<pair<int,double>>& obs) -> SplitInfo {\n            SplitInfo info;\n            int n = (int)obs.size();\n            if (n == 0) return info;\n            info.has_obs = true;\n            double sum = 0.0;\n            for (auto &p : obs) sum += p.second;\n            info.mean_single = sum / n;\n\n            double sse_single = 0.0;\n            for (auto &p : obs) {\n                double d = p.second - info.mean_single;\n                sse_single += d * d;\n            }\n\n            if (n >= 4) {\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl == 0 || cr == 0) continue;\n                    double ml = sl / cl;\n                    double mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse;\n                        best_s = s;\n                        best_ml = ml;\n                        best_mr = mr;\n                    }\n                }\n\n                if (best_s != -1) {\n                    // BIC: split model has 3 params (2 means + shared variance),\n                    //      single model has 2 params (1 mean + variance).\n                    double bic_single = n * log(sse_single / n + 1e-9) + 2.0 * log((double)n);\n                    double bic_split  = n * log(best_sse  / n + 1e-9) + 3.0 * log((double)n);\n                    bool accept = bic_split < bic_single;\n                    // strong override for obvious jumps even if BIC is on the fence\n                    if (!accept && best_sse < sse_single * 0.30) accept = true;\n\n                    if (accept) {\n                        info.use = true;\n                        info.s = best_s;\n                        info.ml = best_ml;\n                        info.mr = best_mr;\n                    }\n                }\n            }\n            return info;\n        };\n\n        /* ---- gather observations and fit rows / columns ---- */\n        vector<SplitInfo> row_info(N);\n        vector<SplitInfo> col_info(N);\n        int strong_split_rows = 0, strong_split_cols = 0;\n\n        for (int i = 0; i < N; ++i) {\n            vector<pair<int,double>> obs;\n            for (int j = 0; j < N - 1; ++j)\n                if (cnt_h[i][j] > 0) obs.emplace_back(j, est_h[i][j]);\n            row_info[i] = fit_split(obs);\n            if (row_info[i].use) ++strong_split_rows;\n        }\n        for (int j = 0; j < N; ++j) {\n            vector<pair<int,double>> obs;\n            for (int i = 0; i < N - 1; ++i)\n                if (cnt_v[i][j] > 0) obs.emplace_back(i, est_v[i][j]);\n            col_info[j] = fit_split(obs);\n            if (col_info[j].use) ++strong_split_cols;\n        }\n\n        // global M=2 detection\n        if (!likely_m2 && (strong_split_rows >= 5 || strong_split_cols >= 5))\n            likely_m2 = true;\n\n        // if M=2 seems likely, re-fit sparse rows/columns with relaxed threshold\n        if (likely_m2) {\n            for (int i = 0; i < N; ++i) {\n                if (row_info[i].use || !row_info[i].has_obs) continue;\n                vector<pair<int,double>> obs;\n                for (int j = 0; j < N - 1; ++j)\n                    if (cnt_h[i][j] > 0) obs.emplace_back(j, est_h[i][j]);\n                int n = (int)obs.size();\n                if (n < 3) continue;\n                // recompute best split with a permissive ratio\n                double sum = 0.0;\n                for (auto &p : obs) sum += p.second;\n                double mean = sum / n;\n                double sse_single = 0.0;\n                for (auto &p : obs) { double d = p.second - mean; sse_single += d*d; }\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl == 0 || cr == 0) continue;\n                    double ml = sl / cl, mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse; best_s = s; best_ml = ml; best_mr = mr;\n                    }\n                }\n                if (best_s != -1 && best_sse < sse_single * 0.50) {\n                    row_info[i].use = true;\n                    row_info[i].s = best_s;\n                    row_info[i].ml = best_ml;\n                    row_info[i].mr = best_mr;\n                }\n            }\n\n            for (int j = 0; j < N; ++j) {\n                if (col_info[j].use || !col_info[j].has_obs) continue;\n                vector<pair<int,double>> obs;\n                for (int i = 0; i < N - 1; ++i)\n                    if (cnt_v[i][j] > 0) obs.emplace_back(i, est_v[i][j]);\n                int n = (int)obs.size();\n                if (n < 3) continue;\n                double sum = 0.0;\n                for (auto &p : obs) sum += p.second;\n                double mean = sum / n;\n                double sse_single = 0.0;\n                for (auto &p : obs) { double d = p.second - mean; sse_single += d*d; }\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl == 0 || cr == 0) continue;\n                    double ml = sl / cl, mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse; best_s = s; best_ml = ml; best_mr = mr;\n                    }\n                }\n                if (best_s != -1 && best_sse < sse_single * 0.50) {\n                    col_info[j].use = true;\n                    col_info[j].s = best_s;\n                    col_info[j].ml = best_ml;\n                    col_info[j].mr = best_mr;\n                }\n            }\n        }\n\n        /* ---- prior accessors (structural, ignoring individual est) ---- */\n        auto prior_h = [&](int i, int j) -> double {\n            const SplitInfo &ri = row_info[i];\n            if (!ri.has_obs) return global_mean;\n            if (ri.use) return (j < ri.s) ? ri.ml : ri.mr;\n            return ri.mean_single;\n        };\n        auto prior_v = [&](int i, int j) -> double {\n            const SplitInfo &ci = col_info[j];\n            if (!ci.has_obs) return global_mean;\n            if (ci.use) return (i < ci.s) ? ci.ml : ci.mr;\n            return ci.mean_single;\n        };\n\n        /* ---- Dijkstra with optimistic exploration ---- */\n        int S = si * N + sj;\n        int T = ti * N + tj;\n        const int V = N * N;\n        const double INF = 1e100;\n\n        vector<double> dist(V, INF);\n        vector<pair<int,char>> prv(V, {-1, 0});\n        using State = pair<double,int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[S] = 0.0;\n        pq.emplace(0.0, S);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d > dist[v] + 1e-9) continue;\n            if (v == T) break;\n            int i = v / N;\n            int j = v % N;\n\n            auto relax = [&](int ni, int nj, bool is_h, int ei, int ej, char dir) {\n                int u = ni * N + nj;\n                double base = is_h ? (cnt_h[ei][ej] > 0 ? est_h[ei][ej] : prior_h(ei, ej))\n                                   : (cnt_v[ei][ej] > 0 ? est_v[ei][ej] : prior_v(ei, ej));\n                int c = is_h ? cnt_h[ei][ej] : cnt_v[ei][ej];\n                double w = base * (1.0 - explore / sqrt((double)c + 1.0));\n                if (w < MINW) w = MINW;\n                if (dist[u] > d + w) {\n                    dist[u] = d + w;\n                    prv[u] = {v, dir};\n                    pq.emplace(dist[u], u);\n                }\n            };\n\n            if (i > 0)     relax(i - 1, j,     false, i - 1, j,     'U');\n            if (i + 1 < N) relax(i + 1, j,     false, i,     j,     'D');\n            if (j > 0)     relax(i,     j - 1, true,  i,     j - 1, 'L');\n            if (j + 1 < N) relax(i,     j + 1, true,  i,     j,     'R');\n        }\n\n        /* ---- reconstruct path ---- */\n        string path;\n        int cur = T;\n        while (cur != S) {\n            auto [p, c] = prv[cur];\n            path.push_back(c);\n            cur = p;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << '\\n' << flush;\n\n        /* ---- read noisy observation ---- */\n        long long y;\n        cin >> y;\n        int L = (int)path.size();\n        if (L == 0) continue;\n\n        /* ---- update global mean ---- */\n        double avg_step = (double)y / (double)L;\n        global_mean = global_mean * 0.95 + avg_step * 0.05;\n        if (global_mean < MINW) global_mean = MINW;\n        if (global_mean > MAXW) global_mean = MAXW;\n\n        /* ---- list edges, init unseen ones to their priors ---- */\n        struct Eref { bool h; int i, j; };\n        vector<Eref> edges;\n        edges.reserve(L);\n        double pred = 0.0;\n        int ci = si, cj = sj;\n\n        for (char c : path) {\n            if (c == 'U') {\n                if (cnt_v[ci-1][cj] == 0) est_v[ci-1][cj] = prior_v(ci-1, cj);\n                pred += est_v[ci-1][cj];\n                edges.push_back({false, ci-1, cj});\n                --ci;\n            } else if (c == 'D') {\n                if (cnt_v[ci][cj] == 0) est_v[ci][cj] = prior_v(ci, cj);\n                pred += est_v[ci][cj];\n                edges.push_back({false, ci, cj});\n                ++ci;\n            } else if (c == 'L') {\n                if (cnt_h[ci][cj-1] == 0) est_h[ci][cj-1] = prior_h(ci, cj-1);\n                pred += est_h[ci][cj-1];\n                edges.push_back({true, ci, cj-1});\n                --cj;\n            } else if (c == 'R') {\n                if (cnt_h[ci][cj] == 0) est_h[ci][cj] = prior_h(ci, cj);\n                pred += est_h[ci][cj];\n                edges.push_back({true, ci, cj});\n                ++cj;\n            }\n        }\n\n        double diff = (double)y - pred;\n        double total_inv = 0.0;\n        for (auto &e : edges) {\n            int c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            total_inv += 1.0 / ((double)c + 1.0);\n        }\n\n        /* ---- weighted LMS update + shrinkage toward structural prior ---- */\n        for (auto &e : edges) {\n            int &c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            double &est = e.h ? est_h[e.i][e.j] : est_v[e.i][e.j];\n            double structural = e.h ? prior_h(e.i, e.j) : prior_v(e.i, e.j);\n\n            double w = (1.0 / ((double)c + 1.0)) / total_inv;\n            est += diff * w * LR;\n\n            // mild shrinkage toward structural prior; fades as count grows\n            double shrink = 0.08 / (1.0 + (double)c / 3.0);\n            est = est * (1.0 - shrink) + structural * shrink;\n\n            if (est < MINW) est = MINW;\n            if (est > MAXW) est = MAXW;\n            ++c;\n        }\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    uint16_t cell[12];\n    uint8_t len;\n};\n\nint N, M;\nvector<string> S;\nvector<Placement> placements;\nvector<int> pid_sid;\nvector<uint8_t> pid_len;\nvector<vector<int>> cell_pids_by_char; // [cell*8 + ch]\nvector<vector<int>> cell_to_pids;      // [cell]\nint P;\n\n// current board state\nvector<uint8_t> board;\nvector<int> pid_match_cnt;\nvector<int> sid_ok;\nint total_matched;\n\nchrono::steady_clock::time_point start_time;\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nconst double UINT_MAX_INV = 1.0 / numeric_limits<uint32_t>::max();\n\n/* ---------- build structures ---------- */\nvoid build_structures() {\n    P = M * 800;\n    placements.resize(P);\n    pid_sid.resize(P);\n    pid_len.resize(P);\n    for (int sid = 0; sid < M; ++sid) {\n        int len = (int)S[sid].size();\n        int base = sid * 800;\n        int idx = 0;\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Placement p;\n                    p.len = (uint8_t)len;\n                    for (int k = 0; k < len; ++k) {\n                        int rr = (dir == 0) ? r : (r + k) % N;\n                        int cc = (dir == 0) ? (c + k) % N : c;\n                        p.cell[k] = (uint16_t)(rr * N + cc);\n                    }\n                    placements[base + idx] = p;\n                    pid_sid[base + idx] = sid;\n                    pid_len[base + idx] = (uint8_t)len;\n                    ++idx;\n                }\n            }\n        }\n    }\n\n    cell_pids_by_char.assign(400 * 8, {});\n    cell_to_pids.assign(400, {});\n    for (int sid = 0; sid < M; ++sid) {\n        int base = sid * 800;\n        for (int k = 0; k < 800; ++k) {\n            int pid = base + k;\n            const Placement &p = placements[pid];\n            for (int i = 0; i < p.len; ++i) {\n                int cell = p.cell[i];\n                int ch = S[sid][i] - 'A';\n                cell_pids_by_char[cell * 8 + ch].push_back(pid);\n                cell_to_pids[cell].push_back(pid);\n            }\n        }\n    }\n\n    board.resize(400);\n    pid_match_cnt.assign(P, 0);\n    sid_ok.assign(M, 0);\n}\n\n/* ---------- greedy initial board ---------- */\nvector<uint8_t> greedy_board() {\n    int cell_cnt[400][8] = {};\n    uint8_t cell_mask[400] = {};\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int sid : order) {\n        int base = sid * 800;\n        int best_k = 0;\n        int best_conf = INT_MAX;\n        int best_cov = INT_MAX;\n        for (int k = 0; k < 800; ++k) {\n            const Placement &p = placements[base + k];\n            int add_conf = 0;\n            int add_cov = 0;\n            for (int i = 0; i < p.len; ++i) {\n                int cell = p.cell[i];\n                int ch = S[sid][i] - 'A';\n                if (cell_mask[cell] == 0) {\n                    ++add_cov;\n                } else if (((cell_mask[cell] >> ch) & 1) == 0) {\n                    ++add_conf;\n                }\n            }\n            if (add_conf < best_conf ||\n                (add_conf == best_conf && add_cov < best_cov) ||\n                (add_conf == best_conf && add_cov == best_cov && (rng() & 1))) {\n                best_conf = add_conf;\n                best_cov = add_cov;\n                best_k = k;\n            }\n        }\n        const Placement &p = placements[base + best_k];\n        for (int i = 0; i < p.len; ++i) {\n            int cell = p.cell[i];\n            int ch = S[sid][i] - 'A';\n            cell_cnt[cell][ch]++;\n            cell_mask[cell] |= (1 << ch);\n        }\n    }\n\n    vector<uint8_t> b(400);\n    for (int cell = 0; cell < 400; ++cell) {\n        int best_ch = 0;\n        for (int ch = 1; ch < 8; ++ch) {\n            if (cell_cnt[cell][ch] > cell_cnt[cell][best_ch]) best_ch = ch;\n        }\n        b[cell] = (uint8_t)best_ch;\n    }\n    return b;\n}\n\n/* ---------- board evaluation from scratch ---------- */\nvoid eval_board(const vector<uint8_t> &b) {\n    board = b;\n    fill(pid_match_cnt.begin(), pid_match_cnt.end(), 0);\n    for (int cell = 0; cell < 400; ++cell) {\n        int ch = board[cell];\n        for (int pid : cell_pids_by_char[cell * 8 + ch]) {\n            ++pid_match_cnt[pid];\n        }\n    }\n    fill(sid_ok.begin(), sid_ok.end(), 0);\n    for (int pid = 0; pid < P; ++pid) {\n        if (pid_match_cnt[pid] == pid_len[pid]) {\n            ++sid_ok[pid_sid[pid]];\n        }\n    }\n    total_matched = 0;\n    for (int i = 0; i < M; ++i)\n        if (sid_ok[i] > 0) ++total_matched;\n}\n\n/* ---------- incremental move ---------- */\ninline void apply_move(int cell, int new_ch) {\n    int old_ch = board[cell];\n    if (old_ch == new_ch) return;\n    board[cell] = (uint8_t)new_ch;\n\n    for (int pid : cell_pids_by_char[cell * 8 + old_ch]) {\n        if (pid_match_cnt[pid] == pid_len[pid]) {\n            int sid = pid_sid[pid];\n            if (--sid_ok[sid] == 0) --total_matched;\n        }\n        --pid_match_cnt[pid];\n    }\n\n    for (int pid : cell_pids_by_char[cell * 8 + new_ch]) {\n        ++pid_match_cnt[pid];\n        if (pid_match_cnt[pid] == pid_len[pid]) {\n            int sid = pid_sid[pid];\n            if (++sid_ok[sid] == 1) ++total_matched;\n        }\n    }\n}\n\n/* ---------- dotting ---------- */\npair<vector<string>, int> dot_board(const vector<uint8_t> &b, double time_limit) {\n    vector<int> pm(P, 0);\n    for (int cell = 0; cell < 400; ++cell) {\n        int ch = b[cell];\n        for (int pid : cell_pids_by_char[cell * 8 + ch]) ++pm[pid];\n    }\n\n    vector<char> pid_alive(P);\n    vector<int> sid_alive_cnt(M);\n    vector<int> sid_cell_ref(M * 400);\n    vector<char> is_dot(400);\n    vector<int> vis_sid(M, 0);\n    int vis_token = 1;\n\n    int best_dots = -1;\n    vector<string> best_ans;\n\n    while (elapsed() < time_limit) {\n        fill(pid_alive.begin(), pid_alive.end(), 0);\n        fill(sid_alive_cnt.begin(), sid_alive_cnt.end(), 0);\n        fill(sid_cell_ref.begin(), sid_cell_ref.end(), 0);\n\n        for (int pid = 0; pid < P; ++pid) {\n            if (pm[pid] == pid_len[pid]) {\n                pid_alive[pid] = 1;\n                int sid = pid_sid[pid];\n                ++sid_alive_cnt[sid];\n                const Placement &p = placements[pid];\n                for (int i = 0; i < p.len; ++i) {\n                    ++sid_cell_ref[sid * 400 + p.cell[i]];\n                }\n            }\n        }\n\n        fill(is_dot.begin(), is_dot.end(), 0);\n        int dots = 0;\n\n        while (true) {\n            vector<int> cells(400);\n            iota(cells.begin(), cells.end(), 0);\n            shuffle(cells.begin(), cells.end(), rng);\n            bool changed = false;\n            for (int x : cells) {\n                if (is_dot[x]) continue;\n                bool ok = true;\n                ++vis_token;\n                for (int pid : cell_to_pids[x]) {\n                    if (!pid_alive[pid]) continue;\n                    int sid = pid_sid[pid];\n                    if (vis_sid[sid] == vis_token) continue;\n                    vis_sid[sid] = vis_token;\n                    if (sid_alive_cnt[sid] == sid_cell_ref[sid * 400 + x]) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n                for (int pid : cell_to_pids[x]) {\n                    if (!pid_alive[pid]) continue;\n                    pid_alive[pid] = 0;\n                    int sid = pid_sid[pid];\n                    --sid_alive_cnt[sid];\n                    const Placement &p = placements[pid];\n                    for (int i = 0; i < p.len; ++i) {\n                        --sid_cell_ref[sid * 400 + p.cell[i]];\n                    }\n                }\n                is_dot[x] = 1;\n                ++dots;\n                changed = true;\n            }\n            if (!changed) break;\n        }\n\n        if (dots > best_dots) {\n            best_dots = dots;\n            vector<string> ans(N, string(N, '.'));\n            for (int cell = 0; cell < 400; ++cell) {\n                if (!is_dot[cell]) {\n                    ans[cell / N][cell % N] = char('A' + b[cell]);\n                }\n            }\n            best_ans = move(ans);\n        }\n    }\n    return {best_ans, best_dots};\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N >> M)) return 0;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    build_structures();\n    start_time = chrono::steady_clock::now();\n\n    int best_dots = -1;\n    vector<string> best_ans;\n    vector<uint8_t> best_board;\n\n    int fallback_matched = -1;\n    vector<uint8_t> fallback_board;\n\n    const double PHASE1_END = 2.7;\n\n    while (elapsed() < PHASE1_END) {\n        vector<uint8_t> b;\n        int r = rng() % 5;\n        if (r == 0) {\n            // random\n            b.resize(400);\n            for (int i = 0; i < 400; ++i) b[i] = (uint8_t)(rng() % 8);\n        } else if (r == 1 && !best_board.empty()) {\n            // perturb best known board\n            b = best_board;\n            for (int i = 0; i < 15; ++i) b[rng() % 400] = (uint8_t)(rng() % 8);\n        } else {\n            b = greedy_board();\n        }\n\n        eval_board(b);\n        if (total_matched > fallback_matched) {\n            fallback_matched = total_matched;\n            fallback_board = board;\n        }\n\n        if (total_matched == M) {\n            auto [ans, d] = dot_board(b, elapsed() + 0.02);\n            if (d > best_dots) {\n                best_dots = d;\n                best_ans = ans;\n                best_board = b;\n            }\n            continue;\n        }\n\n        // SA on board\n        double T = 2.0;\n        int last_best = total_matched;\n        int since_improve = 0;\n        while (elapsed() < PHASE1_END && total_matched < M) {\n            int cell = (int)(rng() % 400);\n            int old_ch = board[cell];\n            int new_ch = (int)(rng() % 8);\n            if (new_ch == old_ch) continue;\n\n            int before = total_matched;\n            apply_move(cell, new_ch);\n            int d = total_matched - before;\n            if (d < 0) {\n                if (rng() * UINT_MAX_INV >= exp(d / T)) {\n                    apply_move(cell, old_ch);\n                }\n            }\n            T *= 0.99995;\n            if (T < 1e-9) T = 1e-9;\n\n            ++since_improve;\n            if (total_matched > last_best) {\n                last_best = total_matched;\n                since_improve = 0;\n            }\n            if (since_improve > 25000) {\n                T = min(T * 2.0, 5.0);\n                since_improve = 0;\n            }\n        }\n\n        if (total_matched > fallback_matched) {\n            fallback_matched = total_matched;\n            fallback_board = board;\n        }\n\n        if (total_matched == M) {\n            auto [ans, d] = dot_board(board, elapsed() + 0.02);\n            if (d > best_dots) {\n                best_dots = d;\n                best_ans = ans;\n                best_board = board;\n            }\n        }\n    }\n\n    if (best_dots >= 0) {\n        double limit = min(2.95, elapsed() + 0.25);\n        auto [ans, d] = dot_board(best_board, limit);\n        if (d > best_dots) {\n            best_dots = d;\n            best_ans = ans;\n        }\n        for (const auto &row : best_ans) cout << row << '\\n';\n    } else {\n        // fallback: output best board found (no dots)\n        vector<string> ans(N, string(N, 'A'));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                ans[i][j] = char('A' + fallback_board[i * N + j]);\n        for (const auto &row : ans) cout << row << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, si, sj;\n    vector<string> g;\n    vector<vector<int>> w;\n    vector<int> ui, uj;\n    vector<vector<int>> adj;\n    vector< bitset<1024> > cellMask;\n    vector<vector<int>> groupCells;\n    int Hreq = 0, Vreq = 0, R = 0, S = -1, V = 0;\n    bitset<1024> allReq;\n    mt19937 rng;\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n    const int INF = 1e9;\n\n    inline int dirMove(int u, int v) const {\n        int i1 = ui[u], j1 = uj[u];\n        int i2 = ui[v], j2 = uj[v];\n        if (i2 == i1 - 1) return 0;\n        if (i2 == i1 + 1) return 1;\n        if (j2 == j1 - 1) return 2;\n        return 3;\n    }\n\n    /* ---------- fast binary heap with decrease-key ---------- */\n    struct IntHeap {\n        vector<int> h;\n        vector<int> *d;\n        vector<int> pos;\n        IntHeap(int n, vector<int> &dist) : d(&dist), pos(n, -1) {}\n        bool empty() const { return h.empty(); }\n        void push(int v) {\n            if (pos[v] == -1) {\n                pos[v] = (int)h.size();\n                h.push_back(v);\n            }\n            siftup(pos[v]);\n        }\n        int pop() {\n            int res = h[0];\n            pos[res] = -1;\n            int v = h.back();\n            h.pop_back();\n            if (!h.empty()) {\n                h[0] = v;\n                pos[v] = 0;\n                siftdown(0);\n            }\n            return res;\n        }\n        void siftup(int i) {\n            int v = h[i];\n            int dv = (*d)[v];\n            while (i > 0) {\n                int p = (i - 1) >> 1;\n                int u = h[p];\n                if ((*d)[u] <= dv) break;\n                h[i] = u; pos[u] = i;\n                i = p;\n            }\n            h[i] = v; pos[v] = i;\n        }\n        void siftdown(int i) {\n            int v = h[i];\n            int dv = (*d)[v];\n            int n = (int)h.size();\n            while (true) {\n                int l = i * 2 + 1;\n                if (l >= n) break;\n                int r = l + 1;\n                int best = l;\n                if (r < n && (*d)[h[r]] < (*d)[h[l]]) best = r;\n                if ((*d)[h[best]] >= dv) break;\n                int u = h[best];\n                h[i] = u; pos[u] = i;\n                i = best;\n            }\n            h[i] = v; pos[v] = i;\n        }\n    };\n\n    void dijkstra(const vector<char> &src, vector<int> &dist,\n                  vector<int> &parent, vector<int> *order = nullptr) {\n        dist.assign(V, INF);\n        parent.assign(V, -1);\n        IntHeap heap(V, dist);\n        for (int u = 0; u < V; ++u) {\n            if (src[u]) {\n                dist[u] = 0;\n                heap.push(u);\n            }\n        }\n        if (order) order->clear();\n        while (!heap.empty()) {\n            int u = heap.pop();\n            if (order) order->push_back(u);\n            int du = dist[u];\n            for (int v : adj[u]) {\n                int nd = du + w[ui[v]][uj[v]];\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parent[v] = u;\n                    heap.push(v);\n                }\n            }\n        }\n    }\n\n    /* ---------- prune a tree given by edges, return cost ---------- */\n    long long pruneAndCost(vector<pair<int,int>> &edges,\n                           bitset<1024> &outCovered) {\n        vector<vector<int>> tAdj(V);\n        for (auto [u,v] : edges) {\n            tAdj[u].push_back(v);\n            tAdj[v].push_back(u);\n        }\n        vector<char> alive(V, 0);\n        vector<int> deg(V, 0);\n        for (int u = 0; u < V; ++u) {\n            int d = (int)tAdj[u].size();\n            if (d > 0) {\n                alive[u] = 1;\n                deg[u] = d;\n            }\n        }\n        vector<int> coverCnt(R, 0);\n        for (int u = 0; u < V; ++u) if (alive[u]) {\n            for (int r = 0; r < R; ++r)\n                if (cellMask[u].test(r)) ++coverCnt[r];\n        }\n        queue<int> q;\n        for (int u = 0; u < V; ++u)\n            if (alive[u] && deg[u] == 1 && u != S) q.push(u);\n\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            if (!alive[u] || deg[u] != 1 || u == S) continue;\n            bool ok = true;\n            for (int r = 0; r < R; ++r) {\n                if (cellMask[u].test(r) && coverCnt[r] <= 1) {\n                    ok = false; break;\n                }\n            }\n            if (!ok) continue;\n            alive[u] = 0;\n            deg[u] = 0;\n            for (int r = 0; r < R; ++r)\n                if (cellMask[u].test(r)) --coverCnt[r];\n            for (int v : tAdj[u]) {\n                if (!alive[v]) continue;\n                if (--deg[v] == 1 && v != S) q.push(v);\n            }\n        }\n\n        long long cost = 0;\n        vector<pair<int,int>> pruned;\n        outCovered.reset();\n        for (int u = 0; u < V; ++u) if (alive[u]) {\n            outCovered |= cellMask[u];\n            for (int v : tAdj[u]) if (u < v) {\n                pruned.emplace_back(u, v);\n                cost += w[ui[u]][uj[u]] + w[ui[v]][uj[v]];\n            }\n        }\n        edges.swap(pruned);\n        return cost;\n    }\n\n    /* ---------- MST-guided tree construction ---------- */\n    long long buildMSTTree(const vector<vector<int>> &children,\n                           vector<pair<int,int>> &outEdges,\n                           bitset<1024> &outCovered) {\n        vector<char> inTree(V, 0);\n        inTree[S] = 1;\n        bitset<1024> covered = cellMask[S];\n        vector<pair<int,int>> edges;\n        vector<int> dist(V), parent(V);\n        vector<char> src(V);\n        vector<int> order;\n\n        function<void(int)> dfs = [&](int g) {\n            for (int child : children[g]) {\n                int gid = child;               // group id, or R for start\n                if (gid < R && covered.test(gid)) {\n                    dfs(child);\n                    continue;\n                }\n                // multi-source Dijkstra from current tree\n                for (int i = 0; i < V; ++i) src[i] = inTree[i];\n                dijkstra(src, dist, parent, &order);\n                int bestV = -1, bestD = INF;\n                if (gid < R) {\n                    for (int v : groupCells[gid]) {\n                        if (dist[v] < bestD) {\n                            bestD = dist[v];\n                            bestV = v;\n                        }\n                    }\n                } else {\n                    bestV = S; bestD = 0;\n                }\n                if (bestV == -1) { dfs(child); continue; }\n\n                int cur = bestV;\n                while (!inTree[cur]) {\n                    int p = parent[cur];\n                    edges.emplace_back(cur, p);\n                    inTree[cur] = 1;\n                    covered |= cellMask[cur];\n                    cur = p;\n                }\n                dfs(child);\n            }\n        };\n        dfs(R);\n\n        outCovered.reset();\n        long long cost = pruneAndCost(edges, outCovered);\n        outEdges.swap(edges);\n        return cost;\n    }\n\n    /* ---------- TM greedy tree construction ---------- */\n    long long buildGreedyTree(int iter,\n                              vector<pair<int,int>> &outEdges,\n                              bitset<1024> &outCovered) {\n        vector<char> inTree(V, 0);\n        inTree[S] = 1;\n        bitset<1024> covered = cellMask[S];\n        vector<pair<int,int>> edges;\n        vector<int> dist(V), parent(V), order;\n        vector< bitset<1024> > pathMask(V);\n        vector<char> src(V);\n\n        struct Cand { int v, d, g; };\n        while (covered != allReq) {\n            for (int i = 0; i < V; ++i) src[i] = inTree[i];\n            dijkstra(src, dist, parent, &order);\n            for (int u : order) {\n                if (inTree[u]) pathMask[u].reset();\n                else {\n                    int p = parent[u];\n                    if (p >= 0) pathMask[u] = pathMask[p];\n                    pathMask[u] |= cellMask[u];\n                }\n            }\n            vector<Cand> cands;\n            for (int u = 0; u < V; ++u) {\n                if (inTree[u]) continue;\n                bitset<1024> add = pathMask[u] & ~covered;\n                int gain = (int)add.count();\n                if (gain > 0) cands.push_back({u, dist[u], gain});\n            }\n            if (cands.empty()) return (1LL<<60);\n\n            sort(cands.begin(), cands.end(),\n                [](const Cand& a, const Cand& b) {\n                    return (long long)a.d * b.g < (long long)b.d * a.g;\n                });\n            int K = min(3, (int)cands.size());\n            int pick = (iter > 0) ? (int)(rng() % K) : 0;\n            int bestV = cands[pick].v;\n\n            int cur = bestV;\n            while (!inTree[cur]) {\n                int p = parent[cur];\n                edges.emplace_back(cur, p);\n                inTree[cur] = 1;\n                covered |= cellMask[cur];\n                cur = p;\n            }\n        }\n        outCovered.reset();\n        long long cost = pruneAndCost(edges, outCovered);\n        outEdges.swap(edges);\n        return cost;\n    }\n\n    /* ---------- shake local search ---------- */\n    void shakeImprove(vector<pair<int,int>> &bestEdges,\n                      long long &bestCost,\n                      bitset<1024> &bestCovered) {\n        const int SHAKE_ITERS = 200;\n        for (int it = 0; it < SHAKE_ITERS; ++it) {\n            auto edges = bestEdges;\n            vector<char> alive(V, 0);\n            for (auto &e : edges) {\n                alive[e.first] = 1;\n                alive[e.second] = 1;\n            }\n\n            int numShakes = 1 + (int)(rng() % 3);\n            bool bad = false;\n            for (int s = 0; s < numShakes && !bad; ++s) {\n                vector<vector<int>> tAdj(V);\n                vector<int> deg(V, 0);\n                for (auto &e : edges) {\n                    int u = e.first, v = e.second;\n                    if (!alive[u] || !alive[v]) continue;\n                    tAdj[u].push_back(v);\n                    tAdj[v].push_back(u);\n                    ++deg[u]; ++deg[v];\n                }\n                vector<int> leaves;\n                for (int u = 0; u < V; ++u)\n                    if (alive[u] && deg[u] == 1 && u != S) leaves.push_back(u);\n                if (leaves.empty()) { bad = true; break; }\n\n                int leaf = leaves[rng() % leaves.size()];\n                vector<int> rem;\n                int cur = leaf, prev = -1;\n                while (true) {\n                    rem.push_back(cur);\n                    int nxt = -1;\n                    for (int v : tAdj[cur]) if (v != prev) { nxt = v; break; }\n                    if (nxt == -1) break;\n                    if (nxt == S || deg[nxt] > 2) break;\n                    prev = cur;\n                    cur = nxt;\n                }\n                for (int u : rem) alive[u] = 0;\n            }\n            if (bad) continue;\n\n            // rebuild edge list of surviving tree\n            vector<pair<int,int>> keep;\n            for (auto &e : edges)\n                if (alive[e.first] && alive[e.second]) keep.push_back(e);\n\n            // greedy recover\n            bitset<1024> covered;\n            for (int u = 0; u < V; ++u) if (alive[u]) covered |= cellMask[u];\n\n            vector<char> inTree = alive;\n            vector<pair<int,int>> addEdges;\n            vector<int> dist(V), parent(V), order;\n            vector< bitset<1024> > pathMask(V);\n            vector<char> src(V);\n            struct Cand { int v, d, g; };\n\n            while (covered != allReq) {\n                for (int i = 0; i < V; ++i) src[i] = inTree[i];\n                dijkstra(src, dist, parent, &order);\n                for (int u : order) {\n                    if (inTree[u]) pathMask[u].reset();\n                    else {\n                        int p = parent[u];\n                        if (p >= 0) pathMask[u] = pathMask[p];\n                        pathMask[u] |= cellMask[u];\n                    }\n                }\n                vector<Cand> cands;\n                for (int u = 0; u < V; ++u) {\n                    if (inTree[u]) continue;\n                    bitset<1024> add = pathMask[u] & ~covered;\n                    int gain = (int)add.count();\n                    if (gain > 0) cands.push_back({u, dist[u], gain});\n                }\n                if (cands.empty()) { bad = true; break; }\n\n                sort(cands.begin(), cands.end(),\n                    [](const Cand& a, const Cand& b) {\n                        return (long long)a.d * b.g < (long long)b.d * a.g;\n                    });\n                int K = min(3, (int)cands.size());\n                int pick = (int)(rng() % K);\n                int bestV = cands[pick].v;\n\n                int cur = bestV;\n                while (!inTree[cur]) {\n                    int p = parent[cur];\n                    addEdges.emplace_back(cur, p);\n                    inTree[cur] = 1;\n                    covered |= cellMask[cur];\n                    cur = p;\n                }\n            }\n            if (bad) continue;\n\n            vector<pair<int,int>> combined = keep;\n            combined.insert(combined.end(), addEdges.begin(), addEdges.end());\n            bitset<1024> finalCov;\n            long long cost = pruneAndCost(combined, finalCov);\n            if (finalCov == allReq && cost < bestCost) {\n                bestCost = cost;\n                bestEdges.swap(combined);\n                bestCovered = finalCov;\n            }\n        }\n    }\n\n    /* ---------- main ---------- */\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n        rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n\n        if (!(cin >> N >> si >> sj)) return;\n        g.resize(N);\n        for (int i = 0; i < N; ++i) cin >> g[i];\n        w.assign(N, vector<int>(N, 0));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (g[i][j] != '#') w[i][j] = g[i][j] - '0';\n\n        /* build road graph */\n        vector<vector<int>> id(N, vector<int>(N, -1));\n        queue<pair<int,int>> q;\n        q.emplace(si, sj);\n        id[si][sj] = 0;\n        ui.push_back(si); uj.push_back(sj);\n        while (!q.empty()) {\n            auto [i, j] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (g[ni][nj] == '#') continue;\n                if (id[ni][nj] == -1) {\n                    id[ni][nj] = (int)ui.size();\n                    ui.push_back(ni);\n                    uj.push_back(nj);\n                    q.emplace(ni, nj);\n                }\n            }\n        }\n        V = (int)ui.size();\n        S = id[si][sj];\n        adj.assign(V, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1)\n                    adj[u].push_back(id[ni][nj]);\n            }\n        }\n\n        /* identify long segments */\n        vector<vector<int>> hId(N, vector<int>(N, -1));\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ) {\n                if (g[i][j] == '#') { ++j; continue; }\n                int j0 = j;\n                while (j < N && g[i][j] != '#') ++j;\n                if (j - j0 >= 2) {\n                    for (int k = j0; k < j; ++k) hId[i][k] = Hreq;\n                    ++Hreq;\n                }\n            }\n        }\n        vector<vector<int>> vId(N, vector<int>(N, -1));\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ) {\n                if (g[i][j] == '#') { ++i; continue; }\n                int i0 = i;\n                while (i < N && g[i][j] != '#') ++i;\n                if (i - i0 >= 2) {\n                    for (int k = i0; k < i; ++k) vId[k][j] = Vreq;\n                    ++Vreq;\n                }\n            }\n        }\n        R = Hreq + Vreq;\n        allReq.reset();\n        for (int i = 0; i < R; ++i) allReq.set(i);\n\n        cellMask.assign(V, bitset<1024>());\n        groupCells.assign(R, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            if (hId[i][j] != -1) {\n                cellMask[u].set(hId[i][j]);\n                groupCells[hId[i][j]].push_back(u);\n            }\n            if (vId[i][j] != -1) {\n                cellMask[u].set(Hreq + vId[i][j]);\n                groupCells[Hreq + vId[i][j]].push_back(u);\n            }\n        }\n\n        if (R == 0) {\n            cout << \"\\n\";\n            return;\n        }\n\n        /* ---------- fallback: Dijkstra spanning tree over whole component ---------- */\n        vector<pair<int,int>> bestEdges;\n        long long bestCost = (1LL<<60);\n        bitset<1024> bestCovered;\n\n        {\n            vector<int> fdist(V, INF), fpar(V, -1);\n            vector<char> fsrc(V, 0); fsrc[S] = 1;\n            dijkstra(fsrc, fdist, fpar);\n            vector<pair<int,int>> fedges;\n            for (int u = 0; u < V; ++u) if (fpar[u] != -1)\n                fedges.emplace_back(u, fpar[u]);\n            bitset<1024> cov;\n            bestCost = pruneAndCost(fedges, cov);\n            bestEdges.swap(fedges);\n            bestCovered = cov;\n        }\n\n        /* ---------- pre-compute group (and start) Dijkstras ---------- */\n        int M = R + 1; // groups + start\n        vector<vector<int>> metaDist(M, vector<int>(V));\n        vector<vector<int>> metaPrev(M, vector<int>(V));\n        vector<char> src(V);\n        for (int g = 0; g < M; ++g) {\n            fill(src.begin(), src.end(), 0);\n            if (g == R) src[S] = 1;\n            else for (int v : groupCells[g]) src[v] = 1;\n            dijkstra(src, metaDist[g], metaPrev[g]);\n        }\n\n        /* ---------- group-group distances and MST ---------- */\n        vector<vector<int>> d(M, vector<int>(M, INF));\n        for (int i = 0; i < M; ++i) {\n            for (int j = i + 1; j < M; ++j) {\n                int best = INF;\n                const vector<int> &di = metaDist[i];\n                const vector<int> &dj = metaDist[j];\n                for (int v = 0; v < V; ++v) {\n                    int s = di[v] + dj[v];\n                    if (s < best) best = s;\n                }\n                d[i][j] = d[j][i] = best;\n            }\n        }\n\n        vector<int> mincost(M, INF), used(M, 0), sel(M, -1);\n        vector<vector<int>> mstAdj(M);\n        mincost[R] = 0;\n        for (int i = 0; i < M; ++i) {\n            int v = -1;\n            for (int j = 0; j < M; ++j)\n                if (!used[j] && (v == -1 || mincost[j] < mincost[v])) v = j;\n            used[v] = 1;\n            if (sel[v] != -1) {\n                mstAdj[v].push_back(sel[v]);\n                mstAdj[sel[v]].push_back(v);\n            }\n            for (int j = 0; j < M; ++j)\n                if (!used[j] && d[v][j] < mincost[j]) {\n                    mincost[j] = d[v][j];\n                    sel[j] = v;\n                }\n        }\n\n        // build rooted children lists\n        vector<vector<int>> children(M);\n        function<void(int,int)> buildChildren = [&](int u, int p) {\n            for (int v : mstAdj[u]) if (v != p) {\n                children[u].push_back(v);\n                buildChildren(v, u);\n            }\n        };\n        buildChildren(R, -1);\n\n        /* ---------- MST-guided trees with shuffled orders ---------- */\n        for (int iter = 0; iter < 25; ++iter) {\n            if (iter > 0) {\n                for (int i = 0; i < M; ++i)\n                    shuffle(children[i].begin(), children[i].end(), rng);\n            }\n            vector<pair<int,int>> edges;\n            bitset<1024> cov;\n            long long c = buildMSTTree(children, edges, cov);\n            if (cov == allReq && c < bestCost) {\n                bestCost = c;\n                bestEdges.swap(edges);\n                bestCovered = cov;\n            }\n        }\n\n        /* ---------- traditional TM greedy ---------- */\n        for (int iter = 0; iter < 35; ++iter) {\n            vector<pair<int,int>> edges;\n            bitset<1024> cov;\n            long long c = buildGreedyTree(iter, edges, cov);\n            if (cov == allReq && c < bestCost) {\n                bestCost = c;\n                bestEdges.swap(edges);\n                bestCovered = cov;\n            }\n        }\n\n        /* ---------- shake local search ---------- */\n        if (!bestEdges.empty())\n            shakeImprove(bestEdges, bestCost, bestCovered);\n\n        /* ---------- output doubled tour ---------- */\n        vector<vector<int>> finalAdj(V);\n        for (auto [u, v] : bestEdges) {\n            finalAdj[u].push_back(v);\n            finalAdj[v].push_back(u);\n        }\n        string tour;\n        function<void(int,int)> dfs = [&](int u, int p) {\n            for (int v : finalAdj[u]) if (v != p) {\n                tour.push_back(dc[dirMove(u, v)]);\n                dfs(v, u);\n                tour.push_back(dc[dirMove(v, u)]);\n            }\n        };\n        dfs(S, -1);\n        cout << tour << \"\\n\";\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.run();\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\n/* ---------- global data ---------- */\nint N, M, K, R;\nvector<vector<int>> task_d;\nvector<int> task_sumd;\nvector<int> task_dom;\nvector<vector<int>> dag_out;\nvector<int> indeg0;\n\nvector<double> down_len;\nvector<int> wait_cnt;\n\nvector<vector<double>> skill_est;\nvector<vector<int>> explored;   // per worker, count of explored dominant dims\nvector<vector<pair<int,int>>> history;\n\nvector<int> worker_task;\nvector<int> worker_start;\nvector<int> worker_done_cnt;\n\nvector<int> rem_indeg;\nvector<int> ready;\n\nmt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\ninline double predicted_dur(int task, int w) {\n    double wsum = 0.0;\n    const auto &td = task_d[task];\n    const auto &sk = skill_est[w];\n    for (int k = 0; k < K; ++k) {\n        if (td[k] > sk[k]) wsum += td[k] - sk[k];\n    }\n    return wsum < 1.0 ? 1.0 : wsum;\n}\n\nvoid recompute_down_len() {\n    vector<double> mindur(N);\n    for (int i = 0; i < N; ++i) {\n        double best = 1e100;\n        for (int j = 0; j < M; ++j)\n            best = min(best, predicted_dur(i, j));\n        mindur[i] = best;\n    }\n    for (int i = N - 1; i >= 0; --i) {\n        double child = 0.0;\n        for (int v : dag_out[i]) child = max(child, down_len[v]);\n        down_len[i] = mindur[i] + child;\n    }\n}\n\n/* Hungarian for n rows, m cols (n <= m), minimisation, 1-indexed inside */\nvector<int> hungarian(const vector<vector<double>>& a) {\n    int n = (int)a.size() - 1;\n    int m = (int)a[0].size() - 1;\n    const double INF = 1e100;\n    vector<double> u(n + 1), v(m + 1);\n    vector<int> p(m + 1), way(m + 1);\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        vector<double> minv(m + 1, INF);\n        vector<char> used(m + 1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0], j1 = 0;\n            double delta = INF;\n            for (int j = 1; j <= m; ++j) if (!used[j]) {\n                double cur = a[i0][j] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= m; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n    vector<int> ans(n + 1);\n    for (int j = 1; j <= m; ++j)\n        if (p[j] != 0)\n            ans[p[j]] = j;\n    return ans;\n}\n\n/* assign tasks for the coming day */\nvector<pair<int,int>> assign_day(int day) {\n    vector<pair<int,int>> out_pairs;\n    vector<int> idle;\n    for (int j = 0; j < M; ++j)\n        if (worker_task[j] == -1) idle.push_back(j);\n\n    if (idle.empty() || ready.empty()) return out_pairs;\n\n    vector<int> avail = ready;\n\n    /* ---- exploration: first 2 tasks per worker ---- */\n    vector<int> explorers;\n    for (int j : idle)\n        if (worker_done_cnt[j] < 2) explorers.push_back(j);\n\n    if (!explorers.empty() && !avail.empty()) {\n        for (int j : explorers) {\n            if (avail.empty()) break;\n            // find least explored dimension for this worker\n            int best_k = 0;\n            for (int k = 1; k < K; ++k)\n                if (explored[j][k] < explored[j][best_k]) best_k = k;\n\n            int chosen = -1;\n            int best_sum = INT_MAX;\n            // try to find a short task dominated by best_k\n            for (int t : avail) {\n                if (task_dom[t] == best_k && task_sumd[t] < 60 && task_sumd[t] < best_sum) {\n                    best_sum = task_sumd[t];\n                    chosen = t;\n                }\n            }\n            if (chosen == -1) {\n                // fallback: globally shortest ready task\n                for (int t : avail) {\n                    if (task_sumd[t] < best_sum) {\n                        best_sum = task_sumd[t];\n                        chosen = t;\n                    }\n                }\n            }\n            if (chosen != -1) {\n                auto it = find(avail.begin(), avail.end(), chosen);\n                if (it != avail.end()) avail.erase(it);\n                out_pairs.emplace_back(j, chosen);\n                worker_task[j] = chosen;\n                worker_start[j] = day;\n                explored[j][task_dom[chosen]]++;\n            }\n        }\n    }\n\n    /* ---- exploitation: Hungarian matching ---- */\n    vector<int> idle2;\n    for (int j : idle)\n        if (worker_task[j] == -1) idle2.push_back(j);\n\n    if (!idle2.empty() && !avail.empty()) {\n        int nW = (int)idle2.size();\n        int nT = (int)avail.size();\n\n        vector<pair<int,int>> matched;\n        if (nW <= nT) {\n            vector<vector<double>> cost(nW + 1, vector<double>(nT + 1));\n            for (int i = 1; i <= nW; ++i) {\n                for (int j = 1; j <= nT; ++j) {\n                    double dur = predicted_dur(avail[j - 1], idle2[i - 1]);\n                    double c = dur\n                             - 0.08 * down_len[avail[j - 1]]\n                             - 0.18 * min(wait_cnt[avail[j - 1]], 40);\n                    c += uniform_real_distribution<double>(-1e-9, 1e-9)(rng);\n                    cost[i][j] = c;\n                }\n            }\n            auto ans = hungarian(cost); // ans[i] = task idx (1-based in avail)\n            for (int i = 1; i <= nW; ++i) {\n                int t = avail[ans[i] - 1];\n                matched.emplace_back(idle2[i - 1], t);\n            }\n        } else {\n            vector<vector<double>> cost(nT + 1, vector<double>(nW + 1));\n            for (int i = 1; i <= nT; ++i) {\n                for (int j = 1; j <= nW; ++j) {\n                    double dur = predicted_dur(avail[i - 1], idle2[j - 1]);\n                    double c = dur\n                             - 0.08 * down_len[avail[i - 1]]\n                             - 0.18 * min(wait_cnt[avail[i - 1]], 40);\n                    c += uniform_real_distribution<double>(-1e-9, 1e-9)(rng);\n                    cost[i][j] = c;\n                }\n            }\n            auto ans = hungarian(cost); // ans[i] = worker idx (1-based in idle2)\n            for (int i = 1; i <= nT; ++i) {\n                int w = idle2[ans[i] - 1];\n                matched.emplace_back(w, avail[i - 1]);\n            }\n        }\n\n        for (auto &p : matched) {\n            int j = p.first, t = p.second;\n            out_pairs.emplace_back(j, t);\n            worker_task[j] = t;\n            worker_start[j] = day;\n        }\n    }\n\n    /* erase assigned tasks from the global ready list */\n    vector<char> mark(N, 0);\n    for (auto &p : out_pairs) mark[p.second] = 1;\n    vector<int> new_ready;\n    new_ready.reserve(ready.size());\n    for (int t : ready)\n        if (!mark[t]) new_ready.push_back(t);\n    ready.swap(new_ready);\n    return out_pairs;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    task_d.assign(N, vector<int>(K));\n    task_sumd.assign(N, 0);\n    task_dom.assign(N, 0);\n    for (int i = 0; i < N; ++i) {\n        int s = 0, best_k = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> task_d[i][k];\n            s += task_d[i][k];\n            if (task_d[i][k] > task_d[i][best_k]) best_k = k;\n        }\n        task_sumd[i] = s;\n        task_dom[i] = best_k;\n    }\n\n    dag_out.assign(N, {});\n    indeg0.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v; cin >> u >> v; --u; --v;\n        dag_out[u].push_back(v);\n        ++indeg0[v];\n    }\n\n    wait_cnt.assign(N, 0);\n    skill_est.assign(M, vector<double>(K, 0.0));\n\n    // initialise with mean difficulty per dimension\n    vector<double> mean_d(K, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            mean_d[k] += task_d[i][k];\n    for (int k = 0; k < K; ++k) mean_d[k] /= N;\n    for (int j = 0; j < M; ++j)\n        for (int k = 0; k < K; ++k)\n            skill_est[j][k] = mean_d[k];\n\n    explored.assign(M, vector<int>(K, 0));\n    history.assign(M, {});\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    worker_done_cnt.assign(M, 0);\n    rem_indeg = indeg0;\n    ready.clear();\n    for (int i = 0; i < N; ++i)\n        if (rem_indeg[i] == 0) ready.push_back(i);\n\n    down_len.assign(N, 1.0);\n    recompute_down_len();\n\n    int day = 1;\n    auto assignments = assign_day(day);\n\n    while (true) {\n        cout << assignments.size();\n        for (auto &p : assignments)\n            cout << ' ' << p.first + 1 << ' ' << p.second + 1;\n        cout << '\\n';\n        cout.flush();\n\n        int n;  cin >> n;\n        if (n == -1) break;\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int t : ready) ++wait_cnt[t];\n\n        bool updated = false;\n        for (int j : finished) {\n            int t = worker_task[j];\n            int dur = day - worker_start[j] + 1;\n\n            history[j].emplace_back(t, dur);\n\n            const double LR2 = 0.015;\n            const int EPOCHS = 10;\n            auto &hist = history[j];\n            double lr = max(0.03, 0.25 / sqrt((double)hist.size()));\n\n            for (int ep = 0; ep < EPOCHS; ++ep) {\n                shuffle(hist.begin(), hist.end(), rng);\n                for (auto &ob : hist) {\n                    int tid = ob.first;\n                    int odur = ob.second;\n\n                    double otarget, oweight;\n                    if (odur == 1) {\n                        otarget = 2.0;   // midpoint of [0,4]\n                        oweight = 0.15;\n                    } else if (odur == 2) {\n                        otarget = 2.5;   // approximate midpoint of [0,5]\n                        oweight = 0.4;\n                    } else if (odur == 3) {\n                        otarget = 3.0;   // approximate midpoint of [0,6]\n                        oweight = 0.6;\n                    } else {\n                        otarget = odur;  // for w>=4, t=w+r, posterior mean = t\n                        oweight = 1.0;\n                    }\n\n                    const auto &td = task_d[tid];\n                    double wpred = 0.0;\n                    vector<int> active;\n                    active.reserve(K);\n                    for (int k = 0; k < K; ++k) {\n                        if (td[k] > skill_est[j][k] + 1e-12) {\n                            wpred += td[k] - skill_est[j][k];\n                            active.push_back(k);\n                        }\n                    }\n\n                    double err = wpred - otarget;\n                    if (fabs(err) < 1e-12) continue;\n\n                    if (!active.empty()) {\n                        double delta = lr * err * oweight / active.size();\n                        if (delta >  5.0) delta =  5.0;\n                        if (delta < -5.0) delta = -5.0;\n                        for (int k : active) skill_est[j][k] += delta;\n                    } else if (err < 0.0) {\n                        double dec = LR2 * (-err) * oweight / K;\n                        for (int k = 0; k < K; ++k)\n                            skill_est[j][k] = max(0.0, skill_est[j][k] - dec);\n                    }\n                    for (int k = 0; k < K; ++k)\n                        if (skill_est[j][k] < 0.0) skill_est[j][k] = 0.0;\n                }\n            }\n\n            worker_task[j] = -1;\n            worker_start[j] = -1;\n            ++worker_done_cnt[j];\n            updated = true;\n\n            for (int v : dag_out[t]) {\n                if (--rem_indeg[v] == 0)\n                    ready.push_back(v);\n            }\n        }\n\n        if (updated) recompute_down_len();\n\n        ++day;\n        if (day > 2000) break;\n        assignments = assign_day(day);\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nint Xc[2001];\nint Yc[2001];\nint dist_mat[2001][2001];\n\ninline int D(int u, int v) { return dist_mat[u][v]; }\n\n/* node 0 = depot (400,400)\n   order i (0-based): pickup = 2*i+1, delivery = 2*i+2 */\ninline int partner(int v) {\n    if (v & 1) return v + 1;   // pickup -> delivery\n    return v - 1;              // delivery -> pickup\n}\n\n/* ---------- route construction helpers ---------- */\nvoid eval_insert(const vector<int>& route, int oid, int& best_delta, int& best_ip, int& best_id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    int L = (int)route.size();\n    best_delta = INT_MAX;\n    for (int ip = 0; ip < L - 1; ++ip) {\n        int cost_p = D(route[ip], p) + D(p, route[ip + 1]) - D(route[ip], route[ip + 1]);\n        int left = p;\n        for (int id = ip; id < L - 1; ++id) {\n            if (id > ip) left = route[id];\n            int cost_d = D(left, d) + D(d, route[id + 1]) - D(left, route[id + 1]);\n            int delta = cost_p + cost_d;\n            if (delta < best_delta) {\n                best_delta = delta;\n                best_ip = ip;\n                best_id = id;\n            }\n        }\n    }\n}\n\nvoid apply_insert(vector<int>& route, int oid, int ip, int id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() + 2);\n    for (int k = 0; k <= ip; ++k) res.push_back(route[k]);\n    res.push_back(p);\n    for (int k = ip + 1; k <= id; ++k) res.push_back(route[k]);\n    res.push_back(d);\n    for (int k = id + 1; k < (int)route.size(); ++k) res.push_back(route[k]);\n    route.swap(res);\n}\n\nvector<int> remove_order(const vector<int>& route, int oid) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() - 2);\n    for (int node : route) if (node != p && node != d) res.push_back(node);\n    return res;\n}\n\nint route_cost(const vector<int>& route) {\n    int sum = 0;\n    for (int i = 0; i + 1 < (int)route.size(); ++i) sum += D(route[i], route[i + 1]);\n    return sum;\n}\n\n/* ---------- local search on a fixed route ---------- */\nbool optimize_pass(vector<int>& route, int& cost) {\n    int n = (int)route.size();\n    vector<int> pos(2001, -1);\n    for (int i = 0; i < n; ++i) pos[route[i]] = i;\n\n    vector<int> pp(n);\n    for (int i = 1; i < n - 1; ++i) pp[i] = pos[partner(route[i])];\n\n    int best_delta = 0;\n    int best_type = -1;          // 0 swap, 1 2opt, 2 relocate\n    int b_i = 0, b_j = 0, b_l = 0, b_r = 0;\n\n    // 1. swap two internal nodes\n    for (int i = 1; i < n - 1; ++i) {\n        for (int j = i + 1; j < n - 1; ++j) {\n            int u = route[i], v = route[j];\n            if (partner(u) == v) continue;               // same order\n            if ((u & 1) && pp[i] <= j) continue;         // pickup must stay before delivery\n            if (!(v & 1) && pp[j] >= i) continue;        // delivery must stay after pickup\n            int delta;\n            if (j == i + 1) {\n                delta = D(route[i - 1], v) + D(v, u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, v) - D(v, route[j + 1]);\n            } else {\n                delta = D(route[i - 1], v) + D(v, route[i + 1])\n                      + D(route[j - 1], u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, route[i + 1])\n                      - D(route[j - 1], v) - D(v, route[j + 1]);\n            }\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 0; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    // 2. 2-opt (segment reversal)\n    for (int l = 1; l < n - 1; ++l) {\n        for (int r = l + 1; r < n - 1; ++r) {\n            bool ok = true;\n            for (int k = l; k <= r; ++k) {\n                if (pp[k] >= l && pp[k] <= r) { ok = false; break; }\n            }\n            if (!ok) continue;\n            int delta = D(route[l - 1], route[r]) + D(route[l], route[r + 1])\n                      - D(route[l - 1], route[l]) - D(route[r], route[r + 1]);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 1; b_l = l; b_r = r;\n            }\n        }\n    }\n\n    // 3. relocate a single node\n    for (int i = 1; i < n - 1; ++i) {\n        int u = route[i];\n        int A = route[i - 1], B = route[i + 1];\n        int delta_remove = D(A, B) - D(A, u) - D(u, B);\n        // move left: j < i\n        for (int j = 1; j < i; ++j) {\n            if (!(u & 1) && j <= pp[i]) continue; // delivery cannot pass its pickup\n            int left = route[j - 1], right = route[j];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n        // move right: j > i\n        for (int j = i + 1; j < n - 1; ++j) {\n            if ((u & 1) && j >= pp[i]) continue; // pickup cannot pass its delivery\n            int left = route[j], right = route[j + 1];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    if (best_type == -1) return false;\n\n    if (best_type == 0) {\n        swap(route[b_i], route[b_j]);\n    } else if (best_type == 1) {\n        reverse(route.begin() + b_l, route.begin() + b_r + 1);\n    } else {\n        int u = route[b_i];\n        route.erase(route.begin() + b_i);\n        route.insert(route.begin() + b_j, u);\n    }\n    cost += best_delta;\n    return true;\n}\n\nvoid optimize_route(vector<int>& route, int& cost) {\n    while (optimize_pass(route, cost)) {}\n}\n\n/* ---------- greedy construction ---------- */\nstruct State {\n    vector<int> route;\n    vector<int> selected;\n    int cost;\n};\n\nState greedy_build(bool use_rand, int rand_k, mt19937& rng) {\n    State st;\n    st.route = {0, 0};\n    st.selected.reserve(50);\n    vector<char> used(1000, 0);\n    struct Cand { int delta, oid, ip, id; };\n    for (int step = 0; step < 50; ++step) {\n        vector<Cand> cands;\n        cands.reserve(1000);\n        for (int oid = 0; oid < 1000; ++oid) if (!used[oid]) {\n            int d, ip, id;\n            eval_insert(st.route, oid, d, ip, id);\n            cands.push_back({d, oid, ip, id});\n        }\n        sort(cands.begin(), cands.end(),\n             [](const Cand& a, const Cand& b){ return a.delta < b.delta; });\n        int pick = 0;\n        if (use_rand && rand_k > 1 && (int)cands.size() > 1) {\n            int k = min(rand_k, (int)cands.size());\n            pick = uniform_int_distribution<int>(0, k - 1)(rng);\n        }\n        const Cand& c = cands[pick];\n        apply_insert(st.route, c.oid, c.ip, c.id);\n        used[c.oid] = 1;\n        st.selected.push_back(c.oid);\n    }\n    st.cost = route_cost(st.route);\n    return st;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    vector<int> ax(1000), ay(1000), cx(1000), cy(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n    }\n\n    Xc[0] = Yc[0] = 400;\n    for (int i = 0; i < 1000; ++i) {\n        Xc[2 * i + 1] = ax[i]; Yc[2 * i + 1] = ay[i];\n        Xc[2 * i + 2] = cx[i]; Yc[2 * i + 2] = cy[i];\n    }\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist_mat[i][j] = abs(Xc[i] - Xc[j]) + abs(Yc[i] - Yc[j]);\n\n    vector<int> standalone(1000);\n    for (int i = 0; i < 1000; ++i)\n        standalone[i] = D(0, 2 * i + 1) + D(2 * i + 1, 2 * i + 2) + D(2 * i + 2, 0);\n\n    vector<int> order_ids(1000);\n    iota(order_ids.begin(), order_ids.end(), 0);\n    sort(order_ids.begin(), order_ids.end(),\n         [&](int a, int b){ return standalone[a] < standalone[b]; });\n\n    mt19937 rng(42);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]()->double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n    const double TL = 1.90;\n\n    State best = greedy_build(false, 0, rng);\n    optimize_route(best.route, best.cost);\n\n    // set improvement: swap one selected order with one promising outside order\n    while (elapsed() < TL * 0.65) {\n        vector<char> in_sel(1000, 0);\n        for (int oid : best.selected) in_sel[oid] = 1;\n        vector<int> cand_out;\n        for (int oid : order_ids) {\n            if (!in_sel[oid]) {\n                cand_out.push_back(oid);\n                if ((int)cand_out.size() >= 200) break;\n            }\n        }\n\n        int best_in = -1, best_out = -1, best_ip = -1, best_id = -1;\n        int best_new_cost = best.cost;\n\n        for (int oid_in : best.selected) {\n            if (elapsed() > TL * 0.65) break;\n            vector<int> tmp = remove_order(best.route, oid_in);\n            int tmp_cost = route_cost(tmp);\n            for (int oid_out : cand_out) {\n                int dlt, ip, id;\n                eval_insert(tmp, oid_out, dlt, ip, id);\n                int ncost = tmp_cost + dlt;\n                if (ncost < best_new_cost) {\n                    best_new_cost = ncost;\n                    best_in = oid_in;\n                    best_out = oid_out;\n                    best_ip = ip;\n                    best_id = id;\n                }\n            }\n        }\n\n        if (best_in == -1) break;\n\n        vector<int> new_route = remove_order(best.route, best_in);\n        apply_insert(new_route, best_out, best_ip, best_id);\n        best.route = move(new_route);\n        best.cost = best_new_cost;\n        for (int& oid : best.selected) if (oid == best_in) { oid = best_out; break; }\n\n        optimize_route(best.route, best.cost);\n    }\n\n    // random restarts with remaining time\n    int restart = 0;\n    while (elapsed() < TL && restart < 6) {\n        ++restart;\n        State cand = greedy_build(true, 3, rng);\n        optimize_route(cand.route, cand.cost);\n        if (cand.cost < best.cost) best = move(cand);\n    }\n\n    cout << best.selected.size();\n    for (int oid : best.selected) cout << ' ' << (oid + 1);\n    cout << \"\\n\";\n    cout << best.route.size();\n    for (int node : best.route) cout << ' ' << Xc[node] << ' ' << Yc[node];\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*** DSU for the main forest and bridge checks ***/\nstruct DSU {\n    unsigned short p[400];\n    unsigned char r[400];\n    void init() {\n        for (int i = 0; i < 400; ++i) {\n            p[i] = (unsigned short)i;\n            r[i] = 0;\n        }\n    }\n    int find(int x) {\n        unsigned short *pp = p;\n        while (pp[x] != x) {\n            pp[x] = pp[pp[x]];\n            x = pp[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (r[a] < r[b]) swap(a, b);\n        p[b] = (unsigned short)a;\n        if (r[a] == r[b]) ++r[a];\n        return true;\n    }\n    bool same(int a, int b) {\n        return find(a) == find(b);\n    }\n};\n\n/*** Fast Kruskal with static bucket lists (weights <= 3600) ***/\nstruct Solver {\n    static const int MAXW = 3600;\n    static const int MAXE = 2005;\n    static const int MAXV = 400;\n\n    short U[MAXE];\n    short V[MAXE];\n    int nxt[MAXE];\n    int head[MAXW];\n    int vis[MAXW];\n    int ecnt;\n    int curVis;\n    int minW, maxW;\n\n    int par[MAXV];\n    unsigned char rnk[MAXV];\n\n    Solver() {\n        memset(vis, 0, sizeof(vis));\n        curVis = 1;\n    }\n\n    inline void clear() {\n        ecnt = 0;\n        ++curVis;\n        minW = MAXW;\n        maxW = 0;\n    }\n\n    inline void add(int w, short u, short v) {\n        if (vis[w] != curVis) {\n            vis[w] = curVis;\n            head[w] = -1;\n        }\n        U[ecnt] = u;\n        V[ecnt] = v;\n        nxt[ecnt] = head[w];\n        head[w] = ecnt++;\n        if (w < minW) minW = w;\n        if (w > maxW) maxW = w;\n    }\n\n    inline int find(int x) {\n        int root = x;\n        while (par[root] != root) root = par[root];\n        while (par[x] != x) {\n            int p = par[x];\n            par[x] = root;\n            x = p;\n        }\n        return root;\n    }\n\n    inline bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a, b);\n        par[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n\n    long long solve(int need) {\n        if (need <= 0) return 0;\n        for (int i = 0; i < MAXV; ++i) {\n            par[i] = i;\n            rnk[i] = 0;\n        }\n        int taken = 0;\n        long long sum = 0;\n        for (int w = minW; w <= maxW; ++w) {\n            if (vis[w] != curVis) continue;\n            for (int e = head[w]; e != -1; e = nxt[e]) {\n                if (unite(U[e], V[e])) {\n                    sum += w;\n                    if (++taken == need) return sum;\n                }\n            }\n        }\n        return sum; // graph is guaranteed connected here\n    }\n};\n\n/*** fast bounded RNG: returns value in [0, range) ***/\nstatic inline uint32_t rand_range(uint64_t &state, uint32_t range) {\n    state = state * 6364136223846793005ULL + 1;\n    return (uint32_t)(((state >> 32) * (uint64_t)range) >> 32);\n}\n\nint main() {\n    const int N = 400;\n    const int M = 1995;\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) scanf(\"%d %d\", &xs[i], &ys[i]);\n\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) scanf(\"%d %d\", &U[i], &V[i]);\n\n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        long long dx = (long long)xs[U[i]] - xs[V[i]];\n        long long dy = (long long)ys[U[i]] - ys[V[i]];\n        long long dist2 = dx * dx + dy * dy;\n        d[i] = (int)llround(sqrt((double)dist2));\n    }\n\n    DSU dsu;\n    dsu.init();\n    int comp = N;\n\n    Solver solver_rej, solver_acc;\n    uint64_t rng = 123456789123456789ULL;\n    const int K = 20;\n\n    short buf_a[M];\n    short buf_b[M];\n    short buf_d[M];\n    uint16_t buf_r[M];\n    int comp_of[400];\n\n    for (int i = 0; i < M; ++i) {\n        long long l;\n        scanf(\"%lld\", &l);\n        int u = U[i], v = V[i];\n\n        // already connected -> never useful\n        if (dsu.same(u, v)) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        // component ids under current DSU\n        for (int x = 0; x < N; ++x) comp_of[x] = dsu.find(x);\n        int cu = comp_of[u];\n        int cv = comp_of[v];\n\n        // build list of future cross edges and simultaneously test bridge\n        DSU tmp = dsu;\n        int E = 0;\n        for (int j = i + 1; j < M; ++j) {\n            int a = comp_of[U[j]];\n            int b = comp_of[V[j]];\n            if (a == b) continue;\n            buf_a[E] = (short)a;\n            buf_b[E] = (short)b;\n            buf_d[E] = (short)d[j];\n            buf_r[E] = (uint16_t)(2 * d[j] + 1);\n            ++E;\n            tmp.unite(a, b);\n        }\n\n        // if future edges alone cannot connect the two components, we must take this edge\n        if (!tmp.same(cu, cv)) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n\n        // quick cheap / expensive filters\n        double ratio = (double)l / (double)d[i];\n        if (ratio <= 1.25) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n        if (ratio >= 2.75) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        // Monte-Carlo: estimate whether accepting reduces expected total cost\n        long long total = 0;\n        for (int s = 0; s < K; ++s) {\n            solver_rej.clear();\n            solver_acc.clear();\n            for (int k = 0; k < E; ++k) {\n                int w = buf_d[k] + (int)rand_range(rng, (uint32_t)buf_r[k]);\n                solver_rej.add(w, buf_a[k], buf_b[k]);\n\n                int a2 = buf_a[k];\n                int b2 = buf_b[k];\n                if (a2 == cv) a2 = cu;\n                if (b2 == cv) b2 = cu;\n                if (a2 != b2) solver_acc.add(w, (short)a2, (short)b2);\n            }\n            long long w_rej = solver_rej.solve(comp - 1);\n            long long w_acc = l + solver_acc.solve(comp - 2);\n            total += w_acc - w_rej;\n        }\n\n        if (total < 0) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n        } else {\n            printf(\"0\\n\");\n            fflush(stdout);\n        }\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int MAX_TURN = 300;\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char BUILD[4] = {'u', 'd', 'l', 'r'};\nconst char MOVE[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n};\n\nbool in_bounds(int x, int y) {\n    return x >= 0 && x < H && y >= 0 && y < W;\n}\n\nchar build_action(int hx, int hy, int wx, int wy) {\n    if (wx == hx - 1 && wy == hy) return 'u';\n    if (wx == hx + 1 && wy == hy) return 'd';\n    if (wx == hx && wy == hy - 1) return 'l';\n    if (wx == hx && wy == hy + 1) return 'r';\n    return '.';\n}\n\nchar move_action(int hx, int hy, int nx, int ny) {\n    if (nx == hx - 1 && ny == hy) return 'U';\n    if (nx == hx + 1 && ny == hy) return 'D';\n    if (nx == hx && ny == hy - 1) return 'L';\n    if (nx == hx && ny == hy + 1) return 'R';\n    return '.';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pos> pet_pos(N);\n    vector<int> pet_type(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].x >> pet_pos[i].y >> pet_type[i];\n        --pet_pos[i].x; --pet_pos[i].y;\n    }\n\n    int M;\n    cin >> M;\n    vector<Pos> human_pos(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].x >> human_pos[i].y;\n        --human_pos[i].x; --human_pos[i].y;\n    }\n\n    vector<vector<bool>> passable(H, vector<bool>(W, true));\n    vector<vector<bool>> has_pet(H, vector<bool>(W, false));\n    vector<vector<bool>> has_human(H, vector<bool>(W, false));\n\n    auto update_occupancy = [&]() {\n        for (int i = 0; i < H; ++i) {\n            fill(has_pet[i].begin(), has_pet[i].end(), false);\n            fill(has_human[i].begin(), has_human[i].end(), false);\n        }\n        for (auto &p : pet_pos) has_pet[p.x][p.y] = true;\n        for (auto &h : human_pos) has_human[h.x][h.y] = true;\n    };\n    update_occupancy();\n\n    // Prefix sum of initial pets\n    vector<vector<int>> pet_ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            pet_ps[i + 1][j + 1] = pet_ps[i][j + 1] + pet_ps[i + 1][j] - pet_ps[i][j] + (has_pet[i][j] ? 1 : 0);\n        }\n    }\n    auto rect_pet_cnt = [&](int r1, int c1, int r2, int c2) -> int {\n        if (r1 > r2 || c1 > c2) return 0;\n        return pet_ps[r2 + 1][c2 + 1] - pet_ps[r1][c2 + 1] - pet_ps[r2 + 1][c1] + pet_ps[r1][c1];\n    };\n\n    // Find best rectangle\n    long long best_score = LLONG_MIN;\n    int best_r1 = 0, best_c1 = 0, best_r2 = 0, best_c2 = 0;\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    int petcnt = rect_pet_cnt(r1, c1, r2, c2);\n                    if (petcnt > 5) continue; // too many pets, not worth it\n\n                    int walls = 0;\n                    if (r1 > 0) walls += (c2 - c1 + 1);\n                    if (r2 < H - 1) walls += (c2 - c1 + 1);\n                    if (c1 > 0) walls += (r2 - r1 + 1);\n                    if (c2 < W - 1) walls += (r2 - r1 + 1);\n\n                    int sumd = 0;\n                    for (auto &h : human_pos) {\n                        int tx = max(r1, min(h.x, r2));\n                        int ty = max(c1, min(h.y, c2));\n                        sumd += abs(h.x - tx) + abs(h.y - ty);\n                    }\n\n                    long long value = (long long)area * 1000000LL / (1LL << petcnt);\n                    long long score = value - (long long)walls * 100 - (long long)sumd * 10;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1; best_c1 = c1;\n                        best_r2 = r2; best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n\n    int R1 = best_r1, C1 = best_c1, R2 = best_r2, C2 = best_c2;\n\n    // Generate wall cells\n    vector<Pos> all_walls;\n    if (R1 > 0) for (int c = C1; c <= C2; ++c) all_walls.push_back({R1 - 1, c});\n    if (R2 < H - 1) for (int c = C1; c <= C2; ++c) all_walls.push_back({R2 + 1, c});\n    if (C1 > 0) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C1 - 1});\n    if (C2 < W - 1) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C2 + 1});\n\n    // Choose gate farthest from initial pets\n    Pos gate = {-1, -1};\n    if (!all_walls.empty()) {\n        int best = -1;\n        for (auto &w : all_walls) {\n            int mind = 1e9;\n            for (auto &p : pet_pos) mind = min(mind, abs(w.x - p.x) + abs(w.y - p.y));\n            if (mind > best) {\n                best = mind;\n                gate = w;\n            }\n        }\n    }\n\n    vector<Pos> pre_walls;\n    set<pair<int,int>> gate_set;\n    if (gate.x != -1) gate_set.insert({gate.x, gate.y});\n    for (auto &w : all_walls) {\n        if (!gate_set.count({w.x, w.y})) pre_walls.push_back(w);\n    }\n\n    Pos gate_inside = {-1, -1};\n    if (gate.x != -1) {\n        for (int d = 0; d < 4; ++d) {\n            int nx = gate.x + dx[d], ny = gate.y + dy[d];\n            if (nx >= R1 && nx <= R2 && ny >= C1 && ny <= C2) {\n                gate_inside = {nx, ny};\n                break;\n            }\n        }\n    }\n\n    auto can_build = [&](int wx, int wy) -> bool {\n        if (!passable[wx][wy]) return false;\n        if (has_pet[wx][wy] || has_human[wx][wy]) return false;\n        for (int d = 0; d < 4; ++d) {\n            int ax = wx + dx[d], ay = wy + dy[d];\n            if (in_bounds(ax, ay) && has_pet[ax][ay]) return false;\n        }\n        return true;\n    };\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        update_occupancy();\n\n        string action(M, '.');\n        vector<vector<bool>> blocked(H, vector<bool>(W, false));\n        for (int x = 0; x < H; ++x)\n            for (int y = 0; y < W; ++y)\n                blocked[x][y] = !passable[x][y];\n\n        vector<bool> prewall_built(pre_walls.size(), false);\n        for (int i = 0; i < (int)pre_walls.size(); ++i)\n            prewall_built[i] = !passable[pre_walls[i].x][pre_walls[i].y];\n        bool all_prewalls_done = true;\n        for (bool b : prewall_built) if (!b) { all_prewalls_done = false; break; }\n\n        vector<bool> is_inside(M, false);\n        for (int i = 0; i < M; ++i)\n            is_inside[i] = (human_pos[i].x >= R1 && human_pos[i].x <= R2 && human_pos[i].y >= C1 && human_pos[i].y <= C2);\n        bool all_inside = true;\n        for (bool b : is_inside) if (!b) { all_inside = false; break; }\n\n        set<pair<int,int>> being_built;\n        set<pair<int,int>> move_targets;\n        vector<bool> acted(M, false);\n\n        // 1. Try to build pre-walls or gate\n        for (int i = 0; i < M; ++i) {\n            if (acted[i]) continue;\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n\n            // Build a pre-wall\n            int chosen_j = -1;\n            for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                if (prewall_built[j]) continue;\n                int wx = pre_walls[j].x, wy = pre_walls[j].y;\n                if (abs(hx - wx) + abs(hy - wy) != 1) continue;\n                if (being_built.count({wx, wy})) continue;\n                if (move_targets.count({wx, wy})) continue;\n                if (!can_build(wx, wy)) continue;\n                chosen_j = j;\n                break;\n            }\n            if (chosen_j != -1) {\n                int wx = pre_walls[chosen_j].x, wy = pre_walls[chosen_j].y;\n                action[i] = build_action(hx, hy, wx, wy);\n                acted[i] = true;\n                being_built.insert({wx, wy});\n                blocked[wx][wy] = true;\n                continue;\n            }\n\n            // Build gate if ready\n            if (all_prewalls_done && all_inside && gate.x != -1 && passable[gate.x][gate.y]) {\n                if (abs(hx - gate.x) + abs(hy - gate.y) == 1 && can_build(gate.x, gate.y) && !being_built.count({gate.x, gate.y}) && !move_targets.count({gate.x, gate.y})) {\n                    action[i] = build_action(hx, hy, gate.x, gate.y);\n                    acted[i] = true;\n                    being_built.insert({gate.x, gate.y});\n                    blocked[gate.x][gate.y] = true;\n                    continue;\n                }\n            }\n        }\n\n        // 2. Move\n        for (int i = 0; i < M; ++i) {\n            if (acted[i]) continue;\n\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n\n            // BFS\n            vector<vector<int>> dist(H, vector<int>(W, -1));\n            vector<vector<pair<int,int>>> par(H, vector<pair<int,int>>(W, {-1, -1}));\n            queue<pair<int,int>> q;\n            dist[hx][hy] = 0;\n            q.push({hx, hy});\n            while (!q.empty()) {\n                auto [x, y] = q.front(); q.pop();\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (!in_bounds(nx, ny)) continue;\n                    if (blocked[nx][ny]) continue;\n                    if (dist[nx][ny] != -1) continue;\n                    dist[nx][ny] = dist[x][y] + 1;\n                    par[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n\n            Pos move_target = {-1, -1};\n\n            if (!all_prewalls_done) {\n                // Move toward nearest unbuilt pre-wall (prefer buildable)\n                int best_d = 1e9;\n                bool best_buildable = false;\n                Pos best_pos = {-1, -1};\n                for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                    if (prewall_built[j]) continue;\n                    int wx = pre_walls[j].x, wy = pre_walls[j].y;\n                    bool buildable = can_build(wx, wy);\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = wx + dx[d], ay = wy + dy[d];\n                        if (!in_bounds(ax, ay)) continue;\n                        if (dist[ax][ay] == -1) continue;\n                        if (buildable && !best_buildable) {\n                            best_buildable = true;\n                            best_d = dist[ax][ay];\n                            best_pos = {ax, ay};\n                        } else if (buildable == best_buildable && dist[ax][ay] < best_d) {\n                            best_d = dist[ax][ay];\n                            best_pos = {ax, ay};\n                        }\n                    }\n                }\n                if (best_pos.x != -1) {\n                    if (best_d == 0) {\n                        // Already adjacent but cannot build now (blocked by pet, etc). Wait.\n                        action[i] = '.';\n                        acted[i] = true;\n                        continue;\n                    } else {\n                        move_target = best_pos;\n                    }\n                }\n            } else if (!is_inside[i]) {\n                // Need to enter\n                if (gate.x != -1) {\n                    if (hx == gate.x && hy == gate.y && gate_inside.x != -1) {\n                        // Standing on gate, move inside\n                        action[i] = move_action(hx, hy, gate_inside.x, gate_inside.y);\n                        acted[i] = true;\n                        move_targets.insert({gate_inside.x, gate_inside.y});\n                        continue;\n                    } else if (dist[gate.x][gate.y] != -1) {\n                        if (dist[gate.x][gate.y] == 0) {\n                            // At gate? Already handled above.\n                            action[i] = '.';\n                            acted[i] = true;\n                            continue;\n                        } else {\n                            move_target = gate;\n                        }\n                    }\n                }\n            } else {\n                // Inside, pre-walls done. Just wait (gate will be closed by someone else or wait for all)\n                action[i] = '.';\n                acted[i] = true;\n                continue;\n            }\n\n            if (!acted[i] && move_target.x != -1 && dist[move_target.x][move_target.y] > 0) {\n                int cx = move_target.x, cy = move_target.y;\n                while (par[cx][cy] != make_pair(hx, hy)) {\n                    auto p = par[cx][cy];\n                    cx = p.first;\n                    cy = p.second;\n                }\n                action[i] = move_action(hx, hy, cx, cy);\n                acted[i] = true;\n                move_targets.insert({cx, cy});\n            } else if (!acted[i]) {\n                action[i] = '.';\n                acted[i] = true;\n            }\n        }\n\n        cout << action << endl;\n\n        // Apply human actions\n        for (int i = 0; i < M; ++i) {\n            char c = action[i];\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int wx = hx, wy = hy;\n                if (c == 'u') wx--;\n                else if (c == 'd') wx++;\n                else if (c == 'l') wy--;\n                else if (c == 'r') wy++;\n                if (in_bounds(wx, wy)) passable[wx][wy] = false;\n            } else if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int nx = hx, ny = hy;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    human_pos[i] = {nx, ny};\n                }\n            }\n        }\n\n        // Read pet movements\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            for (char c : s) {\n                int nx = pet_pos[i].x, ny = pet_pos[i].y;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    pet_pos[i] = {nx, ny};\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int H = 20;\nconst int W = 20;\nconst int N = H * W;\nconst int L = 200;\n\nint start_id, goal_id;\ndouble P, ONE_MINUS_P;\nint nxt_id[N][4];               // 0:U 1:D 2:L 3:R\nint dist_to_goal[N];\nchar DIRCHAR[4] = {'U', 'D', 'L', 'R'};\nint CMDMAP[256];\n\n// RNG\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> uniform01(0.0, 1.0);\n\n// ------------------------------------------------------------\n// full evaluation (standalone)\ndouble full_evaluate(const string& s) {\n    array<double, N> dp{}, ndp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    double score = 0.0;\n    for (int t = 0; t < (int)s.size(); ++t) {\n        int c = CMDMAP[(unsigned char)s[t]];\n        ndp.fill(0.0);\n        double imm = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            double stay = x * P;\n            double move = x * ONE_MINUS_P;\n            ndp[v] += stay;\n            int to = nxt_id[v][c];\n            if (to == goal_id) {\n                imm += move * (401 - (t + 1));\n            } else {\n                ndp[to] += move;\n            }\n        }\n        score += imm;\n        dp.swap(ndp);\n    }\n    return score;\n}\n\n// ------------------------------------------------------------\n// BFS shortest path (ignoring forgetting)\nvector<char> bfs_shortest_path() {\n    queue<int> q;\n    vector<int> dist(N, -1), par(N, -1), pc(N, -1);\n    dist[start_id] = 0;\n    q.push(start_id);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == goal_id) break;\n        for (int d = 0; d < 4; ++d) {\n            int u = nxt_id[v][d];\n            if (u != v && dist[u] == -1) {\n                dist[u] = dist[v] + 1;\n                par[u] = v;\n                pc[u] = d;\n                q.push(u);\n            }\n        }\n    }\n    if (dist[goal_id] == -1) return {};\n    vector<char> path;\n    int cur = goal_id;\n    while (cur != start_id) {\n        path.push_back(DIRCHAR[pc[cur]]);\n        cur = par[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// monotone D/R path\nvector<char> monotone_path(const vector<string>& hwall,\n                           const vector<string>& vwall,\n                           int si, int sj, int ti, int tj) {\n    vector<vector<bool>> reach(H, vector<bool>(W, false));\n    vector<vector<char>> from(H, vector<char>(W, 0));\n    reach[si][sj] = true;\n    for (int i = si; i <= ti; ++i) {\n        for (int j = sj; j <= tj; ++j) {\n            if (!reach[i][j]) continue;\n            if (i < ti && vwall[i][j] == '0' && !reach[i + 1][j]) {\n                reach[i + 1][j] = true;\n                from[i + 1][j] = 'D';\n            }\n            if (j < tj && hwall[i][j] == '0' && !reach[i][j + 1]) {\n                reach[i][j + 1] = true;\n                from[i][j + 1] = 'R';\n            }\n        }\n    }\n    if (!reach[ti][tj]) return {};\n    vector<char> path;\n    int i = ti, j = tj;\n    while (i != si || j != sj) {\n        char c = from[i][j];\n        path.push_back(c);\n        if (c == 'D') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// greedy open-loop path\nstring greedy_path() {\n    array<double, N> dp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    string s;\n    s.reserve(L);\n    for (int t = 0; t < L; ++t) {\n        int best_c = 3;\n        double best_cost = 1e100;\n        for (int c = 0; c < 4; ++c) {\n            double cost = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = dp[v];\n                if (x == 0.0) continue;\n                int to = nxt_id[v][c];\n                double d = (to == goal_id) ? 0.0 : (double)dist_to_goal[to];\n                cost += x * (P * (double)dist_to_goal[v] + ONE_MINUS_P * d);\n            }\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_c = c;\n            }\n        }\n        s.push_back(DIRCHAR[best_c]);\n        array<double, N> ndp{};\n        ndp.fill(0.0);\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            ndp[v] += x * P;\n            int to = nxt_id[v][best_c];\n            if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n        }\n        dp.swap(ndp);\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Local search structure\nstruct Solver {\n    string cur;\n    double cur_score;\n    vector<array<double, N>> fw;   // size L+1\n    vector<array<double, N>> b;    // size L+1\n    vector<double> pref;           // size L+1\n\n    void init(const string& s) {\n        cur = s;\n        fw.assign(L + 1, {});\n        b.assign(L + 1, {});\n        pref.assign(L + 1, 0.0);\n        fw[0].fill(0.0);\n        fw[0][start_id] = 1.0;\n        for (int t = 0; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        b[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n\n    // O(N) evaluation of changing position pos to command cmd (0..3)\n    double try_mutate(int pos, int cmd) const {\n        double reward = (401 - (pos + 1)) * ONE_MINUS_P;\n        double dot = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double val = P * b[pos + 1][v];\n            int to = nxt_id[v][cmd];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * b[pos + 1][to];\n            dot += fw[pos][v] * val;\n        }\n        return pref[pos] + dot;\n    }\n\n    // apply mutation and incrementally update tables\n    void apply_mutate(int pos, int cmd) {\n        cur[pos] = DIRCHAR[cmd];\n        // forward recompute from pos\n        for (int t = pos; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        // backward recompute from pos down to 0\n        for (int t = pos; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n};\n\n// ------------------------------------------------------------\n// Hill climbing with optional wall-clock limit\nvoid hill_climb(Solver& sol, const function<double()>& elapsed, double time_limit = 1e100) {\n    bool improved = true;\n    while (improved) {\n        if (elapsed() > time_limit) break;\n        improved = false;\n        for (int i = 0; i < L; ++i) {\n            int cur_cmd = CMDMAP[(unsigned char)sol.cur[i]];\n            int best_cmd = cur_cmd;\n            double best_sc = sol.cur_score;\n            for (int d = 0; d < 3; ++d) {\n                int nc = (cur_cmd + 1 + d) & 3;\n                double sc = sol.try_mutate(i, nc);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    best_cmd = nc;\n                }\n            }\n            if (best_cmd != cur_cmd) {\n                sol.apply_mutate(i, best_cmd);\n                improved = true;\n            }\n        }\n    }\n}\n\nstring perturb(const string& s, int k) {\n    string r = s;\n    for (int i = 0; i < k; ++i) {\n        int pos = rng() % L;\n        r[pos] = DIRCHAR[rng() % 4];\n    }\n    return r;\n}\n\n// generic SA runner\nvoid run_sa(Solver& sol, int max_iter, double time_limit,\n            const function<double()>& elapsed, double T0) {\n    const double T_end = 1e-4;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        if ((iter & 1023) == 0 && elapsed() > time_limit) break;\n        double T = T0 * pow(T_end / T0, (double)iter / max_iter);\n        int pos = rng() % L;\n        int cur_cmd = CMDMAP[(unsigned char)sol.cur[pos]];\n        int best_cmd = cur_cmd;\n        double best_mut_sc = sol.cur_score;\n        for (int d = 0; d < 3; ++d) {\n            int nc = (cur_cmd + 1 + d) & 3;\n            double sc = sol.try_mutate(pos, nc);\n            if (sc > best_mut_sc) {\n                best_mut_sc = sc;\n                best_cmd = nc;\n            }\n        }\n        if (best_cmd != cur_cmd) {\n            bool accept = false;\n            if (best_mut_sc >= sol.cur_score) {\n                accept = true;\n            } else if (T > 1e-12) {\n                if (uniform01(rng) < exp((best_mut_sc - sol.cur_score) / T))\n                    accept = true;\n            }\n            if (accept) sol.apply_mutate(pos, best_cmd);\n        }\n    }\n}\n\n// ------------------------------------------------------------\n// Beam search with closed-loop upper bound\nstring beam_search(const vector<array<double, N>>& V) {\n    const int MAX_B = 500; // moderate width, fast enough\n\n    struct Cand {\n        double pref;\n        double ub;\n        int par_id;\n        char c;\n    };\n\n    vector<double> node_pref;\n    vector<int> parent;\n    vector<char> pcmd;\n    vector<int> layer_start;\n\n    node_pref.reserve((L + 1) * MAX_B);\n    parent.reserve((L + 1) * MAX_B);\n    pcmd.reserve((L + 1) * MAX_B);\n\n    node_pref.push_back(0.0);\n    parent.push_back(-1);\n    pcmd.push_back(0);\n    layer_start.push_back(0);\n    layer_start.push_back(1);\n\n    vector<int> cur_id(1, 0);\n    vector<array<double, N>> cur_fw(1);\n    cur_fw[0].fill(0.0);\n    cur_fw[0][start_id] = 1.0;\n\n    for (int t = 0; t < L; ++t) {\n        int cur_sz = (int)cur_id.size();\n        const double* vt = V[t + 1].data();\n        double reward = 401.0 - (t + 1);\n\n        vector<Cand> cands;\n        cands.reserve(cur_sz * 4);\n\n        for (int idx = 0; idx < cur_sz; ++idx) {\n            int gid = cur_id[idx];\n            const array<double, N>& fw = cur_fw[idx];\n            double sum_base = 0.0;\n            for (int v = 0; v < N; ++v) sum_base += fw[v] * vt[v];\n            for (int cmd = 0; cmd < 4; ++cmd) {\n                double dot_move = 0.0;\n                double goal_mass = 0.0;\n                for (int v = 0; v < N; ++v) {\n                    int to = nxt_id[v][cmd];\n                    if (to == goal_id) goal_mass += fw[v];\n                    else dot_move += fw[v] * vt[to];\n                }\n                double pref_new = node_pref[gid] + goal_mass * ONE_MINUS_P * reward;\n                double ub = pref_new + P * sum_base + ONE_MINUS_P * dot_move;\n                cands.push_back({pref_new, ub, gid, DIRCHAR[cmd]});\n            }\n        }\n\n        int keep = min((int)cands.size(), MAX_B);\n        nth_element(cands.begin(), cands.begin() + keep, cands.end(),\n                    [](const Cand& a, const Cand& b) { return a.ub > b.ub; });\n\n        vector<int> next_id;\n        next_id.reserve(keep);\n        vector<array<double, N>> next_fw;\n        next_fw.reserve(keep);\n\n        for (int i = 0; i < keep; ++i) {\n            const Cand& lc = cands[i];\n            int new_id = (int)node_pref.size();\n            node_pref.push_back(lc.pref);\n            parent.push_back(lc.par_id);\n            pcmd.push_back(lc.c);\n            next_id.push_back(new_id);\n\n            int par_idx = lc.par_id - layer_start[t];\n            const array<double, N>& pfw = cur_fw[par_idx];\n            array<double, N> ndp;\n            ndp.fill(0.0);\n            int cmd = CMDMAP[(unsigned char)lc.c];\n            for (int v = 0; v < N; ++v) {\n                double x = pfw[v];\n                ndp[v] += x * P;\n                int to = nxt_id[v][cmd];\n                if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n            }\n            next_fw.push_back(ndp);\n        }\n\n        cur_id.swap(next_id);\n        cur_fw.swap(next_fw);\n        layer_start.push_back((int)node_pref.size());\n    }\n\n    double best_score = -1.0;\n    int best_leaf = -1;\n    for (int gid : cur_id) {\n        if (node_pref[gid] > best_score) {\n            best_score = node_pref[gid];\n            best_leaf = gid;\n        }\n    }\n    if (best_leaf == -1) return string(L, 'D');\n\n    string beam_str(L, '?');\n    int cur = best_leaf;\n    for (int t = L - 1; t >= 0; --t) {\n        beam_str[t] = pcmd[cur];\n        cur = parent[cur];\n    }\n    return beam_str;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    CMDMAP['U'] = 0; CMDMAP['D'] = 1; CMDMAP['L'] = 2; CMDMAP['R'] = 3;\n\n    int si, sj, ti, tj;\n    double p_input;\n    if (!(cin >> si >> sj >> ti >> tj >> p_input)) return 0;\n    P = p_input;\n    ONE_MINUS_P = 1.0 - P;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; ++i) cin >> hwall[i];\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; ++i) cin >> vwall[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int v = i * W + j;\n            if (i > 0 && vwall[i - 1][j] == '0') nxt_id[v][0] = (i - 1) * W + j;\n            else nxt_id[v][0] = v;\n            if (i + 1 < H && vwall[i][j] == '0') nxt_id[v][1] = (i + 1) * W + j;\n            else nxt_id[v][1] = v;\n            if (j > 0 && hwall[i][j - 1] == '0') nxt_id[v][2] = i * W + (j - 1);\n            else nxt_id[v][2] = v;\n            if (j + 1 < W && hwall[i][j] == '0') nxt_id[v][3] = i * W + (j + 1);\n            else nxt_id[v][3] = v;\n        }\n    }\n\n    // distances to goal (real graph distance)\n    {\n        queue<int> q;\n        vector<int> dist(N, -1);\n        dist[goal_id] = 0;\n        q.push(goal_id);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int u = nxt_id[v][d];\n                if (u != v && dist[u] == -1) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) dist_to_goal[i] = dist[i];\n    }\n\n    // closed-loop upper bound V[t][v]\n    vector<array<double, N>> V(L + 1);\n    for (int v = 0; v < N; ++v) V[L][v] = 0.0;\n    for (int t = L - 1; t >= 0; --t) {\n        double reward = 401.0 - (t + 1);\n        for (int v = 0; v < N; ++v) {\n            if (v == goal_id) {\n                V[t][v] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int c = 0; c < 4; ++c) {\n                int to = nxt_id[v][c];\n                double val = P * V[t + 1][v];\n                if (to == goal_id) val += ONE_MINUS_P * reward;\n                else val += ONE_MINUS_P * V[t + 1][to];\n                if (val > best) best = val;\n            }\n            V[t][v] = best;\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    // ---------- generate candidates ----------\n    vector<string> candidates;\n    auto make_repeat = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        string s;\n        while ((int)s.size() < L) s += string(path.begin(), path.end());\n        s.resize(L);\n        return s;\n    };\n    auto make_stretch = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        int rep = max(1, L / (int)path.size());\n        string s;\n        for (char c : path) s += string(rep, c);\n        while ((int)s.size() < L) s.push_back(path[s.size() % path.size()]);\n        s.resize(L);\n        return s;\n    };\n\n    vector<char> sp = bfs_shortest_path();\n    if (!sp.empty()) {\n        candidates.push_back(make_repeat(sp));\n        candidates.push_back(make_stretch(sp));\n    }\n    vector<char> mono = monotone_path(hwall, vwall, si, sj, ti, tj);\n    if (!mono.empty()) {\n        candidates.push_back(make_repeat(mono));\n        candidates.push_back(make_stretch(mono));\n    }\n    candidates.push_back(greedy_path());\n\n    // raw directional candidates\n    {\n        string s(L, 'D');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needD); ++i) s[i] = 'D';\n        for (; i < min(L, needD + needR); ++i) s[i] = 'R';\n        candidates.push_back(s);\n    }\n    {\n        string s(L, 'R');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needR); ++i) s[i] = 'R';\n        for (; i < min(L, needR + needD); ++i) s[i] = 'D';\n        candidates.push_back(s);\n    }\n    for (int k = 0; k < 10; ++k) {\n        string s;\n        for (int i = 0; i < L; ++i) {\n            int r = rng() % 100;\n            if (r < 45) s += 'D';\n            else if (r < 90) s += 'R';\n            else if (r < 95) s += 'L';\n            else s += 'U';\n        }\n        candidates.push_back(s);\n    }\n\n    // beam search candidate\n    candidates.push_back(beam_search(V));\n\n    // evaluate all\n    string best_str(L, 'R');\n    double best_score = -1.0;\n    for (auto& s : candidates) {\n        if ((int)s.size() != L) continue;\n        double sc = full_evaluate(s);\n        if (sc > best_score) {\n            best_score = sc;\n            best_str = s;\n        }\n    }\n\n    // ---------- hill climb + SA from best ----------\n    Solver solver;\n    solver.init(best_str);\n    hill_climb(solver, elapsed);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    // sample diffs to set SA temperature\n    vector<double> diffs;\n    for (int k = 0; k < 1000; ++k) {\n        int pos = rng() % L;\n        int cur_cmd = CMDMAP[(unsigned char)solver.cur[pos]];\n        int nd = (cur_cmd + 1 + (rng() % 3)) & 3;\n        double sc = solver.try_mutate(pos, nd);\n        if (sc < solver.cur_score) diffs.push_back(solver.cur_score - sc);\n    }\n    sort(diffs.begin(), diffs.end());\n    double T0 = 1.0;\n    if (!diffs.empty()) {\n        T0 = diffs[min((int)diffs.size() - 1, (int)(diffs.size() * 9 / 10))];\n        if (T0 < 1.0) T0 = 1.0;\n    }\n\n    run_sa(solver, 300000, 1.90, elapsed, T0);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    // ---------- a few safe restarts ----------\n    for (int rep = 0; rep < 3; ++rep) {\n        if (elapsed() > 1.96) break;\n        string p = perturb(best_str, 5 + rep);\n        Solver rs;\n        rs.init(p);\n        hill_climb(rs, elapsed, 1.97);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n        }\n        if (elapsed() > 1.97) break;\n        run_sa(rs, 20000, 1.98, elapsed, T0);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n        }\n    }\n\n    cout << best_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static const int N = 30;\n    static const int V = N * N;          // 900\n    static const int S = V * 4;          // 3600\n\n    struct Vec4 {\n        int v[4];\n        int sz;\n        void clear() { sz = 0; }\n        void push(int x) { v[sz++] = x; }\n        int sum() const {\n            int s = 0;\n            for (int i = 0; i < sz; ++i) s += v[i];\n            return s;\n        }\n    };\n\n    int base[V];\n    unsigned char rot[V];\n    unsigned char best_rot[V];\n\n    // precomputed successor: cell idx, rotation r, entry dir d\n    int16_t pre_nxt[V][4][4];\n\n    int8_t to_tbl[8][4];\n    int ft[8][4];\n    const int di[4] = {0, -1, 0, 1};\n    const int dj[4] = {-1, 0, 1, 0};\n\n    // current graph\n    int16_t nxt[S];\n\n    // cycle statistics\n    int cnt[3601];\n    int total_len;\n    set<int> active_lens;\n    int best1, best2;\n    int best_score;\n\n    // visited arrays for cycle detection\n    int state_vis[S];\n    int cycle_vis[S];\n    int vis_token;\n    int cycle_token;\n\n    // random\n    uint64_t rng;\n    uint64_t rand64() {\n        uint64_t z = (rng += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int rand_int(int m) { return (int)(rand64() % (uint64_t)m); }\n\n    // ------------------------------------------------------------\n    // count of length 'len' after removing oldv and adding newv\n    // ------------------------------------------------------------\n    inline int adj_cnt(int len, const Vec4& oldv, const Vec4& newv) const {\n        int c = cnt[len];\n        for (int i = 0; i < oldv.sz; ++i) if (oldv.v[i] == len) --c;\n        for (int i = 0; i < newv.sz; ++i) if (newv.v[i] == len) ++c;\n        return c;\n    }\n\n    int find_best1(const Vec4& oldv, const Vec4& newv) const {\n        int max_new = 0;\n        for (int i = 0; i < newv.sz; ++i) max_new = max(max_new, newv.v[i]);\n        for (auto it = active_lens.rbegin(); it != active_lens.rend(); ++it) {\n            int len = *it;\n            if (len < max_new) break;\n            if (adj_cnt(len, oldv, newv) > 0) return len;\n        }\n        return max_new;\n    }\n\n    int find_best2(int b1, const Vec4& oldv, const Vec4& newv) const {\n        if (b1 == 0) return 0;\n        if (adj_cnt(b1, oldv, newv) >= 2) return b1;\n        int b2 = 0;\n        for (int i = 0; i < newv.sz; ++i) {\n            int L = newv.v[i];\n            if (L != b1 && L > b2) b2 = L;\n        }\n        for (auto it = active_lens.rbegin(); it != active_lens.rend(); ++it) {\n            int len = *it;\n            if (len <= b2) break;\n            if (len == b1) continue;\n            if (adj_cnt(len, oldv, newv) > 0) {\n                b2 = len;\n                break;\n            }\n        }\n        return b2;\n    }\n\n    void update_globals(const Vec4& oldv, const Vec4& newv) {\n        for (int i = 0; i < oldv.sz; ++i) {\n            int L = oldv.v[i];\n            if (--cnt[L] == 0) active_lens.erase(L);\n            total_len -= L;\n        }\n        for (int i = 0; i < newv.sz; ++i) {\n            int L = newv.v[i];\n            if (cnt[L]++ == 0) active_lens.insert(L);\n            total_len += L;\n        }\n        if (active_lens.empty()) {\n            best1 = best2 = 0;\n        } else {\n            auto it = active_lens.rbegin();\n            best1 = *it;\n            if (cnt[best1] >= 2) best2 = best1;\n            else {\n                ++it;\n                best2 = (it == active_lens.rend()) ? 0 : *it;\n            }\n        }\n    }\n\n    inline int get_score() const { return best1 * best2; }\n    inline int64_t eval_val(int b1, int b2, int tot) const {\n        return (int64_t)b1 * b2 * 1000LL + tot;\n    }\n\n    // ------------------------------------------------------------\n    // find all cycles that contain at least one of st[0..3]\n    // each cycle is reported exactly once\n    // ------------------------------------------------------------\n    Vec4 find_cycles(const int st[4]) {\n        Vec4 res;\n        res.clear();\n        int my_cycle = ++cycle_token;\n\n        for (int k = 0; k < 4; ++k) {\n            int s = st[k];\n            if (nxt[s] == -1) continue;\n            if (cycle_vis[s] == my_cycle) continue;\n\n            int my_vis = ++vis_token;\n            int cur = s;\n            int len = 0;\n            while (cur != -1 && state_vis[cur] != my_vis) {\n                state_vis[cur] = my_vis;\n                cur = nxt[cur];\n                ++len;\n                if (len > S) break;\n            }\n            if (cur == s) {\n                res.push(len);\n                int c = s;\n                do {\n                    cycle_vis[c] = my_cycle;\n                    c = nxt[c];\n                } while (c != s);\n            }\n        }\n        return res;\n    }\n\n    // ------------------------------------------------------------\n    // full rebuild of graph and cycle statistics from rot[]\n    // ------------------------------------------------------------\n    void rebuild_from_rot() {\n        for (int s = 0; s < S; ++s) nxt[s] = -1;\n        for (int idx = 0; idx < V; ++idx) {\n            int s0 = idx * 4;\n            int r = rot[idx];\n            for (int d = 0; d < 4; ++d) nxt[s0 + d] = pre_nxt[idx][r][d];\n        }\n\n        memset(cnt, 0, sizeof(cnt));\n        total_len = 0;\n        active_lens.clear();\n\n        static uint8_t mark[S];\n        static int path_nodes[S];\n        memset(mark, 0, sizeof(mark));\n\n        for (int s = 0; s < S; ++s) {\n            if (nxt[s] == -1 || mark[s]) continue;\n            int cur = s;\n            int path_len = 0;\n            while (cur != -1 && mark[cur] == 0) {\n                mark[cur] = 1;\n                path_nodes[path_len++] = cur;\n                cur = nxt[cur];\n            }\n            if (cur != -1 && mark[cur] == 1) {\n                int cycle_len = 0;\n                for (int i = path_len - 1; i >= 0; --i) {\n                    ++cycle_len;\n                    if (path_nodes[i] == cur) break;\n                }\n                cnt[cycle_len]++;\n                total_len += cycle_len;\n                active_lens.insert(cycle_len);\n            }\n            for (int i = 0; i < path_len; ++i) mark[path_nodes[i]] = 2;\n        }\n\n        if (active_lens.empty()) {\n            best1 = best2 = 0;\n        } else {\n            auto it = active_lens.rbegin();\n            best1 = *it;\n            if (cnt[best1] >= 2) best2 = best1;\n            else {\n                ++it;\n                best2 = (it == active_lens.rend()) ? 0 : *it;\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    void solve() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n        for (int i = 0; i < N; ++i) {\n            string line;\n            cin >> line;\n            for (int j = 0; j < N; ++j) base[i * N + j] = line[j] - '0';\n        }\n\n        const int8_t to_arr[8][4] = {\n            {1,0,-1,-1}, {3,-1,-1,0}, {-1,-1,3,2}, {-1,2,1,-1},\n            {1,0,3,2},   {3,2,1,0},   {2,-1,0,-1}, {-1,3,-1,1}\n        };\n        memcpy(to_tbl, to_arr, sizeof(to_arr));\n        for (int b = 0; b < 8; ++b) {\n            for (int r = 0; r < 4; ++r) {\n                if (b < 4) ft[b][r] = (b + r) & 3;\n                else if (b < 6) ft[b][r] = 4 + ((b - 4 + r) & 1);\n                else ft[b][r] = 6 + ((b - 6 + r) & 1);\n            }\n        }\n\n        for (int idx = 0; idx < V; ++idx) {\n            int i = idx / N, j = idx % N;\n            for (int r = 0; r < 4; ++r) {\n                int t = ft[base[idx]][r];\n                for (int d = 0; d < 4; ++d) {\n                    int d2 = to_tbl[t][d];\n                    if (d2 == -1) {\n                        pre_nxt[idx][r][d] = -1;\n                    } else {\n                        int ni = i + di[d2];\n                        int nj = j + dj[d2];\n                        if (ni < 0 || ni >= N || nj < 0 || nj >= N)\n                            pre_nxt[idx][r][d] = -1;\n                        else\n                            pre_nxt[idx][r][d] = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                    }\n                }\n            }\n        }\n\n        rng = chrono::steady_clock::now().time_since_epoch().count();\n        vis_token = 0;\n        cycle_token = 0;\n\n        // ----- greedy init : avoid edges leaving the board ----------------\n        for (int idx = 0; idx < V; ++idx) {\n            int b = base[idx];\n            int best_r = 0, best_sc = -1;\n            if (b < 4) {\n                for (int r = 0; r < 4; ++r) {\n                    int sc = 0;\n                    for (int d = 0; d < 4; ++d) if (pre_nxt[idx][r][d] != -1) ++sc;\n                    if (sc > best_sc) { best_sc = sc; best_r = r; }\n                }\n            } else {\n                for (int r = 0; r < 2; ++r) {\n                    int sc = 0;\n                    for (int d = 0; d < 4; ++d) if (pre_nxt[idx][r][d] != -1) ++sc;\n                    if (sc > best_sc) { best_sc = sc; best_r = r; }\n                }\n            }\n            rot[idx] = (unsigned char)best_r;\n        }\n\n        rebuild_from_rot();\n        best_score = get_score();\n        memcpy(best_rot, rot, V);\n\n        const double TL = 1.9;\n        clock_t start = clock();\n        auto elapsed = [&]() { return double(clock() - start) / CLOCKS_PER_SEC; };\n\n        // ----- Simulated Annealing ------------------------------------\n        double T0 = 1e7;\n        double T1 = 1.0;\n        double logT0 = log(T0);\n        double logT1 = log(T1);\n\n        while (elapsed() < TL - 0.2) {\n            double p = elapsed() / (TL - 0.2);\n            double T = exp(logT0 + (logT1 - logT0) * p);\n\n            int idx = rand_int(V);\n            int s0 = idx * 4;\n            int st[4] = {s0, s0 + 1, s0 + 2, s0 + 3};\n\n            Vec4 oldv = find_cycles(st);\n            int sum_old = oldv.sum();\n\n            // detach\n            int orig_nxt[4];\n            for (int k = 0; k < 4; ++k) {\n                orig_nxt[k] = nxt[st[k]];\n                nxt[st[k]] = -1;\n            }\n\n            int cur_r = rot[idx];\n            int best_r = cur_r;\n            int64_t best_val = -(1LL << 60);\n            Vec4 best_newv;\n            best_newv.clear();\n\n            int alts[3], nalt = 0;\n            if (base[idx] < 4) {\n                for (int d = 1; d < 4; ++d) alts[nalt++] = (cur_r + d) & 3;\n            } else {\n                alts[nalt++] = cur_r ^ 1;\n            }\n\n            for (int a = 0; a < nalt; ++a) {\n                int nr = alts[a];\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][nr][k];\n\n                Vec4 newv = find_cycles(st);\n                int sum_new = newv.sum();\n                int b1 = find_best1(oldv, newv);\n                int b2 = find_best2(b1, oldv, newv);\n                int alt_tot = total_len - sum_old + sum_new;\n                int64_t val = eval_val(b1, b2, alt_tot);\n\n                if (val > best_val) {\n                    best_val = val;\n                    best_r = nr;\n                    best_newv = newv;\n                }\n\n                // detach for next alternative\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = -1;\n            }\n\n            // restore original edges\n            for (int k = 0; k < 4; ++k) nxt[st[k]] = (int16_t)orig_nxt[k];\n\n            if (best_r != cur_r) {\n                int64_t cur_val = eval_val(best1, best2, total_len);\n                int64_t delta = best_val - cur_val;\n                bool accept = false;\n                if (delta > 0) {\n                    accept = true;\n                } else {\n                    double prob = exp((double)delta / T);\n                    double r = (rand64() >> 11) * (1.0 / (1ULL << 53));\n                    if (r < prob) accept = true;\n                }\n\n                if (accept) {\n                    update_globals(oldv, best_newv);\n                    rot[idx] = (unsigned char)best_r;\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][best_r][k];\n                    int sc = get_score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        memcpy(best_rot, rot, V);\n                    }\n                }\n            }\n        }\n\n        // ----- Hill climbing polish -----------------------------------\n        memcpy(rot, best_rot, V);\n        rebuild_from_rot();\n\n        bool improved = true;\n        while (improved && elapsed() < TL) {\n            improved = false;\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine((unsigned)rand64()));\n\n            for (int idx : order) {\n                if (elapsed() >= TL) break;\n                int s0 = idx * 4;\n                int st[4] = {s0, s0 + 1, s0 + 2, s0 + 3};\n\n                Vec4 oldv = find_cycles(st);\n                int sum_old = oldv.sum();\n\n                int orig_nxt[4];\n                for (int k = 0; k < 4; ++k) {\n                    orig_nxt[k] = nxt[st[k]];\n                    nxt[st[k]] = -1;\n                }\n\n                int cur_r = rot[idx];\n                int best_r = cur_r;\n                int64_t best_val = eval_val(best1, best2, total_len);\n                Vec4 best_newv;\n                best_newv.clear();\n\n                int alts[3], nalt = 0;\n                if (base[idx] < 4) {\n                    for (int d = 1; d < 4; ++d) alts[nalt++] = (cur_r + d) & 3;\n                } else {\n                    alts[nalt++] = cur_r ^ 1;\n                }\n\n                for (int a = 0; a < nalt; ++a) {\n                    int nr = alts[a];\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][nr][k];\n\n                    Vec4 newv = find_cycles(st);\n                    int sum_new = newv.sum();\n                    int b1 = find_best1(oldv, newv);\n                    int b2 = find_best2(b1, oldv, newv);\n                    int alt_tot = total_len - sum_old + sum_new;\n                    int64_t val = eval_val(b1, b2, alt_tot);\n\n                    if (val > best_val) {\n                        best_val = val;\n                        best_r = nr;\n                        best_newv = newv;\n                    }\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = -1;\n                }\n\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = (int16_t)orig_nxt[k];\n\n                if (best_r != cur_r) {\n                    update_globals(oldv, best_newv);\n                    rot[idx] = (unsigned char)best_r;\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][best_r][k];\n                    int sc = get_score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        memcpy(best_rot, rot, V);\n                    }\n                    improved = true;\n                }\n            }\n        }\n\n        // ----- output -------------------------------------------------\n        string out;\n        out.reserve(V);\n        for (int i = 0; i < V; ++i) out.push_back(char('0' + best_rot[i]));\n        cout << out << '\\n';\n    }\n};\n\nint main() {\n    Solver s;\n    s.solve();\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T, SZ, TARGET;\n\n/* U,D,L,R */\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dc[4] = {'U', 'D', 'L', 'R'};\nconst int opp[4] = {1, 0, 3, 2};\n\ninline bool inside(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N;\n}\n\nstruct State {\n    array<uint8_t, 100> b;   // 0 = empty\n    int epos;\n};\n\nstruct Eval {\n    int actual;   // size of largest tree component\n    int edges;    // total number of good edges\n};\n\ninline int combined(const Eval& e) {\n    return (e.actual << 10) + e.edges;   // actual*1024 + edges  (edges < 1024)\n}\n\n/* ------------------------------------------------------------------ */\n/*  Fast evaluation                                                   */\n/* ------------------------------------------------------------------ */\nEval evaluate(const array<uint8_t, 100>& b) {\n    int edges = 0;\n\n    // horizontal\n    for (int i = 0; i < N; ++i) {\n        int base = i * N;\n        for (int j = 0; j + 1 < N; ++j) {\n            int t1 = b[base + j];\n            int t2 = b[base + j + 1];\n            if (t1 && t2 && (t1 & 4) && (t2 & 1)) ++edges;\n        }\n    }\n    // vertical\n    for (int i = 0; i + 1 < N; ++i) {\n        int base = i * N;\n        for (int j = 0; j < N; ++j) {\n            int t1 = b[base + j];\n            int t2 = b[base + j + N];\n            if (t1 && t2 && (t1 & 8) && (t2 & 2)) ++edges;\n        }\n    }\n\n    uint8_t vis[100] = {0};\n    int best_actual = 0;\n    int q[100];\n    int cells[100];\n\n    for (int idx = 0; idx < SZ; ++idx) {\n        if (!b[idx] || vis[idx]) continue;\n\n        int qs = 0, qe = 0;\n        q[qe++] = idx;\n        vis[idx] = 1;\n        int vcnt = 0;\n\n        while (qs < qe) {\n            int u = q[qs++];\n            cells[vcnt++] = u;\n            int t = b[u];\n            int ui = u / N;\n            int uj = u % N;\n\n            if (ui && !vis[u - N] && b[u - N] && (t & 2) && (b[u - N] & 8)) {\n                vis[u - N] = 1; q[qe++] = u - N;\n            }\n            if (ui + 1 < N && !vis[u + N] && b[u + N] && (t & 8) && (b[u + N] & 2)) {\n                vis[u + N] = 1; q[qe++] = u + N;\n            }\n            if (uj && !vis[u - 1] && b[u - 1] && (t & 1) && (b[u - 1] & 4)) {\n                vis[u - 1] = 1; q[qe++] = u - 1;\n            }\n            if (uj + 1 < N && !vis[u + 1] && b[u + 1] && (t & 4) && (b[u + 1] & 1)) {\n                vis[u + 1] = 1; q[qe++] = u + 1;\n            }\n        }\n\n        int ecnt = 0;\n        for (int k = 0; k < vcnt; ++k) {\n            int u = cells[k];\n            int ui = u / N;\n            int uj = u % N;\n            int t = b[u];\n            if (uj + 1 < N && b[u + 1] && (t & 4) && (b[u + 1] & 1)) ++ecnt;\n            if (ui + 1 < N && b[u + N] && (t & 8) && (b[u + N] & 2)) ++ecnt;\n        }\n        if (ecnt == vcnt - 1 && vcnt > best_actual) best_actual = vcnt;\n    }\n    return {best_actual, edges};\n}\n\n/* ------------------------------------------------------------------ */\nState apply_move(const State& s, int d) {\n    State ns = s;\n    int ei = s.epos / N;\n    int ej = s.epos % N;\n    int ni = ei + di[d];\n    int nj = ej + dj[d];\n    int npos = ni * N + nj;\n    ns.b[s.epos] = s.b[npos];\n    ns.b[npos] = 0;\n    ns.epos = npos;\n    return ns;\n}\n\ninline int char2dir(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Iterative Deepening DFS (1 .. max_depth)                         */\n/*  Searches for a path that strictly improves 'combined'.           */\n/*  Returns empty string if nothing is found.                        */\n/* ------------------------------------------------------------------ */\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\nint g_start_actual;\nint g_start_combined;\nint g_best_combined;\nstring g_best_seq;\n\nbool dfs_ida(const State& s, int depth, int max_depth, int last_dir, string& cur) {\n    if (depth == max_depth) return false;\n\n    int order[4] = {0, 1, 2, 3};\n    for (int i = 3; i > 0; --i) swap(order[i], order[rng() % (i + 1)]);\n\n    for (int idx = 0; idx < 4; ++idx) {\n        int d = order[idx];\n        if (last_dir != -1 && d == opp[last_dir]) continue;\n        int ei = s.epos / N;\n        int ej = s.epos % N;\n        if (!inside(ei + di[d], ej + dj[d])) continue;\n\n        State ns = apply_move(s, d);\n        Eval ev = evaluate(ns.b);\n        int c = combined(ev);\n\n        if (c > g_best_combined) {\n            g_best_combined = c;\n            g_best_seq = cur + dc[d];\n        }\n\n        if (ev.actual > g_start_actual) {\n            return true;                 // found a real tree improvement!\n        }\n\n        // allow temporary loss of up to ~5 actual vertices (5120) plus edge drop\n        if (c >= g_start_combined - 5500) {\n            cur.push_back(dc[d]);\n            if (dfs_ida(ns, depth + 1, max_depth, d, cur)) return true;\n            cur.pop_back();\n        }\n    }\n    return false;\n}\n\nstring ida_search(const State& s, int start_actual, int start_combined, int max_depth) {\n    g_start_actual = start_actual;\n    g_start_combined = start_combined;\n    g_best_combined = start_combined;\n    g_best_seq.clear();\n\n    string cur;\n    for (int d = 1; d <= max_depth; ++d) {\n        if (dfs_ida(s, 0, d, -1, cur)) {\n            return g_best_seq;           // actual improvement found\n        }\n        if (g_best_combined > start_combined) {\n            return g_best_seq;           // combined improvement (same actual, more edges)\n        }\n    }\n    return \"\";                           // stuck\n}\n\n/* ------------------------------------------------------------------ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    SZ = N * N;\n    TARGET = SZ - 1;\n\n    State init{};\n    init.epos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int v = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;\n            init.b[i * N + j] = static_cast<uint8_t>(v);\n            if (v == 0) init.epos = i * N + j;\n        }\n    }\n\n    Eval ev0 = evaluate(init.b);\n    int best_actual = ev0.actual;\n    if (best_actual == TARGET) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    State best_state = init;\n    string best_path;\n\n    auto start_tp = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.85;\n\n    State cur = init;\n    string cur_path;\n    Eval cur_ev = ev0;\n\n    int stuck_count = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_tp).count();\n        if (elapsed > TIME_LIMIT) break;\n        if (best_actual == TARGET) break;\n\n        bool made_progress = false;\n\n        /* -------- greedy hill climbing on combined score -------- */\n        while ((int)cur_path.size() < T) {\n            int last_dir = cur_path.empty() ? -1 : char2dir(cur_path.back());\n\n            int best_d = -1;\n            int best_c = -1;\n            State best_ns{};\n            Eval best_ev{};\n\n            int order[4] = {0, 1, 2, 3};\n            for (int i = 3; i > 0; --i) swap(order[i], order[rng() % (i + 1)]);\n\n            for (int idx = 0; idx < 4; ++idx) {\n                int d = order[idx];\n                if (last_dir != -1 && d == opp[last_dir]) continue;\n                int ei = cur.epos / N;\n                int ej = cur.epos % N;\n                if (!inside(ei + di[d], ej + dj[d])) continue;\n\n                State ns = apply_move(cur, d);\n                Eval ev = evaluate(ns.b);\n                int c = combined(ev);\n                if (c > best_c) {\n                    best_c = c;\n                    best_d = d;\n                    best_ns = ns;\n                    best_ev = ev;\n                }\n            }\n\n            if (best_d != -1 && best_c > combined(cur_ev)) {\n                cur = best_ns;\n                cur_path.push_back(dc[best_d]);\n                cur_ev = best_ev;\n                if (cur_ev.actual > best_actual) {\n                    best_actual = cur_ev.actual;\n                    best_state = cur;\n                    best_path = cur_path;\n                }\n                made_progress = true;\n            } else {\n                break;\n            }\n        }\n        if (best_actual == TARGET) break;\n\n        /* -------- iterative deepening lookahead -------- */\n        if ((int)cur_path.size() < T) {\n            int remain = T - (int)cur_path.size();\n            int max_depth = min(8, remain);\n            if (cur_ev.actual >= TARGET - 5) max_depth = min(12, remain);\n            if (cur_ev.actual >= TARGET - 2) max_depth = min(15, remain);\n\n            string seq = ida_search(cur, cur_ev.actual, combined(cur_ev), max_depth);\n            if (!seq.empty()) {\n                for (char c : seq) {\n                    int d = char2dir(c);\n                    cur = apply_move(cur, d);\n                    cur_path.push_back(c);\n                }\n                cur_ev = evaluate(cur.b);\n                if (cur_ev.actual > best_actual) {\n                    best_actual = cur_ev.actual;\n                    best_state = cur;\n                    best_path = cur_path;\n                }\n                made_progress = true;\n            }\n        }\n        if (best_actual == TARGET) break;\n\n        /* -------- kick / restart -------- */\n        if (!made_progress) {\n            ++stuck_count;\n\n            // gradually lengthen kick\n            int kick_len = 8 + stuck_count * 4;\n            if (kick_len > 120) kick_len = 120;\n\n            // choose restart base\n            if (stuck_count % 3 == 0 && !best_path.empty()\n                && (int)best_path.size() + kick_len + 20 <= T) {\n                cur = best_state;\n                cur_path = best_path;\n            } else if (stuck_count % 5 == 0 || (int)cur_path.size() + kick_len > T) {\n                cur = init;\n                cur_path.clear();\n                stuck_count = 0;\n            }\n\n            cur_ev = evaluate(cur.b);\n            int room = T - (int)cur_path.size();\n            if (kick_len > room) kick_len = room;\n\n            for (int k = 0; k < kick_len; ++k) {\n                int ld = cur_path.empty() ? -1 : char2dir(cur_path.back());\n                int ei = cur.epos / N;\n                int ej = cur.epos % N;\n\n                int order[4] = {0, 1, 2, 3};\n                for (int i = 3; i > 0; --i) swap(order[i], order[rng() % (i + 1)]);\n\n                bool moved = false;\n                for (int idx = 0; idx < 4; ++idx) {\n                    int d = order[idx];\n                    if (ld != -1 && d == opp[ld]) continue;\n                    if (!inside(ei + di[d], ej + dj[d])) continue;\n                    cur = apply_move(cur, d);\n                    cur_path.push_back(dc[d]);\n                    moved = true;\n                    break;\n                }\n                if (!moved) { // cornered: allow undo\n                    for (int d = 0; d < 4; ++d) {\n                        if (!inside(ei + di[d], ej + dj[d])) continue;\n                        cur = apply_move(cur, d);\n                        cur_path.push_back(dc[d]);\n                        break;\n                    }\n                }\n            }\n            cur_ev = evaluate(cur.b);\n            if (cur_ev.actual > best_actual) {\n                best_actual = cur_ev.actual;\n                best_state = cur;\n                best_path = cur_path;\n            }\n        }\n    }\n\n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ------------------------------------------------------------\n// Random (xoshiro256++)\n// ------------------------------------------------------------\nuint64_t rng_seed() {\n    return chrono::steady_clock::now().time_since_epoch().count();\n}\nstruct xoshiro256ss {\n    uint64_t s[4];\n    xoshiro256ss(uint64_t seed) {\n        s[0] = splitmix64(seed);\n        s[1] = splitmix64(s[0]);\n        s[2] = splitmix64(s[1]);\n        s[3] = splitmix64(s[2]);\n    }\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;\n        return x ^ (x >> 31);\n    }\n    uint64_t operator()() {\n        uint64_t r = rotl(s[1] * 5, 7) * 9;\n        uint64_t t = s[1] << 17;\n        s[2] ^= s[0];\n        s[3] ^= s[1];\n        s[1] ^= s[2];\n        s[0] ^= s[3];\n        s[2] ^= t;\n        s[3] = rotl(s[3], 45);\n        return r;\n    }\n    static uint64_t rotl(uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n};\nxoshiro256ss rng(rng_seed());\n\nlong long rnd_ll(long long l, long long r) {\n    if (l >= r) return l;\n    return l + (long long)(rng() % (uint64_t)(r - l + 1));\n}\nint rnd_int(int l, int r) {\n    if (l >= r) return l;\n    return l + (int)(rng() % (uint64_t)(r - l + 1));\n}\ndouble rnd_double() {\n    return (rng() >> 11) * (1.0 / (1ull << 53));\n}\n\n// ------------------------------------------------------------\n// Problem data\n// ------------------------------------------------------------\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C;\n};\n\nint N, K;\narray<int,11> need{};\nvector<long long> xs, ys;\nint target_score = 0;\n\nLine make_line_pts(long long px, long long py, long long qx, long long qy) {\n    Line L;\n    L.px = px; L.py = py; L.qx = qx; L.qy = qy;\n    L.A = qy - py;\n    L.B = px - qx;\n    L.C = qx*py - px*qy;\n    return L;\n}\n\n// extended gcd, returns g = gcd(a,b), finds x,y with ax+by=g\nlong long egcd(long long a, long long b, long long &x, long long &y) {\n    if (b == 0) { x = (a >= 0 ? 1 : -1); y = 0; return std::abs(a); }\n    long long x1, y1;\n    long long g = egcd(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\n// Find two integer points on Ax+By+C=0 inside [-1e9,1e9]\nbool get_two_points(long long A, long long B, long long C,\n                    long long &x1, long long &y1, long long &x2, long long &y2) {\n    const long long LIM = 1000000000LL;\n    if (B == 0) {\n        if (A == 0) return false;\n        if (C % A != 0) return false;\n        x1 = -C / A;\n        if (x1 < -LIM || x1 > LIM) return false;\n        y1 = 0;\n        x2 = x1; y2 = 1;\n        if (y2 < -LIM || y2 > LIM) return false;\n        return true;\n    }\n    long long g = std::gcd(std::abs(A), std::abs(B));\n    if (C % g != 0) return false;\n    long long a = A / g;\n    long long b = B / g;\n    long long c = -C / g;               // a*x + b*y = c\n    long long mod = std::abs(b);\n    long long a_mod = ((a % mod) + mod) % mod;\n    long long c_mod = ((c % mod) + mod) % mod;\n    long long inv, tmp;\n    egcd(a_mod, mod, inv, tmp);\n    inv = ((inv % mod) + mod) % mod;\n    long long x0 = (long long)((__int128)c_mod * inv % mod);\n\n    long long t = 0;\n    if (x0 < -LIM) t = (-LIM - x0 + mod - 1) / mod;\n    else if (x0 > LIM) t = -(x0 - LIM + mod - 1) / mod;\n\n    long long x = x0 + mod * t;\n    __int128 num = -(__int128)C - (__int128)A * x;\n    long long y = (long long)(num / B);\n\n    long long step_y = (b > 0) ? -a : a;   // change of y when x increases by mod\n    if (y < -LIM) {\n        long long need_up = -LIM - y;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need_up + abs_sy - 1) / abs_sy;\n            x += mod * dt;\n            y += step_y * dt;\n        }\n    } else if (y > LIM) {\n        long long need_down = y - LIM;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need_down + abs_sy - 1) / abs_sy;\n            x -= mod * dt;\n            y -= step_y * dt;\n        }\n    }\n    if (x < -LIM || x > LIM || y < -LIM || y > LIM) return false;\n\n    x1 = x; y1 = y;\n    x2 = x1 + mod;\n    if (x2 > LIM) x2 = x1 - mod;\n    __int128 num2 = -(__int128)C - (__int128)A * x2;\n    y2 = (long long)(num2 / B);\n\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) return false;\n    if (x1 == x2 && y1 == y2) return false;\n    return true;\n}\n\nbool intersects_disk(const Line& L) {\n    __int128 c2 = (__int128)L.C * L.C;\n    __int128 ab2 = (__int128)L.A * L.A + (__int128)L.B * L.B;\n    return c2 < ab2 * 100000000LL;   // radius 1e4  =>  r^2 = 1e8\n}\n\nbool valid_line(const Line& L) {\n    const long long LIM = 1000000000LL;\n    if (L.px < -LIM || L.px > LIM || L.py < -LIM || L.py > LIM) return false;\n    if (L.qx < -LIM || L.qx > LIM || L.qy < -LIM || L.qy > LIM) return false;\n    if (L.px == L.qx && L.py == L.qy) return false;\n    if (!intersects_disk(L)) return false;\n    for (int i = 0; i < N; ++i) {\n        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n        if (v == 0) return false;\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// Signature and hash table (must appear before functions that use them)\n// ------------------------------------------------------------\nstruct Sig {\n    uint64_t a, b;\n};\n\nstruct FastHT {\n    struct Node {\n        uint64_t a, b;\n        int cnt;\n    };\n    int n;\n    vector<Node> nodes;\n    vector<int> seen;\n    vector<int> occ;\n    int timer;\n    FastHT(int n_ = 1 << 14) {\n        n = n_;\n        nodes.resize(n);\n        seen.assign(n, 0);\n        timer = 1;\n    }\n    inline void next_timer() {\n        ++timer;\n        occ.clear();\n        if (timer > 2000000000) {\n            fill(seen.begin(), seen.end(), 0);\n            timer = 1;\n        }\n    }\n    inline void add(uint64_t a, uint64_t b) {\n        size_t h = a ^ (b * 11400714819323198485ull);\n        size_t idx = h & (n - 1);\n        while (seen[idx] == timer) {\n            if (nodes[idx].a == a && nodes[idx].b == b) {\n                ++nodes[idx].cnt;\n                return;\n            }\n            idx = (idx + 1) & (n - 1);\n        }\n        seen[idx] = timer;\n        nodes[idx].a = a;\n        nodes[idx].b = b;\n        nodes[idx].cnt = 1;\n        occ.push_back((int)idx);\n    }\n    inline int get_score(const array<int,11>& need) const {\n        int have[11] = {0};\n        for (int idx : occ) {\n            int c = nodes[idx].cnt;\n            if (c >= 1 && c <= 10) ++have[c];\n        }\n        int s = 0;\n        for (int d = 1; d <= 10; ++d) s += min(need[d], have[d]);\n        return s;\n    }\n};\n\nFastHT ht;\n\ninline int evaluate_sigs(const vector<Sig>& sigs) {\n    ht.next_timer();\n    for (const auto& s : sigs) ht.add(s.a, s.b);\n    return ht.get_score(need);\n}\n\nvector<Sig> recompute_sigs(const vector<Line>& ls) {\n    vector<Sig> s(N, {0, 0});\n    for (int j = 0; j < (int)ls.size(); ++j) {\n        if (j < 64) {\n            uint64_t mask = 1ULL << j;\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)ls[j].A * xs[i] + (__int128)ls[j].B * ys[i] + (__int128)ls[j].C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                s[i].a = (s[i].a & ~mask) | (bit << j);\n            }\n        } else {\n            uint64_t mask = 1ULL << (j - 64);\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)ls[j].A * xs[i] + (__int128)ls[j].B * ys[i] + (__int128)ls[j].C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                s[i].b = (s[i].b & ~mask) | (bit << (j - 64));\n            }\n        }\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Candidate generators (Sig is now known)\n// ------------------------------------------------------------\nLine gen_random_line() {\n    const long long LIM = 200000;\n    while (true) {\n        long long x1 = rnd_ll(-LIM, LIM);\n        long long y1 = rnd_ll(-LIM, LIM);\n        long long x2 = rnd_ll(-LIM, LIM);\n        long long y2 = rnd_ll(-LIM, LIM);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n}\n\nLine gen_separator_line() {\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        int i = rnd_int(0, N - 1);\n        int j = rnd_int(0, N - 1);\n        if (i == j) continue;\n        long long xi = xs[i], yi = ys[i];\n        long long xj = xs[j], yj = ys[j];\n        long long A = xj - xi;\n        long long B = yj - yi;\n        if (A == 0 && B == 0) continue;\n        __int128 rhs = (__int128)xj*xj + (__int128)yj*yj - (__int128)xi*xi - (__int128)yi*yi;\n        long long T = (long long)(rhs / 2);\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        for (int d = -10; d <= 10; ++d) {\n            long long C = T + d;\n            if (C % g != 0) continue;\n            long long px, py, qx, qy;\n            if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\nLine gen_gap_line() {\n    static vector<long long> vals;\n    vals.assign(N, 0);\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        long long A = rnd_ll(-1000, 1000);\n        long long B = rnd_ll(-1000, 1000);\n        if (A == 0 && B == 0) continue;\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        A /= g; B /= g;\n        for (int i = 0; i < N; ++i) vals[i] = A * xs[i] + B * ys[i];\n        sort(vals.begin(), vals.end());\n        vector<long long> uniq;\n        for (long long v : vals) {\n            if (uniq.empty() || uniq.back() != v) uniq.push_back(v);\n        }\n        if (uniq.size() <= 1) continue;\n        int idx = rnd_int(0, (int)uniq.size() - 2);\n        long long lo = uniq[idx];\n        long long hi = uniq[idx + 1];\n        if (hi <= lo + 1) continue;\n        long long C;\n        if (hi - lo > 2000000) C = lo + 1 + rnd_ll(0, 2000000);\n        else C = lo + 1 + rnd_ll(0, hi - lo - 1);\n        long long px, py, qx, qy;\n        if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n        Line L = make_line_pts(px, py, qx, qy);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\nLine perturb_line(const Line& L0) {\n    const long long D = 5;\n    for (int attempt = 0; attempt < 10; ++attempt) {\n        long long x1 = L0.px + rnd_ll(-D, D);\n        long long y1 = L0.py + rnd_ll(-D, D);\n        long long x2 = L0.qx + rnd_ll(-D, D);\n        long long y2 = L0.qy + rnd_ll(-D, D);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\n// Split a random piece into two parts; target size t\nLine gen_split_line(const vector<Sig>& sigs) {\n    static vector<int> bucket;\n    static vector<pair<long long,int>> proj;\n    bucket.reserve(64);\n    proj.reserve(64);\n\n    // First try to find a piece with >10 points (high priority)\n    for (int attempt = 0; attempt < 3; ++attempt) {\n        int idx = rnd_int(0, N - 1);\n        uint64_t ta = sigs[idx].a, tb = sigs[idx].b;\n        bucket.clear();\n        for (int i = 0; i < N; ++i) {\n            if (sigs[i].a == ta && sigs[i].b == tb) bucket.push_back(i);\n        }\n        int c = (int)bucket.size();\n        if (c <= 1) continue;\n        int t;\n        if (c > 10) {\n            t = rnd_int(1, 10);\n        } else {\n            t = rnd_int(1, c - 1);\n        }\n        for (int dir = 0; dir < 20; ++dir) {\n            long long dx = rnd_ll(-200, 200);\n            long long dy = rnd_ll(-200, 200);\n            if (dx == 0 && dy == 0) continue;\n            proj.clear();\n            for (int id : bucket) {\n                proj.emplace_back(dx * xs[id] + dy * ys[id], id);\n            }\n            sort(proj.begin(), proj.end());\n            if (proj[t - 1].first == proj[t].first) continue;\n            long long C = proj[t - 1].first + 1;\n            long long px, py, qx, qy;\n            if (!get_two_points(dx, dy, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n\n    // Fallback: any piece\n    for (int attempt = 0; attempt < 2; ++attempt) {\n        int idx = rnd_int(0, N - 1);\n        uint64_t ta = sigs[idx].a, tb = sigs[idx].b;\n        bucket.clear();\n        for (int i = 0; i < N; ++i) {\n            if (sigs[i].a == ta && sigs[i].b == tb) bucket.push_back(i);\n        }\n        int c = (int)bucket.size();\n        if (c <= 1) continue;\n        int t = rnd_int(1, c - 1);\n        for (int dir = 0; dir < 15; ++dir) {\n            long long dx = rnd_ll(-200, 200);\n            long long dy = rnd_ll(-200, 200);\n            if (dx == 0 && dy == 0) continue;\n            proj.clear();\n            for (int id : bucket) {\n                proj.emplace_back(dx * xs[id] + dy * ys[id], id);\n            }\n            sort(proj.begin(), proj.end());\n            if (proj[t - 1].first == proj[t].first) continue;\n            long long C = proj[t - 1].first + 1;\n            long long px, py, qx, qy;\n            if (!get_two_points(dx, dy, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\n// ------------------------------------------------------------\n// Main solver\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> need[d];\n        target_score += need[d];\n    }\n    xs.resize(N); ys.resize(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    const double TIME_LIMIT = 2.88;\n\n    vector<Line> best_lines;\n    int best_score = -1;\n\n    // We do one greedy build then SA; if time remains we restart.\n    int pass = 0;\n    while (elapsed() < TIME_LIMIT) {\n        ++pass;\n        // ---------- Greedy construction ----------\n        vector<Line> lines;\n        vector<Sig> sig(N, {0, 0});\n        int cur_score = 0;\n        const int GREEDY_CANDS = 100;\n        vector<Sig> tmp(N), best_sig;\n\n        for (int step = 0; step < K; ++step) {\n            Line best_line;\n            int best_score_local = cur_score;\n\n            for (int cand = 0; cand < GREEDY_CANDS; ++cand) {\n                int type = rnd_int(0, 3);\n                Line L;\n                if (type == 0) L = gen_random_line();\n                else if (type == 1) L = gen_gap_line();\n                else if (type == 2) L = gen_separator_line();\n                else L = gen_split_line(sig);\n                if (!valid_line(L)) continue;\n\n                int pj = step;\n                if (pj < 64) {\n                    uint64_t mask = 1ULL << pj;\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = (sig[i].a & ~mask) | (bit << pj);\n                        tmp[i].b = sig[i].b;\n                    }\n                } else {\n                    uint64_t mask = 1ULL << (pj - 64);\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = sig[i].a;\n                        tmp[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                    }\n                }\n                int sc = evaluate_sigs(tmp);\n                if (sc > best_score_local) {\n                    best_score_local = sc;\n                    best_line = L;\n                    best_sig = tmp;\n                }\n            }\n\n            if (best_score_local > cur_score) {\n                lines.push_back(best_line);\n                sig.swap(best_sig);\n                cur_score = best_score_local;\n            } else {\n                Line L = gen_random_line();\n                while (!valid_line(L)) L = gen_random_line();\n                lines.push_back(L);\n                int pj = step;\n                if (pj < 64) {\n                    uint64_t mask = 1ULL << pj;\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n                    }\n                } else {\n                    uint64_t mask = 1ULL << (pj - 64);\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                    }\n                }\n                cur_score = evaluate_sigs(sig);\n            }\n            if (cur_score == target_score) break;\n        }\n\n        while ((int)lines.size() < K) {\n            Line L = gen_random_line();\n            lines.push_back(L);\n            int pj = (int)lines.size() - 1;\n            if (pj < 64) {\n                uint64_t mask = 1ULL << pj;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n                }\n            } else {\n                uint64_t mask = 1ULL << (pj - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                }\n            }\n        }\n        cur_score = evaluate_sigs(sig);\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_lines = lines;\n        }\n\n        // ---------- Simulated Annealing ----------\n        double T = 2.0;\n        int last_improve = 0;\n        int iter = 0;\n        while (elapsed() < TIME_LIMIT) {\n            ++iter;\n            int j = rnd_int(0, K - 1);\n            int r = rnd_int(0, 99);\n            Line L;\n            if (r < 35) L = gen_split_line(sig);\n            else if (r < 55) L = gen_gap_line();\n            else if (r < 75) L = gen_random_line();\n            else if (r < 90) L = gen_separator_line();\n            else L = perturb_line(lines[j]);\n\n            if (!valid_line(L)) continue;\n\n            if (j < 64) {\n                uint64_t mask = 1ULL << j;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = (sig[i].a & ~mask) | (bit << j);\n                    tmp[i].b = sig[i].b;\n                }\n            } else {\n                uint64_t mask = 1ULL << (j - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = sig[i].a;\n                    tmp[i].b = (sig[i].b & ~mask) | (bit << (j - 64));\n                }\n            }\n            int new_score = evaluate_sigs(tmp);\n            int delta = new_score - cur_score;\n            if (delta > 0 || exp(delta / T) > rnd_double()) {\n                lines[j] = L;\n                sig.swap(tmp);\n                cur_score = new_score;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_lines = lines;\n                    last_improve = iter;\n                }\n            }\n\n            T *= 0.9997;\n            if (T < 0.0005) T = 0.0005;\n\n            // Kick if stuck for a while\n            if (iter - last_improve > 5000) {\n                T = 2.0;\n                last_improve = iter;\n                // Randomize 20 lines\n                for (int rep = 0; rep < 20; ++rep) {\n                    int jj = rnd_int(0, K - 1);\n                    Line RL = gen_random_line();\n                    lines[jj] = RL;\n                }\n                sig = recompute_sigs(lines);\n                cur_score = evaluate_sigs(sig);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_lines = lines;\n                }\n            }\n        }\n\n        // If we have little time left, don't start another greedy\n        if (elapsed() >= TIME_LIMIT - 0.3) break;\n    }\n\n    // Final validation\n    for (int j = 0; j < K; ++j) {\n        if (!valid_line(best_lines[j])) {\n            best_lines[j] = gen_random_line();\n        }\n    }\n\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << best_lines[i].px << \" \" << best_lines[i].py << \" \"\n             << best_lines[i].qx << \" \" << best_lines[i].qy << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 64;\nconst int MAXD = 2 * MAXN;\n\nusing Record = array<int,8>;\n\nstruct Solver {\n    int N, M, cx;\n    int wgt[MAXN][MAXN];\n    bool init_dot[MAXN][MAXN];\n    long long init_sum = 0;\n\n    // per-run\n    bool dot[MAXN][MAXN];\n    bool horiz[MAXN][MAXN];\n    bool vert[MAXN][MAXN];\n    bool diag1[MAXN][MAXN];\n    bool diag2[MAXN][MAXN];\n    int best_peri[MAXN][MAXN];\n\n    vector<int> row_dots[MAXN];\n    vector<int> col_dots[MAXN];\n    vector<pair<int,int>> diag1_dots[MAXD];\n    vector<pair<int,int>> diag2_dots[MAXD];\n\n    priority_queue<tuple<long long,int,int>> pq;\n    mt19937 rng;\n    int mode;\n\n    // ---------- segment utilities ----------\n    inline bool seg_drawn(int x, int y, int dx, int dy) const {\n        if (dx == 1 && dy == 0) return horiz[x][y];\n        if (dx == -1 && dy == 0) return horiz[x-1][y];\n        if (dx == 0 && dy == 1) return vert[x][y];\n        if (dx == 0 && dy == -1) return vert[x][y-1];\n        if (dx == 1 && dy == 1) return diag1[x][y];\n        if (dx == -1 && dy == -1) return diag1[x-1][y-1];\n        if (dx == 1 && dy == -1) return diag2[x][y];\n        if (dx == -1 && dy == 1) return diag2[x-1][y+1];\n        return true;\n    }\n    inline void set_seg(int x, int y, int dx, int dy) {\n        if (dx == 1 && dy == 0) horiz[x][y] = true;\n        else if (dx == -1 && dy == 0) horiz[x-1][y] = true;\n        else if (dx == 0 && dy == 1) vert[x][y] = true;\n        else if (dx == 0 && dy == -1) vert[x][y-1] = true;\n        else if (dx == 1 && dy == 1) diag1[x][y] = true;\n        else if (dx == -1 && dy == -1) diag1[x-1][y-1] = true;\n        else if (dx == 1 && dy == -1) diag2[x][y] = true;\n        else if (dx == -1 && dy == 1) diag2[x-1][y+1] = true;\n    }\n\n    bool check_edge(int x1, int y1, int x2, int y2) const {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int x = x1, y = y1;\n        while (x != x2 || y != y2) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (nx != x2 || ny != y2) {\n                if (dot[nx][ny]) return false;\n            }\n            if (seg_drawn(x, y, dx, dy)) return false;\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void draw_edge(int x1, int y1, int x2, int y2) {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int x = x1, y = y1;\n        while (x != x2 || y != y2) {\n            set_seg(x, y, dx, dy);\n            x += dx; y += dy;\n        }\n    }\n\n    bool check_rect(int x1, int y1, int x2, int y2,\n                    int x3, int y3, int x4, int y4) const {\n        if (dot[x1][y1]) return false;\n        if (!dot[x2][y2] || !dot[x3][y3] || !dot[x4][y4]) return false;\n        if (!check_edge(x1,y1,x2,y2)) return false;\n        if (!check_edge(x2,y2,x3,y3)) return false;\n        if (!check_edge(x3,y3,x4,y4)) return false;\n        if (!check_edge(x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void draw_rect(const Record &r) {\n        draw_edge(r[0],r[1],r[2],r[3]);\n        draw_edge(r[2],r[3],r[4],r[5]);\n        draw_edge(r[4],r[5],r[6],r[7]);\n        draw_edge(r[6],r[7],r[0],r[1]);\n    }\n\n    // ---------- rectangle enumeration for a fixed p1 (always min perimeter) ----------\n    bool choose_rect(int x, int y, Record &out, int &out_peri) const {\n        bool found = false;\n        int best_peri = 0;\n        Record best;\n\n        // axis-aligned\n        for (int x2 : row_dots[y]) {\n            for (int y2 : col_dots[x]) {\n                if (!dot[x2][y2]) continue;\n                Record r = {x,y,x2,y,x2,y2,x,y2};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                int peri = 2 * (abs(x2 - x) + abs(y2 - y));\n                if (!found || peri < best_peri) {\n                    found = true; best_peri = peri; best = r;\n                }\n            }\n        }\n\n        // 45-degree\n        int off = N - 1;\n        int idx1 = x - y + off;\n        int idx2 = x + y;\n        for (auto [x2,y2] : diag1_dots[idx1]) {\n            if (x2 == x && y2 == y) continue;\n            for (auto [x4,y4] : diag2_dots[idx2]) {\n                if (x4 == x && y4 == y) continue;\n                int x3 = x2 + x4 - x;\n                int y3 = y2 + y4 - y;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                Record r = {x,y,x2,y2,x3,y3,x4,y4};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                int peri = 2 * (abs(x2 - x) + abs(x4 - x));\n                if (!found || peri < best_peri) {\n                    found = true; best_peri = peri; best = r;\n                }\n            }\n        }\n\n        if (found) { out = best; out_peri = best_peri; }\n        return found;\n    }\n\n    // ---------- priority functions ----------\n    long long calc_pri(int w, int p) {\n        if (p <= 0) p = 1;\n        if (mode == 0) return w * 1000000LL / p;          // efficiency\n        if (mode == 1) return w * 10000LL - p * 500LL;     // linear\n        if (mode == 2) return w * 10000LL;                // weight only\n        if (mode == 3) return -p * 10000LL + w;          // small first\n        if (mode == 4) return w * 10000LL - 1LL * p * p;  // quadratic\n        // noisy efficiency\n        long long base = w * 1000000LL / p;\n        return base + (long long)(rng() & 0x7FFF);\n    }\n\n    void try_push(int x, int y, int peri) {\n        if (dot[x][y]) return;\n        if (peri >= best_peri[x][y]) return;\n        best_peri[x][y] = peri;\n        pq.emplace(calc_pri(wgt[x][y], peri), x, y);\n    }\n\n    // ---------- complete incremental candidate generation ----------\n    void find_new_candidates(int x, int y) {\n        int off = N - 1;\n\n        // ---- axis: p_new as p2, p1 same row ----\n        for (int x1 = 0; x1 < N; ++x1) {\n            if (dot[x1][y]) continue;\n            for (int y1 : col_dots[x]) {\n                if (!dot[x1][y1]) continue;\n                if (check_rect(x1,y, x,y, x,y1, x1,y1))\n                    try_push(x1, y, 2*(abs(x1-x)+abs(y1-y)));\n            }\n        }\n\n        // ---- axis: p_new as p2, p1 same column ----\n        for (int y1 = 0; y1 < N; ++y1) {\n            if (dot[x][y1]) continue;\n            for (int x2 : row_dots[y]) {\n                if (!dot[x2][y1]) continue;\n                if (check_rect(x,y1, x,y, x2,y, x2,y1))\n                    try_push(x, y1, 2*(abs(y1-y)+abs(x2-x)));\n            }\n        }\n\n        // ---- axis: p_new as p4, p1 same column ----\n        for (int y1 = 0; y1 < N; ++y1) {\n            if (dot[x][y1]) continue;\n            for (int x1 : row_dots[y]) {\n                if (!dot[x1][y1]) continue;\n                if (check_rect(x,y1, x1,y1, x1,y, x,y))\n                    try_push(x, y1, 2*(abs(x1-x)+abs(y1-y)));\n            }\n        }\n\n        // ---- axis: p_new as p4, p1 same row ----\n        for (int x1 = 0; x1 < N; ++x1) {\n            if (dot[x1][y]) continue;\n            for (int y2 : col_dots[x]) {\n                if (!dot[x1][y2]) continue;\n                if (check_rect(x1,y, x1,y2, x,y2, x,y))\n                    try_push(x1, y, 2*(abs(x1-x)+abs(y2-y)));\n            }\n        }\n\n        // ---- axis: p_new as p3 (opposite) ----\n        for (int x1 : row_dots[y]) {\n            for (int y1 : col_dots[x]) {\n                if (dot[x1][y1]) continue;\n                if (check_rect(x1,y1, x1,y, x,y, x,y1))\n                    try_push(x1, y1, 2*(abs(x1-x)+abs(y1-y)));\n            }\n        }\n\n        // ---- 45: p_new as p2 on diag+1 ----\n        for (int i = max(0, x-y), j = i - (x-y); i < N && j < N; ++i, ++j) {\n            if (i == x && j == y) continue;\n            if (dot[i][j]) continue;\n            int s = i + j;\n            for (auto [x4,y4] : diag2_dots[s]) {\n                int x3 = x + x4 - i;\n                int y3 = y + y4 - j;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                if (check_rect(i,j, x,y, x3,y3, x4,y4))\n                    try_push(i, j, 2*(abs(x-i)+abs(x4-i)));\n            }\n        }\n\n        // ---- 45: p_new as p2 on diag-1 ----\n        int s0 = x + y;\n        for (int i = max(0, s0-(N-1)); i <= min(N-1, s0); ++i) {\n            int j = s0 - i;\n            if (i == x && j == y) continue;\n            if (dot[i][j]) continue;\n            int d = i - j + off;\n            for (auto [x4,y4] : diag1_dots[d]) {\n                int x3 = x + x4 - i;\n                int y3 = y + y4 - j;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                if (check_rect(i,j, x,y, x3,y3, x4,y4))\n                    try_push(i, j, 2*(abs(x-i)+abs(x4-i)));\n            }\n        }\n\n        // ---- 45: p_new as p4 on diag+1 ----\n        int diff = x - y;\n        for (int x3 = max(0, diff), y3 = x3 - diff; x3 < N && y3 < N; ++x3, ++y3) {\n            if (x3 == x && y3 == y) continue;\n            if (!dot[x3][y3]) continue;\n            int sum = x + y;\n            for (int i = max(0, sum-(N-1)); i <= min(N-1, sum); ++i) {\n                int j = sum - i;\n                if (i == x && j == y) continue;\n                if (dot[i][j]) continue;\n                int x2 = i + x3 - x;\n                int y2 = j + y3 - y;\n                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N) continue;\n                if (!dot[x2][y2]) continue;\n                if (check_rect(i,j, x2,y2, x3,y3, x,y))\n                    try_push(i, j, 2*(abs(x3-x)+abs(i-x)));\n            }\n        }\n\n        // ---- 45: p_new as p4 on diag-1 ----\n        for (int x3 = max(0, s0-(N-1)); x3 <= min(N-1, s0); ++x3) {\n            int y3 = s0 - x3;\n            if (x3 == x && y3 == y) continue;\n            if (!dot[x3][y3]) continue;\n            for (int i = max(0, diff), j = i - diff; i < N && j < N; ++i, ++j) {\n                if (i == x && j == y) continue;\n                if (dot[i][j]) continue;\n                int x2 = i + x3 - x;\n                int y2 = j + y3 - y;\n                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N) continue;\n                if (!dot[x2][y2]) continue;\n                if (check_rect(i,j, x2,y2, x3,y3, x,y))\n                    try_push(i, j, 2*(abs(x3-x)+abs(i-x)));\n            }\n        }\n\n        // ---- 45: p_new as p3 (opposite) ----\n        int id1 = x - y + off;\n        int id2 = x + y;\n        for (auto [x2,y2] : diag1_dots[id1]) {\n            if (x2 == x && y2 == y) continue;\n            for (auto [x4,y4] : diag2_dots[id2]) {\n                if (x4 == x && y4 == y) continue;\n                int x1 = x2 + x4 - x;\n                int y1 = y2 + y4 - y;\n                if (x1 < 0 || x1 >= N || y1 < 0 || y1 >= N) continue;\n                if (dot[x1][y1]) continue;\n                if (check_rect(x1,y1, x2,y2, x,y, x4,y4))\n                    try_push(x1, y1, 2*(abs(x2-x)+abs(x4-x)));\n            }\n        }\n    }\n\n    // ---------- solve one run ----------\n    pair<long long, vector<Record>> solve_run(int mode_, int seed) {\n        mode = mode_;\n        rng.seed(seed);\n\n        memcpy(dot, init_dot, sizeof(dot));\n        memset(horiz, 0, sizeof(horiz));\n        memset(vert, 0, sizeof(vert));\n        memset(diag1, 0, sizeof(diag1));\n        memset(diag2, 0, sizeof(diag2));\n        for (int i = 0; i < N; ++i) {\n            row_dots[i].clear();\n            col_dots[i].clear();\n        }\n        for (int i = 0; i < MAXD; ++i) {\n            diag1_dots[i].clear();\n            diag2_dots[i].clear();\n        }\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) best_peri[i][j] = (int)1e9;\n        while (!pq.empty()) pq.pop();\n\n        int off = N - 1;\n        for (int x = 0; x < N; ++x) {\n            for (int y = 0; y < N; ++y) if (dot[x][y]) {\n                row_dots[y].push_back(x);\n                col_dots[x].push_back(y);\n                diag1_dots[x - y + off].push_back({x,y});\n                diag2_dots[x + y].push_back({x,y});\n            }\n        }\n\n        // initial scan\n        Record rec;\n        int p;\n        for (int x = 0; x < N; ++x) {\n            for (int y = 0; y < N; ++y) if (!dot[x][y]) {\n                if (choose_rect(x, y, rec, p)) {\n                    best_peri[x][y] = p;\n                    pq.emplace(calc_pri(wgt[x][y], p), x, y);\n                }\n            }\n        }\n\n        long long cur_sum = init_sum;\n        vector<Record> ops;\n        ops.reserve(N * N);\n\n        while (!pq.empty()) {\n            auto [pri, x, y] = pq.top();\n            pq.pop();\n            if (dot[x][y]) continue;\n\n            Record r;\n            int peri;\n            if (!choose_rect(x, y, r, peri)) {\n                best_peri[x][y] = (int)1e9;\n                continue;\n            }\n            if (peri != best_peri[x][y]) {\n                best_peri[x][y] = peri;\n                pq.emplace(calc_pri(wgt[x][y], peri), x, y);\n                continue;\n            }\n\n            // execute move\n            dot[x][y] = true;\n            cur_sum += wgt[x][y];\n            draw_rect(r);\n            ops.push_back(r);\n\n            row_dots[y].push_back(x);\n            col_dots[x].push_back(y);\n            diag1_dots[x - y + off].push_back({x,y});\n            diag2_dots[x + y].push_back({x,y});\n\n            find_new_candidates(x, y);\n        }\n        return {cur_sum, ops};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n\n    Solver sol;\n    sol.N = N; sol.M = M;\n    sol.cx = (N - 1) / 2;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sol.wgt[i][j] = (i - sol.cx)*(i - sol.cx) + (j - sol.cx)*(j - sol.cx) + 1;\n\n    memset(sol.init_dot, 0, sizeof(sol.init_dot));\n    for (int i = 0; i < M; ++i) {\n        int x, y; cin >> x >> y;\n        sol.init_dot[x][y] = true;\n        sol.init_sum += sol.wgt[x][y];\n    }\n\n    const double TIME_LIMIT = 4.5;\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    long long best_score = -1;\n    vector<Record> best_ops;\n\n    // deterministic heuristics\n    vector<int> modes = {0, 1, 3, 4, 2};\n    for (int md : modes) {\n        if (elapsed() > TIME_LIMIT) break;\n        auto [sc, ops] = sol.solve_run(md, 0);\n        if (sc > best_score) {\n            best_score = sc;\n            best_ops = std::move(ops);\n        }\n    }\n\n    // random restarts with noisy efficiency\n    for (int seed = 1; ; ++seed) {\n        if (elapsed() > TIME_LIMIT) break;\n        auto [sc, ops] = sol.solve_run(5, seed);\n        if (sc > best_score) {\n            best_score = sc;\n            best_ops = std::move(ops);\n        }\n    }\n\n    cout << best_ops.size() << \"\\n\";\n    for (auto &r : best_ops) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << r[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    array<int, 100> a;\n    State() { a.fill(0); }\n};\n\n/* tilt the whole box in one direction\n   0:F (up, row 0), 1:B (down, row 9), 2:L (left, col 0), 3:R (right, col 9) */\nState tilt(const State& s, int dir) {\n    State ns;\n    ns.a.fill(0);\n    if (dir == 0) {                 // Forward / Up\n        for (int c = 0; c < 10; ++c) {\n            int w = 0;\n            for (int r = 0; r < 10; ++r) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[w++ * 10 + c] = x;\n            }\n        }\n    } else if (dir == 1) {          // Backward / Down\n        for (int c = 0; c < 10; ++c) {\n            int w = 9;\n            for (int r = 9; r >= 0; --r) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[w-- * 10 + c] = x;\n            }\n        }\n    } else if (dir == 2) {          // Left\n        for (int r = 0; r < 10; ++r) {\n            int w = 0;\n            for (int c = 0; c < 10; ++c) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[r * 10 + w++] = x;\n            }\n        }\n    } else {                         // Right\n        for (int r = 0; r < 10; ++r) {\n            int w = 9;\n            for (int c = 9; c >= 0; --c) {\n                int x = s.a[r * 10 + c];\n                if (x != 0) ns.a[r * 10 + w--] = x;\n            }\n        }\n    }\n    return ns;\n}\n\n/* where does the candy currently at 'pos' end up after tilting 'dir'? */\nint new_pos_after_tilt(const State& s, int pos, int dir) {\n    int r = pos / 10;\n    int c = pos % 10;\n    if (dir == 0) {                 // F\n        int cnt = 0;\n        for (int i = 0; i < r; ++i) if (s.a[i * 10 + c] != 0) ++cnt;\n        return cnt * 10 + c;\n    } else if (dir == 1) {          // B\n        int cnt = 0;\n        for (int i = r + 1; i < 10; ++i) if (s.a[i * 10 + c] != 0) ++cnt;\n        return (9 - cnt) * 10 + c;\n    } else if (dir == 2) {          // L\n        int cnt = 0;\n        for (int i = 0; i < c; ++i) if (s.a[r * 10 + i] != 0) ++cnt;\n        return r * 10 + cnt;\n    } else {                         // R\n        int cnt = 0;\n        for (int i = c + 1; i < 10; ++i) if (s.a[r * 10 + i] != 0) ++cnt;\n        return r * 10 + (9 - cnt);\n    }\n}\n\n/* exact score = sum of n_i^2 */\nint evaluate(const State& s) {\n    bool vis[100] = {false};\n    int q[100];\n    int sum = 0;\n    for (int i = 0; i < 100; ++i) {\n        if (s.a[i] == 0 || vis[i]) continue;\n        int f = s.a[i];\n        int sz = 0;\n        int qh = 0, qt = 0;\n        q[qt++] = i;\n        vis[i] = true;\n        while (qh < qt) {\n            int u = q[qh++];\n            ++sz;\n            int r = u / 10;\n            int c = u % 10;\n            if (r > 0) {\n                int v = (r - 1) * 10 + c;\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (r < 9) {\n                int v = (r + 1) * 10 + c;\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (c > 0) {\n                int v = r * 10 + (c - 1);\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n            if (c < 9) {\n                int v = r * 10 + (c + 1);\n                if (!vis[v] && s.a[v] == f) { vis[v] = true; q[qt++] = v; }\n            }\n        }\n        sum += sz * sz;\n    }\n    return sum;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> flav(100);\n    for (int i = 0; i < 100; ++i) {\n        if (!(cin >> flav[i])) return 0;\n    }\n\n    const int K = 40;                     // rollouts per direction\n    const char dname[4] = {'F', 'B', 'L', 'R'};\n    State cur;\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        --p;                              // 0-based\n\n        /* place in the p-th empty cell (row-major = front-to-back, left-to-right) */\n        int pos = -1;\n        for (int i = 0; i < 100; ++i) {\n            if (cur.a[i] == 0) {\n                if (p == 0) { pos = i; break; }\n                --p;\n            }\n        }\n        cur.a[pos] = flav[t];\n\n        /* 100th placement fills the board; tilt does nothing */\n        if (t == 99) {\n            cout << \"F\\n\";\n            cout.flush();\n            break;\n        }\n\n        State base[4];\n        for (int d = 0; d < 4; ++d) base[d] = tilt(cur, d);\n\n        long long total[4] = {0, 0, 0, 0};\n\n        for (int k = 0; k < K; ++k) {\n            /* same random seed for all 4 directions -> variance reduction */\n            unsigned seed = 123456789u + t * 10007u + k;\n            for (int d = 0; d < 4; ++d) {\n                mt19937 rng(seed);\n                State sim = base[d];\n\n                for (int s = t + 1; s < 100; ++s) {\n                    int empties[100];\n                    int ecnt = 0;\n                    for (int i = 0; i < 100; ++i)\n                        if (sim.a[i] == 0) empties[ecnt++] = i;\n\n                    if (ecnt == 0) break;\n                    int idx = empties[rng() % ecnt];\n                    int f = flav[s];\n                    sim.a[idx] = f;\n\n                    if (s == 99) break;   // last candy, no tilt follows\n\n                    /* local greedy: maximize same-flavor neighbours of the new candy */\n                    int best_dir = 0;\n                    int best_sc = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int np = new_pos_after_tilt(sim, idx, d2);\n                        State ns = tilt(sim, d2);\n                        int sc = 0;\n                        int r = np / 10;\n                        int c = np % 10;\n                        if (r > 0 && ns.a[(r - 1) * 10 + c] == f) ++sc;\n                        if (r < 9 && ns.a[(r + 1) * 10 + c] == f) ++sc;\n                        if (c > 0 && ns.a[r * 10 + (c - 1)] == f) ++sc;\n                        if (c < 9 && ns.a[r * 10 + (c + 1)] == f) ++sc;\n                        if (sc > best_sc) {\n                            best_sc = sc;\n                            best_dir = d2;\n                        }\n                    }\n                    sim = tilt(sim, best_dir);\n                }\n                total[d] += evaluate(sim);\n            }\n        }\n\n        int best = 0;\n        for (int d = 1; d < 4; ++d)\n            if (total[d] > total[best]) best = d;\n\n        cur = tilt(cur, best);\n        cout << dname[best] << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\nusing Feature = vector<double>;\n\nint M;\ndouble eps;\nmt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// Graph with up to 100 vertices (stored as two 64-bit rows)\n// ------------------------------------------------------------\nstruct Graph {\n    ull a[100][2];\n};\n\ninline void initGraph(Graph& g, int n) {\n    for (int i = 0; i < n; ++i) g.a[i][0] = g.a[i][1] = 0;\n}\n\ninline void setBit(Graph& g, int u, int v) {\n    int idx = v >> 6;\n    int bit = v & 63;\n    g.a[u][idx] |= (1ULL << bit);\n}\n\ninline bool getBit(const Graph& g, int u, int v) {\n    int idx = v >> 6;\n    int bit = v & 63;\n    return (g.a[u][idx] >> bit) & 1ULL;\n}\n\n// generate a random graph with exactly wantEdges edges\nGraph randomGraphWithEdges(int n, int wantEdges) {\n    Graph g;\n    initGraph(g, n);\n    int L = n * (n - 1) / 2;\n    vector<pair<int,int>> edges;\n    edges.reserve(L);\n    for (int i = 0; i < n; ++i)\n        for (int j = i + 1; j < n; ++j)\n            edges.emplace_back(i, j);\n    shuffle(edges.begin(), edges.end(), rng);\n    wantEdges = max(0, min(L, wantEdges));\n    for (int e = 0; e < wantEdges; ++e) {\n        auto [u, v] = edges[e];\n        setBit(g, u, v);\n        setBit(g, v, u);\n    }\n    return g;\n}\n\n// channel: random permutation + BSC(eps)\nGraph addNoise(const Graph& g, int n, double ep) {\n    vector<int> perm(n);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    Graph h;\n    initGraph(h, n);\n    uniform_real_distribution<double> d(0.0, 1.0);\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            int pi = perm[i];\n            int pj = perm[j];\n            bool has = getBit(g, pi, pj);\n            if (d(rng) < ep) has = !has;\n            if (has) {\n                setBit(h, i, j);\n                setBit(h, j, i);\n            }\n        }\n    }\n    return h;\n}\n\n// ------------------------------------------------------------\n// Fast permutation-invariant feature extraction\n// ------------------------------------------------------------\nFeature extract(const Graph& g, int n) {\n    ull mask[2];\n    if (n >= 64) {\n        mask[0] = ~0ULL;\n        int r = n - 64;\n        mask[1] = (1ULL << r) - 1ULL;\n    } else {\n        mask[0] = (1ULL << n) - 1ULL;\n        mask[1] = 0;\n    }\n\n    int deg[100] = {};\n    for (int i = 0; i < n; ++i) {\n        deg[i] = __builtin_popcountll(g.a[i][0] & mask[0])\n               + __builtin_popcountll(g.a[i][1] & mask[1]);\n    }\n\n    double tri = 0.0;\n    double tri_pv[100] = {};\n    long long c4h = 0;\n    long long trace4 = 0;\n\n    for (int i = 0; i < n; ++i) {\n        trace4 += 1LL * deg[i] * deg[i];\n        for (int j = i + 1; j < n; ++j) {\n            int c = __builtin_popcountll(g.a[i][0] & g.a[j][0] & mask[0])\n                  + __builtin_popcountll(g.a[i][1] & g.a[j][1] & mask[1]);\n            if (getBit(g, i, j)) {\n                tri += c;\n                tri_pv[i] += c;\n                tri_pv[j] += c;\n            }\n            c4h += 1LL * c * (c - 1) / 2;\n            trace4 += 2LL * c * c;\n        }\n    }\n    tri /= 3.0;\n    for (int i = 0; i < n; ++i) tri_pv[i] *= 0.5;\n\n    double t2[100] = {};\n    double w3[100] = {};\n    for (int i = 0; i < n; ++i) {\n        long long s2 = 0;\n        for (int j = 0; j < n; ++j) if (getBit(g, i, j)) s2 += deg[j];\n        t2[i] = (double)s2;\n    }\n    for (int i = 0; i < n; ++i) {\n        double s3 = 0;\n        for (int j = 0; j < n; ++j) if (getBit(g, i, j)) s3 += t2[j];\n        w3[i] = s3;\n    }\n\n    long long p2 = 0;\n    long long sum_deg2 = 0, sum_deg3 = 0;\n    long long sum_tri = 0, sum_t2 = 0;\n    for (int i = 0; i < n; ++i) {\n        p2 += 1LL * deg[i] * (deg[i] - 1) / 2;\n        sum_deg2 += 1LL * deg[i] * deg[i];\n        sum_deg3 += 1LL * deg[i] * deg[i] * deg[i];\n        sum_tri += (long long)tri_pv[i];\n        sum_t2 += (long long)t2[i];\n    }\n\n    double darr[100], tarr[100], t2arr[100], w3arr[100];\n    for (int i = 0; i < n; ++i) {\n        darr[i] = deg[i];\n        tarr[i] = tri_pv[i];\n        t2arr[i] = t2[i];\n        w3arr[i] = w3[i];\n    }\n    sort(darr, darr + n);\n    sort(tarr, tarr + n);\n    sort(t2arr, t2arr + n);\n    sort(w3arr, w3arr + n);\n\n    double m = 0;\n    for (int i = 0; i < n; ++i) m += deg[i];\n    m *= 0.5;\n\n    Feature f;\n    f.reserve(10 + 4 * n);\n    f.push_back(m);\n    f.push_back(tri);\n    f.push_back(6.0 * tri);          // trace(A^3)\n    f.push_back((double)trace4);     // trace(A^4)\n    f.push_back((double)p2);         // # 2-paths\n    f.push_back((double)c4h);        // helper for 4-cycles\n    f.push_back((double)sum_deg2);\n    f.push_back((double)sum_deg3);\n    f.push_back((double)sum_tri);\n    f.push_back((double)sum_t2);\n    for (int i = 0; i < n; ++i) f.push_back(darr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(tarr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(t2arr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(w3arr[i]);\n    return f;\n}\n\n// ------------------------------------------------------------\n// Decoder\n// ------------------------------------------------------------\nint predict(const Feature& f, const vector<Feature>& F, const vector<double>& w) {\n    int best = 0;\n    double bestv = 1e300;\n    int D = (int)f.size();\n    for (int k = 0; k < (int)F.size(); ++k) {\n        double d = 0.0;\n        for (int i = 0; i < D; ++i) {\n            double diff = f[i] - F[k][i];\n            d += diff * diff * w[i];\n        }\n        if (d < bestv) {\n            bestv = d;\n            best = k;\n        }\n    }\n    return best;\n}\n\n// ------------------------------------------------------------\n// Utilities\n// ------------------------------------------------------------\ndouble binaryEntropy(double p) {\n    if (p <= 0.0 || p >= 1.0) return 0.0;\n    return -(p * log2(p) + (1.0 - p) * log2(1.0 - p));\n}\n\n// Lightweight greedy farthest-point codebook construction\nvector<Graph> generateCodebook(int n, int m) {\n    int L = n * (n - 1) / 2;\n    int poolSize = max(200, m * 2);\n    vector<Graph> pool;\n    pool.reserve(poolSize);\n    uniform_real_distribution<double> pDist(0.05, 0.95);\n\n    for (int i = 0; i < poolSize; ++i) {\n        int want = (int)(L * pDist(rng));\n        want = max(0, min(L, want));\n        pool.push_back(randomGraphWithEdges(n, want));\n    }\n\n    vector<Feature> poolF(poolSize);\n    for (int i = 0; i < poolSize; ++i) poolF[i] = extract(pool[i], n);\n    int D = (int)poolF[0].size();\n\n    // normalize for distance computation\n    vector<double> mean(D, 0.0), stdv(D, 0.0);\n    for (int i = 0; i < poolSize; ++i)\n        for (int d = 0; d < D; ++d) mean[d] += poolF[i][d];\n    for (int d = 0; d < D; ++d) mean[d] /= poolSize;\n    for (int i = 0; i < poolSize; ++i) {\n        for (int d = 0; d < D; ++d) {\n            double diff = poolF[i][d] - mean[d];\n            stdv[d] += diff * diff;\n        }\n    }\n    for (int d = 0; d < D; ++d) stdv[d] = sqrt(stdv[d] / poolSize + 1e-12);\n\n    vector<Graph> cb;\n    vector<Feature> selF;\n    cb.reserve(m);\n    selF.reserve(m);\n\n    int first = (int)(rng() % poolSize);\n    cb.push_back(pool[first]);\n    selF.push_back(poolF[first]);\n\n    vector<double> minDist(poolSize, 1e300);\n    while ((int)cb.size() < m) {\n        int last = (int)cb.size() - 1;\n        for (int j = 0; j < poolSize; ++j) {\n            double d = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double diff = (poolF[j][k] - selF[last][k]) / stdv[k];\n                d += diff * diff;\n            }\n            if (d < minDist[j]) minDist[j] = d;\n        }\n        int best = 0;\n        for (int j = 1; j < poolSize; ++j)\n            if (minDist[j] > minDist[best]) best = j;\n        cb.push_back(pool[best]);\n        selF.push_back(poolF[best]);\n    }\n    return cb;\n}\n\nvector<double> learnWeights(const vector<Graph>& Gs, const vector<Feature>& F, int n) {\n    int D = (int)F[0].size();\n    vector<double> var(D, 0.0);\n    uniform_int_distribution<int> sdist(0, M - 1);\n    int S = 80;\n    for (int b = 0; b < S; ++b) {\n        int s = sdist(rng);\n        Graph h = addNoise(Gs[s], n, eps);\n        Feature f = extract(h, n);\n        for (int d = 0; d < D; ++d) {\n            double diff = f[d] - F[s][d];\n            var[d] += diff * diff;\n        }\n    }\n    vector<double> w(D);\n    for (int d = 0; d < D; ++d) {\n        var[d] /= S;\n        w[d] = 1.0 / (var[d] + 1e-6);\n    }\n    return w;\n}\n\nint validate(const vector<Graph>& Gs, const vector<Feature>& F,\n             const vector<double>& w, int n) {\n    int err = 0;\n    uniform_int_distribution<int> sdist(0, M - 1);\n    for (int b = 0; b < 80; ++b) {\n        int s = sdist(rng);\n        Graph h = addNoise(Gs[s], n, eps);\n        Feature f = extract(h, n);\n        if (predict(f, F, w) != s) ++err;\n    }\n    return err;\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> M >> eps)) return 0;\n\n    double cap = 1.0 - binaryEntropy(eps);\n    double needBits = log2((double)M) + 20.0;          // generous margin\n    double needEdges = needBits / max(cap, 1e-9);\n    int startN = 4;\n    while (startN * (startN - 1) / 2.0 < needEdges && startN < 100) ++startN;\n    startN = max(startN, 8);\n    startN = min(startN, 100);\n\n    vector<Graph> bestG;\n    vector<Feature> bestF;\n    vector<double> bestW;\n    int bestN = 100;\n    bool found = false;\n\n    for (int delta = 0; delta <= 8; delta += 2) {\n        int n = startN + delta;\n        if (n > 100) n = 100;\n        for (int attempt = 0; attempt < 3; ++attempt) {\n            auto Gs = generateCodebook(n, M);\n            vector<Feature> F(M);\n            for (int k = 0; k < M; ++k) F[k] = extract(Gs[k], n);\n            auto w = learnWeights(Gs, F, n);\n            int err = validate(Gs, F, w, n);\n            if (err == 0) {\n                bestN = n;\n                bestG = move(Gs);\n                bestF = move(F);\n                bestW = move(w);\n                found = true;\n                break;\n            }\n        }\n        if (found) break;\n        if (n == 100) break;\n    }\n\n    if (!found) {\n        bestN = 100;\n        bestG = generateCodebook(100, M);\n        bestF.resize(M);\n        for (int k = 0; k < M; ++k) bestF[k] = extract(bestG[k], 100);\n        bestW = learnWeights(bestG, bestF, 100);\n    }\n\n    // output codebook\n    cout << bestN << \"\\n\";\n    for (int k = 0; k < M; ++k) {\n        string s;\n        s.reserve(bestN * (bestN - 1) / 2);\n        for (int i = 0; i < bestN; ++i) {\n            for (int j = i + 1; j < bestN; ++j) {\n                s.push_back(getBit(bestG[k], i, j) ? '1' : '0');\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // answer 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string hs;\n        cin >> hs;\n        Graph h;\n        initGraph(h, bestN);\n        int pos = 0;\n        for (int i = 0; i < bestN; ++i) {\n            for (int j = i + 1; j < bestN; ++j) {\n                if (hs[pos++] == '1') {\n                    setBit(h, i, j);\n                    setBit(h, j, i);\n                }\n            }\n        }\n        Feature f = extract(h, bestN);\n        int ans = predict(f, bestF, bestW);\n        cout << ans << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst int INF_INT = 1000000000;\nconst ll INF_LL = (1LL<<60);\n\nstruct SimpleHeap {\n    static const int MAXN = 10005;\n    pair<int,int> a[MAXN];\n    int n;\n    void clear(){ n=0; }\n    void push(pair<int,int> x){\n        int i=n++;\n        while(i>0){\n            int p=(i-1)>>1;\n            if(a[p].first <= x.first) break;\n            a[i]=a[p];\n            i=p;\n        }\n        a[i]=x;\n    }\n    pair<int,int> top() const { return a[0]; }\n    void pop(){\n        pair<int,int> x = a[--n];\n        int i=0;\n        while(true){\n            int l=(i<<1)|1;\n            if(l>=n) break;\n            int r=l+1, c=l;\n            if(r<n && a[r].first < a[l].first) c=r;\n            if(x.first <= a[c].first) break;\n            a[i]=a[c];\n            i=c;\n        }\n        a[i]=x;\n    }\n    bool empty() const { return n==0; }\n};\n\nint N, M, D, K;\nstruct Edge {int u, v, w;};\nvector<Edge> edges;\nvector<vector<tuple<int,int,int>>> adj;\nvector<int> rem_stamp;\nint cur_stamp = 1;\n\ninline pair<int,ll> dijkstra(int s, int stamp, vector<int>& dist, SimpleHeap& pq){\n    fill(dist.begin(), dist.end(), INF_INT);\n    dist[s] = 0;\n    pq.clear();\n    pq.push({0, s});\n    ll sum = 0;\n    int visited = 0;\n    while(!pq.empty()){\n        auto [d,u] = pq.top(); pq.pop();\n        if(d != dist[u]) continue;\n        visited++;\n        sum += d;\n        for(const auto& [v,w,eid] : adj[u]){\n            if(rem_stamp[eid] == stamp) continue;\n            if(dist[v] > d + w){\n                dist[v] = d + w;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {visited, sum};\n}\n\n// Evaluate proxy score of a day. exact=false -> INF if disconnected. exact=true -> add penalty.\nll eval_day(int day, int out_eid, int in_eid, const vector<int>& samples,\n            const vector<vector<int>>& day_edges,\n            vector<int>& dist, SimpleHeap& pq, bool exact=false){\n    int stamp = cur_stamp++;\n    for(int eid : day_edges[day]){\n        if(eid == out_eid) continue;\n        rem_stamp[eid] = stamp;\n    }\n    if(in_eid != -1) rem_stamp[in_eid] = stamp;\n    ll total = 0;\n    for(int s : samples){\n        auto [vis, sum] = dijkstra(s, stamp, dist, pq);\n        if(vis < N){\n            if(!exact) return INF_LL;\n            total += sum + (ll)(N - vis) * INF_INT;\n        } else {\n            total += sum;\n        }\n    }\n    return total;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    cin >> N >> M >> D >> K;\n    edges.resize(M);\n    adj.assign(N, {});\n    vector<int> xs(N), ys(N);\n    for(int i=0;i<M;i++){\n        int u,v,w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u,v,w};\n        adj[u].push_back({v,w,i});\n        adj[v].push_back({u,w,i});\n    }\n    for(int i=0;i<N;i++) cin >> xs[i] >> ys[i];\n\n    rem_stamp.assign(M, 0);\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // ----- approximate edge importance (shortest path tree usage) -----\n    vector<int> imp(M, 0);\n    vector<int> dist0(N);\n    vector<int> parent(N);\n    SimpleHeap pq0;\n    for(int it=0; it<100; it++){\n        int s = rng() % N;\n        fill(dist0.begin(), dist0.end(), INF_INT);\n        dist0[s] = 0;\n        fill(parent.begin(), parent.end(), -1);\n        pq0.clear();\n        pq0.push({0, s});\n        while(!pq0.empty()){\n            auto [d,u] = pq0.top(); pq0.pop();\n            if(d != dist0[u]) continue;\n            for(const auto& [v,w,eid] : adj[u]){\n                if(dist0[v] > d + w){\n                    dist0[v] = d + w;\n                    parent[v] = eid;\n                    pq0.push({dist0[v], v});\n                }\n            }\n        }\n        for(int v=0; v<N; v++){\n            if(v != s && parent[v] != -1) imp[parent[v]]++;\n        }\n    }\n\n    // ----- greedy initialization (balance importance) -----\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        if(imp[a] != imp[b]) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    vector<int> edge_day(M);\n    vector<vector<int>> day_edges(D);\n    vector<ll> day_imp_sum(D, 0);\n    vector<int> day_load(D, 0);\n    for(int eid : order){\n        int best_d = -1;\n        ll best_val = INF_LL;\n        for(int d=0; d<D; d++){\n            if(day_load[d] >= K) continue;\n            if(day_imp_sum[d] < best_val){\n                best_val = day_imp_sum[d];\n                best_d = d;\n            }\n        }\n        if(best_d == -1){\n            for(int d=0; d<D; d++) if(day_load[d] < K){ best_d = d; break; }\n        }\n        edge_day[eid] = best_d;\n        day_edges[best_d].push_back(eid);\n        day_load[best_d]++;\n        day_imp_sum[best_d] += imp[eid];\n    }\n\n    // ----- ensure every day is connected -----\n    vector<int> dist(N);\n    SimpleHeap pq;\n    auto is_conn = [&](int d)->bool{\n        static vector<int> dummy = {0};\n        return eval_day(d, -1, -1, dummy, day_edges, dist, pq) < INF_LL;\n    };\n\n    for(int d=0; d<D; d++){\n        int attempts = 0;\n        while(!is_conn(d)){\n            int d2 = rng() % D;\n            if(d2 == d) continue;\n            if(day_edges[d].empty() || day_edges[d2].empty()) continue;\n            int i1 = rng() % (int)day_edges[d].size();\n            int i2 = rng() % (int)day_edges[d2].size();\n            int e1 = day_edges[d][i1];\n            int e2 = day_edges[d2][i2];\n            swap(day_edges[d][i1], day_edges[d2][i2]);\n            edge_day[e1] = d2;\n            edge_day[e2] = d;\n            if(is_conn(d) && is_conn(d2)){\n                // keep swap\n            } else {\n                swap(day_edges[d][i1], day_edges[d2][i2]);\n                edge_day[e1] = d;\n                edge_day[e2] = d2;\n            }\n            if(++attempts > 20000) break;\n        }\n    }\n\n    // ----- stratified sample sources -----\n    vector<pair<int,int>> nodes_by_x;\n    for(int i=0;i<N;i++) nodes_by_x.push_back({xs[i], i});\n    sort(nodes_by_x.begin(), nodes_by_x.end());\n    const int NS = 20;\n    vector<int> samples;\n    for(int i=0;i<NS;i++){\n        int L = i * N / NS;\n        int R = (i+1) * N / NS;\n        if(L >= R) continue;\n        int idx = L + (int)(rng() % (R - L));\n        samples.push_back(nodes_by_x[idx].second);\n    }\n    while((int)samples.size() < NS) samples.push_back(rng() % N);\n\n    // ----- compute initial proxy scores -----\n    vector<ll> day_score(D);\n    auto recompute_day = [&](int d){\n        day_score[d] = eval_day(d, -1, -1, samples, day_edges, dist, pq);\n    };\n    for(int d=0; d<D; d++) recompute_day(d);\n    ll cur_total = 0;\n    for(ll v : day_score) cur_total += v;\n\n    vector<int> best_edge_day = edge_day;\n    vector<vector<int>> best_day_edges = day_edges;\n    ll best_total = cur_total;\n\n    const double TIME_LIMIT = 5.4;\n    int stagnant = 0;\n\n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if(elapsed > TIME_LIMIT) break;\n\n        int d1 = rng() % D;\n        int d2 = rng() % D;\n        if(d1 == d2) continue;\n        if(day_edges[d1].empty() || day_edges[d2].empty()) continue;\n        int i1 = rng() % (int)day_edges[d1].size();\n        int i2 = rng() % (int)day_edges[d2].size();\n        int e1 = day_edges[d1][i1];\n        int e2 = day_edges[d2][i2];\n\n        ll s1 = eval_day(d1, e1, e2, samples, day_edges, dist, pq);\n        if(s1 >= INF_LL) continue;\n        ll s2 = eval_day(d2, e2, e1, samples, day_edges, dist, pq);\n        if(s2 >= INF_LL) continue;\n\n        ll new_total = cur_total - day_score[d1] - day_score[d2] + s1 + s2;\n        if(new_total < cur_total){\n            edge_day[e1] = d2;\n            edge_day[e2] = d1;\n            day_edges[d1][i1] = e2;\n            day_edges[d2][i2] = e1;\n            day_score[d1] = s1;\n            day_score[d2] = s2;\n            cur_total = new_total;\n            stagnant = 0;\n            if(cur_total < best_total){\n                best_total = cur_total;\n                best_edge_day = edge_day;\n                best_day_edges = day_edges;\n            }\n        } else {\n            stagnant++;\n            if(stagnant > 300){\n                // perturb from best and continue\n                bool ok = false;\n                for(int attempt=0; attempt<10; attempt++){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                    int num_swaps = 10 + (int)(rng() % 10);\n                    for(int k=0; k<num_swaps; k++){\n                        int a = rng() % D;\n                        int b = rng() % D;\n                        if(a == b) continue;\n                        if(day_edges[a].empty() || day_edges[b].empty()) continue;\n                        int ai = rng() % (int)day_edges[a].size();\n                        int bi = rng() % (int)day_edges[b].size();\n                        int ae = day_edges[a][ai];\n                        int be = day_edges[b][bi];\n                        swap(day_edges[a][ai], day_edges[b][bi]);\n                        edge_day[ae] = b;\n                        edge_day[be] = a;\n                    }\n                    bool all_conn = true;\n                    for(int d=0; d<D; d++){\n                        if(!is_conn(d)){\n                            all_conn = false;\n                            break;\n                        }\n                    }\n                    if(all_conn){\n                        ok = true;\n                        break;\n                    }\n                }\n                if(!ok){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                }\n                for(int d=0; d<D; d++) recompute_day(d);\n                cur_total = 0;\n                for(ll v : day_score) cur_total += v;\n                stagnant = 0;\n                if(cur_total < best_total){\n                    best_total = cur_total;\n                    best_edge_day = edge_day;\n                    best_day_edges = day_edges;\n                }\n            }\n        }\n    }\n\n    for(int i=0;i<M;i++){\n        if(i) cout << ' ';\n        cout << best_edge_day[i] + 1;\n    }\n    cout << '\\n';\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nvector<string> F[2], R[2];\n\n// bitsets for fast occupancy / validity checks on a layer\nusing BS = bitset<196>;\nBS validMask[2][16];\nBS occ[2][16];\nbool needF[2][16][16] = {};\nbool needR[2][16][16] = {};\n\n// 3D prefix sums: pref[idx][x][y][z] (size D+1)\nint pref[2][17][17][17];\n// prefix sums for needF / needR per layer\nint needPrefF[2][16][17];\nint needPrefR[2][16][17];\n\nstruct Block {\n    int id;\n    vector<array<int,3>> c[2];\n};\nvector<Block> blocks;\nint nextId = 1;\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nchrono::steady_clock::time_point startT;\n\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startT).count();\n}\n\n/* ---------- 3D prefix sum helpers ---------- */\nvoid rebuildPref(int idx) {\n    for (int x = 0; x < D; ++x)\n        for (int y = 0; y < D; ++y)\n            for (int z = 0; z < D; ++z) {\n                int v = (validMask[idx][z].test(x * D + y) && !occ[idx][z].test(x * D + y)) ? 1 : 0;\n                pref[idx][x + 1][y + 1][z + 1] =\n                    v\n                    + pref[idx][x][y + 1][z + 1]\n                    + pref[idx][x + 1][y][z + 1]\n                    + pref[idx][x + 1][y + 1][z]\n                    - pref[idx][x][y][z + 1]\n                    - pref[idx][x][y + 1][z]\n                    - pref[idx][x + 1][y][z]\n                    + pref[idx][x][y][z];\n            }\n}\n\ninline int boxSum(int idx, int x, int y, int z, int dx, int dy, int dz) {\n    auto &p = pref[idx];\n    int x1 = x, y1 = y, z1 = z;\n    int x2 = x + dx, y2 = y + dy, z2 = z + dz;\n    return p[x2][y2][z2] - p[x1][y2][z2] - p[x2][y1][z2] - p[x2][y2][z1]\n         + p[x1][y1][z2] + p[x1][y2][z1] + p[x2][y1][z1] - p[x1][y1][z1];\n}\n\n/* ---------- need prefix helpers ---------- */\nvoid rebuildNeedPref(int idx) {\n    for (int z = 0; z < D; ++z) {\n        needPrefF[idx][z][0] = 0;\n        needPrefR[idx][z][0] = 0;\n        for (int i = 0; i < D; ++i) {\n            needPrefF[idx][z][i + 1] = needPrefF[idx][z][i] + (needF[idx][z][i] ? 1 : 0);\n            needPrefR[idx][z][i + 1] = needPrefR[idx][z][i] + (needR[idx][z][i] ? 1 : 0);\n        }\n    }\n}\n\ninline int boxBenefit(int idx, int x, int y, int z, int dx, int dy, int dz) {\n    int ben = 0;\n    for (int k = 0; k < dz; ++k) {\n        ben += needPrefF[idx][z + k][x + dx] - needPrefF[idx][z + k][x];\n        ben += needPrefR[idx][z + k][y + dy] - needPrefR[idx][z + k][y];\n    }\n    return ben;\n}\n\n/* ---------- placement helper ---------- */\nvoid placeShared(const vector<array<int,3>> &c1, const vector<array<int,3>> &c2) {\n    int id = nextId++;\n    for (auto [x, y, z] : c1) {\n        occ[0][z].set(x * D + y);\n        needF[0][z][x] = false;\n        needR[0][z][y] = false;\n    }\n    for (auto [x, y, z] : c2) {\n        occ[1][z].set(x * D + y);\n        needF[1][z][x] = false;\n        needR[1][z][y] = false;\n    }\n    blocks.push_back({id, c1, c2});\n}\n\n/* ---------- 24 proper rotations ---------- */\nvector<array<array<int,3>,3>> genRotations() {\n    vector<array<array<int,3>,3>> res;\n    array<int,3> p = {0, 1, 2};\n    do {\n        int signPerm = ((p[0] == 0 && p[1] == 1 && p[2] == 2) ||\n                        (p[0] == 1 && p[1] == 2 && p[2] == 0) ||\n                        (p[0] == 2 && p[1] == 0 && p[2] == 1)) ? 1 : -1;\n        for (int sx : {1, -1}) {\n            for (int sy : {1, -1}) {\n                int sz = sx * sy * signPerm;\n                array<array<int,3>,3> m = {};\n                m[0][p[0]] = sx;\n                m[1][p[1]] = sy;\n                m[2][p[2]] = sz;\n                res.push_back(m);\n            }\n        }\n    } while (next_permutation(p.begin(), p.end()));\n    return res;\n}\n\n/* ================================================================ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    startT = chrono::steady_clock::now();\n\n    /* ---- input ---- */\n    if (!(cin >> D)) return 0;\n    for (int i = 0; i < 2; ++i) {\n        F[i].resize(D);\n        R[i].resize(D);\n        for (int z = 0; z < D; ++z) cin >> F[i][z];\n        for (int z = 0; z < D; ++z) cin >> R[i][z];\n    }\n\n    auto rots = genRotations();\n\n    /* ---- valid masks and needs ---- */\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            for (int x = 0; x < D; ++x) {\n                needF[i][z][x] = (F[i][z][x] == '1');\n                for (int y = 0; y < D; ++y) {\n                    bool ok = (F[i][z][x] == '1' && R[i][z][y] == '1');\n                    if (ok) validMask[i][z].set(x * D + y);\n                    needR[i][z][y] = (R[i][z][y] == '1');\n                }\n            }\n        }\n    }\n\n    /* ---- list of ordered box shapes (volume >= 2) ---- */\n    struct Shape { int dx, dy, dz, vol; };\n    vector<Shape> shapes;\n    for (int dx = 1; dx <= D; ++dx)\n        for (int dy = 1; dy <= D; ++dy)\n            for (int dz = 1; dz <= D; ++dz)\n                if (dx * dy * dz >= 2)\n                    shapes.push_back({dx, dy, dz, dx * dy * dz});\n    sort(shapes.begin(), shapes.end(),\n         [](const Shape &a, const Shape &b) { return a.vol > b.vol; });\n\n    const double BOX_TIME = 3.5;\n    const double TIME_LIMIT = 5.7;\n\n    /* ============================================================\n       PHASE 1 : Greedy shared boxes\n       ============================================================ */\n    while (elapsed() < BOX_TIME) {\n        rebuildPref(0); rebuildPref(1);\n        rebuildNeedPref(0); rebuildNeedPref(1);\n\n        long long bestScore = -1;\n        int best_x1 = 0, best_y1 = 0, best_z1 = 0;\n        int best_x2 = 0, best_y2 = 0, best_z2 = 0;\n        int best_dx = 0, best_dy = 0, best_dz = 0;\n        int best_px = 0, best_py = 0, best_pz = 0;\n\n        int limitShapes = min((int)shapes.size(), 300);\n        for (int si = 0; si < limitShapes; ++si) {\n            int dx = shapes[si].dx, dy = shapes[si].dy, dz = shapes[si].dz;\n            int vol = shapes[si].vol;\n\n            /* positions in object 1 */\n            vector<array<int,3>> L1;\n            L1.reserve(512);\n            for (int x = 0; x + dx <= D; ++x)\n                for (int y = 0; y + dy <= D; ++y)\n                    for (int z = 0; z + dz <= D; ++z)\n                        if (boxSum(0, x, y, z, dx, dy, dz) == vol)\n                            L1.push_back({x, y, z});\n            if (L1.empty()) continue;\n            if ((int)L1.size() > 50) {\n                shuffle(L1.begin(), L1.end(), rng);\n                L1.resize(50);\n            }\n\n            /* try all rotations of the box for object 2 */\n            array<int,3> dim = {dx, dy, dz};\n            sort(dim.begin(), dim.end());\n            do {\n                int px = dim[0], py = dim[1], pz = dim[2];\n                vector<array<int,3>> L2;\n                L2.reserve(512);\n                for (int x = 0; x + px <= D; ++x)\n                    for (int y = 0; y + py <= D; ++y)\n                        for (int z = 0; z + pz <= D; ++z)\n                            if (boxSum(1, x, y, z, px, py, pz) == vol)\n                                L2.push_back({x, y, z});\n                if (L2.empty()) continue;\n                if ((int)L2.size() > 50) {\n                    shuffle(L2.begin(), L2.end(), rng);\n                    L2.resize(50);\n                }\n\n                for (auto &p1 : L1) {\n                    int ben1 = boxBenefit(0, p1[0], p1[1], p1[2], dx, dy, dz);\n                    for (auto &p2 : L2) {\n                        int ben2 = boxBenefit(1, p2[0], p2[1], p2[2], px, py, pz);\n                        if (ben1 + ben2 == 0) continue;\n                        long long score = (long long)(ben1 + ben2) * 1000LL + vol;\n                        if (score > bestScore) {\n                            bestScore = score;\n                            best_x1 = p1[0]; best_y1 = p1[1]; best_z1 = p1[2];\n                            best_x2 = p2[0]; best_y2 = p2[1]; best_z2 = p2[2];\n                            best_dx = dx; best_dy = dy; best_dz = dz;\n                            best_px = px; best_py = py; best_pz = pz;\n                        }\n                    }\n                }\n            } while (next_permutation(dim.begin(), dim.end()));\n        }\n\n        if (bestScore <= 0) break;\n\n        vector<array<int,3>> c1, c2;\n        c1.reserve(best_dx * best_dy * best_dz);\n        c2.reserve(best_px * best_py * best_pz);\n        for (int k = 0; k < best_dz; ++k)\n            for (int i = 0; i < best_dx; ++i)\n                for (int j = 0; j < best_dy; ++j)\n                    c1.push_back({best_x1 + i, best_y1 + j, best_z1 + k});\n        for (int k = 0; k < best_pz; ++k)\n            for (int i = 0; i < best_px; ++i)\n                for (int j = 0; j < best_py; ++j)\n                    c2.push_back({best_x2 + i, best_y2 + j, best_z2 + k});\n        placeShared(c1, c2);\n    }\n\n    /* ============================================================\n       PHASE 2 : Randomized shared polycubes\n       ============================================================ */\n    const int DIRS[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};\n\n    while (elapsed() < TIME_LIMIT) {\n        /* gather free cells for seeding */\n        vector<array<int,3>> freeList[2];\n        for (int idx = 0; idx < 2; ++idx)\n            for (int x = 0; x < D; ++x)\n                for (int y = 0; y < D; ++y)\n                    for (int z = 0; z < D; ++z)\n                        if (validMask[idx][z].test(x * D + y) && !occ[idx][z].test(x * D + y))\n                            freeList[idx].push_back({x, y, z});\n\n        if (freeList[0].empty() || freeList[1].empty()) break;\n\n        long long bestScore = -1;\n        vector<array<int,3>> bestC1, bestC2;\n\n        for (int it = 0; it < 2500; ++it) {\n            auto s1 = freeList[0][rng() % freeList[0].size()];\n            auto s2 = freeList[1][rng() % freeList[1].size()];\n            const auto &rot = rots[rng() % rots.size()];\n\n            vector<array<int,3>> shape;\n            shape.reserve(50);\n            shape.push_back({0, 0, 0});\n            vector<array<int,3>> q = {{0, 0, 0}};\n\n            while (!q.empty() && (int)shape.size() < 50) {\n                int qi = (int)(rng() % q.size());\n                auto cur = q[qi];\n                q[qi] = q.back(); q.pop_back();\n\n                array<int,6> order = {0, 1, 2, 3, 4, 5};\n                shuffle(order.begin(), order.end(), rng);\n                for (int di : order) {\n                    int nx = cur[0] + DIRS[di][0];\n                    int ny = cur[1] + DIRS[di][1];\n                    int nz = cur[2] + DIRS[di][2];\n\n                    bool dup = false;\n                    for (auto &v : shape)\n                        if (v[0] == nx && v[1] == ny && v[2] == nz) { dup = true; break; }\n                    if (dup) continue;\n\n                    int ax1 = s1[0] + nx, ay1 = s1[1] + ny, az1 = s1[2] + nz;\n                    if (ax1 < 0 || ax1 >= D || ay1 < 0 || ay1 >= D || az1 < 0 || az1 >= D) continue;\n                    if (!validMask[0][az1].test(ax1 * D + ay1) || occ[0][az1].test(ax1 * D + ay1)) continue;\n\n                    int rx = rot[0][0] * nx + rot[0][1] * ny + rot[0][2] * nz;\n                    int ry = rot[1][0] * nx + rot[1][1] * ny + rot[1][2] * nz;\n                    int rz = rot[2][0] * nx + rot[2][1] * ny + rot[2][2] * nz;\n                    int ax2 = s2[0] + rx, ay2 = s2[1] + ry, az2 = s2[2] + rz;\n                    if (ax2 < 0 || ax2 >= D || ay2 < 0 || ay2 >= D || az2 < 0 || az2 >= D) continue;\n                    if (!validMask[1][az2].test(ax2 * D + ay2) || occ[1][az2].test(ax2 * D + ay2)) continue;\n\n                    shape.push_back({nx, ny, nz});\n                    q.push_back({nx, ny, nz});\n                }\n            }\n\n            if ((int)shape.size() < 2) continue;\n\n            bool seenF1[16][16] = {}, seenR1[16][16] = {};\n            int ben1 = 0;\n            for (auto &rel : shape) {\n                int ax = s1[0] + rel[0], ay = s1[1] + rel[1], az = s1[2] + rel[2];\n                if (!seenF1[az][ax] && needF[0][az][ax]) { seenF1[az][ax] = true; ++ben1; }\n                if (!seenR1[az][ay] && needR[0][az][ay]) { seenR1[az][ay] = true; ++ben1; }\n            }\n\n            bool seenF2[16][16] = {}, seenR2[16][16] = {};\n            int ben2 = 0;\n            for (auto &rel : shape) {\n                int rx = rot[0][0] * rel[0] + rot[0][1] * rel[1] + rot[0][2] * rel[2];\n                int ry = rot[1][0] * rel[0] + rot[1][1] * rel[1] + rot[1][2] * rel[2];\n                int rz = rot[2][0] * rel[0] + rot[2][1] * rel[1] + rot[2][2] * rel[2];\n                int ax = s2[0] + rx, ay = s2[1] + ry, az = s2[2] + rz;\n                if (!seenF2[az][ax] && needF[1][az][ax]) { seenF2[az][ax] = true; ++ben2; }\n                if (!seenR2[az][ay] && needR[1][az][ay]) { seenR2[az][ay] = true; ++ben2; }\n            }\n\n            if (ben1 + ben2 == 0) continue;\n            long long score = (long long)(ben1 + ben2) * 1000LL + (int)shape.size();\n            if (score > bestScore) {\n                bestScore = score;\n                bestC1.clear(); bestC2.clear();\n                for (auto &rel : shape) bestC1.push_back({s1[0] + rel[0], s1[1] + rel[1], s1[2] + rel[2]});\n                for (auto &rel : shape) {\n                    int rx = rot[0][0] * rel[0] + rot[0][1] * rel[1] + rot[0][2] * rel[2];\n                    int ry = rot[1][0] * rel[0] + rot[1][1] * rel[1] + rot[1][2] * rel[2];\n                    int rz = rot[2][0] * rel[0] + rot[2][1] * rel[1] + rot[2][2] * rel[2];\n                    bestC2.push_back({s2[0] + rx, s2[1] + ry, s2[2] + rz});\n                }\n            }\n        }\n\n        if (bestScore > 0) placeShared(bestC1, bestC2);\n        else break;\n    }\n\n    /* ============================================================\n       PHASE 3 : Minimum edge cover for the remaining needs\n       ============================================================ */\n    vector<array<int,3>> uniq[2];\n\n    for (int idx = 0; idx < 2; ++idx) {\n        for (int z = 0; z < D; ++z) {\n            vector<int> xs, ys;\n            for (int x = 0; x < D; ++x) if (needF[idx][z][x]) xs.push_back(x);\n            for (int y = 0; y < D; ++y) if (needR[idx][z][y]) ys.push_back(y);\n            int nL = (int)xs.size(), nR = (int)ys.size();\n            if (nL == 0 && nR == 0) continue;\n\n            /* no front needs -> just pick any valid cell for each right need */\n            if (nL == 0) {\n                for (int y : ys) {\n                    for (int x = 0; x < D; ++x) {\n                        int c = x * D + y;\n                        if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                            occ[idx][z].set(c);\n                            uniq[idx].push_back({x, y, z});\n                            break;\n                        }\n                    }\n                }\n                continue;\n            }\n            /* no right needs -> pick any valid cell for each front need */\n            if (nR == 0) {\n                for (int x : xs) {\n                    for (int y = 0; y < D; ++y) {\n                        int c = x * D + y;\n                        if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                            occ[idx][z].set(c);\n                            uniq[idx].push_back({x, y, z});\n                            break;\n                        }\n                    }\n                }\n                continue;\n            }\n\n            /* build adjacency and map y -> right index */\n            int yId[16];\n            fill(begin(yId), end(yId), -1);\n            for (int i = 0; i < nR; ++i) yId[ys[i]] = i;\n            vector<vector<int>> adj(nL);\n            for (int i = 0; i < nL; ++i) {\n                int x = xs[i];\n                for (int y : ys) {\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c))\n                        adj[i].push_back(yId[y]);\n                }\n            }\n\n            /* Kuhn's augmenting path (left size <= 14, right size <= 14) */\n            vector<int> matchR(nR, -1);\n            function<bool(int, vector<char>&)> dfs = [&](int v, vector<char> &seen) -> bool {\n                for (int to : adj[v]) {\n                    if (seen[to]) continue;\n                    seen[to] = 1;\n                    if (matchR[to] == -1 || dfs(matchR[to], seen)) {\n                        matchR[to] = v;\n                        return true;\n                    }\n                }\n                return false;\n            };\n            for (int v = 0; v < nL; ++v) {\n                vector<char> seen(nR, 0);\n                dfs(v, seen);\n            }\n\n            vector<char> matchedL(nL, 0), matchedR(nR, 0);\n            vector<pair<int,int>> cover; // (left idx, right idx)\n\n            for (int j = 0; j < nR; ++j) if (matchR[j] != -1) {\n                cover.push_back({matchR[j], j});\n                matchedL[matchR[j]] = 1;\n                matchedR[j] = 1;\n            }\n            for (int i = 0; i < nL; ++i) if (!matchedL[i]) {\n                for (int to : adj[i]) {\n                    cover.push_back({i, to});\n                    break;\n                }\n            }\n            for (int j = 0; j < nR; ++j) if (!matchedR[j]) {\n                int y = ys[j];\n                for (int i = 0; i < nL; ++i) {\n                    int x = xs[i];\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                        cover.push_back({i, j});\n                        break;\n                    }\n                }\n            }\n\n            sort(cover.begin(), cover.end());\n            cover.erase(unique(cover.begin(), cover.end()), cover.end());\n\n            for (auto &e : cover) {\n                int x = xs[e.first];\n                int y = ys[e.second];\n                int c = x * D + y;\n                if (!validMask[idx][z].test(c) || occ[idx][z].test(c)) continue;\n                occ[idx][z].set(c);\n                uniq[idx].push_back({x, y, z});\n            }\n        }\n    }\n\n    /* ============================================================\n       PHASE 4 : Pair unit cubes between the two objects\n       ============================================================ */\n    int common = min((int)uniq[0].size(), (int)uniq[1].size());\n    vector<int> id0(uniq[0].size()), id1(uniq[1].size());\n    int curId = 1;\n    for (auto &bl : blocks) bl.id = curId++;\n    for (int i = 0; i < common; ++i) {\n        id0[i] = curId;\n        id1[i] = curId;\n        ++curId;\n    }\n    for (int i = common; i < (int)uniq[0].size(); ++i) id0[i] = curId++;\n    for (int i = common; i < (int)uniq[1].size(); ++i) id1[i] = curId++;\n\n    /* ============================================================\n       Output\n       ============================================================ */\n    vector<int> b0(D * D * D, 0), b1(D * D * D, 0);\n    for (auto &bl : blocks) {\n        for (auto [x, y, z] : bl.c[0]) b0[x * D * D + y * D + z] = bl.id;\n        for (auto [x, y, z] : bl.c[1]) b1[x * D * D + y * D + z] = bl.id;\n    }\n    for (int i = 0; i < (int)uniq[0].size(); ++i) {\n        auto [x, y, z] = uniq[0][i];\n        b0[x * D * D + y * D + z] = id0[i];\n    }\n    for (int i = 0; i < (int)uniq[1].size(); ++i) {\n        auto [x, y, z] = uniq[1][i];\n        b1[x * D * D + y * D + z] = id1[i];\n    }\n\n    cout << (curId - 1) << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b0[i];\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b1[i];\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = (1LL << 60);\n\nint N, M, K;\nlong long xs[100], ys[100];\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nEdge edges[300];\nEdge esort[300];\nint edgeIdMat[100][100];\nvector<pair<int,int>> adj[100];\n\n// need[k][v] : ceil distance between resident k and vertex v\nstatic int need[5000][100];\n\n// ---------- DSU ----------\nstruct DSU {\n    int p[100];\n    int rnk[100];\n    void init(int n) {\n        for (int i = 0; i < n; ++i) {\n            p[i] = i;\n            rnk[i] = 0;\n        }\n    }\n    int find(int x) { return p[x]==x ? x : p[x]=find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a,b);\n        p[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n};\n\n// ---------- MST of induced subgraph ----------\nlong long mst(const char inV[100], pair<int,int> te[100], int& teCnt) {\n    teCnt = 0;\n    int nV = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) ++nV;\n    if (nV == 0) return INF;\n    if (nV == 1) return 0;\n    DSU dsu;\n    dsu.init(N);\n    long long cost = 0;\n    int used = 0;\n    for (int j = 0; j < M; ++j) {\n        int u = esort[j].u, v = esort[j].v;\n        if (!inV[u] || !inV[v]) continue;\n        if (dsu.unite(u, v)) {\n            te[teCnt++] = {u, v};\n            cost += esort[j].w;\n            if (++used == nV - 1) break;\n        }\n    }\n    if (used != nV - 1) return INF;\n    return cost;\n}\n\n// ---------- Greedy power cost, capped at 5000 ----------\nlong long calc_power(const char inV[100], int outP[100]) {\n    int act[100];\n    int R = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) act[R++] = i;\n    if (R == 0) return INF;\n\n    static int minNeed[5000];\n    for (int k = 0; k < K; ++k) {\n        int mn = 100000;\n        for (int i = 0; i < R; ++i) {\n            int d = need[k][act[i]];\n            if (d < mn) mn = d;\n        }\n        if (mn > 5000) return INF;\n        minNeed[k] = mn;\n    }\n\n    static int bucketHead[5001];\n    static int bucketNext[5000];\n    memset(bucketHead, -1, sizeof(bucketHead));\n    for (int k = 0; k < K; ++k) {\n        int d = minNeed[k];\n        bucketNext[k] = bucketHead[d];\n        bucketHead[d] = k;\n    }\n\n    static int Plocal[100];\n    for (int i = 0; i < R; ++i) Plocal[i] = 0;\n\n    for (int d = 5000; d >= 0; --d) {\n        for (int k = bucketHead[d]; k != -1; k = bucketNext[k]) {\n            int bestIdx = -1;\n            long long bestInc = LLONG_MAX;\n            for (int i = 0; i < R; ++i) {\n                int dist = need[k][act[i]];\n                if (dist > 5000) continue;\n                if (Plocal[i] >= dist) {\n                    bestIdx = i;\n                    bestInc = 0;\n                    break;\n                }\n                long long inc = 1LL*dist*dist - 1LL*Plocal[i]*Plocal[i];\n                if (inc < bestInc) {\n                    bestInc = inc;\n                    bestIdx = i;\n                }\n            }\n            if (bestIdx == -1) return INF;\n            int dist = need[k][act[bestIdx]];\n            if (dist > Plocal[bestIdx]) Plocal[bestIdx] = dist;\n        }\n    }\n\n    long long cost = 0;\n    for (int i = 0; i < N; ++i) outP[i] = 0;\n    for (int i = 0; i < R; ++i) {\n        outP[act[i]] = Plocal[i];\n        cost += 1LL*Plocal[i]*Plocal[i];\n    }\n    return cost;\n}\n\n// ---------- evaluate full state ----------\nbool evalFull(const char inV[100], long long& outCost,\n              pair<int,int> te[100], int& teCnt, int outP[100]) {\n    long long ec = mst(inV, te, teCnt);\n    if (ec >= INF) return false;\n    long long pc = calc_power(inV, outP);\n    if (pc >= INF) return false;\n    outCost = ec + pc;\n    return true;\n}\n\n// ---------- deterministic first-improvement descent ----------\nvoid descent(char inV[100], long long& cost,\n             pair<int,int> te[100], int& teCnt, int P[100],\n             mt19937& rng) {\n    while (true) {\n        // --- try remove a leaf ---\n        int deg[100] = {0};\n        for (int i = 0; i < teCnt; ++i) {\n            ++deg[te[i].first];\n            ++deg[te[i].second];\n        }\n        int leaves[100], leafCnt = 0;\n        for (int i = 1; i < N; ++i)\n            if (inV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n\n        if (leafCnt > 0) {\n            shuffle(leaves, leaves + leafCnt, rng);\n            bool improved = false;\n            for (int idx = 0; idx < leafCnt; ++idx) {\n                int u = leaves[idx];\n                inV[u] = 0;\n                pair<int,int> nte[100]; int nteCnt;\n                int nP[100];\n                long long ncost;\n                if (evalFull(inV, ncost, nte, nteCnt, nP) && ncost < cost) {\n                    cost = ncost;\n                    teCnt = nteCnt;\n                    memcpy(te, nte, sizeof(pair<int,int>) * teCnt);\n                    memcpy(P, nP, sizeof(int) * N);\n                    improved = true;\n                    break;\n                }\n                inV[u] = 1;\n            }\n            if (improved) continue;\n        }\n\n        // --- try add a neighbour ---\n        bool seen[100] = {false};\n        int cand[100], candCnt = 0;\n        for (int i = 0; i < N; ++i) if (inV[i]) {\n            for (auto& [to, id] : adj[i]) {\n                if (!inV[to] && !seen[to]) {\n                    seen[to] = true;\n                    cand[candCnt++] = to;\n                }\n            }\n        }\n\n        if (candCnt > 0) {\n            shuffle(cand, cand + candCnt, rng);\n            bool improved = false;\n            for (int idx = 0; idx < candCnt; ++idx) {\n                int v = cand[idx];\n                inV[v] = 1;\n                pair<int,int> nte[100]; int nteCnt;\n                int nP[100];\n                long long ncost;\n                if (evalFull(inV, ncost, nte, nteCnt, nP) && ncost < cost) {\n                    cost = ncost;\n                    teCnt = nteCnt;\n                    memcpy(te, nte, sizeof(pair<int,int>) * teCnt);\n                    memcpy(P, nP, sizeof(int) * N);\n                    improved = true;\n                    break;\n                }\n                inV[v] = 0;\n            }\n            if (improved) continue;\n        }\n\n        break; // local minimum\n    }\n}\n\n// ---------- random connected starting state ----------\nvoid randomState(char inV[100], mt19937& rng) {\n    for (int i = 0; i < N; ++i) inV[i] = 1;\n    uniform_int_distribution<int> dist_step(1, N / 2);\n    int steps = dist_step(rng);\n    for (int s = 0; s < steps; ++s) {\n        pair<int,int> te[100]; int teCnt;\n        if (mst(inV, te, teCnt) >= INF) break;\n        int deg[100] = {0};\n        for (int i = 0; i < teCnt; ++i) {\n            ++deg[te[i].first];\n            ++deg[te[i].second];\n        }\n        int leaves[100], leafCnt = 0;\n        for (int i = 1; i < N; ++i)\n            if (inV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n        if (leafCnt == 0) break;\n        uniform_int_distribution<int> d(0, leafCnt - 1);\n        inV[leaves[d(rng)]] = 0;\n    }\n}\n\n// ============================================================\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto time_start = chrono::steady_clock::now();\n    const double TL = 1.80;\n\n    cin >> N >> M >> K;\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    memset(edgeIdMat, -1, sizeof(edgeIdMat));\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n        edgeIdMat[u][v] = edgeIdMat[v][u] = j;\n    }\n    memcpy(esort, edges, sizeof(Edge) * M);\n    sort(esort, esort + M, [](const Edge& a, const Edge& b){ return a.w < b.w; });\n\n    for (int k = 0; k < K; ++k) {\n        long long a, b;\n        cin >> a >> b;\n        for (int i = 0; i < N; ++i) {\n            long long dx = xs[i] - a;\n            long long dy = ys[i] - b;\n            long long sq = dx*dx + dy*dy;\n            int d = (int)ceil(sqrt((double)sq));\n            while (1LL*d*d < sq) ++d;\n            while (d > 0 && 1LL*(d-1)*(d-1) >= sq) --d;\n            need[k][i] = d;\n        }\n    }\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    char best_inV[100];\n    pair<int,int> best_te[100];\n    int best_teCnt = 0;\n    int best_P[100];\n    long long best_cost = INF;\n\n    char inV[100];\n    pair<int,int> te[100];\n    int teCnt;\n    int P[100];\n    long long cost;\n\n    // 1) start from all vertices\n    for (int i = 0; i < N; ++i) inV[i] = 1;\n    if (evalFull(inV, cost, te, teCnt, P)) {\n        descent(inV, cost, te, teCnt, P, rng);\n        if (cost < best_cost) {\n            best_cost = cost;\n            memcpy(best_inV, inV, sizeof(char) * N);\n            best_teCnt = teCnt;\n            memcpy(best_te, te, sizeof(pair<int,int>) * teCnt);\n            memcpy(best_P, P, sizeof(int) * N);\n        }\n    }\n\n    // 2) random restarts\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - time_start).count();\n        if (elapsed > TL) break;\n\n        randomState(inV, rng);\n        if (!evalFull(inV, cost, te, teCnt, P)) continue;\n        descent(inV, cost, te, teCnt, P, rng);\n        if (cost < best_cost) {\n            best_cost = cost;\n            memcpy(best_inV, inV, sizeof(char) * N);\n            best_teCnt = teCnt;\n            memcpy(best_te, te, sizeof(pair<int,int>) * teCnt);\n            memcpy(best_P, P, sizeof(int) * N);\n        }\n    }\n\n    // ---------- output ----------\n    int Pout[100] = {0};\n    for (int i = 0; i < N; ++i)\n        if (best_inV[i]) Pout[i] = best_P[i];\n\n    int Bout[300] = {0};\n    for (int i = 0; i < best_teCnt; ++i) {\n        int u = best_te[i].first;\n        int v = best_te[i].second;\n        Bout[edgeIdMat[u][v]] = 1;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << Pout[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << Bout[j];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    int x1, y1, x2, y2;\n};\n\nstruct Solver {\n    static constexpr int N = 30;\n    static constexpr int TOTAL = N * (N + 1) / 2;   // 465\n\n    vector<int> init_val;\n    mt19937 rng;\n\n    Solver() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    static int ID(int x, int y) { return x * (x + 1) / 2 + y; }\n\n    // mode: 0=lr, 1=rl, 2=desc value, 3=asc value,\n    //       4=desc excess, 5=violations first, 6=random\n    vector<Operation> trial(const vector<int>& start_val, int mode, int seed = 0) {\n        vector<int> val = start_val;\n        vector<Operation> ops;\n        ops.reserve(5000);\n\n        mt19937 local_rng(seed);\n\n        for (int x = N - 2; x >= 0; --x) {\n            vector<int> ys(x + 1);\n            iota(ys.begin(), ys.end(), 0);\n\n            if (mode == 1) {\n                reverse(ys.begin(), ys.end());\n            } else if (mode == 2) {\n                sort(ys.begin(), ys.end(),\n                     [&](int a, int b) { return val[ID(x, a)] > val[ID(x, b)]; });\n            } else if (mode == 3) {\n                sort(ys.begin(), ys.end(),\n                     [&](int a, int b) { return val[ID(x, a)] < val[ID(x, b)]; });\n            } else if (mode == 4) {\n                sort(ys.begin(), ys.end(), [&](int a, int b) {\n                    int da = val[ID(x, a)] - min(val[ID(x + 1, a)], val[ID(x + 1, a + 1)]);\n                    int db = val[ID(x, b)] - min(val[ID(x + 1, b)], val[ID(x + 1, b + 1)]);\n                    if (da != db) return da > db;\n                    return val[ID(x, a)] > val[ID(x, b)];\n                });\n            } else if (mode == 5) {\n                sort(ys.begin(), ys.end(), [&](int a, int b) {\n                    int va = val[ID(x, a)];\n                    int vb = val[ID(x, b)];\n                    bool ia = va > min(val[ID(x + 1, a)], val[ID(x + 1, a + 1)]);\n                    bool ib = vb > min(val[ID(x + 1, b)], val[ID(x + 1, b + 1)]);\n                    if (ia != ib) return ia > ib;\n                    int da = va - min(val[ID(x + 1, a)], val[ID(x + 1, a + 1)]);\n                    int db = vb - min(val[ID(x + 1, b)], val[ID(x + 1, b + 1)]);\n                    if (da != db) return da > db;\n                    return va > vb;\n                });\n            } else if (mode == 6) {\n                shuffle(ys.begin(), ys.end(), local_rng);\n            }\n\n            for (int y : ys) {\n                int cx = x, cy = y;\n                while (true) {\n                    if (cx == N - 1) break;\n                    int c1_id = ID(cx + 1, cy);\n                    int c2_id = ID(cx + 1, cy + 1);\n                    int c1_val = val[c1_id];\n                    int c2_val = val[c2_id];\n                    int best_id = (c1_val < c2_val) ? c1_id : c2_id;\n                    int cur_id = ID(cx, cy);\n                    if (val[cur_id] > val[best_id]) {\n                        int nx = cx + 1;\n                        int ny = (best_id == c1_id) ? cy : cy + 1;\n                        ops.push_back({cx, cy, nx, ny});\n                        swap(val[cur_id], val[best_id]);\n                        cx = nx;\n                        cy = ny;\n                    } else {\n                        break;\n                    }\n                }\n            }\n        }\n        return ops;\n    }\n\n    vector<Operation> solve() {\n        vector<Operation> best;\n        bool first = true;\n\n        auto upd = [&](const vector<Operation>& cur) {\n            if (first || cur.size() < best.size()) {\n                best = cur;\n                first = false;\n            }\n        };\n\n        for (int mode = 0; mode <= 5; ++mode) upd(trial(init_val, mode, 0));\n        for (int i = 0; i < 10000; ++i) upd(trial(init_val, 6, i));\n\n        return best;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 30;\n    constexpr int TOTAL = N * (N + 1) / 2;\n\n    Solver solver;\n    solver.init_val.resize(TOTAL);\n\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            solver.init_val[Solver::ID(x, y)] = v;\n        }\n    }\n\n    auto ops = solver.solve();\n    cout << ops.size() << '\\n';\n    for (const auto& op : ops) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << '\\n';\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int D, N;\n    if (!(cin >> D >> N)) return 0;\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n\n    vector<vector<bool>> obstacle(D, vector<bool>(D, false));\n    for (int k = 0; k < N; ++k) {\n        int r, c; cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    const int si = 0;\n    const int sj = (D - 1) / 2;               // entrance\n\n    /*--- BFS distances from entrance (original graph) ---*/\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n    dist[si][sj] = 0;\n    q.push({si, sj});\n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obstacle[ni][nj]) continue;\n            if (dist[ni][nj] != -1) continue;\n            dist[ni][nj] = dist[i][j] + 1;\n            q.push({ni, nj});\n        }\n    }\n\n    /*--- collect storage cells ---*/\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            if (!(i == si && j == sj) && !obstacle[i][j])\n                cells.push_back({i, j});\n\n    const int M = (int)cells.size();\n\n    auto is_traversable = [&](int i, int j, const vector<vector<bool>>& filled_arr)->bool {\n        if (i == si && j == sj) return true;\n        if (i < 0 || i >= D || j < 0 || j >= D) return false;\n        if (obstacle[i][j]) return false;\n        return !filled_arr[i][j];\n    };\n\n    auto compute_degree = [&](int i, int j, const vector<vector<bool>>& filled_arr)->int {\n        int deg = 0;\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obstacle[ni][nj]) continue;\n            if (ni == si && nj == sj) {\n                ++deg;\n            } else if (!filled_arr[ni][nj]) {\n                ++deg;\n            }\n        }\n        return deg;\n    };\n\n    auto find_safe = [&](const vector<vector<bool>>& filled_arr)->vector<pair<int,int>> {\n        bool vis[9][9] = {};\n        bool ap[9][9] = {};\n        int disc[9][9] = {};\n        int low[9][9] = {};\n        int timer = 0;\n        function<void(int,int,int,int)> dfs = [&](int i, int j, int pi, int pj) {\n            vis[i][j] = true;\n            disc[i][j] = low[i][j] = ++timer;\n            int child_cnt = 0;\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (!is_traversable(ni, nj, filled_arr)) continue;\n                if (ni == pi && nj == pj) continue;\n                if (!vis[ni][nj]) {\n                    ++child_cnt;\n                    dfs(ni, nj, i, j);\n                    low[i][j] = min(low[i][j], low[ni][nj]);\n                    if (pi != -1 && low[ni][nj] >= disc[i][j]) ap[i][j] = true;\n                } else {\n                    low[i][j] = min(low[i][j], disc[ni][nj]);\n                }\n            }\n            if (pi == -1 && child_cnt > 1) ap[i][j] = true;\n        };\n        dfs(si, sj, -1, -1);\n        vector<pair<int,int>> safe;\n        for (auto &c : cells) {\n            int i = c.first, j = c.second;\n            if (filled_arr[i][j]) continue;\n            if (vis[i][j] && !ap[i][j]) safe.push_back(c);\n        }\n        return safe;\n    };\n\n    /*--- precompute elimination order P (farthest safe first) ---*/\n    vector<vector<bool>> p_filled(D, vector<bool>(D, false));\n    vector<pair<int,int>> P;\n    P.reserve(M);\n    for (int step = 0; step < M; ++step) {\n        vector<pair<int,int>> safe = find_safe(p_filled);\n        // emergency fallback (should never trigger)\n        if (safe.empty()) {\n            for (auto &c : cells) if (!p_filled[c.first][c.second]) safe.push_back(c);\n        }\n        int bi = -1, bj = -1;\n        int bdist = -1, bdeg = 100;\n        for (auto [i, j] : safe) {\n            int d = dist[i][j];\n            int deg = compute_degree(i, j, p_filled);\n            if (d > bdist || (d == bdist && deg < bdeg) ||\n                (d == bdist && deg == bdeg && i < bi) ||\n                (d == bdist && deg == bdeg && i == bi && j < bj)) {\n                bdist = d; bdeg = deg; bi = i; bj = j;\n            }\n        }\n        p_filled[bi][bj] = true;\n        P.push_back({bi, bj});\n    }\n\n    vector<vector<int>> pos(D, vector<int>(D, -1));\n    vector<vector<int>> ideal(D, vector<int>(D, -1));\n    for (int k = 0; k < M; ++k) {\n        auto [i, j] = P[k];\n        pos[i][j] = k;\n        ideal[i][j] = M - 1 - k;\n    }\n\n    /*--- online placement ---*/\n    vector<vector<bool>> filled(D, vector<bool>(D, false));\n    vector<vector<int>>  label_at(D, vector<int>(D, -1));\n    vector<bool> placed_label(M, false);\n\n    for (int step = 0; step < M; ++step) {\n        int t; cin >> t;\n        placed_label[t] = true;\n\n        vector<pair<int,int>> safe = find_safe(filled);\n        if (safe.empty()) { // should not happen\n            for (auto &c : cells) if (!filled[c.first][c.second]) safe.push_back(c);\n        }\n\n        int best_i = -1, best_j = -1;\n        int best_cat = -1, best_sub = INT_MAX, best_deg = INT_MAX;\n\n        for (auto [i, j] : safe) {\n            int ide = ideal[i][j];\n            int cat, sub;\n            if (ide == t) {\n                cat = 3;          // perfect\n                sub = 0;\n            } else if (ide > t) {\n                cat = 2;          // suitable: deep enough\n                sub = ide - t;    // want closest ideal above t\n            } else if (placed_label[ide]) {\n                cat = 1;          // free: its owner already placed elsewhere\n                sub = t - ide;    // want closest to t\n            } else {\n                cat = 0;          // reserved: owner still unseen\n                sub = t - ide;    // want closest to t (largest ide)\n            }\n            int deg = compute_degree(i, j, filled);\n            if (cat > best_cat ||\n                (cat == best_cat && sub < best_sub) ||\n                (cat == best_cat && sub == best_sub && deg < best_deg)) {\n                best_cat = cat;\n                best_sub = sub;\n                best_deg = deg;\n                best_i = i;\n                best_j = j;\n            }\n        }\n\n        filled[best_i][best_j] = true;\n        label_at[best_i][best_j] = t;\n        cout << best_i << ' ' << best_j << '\\n' << flush;\n    }\n\n    /*--- greedy removal (optimal for fixed assignment) ---*/\n    vector<vector<bool>> is_empty(D, vector<bool>(D, false));\n    is_empty[si][sj] = true;\n\n    using State = tuple<int,int,int>; // (label, i, j)\n    priority_queue<State, vector<State>, greater<State>> pq;\n    bool in_pq[9][9] = {};\n\n    auto add_nei = [&](int i, int j) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obstacle[ni][nj]) continue;\n            if (is_empty[ni][nj]) continue;\n            if (in_pq[ni][nj]) continue;\n            pq.emplace(label_at[ni][nj], ni, nj);\n            in_pq[ni][nj] = true;\n        }\n    };\n    add_nei(si, sj);\n\n    vector<pair<int,int>> out_order;\n    while (!pq.empty()) {\n        auto [lab, i, j] = pq.top(); pq.pop();\n        out_order.emplace_back(i, j);\n        is_empty[i][j] = true;\n        add_nei(i, j);\n    }\n\n    for (auto &p : out_order) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    cout << flush;\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nint n, m;\nint orig_g[50][50];\nint need[101][101];\nbool isB[101];\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\ninline bool inside(int i, int j) { return i >= 0 && i < n && j >= 0 && j < n; }\n\nstruct State {\n    int g[50][50];\n    int sz[101];\n    int adjCnt[101][101];\n    int vis[50][50];\n    int visToken;\n    mt19937 rng;\n\n    State(unsigned seed) : visToken(1), rng(seed) {\n        memset(vis, 0, sizeof(vis));\n    }\n\n    void recompute() {\n        memset(sz, 0, sizeof(sz));\n        memset(adjCnt, 0, sizeof(adjCnt));\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                int c = g[i][j];\n                ++sz[c];\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    if (inside(ni, nj)) {\n                        int d = g[ni][nj];\n                        if (c != d) ++adjCnt[c][d];\n                    } else {\n                        ++adjCnt[c][0];\n                    }\n                }\n            }\n        }\n    }\n\n    void init() {\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                g[i][j] = orig_g[i][j];\n        recompute();\n    }\n\n    void load(const vector<vector<int>> &gr) {\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                g[i][j] = gr[i][j];\n        recompute();\n    }\n\n    vector<vector<int>> get_grid() const {\n        vector<vector<int>> res(n, vector<int>(n));\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                res[i][j] = g[i][j];\n        return res;\n    }\n\n    // Quick connectivity test for color c after removing cell (i,j).\n    // same_c = number of 4-neighbors of (i,j) that already have color c.\n    bool connectedWithout(int i, int j, int c, int szc, int same_c) {\n        if (szc <= 1) return false;\n        if (szc == 2) return true;          // one other cell remains\n        if (same_c == 0) return false;      // should never happen for a valid state\n        if (same_c == 1) return true;       // leaf: removing it cannot disconnect the rest\n\n        int si = -1, sj = -1;\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (inside(ni, nj) && g[ni][nj] == c) {\n                si = ni; sj = nj; break;\n            }\n        }\n        if (si == -1) return false;\n\n        int cnt = 1;\n        queue<pair<int, int>> q;\n        q.emplace(si, sj);\n        vis[si][sj] = visToken;\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + di[dir], ny = y + dj[dir];\n                if (!inside(nx, ny)) continue;\n                if (g[nx][ny] != c) continue;\n                if (nx == i && ny == j) continue;\n                if (vis[nx][ny] == visToken) continue;\n                vis[nx][ny] = visToken;\n                ++cnt;\n                if (cnt == szc - 1) {       // early stop\n                    ++visToken;\n                    return true;\n                }\n                q.emplace(nx, ny);\n            }\n        }\n        ++visToken;\n        return cnt == szc - 1;\n    }\n\n    void applyRecolor(int i, int j, int d) {\n        int c = g[i][j];\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            int e = inside(ni, nj) ? g[ni][nj] : 0;\n            if (e != c) {\n                --adjCnt[c][e];\n                --adjCnt[e][c];\n            }\n            if (e != d) {\n                ++adjCnt[d][e];\n                ++adjCnt[e][d];\n            }\n        }\n        g[i][j] = d;\n        --sz[c];\n        ++sz[d];\n    }\n\n    int solve(int heuristic) {\n        for (int iter = 0; iter < 500; ++iter) {\n            bool changed = false;\n\n            // Build list of non-zero cells\n            vector<pair<int, int>> cells;\n            cells.reserve(2500);\n            for (int i = 0; i < n; ++i)\n                for (int j = 0; j < n; ++j)\n                    if (g[i][j] > 0) cells.emplace_back(i, j);\n\n            // Order cells according to heuristic\n            if (heuristic & 1) {\n                // Bucket by number of 0-neighbors (including outside), higher first\n                vector<pair<int, int>> bucket[5];\n                for (auto [i, j] : cells) {\n                    int key = 0;\n                    for (int dir = 0; dir < 4; ++dir) {\n                        int ni = i + di[dir], nj = j + dj[dir];\n                        if (!inside(ni, nj) || g[ni][nj] == 0) ++key;\n                    }\n                    bucket[key].push_back({i, j});\n                }\n                cells.clear();\n                for (int k = 4; k >= 0; --k) {\n                    shuffle(bucket[k].begin(), bucket[k].end(), rng);\n                    cells.insert(cells.end(), bucket[k].begin(), bucket[k].end());\n                }\n            } else {\n                shuffle(cells.begin(), cells.end(), rng);\n            }\n\n            for (auto [i, j] : cells) {\n                int c = g[i][j];\n                if (c == 0) continue;\n                if (sz[c] <= 1) continue;\n\n                int neigh[4];\n                int same_c = 0;\n                int contrib_c[101] = {};\n                bool hasZero = false;\n                bool isBorder = (i == 0 || i == n - 1 || j == 0 || j == n - 1);\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    int e = inside(ni, nj) ? g[ni][nj] : 0;\n                    neigh[dir] = e;\n                    if (e == c) ++same_c;\n                    else ++contrib_c[e];\n                    if (e == 0) hasZero = true;\n                }\n\n                if (!connectedWithout(i, j, c, sz[c], same_c)) continue;\n\n                // ----- try delete -----\n                if (isB[c] && (isBorder || hasZero)) {\n                    bool ok = true;\n                    for (int e = 1; e <= m; ++e)\n                        if (contrib_c[e] && !isB[e]) { ok = false; break; }\n                    if (ok) {\n                        for (int e = 0; e <= m; ++e) {\n                            if (contrib_c[e] == 0) continue;\n                            if (!need[c][e]) continue;\n                            int rem = adjCnt[c][e] - contrib_c[e];\n                            if (e == 0) rem += same_c; // c-neighbors become adjacent to 0\n                            if (rem <= 0) { ok = false; break; }\n                        }\n                    }\n                    if (ok) {\n                        applyRecolor(i, j, 0);\n                        changed = true;\n                        continue;\n                    }\n                }\n\n                // ----- try recolor to a neighbor color -----\n                int bestD = -1;\n                int bestScore = INT_MIN;\n                for (int dir = 0; dir < 4; ++dir) {\n                    int d = neigh[dir];\n                    if (d == 0 || d == c) continue;\n\n                    // Border cells are adjacent to the outside (color 0)\n                    if (isBorder && !need[d][0]) continue;\n\n                    // d must be allowed to touch all current neighbors\n                    bool ok = true;\n                    for (int k = 0; k < 4; ++k) {\n                        int e = neigh[k];\n                        if (e == d) continue;\n                        if (!need[d][e]) { ok = false; break; }\n                    }\n                    if (!ok) continue;\n\n                    // old color c must keep all required adjacencies\n                    ok = true;\n                    for (int e = 0; e <= m; ++e) {\n                        if (contrib_c[e] == 0) continue;\n                        if (!need[c][e]) continue;\n                        int rem = adjCnt[c][e] - contrib_c[e];\n                        if (e == d) rem += same_c; // c-neighbors are now adjacent to d\n                        if (rem <= 0) { ok = false; break; }\n                    }\n                    if (!ok) continue;\n\n                    int score;\n                    switch (heuristic % 6) {\n                        case 0: score = (isB[d] ? 10000 : 0) - sz[d] * 10; break;\n                        case 1: score = (isB[d] ? 10000 : 0) + sz[d] * 10; break;\n                        case 2: score = (isB[d] ? 10000 : 0) + adjCnt[d][0] * 10; break;\n                        case 3: score = -sz[d] * 10; break;\n                        case 4: score = (isB[d] ? 10000 : 0) - sz[d] * 10 + adjCnt[d][0] * 5; break;\n                        default: score = 0; break;\n                    }\n                    score += int(rng() & 0xF); // small random tie-break\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestD = d;\n                    }\n                }\n\n                if (bestD != -1) {\n                    applyRecolor(i, j, bestD);\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n        return sz[0];\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig_g[i][j];\n\n    memset(need, 0, sizeof(need));\n    memset(isB, 0, sizeof(isB));\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = orig_g[i][j];\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (inside(ni, nj)) {\n                    int d = orig_g[ni][nj];\n                    if (c != d) need[c][d] = 1;\n                } else {\n                    need[c][0] = 1;\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) isB[c] = need[c][0];\n    for (int c = 1; c <= m; ++c) need[0][c] = isB[c];\n\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int best_zero = -1;\n    vector<vector<int>> best_grid;\n\n    // One deterministic trial\n    {\n        State s(1234567u);\n        s.init();\n        int z = s.solve(0);\n        if (z > best_zero) {\n            best_zero = z;\n            best_grid = s.get_grid();\n        }\n    }\n\n    // Keep restarting until we run out of time\n    for (int trial = 0; ; ++trial) {\n        if (elapsed() > 1.85) break;\n\n        int h = trial % 6;\n        State s((unsigned)trial + 1000u);\n        s.init();\n        int z = s.solve(h);\n        if (z > best_zero) {\n            best_zero = z;\n            best_grid = s.get_grid();\n        }\n\n        // Occasionally try to improve the current best map\n        if (trial % 3 == 0 && best_zero > 0) {\n            State s2((unsigned)trial + 2000000u);\n            s2.load(best_grid);\n            int z2 = s2.solve((h + 1) % 6);\n            if (z2 > best_zero) {\n                best_zero = z2;\n                best_grid = s2.get_grid();\n            }\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p;\n    DSU(int n = 0) { init(n); }\n    void init(int n) { p.resize(n); iota(p.begin(), p.end(), 0); }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a != b) p[a] = b;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    vector<bitset<128>> gt(N);\n    vector<vector<char>> direct_done(N, vector<char>(N, 0));\n    DSU dsu(N);\n    \n    vector<int> assign(N);\n    for (int i = 0; i < N; ++i) assign[i] = i % D;\n    \n    const double LAMBDA = 1e-5;\n    double M_cap = 100000.0 * N / D;\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0 / i;\n    vector<long long> est(N, 100000);\n    \n    auto recompute_est = [&]() {\n        vector<int> num_gt(N, 0);\n        for (int i = 0; i < N; ++i) num_gt[i] = (int)gt[i].count();\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (num_gt[a] != num_gt[b]) return num_gt[a] > num_gt[b];\n            return a < b;\n        });\n        for (int idx = 0; idx < N; ++idx) {\n            int i = ord[idx];\n            double val = (H[N] - H[idx]) / LAMBDA;\n            if (val > M_cap) val = M_cap;\n            est[i] = max(1LL, (long long)llround(val));\n        }\n    };\n    \n    auto improve_partition = [&](vector<int>& as) {\n        vector<long long> gsum(D, 0);\n        for (int i = 0; i < N; ++i) gsum[as[i]] += est[i];\n        vector<vector<int>> groups(D);\n        for (int i = 0; i < N; ++i) groups[as[i]].push_back(i);\n        \n        bool improved = true;\n        while (improved) {\n            improved = false;\n            long long bestDelta = 0;\n            int best_type = 0;\n            int best_i = -1, best_j = -1, best_to = -1;\n            \n            for (int i = 0; i < N; ++i) {\n                int a = as[i];\n                for (int b = 0; b < D; ++b) {\n                    if (a == b) continue;\n                    long long sa = gsum[a], sb = gsum[b], wi = est[i];\n                    long long nsa = sa - wi, nsb = sb + wi;\n                    long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        best_type = 2;\n                        best_i = i; best_to = b;\n                    }\n                }\n            }\n            \n            for (int i = 0; i < N; ++i) {\n                int a = as[i];\n                for (int j = i + 1; j < N; ++j) {\n                    int b = as[j];\n                    if (a == b) continue;\n                    long long sa = gsum[a], sb = gsum[b];\n                    long long wi = est[i], wj = est[j];\n                    long long nsa = sa - wi + wj;\n                    long long nsb = sb - wj + wi;\n                    long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        best_type = 1;\n                        best_i = i; best_j = j;\n                    }\n                }\n            }\n            \n            if (bestDelta < 0) {\n                improved = true;\n                if (best_type == 2) {\n                    int i = best_i, a = as[i], b = best_to;\n                    as[i] = b;\n                    gsum[a] -= est[i];\n                    gsum[b] += est[i];\n                    auto& ga = groups[a];\n                    for (size_t k = 0; k < ga.size(); ++k) if (ga[k] == i) { ga[k] = ga.back(); ga.pop_back(); break; }\n                    groups[b].push_back(i);\n                } else {\n                    int i = best_i, j = best_j;\n                    int a = as[i], b = as[j];\n                    as[i] = b; as[j] = a;\n                    gsum[a] = gsum[a] - est[i] + est[j];\n                    gsum[b] = gsum[b] - est[j] + est[i];\n                    for (auto& x : groups[a]) if (x == i) { x = j; break; }\n                    for (auto& x : groups[b]) if (x == j) { x = i; break; }\n                }\n            }\n        }\n    };\n    \n    for (int q = 0; q < Q; ++q) {\n        if (q % 50 == 0 || q >= Q - 200) {\n            recompute_est();\n            improve_partition(assign);\n        }\n        \n        vector<int> direct_deg(N, 0);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (direct_done[i][j]) direct_deg[i]++;\n        \n        vector<int> num_gt(N);\n        for (int i = 0; i < N; ++i) num_gt[i] = (int)gt[i].count();\n        \n        int best_i = -1, best_j = -1;\n        int best_val = INT_MAX;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (direct_done[i][j]) continue;\n                if (dsu.find(i) == dsu.find(j)) continue;\n                if (gt[i].test(j) || gt[j].test(i)) continue;\n                \n                int diff = abs(num_gt[i] - num_gt[j]);\n                int deg = direct_deg[i] + direct_deg[j];\n                int cross = (assign[i] != assign[j]) ? -100 : 0;\n                int val = diff * 10 + deg + cross;\n                if (val < best_val) {\n                    best_val = val;\n                    best_i = i; best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (direct_done[i][j]) continue;\n                    if (dsu.find(i) == dsu.find(j)) continue;\n                    \n                    int diff = abs(num_gt[i] - num_gt[j]);\n                    int deg = direct_deg[i] + direct_deg[j];\n                    int cross = (assign[i] != assign[j]) ? -100 : 0;\n                    int val = diff * 10 + deg + cross;\n                    if (val < best_val) {\n                        best_val = val;\n                        best_i = i; best_j = j;\n                    }\n                }\n            }\n        }\n        \n        if (best_i == -1) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (assign[i] != assign[j]) {\n                        best_i = i; best_j = j;\n                        break;\n                    }\n                }\n                if (best_i != -1) break;\n            }\n        }\n        \n        if (best_i == -1) {\n            best_i = 0; best_j = 1;\n        }\n        \n        cout << \"1 1 \" << best_i << \" \" << best_j << '\\n' << flush;\n        string res;\n        cin >> res;\n        \n        direct_done[best_i][best_j] = direct_done[best_j][best_i] = 1;\n        if (res == \">\") {\n            int u = best_i, v = best_j;\n            gt[u].set(v);\n            auto old_u = gt[u];\n            gt[u] |= gt[v];\n            if (gt[u] != old_u) {\n                for (int i = 0; i < N; ++i) {\n                    if (gt[i].test(u)) gt[i] |= gt[u];\n                }\n            }\n        } else if (res == \"<\") {\n            int u = best_j, v = best_i;\n            gt[u].set(v);\n            auto old_u = gt[u];\n            gt[u] |= gt[v];\n            if (gt[u] != old_u) {\n                for (int i = 0; i < N; ++i) {\n                    if (gt[i].test(u)) gt[i] |= gt[u];\n                }\n            }\n        } else {\n            dsu.unite(best_i, best_j);\n        }\n    }\n    \n    recompute_est();\n    improve_partition(assign);\n    \n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    vector<long long> gsum(D, 0);\n    for (int i = 0; i < N; ++i) gsum[assign[i]] += est[i];\n    auto cur_obj = [&]() {\n        long long s = 0;\n        for (long long x : gsum) s += x * x;\n        return s;\n    };\n    \n    long long bestObj = cur_obj();\n    vector<int> bestAssign = assign;\n    vector<vector<int>> groups(D);\n    for (int i = 0; i < N; ++i) groups[assign[i]].push_back(i);\n    \n    double T = 1e12;\n    for (int iter = 0; iter < 200000; ++iter) {\n        T *= 0.99997;\n        int type = uniform_int_distribution<int>(0, 1)(rng);\n        int a = uniform_int_distribution<int>(0, D - 1)(rng);\n        int b = uniform_int_distribution<int>(0, D - 1)(rng);\n        if (a == b) continue;\n        \n        if (type == 0) {\n            if (groups[a].empty()) continue;\n            int idx = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n            int i = groups[a][idx];\n            long long sa = gsum[a], sb = gsum[b];\n            long long wi = est[i];\n            long long nsa = sa - wi, nsb = sb + wi;\n            long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n            bool accept = delta < 0;\n            if (!accept) {\n                if (uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) accept = true;\n            }\n            if (accept) {\n                assign[i] = b;\n                gsum[a] = nsa; gsum[b] = nsb;\n                groups[a][idx] = groups[a].back(); groups[a].pop_back();\n                groups[b].push_back(i);\n                long long obj = cur_obj();\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestAssign = assign;\n                }\n            }\n        } else {\n            if (groups[a].empty() || groups[b].empty()) continue;\n            int idx1 = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, (int)groups[b].size() - 1)(rng);\n            int i = groups[a][idx1], j = groups[b][idx2];\n            long long sa = gsum[a], sb = gsum[b];\n            long long wi = est[i], wj = est[j];\n            long long nsa = sa - wi + wj, nsb = sb - wj + wi;\n            long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n            bool accept = delta < 0;\n            if (!accept) {\n                if (uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) accept = true;\n            }\n            if (accept) {\n                assign[i] = b; assign[j] = a;\n                gsum[a] = nsa; gsum[b] = nsb;\n                swap(groups[a][idx1], groups[b][idx2]);\n                long long obj = cur_obj();\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestAssign = assign;\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestAssign[i];\n    }\n    cout << endl;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SimResult {\n    long long energy;\n    vector<pair<int,int>> ops;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int n, m;\n    if (!(cin >> n >> m)) return 0;\n    const int h = n / m;\n    vector<vector<int>> init(m, vector<int>(h));\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < h; ++j)\n            cin >> init[i][j];\n    \n    const int INF = 1e9;\n    \n    auto simulate = [&](int variant) -> SimResult {\n        vector<vector<int>> st = init;\n        vector<int> pos(n + 1, -1);\n        for (int i = 0; i < m; ++i)\n            for (int x : st[i]) pos[x] = i;\n        \n        vector<int> mn(m, INF);\n        for (int i = 0; i < m; ++i)\n            if (!st[i].empty())\n                mn[i] = *min_element(st[i].begin(), st[i].end());\n        \n        long long energy = 0;\n        vector<pair<int,int>> ops;\n        ops.reserve(5000);\n        \n        auto recompute = [&](int idx) {\n            if (st[idx].empty()) mn[idx] = INF;\n            else {\n                mn[idx] = INF;\n                for (int x : st[idx]) mn[idx] = min(mn[idx], x);\n            }\n        };\n        \n        for (int v = 1; v <= n; ) {\n            int s = pos[v];\n            // free removal if v is on top\n            if (!st[s].empty() && st[s].back() == v) {\n                ops.emplace_back(v, 0);\n                st[s].pop_back();\n                pos[v] = -1;\n                recompute(s);\n                ++v;\n                continue;\n            }\n            \n            // v is buried: locate it\n            int hpos = 0;\n            while (hpos < (int)st[s].size() && st[s][hpos] != v) ++hpos;\n            int k = (int)st[s].size() - hpos - 1;           // number of boxes above v\n            vector<int> T(st[s].begin() + hpos + 1, st[s].end());\n            int mxT = *max_element(T.begin(), T.end());\n            int minT = *min_element(T.begin(), T.end());\n            int w = T[0];                                    // box directly above v\n            \n            int best_d = -1;\n            tuple<int,int,int,int> best_score;\n            bool first = true;\n            \n            for (int d = 0; d < m; ++d) if (d != s) {\n                tuple<int,int,int,int> sc;\n                bool empty = st[d].empty();\n                bool safe = !empty && mn[d] >= mxT;\n                \n                if (empty) {\n                    if (variant == 2) sc = make_tuple(0, 0, 0, 0);   // prefer empty\n                    else               sc = make_tuple(1, 0, 0, 0);   // empty second\n                } else if (safe) {\n                    if (variant == 0) {               // original: best\u2011fit by top\n                        sc = make_tuple(0, st[d].back(), 0, 0);\n                    } else if (variant == 5) {        // prefer smallest host size\n                        sc = make_tuple(0, (int)st[d].size(), mn[d], 0);\n                    } else {                          // best\u2011fit by minimum\n                        sc = make_tuple(0, mn[d], 0, 0);\n                    }\n                } else {\n                    int inv = 0;\n                    int blockers = 0;\n                    for (int t : T) {\n                        if (t > mn[d]) ++blockers;\n                        for (int x : st[d])\n                            if (t > x) ++inv;\n                    }\n                    if (variant == 3) {               // blockers first\n                        sc = make_tuple(2, blockers, -mn[d], 0);\n                    } else if (variant == 4) {        // blockers, then inversions\n                        sc = make_tuple(2, blockers, inv, -mn[d]);\n                    } else {                          // original unsafe metric\n                        sc = make_tuple(2, inv, -mn[d], 0);\n                    }\n                }\n                \n                if (first || sc < best_score) {\n                    best_score = sc;\n                    best_d = d;\n                    first = false;\n                }\n            }\n            \n            // execute operation 1\n            ops.emplace_back(w, best_d + 1);\n            energy += k + 1;\n            for (int x : T) {\n                st[best_d].push_back(x);\n                pos[x] = best_d;\n            }\n            mn[best_d] = min(mn[best_d], minT);\n            st[s].resize(hpos + 1);          // keep v on top of s\n            \n            // execute operation 2\n            ops.emplace_back(v, 0);\n            st[s].pop_back();\n            pos[v] = -1;\n            recompute(s);\n            ++v;\n        }\n        return {energy, ops};\n    };\n    \n    long long best_energy = (1LL << 60);\n    vector<pair<int,int>> best_ops;\n    \n    for (int var = 0; var < 6; ++var) {\n        SimResult res = simulate(var);\n        if (res.ops.size() <= 5000 && res.energy < best_energy) {\n            best_energy = res.energy;\n            best_ops = std::move(res.ops);\n        }\n    }\n    \n    for (auto &p : best_ops)\n        cout << p.first << ' ' << p.second << '\\n';\n    \n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n};\n\nstruct HeapItem {\n    double score;\n    int eid;\n    long long ku, kv;\n    bool operator<(const HeapItem& other) const {\n        return score < other.score; // max-heap\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    if(!(cin >> N)) return 0;\n    vector<string> h(N - 1);\n    vector<string> vwall(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> vwall[i];\n    vector<vector<int>> dmat(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> dmat[i][j];\n    \n    const int V = N * N;\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto geti = [&](int v) { return v / N; };\n    auto getj = [&](int v) { return v % N; };\n    \n    vector<int> dval(V);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dval[id(i, j)] = dmat[i][j];\n    \n    // Build graph\n    vector<Edge> edges;\n    vector<vector<pair<int,int>>> adj(V); // (neighbor, edge_id)\n    auto add_edge = [&](int u, int v) {\n        int eid = (int)edges.size();\n        edges.push_back({u, v});\n        adj[u].push_back({v, eid});\n        adj[v].push_back({u, eid});\n    };\n    \n    for (int i = 0; i < N - 1; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] == '0')\n                add_edge(id(i, j), id(i + 1, j));\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N - 1; ++j) {\n            if (vwall[i][j] == '0')\n                add_edge(id(i, j), id(i, j + 1));\n        }\n    }\n    const int E = (int)edges.size();\n    \n    // Spanning tree by BFS\n    vector<int> parent(V, -1);\n    vector<char> vis(V, 0);\n    queue<int> q;\n    vis[0] = 1;\n    q.push(0);\n    vector<char> is_tree_edge(E, 0);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [v, eid] : adj[u]) {\n            if (!vis[v]) {\n                vis[v] = 1;\n                parent[v] = u;\n                is_tree_edge[eid] = 1;\n                q.push(v);\n            }\n        }\n    }\n    \n    // Multiplicity of each undirected edge (number of traversals)\n    // We keep multiplicities even. Tree edges start with 2.\n    vector<int> mult(E, 0);\n    vector<long long> k(V, 0); // visit count = half degree = sum_{e incident} mult[e]/2, but here mult counts traversals. Actually k[v] = sum_{e incident} mult[e] / 2.\n    // To avoid fractions, we define mult[e] as number of traversals (always even), and k[v] = degree/2.\n    for (int eid = 0; eid < E; ++eid) {\n        if (is_tree_edge[eid]) {\n            mult[eid] = 2;\n            k[edges[eid].u]++;\n            k[edges[eid].v]++;\n        }\n    }\n    long long L = 0;\n    for (int i = 0; i < V; ++i) L += k[i];\n    \n    const long long L_MAX = 100000;\n    \n    auto edge_score = [&](int eid) -> double {\n        int u = edges[eid].u;\n        int v = edges[eid].v;\n        return (double)dval[u] / ((double)k[u] * (k[u] + 1.0))\n             + (double)dval[v] / ((double)k[v] * (k[v] + 1.0));\n    };\n    \n    priority_queue<HeapItem> pq;\n    for (int eid = 0; eid < E; ++eid) {\n        double sc = edge_score(eid);\n        pq.push({sc, eid, k[edges[eid].u], k[edges[eid].v]});\n    }\n    \n    while (L + 2 <= L_MAX) {\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int eid = cur.eid;\n            int u = edges[eid].u;\n            int v = edges[eid].v;\n            if (k[u] != cur.ku || k[v] != cur.kv) continue; // stale\n            // apply\n            mult[eid] += 2;\n            k[u]++; k[v]++;\n            L += 2;\n            // push neighbors of u and v\n            for (auto [w, eid2] : adj[u]) {\n                double sc = edge_score(eid2);\n                pq.push({sc, eid2, k[edges[eid2].u], k[edges[eid2].v]});\n            }\n            for (auto [w, eid2] : adj[v]) {\n                double sc = edge_score(eid2);\n                pq.push({sc, eid2, k[edges[eid2].u], k[edges[eid2].v]});\n            }\n            break;\n        }\n        if (pq.empty()) break;\n    }\n    \n    // Helper: get move character between adjacent cells\n    auto move_char = [&](int u, int v) -> char {\n        int i1 = geti(u), j1 = getj(u);\n        int i2 = geti(v), j2 = getj(v);\n        if (i2 == i1 - 1) return 'U';\n        if (i2 == i1 + 1) return 'D';\n        if (j2 == j1 - 1) return 'L';\n        return 'R';\n    };\n    \n    // Build an Eulerian tour on the multigraph.\n    auto build_tour = [&](mt19937& rng, bool use_random) -> vector<int> {\n        vector<int> mcur = mult;\n        vector<int> path;\n        path.reserve((size_t)L + 1);\n        vector<int> stk;\n        stk.reserve((size_t)L + 1);\n        stk.push_back(0);\n        vector<int> last_from(V, -1);\n        vector<int> rr_idx(V, 0);\n        \n        while (!stk.empty()) {\n            int u = stk.back();\n            int total = 0;\n            for (auto [v2, eid2] : adj[u]) total += mcur[eid2];\n            if (total == 0) {\n                path.push_back(u);\n                stk.pop_back();\n                continue;\n            }\n            int picked_eid = -1;\n            int picked_v = -1;\n            if (use_random) {\n                vector<int> cand_eid;\n                vector<int> cand_v;\n                int back_eid = -1, back_v = -1;\n                for (auto [v2, eid2] : adj[u]) {\n                    if (mcur[eid2] == 0) continue;\n                    if (v2 == last_from[u]) {\n                        back_eid = eid2;\n                        back_v = v2;\n                    } else {\n                        cand_eid.push_back(eid2);\n                        cand_v.push_back(v2);\n                    }\n                }\n                if (!cand_eid.empty()) {\n                    int idx = (int)(rng() % cand_eid.size());\n                    picked_eid = cand_eid[idx];\n                    picked_v = cand_v[idx];\n                } else {\n                    picked_eid = back_eid;\n                    picked_v = back_v;\n                }\n            } else {\n                // round-robin, avoid immediate backtrack if possible\n                int deg = (int)adj[u].size();\n                for (int iter = 0; iter < deg; ++iter) {\n                    int idx = (rr_idx[u] + iter) % deg;\n                    int eid2 = adj[u][idx].second;\n                    int v2 = adj[u][idx].first;\n                    if (mcur[eid2] == 0) continue;\n                    if (v2 == last_from[u] && total > mcur[eid2]) continue;\n                    picked_eid = eid2;\n                    picked_v = v2;\n                    rr_idx[u] = (idx + 1) % deg;\n                    break;\n                }\n                if (picked_eid == -1) {\n                    for (int iter = 0; iter < deg; ++iter) {\n                        int idx = (rr_idx[u] + iter) % deg;\n                        int eid2 = adj[u][idx].second;\n                        int v2 = adj[u][idx].first;\n                        if (mcur[eid2] > 0) {\n                            picked_eid = eid2;\n                            picked_v = v2;\n                            rr_idx[u] = (idx + 1) % deg;\n                            break;\n                        }\n                    }\n                }\n            }\n            mcur[picked_eid]--;\n            last_from[picked_v] = u;\n            stk.push_back(picked_v);\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n    \n    auto eval_cost = [&](const vector<int>& path) -> long long {\n        // path[0] = start, path.back() = start, length = L+1\n        int T = (int)path.size() - 1; // number of moves\n        vector<int> first_pos(V, -1);\n        vector<int> last_pos(V, -1);\n        vector<long long> sumsq(V, 0);\n        for (int t = 0; t < T; ++t) {\n            int cell = path[t + 1];\n            if (last_pos[cell] != -1) {\n                int gap = (t + 1) - last_pos[cell];\n                sumsq[cell] += 1LL * gap * gap;\n            } else {\n                first_pos[cell] = t + 1;\n            }\n            last_pos[cell] = t + 1;\n        }\n        long long cost = 0;\n        for (int v = 0; v < V; ++v) {\n            if (first_pos[v] != -1) {\n                int gap = T - last_pos[v] + first_pos[v];\n                sumsq[v] += 1LL * gap * gap;\n                cost += 1LL * dval[v] * sumsq[v];\n            }\n        }\n        return cost;\n    };\n    \n    long long best_cost = LLONG_MAX;\n    string best_route;\n    best_route.reserve((size_t)L);\n    \n    // fallback base DFS traversal of the spanning tree (double walk)\n    {\n        vector<vector<pair<int,char>>> children(V);\n        for (int v = 1; v < V; ++v) {\n            int p = parent[v];\n            // determine direction char from p to v\n            char c = move_char(p, v);\n            children[p].push_back({v, c});\n        }\n        string fallback;\n        function<void(int)> dfs = [&](int u) {\n            for (auto [v, c] : children[u]) {\n                fallback.push_back(c);\n                dfs(v);\n                // opposite direction\n                if (c == 'U') fallback.push_back('D');\n                else if (c == 'D') fallback.push_back('U');\n                else if (c == 'L') fallback.push_back('R');\n                else fallback.push_back('L');\n            }\n        };\n        dfs(0);\n        // ensure it returns to 0 and visits all\n        if ((int)fallback.size() <= 100000) {\n            best_route = fallback;\n            // we could eval it, but we will replace with better ones\n        }\n    }\n    \n    // Try many random seeds and heuristics\n    vector<uint32_t> seeds;\n    for (int s = 0; s < 20; ++s) seeds.push_back((uint32_t)s);\n    seeds.push_back((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n    \n    for (uint32_t seed : seeds) {\n        mt19937 rng(seed);\n        for (int trial = 0; trial < 15; ++trial) {\n            bool use_random = (trial % 3 != 0); // mix random and round-robin\n            auto path = build_tour(rng, use_random);\n            if ((int)path.size() != L + 1) continue;\n            long long c = eval_cost(path);\n            if (c < best_cost) {\n                best_cost = c;\n                best_route.clear();\n                for (int i = 0; i < L; ++i)\n                    best_route.push_back(move_char(path[i], path[i + 1]));\n            }\n        }\n    }\n    \n    cout << best_route << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint start_cell;\nstring targets[200];\nvector<int> pos[26];\nint dist_arr[225][225];\n\nint last_cells[200][225];\nint last_sz[200];\n// cost_tbl[t][k][c * last_sz[t] + e]  : cost to type t[k..4] starting from cell c, ending at e-th cell of t[4]\nvector<int16_t> cost_tbl[200][5];\n\ninline int manhattan(int a, int b) { return dist_arr[a][b]; }\n\n/*--------------- suffix state (last up to 5 chars) ---------------*/\nstruct State {\n    char s[5];\n    uint8_t len;\n    State() : len(0) {}\n    int overlap(const string& t) const {\n        int mk = min<int>(len, (int)t.size());\n        for (int k = mk; k >= 1; --k) {\n            bool ok = true;\n            for (int i = 0; i < k; ++i)\n                if (s[len - k + i] != t[i]) { ok = false; break; }\n            if (ok) return k;\n        }\n        return 0;\n    }\n    void append(const string& t, int k) {\n        for (int i = k; i < (int)t.size(); ++i) {\n            char c = t[i];\n            if (len < 5) {\n                s[len++] = c;\n            } else {\n                s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; s[3] = s[4]; s[4] = c;\n            }\n        }\n    }\n};\n\n/*--------------- evaluate a permutation (exact cost) ---------------*/\nint evaluate(const vector<int>& ord) {\n    int ks[200];\n    State suf;\n    for (int i = 0; i < M; ++i) {\n        int t = ord[i];\n        ks[i] = suf.overlap(targets[t]);\n        suf.append(targets[t], ks[i]);\n    }\n\n    int dp_prev[225];\n    int prev_t = -1;\n    int sza = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int t = ord[i];\n        int k = ks[i];\n        if (k == 5) continue;                 // already contained\n        int sz = last_sz[t];\n        if (prev_t == -1) {\n            for (int e = 0; e < sz; ++e)\n                dp_prev[e] = (int)cost_tbl[t][k][start_cell * sz + e];\n            sza = sz;\n            prev_t = t;\n        } else {\n            int dp_cur[225];\n            for (int e2 = 0; e2 < sz; ++e2) {\n                int best = INT_MAX;\n                for (int e1 = 0; e1 < sza; ++e1) {\n                    int c = last_cells[prev_t][e1];\n                    int cand = dp_prev[e1] + (int)cost_tbl[t][k][c * sz + e2];\n                    if (cand < best) best = cand;\n                }\n                dp_cur[e2] = best;\n            }\n            for (int e2 = 0; e2 < sz; ++e2) dp_prev[e2] = dp_cur[e2];\n            sza = sz;\n            prev_t = t;\n        }\n    }\n    if (prev_t == -1) return 0;\n    int ans = INT_MAX;\n    for (int e = 0; e < sza; ++e) ans = min(ans, dp_prev[e]);\n    return ans;\n}\n\n/*--------------- reconstruct the best order ---------------*/\nvector<pair<int,int>> reconstruct(const vector<int>& ord) {\n    vector<pair<int,int>> answer;\n    int ks[200];\n    State suf;\n    for (int i = 0; i < M; ++i) {\n        ks[i] = suf.overlap(targets[ord[i]]);\n        suf.append(targets[ord[i]], ks[i]);\n    }\n\n    vector<vector<uint8_t>> back_ptrs;\n    vector<int> chunk_t;\n    vector<int> chunk_k;\n    int dp_prev[225];\n    int prev_t = -1;\n    int sza = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int t = ord[i];\n        int k = ks[i];\n        if (k == 5) continue;\n        int sz = last_sz[t];\n        if (prev_t == -1) {\n            for (int e = 0; e < sz; ++e)\n                dp_prev[e] = (int)cost_tbl[t][k][start_cell * sz + e];\n            sza = sz;\n            prev_t = t;\n            chunk_t.push_back(t);\n            chunk_k.push_back(k);\n        } else {\n            vector<uint8_t> bp(sz);\n            int dp_cur[225];\n            for (int e2 = 0; e2 < sz; ++e2) {\n                int best = INT_MAX;\n                uint8_t best_e1 = 0;\n                for (int e1 = 0; e1 < sza; ++e1) {\n                    int c = last_cells[prev_t][e1];\n                    int cand = dp_prev[e1] + (int)cost_tbl[t][k][c * sz + e2];\n                    if (cand < best) {\n                        best = cand;\n                        best_e1 = (uint8_t)e1;\n                    }\n                }\n                dp_cur[e2] = best;\n                bp[e2] = best_e1;\n            }\n            for (int e2 = 0; e2 < sz; ++e2) dp_prev[e2] = dp_cur[e2];\n            back_ptrs.push_back(std::move(bp));\n            sza = sz;\n            prev_t = t;\n            chunk_t.push_back(t);\n            chunk_k.push_back(k);\n        }\n    }\n\n    int Cn = (int)chunk_t.size();\n    if (Cn == 0) return answer;\n\n    int best_e = 0;\n    for (int e = 1; e < sza; ++e)\n        if (dp_prev[e] < dp_prev[best_e]) best_e = e;\n\n    vector<int> end_idx(Cn);\n    end_idx[Cn - 1] = best_e;\n    for (int i = Cn - 1; i >= 1; --i)\n        end_idx[i - 1] = back_ptrs[i - 1][end_idx[i]];\n\n    int cur_cell = start_cell;\n    for (int idx = 0; idx < Cn; ++idx) {\n        int t = chunk_t[idx];\n        int k = chunk_k[idx];\n        int ej = end_idx[idx];\n        int L = 5 - k;\n        vector<int> layers[5];\n        for (int l = 0; l < L; ++l)\n            layers[l] = pos[targets[t][k + l] - 'A'];\n\n        int dp_p[225], dp_c[225];\n        uint8_t par[5][225];\n\n        int sz0 = (int)layers[0].size();\n        for (int i = 0; i < sz0; ++i)\n            dp_p[i] = manhattan(cur_cell, layers[0][i]);\n\n        for (int l = 1; l < L; ++l) {\n            int szp = (int)layers[l - 1].size();\n            int szc = (int)layers[l].size();\n            for (int j = 0; j < szc; ++j) {\n                int best = INT_MAX;\n                uint8_t best_i = 0;\n                for (int i = 0; i < szp; ++i) {\n                    int val = dp_p[i] + manhattan(layers[l - 1][i], layers[l][j]);\n                    if (val < best) {\n                        best = val;\n                        best_i = (uint8_t)i;\n                    }\n                }\n                dp_c[j] = best;\n                par[l][j] = best_i;\n            }\n            for (int j = 0; j < szc; ++j) dp_p[j] = dp_c[j];\n        }\n\n        int cells[5];\n        int cur_j = ej;\n        cells[L - 1] = layers[L - 1][cur_j];\n        for (int l = L - 1; l >= 1; --l) {\n            cur_j = par[l][cur_j];\n            cells[l - 1] = layers[l - 1][cur_j];\n        }\n\n        for (int l = 0; l < L; ++l) {\n            int id = cells[l];\n            answer.emplace_back(id / N, id % N);\n        }\n        cur_cell = cells[L - 1];\n    }\n    return answer;\n}\n\n/*--------------- main ---------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    start_cell = si * N + sj;\n    const int C = N * N;\n\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            pos[s[j] - 'A'].push_back(id);\n        }\n    }\n    for (int k = 0; k < M; ++k) cin >> targets[k];\n\n    /* precompute Manhattan distances */\n    for (int i = 0; i < C; ++i) {\n        int i1 = i / N, j1 = i % N;\n        for (int j = 0; j < C; ++j) {\n            int i2 = j / N, j2 = j % N;\n            dist_arr[i][j] = abs(i1 - i2) + abs(j1 - j2);\n        }\n    }\n\n    /* precompute suffix costs for every target and every split k = 0..4 */\n    for (int t = 0; t < M; ++t) {\n        char last_ch = targets[t][4];\n        last_sz[t] = (int)pos[last_ch - 'A'].size();\n        for (int i = 0; i < last_sz[t]; ++i)\n            last_cells[t][i] = pos[last_ch - 'A'][i];\n\n        for (int k = 0; k < 5; ++k) {\n            int L = 5 - k;\n            vector<int> cells[5];\n            for (int l = 0; l < L; ++l)\n                cells[l] = pos[targets[t][k + l] - 'A'];\n\n            int sz_last = (int)cells[L - 1].size(); // = last_sz[t]\n            cost_tbl[t][k].assign(C * sz_last, 0);\n            vector<int> dp_prev(225), dp_cur(225);\n            for (int c = 0; c < C; ++c) {\n                int sz0 = (int)cells[0].size();\n                for (int i = 0; i < sz0; ++i)\n                    dp_prev[i] = manhattan(c, cells[0][i]) + 1;\n                for (int l = 1; l < L; ++l) {\n                    int szp = (int)cells[l - 1].size();\n                    int szc = (int)cells[l].size();\n                    for (int j = 0; j < szc; ++j) {\n                        int best = INT_MAX;\n                        for (int i = 0; i < szp; ++i) {\n                            int val = dp_prev[i] + manhattan(cells[l - 1][i], cells[l][j]);\n                            if (val < best) best = val;\n                        }\n                        dp_cur[j] = best + 1;\n                    }\n                    for (int j = 0; j < szc; ++j) dp_prev[j] = dp_cur[j];\n                }\n                for (int e = 0; e < sz_last; ++e)\n                    cost_tbl[t][k][c * sz_last + e] = (int16_t)dp_prev[e];\n            }\n        }\n    }\n\n    /* greedy initial order (overlap + geometry aware) */\n    vector<int> init_order;\n    {\n        vector<char> used(M, 0);\n        State suf;\n        int cur = start_cell;\n        for (int step = 0; step < M; ++step) {\n            int best_t = -1, best_e = -1;\n            int best_c = INT_MAX;\n            for (int t = 0; t < M; ++t) if (!used[t]) {\n                int k = suf.overlap(targets[t]);\n                int sz = last_sz[t];\n                for (int e = 0; e < sz; ++e) {\n                    int c = (int)cost_tbl[t][k][cur * sz + e];\n                    if (c < best_c) {\n                        best_c = c;\n                        best_t = t;\n                        best_e = e;\n                    }\n                }\n            }\n            init_order.push_back(best_t);\n            used[best_t] = 1;\n            int k = suf.overlap(targets[best_t]);\n            suf.append(targets[best_t], k);\n            cur = last_cells[best_t][best_e];\n        }\n    }\n\n    /* iterated local search */\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    vector<int> best_order = init_order;\n    int best_val = evaluate(best_order);\n    vector<int> cur_order = init_order;\n    int cur_val = best_val;\n\n    const double TL = 1.92;\n    int iter = 0, last_improve = 0;\n\n    while (elapsed() < TL) {\n        ++iter;\n        int type = rng() % 3;\n        int i = rng() % M;\n        int j = rng() % M;\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<int> nxt = cur_order;\n        if (type == 0) {\n            swap(nxt[i], nxt[j]);\n        } else if (type == 1) {\n            int v = nxt[i];\n            nxt.erase(nxt.begin() + i);\n            nxt.insert(nxt.begin() + j, v);\n        } else {\n            reverse(nxt.begin() + i, nxt.begin() + j + 1);\n        }\n\n        int nxt_val = evaluate(nxt);\n        if (nxt_val < cur_val) {\n            cur_order = std::move(nxt);\n            cur_val = nxt_val;\n            last_improve = iter;\n            if (cur_val < best_val) {\n                best_val = cur_val;\n                best_order = cur_order;\n            }\n        } else if (iter - last_improve > 5000) {\n            /* kick and restart from best known solution */\n            cur_order = best_order;\n            for (int k = 0; k < 5; ++k) {\n                int a = rng() % M, b = rng() % M;\n                if (a != b) swap(cur_order[a], cur_order[b]);\n            }\n            cur_val = evaluate(cur_order);\n            last_improve = iter;\n        }\n    }\n\n    /* reconstruct and output */\n    vector<pair<int,int>> ans = reconstruct(best_order);\n    for (auto &p : ans) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\ndouble eps;\nconst int MAXC = 400;          // max cells\nconst int MAXT = 400;          // max translations per field\n\n/* global data */\nvector<vector<bitset<MAXC>>> masks;                 // masks[k][t]\nvector<vector<bitset<MAXT>>> trans_cover_cell;      // cover[k][p]  (translations)\nvector<vector<bitset<MAXT>>> not_cover_cell;        // ~cover , masked to valid ones\nvector<bitset<MAXT>> all_valid;                     // all translations of field k\nvector<int> drilled_val;                            // -1 = unknown\nvector<int> drilled_cells;\nmt19937 rng;\n\n/* --------------------------------------------------------------- */\nstruct Sol {\n    bitset<MAXC> uni;\n    vector<int> assigned;\n};\n\nstruct State {\n    vector<int> assigned;\n    array<short, MAXC> sum;\n    int depth;\n};\n\n/* safe fixed\u2011point propagation, never removes a true translation */\nvoid global_propagate(vector<bitset<MAXT>>& cand) {\n    bool changed = true;\n    int it = 0;\n    while (changed && it++ < 20) {\n        changed = false;\n        vector<vector<char>> any(M, vector<char>(N * N, 0));\n        vector<vector<char>> all(M, vector<char>(N * N, 0));\n        vector<int> tot_any(N * N, 0), tot_all(N * N, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (!cand[k].any()) return;               // contradiction \u2013 should not happen\n            for (int p : drilled_cells) {\n                bool a = (cand[k] & trans_cover_cell[k][p]).any();\n                bool b = false;\n                if (cand[k].any())\n                    b = (cand[k] & not_cover_cell[k][p]).none();\n                any[k][p] = a;  all[k][p] = b;\n                if (a) tot_any[p]++;\n                if (b) tot_all[p]++;\n            }\n        }\n\n        for (int k = 0; k < M; k++) {\n            for (int t = 0; t < (int)masks[k].size(); t++) if (cand[k].test(t)) {\n                bool ok = true;\n                for (int p : drilled_cells) {\n                    int need = drilled_val[p] - (masks[k][t].test(p) ? 1 : 0);\n                    int minRem = tot_all[p] - (all[k][p] ? 1 : 0);\n                    int maxRem = tot_any[p] - (any[k][p] ? 1 : 0);\n                    if (need < minRem || need > maxRem) { ok = false; break; }\n                }\n                if (!ok) {\n                    cand[k].reset(t);\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\n/* --------------------------------------------------------------- */\nstruct DFSHelper {\n    const vector<bitset<MAXT>>& cand;\n    int limit_sol, limit_node;\n    int nodes;\n    vector<Sol> sols;\n\n    DFSHelper(const vector<bitset<MAXT>>& c, int ls, int ln)\n        : cand(c), limit_sol(ls), limit_node(ln), nodes(0) {}\n\n    void run() {\n        State init;\n        init.assigned.assign(M, -1);\n        init.sum.fill(0);\n        init.depth = 0;\n        rec(init);\n    }\n\n    void rec(State st) {\n        if ((int)sols.size() >= limit_sol || nodes >= limit_node) return;\n        ++nodes;\n        if (st.depth == M) {\n            bitset<MAXC> uni;\n            for (int k = 0; k < M; k++) uni |= masks[k][st.assigned[k]];\n            sols.push_back({uni, st.assigned});\n            return;\n        }\n        vector<int> fields;\n        for (int i = 0; i < M; i++) if (st.assigned[i] == -1) fields.push_back(i);\n        sort(fields.begin(), fields.end(),\n             [&](int a, int b) { return cand[a].count() < cand[b].count(); });\n\n        int pick = min((int)fields.size(), max(1, (int)fields.size() / 2 + 1));\n        int k = fields[rng() % pick];\n\n        vector<int> ts;\n        for (int t = 0; t < (int)masks[k].size(); t++)\n            if (cand[k].test(t)) ts.push_back(t);\n        shuffle(ts.begin(), ts.end(), rng);\n\n        for (int t : ts) {\n            State nst = st;\n            nst.assigned[k] = t;\n            ++nst.depth;\n            bool ok = true;\n            for (int p : drilled_cells) {\n                if (masks[k][t].test(p)) ++nst.sum[p];\n                int rem = M - nst.depth;\n                int need = drilled_val[p] - nst.sum[p];\n                if (need < 0 || need > rem) { ok = false; break; }\n            }\n            if (!ok) continue;\n            rec(nst);\n        }\n    }\n};\n\n/* --------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    if (!(cin >> N >> M >> eps)) return 0;\n    vector<vector<pair<int,int>>> shapes(M);\n    for (int k = 0; k < M; k++) {\n        int d; cin >> d;\n        shapes[k].resize(d);\n        for (int i = 0; i < d; i++) cin >> shapes[k][i].first >> shapes[k][i].second;\n    }\n\n    /* pre\u2011compute translations */\n    masks.assign(M, {});\n    all_valid.assign(M, {});\n    for (int k = 0; k < M; k++) {\n        int hi = 0, hj = 0;\n        for (auto &c : shapes[k]) {\n            hi = max(hi, c.first);\n            hj = max(hj, c.second);\n        }\n        int h = hi + 1, w = hj + 1;\n        for (int di = 0; di + h <= N; di++) {\n            for (int dj = 0; dj + w <= N; dj++) {\n                bitset<MAXC> bs;\n                for (auto &c : shapes[k]) {\n                    int i = di + c.first;\n                    int j = dj + c.second;\n                    bs.set(i * N + j);\n                }\n                masks[k].push_back(bs);\n            }\n        }\n        for (int t = 0; t < (int)masks[k].size(); t++) all_valid[k].set(t);\n    }\n\n    trans_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    not_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    for (int k = 0; k < M; k++) {\n        for (int p = 0; p < N * N; p++) {\n            for (int t = 0; t < (int)masks[k].size(); t++)\n                if (masks[k][t].test(p)) trans_cover_cell[k][p].set(t);\n            not_cover_cell[k][p] = all_valid[k] & ~trans_cover_cell[k][p];\n        }\n    }\n\n    drilled_val.assign(N * N, -1);\n    rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<bitset<MAXT>> cand(M);\n    for (int k = 0; k < M; k++) cand[k] = all_valid[k];\n\n    const int MAX_OPS = 2 * N * N;\n    int ops = 0;\n\n    auto do_drill = [&](int p) {\n        int i = p / N, j = p % N;\n        cout << \"q 1 \" << i << ' ' << j << endl;\n        int v; \n        if (!(cin >> v)) exit(0);\n        ++ops;\n        drilled_val[p] = v;\n        drilled_cells.push_back(p);\n        if (v == 0) {\n            for (int k = 0; k < M; k++) cand[k] &= not_cover_cell[k][p];\n        } else if (v == M) {\n            for (int k = 0; k < M; k++) cand[k] &= trans_cover_cell[k][p];\n        }\n        global_propagate(cand);\n    };\n\n    auto do_guess = [&](const bitset<MAXC>& uni) -> bool {\n        vector<pair<int,int>> ans;\n        for (int p = 0; p < N * N; p++)\n            if (uni.test(p)) ans.emplace_back(p / N, p % N);\n        cout << \"a \" << ans.size();\n        for (auto &pr : ans) cout << ' ' << pr.first << ' ' << pr.second;\n        cout << endl;\n        int resp; \n        if (!(cin >> resp)) exit(0);\n        ++ops;\n        return resp == 1;\n    };\n\n    vector<int> cell_order(N * N);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    shuffle(cell_order.begin(), cell_order.end(), rng);\n    int nxt = 0;\n\n    auto pick_random_undrilled = [&]() -> int {\n        while (nxt < N * N && drilled_val[cell_order[nxt]] != -1) ++nxt;\n        if (nxt < N * N) return cell_order[nxt++];\n        for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) return p;\n        return -1;\n    };\n\n    /* initial random drilling */\n    int init_drills = min(N * N, max(N, 4));\n    for (int i = 0; i < init_drills && ops < MAX_OPS - 5; i++) {\n        int p = pick_random_undrilled();\n        if (p == -1) break;\n        do_drill(p);\n    }\n\n    const int LIMIT_SOL = 12;\n    const int LIMIT_NODE = 60000;\n\n    while (ops < MAX_OPS - 2) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 2.6) {                     // emergency\n            bitset<MAXC> all;\n            for (int p = 0; p < N * N; p++) all.set(p);\n            do_guess(all);\n            return 0;\n        }\n\n        int undrilled = N * N - (int)drilled_cells.size();\n        if (undrilled <= 8 && ops + undrilled + 1 <= MAX_OPS) {\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) do_drill(p);\n            bitset<MAXC> exact;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            if (do_guess(exact)) return 0;\n            break;\n        }\n\n        vector<bitset<MAXC>> sol_unions;\n\n        int total_cand = 0;\n        for (int k = 0; k < M; k++) total_cand += (int)cand[k].count();\n\n        if (total_cand <= 4000) {\n            for (int trial = 0; trial < 2 && (int)sol_unions.size() < LIMIT_SOL; ++trial) {\n                DFSHelper h(cand, LIMIT_SOL - (int)sol_unions.size(), LIMIT_NODE);\n                h.run();\n                for (auto &s : h.sols) {\n                    bool seen = false;\n                    for (auto &u : sol_unions) if (u == s.uni) { seen = true; break; }\n                    if (!seen) sol_unions.push_back(s.uni);\n                }\n            }\n        }\n\n        if (sol_unions.empty()) {\n            int p = pick_random_undrilled();\n            if (p == -1) {\n                bitset<MAXC> all;\n                for (int c = 0; c < N * N; c++) all.set(c);\n                do_guess(all);\n                return 0;\n            }\n            do_drill(p);\n        } else {\n            bool agree = true;\n            for (size_t i = 1; i < sol_unions.size(); i++)\n                if (sol_unions[i] != sol_unions[0]) { agree = false; break; }\n\n            if (agree) {\n                if (do_guess(sol_unions[0])) return 0;\n                /* wrong guess \u2013 force one more drill */\n                int p = pick_random_undrilled();\n                if (p != -1) do_drill(p);\n            } else {\n                int S = (int)sol_unions.size();\n                vector<int> cnt(N * N, 0);\n                for (auto &u : sol_unions)\n                    for (int p = 0; p < N * N; p++) if (u.test(p)) ++cnt[p];\n\n                int best = -1, best_score = -1;\n                for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) {\n                    int score = min(cnt[p], S - cnt[p]);\n                    if (score > best_score) {\n                        best_score = score;\n                        best = p;\n                    }\n                }\n                if (best == -1) best = pick_random_undrilled();\n                do_drill(best);\n            }\n        }\n    }\n\n    /* final fallback */\n    bitset<MAXC> all;\n    for (int c = 0; c < N * N; c++) all.set(c);\n    do_guess(all);\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect {\n    int x, y;\n    int w, h;\n};\n\nstruct FRect {\n    int x, y, w, h;\n};\n\nstatic int W, D, N;\nstatic vector<vector<ll>> a;\n\n/* ------------------------------------------------------------ */\n/*  geometry helpers                                              */\n/* ------------------------------------------------------------ */\nstatic bool intersect(const FRect& A, const FRect& B) {\n    return !(A.x + A.w <= B.x || B.x + B.w <= A.x ||\n             A.y + A.h <= B.y || B.y + B.h <= A.y);\n}\n\n/* ------------------------------------------------------------ */\n/*  single trial of maximal-rectangles packer                     */\n/* ------------------------------------------------------------ */\nstatic vector<Rect> pack_one(const vector<ll>& area, mt19937& rng,\n                             int order_type, int dim_mode) {\n    int n = (int)area.size();\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (order_type == 0) {\n        sort(ord.begin(), ord.end(),\n             [&](int i, int j){ return area[i] > area[j]; });\n    } else if (order_type == 1) {\n        sort(ord.begin(), ord.end(),\n             [&](int i, int j){ return area[i] < area[j]; });\n    } else {\n        shuffle(ord.begin(), ord.end(), rng);\n    }\n\n    vector<pair<int,int>> dim(n);\n    for (int idx : ord) {\n        ll A = area[idx];\n        int w, h;\n        if (dim_mode == 0) {\n            w = max(1, (int)std::sqrt((double)A));\n            h = (int)((A + w - 1) / w);\n        } else if (dim_mode == 1) {\n            h = max(1, (int)std::sqrt((double)A));\n            w = (int)((A + h - 1) / h);\n        } else if (dim_mode == 2) {\n            w = (int)max(1LL, (A + W - 1) / W);\n            h = (int)((A + w - 1) / w);\n        } else if (dim_mode == 3) {\n            h = (int)max(1LL, (A + W - 1) / W);\n            w = (int)((A + h - 1) / h);\n        } else {\n            ll lo = max(1LL, (A + W - 1) / W);\n            ll hi = min((ll)W, A);\n            if (lo >= hi) w = (int)lo;\n            else w = uniform_int_distribution<int>((int)lo, (int)hi)(rng);\n            h = (int)((A + w - 1) / w);\n        }\n        if (h > W) { h = W; w = (int)((A + h - 1) / h); }\n        if (w > W) { w = W; h = (int)((A + w - 1) / w); }\n        if (w < 1) w = 1;\n        if (h < 1) h = 1;\n        dim[idx] = {w, h};\n    }\n\n    vector<Rect> cur(n);\n    vector<FRect> freeList;\n    freeList.reserve(500);\n    freeList.push_back({0, 0, W, W});\n\n    for (int idx : ord) {\n        int w = dim[idx].first;\n        int h = dim[idx].second;\n        int bestPos = -1;\n        ll bestScore = (1LL<<60);\n        int bw = w, bh = h;\n\n        for (int i = 0; i < (int)freeList.size(); ++i) {\n            const FRect& f = freeList[i];\n            if (f.w >= w && f.h >= h) {\n                ll sc = 1LL * (f.w - w) * (f.h - h);\n                if (sc < bestScore) {\n                    bestScore = sc; bestPos = i; bw = w; bh = h;\n                }\n            }\n            if (f.w >= h && f.h >= w) {\n                ll sc = 1LL * (f.w - h) * (f.h - w);\n                if (sc < bestScore) {\n                    bestScore = sc; bestPos = i; bw = h; bh = w;\n                }\n            }\n        }\n        if (bestPos == -1) return {};\n\n        FRect fr = freeList[bestPos];\n        cur[idx] = {fr.x, fr.y, bw, bh};\n        freeList.erase(freeList.begin() + bestPos);\n\n        if (fr.w > bw) freeList.push_back({fr.x + bw, fr.y, fr.w - bw, fr.h});\n        if (fr.h > bh) freeList.push_back({fr.x, fr.y + bh, fr.w, fr.h - bh});\n\n        vector<FRect> nxt;\n        nxt.reserve(freeList.size() * 2);\n        for (auto& f : freeList) {\n            if (!intersect(f, {fr.x, fr.y, bw, bh})) {\n                nxt.push_back(f);\n                continue;\n            }\n            if (f.x >= fr.x && f.y >= fr.y &&\n                f.x + f.w <= fr.x + bw && f.y + f.h <= fr.y + bh) continue;\n\n            if (fr.x > f.x) nxt.push_back({f.x, f.y, fr.x - f.x, f.h});\n            if (fr.x + bw < f.x + f.w)\n                nxt.push_back({fr.x + bw, f.y, f.x + f.w - fr.x - bw, f.h});\n            if (fr.y > f.y) nxt.push_back({f.x, f.y, f.w, fr.y - f.y});\n            if (fr.y + bh < f.y + f.h)\n                nxt.push_back({f.x, fr.y + bh, f.w, f.y + f.h - fr.y - bh});\n        }\n        freeList.swap(nxt);\n\n        vector<FRect> pruned;\n        for (auto& f : freeList) {\n            if (f.w <= 0 || f.h <= 0) continue;\n            bool inside = false;\n            for (auto& g : freeList) {\n                if (&f == &g) continue;\n                if (g.x <= f.x && g.y <= f.y &&\n                    g.x + g.w >= f.x + f.w && g.y + g.h >= f.y + f.h) {\n                    if (g.w > f.w || g.h > f.h ||\n                        (g.w == f.w && g.h == f.h && &g < &f)) {\n                        inside = true; break;\n                    }\n                }\n            }\n            if (!inside) pruned.push_back(f);\n        }\n        freeList.swap(pruned);\n    }\n    return cur;\n}\n\n/* ------------------------------------------------------------ */\n/*  generate many packings for one day                            */\n/* ------------------------------------------------------------ */\nstatic vector<pair<vector<Rect>, vector<ull>>> pack_multi(\n        const vector<ll>& area, int maxTrials) {\n    vector<pair<vector<Rect>, vector<ull>>> res;\n    res.reserve(maxTrials);\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    for (int trial = 0; trial < maxTrials; ++trial) {\n        int order_type, dim_mode;\n        if (trial == 0) { order_type = 0; dim_mode = 0; }\n        else if (trial == 1) { order_type = 1; dim_mode = 0; }\n        else {\n            order_type = 2;\n            dim_mode = trial % 5;\n        }\n        auto r = pack_one(area, rng, order_type, dim_mode);\n        if (!r.empty()) {\n            // build edge mask\n            const int H_BITS = (W - 1) * W;\n            const int V_BITS = W * (W - 1);\n            const int TOT_BITS = H_BITS + V_BITS;\n            const int WORDS = (TOT_BITS + 63) >> 6;\n            vector<ull> mask(WORDS, 0);\n            auto set_bit = [&](int pos){\n                mask[pos >> 6] |= (1ULL << (pos & 63));\n            };\n            for (const auto& rc : r) {\n                int x = rc.x, y = rc.y, w = rc.w, h = rc.h;\n                if (y > 0 && y < W)\n                    for (int j = x; j < x + w; ++j) set_bit((y - 1) * W + j);\n                if (y + h > 0 && y + h < W)\n                    for (int j = x; j < x + w; ++j) set_bit((y + h - 1) * W + j);\n                if (x > 0 && x < W)\n                    for (int i = y; i < y + h; ++i)\n                        set_bit(H_BITS + i * (W - 1) + (x - 1));\n                if (x + w > 0 && x + w < W)\n                    for (int i = y; i < y + h; ++i)\n                        set_bit(H_BITS + i * (W - 1) + (x + w - 1));\n            }\n            res.push_back({std::move(r), std::move(mask)});\n        }\n    }\n    return res;\n}\n\n/* ------------------------------------------------------------ */\n/*  area deficit for one day                                      */\n/* ------------------------------------------------------------ */\nstatic ll day_area_cost(const vector<Rect>& r, const vector<ll>& area) {\n    ll c = 0;\n    for (int k = 0; k < N; ++k) {\n        ll A = 1LL * r[k].w * r[k].h;\n        if (area[k] > A) c += 100LL * (area[k] - A);\n    }\n    return c;\n}\n\n/* ------------------------------------------------------------ */\n/*  transition cost between two masks                            */\n/* ------------------------------------------------------------ */\nstatic ll trans_cost(const vector<ull>& a, const vector<ull>& b) {\n    ll s = 0;\n    for (size_t i = 0; i < a.size(); ++i)\n        s += __builtin_popcountll(a[i] ^ b[i]);\n    return s;\n}\n\n/* ------------------------------------------------------------ */\n/*  evaluate a complete solution (rects per day)                 */\n/* ------------------------------------------------------------ */\nstatic ll evaluate(const vector<vector<Rect>>& sol) {\n    ll total = 0;\n    vector<vector<ull>> masks;\n    masks.reserve(D);\n    for (int d = 0; d < D; ++d) {\n        total += day_area_cost(sol[d], a[d]);\n        const int H_BITS = (W - 1) * W;\n        const int V_BITS = W * (W - 1);\n        const int TOT_BITS = H_BITS + V_BITS;\n        const int WORDS = (TOT_BITS + 63) >> 6;\n        vector<ull> mask(WORDS, 0);\n        auto set_bit = [&](int pos){\n            mask[pos >> 6] |= (1ULL << (pos & 63));\n        };\n        for (const auto& rc : sol[d]) {\n            int x = rc.x, y = rc.y, w = rc.w, h = rc.h;\n            if (y > 0 && y < W)\n                for (int j = x; j < x + w; ++j) set_bit((y - 1) * W + j);\n            if (y + h > 0 && y + h < W)\n                for (int j = x; j < x + w; ++j) set_bit((y + h - 1) * W + j);\n            if (x > 0 && x < W)\n                for (int i = y; i < y + h; ++i)\n                    set_bit(H_BITS + i * (W - 1) + (x - 1));\n            if (x + w > 0 && x + w < W)\n                for (int i = y; i < y + h; ++i)\n                    set_bit(H_BITS + i * (W - 1) + (x + w - 1));\n        }\n        if (d > 0) total += trans_cost(mask, masks.back());\n        masks.push_back(std::move(mask));\n    }\n    return total;\n}\n\n/* ============================================================ */\n/*  Option A : full-height strips (zero transition cost)         */\n/* ============================================================ */\nstatic vector<vector<Rect>> solve_fullheight() {\n    // cost[k][w] = 100 * sum_d max(0, a[d][k] - w*W)\n    vector<vector<ll>> cost(N, vector<ll>(W + 1, 0));\n    for (int k = 0; k < N; ++k)\n        for (int w = 1; w <= W; ++w) {\n            ll c = 0;\n            for (int d = 0; d < D; ++d)\n                if (a[d][k] > 1LL * w * W)\n                    c += 100LL * (a[d][k] - 1LL * w * W);\n            cost[k][w] = c;\n        }\n\n    const ll INF = (1LL<<60);\n    vector<vector<ll>> dp(W + 1, vector<ll>(W + 1, INF));\n    vector<vector<ll>> ndp(W + 1, vector<ll>(W + 1, INF));\n\n    // parent[k][s][w] stored flat, k = 1..N\n    vector<int16_t> parent_flat((N + 1) * (W + 1) * (W + 1), -1);\n    auto PAR = [&](int k, int s, int w) -> int16_t& {\n        return parent_flat[k * (W + 1) * (W + 1) + s * (W + 1) + w];\n    };\n\n    for (int w = 1; w <= W; ++w) dp[w][w] = cost[0][w];\n\n    for (int k = 2; k <= N; ++k) {\n        for (int s = 0; s <= W; ++s)\n            fill(ndp[s].begin(), ndp[s].end(), INF);\n\n        for (int prev = 0; prev <= W; ++prev) {\n            vector<ll> pref(W + 1, INF);\n            vector<int> arg(W + 1, -1);\n            ll curMin = INF;\n            int curArg = -1;\n            for (int w = 1; w <= W; ++w) {\n                if (dp[prev][w] < curMin) {\n                    curMin = dp[prev][w];\n                    curArg = w;\n                }\n                pref[w] = curMin;\n                arg[w] = curArg;\n            }\n            for (int w = 1; w <= W; ++w) {\n                int S = prev + w;\n                if (S > W) break;\n                if (pref[w] == INF) continue;\n                ll val = cost[k - 1][w] + pref[w];\n                if (val < ndp[S][w]) {\n                    ndp[S][w] = val;\n                    PAR(k, S, w) = (int16_t)arg[w];\n                }\n            }\n        }\n        dp.swap(ndp);\n    }\n\n    ll best = INF;\n    int best_w = -1;\n    for (int w = 1; w <= W; ++w) {\n        if (dp[W][w] < best) {\n            best = dp[W][w];\n            best_w = w;\n        }\n    }\n\n    vector<int> widths(N);\n    int s = W;\n    int w = best_w;\n    for (int k = N; k >= 1; --k) {\n        widths[k - 1] = w;\n        if (k == 1) break;\n        int pw = PAR(k, s, w);\n        s -= w;\n        w = pw;\n    }\n\n    vector<vector<Rect>> ans(D, vector<Rect>(N));\n    vector<int> pref(N + 1, 0);\n    for (int k = 0; k < N; ++k) pref[k + 1] = pref[k] + widths[k];\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            ans[d][k] = {pref[k], 0, widths[k], W};\n\n    return ans;\n}\n\n/* ============================================================ */\n/*  Option B : variable-height strips (zero area cost)           */\n/* ============================================================ */\nstatic vector<vector<Rect>> solve_variable_strips() {\n    vector<ll> wmin(N);\n    ll sum_wmin = 0;\n    for (int k = 0; k < N; ++k) {\n        ll mx = 0;\n        for (int d = 0; d < D; ++d) mx = max(mx, a[d][k]);\n        wmin[k] = max(1LL, (mx + W - 1) / W);\n        sum_wmin += wmin[k];\n    }\n    if (sum_wmin > W) return {}; // impossible\n\n    vector<ll> b(N);\n    for (int k = 0; k < N; ++k)\n        for (int d = 0; d < D; ++d) b[k] = max(b[k], a[d][k]);\n    ll S = accumulate(b.begin(), b.end(), 0LL);\n\n    mt19937 rng(1234567);\n    auto eval = [&](const vector<ll>& w)->ll {\n        vector<vector<int>> h(D, vector<int>(N));\n        for (int d = 0; d < D; ++d)\n            for (int k = 0; k < N; ++k) {\n                h[d][k] = (int)((a[d][k] + w[k] - 1) / w[k]);\n                if (h[d][k] > W) h[d][k] = W;\n            }\n        ll cost = 0;\n        for (int d = 1; d < D; ++d) {\n            for (int k = 0; k < N; ++k) {\n                bool e1 = (h[d-1][k] < W);\n                bool e2 = (h[d][k] < W);\n                if (e1 && e2 && h[d-1][k] != h[d][k]) cost += 2LL * w[k];\n                else if (e1 != e2) cost += w[k];\n            }\n            for (int k = 0; k < N - 1; ++k) {\n                int M1 = max(h[d-1][k], h[d-1][k+1]);\n                int M2 = max(h[d][k], h[d][k+1]);\n                cost += abs(M2 - M1);\n            }\n        }\n        return cost;\n    };\n\n    vector<ll> best_w;\n    ll best_cost = (1LL<<60);\n\n    for (int attempt = 0; attempt < 20000; ++attempt) {\n        vector<ll> w = wmin;\n        ll rem = W - sum_wmin;\n        if (attempt == 0) {\n            for (int k = 0; k < N; ++k) {\n                ll add = rem * b[k] / S;\n                w[k] += add;\n                rem -= add;\n            }\n            for (int k = N - 1; k >= 0 && rem > 0; --k) {\n                ++w[k]; --rem;\n            }\n        } else {\n            vector<int> ord(N);\n            iota(ord.begin(), ord.end(), 0);\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int i = 0; i < N && rem > 0; ++i) {\n                ll give = (i == N - 1) ? rem : (rng() % (rem + 1));\n                w[ord[i]] += give;\n                rem -= give;\n            }\n        }\n        ll c = eval(w);\n        if (c < best_cost) {\n            best_cost = c;\n            best_w = w;\n        }\n    }\n\n    // hill climbing\n    bool improved = true;\n    while (improved) {\n        improved = false;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (i == j) continue;\n                if (best_w[i] <= wmin[i]) continue;\n                best_w[i]--; best_w[j]++;\n                ll c = eval(best_w);\n                if (c < best_cost) {\n                    best_cost = c;\n                    improved = true;\n                } else {\n                    best_w[i]++; best_w[j]--;\n                }\n            }\n        }\n    }\n\n    vector<vector<Rect>> ans(D, vector<Rect>(N));\n    vector<int> pref(N + 1, 0);\n    for (int k = 0; k < N; ++k) pref[k + 1] = pref[k] + (int)best_w[k];\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            int h = (int)((a[d][k] + best_w[k] - 1) / best_w[k]);\n            if (h > W) h = W;\n            ans[d][k] = {pref[k], 0, (int)best_w[k], h};\n        }\n    }\n    return ans;\n}\n\n/* ============================================================ */\n/*  Option D : greedy chain packing                               */\n/* ============================================================ */\nstatic vector<vector<Rect>> solve_chain(const vector<int>& full_w) {\n    vector<vector<Rect>> ans(D, vector<Rect>(N));\n    vector<ull> prev_mask;\n    const int TRIALS = 300; // packings per day\n\n    for (int d = 0; d < D; ++d) {\n        auto candidates = pack_multi(a[d], TRIALS);\n\n        // add full-height strip candidate as safe fallback\n        {\n            vector<Rect> r(N);\n            int x = 0;\n            for (int k = 0; k < N; ++k) {\n                r[k] = {x, 0, full_w[k], W};\n                x += full_w[k];\n            }\n            const int H_BITS = (W - 1) * W;\n            const int V_BITS = W * (W - 1);\n            const int TOT_BITS = H_BITS + V_BITS;\n            const int WORDS = (TOT_BITS + 63) >> 6;\n            vector<ull> mask(WORDS, 0);\n            auto set_bit = [&](int pos){\n                mask[pos >> 6] |= (1ULL << (pos & 63));\n            };\n            for (const auto& rc : r) {\n                int x = rc.x, y = rc.y, w = rc.w, h = rc.h;\n                if (y > 0 && y < W)\n                    for (int j = x; j < x + w; ++j) set_bit((y - 1) * W + j);\n                if (y + h > 0 && y + h < W)\n                    for (int j = x; j < x + w; ++j) set_bit((y + h - 1) * W + j);\n                if (x > 0 && x < W)\n                    for (int i = y; i < y + h; ++i)\n                        set_bit(H_BITS + i * (W - 1) + (x - 1));\n                if (x + w > 0 && x + w < W)\n                    for (int i = y; i < y + h; ++i)\n                        set_bit(H_BITS + i * (W - 1) + (x + w - 1));\n            }\n            candidates.push_back({std::move(r), std::move(mask)});\n        }\n\n        ll best_day_cost = (1LL<<60);\n        vector<Rect> best_rects;\n        vector<ull> best_mask;\n        for (auto& cand : candidates) {\n            ll c = day_area_cost(cand.first, a[d]);\n            if (d > 0) c += trans_cost(cand.second, prev_mask);\n            if (c < best_day_cost) {\n                best_day_cost = c;\n                best_rects = cand.first;\n                best_mask = std::move(cand.second);\n            }\n        }\n        ans[d] = std::move(best_rects);\n        prev_mask = std::move(best_mask);\n    }\n    return ans;\n}\n\n/* ============================================================ */\n/*  Main                                                          */\n/* ============================================================ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> W >> D >> N)) return 0;\n    a.assign(D, vector<ll>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    // ---- 1. fixed packing of max areas (cost 0) ----\n    vector<ll> b(N, 0);\n    for (int k = 0; k < N; ++k)\n        for (int d = 0; d < D; ++d)\n            b[k] = max(b[k], a[d][k]);\n\n    {\n        auto fixed = pack_multi(b, 5000); // try hard\n        if (!fixed.empty()) {\n            vector<vector<Rect>> ans(D, vector<Rect>(N));\n            for (int d = 0; d < D; ++d)\n                for (int k = 0; k < N; ++k)\n                    ans[d][k] = fixed[0].first[k];\n            for (int d = 0; d < D; ++d) {\n                for (int k = 0; k < N; ++k) {\n                    const Rect& r = ans[d][k];\n                    cout << r.y << ' ' << r.x << ' '\n                         << r.y + r.h << ' ' << r.x + r.w << '\\n';\n                }\n            }\n            return 0;\n        }\n    }\n\n    // ---- prepare full-height strip widths (used by several options) ----\n    vector<int> full_w;\n    {\n        auto tmp = solve_fullheight();\n        full_w.resize(N);\n        for (int k = 0; k < N; ++k) full_w[k] = tmp[0][k].w;\n    }\n\n    // ---- evaluate all options and keep the best ----\n    ll best_cost = (1LL<<60);\n    vector<vector<Rect>> best_sol;\n\n    // Option A\n    {\n        auto sol = solve_fullheight();\n        ll c = evaluate(sol);\n        if (c < best_cost) {\n            best_cost = c;\n            best_sol = std::move(sol);\n        }\n    }\n\n    // Option B\n    {\n        auto sol = solve_variable_strips();\n        if (!sol.empty()) {\n            ll c = evaluate(sol);\n            if (c < best_cost) {\n                best_cost = c;\n                best_sol = std::move(sol);\n            }\n        }\n    }\n\n    // Option D (chain)\n    {\n        auto sol = solve_chain(full_w);\n        ll c = evaluate(sol);\n        if (c < best_cost) {\n            best_cost = c;\n            best_sol = std::move(sol);\n        }\n    }\n\n    // output\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const Rect& r = best_sol[d][k];\n            cout << r.y << ' ' << r.x << ' '\n                 << r.y + r.h << ' ' << r.x + r.w << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr int POS = (N - 2) * (N - 2);          // 49\nconstexpr int TOTAL_OPS = M * POS;               // 980\nconstexpr int CELLS = N * N;                     // 81\nconstexpr int MOD = 998244353;\nconstexpr int NOP = TOTAL_OPS;                   // sentinel for empty slot\n\nstruct Operation {\n    uint8_t cell[9];\n    uint32_t val[9];\n};\n\nOperation ops[TOTAL_OPS];\n\n// ------------------------------------------------------------------\n// board primitives\ninline ll delta_add(const uint32_t *board, int op) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[ops[op].cell[i]];\n        uint32_t s = ops[op].val[i];\n        d += (v >= MOD - s) ? (ll)s - MOD : s;\n    }\n    return d;\n}\n\ninline ll delta_remove(const uint32_t *board, int op) {\n    ll d = 0;\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[ops[op].cell[i]];\n        uint32_t s = ops[op].val[i];\n        d += (v < s) ? (ll)MOD - s : -(ll)s;\n    }\n    return d;\n}\n\ninline void apply_add(uint32_t *board, int op) {\n    for (int i = 0; i < 9; ++i) {\n        int c = ops[op].cell[i];\n        uint32_t v = board[c];\n        uint32_t s = ops[op].val[i];\n        board[c] = (v >= MOD - s) ? v + s - MOD : v + s;\n    }\n}\n\ninline void apply_remove(uint32_t *board, int op) {\n    for (int i = 0; i < 9; ++i) {\n        int c = ops[op].cell[i];\n        uint32_t v = board[c];\n        uint32_t s = ops[op].val[i];\n        board[c] = (v >= s) ? v - s : v + MOD - s;\n    }\n}\n\n// ------------------------------------------------------------------\n// fast RNG\nstruct FastRNG {\n    uint64_t x;\n    explicit FastRNG(uint64_t seed) : x(seed) {}\n    uint64_t operator()() {\n        uint64_t z = (x += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int rand_int(int n) { return (int)(operator()() % (uint64_t)n); }\n};\n\n// ------------------------------------------------------------------\nusing Board = array<uint32_t, CELLS>;\nusing OpsArr = array<int, K>;\n\nBoard init_board;\nll initial_score;\n\n// for a given slot (with current operation old_op), find the best replacement\ninline pair<ll,int> best_replacement(int old_op, uint32_t *board) {\n    if (old_op == NOP) {\n        ll best = 0;\n        int ba = NOP;\n        for (int a = 0; a < TOTAL_OPS; ++a) {\n            ll d = delta_add(board, a);\n            if (d > best) {\n                best = d;\n                ba = a;\n            }\n        }\n        return {best, ba};\n    } else {\n        ll drem = delta_remove(board, old_op);\n        apply_remove(board, old_op);\n        ll best = drem;          // change to NOP\n        int ba = NOP;\n        for (int a = 0; a < TOTAL_OPS; ++a) {\n            if (a == old_op) continue;\n            ll d = delta_add(board, a);\n            if (drem + d > best) {\n                best = drem + d;\n                ba = a;\n            }\n        }\n        apply_add(board, old_op);\n        return {best, ba};\n    }\n}\n\n// exact steepest-ascent hill climbing (1-opt)\nvoid hill_climb(OpsArr &cur, Board &board, ll &score) {\n    while (true) {\n        ll best_d = 0;\n        int best_i = -1, best_a = -1;\n        for (int i = 0; i < K; ++i) {\n            auto [d, a] = best_replacement(cur[i], board.data());\n            if (d > best_d) {\n                best_d = d;\n                best_i = i;\n                best_a = a;\n            }\n        }\n        if (best_d <= 0) break;\n        if (cur[best_i] != NOP) apply_remove(board.data(), cur[best_i]);\n        if (best_a != NOP) apply_add(board.data(), best_a);\n        cur[best_i] = best_a;\n        score += best_d;\n    }\n}\n\n// greedy construction, optionally randomized\nvoid greedy_construct(OpsArr &cur, Board &board, ll &score, bool randomized, FastRNG &rng) {\n    cur.fill(NOP);\n    board = init_board;\n    score = initial_score;\n    for (int step = 0; step < K; ++step) {\n        ll best_d = LLONG_MIN;\n        int best_a = -1;\n        if (randomized) {\n            static pair<ll,int> cand[1000];\n            int cn = 0;\n            for (int a = 0; a < TOTAL_OPS; ++a) {\n                ll d = delta_add(board.data(), a);\n                if (d > 0) cand[cn++] = {d, a};\n            }\n            if (cn > 0) {\n                sort(cand, cand + cn,\n                     [](const auto &x, const auto &y){ return x.first > y.first; });\n                int t = min(5, cn);\n                int idx = rng.rand_int(t);\n                best_a = cand[idx].second;\n                best_d = cand[idx].first;\n            }\n        } else {\n            best_d = 0;\n            for (int a = 0; a < TOTAL_OPS; ++a) {\n                ll d = delta_add(board.data(), a);\n                if (d > best_d) {\n                    best_d = d;\n                    best_a = a;\n                }\n            }\n        }\n        if (!randomized && best_d <= 0) break;\n        if (randomized && best_a == -1) {\n            if ((rng() & 3u) == 0) {\n                best_a = rng.rand_int(TOTAL_OPS);\n                best_d = delta_add(board.data(), best_a);\n            } else {\n                break;\n            }\n        }\n        int slot = -1;\n        for (int i = 0; i < K; ++i) if (cur[i] == NOP) { slot = i; break; }\n        if (slot == -1) break;\n        apply_add(board.data(), best_a);\n        cur[slot] = best_a;\n        score += best_d;\n    }\n}\n\n// ------------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k_input;\n    if (!(cin >> n >> m >> k_input)) return 0;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            uint32_t x; cin >> x;\n            init_board[i * N + j] = x;\n        }\n\n    vector<vector<vector<uint32_t>>> stamp(M, vector<vector<uint32_t>>(3, vector<uint32_t>(3)));\n    for (int s = 0; s < M; ++s)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamp[s][i][j];\n\n    // precompute operations\n    int id = 0;\n    for (int s = 0; s < M; ++s)\n        for (int p = 0; p <= N - 3; ++p)\n            for (int q = 0; q <= N - 3; ++q) {\n                int t = 0;\n                for (int di = 0; di < 3; ++di)\n                    for (int dj = 0; dj < 3; ++dj) {\n                        ops[id].cell[t] = (p + di) * N + (q + dj);\n                        ops[id].val[t] = stamp[s][di][dj];\n                        ++t;\n                    }\n                ++id;\n            }\n\n    initial_score = 0;\n    for (int i = 0; i < CELLS; ++i) initial_score += init_board[i];\n\n    // best solution found so far\n    ll best_score = initial_score;\n    OpsArr best_ops; best_ops.fill(NOP);\n    Board best_board = init_board;\n\n    FastRNG rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.95;\n\n    // ---------- build diverse initial solutions ----------\n    for (int attempt = 0; attempt < 12; ++attempt) {\n        OpsArr cur; Board board; ll score;\n        if (attempt == 0) {\n            greedy_construct(cur, board, score, false, rng);\n        } else if (attempt < 7) {\n            greedy_construct(cur, board, score, true, rng);\n        } else {\n            // random start\n            cur.fill(NOP);\n            board = init_board;\n            score = initial_score;\n            for (int i = 0; i < K; ++i) {\n                int a = rng.rand_int(TOTAL_OPS);\n                ll d = delta_add(board.data(), a);\n                apply_add(board.data(), a);\n                cur[i] = a;\n                score += d;\n            }\n        }\n        hill_climb(cur, board, score);\n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur;\n            best_board = board;\n        }\n    }\n\n    // ---------- Ruin-and-Recreate ILS ----------\n    OpsArr cur = best_ops;\n    Board board = best_board;\n    ll score = best_score;\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        // --- ruin phase ---\n        int used_cnt = 0;\n        for (int i = 0; i < K; ++i) if (cur[i] != NOP) ++used_cnt;\n        if (used_cnt == 0) {\n            cur = best_ops;\n            board = best_board;\n            score = best_score;\n            continue;\n        }\n\n        int r;\n        int mode = rng.rand_int(10);\n        if (mode < 5) r = 1 + rng.rand_int(3);       // small\n        else if (mode < 8) r = 3 + rng.rand_int(6);  // medium\n        else r = 6 + rng.rand_int(10);               // large\n        if (r > used_cnt) r = used_cnt;\n\n        for (int t = 0; t < r; ++t) {\n            int idx;\n            do { idx = rng.rand_int(K); } while (cur[idx] == NOP);\n            int op = cur[idx];\n            score += delta_remove(board.data(), op);\n            apply_remove(board.data(), op);\n            cur[idx] = NOP;\n        }\n\n        // --- recreate phase (greedy fill) ---\n        while (true) {\n            ll best_d = 0;\n            int best_a = -1;\n            for (int a = 0; a < TOTAL_OPS; ++a) {\n                ll d = delta_add(board.data(), a);\n                if (d > best_d) {\n                    best_d = d;\n                    best_a = a;\n                }\n            }\n            if (best_d <= 0) break;\n            int slot = -1;\n            for (int i = 0; i < K; ++i) if (cur[i] == NOP) { slot = i; break; }\n            if (slot == -1) break;\n            apply_add(board.data(), best_a);\n            cur[slot] = best_a;\n            score += best_d;\n        }\n\n        // --- polish ---\n        hill_climb(cur, board, score);\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = cur;\n            best_board = board;\n        } else {\n            // revert to best (classic ILS)\n            cur = best_ops;\n            board = best_board;\n            score = best_score;\n        }\n        ++iter;\n    }\n\n    // final polishing on the absolute best\n    {\n        OpsArr cur2 = best_ops;\n        Board board2 = best_board;\n        ll score2 = best_score;\n        hill_climb(cur2, board2, score2);\n        if (score2 > best_score) {\n            best_score = score2;\n            best_ops = cur2;\n        }\n    }\n\n    // output\n    int L = 0;\n    for (int i = 0; i < K; ++i) if (best_ops[i] != NOP) ++L;\n    cout << L << '\\n';\n    for (int i = 0; i < K; ++i) {\n        if (best_ops[i] == NOP) continue;\n        int op = best_ops[i];\n        int m = op / POS;\n        int rest = op % POS;\n        int p = rest / 7;\n        int q = rest % 7;\n        cout << m << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    int A[5][5];\n    for (int i = 0; i < 5; ++i)\n        for (int j = 0; j < 5; ++j)\n            cin >> A[i][j];\n\n    int grid[5][5];\n    memset(grid, -1, sizeof(grid));\n\n    int cr = 0, cc = 0;          // large crane\n    int hold = -1;               // what it carries\n    int dispatched[5] = {0};\n    int next_in[5] = {0};\n\n    vector<char> op0;\n    const int MAX_TURN = 10000;\n\n    auto move_toward = [&](int r, int c, int tr, int tc) -> char {\n        if (r == tr && c == tc) return '.';\n        if (r < tr) return 'D';\n        if (r > tr) return 'U';\n        if (c < tc) return 'R';\n        return 'L';\n    };\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        /* ---- 1. receiving ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (next_in[i] < 5 && grid[i][0] == -1) {\n                if (!(cr == i && cc == 0 && hold != -1)) {\n                    grid[i][0] = A[i][next_in[i]++];\n                }\n            }\n        }\n\n        char act = '.';\n\n        auto find_buffer = [&]() -> pair<int,int> {\n            int best = 1e9, br = -1, bc = -1;\n            for (int c = 1; c <= 3; ++c)\n                for (int r = 0; r < 5; ++r)\n                    if (grid[r][c] == -1) {\n                        int d = abs(cr - r) + abs(cc - c);\n                        if (d < best) { best = d; br = r; bc = c; }\n                    }\n            if (br != -1) return {br, bc};\n            // emergency: any non\u2011dispatch empty cell\n            for (int c = 0; c <= 3; ++c)\n                for (int r = 0; r < 5; ++r)\n                    if (grid[r][c] == -1) {\n                        int d = abs(cr - r) + abs(cc - c);\n                        if (d < best) { best = d; br = r; bc = c; }\n                    }\n            return {br, bc};\n        };\n\n        /* ---- 2. choose action ---- */\n        if (hold != -1) {\n            int row = hold / 5;\n            int need = 5 * row + dispatched[row];\n            if (hold == need) {                       // deliver\n                if (cr == row && cc == 4) {\n                    act = (grid[row][4] == -1) ? 'Q' : '.';\n                } else {\n                    act = move_toward(cr, cc, row, 4);\n                }\n            } else {                                  // buffer\n                auto [tr, tc] = find_buffer();\n                if (tr == -1) {\n                    act = '.';                         // nowhere to drop (should not happen)\n                } else if (cr == tr && cc == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_toward(cr, cc, tr, tc);\n                }\n            }\n        } else {                                      // empty\n            int tr = -1, tc = -1, best = 1e9;\n\n            // 2a. is a needed container already on the board?\n            for (int row = 0; row < 5; ++row) {\n                if (dispatched[row] >= 5) continue;\n                int need = 5 * row + dispatched[row];\n                for (int r = 0; r < 5; ++r)\n                    for (int c = 0; c <= 3; ++c)\n                        if (grid[r][c] == need) {\n                            int d = abs(cr - r) + abs(cc - c);\n                            if (d < best) { best = d; tr = r; tc = c; }\n                        }\n            }\n\n            if (tr != -1) {                           // go pick it up\n                act = (cr == tr && cc == tc) ? 'P' : move_toward(cr, cc, tr, tc);\n            } else {                                  // reveal a new container from a gate\n                for (int i = 0; i < 5; ++i) {\n                    if (grid[i][0] == -1) continue;\n                    int d = abs(cr - i) + abs(cc - 0);\n                    if (d < best) { best = d; tr = i; tc = 0; }\n                }\n                if (tr != -1) {\n                    act = (cr == tr && cc == tc) ? 'P' : move_toward(cr, cc, tr, tc);\n                } else {\n                    act = '.';\n                }\n            }\n        }\n\n        /* ---- 3. apply action ---- */\n        if (act == 'P') {\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n        } else if (act == 'Q') {\n            grid[cr][cc] = hold;\n            hold = -1;\n        } else if (act == 'U') {\n            --cr;\n        } else if (act == 'D') {\n            ++cr;\n        } else if (act == 'L') {\n            --cc;\n        } else if (act == 'R') {\n            ++cc;\n        }\n        op0.push_back(act);\n\n        /* ---- 4. dispatch ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (grid[i][4] != -1) {\n                ++dispatched[i];\n                grid[i][4] = -1;\n            }\n        }\n\n        bool done = true;\n        for (int i = 0; i < 5; ++i)\n            if (dispatched[i] < 5) done = false;\n        if (done) break;\n    }\n\n    size_t T = op0.size();\n    string s0(op0.begin(), op0.end());\n    cout << s0 << '\\n';\n    for (int k = 1; k < 5; ++k) {\n        cout << 'B';\n        for (size_t i = 1; i < T; ++i) cout << '.';\n        cout << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Result {\n    long long cost = 0;\n    vector<string> ops;\n    bool valid = false;\n};\n\n/* -------------------------------------------------------------\n   Simulate a given visitation order (move along shortest paths,\n   process every cell passed opportunistically).\n   ------------------------------------------------------------- */\nResult solve_given_order(const vector<vector<int>>& h,\n                         const vector<pair<int,int>>& order)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(100000);\n    int r = 0, c = 0;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n            }\n        }\n    };\n\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n\n    process(r, c);                         // (0,0)\n\n    for (auto [tr, tc] : order) {\n        if (r == tr && c == tc) continue; // already here (processed)\n        move_to(tr, tc);\n    }\n\n    /* deliver anything that is still loaded */\n    while (load > 0) {\n        int tr = -1, tc = -1, best = 1e9;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] < 0) {\n                    int d = abs(r - i) + abs(c - j);\n                    if (d < best) { best = d; tr = i; tc = j; }\n                }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* -------------------------------------------------------------\n   Deterministic nearest\u2011neighbour greedy (original)\n   ------------------------------------------------------------- */\nResult solve_greedy(const vector<vector<int>>& h) {\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(100000);\n    int r = 0, c = 0;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n            }\n        }\n    };\n\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false, has_neg = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j) {\n                if (need[i][j] > 0) has_pos = true;\n                if (need[i][j] < 0) has_neg = true;\n            }\n        if (!has_pos && load == 0) break;\n\n        int tr = -1, tc = -1, best = 1e9;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* -------------------------------------------------------------\n   Path generators\n   ------------------------------------------------------------- */\nvector<pair<int,int>> spiral_snake(int N, bool row_first) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    int r = 0, c = 0;\n    int dr = row_first ? 0 : 1;\n    int dc = row_first ? 1 : 0;\n    for (int step = 0; step < N * N; ++step) {\n        res.emplace_back(r, c);\n        vis[r][c] = true;\n        int nr = r + dr;\n        int nc = c + dc;\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N || vis[nr][nc]) {\n            int ndr, ndc;\n            if (row_first) { ndr = dc; ndc = -dr; }\n            else           { ndr = -dc; ndc = dr; }\n            dr = ndr; dc = ndc;\n            nr = r + dr; nc = c + dc;\n        }\n        r = nr; c = nc;\n    }\n    return res;\n}\n\nvector<pair<int,int>> diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int s = 0; s <= 2 * (N - 1); ++s) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = s - i;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        bool reverse = (s % 2 == (rev ? 0 : 1));\n        if (reverse) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nvector<pair<int,int>> anti_diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int d = -(N - 1); d <= N - 1; ++d) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = i - d;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        int parity = d & 1; // 0 = even, 1 = odd\n        bool reverse = (parity == (rev ? 1 : 0));\n        if (reverse) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nvector<pair<int,int>> block_row_snake(int N, int block_h, bool block_rev) {\n    vector<pair<int,int>> res;\n    int num_blocks = N / block_h;\n    for (int b = 0; b < num_blocks; ++b) {\n        int bi = block_rev ? (num_blocks - 1 - b) : b;\n        int base_r = bi * block_h;\n        bool snake_rev = (b % 2 == 1);\n        for (int col = 0; col < N; ++col) {\n            int c = snake_rev ? (N - 1 - col) : col;\n            if (col % 2 == 0) {\n                for (int dr = 0; dr < block_h; ++dr)\n                    res.emplace_back(base_r + dr, c);\n            } else {\n                for (int dr = block_h - 1; dr >= 0; --dr)\n                    res.emplace_back(base_r + dr, c);\n            }\n        }\n    }\n    return res;\n}\n\n/* -------------------------------------------------------------\n   Randomised greedy \u2013 evaluation only (no strings stored)\n   ------------------------------------------------------------- */\nlong long eval_random_greedy(const vector<vector<int>>& h,\n                             const vector<vector<int>>& nearest_src,\n                             const vector<vector<int>>& nearest_snk,\n                             uint64_t seed,\n                             double temp_empty,\n                             double temp_loaded,\n                             double pot_w)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    int r = 0, c = 0;\n    int steps = 0;\n    mt19937_64 rng(seed);\n\n    int rem_pos = 0, rem_neg = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (h[i][j] > 0) ++rem_pos;\n            else if (h[i][j] < 0) ++rem_neg;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n            --rem_pos;\n            ++steps;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n                if (need[cr][cc] == 0) --rem_neg;\n                ++steps;\n            }\n        }\n    };\n\n    auto move_step = [&](int dr, int dc) {\n        r += dr; c += dc;\n        cost += 100 + load;\n        ++steps;\n        process(r, c);\n    };\n\n    auto choose_target = [&](const vector<pair<int,int>>& cand,\n                             const vector<double>& w) -> pair<int,int> {\n        double sum = 0.0;\n        for (double x : w) sum += x;\n        if (sum <= 0) return {-1, -1};\n        double x = uniform_real_distribution<double>(0.0, sum)(rng);\n        for (size_t i = 0; i < cand.size(); ++i) {\n            x -= w[i];\n            if (x <= 0) return cand[i];\n        }\n        return cand.back();\n    };\n\n    process(r, c);\n    if (steps > 100000) return LLONG_MAX;\n\n    while (true) {\n        if (rem_pos == 0 && load == 0) break;\n        if (steps > 100000) return LLONG_MAX;\n\n        vector<pair<int,int>> cand;\n        vector<double> w;\n        if (load == 0) {\n            if (rem_pos == 0) return LLONG_MAX;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = need[i][j] * exp(-d / temp_empty);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_snk[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        } else {\n            if (rem_neg == 0) return LLONG_MAX;\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = -need[i][j] * exp(-d / temp_loaded);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_src[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        }\n        if (cand.empty()) return LLONG_MAX;\n        auto [tr, tc] = choose_target(cand, w);\n        if (tr < 0) return LLONG_MAX;\n\n        while (r != tr || c != tc) {\n            if (steps > 100000) return LLONG_MAX;\n            vector<pair<int,int>> dirs;\n            if (r < tr) dirs.emplace_back(1, 0);\n            else if (r > tr) dirs.emplace_back(-1, 0);\n            if (c < tc) dirs.emplace_back(0, 1);\n            else if (c > tc) dirs.emplace_back(0, -1);\n            int idx = uniform_int_distribution<int>(0, (int)dirs.size() - 1)(rng);\n            auto [dr, dc] = dirs[idx];\n            move_step(dr, dc);\n        }\n    }\n\n    if (load != 0) return LLONG_MAX;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (need[i][j] != 0) return LLONG_MAX;\n    if (steps > 100000) return LLONG_MAX;\n    return cost;\n}\n\n/* -------------------------------------------------------------\n   Randomised greedy \u2013 build full operation list\n   ------------------------------------------------------------- */\nResult build_random_greedy(const vector<vector<int>>& h,\n                           const vector<vector<int>>& nearest_src,\n                           const vector<vector<int>>& nearest_snk,\n                           uint64_t seed,\n                           double temp_empty,\n                           double temp_loaded,\n                           double pot_w)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(100000);\n    int r = 0, c = 0;\n    int steps = 0;\n    mt19937_64 rng(seed);\n\n    int rem_pos = 0, rem_neg = 0;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            if (h[i][j] > 0) ++rem_pos;\n            else if (h[i][j] < 0) ++rem_neg;\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            need[cr][cc] = 0;\n            --rem_pos;\n            ++steps;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d;\n                load -= d;\n                need[cr][cc] += d;\n                if (need[cr][cc] == 0) --rem_neg;\n                ++steps;\n            }\n        }\n    };\n\n    auto move_step = [&](int dr, int dc) {\n        r += dr; c += dc;\n        ops.emplace_back(1, (dr == 1 ? 'D' : (dr == -1 ? 'U' : (dc == 1 ? 'R' : 'L'))));\n        cost += 100 + load;\n        ++steps;\n        process(r, c);\n    };\n\n    auto choose_target = [&](const vector<pair<int,int>>& cand,\n                             const vector<double>& w) -> pair<int,int> {\n        double sum = 0.0;\n        for (double x : w) sum += x;\n        if (sum <= 0) return {-1, -1};\n        double x = uniform_real_distribution<double>(0.0, sum)(rng);\n        for (size_t i = 0; i < cand.size(); ++i) {\n            x -= w[i];\n            if (x <= 0) return cand[i];\n        }\n        return cand.back();\n    };\n\n    process(r, c);\n    if (steps > 100000) return {0, {}, false};\n\n    while (true) {\n        if (rem_pos == 0 && load == 0) break;\n        if (steps > 100000) return {0, {}, false};\n\n        vector<pair<int,int>> cand;\n        vector<double> w;\n        if (load == 0) {\n            if (rem_pos == 0) return {0, {}, false};\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = need[i][j] * exp(-d / temp_empty);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_snk[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        } else {\n            if (rem_neg == 0) return {0, {}, false};\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        double weight = -need[i][j] * exp(-d / temp_loaded);\n                        if (pot_w > 0.0)\n                            weight *= exp(-nearest_src[i][j] * pot_w);\n                        cand.emplace_back(i, j);\n                        w.push_back(weight);\n                    }\n        }\n        if (cand.empty()) return {0, {}, false};\n        auto [tr, tc] = choose_target(cand, w);\n        if (tr < 0) return {0, {}, false};\n\n        while (r != tr || c != tc) {\n            if (steps > 100000) return {0, {}, false};\n            vector<pair<int,int>> dirs;\n            if (r < tr) dirs.emplace_back(1, 0);\n            else if (r > tr) dirs.emplace_back(-1, 0);\n            if (c < tc) dirs.emplace_back(0, 1);\n            else if (c > tc) dirs.emplace_back(0, -1);\n            int idx = uniform_int_distribution<int>(0, (int)dirs.size() - 1)(rng);\n            auto [dr, dc] = dirs[idx];\n            move_step(dr, dc);\n        }\n    }\n\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* ------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    /* pre\u2011compute static Manhattan potentials */\n    vector<vector<int>> nearest_src(N, vector<int>(N, INT_MAX));\n    vector<vector<int>> nearest_snk(N, vector<int>(N, INT_MAX));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (h[i][j] > 0) {\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < N; ++y)\n                        nearest_src[x][y] = min(nearest_src[x][y], abs(x - i) + abs(y - j));\n            } else if (h[i][j] < 0) {\n                for (int x = 0; x < N; ++x)\n                    for (int y = 0; y < N; ++y)\n                        nearest_snk[x][y] = min(nearest_snk[x][y], abs(x - i) + abs(y - j));\n            }\n        }\n    }\n\n    vector<Result> candidates;\n\n    auto add_order = [&](const vector<pair<int,int>>& order) {\n        candidates.push_back(solve_given_order(h, order));\n    };\n\n    /* pure row / column snakes */\n    vector<pair<int,int>> ord;\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else            for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    ord.clear();\n    for (int i = N - 1; i >= 0; --i) {\n        if ((N - 1 - i) % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else                      for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    ord.clear();\n    for (int j = 0; j < N; ++j) {\n        if (j % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else            for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    ord.clear();\n    for (int j = N - 1; j >= 0; --j) {\n        if ((N - 1 - j) % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else                      for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    add_order(ord);\n\n    /* spirals */\n    add_order(spiral_snake(N, true));\n    add_order(spiral_snake(N, false));\n\n    /* diagonal snakes */\n    add_order(diagonal_snake(N, false));\n    add_order(diagonal_snake(N, true));\n\n    /* anti\u2011diagonal snakes */\n    add_order(anti_diagonal_snake(N, false));\n    add_order(anti_diagonal_snake(N, true));\n\n    /* block row snakes */\n    for (int bh : {2, 4, 5}) {\n        add_order(block_row_snake(N, bh, false));\n        add_order(block_row_snake(N, bh, true));\n    }\n\n    /* deterministic greedy */\n    candidates.push_back(solve_greedy(h));\n\n    /* -------- randomised greedy : evaluate many seeds -------- */\n    const vector<tuple<double,double,double>> param_sets = {\n        {1.0,  1.0,  0.0},\n        {3.0,  3.0,  0.0},\n        {5.0,  5.0,  0.0},\n        {10.0, 10.0, 0.0},\n        {20.0, 20.0, 0.0},\n        {1.0,  1.0,  0.05},\n        {3.0,  3.0,  0.05},\n        {5.0,  5.0,  0.1},\n        {10.0, 5.0,  0.0},\n        {5.0,  10.0, 0.0},\n    };\n    const int REPS = 200;\n\n    long long best_rand_cost = LLONG_MAX;\n    uint64_t best_seed = 0;\n    int best_pidx = 0;\n\n    for (int pidx = 0; pidx < (int)param_sets.size(); ++pidx) {\n        auto [te, tl, pw] = param_sets[pidx];\n        for (int r = 0; r < REPS; ++r) {\n            uint64_t seed = (uint64_t)pidx * 1000000ULL + (uint64_t)r;\n            long long c = eval_random_greedy(h, nearest_src, nearest_snk,\n                                             seed, te, tl, pw);\n            if (c < best_rand_cost) {\n                best_rand_cost = c;\n                best_seed = seed;\n                best_pidx = pidx;\n            }\n        }\n    }\n\n    if (best_rand_cost != LLONG_MAX) {\n        auto [te, tl, pw] = param_sets[best_pidx];\n        candidates.push_back(build_random_greedy(h, nearest_src, nearest_snk,\n                                                best_seed, te, tl, pw));\n    }\n\n    /* -------- choose the best valid candidate -------- */\n    Result best; best.valid = false; best.cost = LLONG_MAX;\n    for (auto &res : candidates) {\n        if (res.valid && res.cost < best.cost) best = res;\n    }\n\n    if (!best.valid) best = solve_greedy(h); // ultimate fallback\n\n    for (auto &s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int S = 2 * N * (N - 1); // 60 seeds\nconstexpr int P = N * N;            // 36 cells\n\nint X[S][M];\n\n// grid topology\nint nbr[P][4];\nint nbr_cnt[P];\nint deg[P];\nbool is_corner_cell[P];\nint cells_by_deg[P];\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- pre\u2011compute grid topology -----\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            int k = 0;\n            if (r > 0)     nbr[id][k++] = (r - 1) * N + c;\n            if (r < N - 1) nbr[id][k++] = (r + 1) * N + c;\n            if (c > 0)     nbr[id][k++] = r * N + (c - 1);\n            if (c < N - 1) nbr[id][k++] = r * N + (c + 1);\n            nbr_cnt[id] = k;\n            deg[id] = k;\n            is_corner_cell[id] = (k == 2);\n        }\n    }\n    iota(cells_by_deg, cells_by_deg + P, 0);\n    sort(cells_by_deg, cells_by_deg + P,\n         [&](int a, int b){ return deg[a] > deg[b]; });\n\n    int N_in, M_in, T;\n    while (cin >> N_in >> M_in >> T) {\n        for (int i = 0; i < S; ++i)\n            for (int l = 0; l < M; ++l)\n                cin >> X[i][l];\n\n        for (int turn = 0; turn < T; ++turn) {\n            // ---- 1. statistics per coordinate ----\n            int mx[M];\n            fill(mx, mx + M, 0);\n            for (int i = 0; i < S; ++i)\n                for (int l = 0; l < M; ++l)\n                    if (X[i][l] > mx[l]) mx[l] = X[i][l];\n\n            int V[S];\n            int mask[S];\n            int cnt_all[M] = {0};\n            for (int i = 0; i < S; ++i) {\n                int s = 0, m = 0;\n                for (int l = 0; l < M; ++l) {\n                    s += X[i][l];\n                    if (X[i][l] == mx[l]) {\n                        m |= (1 << l);\n                        ++cnt_all[l];\n                    }\n                }\n                V[i] = s;\n                mask[i] = m;\n            }\n\n            // ---- 2. seed scores ----\n            int rare_bonus[S] = {0};\n            for (int i = 0; i < S; ++i) {\n                int rb = 0;\n                for (int l = 0; l < M; ++l)\n                    if ((mask[i] >> l & 1) && cnt_all[l] <= 2)\n                        ++rb;\n                rare_bonus[i] = rb * 5000;          // strong but not overwhelming\n            }\n\n            int score[S];\n            for (int i = 0; i < S; ++i)\n                score[i] = V[i] * 10 + __builtin_popcount(mask[i]) * 100 + rare_bonus[i];\n\n            // ---- 3. select 36 seeds (coverage guaranteed) ----\n            bool in_sel[S] = {false};\n            int sel[P];\n            int sel_cnt = 0;\n\n            // force unique carriers\n            for (int l = 0; l < M; ++l) {\n                if (cnt_all[l] == 1) {\n                    for (int i = 0; i < S; ++i)\n                        if ((mask[i] >> l & 1) && !in_sel[i]) {\n                            in_sel[i] = true;\n                            sel[sel_cnt++] = i;\n                            break;\n                        }\n                }\n            }\n\n            // fill rest by score\n            vector<pair<int,int>> cand;\n            for (int i = 0; i < S; ++i)\n                if (!in_sel[i]) cand.emplace_back(score[i], i);\n            sort(cand.begin(), cand.end(),\n                 [&](const auto& a, const auto& b){\n                     if (a.first != b.first) return a.first > b.first;\n                     return V[a.second] > V[b.second];\n                 });\n            for (auto &p : cand) {\n                if (sel_cnt == P) break;\n                in_sel[p.second] = true;\n                sel[sel_cnt++] = p.second;\n            }\n\n            // repair: ensure every coordinate is covered\n            auto recompute_covered = [&]() {\n                int covered = 0;\n                for (int s = 0; s < sel_cnt; ++s) covered |= mask[sel[s]];\n                return covered;\n            };\n            const int FULL = (1 << M) - 1;\n            int covered = recompute_covered();\n\n            while (covered != FULL) {\n                int miss = FULL & ~covered;\n                int l = __builtin_ctz(miss);\n\n                // best unscored carrier of l\n                int best_i = -1, best_sc = -1;\n                for (int i = 0; i < S; ++i)\n                    if (!in_sel[i] && (mask[i] >> l & 1))\n                        if (score[i] > best_sc) { best_sc = score[i]; best_i = i; }\n\n                if (best_i == -1) break; // should never happen\n\n                // selected\u2011carrier counts per coordinate\n                int sel_car[M] = {0};\n                for (int s = 0; s < sel_cnt; ++s)\n                    for (int ll = 0; ll < M; ++ll)\n                        if (mask[sel[s]] >> ll & 1) ++sel_car[ll];\n\n                // drop worst seed that is not a unique pool carrier\n                // and not the sole selected carrier of any coordinate\n                int worst_pos = -1, worst_sc = INT_MAX;\n                for (int s = 0; s < sel_cnt; ++s) {\n                    int i = sel[s];\n                    bool bad = false;\n                    for (int ll = 0; ll < M; ++ll) {\n                        if ((mask[i] >> ll & 1) && cnt_all[ll] == 1) { bad = true; break; }\n                        if ((mask[i] >> ll & 1) && sel_car[ll] == 1) { bad = true; break; }\n                    }\n                    if (!bad && score[i] < worst_sc) {\n                        worst_sc = score[i];\n                        worst_pos = s;\n                    }\n                }\n                if (worst_pos == -1) { // fallback: any non\u2011unique\u2011in\u2011pool seed\n                    for (int s = 0; s < sel_cnt; ++s) {\n                        int i = sel[s];\n                        bool unique = false;\n                        for (int ll = 0; ll < M; ++ll)\n                            if ((mask[i] >> ll & 1) && cnt_all[ll] == 1) { unique = true; break; }\n                        if (!unique && score[i] < worst_sc) {\n                            worst_sc = score[i];\n                            worst_pos = s;\n                        }\n                    }\n                }\n                if (worst_pos == -1) break; // safety\n\n                in_sel[sel[worst_pos]] = false;\n                in_sel[best_i] = true;\n                sel[worst_pos] = best_i;\n                covered = recompute_covered();\n            }\n\n            // ---- 4. which selected seeds are critical? ----\n            bool is_crit[P];\n            for (int s = 0; s < P; ++s) {\n                int i = sel[s];\n                bool c = false;\n                for (int l = 0; l < M; ++l)\n                    if ((mask[i] >> l & 1) && cnt_all[l] <= 2) { c = true; break; }\n                is_crit[s] = c;\n            }\n\n            // ---- 5. pair potential matrix ----\n            static int pot[P][P];\n            for (int i = 0; i < P; ++i) {\n                int a = sel[i];\n                for (int j = i + 1; j < P; ++j) {\n                    int b = sel[j];\n                    int s = 0;\n                    for (int l = 0; l < M; ++l) s += max(X[a][l], X[b][l]);\n                    pot[i][j] = pot[j][i] = s;\n                }\n            }\n\n            // ---- 6. greedy initial placement (respect corner ban) ----\n            int pos2idx[P];\n            for (int i = 0; i < P; ++i) pos2idx[i] = -1;\n            bool used_seed[P] = {false};\n\n            for (int ci = 0; ci < P; ++ci) {\n                int cell = cells_by_deg[ci];\n                bool corner = is_corner_cell[cell];\n                int best_s = -1;\n                int best_gain = -1;\n                int best_sc = -1;\n                for (int s = 0; s < P; ++s) if (!used_seed[s]) {\n                    if (corner && is_crit[s]) continue;\n                    int gain = 0;\n                    for (int k = 0; k < nbr_cnt[cell]; ++k) {\n                        int nb = nbr[cell][k];\n                        if (pos2idx[nb] != -1) gain += pot[s][pos2idx[nb]];\n                    }\n                    int sc = score[sel[s]];\n                    if (gain > best_gain || (gain == best_gain && sc > best_sc)) {\n                        best_gain = gain;\n                        best_s = s;\n                        best_sc = sc;\n                    }\n                }\n                if (best_s == -1) { // safety fallback\n                    for (int s = 0; s < P; ++s)\n                        if (!used_seed[s]) { best_s = s; break; }\n                }\n                used_seed[best_s] = true;\n                pos2idx[cell] = best_s;\n            }\n\n            // ---- 7. hill climbing (best improvement) ----\n            for (int it = 0; it < 200; ++it) {\n                int best_delta = 0;\n                int best_a = -1, best_b = -1;\n                for (int a = 0; a < P; ++a) {\n                    int ia = pos2idx[a];\n                    for (int b = a + 1; b < P; ++b) {\n                        int ib = pos2idx[b];\n                        if (is_crit[ia] && is_corner_cell[b]) continue;\n                        if (is_crit[ib] && is_corner_cell[a]) continue;\n\n                        int delta = 0;\n                        for (int k = 0; k < nbr_cnt[a]; ++k) {\n                            int w = nbr[a][k];\n                            if (w == b) continue;\n                            delta += pot[ib][pos2idx[w]] - pot[ia][pos2idx[w]];\n                        }\n                        for (int k = 0; k < nbr_cnt[b]; ++k) {\n                            int w = nbr[b][k];\n                            if (w == a) continue;\n                            delta += pot[ia][pos2idx[w]] - pot[ib][pos2idx[w]];\n                        }\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_a = a;\n                            best_b = b;\n                        }\n                    }\n                }\n                if (best_delta > 0)\n                    swap(pos2idx[best_a], pos2idx[best_b]);\n                else\n                    break;\n            }\n\n            // ---- 8. output ----\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (c) cout << ' ';\n                    int cell = r * N + c;\n                    cout << sel[pos2idx[cell]];\n                }\n                cout << '\\n';\n            }\n            cout.flush();\n\n            // ---- 9. read next generation ----\n            for (int i = 0; i < S; ++i)\n                for (int l = 0; l < M; ++l)\n                    cin >> X[i][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<char> has_src;   // size N*N\nvector<char> need_tgt;  // size N*N\ninline int ID(int r, int c) { return r * N + c; }\n\nvector<int> len;        // edge length\nint off_r[15][4];\nint off_c[15][4];\nvector<int> cur_dir;\nvector<char> holding;\nint cur_r, cur_c;\n\nvector<string> ans;\nint hold_cnt = 0;\nint rem_src = 0;\n\nconst int dr[4] = {0, 1, 0, -1};\nconst int dc[4] = {1, 0, -1, 0};\n\ninline int rotcost(int a, int b) {\n    int d = abs(a - b);\n    return min(d, 4 - d);\n}\ninline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstruct Batch {\n    int size = 0;\n    int turns = 0;\n    int dist = 0;\n    int r = -1, c = -1;\n    int ndir[15];\n    int tr[15], tc[15];\n};\n\nBatch find_batch() {\n    Batch best;\n    best.size = 0;\n    best.turns = 1e9;\n    best.dist = 1e9;\n\n    int ndir[15];\n    int ncost[15];\n    int ntr[15], ntc[15];\n    int cnt[3];\n\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int dist = manhattan(cur_r, cur_c, r, c);\n\n            cnt[0] = cnt[1] = cnt[2] = 0;\n            for (int i = 1; i < V; ++i) {\n                ndir[i] = -1;\n                if (holding[i]) {\n                    // must deliver\n                    for (int d = 0; d < 4; ++d) {\n                        int nr = r + off_r[i][d];\n                        int nc = c + off_c[i][d];\n                        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                        if (!need_tgt[ID(nr, nc)]) continue;\n                        int cost = rotcost(cur_dir[i], d);\n                        if (ndir[i] == -1 || cost < ncost[i]) {\n                            ndir[i] = d;\n                            ncost[i] = cost;\n                            ntr[i] = nr;\n                            ntc[i] = nc;\n                        }\n                    }\n                } else {\n                    // must pick up\n                    for (int d = 0; d < 4; ++d) {\n                        int nr = r + off_r[i][d];\n                        int nc = c + off_c[i][d];\n                        if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                        if (!has_src[ID(nr, nc)]) continue;\n                        int cost = rotcost(cur_dir[i], d);\n                        if (ndir[i] == -1 || cost < ncost[i]) {\n                            ndir[i] = d;\n                            ncost[i] = cost;\n                            ntr[i] = nr;\n                            ntc[i] = nc;\n                        }\n                    }\n                }\n                if (ndir[i] != -1) cnt[ncost[i]]++;\n            }\n\n            for (int L = 0; L <= 2; ++L) {\n                int sz = cnt[0] + (L >= 1 ? cnt[1] : 0) + (L >= 2 ? cnt[2] : 0);\n                if (sz == 0) continue;\n                int turns = max(dist, L);\n                if (turns == 0) turns = 1;\n\n                if (sz > best.size ||\n                    (sz == best.size && turns < best.turns) ||\n                    (sz == best.size && turns == best.turns && dist < best.dist)) {\n                    best.size = sz;\n                    best.turns = turns;\n                    best.dist = dist;\n                    best.r = r;\n                    best.c = c;\n                    for (int i = 1; i < V; ++i) {\n                        if (ndir[i] != -1 && ncost[i] <= L) {\n                            best.ndir[i] = ndir[i];\n                            best.tr[i] = ntr[i];\n                            best.tc[i] = ntc[i];\n                        } else {\n                            best.ndir[i] = -1;\n                        }\n                    }\n                }\n            }\n        }\n    }\n    return best;\n}\n\nvoid execute_batch(const Batch& b) {\n    int travel = b.turns;\n    for (int step = 0; step < travel; ++step) {\n        char move = '.';\n        if (cur_r < b.r)       { move = 'D'; ++cur_r; }\n        else if (cur_r > b.r)  { move = 'U'; --cur_r; }\n        else if (cur_c < b.c)  { move = 'R'; ++cur_c; }\n        else if (cur_c > b.c)  { move = 'L'; --cur_c; }\n\n        string S(2 * V, '.');\n        S[0] = move;\n\n        for (int i = 1; i < V; ++i) {\n            if (b.ndir[i] == -1) continue;\n            if (cur_dir[i] == b.ndir[i]) continue;\n            int diff = (b.ndir[i] - cur_dir[i] + 4) % 4;\n            if (diff == 1) {\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            } else if (diff == 3) {\n                S[i] = 'L';\n                cur_dir[i] = (cur_dir[i] + 3) & 3;\n            } else { // diff == 2\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            }\n        }\n\n        if (step == travel - 1) {\n            for (int i = 1; i < V; ++i) {\n                if (b.ndir[i] == -1) continue;\n                S[V + i] = 'P';\n                if (holding[i]) {\n                    need_tgt[ID(b.tr[i], b.tc[i])] = 0;\n                    holding[i] = 0;\n                    --hold_cnt;\n                } else {\n                    has_src[ID(b.tr[i], b.tc[i])] = 0;\n                    holding[i] = 1;\n                    ++hold_cnt;\n                    --rem_src;\n                }\n            }\n        }\n        ans.push_back(S);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n    for (int i = 0; i < N; ++i) cin >> t[i];\n\n    has_src.assign(N * N, 0);\n    need_tgt.assign(N * N, 0);\n    long long sumr = 0, sumc = 0, work = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s[i][j] == '1' && t[i][j] == '1') {\n                // already satisfied\n            } else if (s[i][j] == '1') {\n                has_src[ID(i, j)] = 1;\n                ++rem_src;\n                sumr += i; sumc += j; ++work;\n            } else if (t[i][j] == '1') {\n                need_tgt[ID(i, j)] = 1;\n                sumr += i; sumc += j; ++work;\n            }\n        }\n    }\n\n    /*--- design the arm (star with distinct lengths) ---*/\n    cout << V << '\\n';\n    len.assign(V, 0);\n    for (int u = 1; u < V; ++u) {\n        int L = u;\n        if (L > N - 1) L = N - 1;\n        len[u] = L;\n        cout << 0 << ' ' << L << '\\n';\n        for (int d = 0; d < 4; ++d) {\n            off_r[u][d] = dr[d] * L;\n            off_c[u][d] = dc[d] * L;\n        }\n    }\n\n    if (work > 0) {\n        cur_r = int(sumr / work);\n        cur_c = int(sumc / work);\n    } else {\n        cur_r = N / 2;\n        cur_c = N / 2;\n    }\n    cur_r = max(0, min(N - 1, cur_r));\n    cur_c = max(0, min(N - 1, cur_c));\n    cout << cur_r << ' ' << cur_c << '\\n';\n\n    cur_dir.assign(V, 0);\n    holding.assign(V, 0);\n    ans.reserve(200000);\n\n    while (rem_src > 0 || hold_cnt > 0) {\n        Batch b = find_batch();\n        if (b.size > 0) {\n            execute_batch(b);\n        } else {\n            // Safety fallback: move toward nearest remaining work\n            int tr = -1, tc = -1, bestd = 1e9;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (has_src[ID(i, j)] || need_tgt[ID(i, j)]) {\n                        int d = manhattan(cur_r, cur_c, i, j);\n                        if (d < bestd) {\n                            bestd = d;\n                            tr = i; tc = j;\n                        }\n                    }\n                }\n            }\n            if (tr == -1) break;\n            char move = '.';\n            if (cur_r < tr) { move = 'D'; ++cur_r; }\n            else if (cur_r > tr) { move = 'U'; --cur_r; }\n            else if (cur_c < tc) { move = 'R'; ++cur_c; }\n            else if (cur_c > tc) { move = 'L'; --cur_c; }\n            string S(2 * V, '.');\n            S[0] = move;\n            ans.push_back(S);\n        }\n    }\n\n    for (const string& str : ans) cout << str << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    int w;          // +1 = mackerel, -1 = sardine\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    const int MAXC = 100000;\n    int N;\n    if (!(cin >> N)) return 0;\n    const int M = 2 * N;\n\n    vector<Point> pts(M);\n    unordered_set<unsigned long long> occ;\n    occ.reserve(M * 2);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n        pts[i].w = +1;\n        occ.insert(((unsigned long long)pts[i].x << 32) | (unsigned long long)pts[i].y);\n    }\n    for (int i = N; i < M; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n        pts[i].w = -1;\n        occ.insert(((unsigned long long)pts[i].x << 32) | (unsigned long long)pts[i].y);\n    }\n\n    /* coordinate compression */\n    vector<int> ux, uy;\n    ux.reserve(M);\n    uy.reserve(M);\n    for (auto &p : pts) {\n        ux.push_back(p.x);\n        uy.push_back(p.y);\n    }\n    sort(ux.begin(), ux.end());\n    ux.erase(unique(ux.begin(), ux.end()), ux.end());\n    sort(uy.begin(), uy.end());\n    uy.erase(unique(uy.begin(), uy.end()), uy.end());\n    const int X = (int)ux.size();\n    const int Y = (int)uy.size();\n\n    unordered_map<int,int> yid;\n    yid.reserve(Y * 2);\n    for (int i = 0; i < Y; ++i) yid[uy[i]] = i;\n\n    vector<int> py_id(M);\n    for (int i = 0; i < M; ++i) py_id[i] = yid[pts[i].y];\n\n    /* sort points by x */\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(),\n         [&](int a, int b){ return pts[a].x < pts[b].x; });\n    vector<int> spx(M), spy(M), spw(M);\n    for (int i = 0; i < M; ++i) {\n        spx[i] = pts[ord[i]].x;\n        spy[i] = py_id[ord[i]];\n        spw[i] = pts[ord[i]].w;\n    }\n\n    /* reusable buffer */\n    vector<int> ysum(Y);\n\n    auto eval_interval = [&](int x1, int x2, int &out_y1, int &out_y2) -> int {\n        memset(ysum.data(), 0, Y * sizeof(int));\n        int l = lower_bound(spx.begin(), spx.end(), x1) - spx.begin();\n        int r = upper_bound(spx.begin(), spx.end(), x2) - spx.begin();\n        for (int i = l; i < r; ++i) ysum[spy[i]] += spw[i];\n\n        int best = 0, cur = 0;\n        int best_l = 0, best_r = -1;\n        int cur_l = 0;\n        for (int i = 0; i < Y; ++i) {\n            if (cur + ysum[i] < ysum[i]) {\n                cur = ysum[i];\n                cur_l = i;\n            } else {\n                cur += ysum[i];\n            }\n            if (cur > best) {\n                best = cur;\n                best_l = cur_l;\n                best_r = i;\n            }\n        }\n        if (best <= 0) {\n            out_y1 = 0; out_y2 = 0;\n            return 0;\n        }\n        out_y1 = uy[best_l];\n        out_y2 = uy[best_r];\n        return best;\n    };\n\n    auto eval_rect = [&](const Rect &r) -> int {\n        int a = 0, b = 0;\n        for (auto &p : pts) {\n            if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) {\n                if (p.w == 1) ++a; else ++b;\n            }\n        }\n        return a - b;\n    };\n\n    /* fallback empty 1x1 */\n    Rect best_rect{0, 0, 1, 1};\n    int best_score = 0;\n    {\n        mt19937 rng(123456789);\n        uniform_int_distribution<int> dx(0, MAXC - 1);\n        uniform_int_distribution<int> dy(0, MAXC - 1);\n        for (int t = 0; t < 20000; ++t) {\n            int x = dx(rng), y = dy(rng);\n            unsigned long long c1 = ((unsigned long long)x << 32) | (unsigned long long)y;\n            unsigned long long c2 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)y;\n            unsigned long long c3 = ((unsigned long long)x << 32) | (unsigned long long)(y + 1);\n            unsigned long long c4 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)(y + 1);\n            if (!occ.count(c1) && !occ.count(c2) && !occ.count(c3) && !occ.count(c4)) {\n                best_rect = {x, y, x + 1, y + 1};\n                best_score = 0;\n                break;\n            }\n        }\n    }\n\n    /* ---------- coarse grid seeds ---------- */\n    auto grid_search = [&](int S, int K) {\n        int G = (MAXC + S) / S;\n        vector<vector<int>> grid(G, vector<int>(G, 0));\n        for (auto &p : pts) {\n            int cx = min(p.x / S, G - 1);\n            int cy = min(p.y / S, G - 1);\n            grid[cy][cx] += p.w;\n        }\n        using T = tuple<int,int,int,int,int>;          // val, y1, y2, x1, x2\n        priority_queue<T, vector<T>, greater<T>> pq;\n        for (int y1 = 0; y1 < G; ++y1) {\n            vector<int> col(G, 0);\n            for (int y2 = y1; y2 < G; ++y2) {\n                for (int x = 0; x < G; ++x) col[x] += grid[y2][x];\n                int cur = col[0], cur_l = 0;\n                int best = col[0], best_l = 0, best_r = 0;\n                for (int x = 1; x < G; ++x) {\n                    if (cur + col[x] < col[x]) {\n                        cur = col[x];\n                        cur_l = x;\n                    } else {\n                        cur += col[x];\n                    }\n                    if (cur > best) {\n                        best = cur;\n                        best_l = cur_l;\n                        best_r = x;\n                    }\n                }\n                if ((int)pq.size() < K) {\n                    pq.emplace(best, y1, y2, best_l, best_r);\n                } else if (best > get<0>(pq.top())) {\n                    pq.pop();\n                    pq.emplace(best, y1, y2, best_l, best_r);\n                }\n            }\n        }\n        vector<tuple<int,int,int,int,int>> res;\n        while (!pq.empty()) {\n            auto v = pq.top(); pq.pop();\n            res.emplace_back(S, get<1>(v), get<2>(v), get<3>(v), get<4>(v));\n        }\n        return res;\n    };\n\n    vector<tuple<int,int,int,int,int>> seeds;\n    for (int S : {500, 1000, 2000}) {\n        auto v = grid_search(S, 5);\n        seeds.insert(seeds.end(), v.begin(), v.end());\n    }\n\n    for (auto &sd : seeds) {\n        int S, gy1, gy2, gx1, gx2;\n        tie(S, gy1, gy2, gx1, gx2) = sd;\n        int x1 = gx1 * S;\n        int x2 = min(MAXC, (gx2 + 1) * S);\n        if (x1 > x2) swap(x1, x2);\n        int yy1, yy2;\n        int sc = eval_interval(x1, x2, yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {x1, yy1, x2, yy2};\n        }\n    }\n\n    /* snap best rectangle to actual point coordinates to obtain start indices */\n    int ix1 = 0, ix2 = X - 1;\n    if (best_score > 0) {\n        int minx = MAXC, maxx = 0, miny = MAXC, maxy = 0;\n        for (auto &p : pts) {\n            if (best_rect.x1 <= p.x && p.x <= best_rect.x2 &&\n                best_rect.y1 <= p.y && p.y <= best_rect.y2) {\n                minx = min(minx, p.x);\n                maxx = max(maxx, p.x);\n                miny = min(miny, p.y);\n                maxy = max(maxy, p.y);\n            }\n        }\n        if (minx <= maxx) {\n            best_rect = {minx, miny, maxx, maxy};\n            best_score = eval_rect(best_rect);\n            ix1 = lower_bound(ux.begin(), ux.end(), minx) - ux.begin();\n            ix2 = lower_bound(ux.begin(), ux.end(), maxx) - ux.begin();\n        }\n    }\n\n    {\n        int yy1, yy2;\n        int sc = eval_interval(ux[ix1], ux[ix2], yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {ux[ix1], yy1, ux[ix2], yy2};\n        }\n    }\n\n    /* ---------- helper to try an interval ---------- */\n    auto try_interval = [&](int i1, int i2) -> bool {\n        if (i1 < 0 || i2 >= X || i1 > i2) return false;\n        int yy1, yy2;\n        int sc = eval_interval(ux[i1], ux[i2], yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {ux[i1], yy1, ux[i2], yy2};\n            ix1 = i1; ix2 = i2;\n            return true;\n        }\n        return false;\n    };\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_local(-30, 30);\n    uniform_int_distribution<int> dist_global(0, X - 1);\n\n    auto hill_climb = [&]() {\n        while (true) {\n            int local_best = best_score;\n            int li1 = -1, li2 = -1;\n            int ly1 = 0, ly2 = 0;\n            for (int d1 = -1; d1 <= 1; ++d1) {\n                for (int d2 = -1; d2 <= 1; ++d2) {\n                    if (d1 == 0 && d2 == 0) continue;\n                    int ti1 = ix1 + d1;\n                    int ti2 = ix2 + d2;\n                    if (ti1 < 0 || ti2 >= X || ti1 > ti2) continue;\n                    int ty1, ty2;\n                    int tsc = eval_interval(ux[ti1], ux[ti2], ty1, ty2);\n                    if (tsc > local_best) {\n                        local_best = tsc;\n                        li1 = ti1; li2 = ti2;\n                        ly1 = ty1; ly2 = ty2;\n                    }\n                }\n            }\n            if (local_best <= best_score) break;\n            best_score = local_best;\n            best_rect = {ux[li1], ly1, ux[li2], ly2};\n            ix1 = li1; ix2 = li2;\n        }\n    };\n\n    /* Phase 1: pure random exploration */\n    for (int it = 0; it < 4000; ++it) {\n        int ni1, ni2;\n        if ((rng() & 1) && X > 1) {\n            ni1 = ix1 + dist_local(rng);\n            ni2 = ix2 + dist_local(rng);\n        } else {\n            ni1 = dist_global(rng);\n            ni2 = dist_global(rng);\n        }\n        if (ni1 < 0) ni1 = 0;\n        if (ni2 < 0) ni2 = 0;\n        if (ni1 >= X) ni1 = X - 1;\n        if (ni2 >= X) ni2 = X - 1;\n        if (ni1 > ni2) swap(ni1, ni2);\n        try_interval(ni1, ni2);\n    }\n\n    /* Phase 2: hill climb from the best found so far */\n    hill_climb();\n\n    /* Phase 3: more random jumps, hill climbing only on real improvement */\n    for (int it = 0; it < 2000; ++it) {\n        int ni1, ni2;\n        if ((rng() & 1) && X > 1) {\n            ni1 = ix1 + dist_local(rng);\n            ni2 = ix2 + dist_local(rng);\n        } else {\n            ni1 = dist_global(rng);\n            ni2 = dist_global(rng);\n        }\n        if (ni1 < 0) ni1 = 0;\n        if (ni2 < 0) ni2 = 0;\n        if (ni1 >= X) ni1 = X - 1;\n        if (ni2 >= X) ni2 = X - 1;\n        if (ni1 > ni2) swap(ni1, ni2);\n        if (try_interval(ni1, ni2))\n            hill_climb();\n    }\n\n    /* final safety: non\u2011zero area */\n    if (best_score <= 0) {\n        best_rect = {0, 0, 1, 1};   // empty fallback\n    } else {\n        if (best_rect.x1 == best_rect.x2) {\n            if (best_rect.x2 < MAXC) ++best_rect.x2;\n            else --best_rect.x1;\n        }\n        if (best_rect.y1 == best_rect.y2) {\n            if (best_rect.y2 < MAXC) ++best_rect.y2;\n            else --best_rect.y1;\n        }\n    }\n\n    cout << 4 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y2 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y2 << \"\\n\";\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Seq {\n    int r[100];\n    char d[100];\n    int b[100];\n};\n\nint N, T;\nlong long SIGMA;\nlong long Wobs[100], Hobs[100];\n\n/*------------------------------------------------------------*/\n/*  simulate from position `start` (0 \u2264 start \u2264 N)             */\ninline long long simulate(const Seq& seq, int n,\n                          long long* xs, long long* ys,\n                          long long* ws, long long* hs,\n                          int start = 0) {\n    long long W = 0, H = 0;\n    for (int i = start; i < n; ++i) {\n        long long wi = seq.r[i] ? Hobs[i] : Wobs[i];\n        long long hi = seq.r[i] ? Wobs[i] : Hobs[i];\n        long long x, y;\n        if (seq.d[i] == 'U') {\n            x = (seq.b[i] == -1) ? 0LL : xs[seq.b[i]] + ws[seq.b[i]];\n            y = 0;\n            for (int j = 0; j < i; ++j) {\n                if (x < xs[j] + ws[j] && xs[j] < x + wi)\n                    y = max(y, ys[j] + hs[j]);\n            }\n        } else {\n            y = (seq.b[i] == -1) ? 0LL : ys[seq.b[i]] + hs[seq.b[i]];\n            x = 0;\n            for (int j = 0; j < i; ++j) {\n                if (y < ys[j] + hs[j] && ys[j] < y + hi)\n                    x = max(x, xs[j] + ws[j]);\n            }\n        }\n        xs[i] = x;  ys[i] = y;\n        ws[i] = wi; hs[i] = hi;\n        if (x + wi > W) W = x + wi;\n        if (y + hi > H) H = y + hi;\n    }\n    return W + H;\n}\n\n/*------------------------------------------------------------*/\n/*  greedy construction / rebuild from `start`                 */\nlong long greedy_build(Seq& seq, int n, int start,\n                       int objective, bool stochastic,\n                       mt19937& rng,\n                       long long* xs, long long* ys,\n                       long long* ws, long long* hs) {\n    long long W = 0, H = 0;\n    for (int j = 0; j < start; ++j) {\n        W = max(W, xs[j] + ws[j]);\n        H = max(H, ys[j] + hs[j]);\n    }\n\n    struct Cand {\n        int r, b; char d;\n        long long x, y, w, h, sc;\n    } cands[404];\n    int cand_cnt;\n\n    for (int i = start; i < n; ++i) {\n        cand_cnt = 0;\n        for (int rot = 0; rot < 2; ++rot) {\n            long long wi = rot ? Hobs[i] : Wobs[i];\n            long long hi = rot ? Wobs[i] : Hobs[i];\n            for (int di = 0; di < 2; ++di) {\n                char dd = di ? 'L' : 'U';\n                for (int bv = -1; bv < i; ++bv) {\n                    long long x, y;\n                    if (dd == 'U') {\n                        x = (bv == -1) ? 0LL : xs[bv] + ws[bv];\n                        y = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (x < xs[j] + ws[j] && xs[j] < x + wi)\n                                y = max(y, ys[j] + hs[j]);\n                    } else {\n                        y = (bv == -1) ? 0LL : ys[bv] + hs[bv];\n                        x = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (y < ys[j] + hs[j] && ys[j] < y + hi)\n                                x = max(x, xs[j] + ws[j]);\n                    }\n                    long long nW = max(W, x + wi);\n                    long long nH = max(H, y + hi);\n                    long long sc;\n                    if (objective == 0) sc = nW + nH;\n                    else if (objective == 1) sc = max(nW, nH);\n                    else if (objective == 2) sc = nW * nH;\n                    else sc = nW + nH + llabs(nW - nH) / 10;\n                    cands[cand_cnt++] = {rot, bv, dd, x, y, wi, hi, sc};\n                }\n            }\n        }\n\n        long long best_sc = cands[0].sc;\n        for (int k = 1; k < cand_cnt; ++k)\n            if (cands[k].sc < best_sc) best_sc = cands[k].sc;\n\n        int idx = 0;\n        if (stochastic) {\n            long long thr = best_sc + max(1LL, best_sc / 50);\n            int good[404], gcnt = 0;\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc <= thr) good[gcnt++] = k;\n            idx = good[rng() % gcnt];\n        } else {\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc == best_sc) { idx = k; break; }\n        }\n\n        const Cand& c = cands[idx];\n        seq.r[i] = c.r; seq.d[i] = c.d; seq.b[i] = c.b;\n        xs[i] = c.x; ys[i] = c.y; ws[i] = c.w; hs[i] = c.h;\n        W = max(W, c.x + c.w);\n        H = max(H, c.y + c.h);\n    }\n    return W + H;\n}\n\n/*------------------------------------------------------------*/\n/*  copy sequence                                              */\ninline void copy_seq(Seq& dst, const Seq& src, int n) {\n    memcpy(dst.r, src.r, n * sizeof(int));\n    memcpy(dst.d, src.d, n * sizeof(char));\n    memcpy(dst.b, src.b, n * sizeof(int));\n}\n\n/*------------------------------------------------------------*/\n/*  exhaustive steepest move at position i (always accepted)   */\ninline void exhaustive_move(Seq& seq, int n,\n                            long long* xs, long long* ys,\n                            long long* ws, long long* hs,\n                            int i, long long& score) {\n    int old_r = seq.r[i], old_b = seq.b[i];\n    char old_d = seq.d[i];\n\n    long long best_sc = score;\n    int best_r = old_r, best_b = old_b;\n    char best_d = old_d;\n\n    for (int rot = 0; rot < 2; ++rot) {\n        for (int di = 0; di < 2; ++di) {\n            char dd = di ? 'L' : 'U';\n            for (int bv = -1; bv < i; ++bv) {\n                seq.r[i] = rot; seq.d[i] = dd; seq.b[i] = bv;\n                long long sc = simulate(seq, n, xs, ys, ws, hs, i);\n                if (sc < best_sc) {\n                    best_sc = sc;\n                    best_r = rot; best_b = bv; best_d = dd;\n                }\n            }\n        }\n    }\n    seq.r[i] = best_r; seq.d[i] = best_d; seq.b[i] = best_b;\n    if (best_sc != score) {\n        score = best_sc;\n        simulate(seq, n, xs, ys, ws, hs, i);\n    }\n}\n\n/*------------------------------------------------------------*/\n/*  random mutation at i (accept only if improves, or rarely)  */\ninline void random_move(Seq& seq, int n,\n                        long long* xs, long long* ys,\n                        long long* ws, long long* hs,\n                        int i, long long& score, mt19937& rng) {\n    int old_r = seq.r[i], old_b = seq.b[i];\n    char old_d = seq.d[i];\n\n    seq.r[i] = rng() & 1;\n    seq.d[i] = (rng() & 1) ? 'L' : 'U';\n    seq.b[i] = (int)(rng() % (i + 1)) - 1;\n\n    long long sc = simulate(seq, n, xs, ys, ws, hs, i);\n    if (sc < score || (rng() & 255) < 3) {   // ~1% chance to accept worsening\n        score = sc;\n    } else {\n        seq.r[i] = old_r; seq.d[i] = old_d; seq.b[i] = old_b;\n    }\n}\n\n/*------------------------------------------------------------*/\n/*  kick: change several random positions                      */\ninline void kick_move(Seq& seq, int n,\n                      long long* xs, long long* ys,\n                      long long* ws, long long* hs,\n                      long long& score, mt19937& rng) {\n    int k = 2 + (int)(rng() % 4);   // change 2..5 positions\n    int min_i = n;\n    for (int t = 0; t < k; ++t) {\n        int i = (int)(rng() % n);\n        min_i = min(min_i, i);\n        seq.r[i] = rng() & 1;\n        seq.d[i] = (rng() & 1) ? 'L' : 'U';\n        seq.b[i] = (int)(rng() % (i + 1)) - 1;\n    }\n    score = simulate(seq, n, xs, ys, ws, hs, min_i);\n}\n\n/*------------------------------------------------------------*/\n/*  local search from `seq` / `score` for `limit_sec` seconds  */\nvoid local_search(Seq& seq, long long& score, double limit_sec,\n                  mt19937& rng) {\n    auto t0 = chrono::steady_clock::now();\n\n    long long xs[100], ys[100], ws[100], hs[100];\n    simulate(seq, N, xs, ys, ws, hs, 0);\n\n    Seq best = seq;\n    long long best_sc = score;\n\n    Seq cur = seq;\n    long long cur_sc = score;\n    long long cx[100], cy[100], cw[100], ch[100];\n    memcpy(cx, xs, sizeof(xs));\n    memcpy(cy, ys, sizeof(ys));\n    memcpy(cw, ws, sizeof(ws));\n    memcpy(ch, hs, sizeof(hs));\n\n    int iter = 0;\n    int no_improve = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - t0).count();\n        if (elapsed >= limit_sec) break;\n\n        int typ = (int)(rng() % 100);\n        if (no_improve > 80 && typ < 15) {\n            /* kick after long stagnation */\n            kick_move(cur, N, cx, cy, cw, ch, cur_sc, rng);\n            if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n            else no_improve = 0;   // reset because we jumped elsewhere\n        } else if (typ < 25) {\n            /* exhaustive steepest move */\n            int i = (int)(rng() % N);\n            exhaustive_move(cur, N, cx, cy, cw, ch, i, cur_sc);\n            if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n            else ++no_improve;\n        } else if (typ < 40) {\n            /* suffix rebuild */\n            int i = (int)(rng() % N);\n            Seq tmp;  copy_seq(tmp, cur, N);\n            long long tx[100], ty[100], tw[100], th[100];\n            memcpy(tx, cx, i * sizeof(long long));\n            memcpy(ty, cy, i * sizeof(long long));\n            memcpy(tw, cw, i * sizeof(long long));\n            memcpy(th, ch, i * sizeof(long long));\n            long long sc = greedy_build(tmp, N, i, (int)(rng() % 4),\n                                        (rng() & 1), rng, tx, ty, tw, th);\n            if (sc < cur_sc || (rng() & 255) < 5) {\n                copy_seq(cur, tmp, N);\n                cur_sc = sc;\n                memcpy(cx, tx, sizeof(tx));\n                memcpy(cy, ty, sizeof(ty));\n                memcpy(cw, tw, sizeof(tw));\n                memcpy(ch, th, sizeof(th));\n                if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n                else ++no_improve;\n            } else {\n                ++no_improve;\n            }\n        } else {\n            /* random mutation */\n            int i = (int)(rng() % N);\n            random_move(cur, N, cx, cy, cw, ch, i, cur_sc, rng);\n            if (cur_sc < best_sc) { best = cur; best_sc = cur_sc; no_improve = 0; }\n            else ++no_improve;\n        }\n        ++iter;\n    }\n    seq = best;\n    score = best_sc;\n}\n\n/*------------------------------------------------------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T >> SIGMA;\n    for (int i = 0; i < N; ++i) cin >> Wobs[i] >> Hobs[i];\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    const double TIME_LIMIT = 2.85;\n    auto start_clock = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_clock).count();\n    };\n\n    /*----- initial deterministic + randomized constructions -----*/\n    long long xs[100], ys[100], ws[100], hs[100];\n    Seq best_seq;\n    long long best_score = LLONG_MAX;\n\n    for (int obj = 0; obj < 4; ++obj) {\n        Seq seq;\n        long long sc = greedy_build(seq, N, 0, obj, false, rng, xs, ys, ws, hs);\n        if (sc < best_score) {\n            best_score = sc;\n            copy_seq(best_seq, seq, N);\n        }\n    }\n    for (int t = 0; t < 30; ++t) {\n        Seq seq;\n        long long sc = greedy_build(seq, N, 0, (int)(rng() % 4), true, rng, xs, ys, ws, hs);\n        if (sc < best_score) {\n            best_score = sc;\n            copy_seq(best_seq, seq, N);\n        }\n    }\n\n    /*----- intensify before first query -----------------------*/\n    double init_time = min(0.45, TIME_LIMIT * 0.15);\n    local_search(best_seq, best_score, init_time, rng);\n\n    long long best_observed = LLONG_MAX;\n    Seq global_best_seq = best_seq;\n\n    double remaining = TIME_LIMIT - elapsed();\n    double per_turn = remaining / max(1, T);\n\n    for (int turn = 0; turn < T; ++turn) {\n        auto turn_start = chrono::steady_clock::now();\n        double turn_budget = min(per_turn * 1.1,\n                                 (TIME_LIMIT - elapsed()) / max(1, T - turn));\n\n        /*-- start from global best and improve --*/\n        Seq cand = global_best_seq;\n        long long cand_sc;\n        {\n            long long tx[100], ty[100], tw[100], th[100];\n            cand_sc = simulate(cand, N, tx, ty, tw, th, 0);\n        }\n        local_search(cand, cand_sc, turn_budget, rng);\n\n        /*-- occasionally also try a fresh random greedy --*/\n        if (turn % 7 == 0) {\n            Seq rnd;\n            long long tx[100], ty[100], tw[100], th[100];\n            long long sc = greedy_build(rnd, N, 0, (int)(rng() % 4), true, rng, tx, ty, tw, th);\n            local_search(rnd, sc, turn_budget * 0.3, rng);\n            if (sc < cand_sc) {\n                cand = rnd;\n                cand_sc = sc;\n            }\n        }\n\n        /*-- output --*/\n        cout << N << '\\n';\n        for (int i = 0; i < N; ++i) {\n            cout << i << ' ' << cand.r[i] << ' ' << cand.d[i] << ' ' << cand.b[i] << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        long long obs = Wp + Hp;\n        if (obs < best_observed) {\n            best_observed = obs;\n            global_best_seq = cand;\n        }\n    }\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, M, H;\n    vector<int> A;\n    vector<vector<int>> adj;\n\n    // current depth state\n    vector<int> d;\n    // sup[v][k] = number of neighbours of v with depth k-1  (1 <= k <= H)\n    vector<array<int, 12>> sup;\n    long long score = 0;\n\n    vector<int> best_d;\n    long long best_score = 0;\n\n    mt19937 rng;\n\n    Solver() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void read_input() {\n        cin >> N >> M >> H;\n        A.resize(N);\n        for (int i = 0; i < N; ++i) cin >> A[i];\n        adj.assign(N, {});\n        for (int i = 0; i < M; ++i) {\n            int u, v; cin >> u >> v;\n            adj[u].push_back(v);\n            adj[v].push_back(u);\n        }\n        // coordinates are irrelevant for the algorithm\n        for (int i = 0; i < N; ++i) {\n            int x, y; cin >> x >> y;\n        }\n        sup.assign(N, {});\n        best_d.resize(N);\n    }\n\n    // set all depths to 0 and compute sup / score\n    void init_state() {\n        d.assign(N, 0);\n        for (int i = 0; i < N; ++i) sup[i].fill(0);\n        for (int v = 0; v < N; ++v) {\n            for (int w : adj[v]) {\n                // w has depth 0, so it supports depth 1\n                sup[v][1]++;\n            }\n        }\n        score = 0;\n        for (int i = 0; i < N; ++i) score += A[i];\n    }\n\n    inline bool can_move(int v, int k) const {\n        if (k == d[v]) return false;\n        if (k > 0 && sup[v][k] == 0) return false;\n        int old = d[v];\n        if (old + 1 <= H) {\n            for (int w : adj[v]) {\n                if (d[w] == old + 1 && sup[w][old + 1] == 1) return false;\n            }\n        }\n        return true;\n    }\n\n    inline void apply_move(int v, int k) {\n        int old = d[v];\n        if (old == k) return;\n        for (int w : adj[v]) {\n            if (old + 1 <= H) sup[w][old + 1]--;\n            if (k + 1 <= H) sup[w][k + 1]++;\n        }\n        score += 1LL * (k - old) * A[v];\n        d[v] = k;\n    }\n\n    void set_state(const vector<int>& nd) {\n        d = nd;\n        score = 0;\n        for (int i = 0; i < N; ++i) {\n            score += 1LL * (d[i] + 1) * A[i];\n            sup[i].fill(0);\n        }\n        for (int v = 0; v < N; ++v) {\n            for (int w : adj[v]) {\n                if (d[w] + 1 <= H) sup[v][d[w] + 1]++;\n            }\n        }\n    }\n\n    inline void save_best() {\n        if (score > best_score) {\n            best_score = score;\n            best_d = d;\n        }\n    }\n\n    // Fast greedy ascent: raise each vertex as much as possible in random order\n    void randomized_ascent() {\n        bool improved = true;\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        while (improved) {\n            improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int v : ord) {\n                int old = d[v];\n                if (old == H) continue;\n                // check whether v is locked by a unique child at old+1\n                bool locked = false;\n                if (old + 1 <= H) {\n                    for (int w : adj[v]) {\n                        if (d[w] == old + 1 && sup[w][old + 1] == 1) {\n                            locked = true;\n                            break;\n                        }\n                    }\n                }\n                if (locked) continue;\n                // best improving move is the largest valid k > old\n                for (int k = H; k > old; --k) {\n                    if (sup[v][k] > 0) {\n                        apply_move(v, k);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    // Simulated annealing on the depth labeling\n    void sa_phase(double deadline, double T0) {\n        double T = T0;\n        const double alpha = 0.99995;\n        const double T_min = 0.01;\n        int last_improve = 0;\n\n        for (int iter = 0; ; ++iter) {\n            double now = (double)clock() / CLOCKS_PER_SEC;\n            if (now >= deadline) break;\n\n            int v = rng() % N;\n            if (adj[v].empty()) continue;\n\n            int k;\n            int r = (int)(rng() % 100);\n            if (r < 10) {\n                k = 0;\n            } else if (r < 30 && d[v] > 0) {\n                k = d[v] - 1;\n            } else {\n                int u = adj[v][rng() % adj[v].size()];\n                k = d[u] + 1;\n                if (k > H) {\n                    if (d[v] > 0) k = d[v] - 1;\n                    else k = 0;\n                }\n            }\n\n            if (!can_move(v, k)) continue;\n\n            long long gain = 1LL * (k - d[v]) * A[v];\n            bool accept = false;\n            if (gain > 0) {\n                accept = true;\n            } else {\n                double prob = exp((double)gain / T);\n                double rnd = (rng() & 0x7FFFFFFF) / 2147483648.0;\n                accept = prob > rnd;\n            }\n\n            if (accept) {\n                apply_move(v, k);\n                if (score > best_score) {\n                    best_score = score;\n                    best_d = d;\n                    last_improve = iter;\n                }\n            }\n\n            T *= alpha;\n            if (T < T_min) T = T_min;\n\n            // reheat if no improvement for a long time\n            if (iter - last_improve > 100000) {\n                // quick polish of current state\n                randomized_ascent();\n                if (score > best_score) {\n                    best_score = score;\n                    best_d = d;\n                    last_improve = iter;\n                }\n                // revert to best known and reheat\n                if (score < best_score) {\n                    set_state(best_d);\n                }\n                T = T0;\n                last_improve = iter;\n            }\n        }\n    }\n\n    vector<int> reconstruct_parents(const vector<int>& depth) {\n        vector<int> parent(N, -1);\n        for (int v = 0; v < N; ++v) {\n            if (depth[v] > 0) {\n                for (int u : adj[v]) {\n                    if (depth[u] == depth[v] - 1) {\n                        parent[v] = u;\n                        break;\n                    }\n                }\n            }\n        }\n        return parent;\n    }\n\n    void solve() {\n        read_input();\n        double TL = 1.90; // leave a safety margin\n\n        // Try a few independent restarts + one long SA run\n        int trial = 0;\n        while ((double)clock() / CLOCKS_PER_SEC < TL) {\n            init_state();\n            randomized_ascent();\n            save_best();\n\n            // Run SA until a short time budget for this trial\n            double sub_deadline = min(TL, (double)clock() / CLOCKS_PER_SEC + 0.15);\n            double T0 = 1000.0; // fixed works well; could scale with best_score\n            sa_phase(sub_deadline, T0);\n\n            // Final polish\n            randomized_ascent();\n            save_best();\n\n            ++trial;\n            if (trial == 1) {\n                // After first trial we already have a decent best_d.\n                // Continue using the remaining time with more restarts.\n            }\n        }\n\n        vector<int> ans = reconstruct_parents(best_d);\n        for (int i = 0; i < N; ++i) {\n            if (i) cout << ' ';\n            cout << ans[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n/* -------------------------------------------------------------\n   Board state (N <= 20, kept as row bitmasks)\n   ------------------------------------------------------------- */\nstruct State {\n    array<unsigned int, 20> oni{}, fuku{};\n    int oni_cnt = 0;\n};\n\n/* -------------------------------------------------------------\n   Non\u2011restoring sweeps (return false if a Fukunokami would fall)\n   ------------------------------------------------------------- */\nbool sweep_L(State &s, int i, int k, int N) {\n    unsigned int dm = (1u << k) - 1;\n    if (s.fuku[i] & dm) return false;\n    s.oni_cnt -= __builtin_popcount(s.oni[i] & dm);\n    s.oni[i] >>= k;\n    s.fuku[i] >>= k;\n    return true;\n}\nbool sweep_R(State &s, int i, int k, int N) {\n    unsigned int keep = (1u << (N - k)) - 1;\n    unsigned int dm   = (~keep) & ((1u << N) - 1);\n    if (s.fuku[i] & dm) return false;\n    s.oni_cnt -= __builtin_popcount(s.oni[i] & dm);\n    s.oni[i] = (s.oni[i] & keep) << k;\n    s.fuku[i] = (s.fuku[i] & keep) << k;\n    return true;\n}\nbool sweep_U(State &s, int j, int k, int N) {\n    unsigned int fcol = 0, ocol = 0;\n    for (int i = 0; i < N; ++i) {\n        if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n        if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n    }\n    unsigned int dm = (1u << k) - 1;\n    if (fcol & dm) return false;\n    s.oni_cnt -= __builtin_popcount(ocol & dm);\n    for (int i = 0; i < N - k; ++i) {\n        unsigned int vo = (s.oni[i + k] >> j) & 1u;\n        unsigned int vf = (s.fuku[i + k] >> j) & 1u;\n        s.oni[i]  = (s.oni[i]  & ~(1u << j)) | (vo << j);\n        s.fuku[i] = (s.fuku[i] & ~(1u << j)) | (vf << j);\n    }\n    for (int i = N - k; i < N; ++i) {\n        s.oni[i]  &= ~(1u << j);\n        s.fuku[i] &= ~(1u << j);\n    }\n    return true;\n}\nbool sweep_D(State &s, int j, int k, int N) {\n    unsigned int fcol = 0, ocol = 0;\n    for (int i = 0; i < N; ++i) {\n        if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n        if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n    }\n    unsigned int keep = (1u << (N - k)) - 1;\n    unsigned int dm   = (~keep) & ((1u << N) - 1);\n    if (fcol & dm) return false;\n    s.oni_cnt -= __builtin_popcount(ocol & dm);\n    for (int i = N - 1; i >= k; --i) {\n        unsigned int vo = (s.oni[i - k] >> j) & 1u;\n        unsigned int vf = (s.fuku[i - k] >> j) & 1u;\n        s.oni[i]  = (s.oni[i]  & ~(1u << j)) | (vo << j);\n        s.fuku[i] = (s.fuku[i] & ~(1u << j)) | (vf << j);\n    }\n    for (int i = 0; i < k; ++i) {\n        s.oni[i]  &= ~(1u << j);\n        s.fuku[i] &= ~(1u << j);\n    }\n    return true;\n}\n\n/* -------------------------------------------------------------\n   Fast feasibility test: every remaining Oni has at least one\n   safe restoring direction on the current board?\n   ------------------------------------------------------------- */\nbool feasible_for_exact(const State &s, int N) {\n    unsigned int all_mask = (1u << N) - 1;\n    for (int i = 0; i < N; ++i) {\n        unsigned int m = s.oni[i];\n        while (m) {\n            int j = __builtin_ctz(m);\n            bool ok = false;\n            if ((s.fuku[i] & ((1u << (j + 1)) - 1)) == 0) ok = true;\n            unsigned int rmask = (~((1u << j) - 1)) & all_mask;\n            if ((s.fuku[i] & rmask) == 0) ok = true;\n            bool up_ok = true;\n            for (int r = 0; r <= i; ++r)\n                if (s.fuku[r] >> j & 1u) { up_ok = false; break; }\n            if (up_ok) ok = true;\n            bool down_ok = true;\n            for (int r = i; r < N; ++r)\n                if (s.fuku[r] >> j & 1u) { down_ok = false; break; }\n            if (down_ok) ok = true;\n            if (!ok) return false;\n            m &= m - 1;\n        }\n    }\n    return true;\n}\n\n/* -------------------------------------------------------------\n   Exact solver for restoring blocks (minimum cost set cover)\n   ------------------------------------------------------------- */\nstruct Block {\n    uint64_t mask;\n    int cost;\n    char dir;\n    int idx;\n    int k;\n};\n\nstatic vector<Block> g_blocks;\nstatic vector<int> g_sol;\n\nint exact_cost(const State &s, int N) {\n    // CRITICAL: clear globals first so that M==0 does not leave stale data\n    g_blocks.clear();\n    g_sol.clear();\n\n    int id_of[20][20];\n    memset(id_of, -1, sizeof(id_of));\n    vector<pair<int,int>> onis;\n    for (int i = 0; i < N; ++i) {\n        unsigned int m = s.oni[i];\n        while (m) {\n            int j = __builtin_ctz(m);\n            id_of[i][j] = (int)onis.size();\n            onis.emplace_back(i, j);\n            m &= m - 1;\n        }\n    }\n    int M = (int)onis.size();\n    if (M == 0) return 0;\n    const uint64_t FULL = (M == 64) ? ~0ULL : ((1ULL << M) - 1ULL);\n\n    vector<Block> ops;\n    auto add = [&](uint64_t mask, int cost, char d, int idx, int k) {\n        if (mask) ops.push_back({mask, cost, d, idx, k});\n    };\n\n    // rows\n    for (int i = 0; i < N; ++i) {\n        int L = N, R = -1;\n        unsigned int fm = s.fuku[i];\n        if (fm) {\n            L = __builtin_ctz(fm);\n            R = 31 - __builtin_clz(fm);\n        }\n        uint64_t m = 0;\n        for (int j = 0; j < L; ++j)\n            if (s.oni[i] >> j & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (j + 1), 'L', i, j + 1);\n            }\n        m = 0;\n        for (int j = N - 1; j > R; --j)\n            if (s.oni[i] >> j & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (N - j), 'R', i, N - j);\n            }\n    }\n    // columns\n    for (int j = 0; j < N; ++j) {\n        unsigned int fcol = 0, ocol = 0;\n        for (int i = 0; i < N; ++i) {\n            if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n            if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n        }\n        int T = N, Bot = -1;\n        if (fcol) {\n            T  = __builtin_ctz(fcol);\n            Bot = 31 - __builtin_clz(fcol);\n        }\n        uint64_t m = 0;\n        for (int i = 0; i < T; ++i)\n            if (ocol >> i & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (i + 1), 'U', j, i + 1);\n            }\n        m = 0;\n        for (int i = N - 1; i > Bot; --i)\n            if (ocol >> i & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (N - i), 'D', j, N - i);\n            }\n    }\n\n    // dominance pruning\n    vector<Block> pruned;\n    for (auto &op : ops) {\n        bool dominated = false;\n        for (auto &p : pruned)\n            if ((p.mask | op.mask) == p.mask && p.cost <= op.cost) {\n                dominated = true; break;\n            }\n        if (dominated) continue;\n        vector<Block> nxt;\n        for (auto &p : pruned)\n            if (!((op.mask | p.mask) == op.mask && op.cost <= p.cost))\n                nxt.push_back(p);\n        nxt.push_back(op);\n        pruned.swap(nxt);\n    }\n    ops.swap(pruned);\n    int S = (int)ops.size();\n\n    vector<vector<int>> cover(M);\n    for (int i = 0; i < S; ++i) {\n        uint64_t m = ops[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            cover[b].push_back(i);\n            m &= m - 1;\n        }\n    }\n\n    for (int o = 0; o < M; ++o)\n        if (cover[o].empty()) return INF;\n\n    // greedy upper bound\n    int greedy_cost = 0;\n    uint64_t uncovered = FULL;\n    vector<int> greedy_sol;\n    while (uncovered) {\n        int best = -1;\n        double best_r = 1e300;\n        for (int i = 0; i < S; ++i) {\n            uint64_t nw = ops[i].mask & uncovered;\n            int cnt = __builtin_popcountll(nw);\n            if (cnt == 0) continue;\n            double r = (double)ops[i].cost / cnt;\n            if (r < best_r) { best_r = r; best = i; }\n        }\n        if (best == -1) return INF;\n        greedy_cost += ops[best].cost;\n        uncovered &= ~ops[best].mask;\n        greedy_sol.push_back(best);\n    }\n\n    int best_cost = greedy_cost;\n    vector<int> best_sol = greedy_sol;\n\n    unordered_map<uint64_t, int> memo;\n    memo.reserve(200000);\n\n    function<void(uint64_t,int,vector<int>&)> dfs = [&](uint64_t unc, int cur, vector<int> &vec) {\n        if (unc == 0) {\n            if (cur < best_cost) {\n                best_cost = cur;\n                best_sol = vec;\n            }\n            return;\n        }\n        if (cur >= best_cost) return;\n        auto it = memo.find(unc);\n        if (it != memo.end() && it->second <= cur) return;\n        memo[unc] = cur;\n\n        int lb = cur;\n        uint64_t tmp = unc;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int mn = INF;\n            for (int id : cover[o])\n                if (ops[id].mask & unc) mn = min(mn, ops[id].cost);\n            if (mn == INF) return;\n            lb += mn;\n            if (lb >= best_cost) return;\n            tmp &= tmp - 1;\n        }\n\n        int target = -1, mindeg = INT_MAX;\n        tmp = unc;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int deg = 0;\n            for (int id : cover[o]) if (ops[id].mask & unc) ++deg;\n            if (deg < mindeg) { mindeg = deg; target = o; }\n            tmp &= tmp - 1;\n        }\n\n        vector<pair<int,int>> cands;\n        for (int id : cover[target])\n            if (ops[id].mask & unc) cands.emplace_back(ops[id].cost, id);\n        sort(cands.begin(), cands.end());\n        for (auto &[c, id] : cands) {\n            if (cur + c >= best_cost) continue;\n            vec.push_back(id);\n            dfs(unc & ~ops[id].mask, cur + c, vec);\n            vec.pop_back();\n        }\n    };\n\n    vector<int> vec;\n    dfs(FULL, 0, vec);\n\n    // remove redundant blocks\n    vector<int> sol = best_sol;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < sol.size(); ++i) {\n            uint64_t u = 0;\n            for (size_t j = 0; j < sol.size(); ++j)\n                if (j != i) u |= ops[sol[j]].mask;\n            if ((u & FULL) == FULL) {\n                sol.erase(sol.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    g_blocks = ops;\n    g_sol = sol;\n    int total = 0;\n    for (int id : sol) total += ops[id].cost;\n    return total;\n}\n\n/* emit restoring moves for the last exact_cost() call */\nvoid exact_seq(vector<pair<char,int>> &out) {\n    for (int id : g_sol) {\n        const Block &op = g_blocks[id];\n        for (int t = 0; t < op.k; ++t) out.emplace_back(op.dir, op.idx);\n        char rev = 0;\n        if (op.dir == 'L') rev = 'R';\n        else if (op.dir == 'R') rev = 'L';\n        else if (op.dir == 'U') rev = 'D';\n        else rev = 'U';\n        for (int t = 0; t < op.k; ++t) out.emplace_back(rev, op.idx);\n    }\n}\n\n/* -------------------------------------------------------------\n   Generate all safe non\u2011restoring sweeps on a state\n   ------------------------------------------------------------- */\nstruct Cand { char d; int idx, k, cnt; };\n\nvector<Cand> gen_cands(const State &s, int N) {\n    vector<Cand> c;\n    unsigned int all = (1u << N) - 1;\n    for (int i = 0; i < N; ++i) {\n        unsigned int orow = s.oni[i], frow = s.fuku[i];\n        int L = N, R = -1;\n        if (frow) {\n            L = __builtin_ctz(frow);\n            R = 31 - __builtin_clz(frow);\n        }\n        for (int j = 0; j < L; ++j)\n            if (orow >> j & 1u) {\n                int k = j + 1;\n                int cnt = __builtin_popcount(orow & ((1u << k) - 1));\n                if (cnt) c.push_back({'L', i, k, cnt});\n            }\n        for (int j = N - 1; j > R; --j)\n            if (orow >> j & 1u) {\n                int k = N - j;\n                int cnt = __builtin_popcount(orow >> j);\n                if (cnt) c.push_back({'R', i, k, cnt});\n            }\n    }\n    for (int j = 0; j < N; ++j) {\n        unsigned int fcol = 0, ocol = 0;\n        for (int i = 0; i < N; ++i) {\n            if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n            if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n        }\n        int T = N, Bot = -1;\n        if (fcol) {\n            T  = __builtin_ctz(fcol);\n            Bot = 31 - __builtin_clz(fcol);\n        }\n        for (int i = 0; i < T; ++i)\n            if (ocol >> i & 1u) {\n                int k = i + 1;\n                int cnt = __builtin_popcount(ocol & ((1u << k) - 1));\n                if (cnt) c.push_back({'U', j, k, cnt});\n            }\n        for (int i = N - 1; i > Bot; --i)\n            if (ocol >> i & 1u) {\n                int k = N - i;\n                int cnt = __builtin_popcount(ocol >> i);\n                if (cnt) c.push_back({'D', j, k, cnt});\n            }\n    }\n    return c;\n}\n\n/* -------------------------------------------------------------\n   Build the pure safe solution (restoring blocks only)\n   ------------------------------------------------------------- */\nvector<pair<char,int>> pure_safe(const vector<string> &B) {\n    int N = (int)B.size();\n    State init;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { init.oni[i] |= 1u << j; ++init.oni_cnt; }\n            else if (B[i][j] == 'o') init.fuku[i] |= 1u << j;\n        }\n    exact_cost(init, N);\n    vector<pair<char,int>> moves;\n    exact_seq(moves);\n    return moves;\n}\n\n/* -------------------------------------------------------------\n   Main\n   ------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> B(N);\n    for (int i = 0; i < N; ++i) cin >> B[i];\n\n    // fallback solution (always valid)\n    vector<pair<char,int>> fallback = pure_safe(B);\n\n    State cur;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { cur.oni[i] |= 1u << j; ++cur.oni_cnt; }\n            else if (B[i][j] == 'o') cur.fuku[i] |= 1u << j;\n        }\n\n    vector<pair<char,int>> answer;\n\n    // 1\u2011ply exact\u2011lookahead greedy (non\u2011restoring)\n    while (cur.oni_cnt > 0) {\n        int finish_now = exact_cost(cur, N);\n        if (finish_now >= INF) break; // should not happen on feasible board\n\n        vector<Cand> cands = gen_cands(cur, N);\n        int best_total = finish_now;\n        Cand best{0,0,0,0};\n        bool found = false;\n\n        for (const auto &c : cands) {\n            if (c.k >= finish_now) continue;          // cannot improve\n            State nxt = cur;\n            bool ok = false;\n            if (c.d == 'L') ok = sweep_L(nxt, c.idx, c.k, N);\n            else if (c.d == 'R') ok = sweep_R(nxt, c.idx, c.k, N);\n            else if (c.d == 'U') ok = sweep_U(nxt, c.idx, c.k, N);\n            else ok = sweep_D(nxt, c.idx, c.k, N);\n            if (!ok) continue;\n            if (!feasible_for_exact(nxt, N)) continue;\n            int rem = exact_cost(nxt, N);\n            if (rem >= INF) continue;\n            int total = c.k + rem;\n            if (total < best_total) {\n                best_total = total;\n                best = c;\n                found = true;\n            }\n        }\n\n        if (!found) break; // no improving non\u2011restoring sweep\n\n        // apply best\n        if (best.d == 'L') sweep_L(cur, best.idx, best.k, N);\n        else if (best.d == 'R') sweep_R(cur, best.idx, best.k, N);\n        else if (best.d == 'U') sweep_U(cur, best.idx, best.k, N);\n        else sweep_D(cur, best.idx, best.k, N);\n\n        for (int t = 0; t < best.k; ++t)\n            answer.emplace_back(best.d, best.idx);\n    }\n\n    // append optimal restoring tail for whatever remains\n    if (cur.oni_cnt > 0) {\n        int tail = exact_cost(cur, N);\n        if (tail < INF) exact_seq(answer);\n        else answer = fallback; // emergency fallback\n    }\n\n    // safety checks\n    if ((int)answer.size() > 4 * N * N) answer = fallback;\n\n    for (auto &p : answer)\n        cout << p.first << ' ' << p.second << '\\n';\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) return 0;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    vector<double> p(N);\n    for (int i = 0; i < N; ++i) p[i] = (double)T[i] / (double)L;\n\n    /*------------------------------------------------------------\n        Phase 1 : greedy init + fast proxy local search\n      ------------------------------------------------------------*/\n    vector<int> a(N), b(N);\n    vector<double> in(N, 0.0);\n\n    auto pick_best_deficit = [&]() {\n        int best = 0;\n        double bestDef = -1e100;\n        for (int i = 0; i < N; ++i) {\n            double def = p[i] - in[i];\n            if (def > bestDef) {\n                bestDef = def;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (int j = 0; j < N; ++j) {\n        int u = pick_best_deficit();\n        a[j] = u;\n        in[u] += p[j] * 0.5;\n        int v = pick_best_deficit();\n        b[j] = v;\n        in[v] += p[j] * 0.5;\n    }\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto proxy_delta = [&](int j, int typ, int newv) -> double {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return 0.0;\n        double d = 0.0;\n        double afterOld = in[oldv] - p[j] * 0.5;\n        d += fabs(afterOld - p[oldv]) - fabs(in[oldv] - p[oldv]);\n        double afterNew = in[newv] + p[j] * 0.5;\n        d += fabs(afterNew - p[newv]) - fabs(in[newv] - p[newv]);\n        return d;\n    };\n\n    auto apply_proxy = [&](int j, int typ, int newv) {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return;\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ) b[j] = newv;\n        else     a[j] = newv;\n    };\n\n    for (int iter = 0; iter < 500000; ++iter) {\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int newv = (int)(rng() % N);\n        double d = proxy_delta(j, typ, newv);\n        if (d < -1e-12) {\n            apply_proxy(j, typ, newv);\n        }\n    }\n\n    /*------------------------------------------------------------\n        Phase 2 : simulation + SA with proxy-guided neighbours\n      ------------------------------------------------------------*/\n    vector<array<uint8_t,2>> nxt(N);\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = (uint8_t)b[i];\n        nxt[i][1] = (uint8_t)a[i];\n    }\n\n    vector<int> simCnt(N);\n    auto simulate_fill = [&]() -> int {\n        fill(simCnt.begin(), simCnt.end(), 0);\n        uint8_t cur = 0;\n        simCnt[0] = 1;\n        for (int step = 1; step < L; ++step) {\n            cur = nxt[cur][simCnt[cur] & 1];\n            ++simCnt[cur];\n        }\n        int err = 0;\n        for (int i = 0; i < N; ++i) err += abs(simCnt[i] - T[i]);\n        return err;\n    };\n\n    int bestE = simulate_fill();\n    vector<int> bestA = a, bestB = b;\n    int curE = bestE;\n\n    vector<int> diff(N);\n    for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n\n    double temp = max(100.0, (double)bestE * 0.2);\n    const double COOL = 0.9995;\n    int iter = 0, lastBestIter = 0;\n\n    auto curTime = [&]() {\n        return (double)clock() / (double)CLOCKS_PER_SEC;\n    };\n\n    while (curTime() < 1.85) {\n        ++iter;\n\n        /*--- kick when stuck ------------------------------------*/\n        if (iter - lastBestIter > 150) {\n            a = bestA; b = bestB;\n            fill(in.begin(), in.end(), 0.0);\n            for (int j = 0; j < N; ++j) {\n                in[a[j]] += p[j] * 0.5;\n                in[b[j]] += p[j] * 0.5;\n            }\n            for (int k = 0; k < 5; ++k) {\n                int jj = (int)(rng() % N);\n                int tt = (int)(rng() % 2);\n                int nv = (int)(rng() % N);\n                apply_proxy(jj, tt, nv);\n            }\n            for (int i = 0; i < N; ++i) {\n                nxt[i][0] = (uint8_t)b[i];\n                nxt[i][1] = (uint8_t)a[i];\n            }\n            curE = simulate_fill();\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n            if (curE < bestE) {\n                bestE = curE;\n                bestA = a; bestB = b;\n                lastBestIter = iter;\n            }\n            temp = max(100.0, (double)curE * 0.2);\n            continue;\n        }\n\n        /*--- choose a neighbour ---------------------------------*/\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int oldv = typ ? b[j] : a[j];\n        int newv = oldv;\n\n        int mode = (int)(rng() % 4);\n        if (mode < 2) {                     // exploitation : best proxy\n            double bestD = 1e100;\n            for (int v = 0; v < N; ++v) {\n                if (v == oldv) continue;\n                double d = proxy_delta(j, typ, v);\n                if (d < bestD) {\n                    bestD = d;\n                    newv = v;\n                }\n            }\n            if (newv == oldv) continue;\n        } else if (mode == 2) {             // pure random\n            newv = (int)(rng() % N);\n            if (newv == oldv) continue;\n        } else {                            // targeted by diff\n            vector<int> over, under;\n            for (int i = 0; i < N; ++i) {\n                if (diff[i] > 0) over.push_back(i);\n                else if (diff[i] < 0) under.push_back(i);\n            }\n            if (over.empty() || under.empty()) {\n                newv = (int)(rng() % N);\n                if (newv == oldv) continue;\n            } else {\n                int to = over[(int)(rng() % over.size())];\n                vector<pair<int,int>> preds;\n                for (int x = 0; x < N; ++x) {\n                    if (a[x] == to) preds.emplace_back(x, 0);\n                    if (b[x] == to) preds.emplace_back(x, 1);\n                }\n                if (preds.empty()) {\n                    newv = (int)(rng() % N);\n                    if (newv == oldv) continue;\n                } else {\n                    auto pr = preds[(int)(rng() % preds.size())];\n                    j = pr.first;\n                    typ = pr.second;\n                    oldv = typ ? b[j] : a[j];\n                    newv = under[(int)(rng() % under.size())];\n                    if (newv == oldv) continue;\n                }\n            }\n        }\n\n        /*--- apply and simulate ---------------------------------*/\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ == 0) {\n            a[j] = newv;\n            nxt[j][1] = (uint8_t)newv;\n        } else {\n            b[j] = newv;\n            nxt[j][0] = (uint8_t)newv;\n        }\n\n        int newE = simulate_fill();\n        bool accept = false;\n\n        if (newE < bestE) {\n            bestE = newE;\n            bestA = a; bestB = b;\n            lastBestIter = iter;\n            accept = true;\n        }\n        if (!accept) {\n            int dE = newE - curE;\n            if (dE <= 0) {\n                accept = true;\n            } else {\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < exp(-dE / temp)) accept = true;\n            }\n        }\n\n        if (accept) {\n            curE = newE;\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n        } else {\n            // revert\n            in[newv] -= p[j] * 0.5;\n            in[oldv] += p[j] * 0.5;\n            if (typ == 0) {\n                a[j] = oldv;\n                nxt[j][1] = (uint8_t)oldv;\n            } else {\n                b[j] = oldv;\n                nxt[j][0] = (uint8_t)oldv;\n            }\n        }\n        temp *= COOL;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\n/* ---------- Morton key for 2\u2011D locality ---------- */\nstatic uint64_t expand_bits(uint32_t x) {\n    uint64_t z = 0;\n    for (int i = 0; i < 15; ++i)                 // x \u2264 20000 < 2^15\n        z |= ((uint64_t)((x >> i) & 1U)) << (2 * i);\n    return z;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    /* estimated centres */\n    vector<double> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) * 0.5;\n        cy[i] = (ly[i] + ry[i]) * 0.5;\n    }\n\n    /* estimated distances */\n    vector<vector<double>> est(N, vector<double>(N));\n    for (int i = 0; i < N; ++i) {\n        est[i][i] = 0.0;\n        for (int j = i + 1; j < N; ++j) {\n            double dx = cx[i] - cx[j];\n            double dy = cy[i] - cy[j];\n            double d = sqrt(dx * dx + dy * dy);\n            est[i][j] = est[j][i] = d;\n        }\n    }\n\n    auto morton = [&](int v) -> uint64_t {\n        uint32_t x = (uint32_t)(lx[v] + rx[v]);\n        uint32_t y = (uint32_t)(ly[v] + ry[v]);\n        return expand_bits(x) | (expand_bits(y) << 1);\n    };\n\n    /* -------------------------------------------------\n       4. build a compact partition\n       ------------------------------------------------- */\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) {\n             if (G[a] != G[b]) return G[a] > G[b];\n             return a < b;\n         });\n\n    vector<vector<int>> group_nodes(M);\n    vector<char> assigned(N, 0);\n    vector<int> unassigned;\n    unassigned.reserve(N);\n    for (int i = 0; i < N; ++i) unassigned.push_back(i);\n\n    auto mst_cost = [&](const vector<int> &nodes) -> double {\n        int g = (int)nodes.size();\n        if (g <= 1) return 0.0;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        double total = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            total += mincost[v];\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) mincost[i] = d;\n            }\n        }\n        return total;\n    };\n\n    /* large groups (size >= 3) */\n    for (int idx : order) {\n        int g = G[idx];\n        if (g < 3) continue;\n        int U = (int)unassigned.size();\n        int K = min(20, U);\n        vector<int> best_cluster;\n        double best_cost = 1e100;\n        for (int s = 0; s < K; ++s) {\n            int seed = unassigned[s * U / K];\n            vector<int> cluster;\n            cluster.reserve(g);\n            cluster.push_back(seed);\n            vector<char> in_cluster(N, 0);\n            in_cluster[seed] = 1;\n            vector<double> d(N, 1e100);\n            for (int v : unassigned) if (v != seed) d[v] = est[seed][v];\n            while ((int)cluster.size() < g) {\n                int best_u = -1;\n                double best_du = 1e100;\n                for (int v : unassigned) {\n                    if (in_cluster[v]) continue;\n                    if (d[v] < best_du) {\n                        best_du = d[v];\n                        best_u = v;\n                    }\n                }\n                cluster.push_back(best_u);\n                in_cluster[best_u] = 1;\n                for (int v : unassigned) if (!in_cluster[v]) {\n                    double nd = est[best_u][v];\n                    if (nd < d[v]) d[v] = nd;\n                }\n            }\n            double cost = mst_cost(cluster);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_cluster = move(cluster);\n            }\n        }\n        group_nodes[idx] = best_cluster;\n        for (int v : best_cluster) assigned[v] = 1;\n        vector<int> nxt;\n        nxt.reserve(unassigned.size() - g);\n        for (int v : unassigned) if (!assigned[v]) nxt.push_back(v);\n        unassigned.swap(nxt);\n    }\n\n    /* pairs (size == 2) */\n    vector<int> pair_idx;\n    for (int idx : order) if (G[idx] == 2) pair_idx.push_back(idx);\n    for (int idx : pair_idx) {\n        int U = (int)unassigned.size();\n        double best_d = 1e100;\n        int best_a = -1, best_b = -1;\n        for (int i = 0; i < U; ++i)\n            for (int j = i + 1; j < U; ++j) {\n                double d = est[unassigned[i]][unassigned[j]];\n                if (d < best_d) {\n                    best_d = d;\n                    best_a = i;\n                    best_b = j;\n                }\n            }\n        int a = unassigned[best_a];\n        int b = unassigned[best_b];\n        group_nodes[idx] = {a, b};\n        assigned[a] = assigned[b] = 1;\n        vector<int> nxt;\n        nxt.reserve(U - 2);\n        for (int i = 0; i < U; ++i)\n            if (i != best_a && i != best_b) nxt.push_back(unassigned[i]);\n        unassigned.swap(nxt);\n    }\n\n    /* singles (size == 1) */\n    vector<int> single_idx;\n    for (int idx : order) if (G[idx] == 1) single_idx.push_back(idx);\n    for (int idx : single_idx) {\n        int v = unassigned.back(); unassigned.pop_back();\n        group_nodes[idx] = {v};\n        assigned[v] = 1;\n    }\n\n    /* -------------------------------------------------\n       5. query allocation\n       ------------------------------------------------- */\n    vector<int> alloc(M, 0);\n    int sum_alloc = 0;\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (g > L) alloc[k] = (g - 1 + L - 2) / (L - 1);   // ceil((g-1)/(L-1))\n        else if (g >= 3) alloc[k] = 1;\n        else alloc[k] = 0;\n        sum_alloc += alloc[k];\n    }\n    int surplus = Q - sum_alloc;\n    if (surplus > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) if (G[k] > L) large.push_back(k);\n        sort(large.begin(), large.end(),\n             [&](int a, int b) { return G[a] > G[b]; });\n        while (surplus > 0) {\n            bool changed = false;\n            for (int k : large) {\n                int max_q = G[k] - L + 1;\n                if (alloc[k] < max_q) {\n                    ++alloc[k];\n                    --surplus;\n                    changed = true;\n                    if (surplus == 0) break;\n                }\n            }\n            if (!changed) break;\n        }\n    }\n\n    /* helper: reorder a group by a DFS walk of its estimated MST */\n    auto mst_order = [&](const vector<int> &nodes) -> vector<int> {\n        int g = (int)nodes.size();\n        if (g <= 1) return nodes;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<int> parent(g, -1);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) {\n                    mincost[i] = d;\n                    parent[i] = v;\n                }\n            }\n        }\n        vector<vector<int>> adj(g);\n        for (int i = 1; i < g; ++i) {\n            adj[i].push_back(parent[i]);\n            adj[parent[i]].push_back(i);\n        }\n        vector<int> ord;\n        ord.reserve(g);\n        stack<int> st;\n        st.push(0);\n        vector<char> vis(g, 0);\n        vis[0] = 1;\n        while (!st.empty()) {\n            int u = st.top(); st.pop();\n            ord.push_back(nodes[u]);\n            for (int v : adj[u]) if (!vis[v]) {\n                vis[v] = 1;\n                st.push(v);\n            }\n        }\n        return ord;\n    };\n\n    /* -------------------------------------------------\n       6. perform queries\n       ------------------------------------------------- */\n    vector<vector<pair<int,int>>> raw_edges(M);\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (alloc[k] == 0) continue;\n        auto &nodes = group_nodes[k];\n        if (g > L) {\n            nodes = mst_order(nodes);               // locality ordering\n            int q = alloc[k];\n            for (int i = 0; i < q; ++i) {\n                int start = (int)((long long)i * (g - L) / (q - 1));\n                cout << \"? \" << L;\n                for (int j = 0; j < L; ++j) cout << ' ' << nodes[start + j];\n                cout << '\\n' << flush;\n                for (int j = 0; j < L - 1; ++j) {\n                    int a, b;  cin >> a >> b;\n                    raw_edges[k].push_back({a, b});\n                }\n            }\n        } else {\n            // 3 <= g <= L\n            cout << \"? \" << g;\n            for (int v : nodes) cout << ' ' << v;\n            cout << '\\n' << flush;\n            for (int i = 0; i < g - 1; ++i) {\n                int a, b;  cin >> a >> b;\n                raw_edges[k].push_back({a, b});\n            }\n        }\n    }\n\n    /* -------------------------------------------------\n       7. output answer\n       ------------------------------------------------- */\n    cout << \"!\\n\";\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        const auto &nodes = group_nodes[k];\n        for (int i = 0; i < g; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n\n        if (g <= 1) {\n            continue;\n        } else if (g == 2) {\n            cout << nodes[0] << ' ' << nodes[1] << '\\n';\n        } else if (g <= L) {\n            for (auto &e : raw_edges[k])\n                cout << e.first << ' ' << e.second << '\\n';\n        } else {\n            // build graph from queried edges\n            vector<int> pos(N, -1);\n            for (int i = 0; i < g; ++i) pos[nodes[i]] = i;\n            vector<vector<int>> adj(g);\n            set<pair<int,int>> seen;\n            for (auto &e : raw_edges[k]) {\n                int u = e.first, v = e.second;\n                if (u > v) swap(u, v);\n                if (!seen.insert({u, v}).second) continue;\n                int iu = pos[u], iv = pos[v];\n                if (iu == -1 || iv == -1) continue;\n                adj[iu].push_back(iv);\n                adj[iv].push_back(iu);\n            }\n            vector<char> vis(g, 0);\n            vector<pair<int,int>> tree;\n            stack<int> st;\n            st.push(0);  vis[0] = 1;\n            while (!st.empty()) {\n                int u = st.top(); st.pop();\n                for (int v : adj[u]) if (!vis[v]) {\n                    vis[v] = 1;\n                    tree.push_back({nodes[u], nodes[v]});\n                    st.push(v);\n                }\n            }\n            if ((int)tree.size() != g - 1) {\n                // fallback: estimated MST\n                tree.clear();\n                const double INF = 1e100;\n                vector<double> mincost(g, INF);\n                vector<int> parent(g, -1);\n                vector<char> used(g, 0);\n                mincost[0] = 0.0;\n                for (int it = 0; it < g; ++it) {\n                    int v = -1;\n                    for (int i = 0; i < g; ++i)\n                        if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n                    used[v] = 1;\n                    if (parent[v] != -1)\n                        tree.push_back({nodes[parent[v]], nodes[v]});\n                    for (int i = 0; i < g; ++i) if (!used[i]) {\n                        double d = est[nodes[v]][nodes[i]];\n                        if (d < mincost[i]) {\n                            mincost[i] = d;\n                            parent[i] = v;\n                        }\n                    }\n                }\n            }\n            for (auto &e : tree)\n                cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\nconst int MAXN = 20;\nconst int MAX_ACTIONS = 1600; // 2 * N * M = 1600\n\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dname[4] = {'U', 'D', 'L', 'R'};\n\ninline int opp(int d) { return d ^ 1; }\n\nint N, M;\nvector<pair<int,int>> pts;\nusing Grid = array<array<char, MAXN>, MAXN>;\nGrid blocks;\narray<array<int, MAXN>, MAXN> target_id;\nvector<pair<char,char>> ans;\n\n/*---------- fast distance-only BFS (directed graph) ----------*/\nint bfs_dist(int sr, int sc, int tr, int tc, const Grid& blk) {\n    if (sr == tr && sc == tc) return 0;\n    array<array<int,MAXN>,MAXN> dist;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dist[i][j] = INF;\n\n    queue<pair<int,int>> q;\n    dist[sr][sc] = 0;\n    q.emplace(sr, sc);\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        int d = dist[r][c];\n\n        // Move edges\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (blk[nr][nc]) continue;\n            if (dist[nr][nc] > d + 1) {\n                if (nr == tr && nc == tc) return d + 1;\n                dist[nr][nc] = d + 1;\n                q.emplace(nr, nc);\n            }\n        }\n\n        // Slide edges\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            while (nr >= 0 && nr < N && nc >= 0 && nc < N && !blk[nr][nc]) {\n                nr += dr[dir];\n                nc += dc[dir];\n            }\n            int rr = nr - dr[dir];\n            int cc = nc - dc[dir];\n            if (rr == r && cc == c) continue;\n            if (dist[rr][cc] > d + 1) {\n                if (rr == tr && cc == tc) return d + 1;\n                dist[rr][cc] = d + 1;\n                q.emplace(rr, cc);\n            }\n        }\n    }\n    return INF;\n}\n\n/*---------- full BFS with parent storage ----------*/\nvoid bfs_full(int sr, int sc, const Grid& blk,\n              array<array<int,MAXN>,MAXN>& dist,\n              array<array<pair<int,int>,MAXN>,MAXN>& par,\n              array<array<char,MAXN>,MAXN>& act,\n              array<array<char,MAXN>,MAXN>& dirc)\n{\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dist[i][j] = INF;\n\n    queue<pair<int,int>> q;\n    dist[sr][sc] = 0;\n    par[sr][sc] = {-1, -1};\n    act[sr][sc] = 0;\n    dirc[sr][sc] = 0;\n    q.emplace(sr, sc);\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        int d = dist[r][c];\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (blk[nr][nc]) continue;\n            if (dist[nr][nc] > d + 1) {\n                dist[nr][nc] = d + 1;\n                par[nr][nc] = {r, c};\n                act[nr][nc] = 'M';\n                dirc[nr][nc] = dname[dir];\n                q.emplace(nr, nc);\n            }\n        }\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            while (nr >= 0 && nr < N && nc >= 0 && nc < N && !blk[nr][nc]) {\n                nr += dr[dir];\n                nc += dc[dir];\n            }\n            int rr = nr - dr[dir];\n            int cc = nc - dc[dir];\n            if (rr == r && cc == c) continue;\n            if (dist[rr][cc] > d + 1) {\n                dist[rr][cc] = d + 1;\n                par[rr][cc] = {r, c};\n                act[rr][cc] = 'S';\n                dirc[rr][cc] = dname[dir];\n                q.emplace(rr, cc);\n            }\n        }\n    }\n}\n\n/*---------- reconstruct path from (sr,sc) to (gr,gc) ----------*/\nvector<pair<char,char>> reconstruct(int sr, int sc, int gr, int gc,\n                                    const array<array<pair<int,int>,MAXN>,MAXN>& par,\n                                    const array<array<char,MAXN>,MAXN>& act,\n                                    const array<array<char,MAXN>,MAXN>& dirc)\n{\n    vector<pair<char,char>> res;\n    int r = gr, c = gc;\n    while (r != sr || c != sc) {\n        res.push_back({act[r][c], dirc[r][c]});\n        auto [pr, pc] = par[r][c];\n        r = pr; c = pc;\n        if (r == -1 && c == -1) break;\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\n/*============================================================*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N >> M)) return 0;\n    pts.resize(M);\n    for (int i = 0; i < M; ++i) cin >> pts[i].first >> pts[i].second;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            blocks[i][j] = 0;\n            target_id[i][j] = -1;\n        }\n    for (int i = 0; i < M; ++i)\n        target_id[pts[i].first][pts[i].second] = i;\n\n    ans.clear();\n    int cur_r = pts[0].first;\n    int cur_c = pts[0].second;\n\n    for (int t = 1; t < M; ++t) {\n        int tr = pts[t].first;\n        int tc = pts[t].second;\n\n        // 1. Baseline BFS from current position\n        array<array<int,MAXN>,MAXN> dist0;\n        array<array<pair<int,int>,MAXN>,MAXN> par0;\n        array<array<char,MAXN>,MAXN> act0, dirc0;\n        bfs_full(cur_r, cur_c, blocks, dist0, par0, act0, dirc0);\n\n        // Baseline future cost (t -> t+1)\n        int base_future = 0;\n        if (t + 1 < M) {\n            base_future = bfs_dist(tr, tc, pts[t+1].first, pts[t+1].second, blocks);\n        }\n\n        int best_cost;\n        if (dist0[tr][tc] >= INF || base_future >= INF) best_cost = INF;\n        else best_cost = dist0[tr][tc] + base_future;\n\n        int best_sr = -1, best_sc = -1, best_pr = -1, best_pc = -1;\n        char best_alter_dir = 0;\n        bool best_is_remove = false;\n\n        auto evaluate = [&](const Grid& blk2, int sr, int sc, bool is_remove) {\n            // BFS from target in the modified grid to check future reachability\n            array<array<int,MAXN>,MAXN> dist_t2;\n            array<array<pair<int,int>,MAXN>,MAXN> par_t2;\n            array<array<char,MAXN>,MAXN> act_t2, dirc_t2;\n            bfs_full(tr, tc, blk2, dist_t2, par_t2, act_t2, dirc_t2);\n\n            for (int k = t + 1; k < M; ++k) {\n                if (dist_t2[pts[k].first][pts[k].second] >= INF) return;\n            }\n\n            int future_cost = 0;\n            if (t + 1 < M) {\n                future_cost = dist_t2[pts[t+1].first][pts[t+1].second];\n                if (future_cost >= INF) return;\n            }\n\n            for (int pd = 0; pd < 4; ++pd) {\n                int pr = sr + dr[pd];\n                int pc = sc + dc[pd];\n                if (pr < 0 || pr >= N || pc < 0 || pc >= N) continue;\n                if (blk2[pr][pc]) continue;          // must stand on an empty cell\n                if (pr == tr && pc == tc) continue;  // altering from target is wasteful\n                if (dist0[pr][pc] >= INF) continue;  // unreachable in original grid\n\n                int d_pt = bfs_dist(pr, pc, tr, tc, blk2);\n                if (d_pt >= INF) continue;\n\n                int cur_len = dist0[pr][pc] + 1 + d_pt;\n                if ((int)ans.size() + cur_len > MAX_ACTIONS) continue;\n\n                int total = cur_len + future_cost;\n                if (total < best_cost) {\n                    best_cost = total;\n                    best_sr = sr; best_sc = sc;\n                    best_pr = pr; best_pc = pc;\n                    best_alter_dir = dname[opp(pd)];\n                    best_is_remove = is_remove;\n                }\n            }\n        };\n\n        // 2. Try placing a new block\n        for (int sr = 0; sr < N; ++sr) {\n            for (int sc = 0; sc < N; ++sc) {\n                if (blocks[sr][sc]) continue;\n                if (sr == tr && sc == tc) continue;\n                if (target_id[sr][sc] > t) continue; // do not block a future target\n                Grid blk2 = blocks;\n                blk2[sr][sc] = 1;\n                evaluate(blk2, sr, sc, false);\n            }\n        }\n\n        // 3. Try removing an existing block\n        for (int sr = 0; sr < N; ++sr) {\n            for (int sc = 0; sc < N; ++sc) {\n                if (!blocks[sr][sc]) continue;\n                if (target_id[sr][sc] > t) continue; // safety\n                Grid blk2 = blocks;\n                blk2[sr][sc] = 0;\n                evaluate(blk2, sr, sc, true);\n            }\n        }\n\n        // 4. Execute the best option\n        if (best_sr == -1) {\n            // Baseline\n            auto path = reconstruct(cur_r, cur_c, tr, tc, par0, act0, dirc0);\n            for (auto &ac : path) ans.push_back(ac);\n        } else {\n            // cur -> P\n            auto path1 = reconstruct(cur_r, cur_c, best_pr, best_pc, par0, act0, dirc0);\n            for (auto &ac : path1) ans.push_back(ac);\n            // Alter\n            ans.push_back({'A', best_alter_dir});\n            // Update permanent block map\n            if (best_is_remove) blocks[best_sr][best_sc] = 0;\n            else               blocks[best_sr][best_sc] = 1;\n            // P -> target\n            array<array<int,MAXN>,MAXN> distP;\n            array<array<pair<int,int>,MAXN>,MAXN> parP;\n            array<array<char,MAXN>,MAXN> actP, dircP;\n            bfs_full(best_pr, best_pc, blocks, distP, parP, actP, dircP);\n            auto path2 = reconstruct(best_pr, best_pc, tr, tc, parP, actP, dircP);\n            for (auto &ac : path2) ans.push_back(ac);\n        }\n\n        cur_r = tr;\n        cur_c = tc;\n    }\n\n    for (auto &ac : ans) {\n        cout << ac.first << ' ' << ac.second << '\\n';\n    }\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nint n;\nvector<int> X, Y, desiredR;\nvector<int> a, b, c, d;\nvector<ll> area;\nvector<double> pval;\ndouble cur_score = 0.0;\ndouble best_score = -1.0;\nvector<int> best_a, best_b, best_c, best_d;\n\nchrono::steady_clock::time_point g_start;\n\ninline double calc_p(int idx, ll s) {\n    if (s <= 0) return 0.0;\n    double t = (s < desiredR[idx]) ? (double)s / desiredR[idx] : (double)desiredR[idx] / s;\n    return 1.0 - (1.0 - t) * (1.0 - t);\n}\n\npair<int,int> get_range(int i, int side) {\n    int Lo = 0, Hi = 10000;\n    if (side == 0) {\n        Lo = 0;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) Lo = max(Lo, c[j]);\n        }\n        Hi = X[i];\n    } else if (side == 1) {\n        Lo = X[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) Hi = min(Hi, a[j]);\n        }\n    } else if (side == 2) {\n        Lo = 0;\n        Hi = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) Lo = max(Lo, d[j]);\n        }\n    } else {\n        Lo = Y[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) Hi = min(Hi, b[j]);\n        }\n    }\n    return {Lo, Hi};\n}\n\npair<int,int> get_range_ignore(int i, int side, int ign) {\n    int Lo = 0, Hi = 10000;\n    if (side == 0) {\n        Lo = 0;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) Lo = max(Lo, c[j]);\n        }\n        Hi = X[i];\n    } else if (side == 1) {\n        Lo = X[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) Hi = min(Hi, a[j]);\n        }\n    } else if (side == 2) {\n        Lo = 0;\n        Hi = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) Lo = max(Lo, d[j]);\n        }\n    } else {\n        Lo = Y[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) Hi = min(Hi, b[j]);\n        }\n    }\n    return {Lo, Hi};\n}\n\ninline int get_cur(int i, int side) {\n    return side == 0 ? a[i] : (side == 1 ? c[i] : (side == 2 ? b[i] : d[i]));\n}\n\ninline int get_opt1d(int i, int side, int Lo, int Hi) {\n    int opt;\n    if (side == 0) {\n        ll h = d[i] - b[i];\n        int w = max(1, (int)round((double)desiredR[i] / (double)h));\n        opt = c[i] - w;\n    } else if (side == 1) {\n        ll h = d[i] - b[i];\n        int w = max(1, (int)round((double)desiredR[i] / (double)h));\n        opt = a[i] + w;\n    } else if (side == 2) {\n        ll w = c[i] - a[i];\n        int h = max(1, (int)round((double)desiredR[i] / (double)w));\n        opt = d[i] - h;\n    } else {\n        ll w = c[i] - a[i];\n        int h = max(1, (int)round((double)desiredR[i] / (double)w));\n        opt = b[i] + h;\n    }\n    if (opt < Lo) opt = Lo;\n    if (opt > Hi) opt = Hi;\n    return opt;\n}\n\ninline void apply_single(int i, int side, int v) {\n    if (side == 0) a[i] = v;\n    else if (side == 1) c[i] = v;\n    else if (side == 2) b[i] = v;\n    else d[i] = v;\n    ll na = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np;\n    area[i] = na;\n}\n\ninline bool overlap_others(int i, int na, int nb, int nc, int nd) {\n    for (int j = 0; j < n; ++j) if (j != i) {\n        if (max(na, a[j]) < min(nc, c[j]) && max(nb, b[j]) < min(nd, d[j])) return true;\n    }\n    return false;\n}\n\ninline void apply_corner(int i, int corner, int v1, int v2) {\n    if (corner == 0) { c[i] = v1; d[i] = v2; }\n    else if (corner == 1) { a[i] = v1; d[i] = v2; }\n    else if (corner == 2) { c[i] = v1; b[i] = v2; }\n    else { a[i] = v1; b[i] = v2; }\n    ll na = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np;\n    area[i] = na;\n}\n\nvoid save_best() {\n    if (cur_score > best_score) {\n        best_score = cur_score;\n        best_a = a; best_b = b; best_c = c; best_d = d;\n    }\n}\n\nvoid restore_best() {\n    a = best_a; b = best_b; c = best_c; d = best_d;\n    cur_score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        area[i] = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n        pval[i] = calc_p(i, area[i]);\n        cur_score += pval[i];\n    }\n}\n\nvoid reset_1x1() {\n    for (int i = 0; i < n; ++i) {\n        a[i] = X[i]; b[i] = Y[i]; c[i] = X[i] + 1; d[i] = Y[i] + 1;\n        area[i] = 1;\n        pval[i] = calc_p(i, 1);\n    }\n    cur_score = 0.0;\n    for (int i = 0; i < n; ++i) cur_score += pval[i];\n}\n\nvoid greedy_single_pass(const vector<int>& ord) {\n    for (int i : ord) {\n        double best_delta = 1e-12;\n        int best_side = -1, best_v = -1;\n        for (int side = 0; side < 4; ++side) {\n            auto [Lo, Hi] = get_range(i, side);\n            int cur = get_cur(i, side);\n            int opt = get_opt1d(i, side, Lo, Hi);\n            if (opt == cur) continue;\n            ll na;\n            if (side == 0) na = 1LL * (c[i] - opt) * (d[i] - b[i]);\n            else if (side == 1) na = 1LL * (opt - a[i]) * (d[i] - b[i]);\n            else if (side == 2) na = 1LL * (c[i] - a[i]) * (d[i] - opt);\n            else na = 1LL * (c[i] - a[i]) * (opt - b[i]);\n            double np = calc_p(i, na);\n            double delta = np - pval[i];\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_side = side;\n                best_v = opt;\n            }\n        }\n        if (best_side != -1) apply_single(i, best_side, best_v);\n    }\n}\n\nvoid greedy_single_pass_rng(mt19937_64& rng) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    shuffle(ord.begin(), ord.end(), rng);\n    greedy_single_pass(ord);\n}\n\nvector<int> ord_by_p_asc() {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int x, int y){ return pval[x] < pval[y]; });\n    return ord;\n}\n\nvoid greedy_init_fast(mt19937_64& rng, int max_pass) {\n    for (int pass = 0; pass < max_pass; ++pass) {\n        double old = cur_score;\n        greedy_single_pass_rng(rng);\n        if (cur_score <= old + 1e-9) break;\n    }\n}\n\nvoid greedy_init_full(const vector<int>& ord) {\n    for (int pass = 0; pass < 100; ++pass) {\n        double old = cur_score;\n        greedy_single_pass(ord);\n        if (cur_score <= old + 1e-9) break;\n    }\n}\n\n// ---------- corner evaluation ----------\ntuple<double,int,int> eval_corner(int i, int corner) {\n    if (corner == 0) { // TR: c,d\n        auto [cL, cR] = get_range(i, 1);\n        if (cL >= cR) return {-1.0, -1, -1};\n        vector<int> cvals = {cL, cR};\n        int csq = a[i] + max(1, (int)round(sqrt((double)desiredR[i])));\n        int copt = a[i] + max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (csq > cL && csq < cR) cvals.push_back(csq);\n        if (copt > cL && copt < cR) cvals.push_back(copt);\n        sort(cvals.begin(), cvals.end());\n        cvals.erase(unique(cvals.begin(), cvals.end()), cvals.end());\n        double best_delta = -1.0;\n        int best_c = -1, best_d = -1;\n        for (int cc : cvals) {\n            int old_c = c[i]; c[i] = cc;\n            auto [dL, dR] = get_range(i, 3);\n            c[i] = old_c;\n            if (dL > dR) continue;\n            int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n            vector<int> dvals = {dL, dR, clamp(dtgt, dL, dR)};\n            sort(dvals.begin(), dvals.end());\n            dvals.erase(unique(dvals.begin(), dvals.end()), dvals.end());\n            for (int dd : dvals) {\n                if (overlap_others(i, a[i], b[i], cc, dd)) continue;\n                ll na = 1LL * (cc - a[i]) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_c = cc; best_d = dd;\n                }\n            }\n        }\n        return {best_delta, best_c, best_d};\n    } else if (corner == 1) { // TL: a,d\n        auto [aL, aR] = get_range(i, 0);\n        if (aL >= aR) return {-1.0, -1, -1};\n        vector<int> avals = {aL, aR};\n        int asq = c[i] - max(1, (int)round(sqrt((double)desiredR[i])));\n        int aopt = c[i] - max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (asq > aL && asq < aR) avals.push_back(asq);\n        if (aopt > aL && aopt < aR) avals.push_back(aopt);\n        sort(avals.begin(), avals.end());\n        avals.erase(unique(avals.begin(), avals.end()), avals.end());\n        double best_delta = -1.0;\n        int best_a2 = -1, best_d2 = -1;\n        for (int aa : avals) {\n            int old_a = a[i]; a[i] = aa;\n            auto [dL, dR] = get_range(i, 3);\n            a[i] = old_a;\n            if (dL > dR) continue;\n            int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n            vector<int> dvals = {dL, dR, clamp(dtgt, dL, dR)};\n            sort(dvals.begin(), dvals.end());\n            dvals.erase(unique(dvals.begin(), dvals.end()), dvals.end());\n            for (int dd : dvals) {\n                if (overlap_others(i, aa, b[i], c[i], dd)) continue;\n                ll na = 1LL * (c[i] - aa) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_a2 = aa; best_d2 = dd;\n                }\n            }\n        }\n        return {best_delta, best_a2, best_d2};\n    } else if (corner == 2) { // BR: c,b\n        auto [cL, cR] = get_range(i, 1);\n        if (cL >= cR) return {-1.0, -1, -1};\n        vector<int> cvals = {cL, cR};\n        int csq = a[i] + max(1, (int)round(sqrt((double)desiredR[i])));\n        int copt = a[i] + max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (csq > cL && csq < cR) cvals.push_back(csq);\n        if (copt > cL && copt < cR) cvals.push_back(copt);\n        sort(cvals.begin(), cvals.end());\n        cvals.erase(unique(cvals.begin(), cvals.end()), cvals.end());\n        double best_delta = -1.0;\n        int best_c = -1, best_b2 = -1;\n        for (int cc : cvals) {\n            int old_c = c[i]; c[i] = cc;\n            auto [bL, bR] = get_range(i, 2);\n            c[i] = old_c;\n            if (bL > bR) continue;\n            int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n            vector<int> bvals = {bL, bR, clamp(btgt, bL, bR)};\n            sort(bvals.begin(), bvals.end());\n            bvals.erase(unique(bvals.begin(), bvals.end()), bvals.end());\n            for (int bb : bvals) {\n                if (overlap_others(i, a[i], bb, cc, d[i])) continue;\n                ll na = 1LL * (cc - a[i]) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_c = cc; best_b2 = bb;\n                }\n            }\n        }\n        return {best_delta, best_c, best_b2};\n    } else { // BL: a,b\n        auto [aL, aR] = get_range(i, 0);\n        if (aL >= aR) return {-1.0, -1, -1};\n        vector<int> avals = {aL, aR};\n        int asq = c[i] - max(1, (int)round(sqrt((double)desiredR[i])));\n        int aopt = c[i] - max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (asq > aL && asq < aR) avals.push_back(asq);\n        if (aopt > aL && aopt < aR) avals.push_back(aopt);\n        sort(avals.begin(), avals.end());\n        avals.erase(unique(avals.begin(), avals.end()), avals.end());\n        double best_delta = -1.0;\n        int best_a2 = -1, best_b2 = -1;\n        for (int aa : avals) {\n            int old_a = a[i]; a[i] = aa;\n            auto [bL, bR] = get_range(i, 2);\n            a[i] = old_a;\n            if (bL > bR) continue;\n            int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n            vector<int> bvals = {bL, bR, clamp(btgt, bL, bR)};\n            sort(bvals.begin(), bvals.end());\n            bvals.erase(unique(bvals.begin(), bvals.end()), bvals.end());\n            for (int bb : bvals) {\n                if (overlap_others(i, aa, bb, c[i], d[i])) continue;\n                ll na = 1LL * (c[i] - aa) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_a2 = aa; best_b2 = bb;\n                }\n            }\n        }\n        return {best_delta, best_a2, best_b2};\n    }\n}\n\nvoid greedy_corner_pass(const vector<int>& ord) {\n    for (int i : ord) {\n        double best_delta = 1e-12;\n        int best_corner = -1, best_v1 = -1, best_v2 = -1;\n        for (int corner = 0; corner < 4; ++corner) {\n            auto [delta, v1, v2] = eval_corner(i, corner);\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_corner = corner;\n                best_v1 = v1; best_v2 = v2;\n            }\n        }\n        if (best_corner != -1) apply_corner(i, best_corner, best_v1, best_v2);\n    }\n}\n\nvoid greedy_corner_pass_rng(mt19937_64& rng) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    shuffle(ord.begin(), ord.end(), rng);\n    greedy_corner_pass(ord);\n}\n\n// ---------- pair wall ----------\nint find_neighbor(int i, int dir) {\n    int best = -1;\n    int best_gap = 100000;\n    for (int j = 0; j < n; ++j) if (j != i) {\n        bool xov = (a[j] < c[i] && c[j] > a[i]);\n        bool yov = (b[j] < d[i] && d[j] > b[i]);\n        if (dir == 0 && yov && c[j] <= a[i]) {\n            int gap = a[i] - c[j];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 1 && yov && a[j] >= c[i]) {\n            int gap = a[j] - c[i];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 2 && xov && d[j] <= b[i]) {\n            int gap = b[i] - d[j];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 3 && xov && b[j] >= d[i]) {\n            int gap = b[j] - d[i];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        }\n    }\n    return (best_gap == 0) ? best : -1;\n}\n\ntuple<double,int> eval_pair_wall(int i, int dir, int j) {\n    int Lo, Hi;\n    if (dir == 0) {\n        auto r1 = get_range_ignore(i, 0, j);\n        auto r2 = get_range_ignore(j, 1, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else if (dir == 1) {\n        auto r1 = get_range_ignore(i, 1, j);\n        auto r2 = get_range_ignore(j, 0, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else if (dir == 2) {\n        auto r1 = get_range_ignore(i, 2, j);\n        auto r2 = get_range_ignore(j, 3, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else {\n        auto r1 = get_range_ignore(i, 3, j);\n        auto r2 = get_range_ignore(j, 2, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    }\n    if (Lo > Hi) return {-1.0, Lo};\n    vector<int> cand = {Lo, Hi};\n    if (dir <= 1) {\n        int x1 = a[i] + (int)round((double)desiredR[i] / (double)(d[i] - b[i]));\n        int x2 = c[j] - (int)round((double)desiredR[j] / (double)(d[j] - b[j]));\n        cand.push_back(clamp(x1, Lo, Hi));\n        cand.push_back(clamp(x2, Lo, Hi));\n        cand.push_back((Lo + Hi) / 2);\n    } else {\n        int y1 = b[i] + (int)round((double)desiredR[i] / (double)(c[i] - a[i]));\n        int y2 = d[j] - (int)round((double)desiredR[j] / (double)(c[j] - a[j]));\n        cand.push_back(clamp(y1, Lo, Hi));\n        cand.push_back(clamp(y2, Lo, Hi));\n        cand.push_back((Lo + Hi) / 2);\n    }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    double best_sc = -1e300;\n    int best_coord = Lo;\n    for (int v : cand) {\n        double g = 0.0;\n        if (dir <= 1) {\n            ll ai = 1LL * ((dir==0 ? (c[i]-v) : (v-a[i]))) * (d[i]-b[i]);\n            ll aj = 1LL * ((dir==0 ? (v-a[j]) : (c[j]-v))) * (d[j]-b[j]);\n            g = calc_p(i, ai) + calc_p(j, aj);\n        } else {\n            ll ai = 1LL * (c[i]-a[i]) * ((dir==2 ? (d[i]-v) : (v-b[i])));\n            ll aj = 1LL * (c[j]-a[j]) * ((dir==2 ? (v-b[j]) : (d[j]-v)));\n            g = calc_p(i, ai) + calc_p(j, aj);\n        }\n        if (g > best_sc) {\n            best_sc = g;\n            best_coord = v;\n        }\n    }\n    double delta = best_sc - (pval[i] + pval[j]);\n    return {delta, best_coord};\n}\n\ninline void apply_pair_wall(int i, int dir, int j, int v) {\n    if (dir == 0) { a[i] = v; c[j] = v; }\n    else if (dir == 1) { c[i] = v; a[j] = v; }\n    else if (dir == 2) { b[i] = v; d[j] = v; }\n    else { d[i] = v; b[j] = v; }\n    ll na = 1LL * (c[i]-a[i]) * (d[i]-b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np; area[i] = na;\n    ll na2 = 1LL * (c[j]-a[j]) * (d[j]-b[j]);\n    double np2 = calc_p(j, na2);\n    cur_score += np2 - pval[j];\n    pval[j] = np2; area[j] = na2;\n}\n\nvoid greedy_pair_pass(mt19937_64& rng) {\n    vector<pair<int,int>> vec;\n    for (int i = 0; i < n; ++i) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int j = find_neighbor(i, dir);\n            if (j >= 0) vec.emplace_back(i, dir);\n        }\n    }\n    shuffle(vec.begin(), vec.end(), rng);\n    for (auto [i, dir] : vec) {\n        int j = find_neighbor(i, dir);\n        if (j < 0) continue;\n        auto [delta, v] = eval_pair_wall(i, dir, j);\n        if (delta > 1e-12) apply_pair_wall(i, dir, j, v);\n    }\n}\n\n// ---------- SA ----------\nvoid run_sa(mt19937_64& rng, double time_limit) {\n    uniform_real_distribution<double> dist01(0.0, 1.0);\n    long long iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 2047) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - g_start).count();\n            if (elapsed > time_limit) break;\n        }\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - g_start).count();\n        double T = 0.08 * pow(1e-5 / 0.08, elapsed / time_limit);\n\n        int i;\n        if (dist01(rng) < 0.30) {\n            vector<int> low;\n            for (int k = 0; k < n; ++k) if (pval[k] < 0.95) low.push_back(k);\n            if (low.empty()) i = (int)(rng() % n);\n            else i = low[(int)(rng() % low.size())];\n        } else {\n            i = (int)(rng() % n);\n        }\n\n        int mtype = (int)(rng() % 100);\n        if (mtype < 70) {\n            // single-side move\n            int side = (int)(rng() % 4);\n            auto [Lo, Hi] = get_range(i, side);\n            if (Lo >= Hi) continue;\n            int cur = get_cur(i, side);\n            int opt = get_opt1d(i, side, Lo, Hi);\n            int nv;\n            double r = dist01(rng);\n            if (r < 0.5) nv = opt;\n            else if (r < 0.8) {\n                int delta = (int)(dist01(rng) * 201) - 100;\n                nv = opt + delta;\n            } else {\n                nv = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n            }\n            if (nv < Lo) nv = Lo;\n            if (nv > Hi) nv = Hi;\n            if (nv == cur) continue;\n            ll na;\n            if (side == 0) na = 1LL * (c[i] - nv) * (d[i] - b[i]);\n            else if (side == 1) na = 1LL * (nv - a[i]) * (d[i] - b[i]);\n            else if (side == 2) na = 1LL * (c[i] - a[i]) * (d[i] - nv);\n            else na = 1LL * (c[i] - a[i]) * (nv - b[i]);\n            double np = calc_p(i, na);\n            double delta = np - pval[i];\n            if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                apply_single(i, side, nv);\n                save_best();\n            }\n        } else if (mtype < 85) {\n            // pair-wall move\n            int dir = (int)(rng() % 4);\n            int j = find_neighbor(i, dir);\n            if (j < 0) continue;\n            auto [delta, v] = eval_pair_wall(i, dir, j);\n            if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                apply_pair_wall(i, dir, j, v);\n                save_best();\n            }\n        } else {\n            // corner-resize move\n            int corner = (int)(rng() % 4);\n            if (corner == 0) { // TR: c,d\n                auto [Lo, Hi] = get_range(i, 1);\n                if (Lo >= Hi) continue;\n                int cc = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_c = c[i]; c[i] = cc;\n                auto [dL, dR] = get_range(i, 3);\n                c[i] = old_c;\n                if (dL > dR) continue;\n                int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n                int dd = dtgt;\n                if (dd < dL) dd = dL;\n                if (dd > dR) dd = dR;\n                if (dist01(rng) < 0.5) dd = dL + (int)(dist01(rng) * (dR - dL + 1));\n                if (overlap_others(i, a[i], b[i], cc, dd)) continue;\n                ll na = 1LL * (cc - a[i]) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 0, cc, dd);\n                    save_best();\n                }\n            } else if (corner == 1) { // TL: a,d\n                auto [Lo, Hi] = get_range(i, 0);\n                if (Lo >= Hi) continue;\n                int aa = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_a = a[i]; a[i] = aa;\n                auto [dL, dR] = get_range(i, 3);\n                a[i] = old_a;\n                if (dL > dR) continue;\n                int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n                int dd = dtgt;\n                if (dd < dL) dd = dL;\n                if (dd > dR) dd = dR;\n                if (dist01(rng) < 0.5) dd = dL + (int)(dist01(rng) * (dR - dL + 1));\n                if (overlap_others(i, aa, b[i], c[i], dd)) continue;\n                ll na = 1LL * (c[i] - aa) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 1, aa, dd);\n                    save_best();\n                }\n            } else if (corner == 2) { // BR: c,b\n                auto [Lo, Hi] = get_range(i, 1);\n                if (Lo >= Hi) continue;\n                int cc = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_c = c[i]; c[i] = cc;\n                auto [bL, bR] = get_range(i, 2);\n                c[i] = old_c;\n                if (bL > bR) continue;\n                int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n                int bb = btgt;\n                if (bb < bL) bb = bL;\n                if (bb > bR) bb = bR;\n                if (dist01(rng) < 0.5) bb = bL + (int)(dist01(rng) * (bR - bL + 1));\n                if (overlap_others(i, a[i], bb, cc, d[i])) continue;\n                ll na = 1LL * (cc - a[i]) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 2, cc, bb);\n                    save_best();\n                }\n            } else { // BL: a,b\n                auto [Lo, Hi] = get_range(i, 0);\n                if (Lo >= Hi) continue;\n                int aa = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_a = a[i]; a[i] = aa;\n                auto [bL, bR] = get_range(i, 2);\n                a[i] = old_a;\n                if (bL > bR) continue;\n                int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n                int bb = btgt;\n                if (bb < bL) bb = bL;\n                if (bb > bR) bb = bR;\n                if (dist01(rng) < 0.5) bb = bL + (int)(dist01(rng) * (bR - bL + 1));\n                if (overlap_others(i, aa, bb, c[i], d[i])) continue;\n                ll na = 1LL * (c[i] - aa) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 3, aa, bb);\n                    save_best();\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n;\n    X.resize(n); Y.resize(n); desiredR.resize(n);\n    for (int i = 0; i < n; ++i) cin >> X[i] >> Y[i] >> desiredR[i];\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n    area.resize(n); pval.resize(n);\n\n    mt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    g_start = chrono::steady_clock::now();\n\n    best_score = -1.0;\n\n    // 1 deterministic start by descending area\n    vector<int> ord_desc(n);\n    iota(ord_desc.begin(), ord_desc.end(), 0);\n    sort(ord_desc.begin(), ord_desc.end(),\n         [&](int x, int y){ return desiredR[x] > desiredR[y]; });\n    reset_1x1();\n    greedy_init_full(ord_desc);\n    save_best();\n\n    // many fast random restarts\n    for (int trial = 0; trial < 60; ++trial) {\n        reset_1x1();\n        greedy_init_fast(rng, 5);\n        save_best();\n    }\n    restore_best();\n\n    // SA\n    run_sa(rng, 4.92);\n    restore_best();\n\n    // Final polish: ordered by ascending p_i\n    for (int pass = 0; pass < 100; ++pass) {\n        double old = cur_score;\n        vector<int> ord = ord_by_p_asc();\n        greedy_single_pass(ord);\n        greedy_corner_pass(ord);\n        greedy_pair_pass(rng);\n        if (cur_score <= old + 1e-9) break;\n    }\n    save_best();\n    restore_best();\n\n    for (int i = 0; i < n; ++i) {\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int H = 50, W = 50, N = 2500;\n\nint cell_tile[N];\nint cell_val[N];\nint nxt_cell[N][4];\nunsigned char used[2500];\nunsigned char deg[N];\nint tile_cell[2500][2];\nunsigned char tile_cell_cnt[2500];\n\n/* fast 64-bit LCG */\nstatic uint64_t fstate;\ninline uint32_t fnoise() {\n    fstate = fstate * 6364136223846793005ULL + 1442695040888963407ULL;\n    return (uint32_t)(fstate >> 33) & 127u;\n}\n\ninline void mark_tile(int t) {\n    used[t] = 1;\n    for (int k = 0; k < tile_cell_cnt[t]; ++k) {\n        int c = tile_cell[t][k];\n        int n0 = nxt_cell[c][0]; if (n0 != -1) deg[n0]--;\n        int n1 = nxt_cell[c][1]; if (n1 != -1) deg[n1]--;\n        int n2 = nxt_cell[c][2]; if (n2 != -1) deg[n2]--;\n        int n3 = nxt_cell[c][3]; if (n3 != -1) deg[n3]--;\n    }\n}\n\ninline void unmark_tile(int t) {\n    used[t] = 0;\n    for (int k = 0; k < tile_cell_cnt[t]; ++k) {\n        int c = tile_cell[t][k];\n        int n0 = nxt_cell[c][0]; if (n0 != -1) deg[n0]++;\n        int n1 = nxt_cell[c][1]; if (n1 != -1) deg[n1]++;\n        int n2 = nxt_cell[c][2]; if (n2 != -1) deg[n2]++;\n        int n3 = nxt_cell[c][3]; if (n3 != -1) deg[n3]++;\n    }\n}\n\n/* Rollout from start_pos.  The tile at start_pos is assumed NOT marked yet.\n   Returns sum of values collected AFTER start_pos. */\ninline int simulate(int start_pos, int dw, int vw, bool noise) {\n    int stack[2500];\n    int sp = 0;\n    int t0 = cell_tile[start_pos];\n    mark_tile(t0);\n    stack[sp++] = t0;\n    int cur = start_pos;\n    int gain = 0;\n\n    while (true) {\n        int best_nxt = -1;\n        int best_pri = -1000000000;\n\n        for (int d = 0; d < 4; ++d) {\n            int np = nxt_cell[cur][d];\n            if (np == -1) continue;\n            int nt = cell_tile[np];\n            if (used[nt]) continue;\n\n            int d_np = deg[np];\n            int bad = 0;\n            for (int d2 = 0; d2 < 4; ++d2) {\n                int w = nxt_cell[np][d2];\n                if (w == -1) continue;\n                int tw = cell_tile[w];\n                if (tw == nt) continue;\n                if (used[tw]) continue;\n                int dw2 = deg[w];\n                if (dw2 == 1) bad += 5;       // strands w's tile completely\n                else if (dw2 == 2) bad += 1;  // turns w's tile into a dead-end\n            }\n\n            int pri = cell_val[np] * vw;\n            if (d_np == 0) pri -= 500000;\n            else pri -= d_np * dw + bad * 10000;\n            if (noise) pri += (int)fnoise();\n\n            if (pri > best_pri) {\n                best_pri = pri;\n                best_nxt = np;\n            }\n        }\n\n        if (best_nxt == -1) break;\n        int nt = cell_tile[best_nxt];\n        mark_tile(nt);\n        stack[sp++] = nt;\n        gain += cell_val[best_nxt];\n        cur = best_nxt;\n    }\n\n    while (sp > 0) unmark_tile(stack[--sp]);\n    return gain;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    int M = 0;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int x; cin >> x;\n            cell_tile[i * W + j] = x;\n            M = max(M, x + 1);\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> cell_val[i * W + j];\n        }\n    }\n\n    for (int i = 0; i < M; ++i) tile_cell_cnt[i] = 0;\n    for (int c = 0; c < N; ++c) {\n        int t = cell_tile[c];\n        tile_cell[t][tile_cell_cnt[t]++] = c;\n    }\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            nxt_cell[id][0] = (i > 0)     ? id - W : -1;\n            nxt_cell[id][1] = (i + 1 < H) ? id + W : -1;\n            nxt_cell[id][2] = (j > 0)     ? id - 1 : -1;\n            nxt_cell[id][3] = (j + 1 < W) ? id + 1 : -1;\n        }\n    }\n\n    const char dch[4] = {'U', 'D', 'L', 'R'};\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    string best_path;\n    int best_score = -1;\n\n    for (int iter = 0; ; ++iter) {\n        if (elapsed() > 1.97) break;\n\n        bool noise = (iter > 0);\n        int dw, vw;\n        if (iter == 0) {\n            dw = 1000;\n            vw = 1;\n            fstate = 123456789ULL;\n        } else {\n            dw = 100 + (int)(rng() % 1900);\n            vw = (int)(rng() % 25);\n            fstate = ((uint64_t)rng() << 32) | (uint64_t)rng();\n        }\n\n        memset(used, 0, M);\n        for (int c = 0; c < N; ++c) {\n            int tc = cell_tile[c];\n            int d = 0;\n            int n0 = nxt_cell[c][0]; if (n0 != -1 && cell_tile[n0] != tc) ++d;\n            int n1 = nxt_cell[c][1]; if (n1 != -1 && cell_tile[n1] != tc) ++d;\n            int n2 = nxt_cell[c][2]; if (n2 != -1 && cell_tile[n2] != tc) ++d;\n            int n3 = nxt_cell[c][3]; if (n3 != -1 && cell_tile[n3] != tc) ++d;\n            deg[c] = (unsigned char)d;\n        }\n\n        int pos = si * W + sj;\n        mark_tile(cell_tile[pos]);\n        int cur_score = cell_val[pos];\n        string path;\n        path.reserve(2500);\n\n        while (true) {\n            int cand_pos[4];\n            int cand_dir[4];\n            int cand_cnt = 0;\n            for (int d = 0; d < 4; ++d) {\n                int np = nxt_cell[pos][d];\n                if (np != -1 && !used[cell_tile[np]]) {\n                    cand_pos[cand_cnt] = np;\n                    cand_dir[cand_cnt] = d;\n                    ++cand_cnt;\n                }\n            }\n            if (cand_cnt == 0) break;\n\n            int best_eval = -1;\n            int best_idx = 0;\n            if (cand_cnt == 1) {\n                best_idx = 0;\n            } else {\n                for (int i = 0; i < cand_cnt; ++i) {\n                    int future = simulate(cand_pos[i], dw, vw, noise);\n                    int eval = cell_val[cand_pos[i]] + future;\n                    if (noise) eval += (int)fnoise();\n                    if (eval > best_eval) {\n                        best_eval = eval;\n                        best_idx = i;\n                    }\n                }\n            }\n\n            int np = cand_pos[best_idx];\n            int nd = cand_dir[best_idx];\n            mark_tile(cell_tile[np]);\n            cur_score += cell_val[np];\n            path.push_back(dch[nd]);\n            pos = np;\n        }\n\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_path = path;\n        }\n    }\n\n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitInfo {\n    bool use = false;\n    int s = -1;\n    double ml = 0.0, mr = 0.0;\n    double mean_single = 0.0;\n    bool has_obs = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const double MINW = 1000.0;\n    const double MAXW = 9000.0;\n    const double LR   = 0.5;\n\n    vector<vector<double>> est_h(N, vector<double>(N - 1, 5000.0));\n    vector<vector<double>> est_v(N - 1, vector<double>(N, 5000.0));\n    vector<vector<int>>    cnt_h(N, vector<int>(N - 1, 0));\n    vector<vector<int>>    cnt_v(N - 1, vector<int>(N, 0));\n\n    double global_mean = 5000.0;\n    bool likely_m2 = false;\n\n    for (int query = 0; query < 1000; ++query) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        /* ---- exploration schedule ---- */\n        double explore = 0.0;\n        if      (query < 200) explore = 0.50;\n        else if (query < 400) explore = 0.25;\n        else if (query < 700) explore = 0.10;\n\n        /* ---- helper: fit a row/column with optional split ---- */\n        auto fit_split = [&](const vector<pair<int,double>>& obs) -> SplitInfo {\n            SplitInfo info;\n            int n = (int)obs.size();\n            if (n == 0) return info;\n            info.has_obs = true;\n            double sum = 0.0;\n            for (auto &p : obs) sum += p.second;\n            info.mean_single = sum / n;\n\n            double sse_single = 0.0;\n            for (auto &p : obs) {\n                double d = p.second - info.mean_single;\n                sse_single += d * d;\n            }\n\n            if (n >= 4) {\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl == 0 || cr == 0) continue;\n                    double ml = sl / cl;\n                    double mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse;\n                        best_s = s;\n                        best_ml = ml;\n                        best_mr = mr;\n                    }\n                }\n\n                if (best_s != -1) {\n                    // BIC: split model has 3 params (2 means + shared variance),\n                    //      single model has 2 params (1 mean + variance).\n                    double bic_single = n * log(sse_single / n + 1e-9) + 2.0 * log((double)n);\n                    double bic_split  = n * log(best_sse  / n + 1e-9) + 3.0 * log((double)n);\n                    bool accept = bic_split < bic_single;\n                    // strong override for obvious jumps even if BIC is on the fence\n                    if (!accept && best_sse < sse_single * 0.30) accept = true;\n\n                    if (accept) {\n                        info.use = true;\n                        info.s = best_s;\n                        info.ml = best_ml;\n                        info.mr = best_mr;\n                    }\n                }\n            }\n            return info;\n        };\n\n        /* ---- gather observations and fit rows / columns ---- */\n        vector<SplitInfo> row_info(N);\n        vector<SplitInfo> col_info(N);\n        int strong_split_rows = 0, strong_split_cols = 0;\n\n        for (int i = 0; i < N; ++i) {\n            vector<pair<int,double>> obs;\n            for (int j = 0; j < N - 1; ++j)\n                if (cnt_h[i][j] > 0) obs.emplace_back(j, est_h[i][j]);\n            row_info[i] = fit_split(obs);\n            if (row_info[i].use) ++strong_split_rows;\n        }\n        for (int j = 0; j < N; ++j) {\n            vector<pair<int,double>> obs;\n            for (int i = 0; i < N - 1; ++i)\n                if (cnt_v[i][j] > 0) obs.emplace_back(i, est_v[i][j]);\n            col_info[j] = fit_split(obs);\n            if (col_info[j].use) ++strong_split_cols;\n        }\n\n        // global M=2 detection\n        if (!likely_m2 && (strong_split_rows >= 5 || strong_split_cols >= 5))\n            likely_m2 = true;\n\n        // if M=2 seems likely, re-fit sparse rows/columns with relaxed threshold\n        if (likely_m2) {\n            for (int i = 0; i < N; ++i) {\n                if (row_info[i].use || !row_info[i].has_obs) continue;\n                vector<pair<int,double>> obs;\n                for (int j = 0; j < N - 1; ++j)\n                    if (cnt_h[i][j] > 0) obs.emplace_back(j, est_h[i][j]);\n                int n = (int)obs.size();\n                if (n < 3) continue;\n                // recompute best split with a permissive ratio\n                double sum = 0.0;\n                for (auto &p : obs) sum += p.second;\n                double mean = sum / n;\n                double sse_single = 0.0;\n                for (auto &p : obs) { double d = p.second - mean; sse_single += d*d; }\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl == 0 || cr == 0) continue;\n                    double ml = sl / cl, mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse; best_s = s; best_ml = ml; best_mr = mr;\n                    }\n                }\n                if (best_s != -1 && best_sse < sse_single * 0.50) {\n                    row_info[i].use = true;\n                    row_info[i].s = best_s;\n                    row_info[i].ml = best_ml;\n                    row_info[i].mr = best_mr;\n                }\n            }\n\n            for (int j = 0; j < N; ++j) {\n                if (col_info[j].use || !col_info[j].has_obs) continue;\n                vector<pair<int,double>> obs;\n                for (int i = 0; i < N - 1; ++i)\n                    if (cnt_v[i][j] > 0) obs.emplace_back(i, est_v[i][j]);\n                int n = (int)obs.size();\n                if (n < 3) continue;\n                double sum = 0.0;\n                for (auto &p : obs) sum += p.second;\n                double mean = sum / n;\n                double sse_single = 0.0;\n                for (auto &p : obs) { double d = p.second - mean; sse_single += d*d; }\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl == 0 || cr == 0) continue;\n                    double ml = sl / cl, mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse; best_s = s; best_ml = ml; best_mr = mr;\n                    }\n                }\n                if (best_s != -1 && best_sse < sse_single * 0.50) {\n                    col_info[j].use = true;\n                    col_info[j].s = best_s;\n                    col_info[j].ml = best_ml;\n                    col_info[j].mr = best_mr;\n                }\n            }\n        }\n\n        /* ---- prior accessors (structural, ignoring individual est) ---- */\n        auto prior_h = [&](int i, int j) -> double {\n            const SplitInfo &ri = row_info[i];\n            if (!ri.has_obs) return global_mean;\n            if (ri.use) return (j < ri.s) ? ri.ml : ri.mr;\n            return ri.mean_single;\n        };\n        auto prior_v = [&](int i, int j) -> double {\n            const SplitInfo &ci = col_info[j];\n            if (!ci.has_obs) return global_mean;\n            if (ci.use) return (i < ci.s) ? ci.ml : ci.mr;\n            return ci.mean_single;\n        };\n\n        /* ---- Dijkstra with optimistic exploration ---- */\n        int S = si * N + sj;\n        int T = ti * N + tj;\n        const int V = N * N;\n        const double INF = 1e100;\n\n        vector<double> dist(V, INF);\n        vector<pair<int,char>> prv(V, {-1, 0});\n        using State = pair<double,int>;\n        priority_queue<State, vector<State>, greater<State>> pq;\n\n        dist[S] = 0.0;\n        pq.emplace(0.0, S);\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top(); pq.pop();\n            if (d > dist[v] + 1e-9) continue;\n            if (v == T) break;\n            int i = v / N;\n            int j = v % N;\n\n            auto relax = [&](int ni, int nj, bool is_h, int ei, int ej, char dir) {\n                int u = ni * N + nj;\n                double base = is_h ? (cnt_h[ei][ej] > 0 ? est_h[ei][ej] : prior_h(ei, ej))\n                                   : (cnt_v[ei][ej] > 0 ? est_v[ei][ej] : prior_v(ei, ej));\n                int c = is_h ? cnt_h[ei][ej] : cnt_v[ei][ej];\n                double w = base * (1.0 - explore / sqrt((double)c + 1.0));\n                if (w < MINW) w = MINW;\n                if (dist[u] > d + w) {\n                    dist[u] = d + w;\n                    prv[u] = {v, dir};\n                    pq.emplace(dist[u], u);\n                }\n            };\n\n            if (i > 0)     relax(i - 1, j,     false, i - 1, j,     'U');\n            if (i + 1 < N) relax(i + 1, j,     false, i,     j,     'D');\n            if (j > 0)     relax(i,     j - 1, true,  i,     j - 1, 'L');\n            if (j + 1 < N) relax(i,     j + 1, true,  i,     j,     'R');\n        }\n\n        /* ---- reconstruct path ---- */\n        string path;\n        int cur = T;\n        while (cur != S) {\n            auto [p, c] = prv[cur];\n            path.push_back(c);\n            cur = p;\n        }\n        reverse(path.begin(), path.end());\n\n        cout << path << '\\n' << flush;\n\n        /* ---- read noisy observation ---- */\n        long long y;\n        cin >> y;\n        int L = (int)path.size();\n        if (L == 0) continue;\n\n        /* ---- update global mean ---- */\n        double avg_step = (double)y / (double)L;\n        global_mean = global_mean * 0.95 + avg_step * 0.05;\n        if (global_mean < MINW) global_mean = MINW;\n        if (global_mean > MAXW) global_mean = MAXW;\n\n        /* ---- list edges, init unseen ones to their priors ---- */\n        struct Eref { bool h; int i, j; };\n        vector<Eref> edges;\n        edges.reserve(L);\n        double pred = 0.0;\n        int ci = si, cj = sj;\n\n        for (char c : path) {\n            if (c == 'U') {\n                if (cnt_v[ci-1][cj] == 0) est_v[ci-1][cj] = prior_v(ci-1, cj);\n                pred += est_v[ci-1][cj];\n                edges.push_back({false, ci-1, cj});\n                --ci;\n            } else if (c == 'D') {\n                if (cnt_v[ci][cj] == 0) est_v[ci][cj] = prior_v(ci, cj);\n                pred += est_v[ci][cj];\n                edges.push_back({false, ci, cj});\n                ++ci;\n            } else if (c == 'L') {\n                if (cnt_h[ci][cj-1] == 0) est_h[ci][cj-1] = prior_h(ci, cj-1);\n                pred += est_h[ci][cj-1];\n                edges.push_back({true, ci, cj-1});\n                --cj;\n            } else if (c == 'R') {\n                if (cnt_h[ci][cj] == 0) est_h[ci][cj] = prior_h(ci, cj);\n                pred += est_h[ci][cj];\n                edges.push_back({true, ci, cj});\n                ++cj;\n            }\n        }\n\n        double diff = (double)y - pred;\n        double total_inv = 0.0;\n        for (auto &e : edges) {\n            int c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            total_inv += 1.0 / ((double)c + 1.0);\n        }\n\n        /* ---- weighted LMS update + shrinkage toward structural prior ---- */\n        for (auto &e : edges) {\n            int &c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            double &est = e.h ? est_h[e.i][e.j] : est_v[e.i][e.j];\n            double structural = e.h ? prior_h(e.i, e.j) : prior_v(e.i, e.j);\n\n            double w = (1.0 / ((double)c + 1.0)) / total_inv;\n            est += diff * w * LR;\n\n            // mild shrinkage toward structural prior; fades as count grows\n            double shrink = 0.08 / (1.0 + (double)c / 3.0);\n            est = est * (1.0 - shrink) + structural * shrink;\n\n            if (est < MINW) est = MINW;\n            if (est > MAXW) est = MAXW;\n            ++c;\n        }\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    uint16_t cell[12];\n    uint8_t len;\n};\n\nint N, M;\nvector<string> S;\nvector<Placement> placements;\nvector<int> pid_sid;\nvector<uint8_t> pid_len;\nint P;\nvector<vector<int>> cell_pids_by_char;\n\n/* current board state */\nvector<uint8_t> board;\nvector<int> pid_match;\nvector<int> sid_ok;\nint total_matched;\n\nchrono::steady_clock::time_point start_time;\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nconst double UINT_MAX_INV = 1.0 / numeric_limits<uint32_t>::max();\n\n/* ---------- build all placements ---------- */\nvoid build() {\n    P = M * 800;\n    placements.resize(P);\n    pid_sid.resize(P);\n    pid_len.resize(P);\n    for (int sid = 0; sid < M; ++sid) {\n        int len = (int)S[sid].size();\n        int base = sid * 800;\n        int idx = 0;\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Placement p;\n                    p.len = (uint8_t)len;\n                    for (int k = 0; k < len; ++k) {\n                        int rr = (dir == 0) ? r : (r + k) % N;\n                        int cc = (dir == 0) ? (c + k) % N : c;\n                        p.cell[k] = (uint16_t)(rr * N + cc);\n                    }\n                    placements[base + idx] = p;\n                    pid_sid[base + idx] = sid;\n                    pid_len[base + idx] = (uint8_t)len;\n                    ++idx;\n                }\n            }\n        }\n    }\n\n    cell_pids_by_char.assign(400 * 8, {});\n    for (int pid = 0; pid < P; ++pid) {\n        int sid = pid_sid[pid];\n        const Placement &p = placements[pid];\n        for (int i = 0; i < p.len; ++i) {\n            int cell = p.cell[i];\n            int ch = S[sid][i] - 'A';\n            cell_pids_by_char[cell * 8 + ch].push_back(pid);\n        }\n    }\n\n    board.resize(400);\n    pid_match.assign(P, 0);\n    sid_ok.assign(M, 0);\n}\n\n/* ---------- evaluate board from scratch ---------- */\nvoid eval_board(const vector<uint8_t> &b) {\n    board = b;\n    fill(pid_match.begin(), pid_match.end(), 0);\n    for (int cell = 0; cell < 400; ++cell) {\n        int ch = board[cell];\n        for (int pid : cell_pids_by_char[cell * 8 + ch]) {\n            ++pid_match[pid];\n        }\n    }\n    fill(sid_ok.begin(), sid_ok.end(), 0);\n    for (int pid = 0; pid < P; ++pid) {\n        if (pid_match[pid] == pid_len[pid]) {\n            ++sid_ok[pid_sid[pid]];\n        }\n    }\n    total_matched = 0;\n    for (int i = 0; i < M; ++i)\n        if (sid_ok[i] > 0) ++total_matched;\n}\n\n/* ---------- apply one cell change incrementally ---------- */\ninline void apply_move(int cell, int new_ch) {\n    int old_ch = board[cell];\n    if (old_ch == new_ch) return;\n    board[cell] = (uint8_t)new_ch;\n\n    for (int pid : cell_pids_by_char[cell * 8 + old_ch]) {\n        if (pid_match[pid] == pid_len[pid]) {\n            int sid = pid_sid[pid];\n            if (--sid_ok[sid] == 0) --total_matched;\n        }\n        --pid_match[pid];\n    }\n\n    for (int pid : cell_pids_by_char[cell * 8 + new_ch]) {\n        ++pid_match[pid];\n        if (pid_match[pid] == pid_len[pid]) {\n            int sid = pid_sid[pid];\n            if (++sid_ok[sid] == 1) ++total_matched;\n        }\n    }\n}\n\n/* ---------- initial board constructors ---------- */\nvector<uint8_t> greedy_init_board() {\n    int cell_cnt[400][8] = {};\n    uint8_t cell_mask[400] = {};\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int sid : order) {\n        int base = sid * 800;\n        int best_k = 0;\n        int best_conf = INT_MAX;\n        int best_cov = INT_MAX;\n        for (int k = 0; k < 800; ++k) {\n            const Placement &p = placements[base + k];\n            int add_conf = 0;\n            int add_cov = 0;\n            for (int i = 0; i < p.len; ++i) {\n                int cell = p.cell[i];\n                int ch = S[sid][i] - 'A';\n                if (cell_mask[cell] == 0) {\n                    ++add_cov;\n                } else if ( ((cell_mask[cell] >> ch) & 1) == 0 ) {\n                    if ((cell_mask[cell] & (cell_mask[cell] - 1)) == 0) ++add_conf;\n                }\n            }\n            if (add_conf < best_conf ||\n                (add_conf == best_conf && add_cov < best_cov) ||\n                (add_conf == best_conf && add_cov == best_cov && (rng() & 1))) {\n                best_conf = add_conf;\n                best_cov = add_cov;\n                best_k = k;\n            }\n        }\n        const Placement &p = placements[base + best_k];\n        for (int i = 0; i < p.len; ++i) {\n            int cell = p.cell[i];\n            int ch = S[sid][i] - 'A';\n            ++cell_cnt[cell][ch];\n            cell_mask[cell] |= (1 << ch);\n        }\n    }\n\n    vector<uint8_t> b(400);\n    for (int cell = 0; cell < 400; ++cell) {\n        int best_ch = 0;\n        for (int ch = 1; ch < 8; ++ch) {\n            if (cell_cnt[cell][ch] > cell_cnt[cell][best_ch]) best_ch = ch;\n        }\n        b[cell] = (uint8_t)best_ch;\n    }\n    return b;\n}\n\nvector<uint8_t> majority_board() {\n    vector<uint8_t> b(400);\n    for (int cell = 0; cell < 400; ++cell) {\n        int best_ch = 0;\n        int best_cnt = (int)cell_pids_by_char[cell * 8 + 0].size();\n        for (int ch = 1; ch < 8; ++ch) {\n            int cnt = (int)cell_pids_by_char[cell * 8 + ch].size();\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_ch = ch;\n            }\n        }\n        b[cell] = (uint8_t)best_ch;\n    }\n    return b;\n}\n\n/* ---------- dotting via placement-set SA ---------- */\npair<vector<string>, int> dot_sa(double time_limit) {\n    static vector<vector<int>> mp;\n    mp.assign(M, {});\n    for (int pid = 0; pid < P; ++pid) {\n        if (pid_match[pid] == pid_len[pid]) {\n            mp[pid_sid[pid]].push_back(pid);\n        }\n    }\n    for (int sid = 0; sid < M; ++sid) {\n        if (mp[sid].empty()) return {vector<string>(), -1};\n    }\n\n    int sel[800];\n    int cell_cov[400] = {0};\n    int covered = 0;\n\n    for (int sid = 0; sid < M; ++sid) {\n        int pid = mp[sid][rng() % mp[sid].size()];\n        sel[sid] = pid;\n        const Placement &p = placements[pid];\n        for (int i = 0; i < p.len; ++i) {\n            int c = p.cell[i];\n            if (cell_cov[c]++ == 0) ++covered;\n        }\n    }\n\n    int best_covered = covered;\n    int best_sel[800];\n    memcpy(best_sel, sel, M * sizeof(int));\n\n    double T = 2.0;\n    while (elapsed() < time_limit) {\n        int sid = rng() % M;\n        int old_pid = sel[sid];\n        const Placement &old_p = placements[old_pid];\n\n        int nc = (int)mp[sid].size();\n        if (nc <= 1) continue;\n\n        int tries = min(nc, 30);\n        int best_pid = old_pid;\n        int best_delta = 0;\n\n        for (int t = 0; t < tries; ++t) {\n            int new_pid = mp[sid][rng() % nc];\n            if (new_pid == old_pid) continue;\n            const Placement &new_p = placements[new_pid];\n\n            int delta = 0;\n            for (int i = 0; i < old_p.len; ++i) {\n                int c = old_p.cell[i];\n                if (--cell_cov[c] == 0) --delta;\n            }\n            for (int i = 0; i < new_p.len; ++i) {\n                int c = new_p.cell[i];\n                if (++cell_cov[c] == 1) ++delta;\n            }\n            for (int i = 0; i < new_p.len; ++i) {\n                int c = new_p.cell[i];\n                --cell_cov[c];\n            }\n            for (int i = 0; i < old_p.len; ++i) {\n                int c = old_p.cell[i];\n                ++cell_cov[c];\n            }\n\n            if (delta < best_delta) {\n                best_delta = delta;\n                best_pid = new_pid;\n            }\n        }\n\n        bool accept = (best_delta < 0) ||\n                      (best_delta > 0 && rng() * UINT_MAX_INV < exp(-best_delta / T));\n        if (accept && best_pid != old_pid) {\n            const Placement &new_p = placements[best_pid];\n            for (int i = 0; i < old_p.len; ++i) {\n                int c = old_p.cell[i];\n                if (--cell_cov[c] == 0) --covered;\n            }\n            for (int i = 0; i < new_p.len; ++i) {\n                int c = new_p.cell[i];\n                if (++cell_cov[c] == 1) ++covered;\n            }\n            sel[sid] = best_pid;\n        }\n\n        if (covered < best_covered) {\n            best_covered = covered;\n            memcpy(best_sel, sel, M * sizeof(int));\n        }\n\n        T *= 0.99997;\n        if (T < 1e-9) T = 1e-9;\n    }\n\n    memset(cell_cov, 0, sizeof(cell_cov));\n    for (int sid = 0; sid < M; ++sid) {\n        const Placement &p = placements[best_sel[sid]];\n        for (int i = 0; i < p.len; ++i) {\n            cell_cov[p.cell[i]] = 1;\n        }\n    }\n\n    vector<string> ans(N, string(N, '.'));\n    for (int c = 0; c < 400; ++c) {\n        if (cell_cov[c]) ans[c / N][c % N] = char('A' + board[c]);\n    }\n    return {ans, 400 - best_covered};\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N >> M)) return 0;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    start_time = chrono::steady_clock::now();\n    build();\n\n    int best_dots = -1;\n    vector<string> best_ans;\n    vector<uint8_t> best_perfect_board;\n    vector<uint8_t> fallback_board;\n    int fallback_matched = -1;\n\n    while (elapsed() < 2.55) {\n        vector<uint8_t> b;\n        int mode = rng() % 5;\n        if (mode == 0) {\n            b = greedy_init_board();\n        } else if (mode == 1) {\n            b = majority_board();\n        } else if (mode == 2 && !best_perfect_board.empty()) {\n            b = best_perfect_board;\n            for (int i = 0; i < 25; ++i) b[rng() % 400] = (uint8_t)(rng() % 8);\n        } else {\n            b.resize(400);\n            for (int i = 0; i < 400; ++i) b[i] = (uint8_t)(rng() % 8);\n        }\n\n        eval_board(b);\n        if (total_matched > fallback_matched) {\n            fallback_matched = total_matched;\n            fallback_board = board;\n        }\n\n        /* board-space SA */\n        double T = 2.0;\n        int last_matched = total_matched;\n        int since_improve = 0;\n\n        while (elapsed() < 2.55 && total_matched < M) {\n            int cell = -1, new_ch = -1;\n            bool targeted = (rng() % 100 < 70);\n\n            if (targeted) {\n                int sid = -1;\n                for (int t = 0; t < 15; ++t) {\n                    int try_sid = rng() % M;\n                    if (sid_ok[try_sid] == 0) {\n                        sid = try_sid;\n                        break;\n                    }\n                }\n                if (sid != -1) {\n                    int pid = sid * 800 + (rng() % 800);\n                    const Placement &p = placements[pid];\n                    int mis[12], mc = 0;\n                    for (int i = 0; i < p.len; ++i) {\n                        int c = p.cell[i];\n                        if (board[c] != (uint8_t)(S[sid][i] - 'A')) {\n                            mis[mc++] = i;\n                        }\n                    }\n                    if (mc > 0) {\n                        int idx = mis[rng() % mc];\n                        cell = p.cell[idx];\n                        new_ch = S[sid][idx] - 'A';\n                    } else {\n                        targeted = false;\n                    }\n                } else {\n                    targeted = false;\n                }\n            }\n\n            if (!targeted) {\n                cell = rng() % 400;\n                new_ch = rng() % 8;\n            }\n\n            int old_ch = board[cell];\n            if (new_ch == old_ch) continue;\n\n            int old_matched = total_matched;\n            apply_move(cell, new_ch);\n            int delta = total_matched - old_matched;\n\n            bool accept = (delta >= 0) || (rng() * UINT_MAX_INV < exp(delta / T));\n            if (!accept) {\n                apply_move(cell, old_ch);\n            }\n\n            if (total_matched > last_matched) {\n                last_matched = total_matched;\n                since_improve = 0;\n            } else {\n                ++since_improve;\n            }\n            if (since_improve > 60000) {\n                T = min(T * 3.0, 15.0);\n                since_improve = 0;\n            }\n            T *= 0.99996;\n            if (T < 1e-9) T = 1e-9;\n        }\n\n        if (total_matched > fallback_matched) {\n            fallback_matched = total_matched;\n            fallback_board = board;\n        }\n\n        if (total_matched == M) {\n            if (best_perfect_board.empty()) best_perfect_board = board;\n            double limit = min(2.95, elapsed() + 0.30);\n            auto [ans, dots] = dot_sa(limit);\n            if (dots > best_dots) {\n                best_dots = dots;\n                best_ans = ans;\n                best_perfect_board = board;\n            }\n        }\n    }\n\n    /* final dotting on the best perfect board */\n    if (!best_perfect_board.empty() && elapsed() < 2.98) {\n        eval_board(best_perfect_board);\n        auto [ans, dots] = dot_sa(2.99);\n        if (dots > best_dots) {\n            best_dots = dots;\n            best_ans = ans;\n        }\n    }\n\n    if (best_dots < 0) {\n        vector<string> ans(N, string(N, 'A'));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                ans[i][j] = char('A' + fallback_board[i * N + j]);\n        best_ans = ans;\n    }\n\n    for (const string &row : best_ans) {\n        cout << row << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, si, sj;\n    int V = 0, S = -1;\n    int Hreq = 0, Vreq = 0, R = 0;\n    vector<string> g;\n    vector<vector<int>> w;\n    vector<int> ui, uj;\n    vector<vector<int>> adj;\n    vector< bitset<1024> > cellMask;\n    vector<vector<int>> groupCells;\n    bitset<1024> allReq;\n    mt19937 rng;\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n    const int INF = 1e9;\n\n    /* Dijkstra with edge cost = w[u] + w[v] */\n    vector<int> dist, parent, heapPos, order;\n    vector< bitset<1024> > pathMask;\n    struct IntHeap {\n        vector<int> h;\n        vector<int> *d, *pos;\n        void init(vector<int> *dist, vector<int> *position) { d = dist; pos = position; }\n        void clear() { for (int v : h) (*pos)[v] = -1; h.clear(); }\n        bool empty() const { return h.empty(); }\n        void push(int v) {\n            if ((*pos)[v] == -1) { (*pos)[v] = (int)h.size(); h.push_back(v); }\n            siftup((*pos)[v]);\n        }\n        int pop() {\n            int res = h[0]; (*pos)[res] = -1;\n            int v = h.back(); h.pop_back();\n            if (!h.empty()) { h[0] = v; (*pos)[v] = 0; siftdown(0); }\n            return res;\n        }\n        void siftup(int i) {\n            int v = h[i], dv = (*d)[v];\n            while (i > 0) {\n                int p = (i - 1) >> 1, u = h[p];\n                if ((*d)[u] <= dv) break;\n                h[i] = u; (*pos)[u] = i; i = p;\n            }\n            h[i] = v; (*pos)[v] = i;\n        }\n        void siftdown(int i) {\n            int v = h[i], dv = (*d)[v], n = (int)h.size();\n            while (true) {\n                int l = i * 2 + 1; if (l >= n) break;\n                int r = l + 1, best = l;\n                if (r < n && (*d)[h[r]] < (*d)[h[l]]) best = r;\n                if ((*d)[h[best]] >= dv) break;\n                int u = h[best]; h[i] = u; (*pos)[u] = i; i = best;\n            }\n            h[i] = v; (*pos)[v] = i;\n        }\n    };\n    IntHeap dijHeap;\n\n    /* local search helpers */\n    vector<vector<int>> swapAdj;\n    vector<char> swapMark;\n    vector<int> swapTouched;\n    vector<int> vertId;\n\n    vector<pair<int,int>> bestEdges;\n    long long bestCost = LLONG_MAX;\n\n    inline int dirMove(int u, int v) const {\n        int i1 = ui[u], j1 = uj[u];\n        int i2 = ui[v], j2 = uj[v];\n        if (i2 == i1 - 1) return 0;\n        if (i2 == i1 + 1) return 1;\n        if (j2 == j1 - 1) return 2;\n        return 3;\n    }\n\n    void dijkstraRun(const vector<char> &srcMask, vector<int> *orderPtr) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(parent.begin(), parent.end(), -1);\n        dijHeap.clear();\n        for (int u = 0; u < V; ++u) if (srcMask[u]) {\n            dist[u] = 0; dijHeap.push(u);\n        }\n        if (orderPtr) orderPtr->clear();\n        while (!dijHeap.empty()) {\n            int u = dijHeap.pop();\n            if (orderPtr) orderPtr->push_back(u);\n            int du = dist[u];\n            int wu = w[ui[u]][uj[u]];\n            for (int v : adj[u]) {\n                int nd = du + wu + w[ui[v]][uj[v]];\n                if (nd < dist[v]) {\n                    dist[v] = nd; parent[v] = u; dijHeap.push(v);\n                }\n            }\n        }\n    }\n\n    long long pruneAndCost(vector<pair<int,int>> &edges, bitset<1024> &outCov) {\n        vector<int> verts;\n        verts.reserve(edges.size() * 2);\n        for (auto &e : edges) {\n            if (vertId[e.first] == -1) { vertId[e.first] = (int)verts.size(); verts.push_back(e.first); }\n            if (vertId[e.second] == -1) { vertId[e.second] = (int)verts.size(); verts.push_back(e.second); }\n        }\n        int nV = (int)verts.size();\n        vector<vector<int>> localAdj(nV);\n        for (auto &e : edges) {\n            int a = vertId[e.first], b = vertId[e.second];\n            localAdj[a].push_back(b);\n            localAdj[b].push_back(a);\n        }\n        vector<char> alive(nV, 1);\n        vector<int> deg(nV);\n        for (int i = 0; i < nV; ++i) deg[i] = (int)localAdj[i].size();\n        vector<int> coverCnt(R, 0);\n        for (int i = 0; i < nV; ++i) {\n            int u = verts[i];\n            for (int r = 0; r < R; ++r) if (cellMask[u].test(r)) ++coverCnt[r];\n        }\n        queue<int> q;\n        for (int i = 0; i < nV; ++i)\n            if (deg[i] == 1 && verts[i] != S) q.push(i);\n\n        while (!q.empty()) {\n            int li = q.front(); q.pop();\n            if (!alive[li] || deg[li] != 1 || verts[li] == S) continue;\n            bool ok = true;\n            int u = verts[li];\n            for (int r = 0; r < R; ++r) {\n                if (cellMask[u].test(r) && coverCnt[r] <= 1) { ok = false; break; }\n            }\n            if (!ok) continue;\n            alive[li] = 0; deg[li] = 0;\n            for (int r = 0; r < R; ++r) if (cellMask[u].test(r)) --coverCnt[r];\n            for (int v : localAdj[li]) {\n                if (!alive[v]) continue;\n                if (--deg[v] == 1 && verts[v] != S) q.push(v);\n            }\n        }\n\n        long long cost = 0;\n        vector<pair<int,int>> pruned;\n        outCov.reset();\n        for (int i = 0; i < nV; ++i) if (alive[i]) {\n            int u = verts[i];\n            outCov |= cellMask[u];\n            for (int v : localAdj[i]) if (i < v) {\n                pruned.emplace_back(u, verts[v]);\n                cost += w[ui[u]][uj[u]] + w[ui[verts[v]]][uj[verts[v]]];\n            }\n        }\n        for (int v : verts) vertId[v] = -1;\n        edges.swap(pruned);\n        return cost;\n    }\n\n    long long greedyBuild(const vector<pair<int,int>> &initEdges, int strategy,\n                          vector<pair<int,int>> &outEdges, bitset<1024> &outCov) {\n        vector<char> inTree(V, 0);\n        for (auto &e : initEdges) {\n            inTree[e.first] = 1;\n            inTree[e.second] = 1;\n        }\n        inTree[S] = 1;\n        bitset<1024> covered;\n        for (int u = 0; u < V; ++u) if (inTree[u]) covered |= cellMask[u];\n\n        vector<pair<int,int>> edges = initEdges;\n        struct Cand { int v, d, g; };\n\n        while (covered != allReq) {\n            dijkstraRun(inTree, &order);\n            for (int u : order) {\n                if (inTree[u]) pathMask[u].reset();\n                else {\n                    int p = parent[u];\n                    if (p >= 0) pathMask[u] = pathMask[p];\n                    else pathMask[u].reset();\n                    pathMask[u] |= cellMask[u];\n                }\n            }\n            vector<Cand> cands;\n            for (int u = 0; u < V; ++u) {\n                if (inTree[u]) continue;\n                bitset<1024> add = pathMask[u] & ~covered;\n                int gain = (int)add.count();\n                if (gain > 0) cands.push_back({u, dist[u], gain});\n            }\n            if (cands.empty()) return LLONG_MAX;\n\n            int bestV = -1;\n            if (strategy == 0) {\n                sort(cands.begin(), cands.end(),\n                    [](const Cand& a, const Cand& b) {\n                        return (long long)a.d * b.g < (long long)b.d * a.g;\n                    });\n                int K = min(3, (int)cands.size());\n                bestV = cands[rng() % K].v;\n            } else if (strategy == 1) {\n                sort(cands.begin(), cands.end(),\n                    [](const Cand& a, const Cand& b) {\n                        if (a.g != b.g) return a.g > b.g;\n                        return a.d < b.d;\n                    });\n                bestV = cands[0].v;\n            } else {\n                vector<int> urg;\n                for (int r = 0; r < R; ++r) if (!covered.test(r)) urg.push_back(r);\n                int rg = urg[rng() % urg.size()];\n                vector<Cand> rc;\n                for (auto &c : cands) if (pathMask[c.v].test(rg)) rc.push_back(c);\n                if (!rc.empty()) {\n                    sort(rc.begin(), rc.end(),\n                        [](const Cand& a, const Cand& b) { return a.d < b.d; });\n                    int K = min(3, (int)rc.size());\n                    bestV = rc[rng() % K].v;\n                } else {\n                    bestV = cands[0].v;\n                }\n            }\n\n            int cur = bestV;\n            while (!inTree[cur]) {\n                int p = parent[cur];\n                edges.emplace_back(cur, p);\n                inTree[cur] = 1;\n                covered |= cellMask[cur];\n                cur = p;\n            }\n        }\n        outCov.reset();\n        long long cost = pruneAndCost(edges, outCov);\n        outEdges.swap(edges);\n        return cost;\n    }\n\n    pair<vector<pair<int,int>>, long long> primFull(int perturb) {\n        vector<int> dvec(V, INF), par(V, -1);\n        vector<char> used(V, 0);\n        vector<int> pos(V, -1);\n        IntHeap heap;\n        heap.init(&dvec, &pos);\n        dvec[S] = 0; heap.push(S);\n        vector<pair<int,int>> edges;\n        while (!heap.empty()) {\n            int u = heap.pop();\n            if (used[u]) continue;\n            used[u] = 1;\n            if (par[u] != -1) edges.emplace_back(u, par[u]);\n            int wu = w[ui[u]][uj[u]];\n            for (int v : adj[u]) {\n                if (used[v]) continue;\n                int c = wu + w[ui[v]][uj[v]] + (perturb ? (int)(rng() % 3) : 0);\n                if (c < dvec[v]) {\n                    dvec[v] = c; par[v] = u; heap.push(v);\n                }\n            }\n        }\n        bitset<1024> cov;\n        long long cost = pruneAndCost(edges, cov);\n        return {edges, cost};\n    }\n\n    /* ---------- Metric closure MST heuristic ---------- */\n    void metricClosureMST(int perturb,\n                          vector<pair<int,int>> &outEdges, long long &outCost,\n                          bitset<1024> &outCov) {\n        int M = R + 1; // groups + start\n        // Precompute Dijkstra from each group and start\n        vector<vector<int>> gdist(M, vector<int>(V, INF));\n        vector<vector<int>> gpar(M, vector<int>(V, -1));\n        vector<char> srcMask(V, 0);\n\n        for (int g = 0; g < R; ++g) {\n            fill(srcMask.begin(), srcMask.end(), 0);\n            for (int v : groupCells[g]) srcMask[v] = 1;\n            dijkstraRun(srcMask, nullptr);\n            gdist[g] = dist;\n            gpar[g] = parent;\n        }\n        // Start\n        {\n            fill(srcMask.begin(), srcMask.end(), 0);\n            srcMask[S] = 1;\n            dijkstraRun(srcMask, nullptr);\n            gdist[R] = dist;\n            gpar[R] = parent;\n        }\n\n        // Compute meta distances\n        vector<vector<int>> md(M, vector<int>(M, INF));\n        vector<vector<int>> mvia(M, vector<int>(M, -1));\n        for (int i = 0; i < M; ++i) {\n            for (int j = 0; j < M; ++j) if (i != j) {\n                int best = INF, bestv = -1;\n                if (j == R) {\n                    if (gdist[i][S] < best) { best = gdist[i][S]; bestv = S; }\n                } else {\n                    for (int v : groupCells[j]) {\n                        if (gdist[i][v] < best) { best = gdist[i][v]; bestv = v; }\n                    }\n                }\n                md[i][j] = best + (perturb ? (int)(rng() % 20) : 0);\n                mvia[i][j] = bestv;\n            }\n        }\n\n        // Prim on meta graph\n        vector<int> mincost(M, INF), used(M, 0), sel(M, -1);\n        vector<vector<int>> metaAdj(M);\n        mincost[R] = 0;\n        for (int it = 0; it < M; ++it) {\n            int v = -1;\n            for (int j = 0; j < M; ++j)\n                if (!used[j] && (v == -1 || mincost[j] < mincost[v])) v = j;\n            used[v] = 1;\n            if (sel[v] != -1) {\n                metaAdj[v].push_back(sel[v]);\n                metaAdj[sel[v]].push_back(v);\n            }\n            for (int j = 0; j < M; ++j)\n                if (!used[j] && md[v][j] < mincost[j]) {\n                    mincost[j] = md[v][j];\n                    sel[j] = v;\n                }\n        }\n\n        // Realize: add all shortest paths for MST edges\n        vector<pair<int,int>> edges;\n        vector<char> hasEdge(V * V, 0); // too big, use unordered_set or sort\n        // Use sort-based dedup\n        vector<pair<int,int>> rawEdges;\n        rawEdges.reserve(M * N);\n\n        function<void(int,int)> addMetaEdge = [&](int i, int j) {\n            int v = mvia[i][j];\n            if (v == -1) return;\n            while (v != -1) {\n                int p = gpar[i][v];\n                if (p != -1) {\n                    int a = v, b = p;\n                    if (a > b) swap(a, b);\n                    rawEdges.emplace_back(a, b);\n                }\n                v = p;\n            }\n        };\n\n        for (int i = 0; i < M; ++i)\n            for (int j : metaAdj[i])\n                if (i < j) addMetaEdge(i, j);\n\n        sort(rawEdges.begin(), rawEdges.end());\n        rawEdges.erase(unique(rawEdges.begin(), rawEdges.end()), rawEdges.end());\n\n        // Build connected component containing S\n        vector<vector<int>> tmpAdj(V);\n        for (auto &e : rawEdges) {\n            tmpAdj[e.first].push_back(e.second);\n            tmpAdj[e.second].push_back(e.first);\n        }\n        vector<char> vis(V, 0);\n        queue<int> qq;\n        qq.push(S); vis[S] = 1;\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            for (int v : tmpAdj[u]) if (!vis[v]) {\n                vis[v] = 1;\n                qq.push(v);\n            }\n        }\n        // BFS tree from S within component\n        for (int u = 0; u < V; ++u) {\n            if (!vis[u]) continue;\n            for (int v : tmpAdj[u]) {\n                if (u < v) edges.emplace_back(u, v);\n            }\n        }\n        // Actually edges might form cycles. Just use all edges and let prune handle it,\n        // or take a spanning tree. Let's use BFS tree to keep it small.\n        edges.clear();\n        fill(vis.begin(), vis.end(), 0);\n        qq.push(S); vis[S] = 1;\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            for (int v : tmpAdj[u]) if (!vis[v]) {\n                vis[v] = 1;\n                edges.emplace_back(u, v);\n                qq.push(v);\n            }\n        }\n\n        outCov.reset();\n        long long cost = pruneAndCost(edges, outCov);\n        outEdges.swap(edges);\n        outCost = cost;\n    }\n\n    bool trySwapImprove() {\n        vector<int> treeVerts;\n        treeVerts.reserve(bestEdges.size() * 2);\n        for (auto &e : bestEdges) {\n            if (!swapMark[e.first]) { swapMark[e.first] = 1; treeVerts.push_back(e.first); }\n            if (!swapMark[e.second]) { swapMark[e.second] = 1; treeVerts.push_back(e.second); }\n            if (swapAdj[e.first].empty()) swapTouched.push_back(e.first);\n            if (swapAdj[e.second].empty()) swapTouched.push_back(e.second);\n            swapAdj[e.first].push_back(e.second);\n            swapAdj[e.second].push_back(e.first);\n        }\n\n        unordered_set<int> treeSet;\n        treeSet.reserve(bestEdges.size() * 2);\n        for (auto &e : bestEdges) {\n            int a = e.first, b = e.second;\n            if (a > b) swap(a, b);\n            treeSet.insert(a * V + b);\n        }\n\n        vector<pair<int,int>> cand;\n        for (int u : treeVerts) {\n            for (int v : adj[u]) {\n                if (!swapMark[v]) continue;\n                if (u < v) {\n                    if (!treeSet.count(u * V + v)) cand.emplace_back(u, v);\n                }\n            }\n        }\n\n        if (cand.empty()) {\n            for (int v : swapTouched) swapAdj[v].clear();\n            swapTouched.clear();\n            for (int v : treeVerts) swapMark[v] = 0;\n            return false;\n        }\n\n        shuffle(cand.begin(), cand.end(), rng);\n\n        for (auto &e : cand) {\n            int u = e.first, v = e.second;\n            vector<int> path;\n            function<bool(int,int)> dfsPath = [&](int x, int p) -> bool {\n                if (x == v) { path.push_back(x); return true; }\n                for (int y : swapAdj[x]) if (y != p) {\n                    if (dfsPath(y, x)) { path.push_back(x); return true; }\n                }\n                return false;\n            };\n            dfsPath(u, -1);\n            reverse(path.begin(), path.end());\n\n            vector<pair<int,int>> pw;\n            for (int i = 0; i < (int)path.size() - 1; ++i) {\n                int a = path[i], b = path[i + 1];\n                pw.push_back({w[ui[a]][uj[a]] + w[ui[b]][uj[b]], i});\n            }\n            sort(pw.begin(), pw.end(), greater<pair<int,int>>());\n            int tryCnt = min(3, (int)pw.size());\n            for (int ti = 0; ti < tryCnt; ++ti) {\n                int idx = pw[ti].second;\n                int a = path[idx], b = path[idx + 1];\n                vector<pair<int,int>> newEdges = bestEdges;\n                newEdges.push_back(e);\n                bool removed = false;\n                for (int i = 0; i < (int)newEdges.size(); ++i) {\n                    int x = newEdges[i].first, y = newEdges[i].second;\n                    if ((x == a && y == b) || (x == b && y == a)) {\n                        newEdges[i] = newEdges.back();\n                        newEdges.pop_back();\n                        removed = true;\n                        break;\n                    }\n                }\n                if (!removed) continue;\n                bitset<1024> cov;\n                long long cost = pruneAndCost(newEdges, cov);\n                if (cov == allReq && cost < bestCost) {\n                    bestCost = cost;\n                    bestEdges.swap(newEdges);\n                    for (int vv : swapTouched) swapAdj[vv].clear();\n                    swapTouched.clear();\n                    for (int vv : treeVerts) swapMark[vv] = 0;\n                    return true;\n                }\n            }\n        }\n\n        for (int v : swapTouched) swapAdj[v].clear();\n        swapTouched.clear();\n        for (int v : treeVerts) swapMark[v] = 0;\n        return false;\n    }\n\n    bool tryShake() {\n        vector<int> treeVerts;\n        treeVerts.reserve(bestEdges.size() * 2);\n        for (auto &e : bestEdges) {\n            if (!swapMark[e.first]) { swapMark[e.first] = 1; treeVerts.push_back(e.first); }\n            if (!swapMark[e.second]) { swapMark[e.second] = 1; treeVerts.push_back(e.second); }\n            if (swapAdj[e.first].empty()) swapTouched.push_back(e.first);\n            if (swapAdj[e.second].empty()) swapTouched.push_back(e.second);\n            swapAdj[e.first].push_back(e.second);\n            swapAdj[e.second].push_back(e.first);\n        }\n        vector<int> parentT(V, -1);\n        vector<char> inT(V, 0);\n        queue<int> qq;\n        qq.push(S); inT[S] = 1;\n        vector<int> bfsOrder;\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            bfsOrder.push_back(u);\n            for (int v : swapAdj[u]) if (!inT[v]) {\n                inT[v] = 1; parentT[v] = u; qq.push(v);\n            }\n        }\n        vector<int> deg(V, 0);\n        for (int u : treeVerts) deg[u] = (int)swapAdj[u].size();\n\n        vector<pair<int,int>> keep;\n        bool ok = true;\n\n        if ((rng() & 1) && bestEdges.size() > 1) {\n            vector<int> childs;\n            for (int u : bfsOrder) if (parentT[u] != -1) childs.push_back(u);\n            if (childs.empty()) ok = false;\n            else {\n                int child = childs[rng() % childs.size()];\n                vector<int> stack = {child};\n                vector<char> sub(V, 0);\n                sub[child] = 1;\n                for (size_t i = 0; i < stack.size(); ++i) {\n                    int u = stack[i];\n                    for (int v : swapAdj[u]) {\n                        if (v == parentT[u]) continue;\n                        if (!sub[v]) { sub[v] = 1; stack.push_back(v); }\n                    }\n                }\n                if (stack.size() > treeVerts.size() * 2 / 3) {\n                    ok = false;\n                } else {\n                    for (auto &e : bestEdges)\n                        if (!sub[e.first] && !sub[e.second]) keep.push_back(e);\n                }\n            }\n        } else {\n            vector<int> leaves;\n            for (int u : treeVerts)\n                if (deg[u] == 1 && u != S) leaves.push_back(u);\n            if (leaves.empty()) ok = false;\n            else {\n                int leaf = leaves[rng() % leaves.size()];\n                vector<char> sub(V, 0);\n                int cur = leaf, prev = -1;\n                while (true) {\n                    sub[cur] = 1;\n                    int nxt = -1;\n                    for (int v : swapAdj[cur]) if (v != prev) { nxt = v; break; }\n                    if (nxt == -1 || nxt == S) break;\n                    if (deg[nxt] > 2) break;\n                    prev = cur;\n                    cur = nxt;\n                }\n                for (auto &e : bestEdges)\n                    if (!sub[e.first] && !sub[e.second]) keep.push_back(e);\n            }\n        }\n\n        for (int v : swapTouched) swapAdj[v].clear();\n        swapTouched.clear();\n        for (int v : treeVerts) swapMark[v] = 0;\n\n        if (!ok) return false;\n\n        vector<pair<int,int>> newEdges;\n        bitset<1024> newCov;\n        long long c = greedyBuild(keep, rng() % 3, newEdges, newCov);\n        if (newCov == allReq && c < bestCost) {\n            bestCost = c;\n            bestEdges.swap(newEdges);\n            return true;\n        }\n        return false;\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n        rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n        auto startTime = chrono::steady_clock::now();\n        auto elapsed = [&]() {\n            return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        };\n\n        if (!(cin >> N >> si >> sj)) return;\n        g.resize(N);\n        for (int i = 0; i < N; ++i) cin >> g[i];\n        w.assign(N, vector<int>(N, 0));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (g[i][j] != '#') w[i][j] = g[i][j] - '0';\n\n        vector<vector<int>> id(N, vector<int>(N, -1));\n        queue<pair<int,int>> q;\n        q.emplace(si, sj);\n        id[si][sj] = 0;\n        ui.push_back(si); uj.push_back(sj);\n        while (!q.empty()) {\n            auto [i, j] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (g[ni][nj] == '#') continue;\n                if (id[ni][nj] == -1) {\n                    id[ni][nj] = (int)ui.size();\n                    ui.push_back(ni);\n                    uj.push_back(nj);\n                    q.emplace(ni, nj);\n                }\n            }\n        }\n        V = (int)ui.size();\n        S = id[si][sj];\n        adj.assign(V, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1)\n                    adj[u].push_back(id[ni][nj]);\n            }\n        }\n\n        vector<vector<int>> hId(N, vector<int>(N, -1));\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ) {\n                if (g[i][j] == '#') { ++j; continue; }\n                int j0 = j;\n                while (j < N && g[i][j] != '#') ++j;\n                if (j - j0 >= 2) {\n                    for (int k = j0; k < j; ++k) hId[i][k] = Hreq;\n                    ++Hreq;\n                }\n            }\n        }\n        vector<vector<int>> vId(N, vector<int>(N, -1));\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ) {\n                if (g[i][j] == '#') { ++i; continue; }\n                int i0 = i;\n                while (i < N && g[i][j] != '#') ++i;\n                if (i - i0 >= 2) {\n                    for (int k = i0; k < i; ++k) vId[k][j] = Vreq;\n                    ++Vreq;\n                }\n            }\n        }\n        R = Hreq + Vreq;\n        allReq.reset();\n        for (int i = 0; i < R; ++i) allReq.set(i);\n        cellMask.assign(V, bitset<1024>());\n        groupCells.assign(R, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            if (hId[i][j] != -1) {\n                cellMask[u].set(hId[i][j]);\n                groupCells[hId[i][j]].push_back(u);\n            }\n            if (vId[i][j] != -1) {\n                cellMask[u].set(Hreq + vId[i][j]);\n                groupCells[Hreq + vId[i][j]].push_back(u);\n            }\n        }\n\n        if (R == 0) {\n            cout << \"\\n\";\n            return;\n        }\n\n        dist.assign(V, INF);\n        parent.assign(V, -1);\n        heapPos.assign(V, -1);\n        order.reserve(V);\n        pathMask.assign(V, bitset<1024>());\n        dijHeap.init(&dist, &heapPos);\n\n        swapAdj.assign(V, {});\n        swapMark.assign(V, 0);\n        swapTouched.reserve(V);\n        vertId.assign(V, -1);\n\n        /* Phase 1: Prim baselines */\n        for (int iter = 0; iter < 15; ++iter) {\n            if (elapsed() > 0.3) break;\n            auto [edges, cost] = primFull(iter > 0);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestEdges = edges;\n            }\n        }\n\n        /* Phase 2: Metric closure MST baselines */\n        for (int iter = 0; iter < 20; ++iter) {\n            if (elapsed() > 1.0) break;\n            vector<pair<int,int>> edges;\n            long long cost;\n            bitset<1024> cov;\n            metricClosureMST(iter > 0, edges, cost, cov);\n            if (cov == allReq && cost < bestCost) {\n                bestCost = cost;\n                bestEdges.swap(edges);\n            }\n        }\n\n        /* Phase 3: Greedy baselines */\n        for (int iter = 0; iter < 80; ++iter) {\n            if (elapsed() > 1.8) break;\n            vector<pair<int,int>> edges;\n            bitset<1024> cov;\n            long long c = greedyBuild({}, iter % 3, edges, cov);\n            if (cov == allReq && c < bestCost) {\n                bestCost = c;\n                bestEdges.swap(edges);\n            }\n        }\n\n        /* Phase 4: Local search */\n        const double TL = 2.95;\n        int swapFail = 0;\n        while (elapsed() < TL) {\n            if (trySwapImprove()) {\n                swapFail = 0;\n            } else {\n                ++swapFail;\n                if (swapFail >= 15) {\n                    bool improved = tryShake();\n                    if (improved) {\n                        swapFail = 0;\n                    } else if (elapsed() < TL - 0.3) {\n                        vector<pair<int,int>> edges;\n                        bitset<1024> cov;\n                        long long c = greedyBuild({}, rng() % 3, edges, cov);\n                        if (cov == allReq && c < bestCost) {\n                            bestCost = c;\n                            bestEdges.swap(edges);\n                            swapFail = 0;\n                        }\n                    }\n                }\n            }\n        }\n\n        /* Output doubled DFS tour */\n        vector<vector<int>> finalAdj(V);\n        for (auto &e : bestEdges) {\n            finalAdj[e.first].push_back(e.second);\n            finalAdj[e.second].push_back(e.first);\n        }\n        string tour;\n        function<void(int,int)> dfs = [&](int u, int p) {\n            for (int v : finalAdj[u]) if (v != p) {\n                tour.push_back(dc[dirMove(u, v)]);\n                dfs(v, u);\n                tour.push_back(dc[dirMove(v, u)]);\n            }\n        };\n        dfs(S, -1);\n        cout << tour << \"\\n\";\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.run();\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, K, R;\nvector<vector<int>> task_d;\nvector<int> task_sumd;\nvector<vector<int>> dag_out;\nvector<int> out_deg;\nvector<int> indeg0;\n\nvector<double> down_len;\nvector<int> wait_cnt;\n\nvector<vector<double>> skill_est;\nvector<vector<pair<int,int>>> history;\n\nvector<int> worker_task;\nvector<int> worker_start;\nvector<int> worker_done_cnt;\n\nvector<int> rem_indeg;\nvector<int> ready;\n\nmt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\ninline double pred_dur(int task, int w) {\n    double wsum = 0.0;\n    const auto &td = task_d[task];\n    const auto &sk = skill_est[w];\n    for (int k = 0; k < K; ++k) {\n        if (td[k] > sk[k]) wsum += td[k] - sk[k];\n    }\n    return wsum < 1.0 ? 1.0 : wsum;\n}\n\nvoid recompute_down_len() {\n    vector<double> mindur(N);\n    for (int i = 0; i < N; ++i) {\n        double best = 1e100;\n        for (int j = 0; j < M; ++j)\n            best = min(best, pred_dur(i, j));\n        mindur[i] = best;\n    }\n    for (int i = N - 1; i >= 0; --i) {\n        double child = 0.0;\n        for (int v : dag_out[i]) child = max(child, down_len[v]);\n        down_len[i] = mindur[i] + child;\n    }\n}\n\n/* Hungarian for n rows, m cols (n <= m), minimisation, 1-indexed inside */\nvector<int> hungarian(const vector<vector<double>>& a) {\n    int n = (int)a.size() - 1;\n    int m = (int)a[0].size() - 1;\n    const double INF = 1e100;\n    vector<double> u(n + 1), v(m + 1);\n    vector<int> p(m + 1), way(m + 1);\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        vector<double> minv(m + 1, INF);\n        vector<char> used(m + 1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0], j1 = 0;\n            double delta = INF;\n            for (int j = 1; j <= m; ++j) if (!used[j]) {\n                double cur = a[i0][j] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= m; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n    vector<int> ans(n + 1);\n    for (int j = 1; j <= m; ++j)\n        if (p[j] != 0)\n            ans[p[j]] = j;\n    return ans;\n}\n\nvoid update_skills(int w) {\n    auto &hist = history[w];\n    if (hist.empty()) return;\n    double lr = max(0.015, 0.4 / sqrt((double)hist.size()));\n    const double LR2 = 0.03;\n    const int EPOCHS = 15;\n    for (int ep = 0; ep < EPOCHS; ++ep) {\n        shuffle(hist.begin(), hist.end(), rng);\n        for (auto &ob : hist) {\n            int tid = ob.first;\n            int odur = ob.second;\n            const auto &td = task_d[tid];\n\n            /* Bayesian posterior mean targets under uniform prior */\n            double target, weight;\n            if (odur == 1) {\n                target = 1.0;   weight = 0.5;\n            } else if (odur == 2) {\n                target = 2.5;   weight = 0.8;\n            } else if (odur == 3) {\n                target = 3.0;   weight = 0.9;\n            } else {\n                target = (double)odur;  weight = 1.0;\n            }\n\n            double wpred = 0.0;\n            vector<int> active;\n            active.reserve(K);\n            for (int k = 0; k < K; ++k) {\n                if (td[k] > skill_est[w][k] + 1e-12) {\n                    wpred += td[k] - skill_est[w][k];\n                    active.push_back(k);\n                }\n            }\n\n            double err = wpred - target;\n            if (fabs(err) < 1e-9) continue;\n\n            if (!active.empty()) {\n                double delta = lr * err * weight / active.size();\n                if (delta >  5.0) delta =  5.0;\n                if (delta < -5.0) delta = -5.0;\n                for (int k : active) {\n                    skill_est[w][k] += delta;\n                    if (skill_est[w][k] < 0.0) skill_est[w][k] = 0.0;\n                }\n            } else if (err < 0.0) {\n                /* Focus on the dimension with smallest margin */\n                int best_k = -1;\n                double best_margin = 1e100;\n                for (int k = 0; k < K; ++k) {\n                    double margin = skill_est[w][k] - td[k];\n                    if (margin < best_margin) {\n                        best_margin = margin;\n                        best_k = k;\n                    }\n                }\n                if (best_k >= 0 && best_margin >= 0.0) {\n                    double dec = LR2 * (-err) * weight;\n                    if (dec > 5.0) dec = 5.0;\n                    skill_est[w][best_k] -= dec;\n                    if (skill_est[w][best_k] < 0.0) skill_est[w][best_k] = 0.0;\n                }\n            }\n        }\n    }\n}\n\n/* assign tasks for the coming day */\nvector<pair<int,int>> assign_day(int day) {\n    vector<pair<int,int>> out_pairs;\n    vector<int> idle;\n    for (int j = 0; j < M; ++j)\n        if (worker_task[j] == -1) idle.push_back(j);\n\n    if (idle.empty() || ready.empty()) return out_pairs;\n\n    vector<int> avail = ready;\n\n    /* ---- exploration: first 2 short tasks per inexperienced worker ---- */\n    vector<int> explorers;\n    for (int j : idle)\n        if (worker_done_cnt[j] < 2) explorers.push_back(j);\n\n    if (!explorers.empty() && !avail.empty()) {\n        vector<int> pool;\n        for (int t : avail)\n            if (task_sumd[t] > 0 && task_sumd[t] < 40) pool.push_back(t);\n        if (pool.empty()) {\n            sort(avail.begin(), avail.end(),\n                 [&](int a, int b){ return task_sumd[a] < task_sumd[b]; });\n            int take = min((int)avail.size(), (int)explorers.size() + 3);\n            pool.assign(avail.begin(), avail.begin() + take);\n        }\n        shuffle(pool.begin(), pool.end(), rng);\n        for (int j : explorers) {\n            if (pool.empty()) break;\n            int t = pool.back(); pool.pop_back();\n            auto it = find(avail.begin(), avail.end(), t);\n            if (it != avail.end()) avail.erase(it);\n            out_pairs.emplace_back(j, t);\n            worker_task[j] = t;\n            worker_start[j] = day;\n        }\n    }\n\n    /* ---- exploitation: Hungarian matching ---- */\n    vector<int> idle2;\n    for (int j : idle)\n        if (worker_task[j] == -1) idle2.push_back(j);\n\n    if (!idle2.empty() && !avail.empty()) {\n        int nW = (int)idle2.size();\n        int nT = (int)avail.size();\n\n        vector<pair<int,int>> matched;\n        if (nW <= nT) {\n            vector<vector<double>> cost(nW + 1, vector<double>(nT + 1));\n            for (int i = 1; i <= nW; ++i) {\n                for (int j = 1; j <= nT; ++j) {\n                    double pd = pred_dur(avail[j - 1], idle2[i - 1]);\n                    double c = pd\n                             - 0.10 * down_len[avail[j - 1]]\n                             - 0.28 * min(wait_cnt[avail[j - 1]], 40)\n                             - 0.03 * out_deg[avail[j - 1]];\n                    c += uniform_real_distribution<double>(-1e-9, 1e-9)(rng);\n                    cost[i][j] = c;\n                }\n            }\n            auto ans = hungarian(cost);\n            for (int i = 1; i <= nW; ++i) {\n                int t = avail[ans[i] - 1];\n                matched.emplace_back(idle2[i - 1], t);\n            }\n        } else {\n            vector<vector<double>> cost(nT + 1, vector<double>(nW + 1));\n            for (int i = 1; i <= nT; ++i) {\n                for (int j = 1; j <= nW; ++j) {\n                    double pd = pred_dur(avail[i - 1], idle2[j - 1]);\n                    double c = pd\n                             - 0.10 * down_len[avail[i - 1]]\n                             - 0.28 * min(wait_cnt[avail[i - 1]], 40)\n                             - 0.03 * out_deg[avail[i - 1]];\n                    c += uniform_real_distribution<double>(-1e-9, 1e-9)(rng);\n                    cost[i][j] = c;\n                }\n            }\n            auto ans = hungarian(cost);\n            for (int i = 1; i <= nT; ++i) {\n                int w = idle2[ans[i] - 1];\n                matched.emplace_back(w, avail[i - 1]);\n            }\n        }\n\n        for (auto &p : matched) {\n            int j = p.first, t = p.second;\n            out_pairs.emplace_back(j, t);\n            worker_task[j] = t;\n            worker_start[j] = day;\n        }\n    }\n\n    /* erase assigned tasks from the global ready list */\n    vector<char> mark(N, 0);\n    for (auto &p : out_pairs) mark[p.second] = 1;\n    vector<int> new_ready;\n    new_ready.reserve(ready.size());\n    for (int t : ready)\n        if (!mark[t]) new_ready.push_back(t);\n    ready.swap(new_ready);\n    return out_pairs;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    task_d.assign(N, vector<int>(K));\n    task_sumd.assign(N, 0);\n    for (int i = 0; i < N; ++i) {\n        int s = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> task_d[i][k];\n            s += task_d[i][k];\n        }\n        task_sumd[i] = s;\n    }\n\n    dag_out.assign(N, {});\n    indeg0.assign(N, 0);\n    out_deg.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v; cin >> u >> v; --u; --v;\n        dag_out[u].push_back(v);\n        ++indeg0[v];\n        ++out_deg[u];\n    }\n\n    wait_cnt.assign(N, 0);\n    skill_est.assign(M, vector<double>(K, 0.0));\n\n    /* initialise with mean difficulty * 1.2 (workers slightly stronger on avg) */\n    vector<double> mean_d(K, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            mean_d[k] += task_d[i][k];\n    for (int k = 0; k < K; ++k) mean_d[k] /= N;\n    for (int j = 0; j < M; ++j)\n        for (int k = 0; k < K; ++k)\n            skill_est[j][k] = mean_d[k] * 1.2;\n\n    history.assign(M, {});\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    worker_done_cnt.assign(M, 0);\n    rem_indeg = indeg0;\n    ready.clear();\n    for (int i = 0; i < N; ++i)\n        if (rem_indeg[i] == 0) ready.push_back(i);\n\n    down_len.assign(N, 1.0);\n    recompute_down_len();\n\n    int day = 1;\n    auto assignments = assign_day(day);\n\n    while (true) {\n        cout << assignments.size();\n        for (auto &p : assignments)\n            cout << ' ' << p.first + 1 << ' ' << p.second + 1;\n        cout << '\\n';\n        cout.flush();\n\n        int n;  cin >> n;\n        if (n == -1) break;\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int t : ready) ++wait_cnt[t];\n\n        bool updated = false;\n        for (int j : finished) {\n            int t = worker_task[j];\n            int dur = day - worker_start[j] + 1;\n\n            history[j].emplace_back(t, dur);\n            update_skills(j);\n\n            worker_task[j] = -1;\n            worker_start[j] = -1;\n            ++worker_done_cnt[j];\n            updated = true;\n\n            for (int v : dag_out[t]) {\n                if (--rem_indeg[v] == 0)\n                    ready.push_back(v);\n            }\n        }\n\n        if (updated) recompute_down_len();\n\n        ++day;\n        if (day > 2000) break;\n        assignments = assign_day(day);\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nint Xc[2001];\nint Yc[2001];\nint dist_mat[2001][2001];\ninline int D(int u, int v) { return dist_mat[u][v]; }\n\n/* node 0 = depot (400,400)\n   order i (0-based): pickup = 2*i+1, delivery = 2*i+2 */\ninline int partner(int v) {\n    if (v & 1) return v + 1;   // pickup -> delivery\n    return v - 1;              // delivery -> pickup\n}\n\n/* ---------- insertion helpers ---------- */\nvoid eval_insert(const vector<int>& route, int oid, int& best_delta, int& best_ip, int& best_id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    int L = (int)route.size();\n    best_delta = INT_MAX;\n    for (int ip = 0; ip < L - 1; ++ip) {\n        int cost_p = D(route[ip], p) + D(p, route[ip + 1]) - D(route[ip], route[ip + 1]);\n        int left = p;\n        for (int id = ip; id < L - 1; ++id) {\n            if (id > ip) left = route[id];\n            int cost_d = D(left, d) + D(d, route[id + 1]) - D(left, route[id + 1]);\n            int delta = cost_p + cost_d;\n            if (delta < best_delta) {\n                best_delta = delta;\n                best_ip = ip;\n                best_id = id;\n            }\n        }\n    }\n}\n\nvoid eval_insert_regret(const vector<int>& route, int oid,\n                        int& best_delta, int& best_ip, int& best_id, int& second_delta) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    int L = (int)route.size();\n    best_delta = INT_MAX;\n    second_delta = INT_MAX;\n    for (int ip = 0; ip < L - 1; ++ip) {\n        int cost_p = D(route[ip], p) + D(p, route[ip + 1]) - D(route[ip], route[ip + 1]);\n        int left = p;\n        for (int id = ip; id < L - 1; ++id) {\n            if (id > ip) left = route[id];\n            int cost_d = D(left, d) + D(d, route[id + 1]) - D(left, route[id + 1]);\n            int delta = cost_p + cost_d;\n            if (delta < best_delta) {\n                second_delta = best_delta;\n                best_delta = delta;\n                best_ip = ip;\n                best_id = id;\n            } else if (delta < second_delta) {\n                second_delta = delta;\n            }\n        }\n    }\n}\n\nvoid apply_insert(vector<int>& route, int oid, int ip, int id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() + 2);\n    for (int k = 0; k <= ip; ++k) res.push_back(route[k]);\n    res.push_back(p);\n    for (int k = ip + 1; k <= id; ++k) res.push_back(route[k]);\n    res.push_back(d);\n    for (int k = id + 1; k < (int)route.size(); ++k) res.push_back(route[k]);\n    route.swap(res);\n}\n\nvector<int> remove_order(const vector<int>& route, int oid) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() - 2);\n    for (int node : route) if (node != p && node != d) res.push_back(node);\n    return res;\n}\n\nint route_cost(const vector<int>& route) {\n    int sum = 0;\n    for (int i = 0; i + 1 < (int)route.size(); ++i) sum += D(route[i], route[i + 1]);\n    return sum;\n}\n\n/* ---------- local search ---------- */\nbool optimize_pass(vector<int>& route, int& cost) {\n    int n = (int)route.size();\n    vector<int> pos(2001, -1);\n    for (int i = 0; i < n; ++i) pos[route[i]] = i;\n\n    vector<int> pp(n);\n    for (int i = 1; i < n - 1; ++i) pp[i] = pos[partner(route[i])];\n\n    int best_delta = 0;\n    int best_type = -1;          // 0 swap, 1 2opt, 2 relocate\n    int b_i = 0, b_j = 0, b_l = 0, b_r = 0;\n\n    // 1. swap two internal nodes\n    for (int i = 1; i < n - 1; ++i) {\n        for (int j = i + 1; j < n - 1; ++j) {\n            int u = route[i], v = route[j];\n            if (partner(u) == v) continue;               // same order\n            if ((u & 1) && pp[i] <= j) continue;         // pickup must stay before delivery\n            if (!(v & 1) && pp[j] >= i) continue;        // delivery must stay after pickup\n            int delta;\n            if (j == i + 1) {\n                delta = D(route[i - 1], v) + D(v, u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, v) - D(v, route[j + 1]);\n            } else {\n                delta = D(route[i - 1], v) + D(v, route[i + 1])\n                      + D(route[j - 1], u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, route[i + 1])\n                      - D(route[j - 1], v) - D(v, route[j + 1]);\n            }\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 0; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    // 2. 2-opt (segment reversal)\n    for (int l = 1; l < n - 1; ++l) {\n        for (int r = l + 1; r < n - 1; ++r) {\n            bool ok = true;\n            for (int k = l; k <= r; ++k) {\n                if (pp[k] >= l && pp[k] <= r) { ok = false; break; }\n            }\n            if (!ok) continue;\n            int delta = D(route[l - 1], route[r]) + D(route[l], route[r + 1])\n                      - D(route[l - 1], route[l]) - D(route[r], route[r + 1]);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 1; b_l = l; b_r = r;\n            }\n        }\n    }\n\n    // 3. relocate a single node\n    for (int i = 1; i < n - 1; ++i) {\n        int u = route[i];\n        int A = route[i - 1], B = route[i + 1];\n        int delta_remove = D(A, B) - D(A, u) - D(u, B);\n        // move left: j < i\n        for (int j = 1; j < i; ++j) {\n            if (!(u & 1) && j <= pp[i]) continue; // delivery cannot pass its pickup\n            int left = route[j - 1], right = route[j];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n        // move right: j > i\n        for (int j = i + 1; j < n - 1; ++j) {\n            if ((u & 1) && j >= pp[i]) continue; // pickup cannot pass its delivery\n            int left = route[j], right = route[j + 1];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    if (best_type == -1) return false;\n\n    if (best_type == 0) {\n        swap(route[b_i], route[b_j]);\n    } else if (best_type == 1) {\n        reverse(route.begin() + b_l, route.begin() + b_r + 1);\n    } else {\n        int u = route[b_i];\n        route.erase(route.begin() + b_i);\n        route.insert(route.begin() + b_j, u);\n    }\n    cost += best_delta;\n    return true;\n}\n\nvoid optimize_route(vector<int>& route, int& cost) {\n    while (optimize_pass(route, cost)) {}\n}\n\n/* ---------- construction ---------- */\nstruct State {\n    vector<int> route;\n    vector<int> selected;\n    int cost;\n};\n\nState greedy_build_rand(int rand_k, mt19937& rng) {\n    State st;\n    st.route = {0, 0};\n    st.selected.reserve(50);\n    vector<char> used(1000, 0);\n    struct Cand { int delta, oid, ip, id; };\n    for (int step = 0; step < 50; ++step) {\n        vector<Cand> cands;\n        cands.reserve(1000);\n        for (int oid = 0; oid < 1000; ++oid) if (!used[oid]) {\n            int d, ip, id;\n            eval_insert(st.route, oid, d, ip, id);\n            cands.push_back({d, oid, ip, id});\n        }\n        sort(cands.begin(), cands.end(),\n             [](const Cand& a, const Cand& b){ return a.delta < b.delta; });\n        int k = min(rand_k, max(1, (int)cands.size()));\n        int pick = uniform_int_distribution<int>(0, k - 1)(rng);\n        const Cand& c = cands[pick];\n        apply_insert(st.route, c.oid, c.ip, c.id);\n        used[c.oid] = 1;\n        st.selected.push_back(c.oid);\n    }\n    st.cost = route_cost(st.route);\n    return st;\n}\n\nState greedy_build_regret(mt19937& rng) {\n    State st;\n    st.route = {0, 0};\n    st.selected.reserve(50);\n    vector<char> used(1000, 0);\n    for (int step = 0; step < 50; ++step) {\n        int best_oid = -1, best_ip = 0, best_id = 0;\n        int max_regret = -1;\n        for (int oid = 0; oid < 1000; ++oid) if (!used[oid]) {\n            int d1, ip1, id1, d2;\n            eval_insert_regret(st.route, oid, d1, ip1, id1, d2);\n            int regret = (d2 >= INT_MAX / 2) ? 0 : (d2 - d1);\n            if (regret > max_regret) {\n                max_regret = regret;\n                best_oid = oid;\n                best_ip = ip1;\n                best_id = id1;\n            }\n        }\n        apply_insert(st.route, best_oid, best_ip, best_id);\n        used[best_oid] = 1;\n        st.selected.push_back(best_oid);\n    }\n    st.cost = route_cost(st.route);\n    return st;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    vector<int> ax(1000), ay(1000), cx(1000), cy(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n    }\n\n    Xc[0] = Yc[0] = 400;\n    for (int i = 0; i < 1000; ++i) {\n        Xc[2 * i + 1] = ax[i]; Yc[2 * i + 1] = ay[i];\n        Xc[2 * i + 2] = cx[i]; Yc[2 * i + 2] = cy[i];\n    }\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist_mat[i][j] = abs(Xc[i] - Xc[j]) + abs(Yc[i] - Yc[j]);\n\n    vector<int> standalone(1000);\n    for (int i = 0; i < 1000; ++i)\n        standalone[i] = D(0, 2 * i + 1) + D(2 * i + 1, 2 * i + 2) + D(2 * i + 2, 0);\n\n    vector<int> order_ids(1000);\n    iota(order_ids.begin(), order_ids.end(), 0);\n    sort(order_ids.begin(), order_ids.end(),\n         [&](int a, int b){ return standalone[a] < standalone[b]; });\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]()->double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n    const double TL = 1.95;\n\n    State best;\n    best.cost = INT_MAX;\n\n    /* ---- Phase 1: many diversified constructions ---- */\n    int attempt = 0;\n    while (elapsed() < TL * 0.70) {\n        ++attempt;\n        State cur;\n        if (attempt % 5 == 0) {\n            cur = greedy_build_regret(rng);\n        } else {\n            int k = 2 + (attempt % 4); // 2..5\n            cur = greedy_build_rand(k, rng);\n        }\n        optimize_route(cur.route, cur.cost);\n        if (cur.cost < best.cost) best = cur;\n    }\n\n    /* ---- Phase 2: intensive 1-swap on the best set ---- */\n    {\n        bool improved = true;\n        while (improved && elapsed() < TL * 0.88) {\n            improved = false;\n            vector<char> in_sel(1000, 0);\n            for (int oid : best.selected) in_sel[oid] = 1;\n            vector<int> cand_out;\n            for (int oid : order_ids) {\n                if (!in_sel[oid]) {\n                    cand_out.push_back(oid);\n                    if ((int)cand_out.size() >= 300) break;\n                }\n            }\n            int best_in = -1, best_out = -1, best_ip = -1, best_id = -1;\n            int best_new_cost = best.cost;\n            for (int oid_in : best.selected) {\n                if (elapsed() > TL * 0.88) break;\n                vector<int> tmp = remove_order(best.route, oid_in);\n                int tmp_cost = route_cost(tmp);\n                for (int oid_out : cand_out) {\n                    int dlt, ip, id;\n                    eval_insert(tmp, oid_out, dlt, ip, id);\n                    int ncost = tmp_cost + dlt;\n                    if (ncost < best_new_cost) {\n                        best_new_cost = ncost;\n                        best_in = oid_in;\n                        best_out = oid_out;\n                        best_ip = ip;\n                        best_id = id;\n                    }\n                }\n            }\n            if (best_in != -1) {\n                vector<int> nr = remove_order(best.route, best_in);\n                apply_insert(nr, best_out, best_ip, best_id);\n                best.route = move(nr);\n                best.cost = best_new_cost;\n                for (int& oid : best.selected) if (oid == best_in) { oid = best_out; break; }\n                optimize_route(best.route, best.cost);\n                improved = true;\n            }\n        }\n    }\n\n    /* ---- Phase 3: iterated local search by random 1-swap ---- */\n    State cur = best;\n    while (elapsed() < TL) {\n        int rem_idx = uniform_int_distribution<int>(0, 49)(rng);\n        int rem_oid = cur.selected[rem_idx];\n        vector<int> base = remove_order(cur.route, rem_oid);\n        int base_cost = route_cost(base);\n\n        vector<char> in_sel(1000, 0);\n        for (int oid : cur.selected) in_sel[oid] = 1;\n        in_sel[rem_oid] = 0;\n\n        int best_add = -1, best_ip = 0, best_id = 0;\n        int best_add_delta = INT_MAX;\n        for (int t = 0; t < 50; ++t) {\n            int add_oid = uniform_int_distribution<int>(0, 999)(rng);\n            if (in_sel[add_oid]) continue;\n            int dlt, ip, id;\n            eval_insert(base, add_oid, dlt, ip, id);\n            if (dlt < best_add_delta) {\n                best_add_delta = dlt;\n                best_add = add_oid;\n                best_ip = ip;\n                best_id = id;\n            }\n        }\n        if (best_add == -1) continue;\n\n        vector<int> nr = base;\n        apply_insert(nr, best_add, best_ip, best_id);\n        int nc = base_cost + best_add_delta;\n        optimize_route(nr, nc);\n        if (nc < cur.cost) {\n            cur.route = move(nr);\n            cur.cost = nc;\n            cur.selected[rem_idx] = best_add;\n            if (nc < best.cost) best = cur;\n        } else {\n            if (uniform_int_distribution<int>(0, 4)(rng) == 0) cur = best;\n        }\n    }\n\n    cout << best.selected.size();\n    for (int oid : best.selected) cout << ' ' << (oid + 1);\n    cout << \"\\n\";\n    cout << best.route.size();\n    for (int node : best.route) cout << ' ' << Xc[node] << ' ' << Yc[node];\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*** DSU ***/\nstruct DSU {\n    unsigned short p[400];\n    unsigned char r[400];\n    void init() {\n        for (int i = 0; i < 400; ++i) {\n            p[i] = (unsigned short)i;\n            r[i] = 0;\n        }\n    }\n    int find(int x) {\n        unsigned short *pp = p;\n        while (pp[x] != x) {\n            pp[x] = pp[pp[x]];\n            x = pp[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (r[a] < r[b]) swap(a, b);\n        p[b] = (unsigned short)a;\n        if (r[a] == r[b]) ++r[a];\n        return true;\n    }\n    bool same(int a, int b) {\n        return find(a) == find(b);\n    }\n};\n\n/*** LCA with max edge weight on tier-0 tree ***/\nstruct LCA {\n    int n, LOG;\n    vector<vector<pair<int,int>>> adj;\n    vector<vector<int>> up;\n    vector<vector<int>> mx;\n    vector<int> dep;\n    LCA(int n = 0) { init(n); }\n    void init(int n_) {\n        n = n_;\n        LOG = 1;\n        while ((1 << LOG) <= n) ++LOG;\n        adj.assign(n, {});\n        up.assign(LOG, vector<int>(n, -1));\n        mx.assign(LOG, vector<int>(n, 0));\n        dep.assign(n, 0);\n    }\n    void add_edge(int u, int v, int w) {\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n    void dfs(int v, int p, int d) {\n        up[0][v] = p;\n        dep[v] = d;\n        for (auto [to, w] : adj[v]) {\n            if (to == p) continue;\n            mx[0][to] = w;\n            dfs(to, v, d + 1);\n        }\n    }\n    void build(int root = 0) {\n        dfs(root, -1, 0);\n        for (int k = 1; k < LOG; ++k) {\n            for (int v = 0; v < n; ++v) {\n                if (up[k-1][v] != -1) {\n                    up[k][v] = up[k-1][ up[k-1][v] ];\n                    mx[k][v] = max(mx[k-1][v], mx[k-1][ up[k-1][v] ]);\n                }\n            }\n        }\n    }\n    int query(int u, int v) const {\n        if (u == v) return 0;\n        if (dep[u] < dep[v]) swap(u, v);\n        int res = 0;\n        int diff = dep[u] - dep[v];\n        for (int k = 0; k < LOG; ++k) {\n            if (diff >> k & 1) {\n                res = max(res, mx[k][u]);\n                u = up[k][u];\n            }\n        }\n        if (u == v) return res;\n        for (int k = LOG - 1; k >= 0; --k) {\n            if (up[k][u] != -1 && up[k][u] != up[k][v]) {\n                res = max(res, mx[k][u]);\n                res = max(res, mx[k][v]);\n                u = up[k][u];\n                v = up[k][v];\n            }\n        }\n        res = max(res, mx[0][u]);\n        res = max(res, mx[0][v]);\n        return res;\n    }\n};\n\n/*** Fast bucket Kruskal (weights <= 3600) ***/\nstruct Solver {\n    static const int MAXW = 3600;\n    static const int MAXE = 2005;\n    static const int MAXV = 400;\n\n    short U[MAXE];\n    short V[MAXE];\n    int nxt[MAXE];\n    int head[MAXW];\n    int vis[MAXW];\n    int ecnt;\n    int curVis;\n    int minW, maxW;\n\n    int par[MAXV];\n    unsigned char rnk[MAXV];\n\n    Solver() {\n        memset(vis, 0, sizeof(vis));\n        curVis = 1;\n    }\n\n    inline void clear() {\n        ecnt = 0;\n        ++curVis;\n        minW = MAXW;\n        maxW = 0;\n    }\n\n    inline void add(int w, short u, short v) {\n        if (vis[w] != curVis) {\n            vis[w] = curVis;\n            head[w] = -1;\n        }\n        U[ecnt] = u;\n        V[ecnt] = v;\n        nxt[ecnt] = head[w];\n        head[w] = ecnt++;\n        if (w < minW) minW = w;\n        if (w > maxW) maxW = w;\n    }\n\n    inline int find(int x) {\n        int root = x;\n        while (par[root] != root) root = par[root];\n        while (par[x] != x) {\n            int p = par[x];\n            par[x] = root;\n            x = p;\n        }\n        return root;\n    }\n\n    inline bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a, b);\n        par[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n\n    long long solve(int need) {\n        if (need <= 0) return 0;\n        for (int i = 0; i < MAXV; ++i) {\n            par[i] = i;\n            rnk[i] = 0;\n        }\n        int taken = 0;\n        long long sum = 0;\n        for (int w = minW; w <= maxW; ++w) {\n            if (vis[w] != curVis) continue;\n            for (int e = head[w]; e != -1; e = nxt[e]) {\n                if (unite(U[e], V[e])) {\n                    sum += w;\n                    if (++taken == need) return sum;\n                }\n            }\n        }\n        return sum;\n    }\n};\n\n/*** fast bounded RNG: returns value in [0, range) ***/\nstatic inline uint32_t rand_range(uint64_t &state, uint32_t range) {\n    state = state * 6364136223846793005ULL + 1;\n    return (uint32_t)(((state >> 32) * (uint64_t)range) >> 32);\n}\n\nint main() {\n    const int N = 400;\n    const int M = 1995;\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) scanf(\"%d %d\", &xs[i], &ys[i]);\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) scanf(\"%d %d\", &U[i], &V[i]);\n\n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        long long dx = (long long)xs[U[i]] - xs[V[i]];\n        long long dy = (long long)ys[U[i]] - ys[V[i]];\n        long long dist2 = dx * dx + dy * dy;\n        d[i] = (int)llround(sqrt((double)dist2));\n    }\n\n    /*--- tiers 0..4 by repeated Kruskal on d ---*/\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) { return d[a] < d[b]; });\n\n    vector<char> used(M, 0);\n    vector<int> tier(M, -1);\n    for (int t = 0; t < 5; ++t) {\n        DSU dsu_tier;\n        dsu_tier.init();\n        int cnt = 0;\n        for (int idx : order) {\n            if (used[idx]) continue;\n            if (dsu_tier.unite(U[idx], V[idx])) {\n                used[idx] = 1;\n                tier[idx] = t;\n                if (++cnt == N - 1) break;\n            }\n        }\n    }\n\n    /*--- tier-0 tree structures ---*/\n    LCA lca(N);\n    vector<vector<pair<int,int>>> tree_adj(N);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) {\n            lca.add_edge(U[i], V[i], d[i]);\n            tree_adj[U[i]].push_back({V[i], i});\n            tree_adj[V[i]].push_back({U[i], i});\n        }\n    }\n    lca.build(0);\n\n    vector<int> maxd_path(M, 0);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) maxd_path[i] = d[i];\n        else               maxd_path[i] = lca.query(U[i], V[i]);\n    }\n\n    int parent[400];\n    int parent_edge[400];\n    int depth[400];\n    function<void(int,int)> dfs = [&](int v, int p) {\n        for (auto [to, eidx] : tree_adj[v]) {\n            if (to == p) continue;\n            parent[to] = v;\n            parent_edge[to] = eidx;\n            depth[to] = depth[v] + 1;\n            dfs(to, v);\n        }\n    };\n    parent[0] = -1;\n    parent_edge[0] = -1;\n    depth[0] = 0;\n    dfs(0, -1);\n\n    const int INF = 1e9;\n    vector<int> rep_d(M, INF);\n    vector<int> max_cross_d(M, 0);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) continue;\n        int u = U[i], v = V[i];\n        while (depth[u] > depth[v]) {\n            int eidx = parent_edge[u];\n            if (d[i] < rep_d[eidx]) rep_d[eidx] = d[i];\n            if (d[i] > max_cross_d[eidx]) max_cross_d[eidx] = d[i];\n            u = parent[u];\n        }\n        while (depth[v] > depth[u]) {\n            int eidx = parent_edge[v];\n            if (d[i] < rep_d[eidx]) rep_d[eidx] = d[i];\n            if (d[i] > max_cross_d[eidx]) max_cross_d[eidx] = d[i];\n            v = parent[v];\n        }\n        while (u != v) {\n            int eidx_u = parent_edge[u];\n            if (d[i] < rep_d[eidx_u]) rep_d[eidx_u] = d[i];\n            if (d[i] > max_cross_d[eidx_u]) max_cross_d[eidx_u] = d[i];\n            u = parent[u];\n            int eidx_v = parent_edge[v];\n            if (d[i] < rep_d[eidx_v]) rep_d[eidx_v] = d[i];\n            if (d[i] > max_cross_d[eidx_v]) max_cross_d[eidx_v] = d[i];\n            v = parent[v];\n        }\n    }\n\n    /*--- online decisions ---*/\n    DSU dsu;\n    dsu.init();\n    int comp = N;\n\n    Solver solver_rej, solver_acc;\n    uint64_t rng = 123456789123456789ULL;\n\n    short buf_a[M];\n    short buf_b[M];\n    short buf_d[M];\n    uint16_t buf_r[M];\n\n    short acc_a[M];\n    short acc_b[M];\n    int acc_idx[M];\n    int wbuf[M];\n    int comp_of[400];\n\n    const double ACC_QUICK[5] = {1.15, 1.12, 1.08, 1.04, 1.02};\n    const double REJ_QUICK[5] = {2.80, 2.75, 2.70, 2.60, 2.50};\n\n    for (int i = 0; i < M; ++i) {\n        long long l;\n        scanf(\"%lld\", &l);\n        int u = U[i], v = V[i];\n\n        if (dsu.same(u, v)) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        for (int x = 0; x < N; ++x) comp_of[x] = dsu.find(x);\n        int cu = comp_of[u];\n        int cv = comp_of[v];\n\n        /* bridge check (with early stop) + buffer construction */\n        DSU tmp = dsu;\n        int E = 0;\n        bool connected = false;\n        for (int j = i + 1; j < M; ++j) {\n            int a = comp_of[U[j]];\n            int b = comp_of[V[j]];\n            if (a == b) continue;\n            buf_a[E] = (short)a;\n            buf_b[E] = (short)b;\n            buf_d[E] = (short)d[j];\n            buf_r[E] = (uint16_t)(2 * d[j] + 1);\n            ++E;\n            if (!connected) {\n                tmp.unite(a, b);\n                if (tmp.same(cu, cv)) connected = true;\n            }\n        }\n\n        if (!connected) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n\n        /* guaranteed accepts */\n        if (tier[i] == 0 && l < rep_d[i]) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n\n        /* guaranteed rejects */\n        if (tier[i] == 0 && max_cross_d[i] > 0 && l > 3LL * max_cross_d[i]) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n        if (tier[i] > 0 && l > 3LL * maxd_path[i]) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        double ratio = (double)l / (double)d[i];\n        if (ratio <= ACC_QUICK[tier[i]]) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n        if (ratio >= REJ_QUICK[tier[i]]) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        /* precompute contracted endpoints for accept solver */\n        int E_acc = 0;\n        for (int k = 0; k < E; ++k) {\n            int a2 = buf_a[k];\n            int b2 = buf_b[k];\n            if (a2 == cv) a2 = cu;\n            if (b2 == cv) b2 = cu;\n            if (a2 != b2) {\n                acc_idx[E_acc] = k;\n                acc_a[E_acc] = (short)a2;\n                acc_b[E_acc] = (short)b2;\n                ++E_acc;\n            }\n        }\n\n        /* adaptive sample count */\n        int K;\n        if (comp > 300) K = 20;\n        else if (comp > 200) K = 30;\n        else if (comp > 100) K = 45;\n        else K = 65;\n\n        long long total = 0;\n        for (int s = 0; s < K; ++s) {\n            solver_rej.clear();\n            solver_acc.clear();\n            for (int k = 0; k < E; ++k) {\n                wbuf[k] = buf_d[k] + (int)rand_range(rng, (uint32_t)buf_r[k]);\n                solver_rej.add(wbuf[k], buf_a[k], buf_b[k]);\n            }\n            for (int k = 0; k < E_acc; ++k) {\n                int idx = acc_idx[k];\n                solver_acc.add(wbuf[idx], acc_a[k], acc_b[k]);\n            }\n            long long w_rej = solver_rej.solve(comp - 1);\n            long long w_acc = l + solver_acc.solve(comp - 2);\n            total += w_acc - w_rej;\n        }\n\n        if (total < 0) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n        } else {\n            printf(\"0\\n\");\n            fflush(stdout);\n        }\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int MAX_TURN = 300;\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char BUILD[4] = {'u', 'd', 'l', 'r'};\nconst char MOVE[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n};\n\nbool in_bounds(int x, int y) {\n    return x >= 0 && x < H && y >= 0 && y < W;\n}\n\nchar build_action(int hx, int hy, int wx, int wy) {\n    if (wx == hx - 1 && wy == hy) return 'u';\n    if (wx == hx + 1 && wy == hy) return 'd';\n    if (wx == hx && wy == hy - 1) return 'l';\n    if (wx == hx && wy == hy + 1) return 'r';\n    return '.';\n}\n\nchar move_action(int hx, int hy, int nx, int ny) {\n    if (nx == hx - 1 && ny == hy) return 'U';\n    if (nx == hx + 1 && ny == hy) return 'D';\n    if (nx == hx && ny == hy - 1) return 'L';\n    if (nx == hx && ny == hy + 1) return 'R';\n    return '.';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pos> pet_pos(N);\n    vector<int> pet_type(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].x >> pet_pos[i].y >> pet_type[i];\n        --pet_pos[i].x; --pet_pos[i].y;\n    }\n\n    int M;\n    cin >> M;\n    vector<Pos> human_pos(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].x >> human_pos[i].y;\n        --human_pos[i].x; --human_pos[i].y;\n    }\n\n    vector<vector<bool>> passable(H, vector<bool>(W, true));\n    vector<vector<bool>> has_pet(H, vector<bool>(W, false));\n    vector<vector<bool>> has_human(H, vector<bool>(W, false));\n\n    auto update_occupancy = [&]() {\n        for (int i = 0; i < H; ++i) {\n            fill(has_pet[i].begin(), has_pet[i].end(), false);\n            fill(has_human[i].begin(), has_human[i].end(), false);\n        }\n        for (auto &p : pet_pos) has_pet[p.x][p.y] = true;\n        for (auto &h : human_pos) has_human[h.x][h.y] = true;\n    };\n    update_occupancy();\n\n    // Prefix sum of initial pets\n    vector<vector<int>> pet_ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            pet_ps[i + 1][j + 1] = pet_ps[i][j + 1] + pet_ps[i + 1][j] - pet_ps[i][j] + (has_pet[i][j] ? 1 : 0);\n        }\n    }\n    auto rect_pet_cnt = [&](int r1, int c1, int r2, int c2) -> int {\n        if (r1 > r2 || c1 > c2) return 0;\n        return pet_ps[r2 + 1][c2 + 1] - pet_ps[r1][c2 + 1] - pet_ps[r2 + 1][c1] + pet_ps[r1][c1];\n    };\n\n    // Find best rectangle\n    long long best_score = LLONG_MIN;\n    int best_r1 = 0, best_c1 = 0, best_r2 = 0, best_c2 = 0;\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    int petcnt = rect_pet_cnt(r1, c1, r2, c2);\n                    if (petcnt > 5) continue; // too many pets, not worth it\n\n                    int walls = 0;\n                    if (r1 > 0) walls += (c2 - c1 + 1);\n                    if (r2 < H - 1) walls += (c2 - c1 + 1);\n                    if (c1 > 0) walls += (r2 - r1 + 1);\n                    if (c2 < W - 1) walls += (r2 - r1 + 1);\n\n                    int sumd = 0;\n                    for (auto &h : human_pos) {\n                        int tx = max(r1, min(h.x, r2));\n                        int ty = max(c1, min(h.y, c2));\n                        sumd += abs(h.x - tx) + abs(h.y - ty);\n                    }\n\n                    long long value = (long long)area * 1000000LL / (1LL << petcnt);\n                    long long score = value - (long long)walls * 100 - (long long)sumd * 10;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1; best_c1 = c1;\n                        best_r2 = r2; best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n\n    int R1 = best_r1, C1 = best_c1, R2 = best_r2, C2 = best_c2;\n\n    // Generate wall cells\n    vector<Pos> all_walls;\n    if (R1 > 0) for (int c = C1; c <= C2; ++c) all_walls.push_back({R1 - 1, c});\n    if (R2 < H - 1) for (int c = C1; c <= C2; ++c) all_walls.push_back({R2 + 1, c});\n    if (C1 > 0) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C1 - 1});\n    if (C2 < W - 1) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C2 + 1});\n\n    // Choose gate farthest from initial pets\n    Pos gate = {-1, -1};\n    if (!all_walls.empty()) {\n        int best = -1;\n        for (auto &w : all_walls) {\n            int mind = 1e9;\n            for (auto &p : pet_pos) mind = min(mind, abs(w.x - p.x) + abs(w.y - p.y));\n            if (mind > best) {\n                best = mind;\n                gate = w;\n            }\n        }\n    }\n\n    vector<Pos> pre_walls;\n    set<pair<int,int>> gate_set;\n    if (gate.x != -1) gate_set.insert({gate.x, gate.y});\n    for (auto &w : all_walls) {\n        if (!gate_set.count({w.x, w.y})) pre_walls.push_back(w);\n    }\n\n    Pos gate_inside = {-1, -1};\n    if (gate.x != -1) {\n        for (int d = 0; d < 4; ++d) {\n            int nx = gate.x + dx[d], ny = gate.y + dy[d];\n            if (nx >= R1 && nx <= R2 && ny >= C1 && ny <= C2) {\n                gate_inside = {nx, ny};\n                break;\n            }\n        }\n    }\n\n    auto can_build = [&](int wx, int wy) -> bool {\n        if (!passable[wx][wy]) return false;\n        if (has_pet[wx][wy] || has_human[wx][wy]) return false;\n        for (int d = 0; d < 4; ++d) {\n            int ax = wx + dx[d], ay = wy + dy[d];\n            if (in_bounds(ax, ay) && has_pet[ax][ay]) return false;\n        }\n        return true;\n    };\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        update_occupancy();\n\n        string action(M, '.');\n        vector<vector<bool>> blocked(H, vector<bool>(W, false));\n        for (int x = 0; x < H; ++x)\n            for (int y = 0; y < W; ++y)\n                blocked[x][y] = !passable[x][y];\n\n        vector<bool> prewall_built(pre_walls.size(), false);\n        for (int i = 0; i < (int)pre_walls.size(); ++i)\n            prewall_built[i] = !passable[pre_walls[i].x][pre_walls[i].y];\n        bool all_prewalls_done = true;\n        for (bool b : prewall_built) if (!b) { all_prewalls_done = false; break; }\n\n        vector<bool> is_inside(M, false);\n        for (int i = 0; i < M; ++i)\n            is_inside[i] = (human_pos[i].x >= R1 && human_pos[i].x <= R2 && human_pos[i].y >= C1 && human_pos[i].y <= C2);\n        bool all_inside = true;\n        for (bool b : is_inside) if (!b) { all_inside = false; break; }\n\n        set<pair<int,int>> being_built;\n        set<pair<int,int>> move_targets;\n        vector<bool> acted(M, false);\n\n        // 1. Try to build pre-walls or gate\n        for (int i = 0; i < M; ++i) {\n            if (acted[i]) continue;\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n\n            // Build a pre-wall\n            int chosen_j = -1;\n            for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                if (prewall_built[j]) continue;\n                int wx = pre_walls[j].x, wy = pre_walls[j].y;\n                if (abs(hx - wx) + abs(hy - wy) != 1) continue;\n                if (being_built.count({wx, wy})) continue;\n                if (move_targets.count({wx, wy})) continue;\n                if (!can_build(wx, wy)) continue;\n                chosen_j = j;\n                break;\n            }\n            if (chosen_j != -1) {\n                int wx = pre_walls[chosen_j].x, wy = pre_walls[chosen_j].y;\n                action[i] = build_action(hx, hy, wx, wy);\n                acted[i] = true;\n                being_built.insert({wx, wy});\n                blocked[wx][wy] = true;\n                continue;\n            }\n\n            // Build gate if ready\n            if (all_prewalls_done && all_inside && gate.x != -1 && passable[gate.x][gate.y]) {\n                if (abs(hx - gate.x) + abs(hy - gate.y) == 1 && can_build(gate.x, gate.y) && !being_built.count({gate.x, gate.y}) && !move_targets.count({gate.x, gate.y})) {\n                    action[i] = build_action(hx, hy, gate.x, gate.y);\n                    acted[i] = true;\n                    being_built.insert({gate.x, gate.y});\n                    blocked[gate.x][gate.y] = true;\n                    continue;\n                }\n            }\n        }\n\n        // 2. Move\n        for (int i = 0; i < M; ++i) {\n            if (acted[i]) continue;\n\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n\n            // BFS\n            vector<vector<int>> dist(H, vector<int>(W, -1));\n            vector<vector<pair<int,int>>> par(H, vector<pair<int,int>>(W, {-1, -1}));\n            queue<pair<int,int>> q;\n            dist[hx][hy] = 0;\n            q.push({hx, hy});\n            while (!q.empty()) {\n                auto [x, y] = q.front(); q.pop();\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (!in_bounds(nx, ny)) continue;\n                    if (blocked[nx][ny]) continue;\n                    if (dist[nx][ny] != -1) continue;\n                    dist[nx][ny] = dist[x][y] + 1;\n                    par[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n\n            Pos move_target = {-1, -1};\n\n            if (!all_prewalls_done) {\n                // Move toward nearest unbuilt pre-wall (prefer buildable)\n                int best_d = 1e9;\n                bool best_buildable = false;\n                Pos best_pos = {-1, -1};\n                for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                    if (prewall_built[j]) continue;\n                    int wx = pre_walls[j].x, wy = pre_walls[j].y;\n                    bool buildable = can_build(wx, wy);\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = wx + dx[d], ay = wy + dy[d];\n                        if (!in_bounds(ax, ay)) continue;\n                        if (dist[ax][ay] == -1) continue;\n                        if (buildable && !best_buildable) {\n                            best_buildable = true;\n                            best_d = dist[ax][ay];\n                            best_pos = {ax, ay};\n                        } else if (buildable == best_buildable && dist[ax][ay] < best_d) {\n                            best_d = dist[ax][ay];\n                            best_pos = {ax, ay};\n                        }\n                    }\n                }\n                if (best_pos.x != -1) {\n                    if (best_d == 0) {\n                        // Already adjacent but cannot build now (blocked by pet, etc). Wait.\n                        action[i] = '.';\n                        acted[i] = true;\n                        continue;\n                    } else {\n                        move_target = best_pos;\n                    }\n                }\n            } else if (!is_inside[i]) {\n                // Need to enter\n                if (gate.x != -1) {\n                    if (hx == gate.x && hy == gate.y && gate_inside.x != -1) {\n                        // Standing on gate, move inside\n                        action[i] = move_action(hx, hy, gate_inside.x, gate_inside.y);\n                        acted[i] = true;\n                        move_targets.insert({gate_inside.x, gate_inside.y});\n                        continue;\n                    } else if (dist[gate.x][gate.y] != -1) {\n                        if (dist[gate.x][gate.y] == 0) {\n                            // At gate? Already handled above.\n                            action[i] = '.';\n                            acted[i] = true;\n                            continue;\n                        } else {\n                            move_target = gate;\n                        }\n                    }\n                }\n            } else {\n                // Inside, pre-walls done. Just wait (gate will be closed by someone else or wait for all)\n                action[i] = '.';\n                acted[i] = true;\n                continue;\n            }\n\n            if (!acted[i] && move_target.x != -1 && dist[move_target.x][move_target.y] > 0) {\n                int cx = move_target.x, cy = move_target.y;\n                while (par[cx][cy] != make_pair(hx, hy)) {\n                    auto p = par[cx][cy];\n                    cx = p.first;\n                    cy = p.second;\n                }\n                action[i] = move_action(hx, hy, cx, cy);\n                acted[i] = true;\n                move_targets.insert({cx, cy});\n            } else if (!acted[i]) {\n                action[i] = '.';\n                acted[i] = true;\n            }\n        }\n\n        cout << action << endl;\n\n        // Apply human actions\n        for (int i = 0; i < M; ++i) {\n            char c = action[i];\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int wx = hx, wy = hy;\n                if (c == 'u') wx--;\n                else if (c == 'd') wx++;\n                else if (c == 'l') wy--;\n                else if (c == 'r') wy++;\n                if (in_bounds(wx, wy)) passable[wx][wy] = false;\n            } else if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int nx = hx, ny = hy;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    human_pos[i] = {nx, ny};\n                }\n            }\n        }\n\n        // Read pet movements\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            for (char c : s) {\n                int nx = pet_pos[i].x, ny = pet_pos[i].y;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    pet_pos[i] = {nx, ny};\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int H = 20;\nconst int W = 20;\nconst int N = H * W;\nconst int L = 200;\n\nint start_id, goal_id;\ndouble P, ONE_MINUS_P;\nint nxt_id[N][4];               // 0:U 1:D 2:L 3:R\nint dist_to_goal[N];\nchar DIRCHAR[4] = {'U', 'D', 'L', 'R'};\nint CMDMAP[256];\n\n// RNG\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> uniform01(0.0, 1.0);\n\n// ------------------------------------------------------------\n// full evaluation (standalone)\ndouble full_evaluate(const string& s) {\n    array<double, N> dp{}, ndp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    double score = 0.0;\n    for (int t = 0; t < (int)s.size(); ++t) {\n        int c = CMDMAP[(unsigned char)s[t]];\n        ndp.fill(0.0);\n        double imm = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            double stay = x * P;\n            double move = x * ONE_MINUS_P;\n            ndp[v] += stay;\n            int to = nxt_id[v][c];\n            if (to == goal_id) {\n                imm += move * (401 - (t + 1));\n            } else {\n                ndp[to] += move;\n            }\n        }\n        score += imm;\n        dp.swap(ndp);\n    }\n    return score;\n}\n\n// ------------------------------------------------------------\n// BFS shortest path\nvector<char> bfs_shortest_path() {\n    queue<int> q;\n    vector<int> dist(N, -1), par(N, -1), pc(N, -1);\n    dist[start_id] = 0;\n    q.push(start_id);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == goal_id) break;\n        for (int d = 0; d < 4; ++d) {\n            int u = nxt_id[v][d];\n            if (u != v && dist[u] == -1) {\n                dist[u] = dist[v] + 1;\n                par[u] = v;\n                pc[u] = d;\n                q.push(u);\n            }\n        }\n    }\n    if (dist[goal_id] == -1) return {};\n    vector<char> path;\n    int cur = goal_id;\n    while (cur != start_id) {\n        path.push_back(DIRCHAR[pc[cur]]);\n        cur = par[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// monotone D/R path\nvector<char> monotone_path(const vector<string>& hwall,\n                           const vector<string>& vwall,\n                           int si, int sj, int ti, int tj) {\n    vector<vector<bool>> reach(H, vector<bool>(W, false));\n    vector<vector<char>> from(H, vector<char>(W, 0));\n    reach[si][sj] = true;\n    for (int i = si; i <= ti; ++i) {\n        for (int j = sj; j <= tj; ++j) {\n            if (!reach[i][j]) continue;\n            if (i < ti && vwall[i][j] == '0' && !reach[i + 1][j]) {\n                reach[i + 1][j] = true;\n                from[i + 1][j] = 'D';\n            }\n            if (j < tj && hwall[i][j] == '0' && !reach[i][j + 1]) {\n                reach[i][j + 1] = true;\n                from[i][j + 1] = 'R';\n            }\n        }\n    }\n    if (!reach[ti][tj]) return {};\n    vector<char> path;\n    int i = ti, j = tj;\n    while (i != si || j != sj) {\n        char c = from[i][j];\n        path.push_back(c);\n        if (c == 'D') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// greedy open-loop path\nstring greedy_path() {\n    array<double, N> dp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    string s;\n    s.reserve(L);\n    for (int t = 0; t < L; ++t) {\n        int best_c = 3;\n        double best_cost = 1e100;\n        for (int c = 0; c < 4; ++c) {\n            double cost = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = dp[v];\n                if (x == 0.0) continue;\n                int to = nxt_id[v][c];\n                double d = (to == goal_id) ? 0.0 : (double)dist_to_goal[to];\n                cost += x * (P * (double)dist_to_goal[v] + ONE_MINUS_P * d);\n            }\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_c = c;\n            }\n        }\n        s.push_back(DIRCHAR[best_c]);\n        array<double, N> ndp{};\n        ndp.fill(0.0);\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            ndp[v] += x * P;\n            int to = nxt_id[v][best_c];\n            if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n        }\n        dp.swap(ndp);\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Local search structure\nstruct Solver {\n    string cur;\n    double cur_score;\n    vector<array<double, N>> fw;   // size L+1\n    vector<array<double, N>> b;    // size L+1\n    vector<double> pref;           // size L+1\n\n    void init(const string& s) {\n        cur = s;\n        fw.assign(L + 1, {});\n        b.assign(L + 1, {});\n        pref.assign(L + 1, 0.0);\n        fw[0].fill(0.0);\n        fw[0][start_id] = 1.0;\n        for (int t = 0; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        b[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n\n    // O(N) evaluation of changing position pos to command cmd (0..3)\n    double try_mutate(int pos, int cmd) const {\n        double reward = (401 - (pos + 1)) * ONE_MINUS_P;\n        double dot = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double val = P * b[pos + 1][v];\n            int to = nxt_id[v][cmd];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * b[pos + 1][to];\n            dot += fw[pos][v] * val;\n        }\n        return pref[pos] + dot;\n    }\n\n    // apply single mutation\n    void apply_mutate(int pos, int cmd) {\n        cur[pos] = DIRCHAR[cmd];\n        for (int t = pos; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        for (int t = pos; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n};\n\n// ------------------------------------------------------------\n// Window evaluation (exact brute force over 4^W strings)\ntemplate<std::size_t W>\ndouble try_window(const Solver& sol, int pos, const array<int, W>& cmd) {\n    alignas(64) static double buf0[N];\n    alignas(64) static double buf1[N];\n    double *cur = buf0;\n    double *nxt = buf1;\n    memcpy(cur, sol.b[pos + (int)W].data(), sizeof(double) * N);\n    for (int k = (int)W - 1; k >= 0; --k) {\n        int c = cmd[k];\n        double reward = (401 - (pos + k + 1)) * ONE_MINUS_P;\n        for (int v = 0; v < N; ++v) {\n            double val = P * cur[v];\n            int to = nxt_id[v][c];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * cur[to];\n            nxt[v] = val;\n        }\n        swap(cur, nxt);\n    }\n    double dot = 0.0;\n    for (int v = 0; v < N; ++v) dot += sol.fw[pos][v] * cur[v];\n    return sol.pref[pos] + dot;\n}\n\ntemplate<std::size_t W>\nvoid apply_window(Solver& sol, int pos, const array<int, W>& cmd) {\n    for (int k = 0; k < (int)W; ++k) sol.cur[pos + k] = DIRCHAR[cmd[k]];\n    // forward recompute from pos\n    for (int t = pos; t < L; ++t) {\n        int c = CMDMAP[(unsigned char)sol.cur[t]];\n        sol.fw[t + 1].fill(0.0);\n        double imm = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double x = sol.fw[t][v];\n            double stay = x * P;\n            double move = x * ONE_MINUS_P;\n            sol.fw[t + 1][v] += stay;\n            int to = nxt_id[v][c];\n            if (to == goal_id) {\n                imm += move * (401 - (t + 1));\n            } else {\n                sol.fw[t + 1][to] += move;\n            }\n        }\n        sol.pref[t + 1] = sol.pref[t] + imm;\n    }\n    // backward recompute from pos+W-1 down to 0\n    for (int t = pos + (int)W - 1; t >= 0; --t) {\n        int c = CMDMAP[(unsigned char)sol.cur[t]];\n        double reward = (401 - (t + 1)) * ONE_MINUS_P;\n        for (int v = 0; v < N; ++v) {\n            double val = P * sol.b[t + 1][v];\n            int to = nxt_id[v][c];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * sol.b[t + 1][to];\n            sol.b[t][v] = val;\n        }\n    }\n    sol.cur_score = sol.pref[L];\n}\n\n// ------------------------------------------------------------\n// Hill climbing\nvoid hill_climb(Solver& sol, const function<double()>& elapsed, double time_limit) {\n    bool improved = true;\n    while (improved) {\n        if (elapsed() > time_limit) break;\n        improved = false;\n        for (int i = 0; i < L; ++i) {\n            int cur_cmd = CMDMAP[(unsigned char)sol.cur[i]];\n            int best_cmd = cur_cmd;\n            double best_sc = sol.cur_score;\n            for (int d = 0; d < 3; ++d) {\n                int nc = (cur_cmd + 1 + d) & 3;\n                double sc = sol.try_mutate(i, nc);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    best_cmd = nc;\n                }\n            }\n            if (best_cmd != cur_cmd) {\n                sol.apply_mutate(i, best_cmd);\n                improved = true;\n            }\n        }\n    }\n}\n\n// Window-size exact coordinate ascent\nvoid optimize_windows(Solver& sol, const function<double()>& elapsed, double time_limit) {\n    // w = 3, up to 5 passes\n    for (int pass = 0; pass < 5; ++pass) {\n        if (elapsed() > time_limit) break;\n        bool improved = false;\n        for (int i = 0; i <= L - 3; ++i) {\n            if (elapsed() > time_limit) break;\n            int cur_cmd[3];\n            for (int k = 0; k < 3; ++k) cur_cmd[k] = CMDMAP[(unsigned char)sol.cur[i + k]];\n            int best_cmd[3] = {cur_cmd[0], cur_cmd[1], cur_cmd[2]};\n            double best_sc = sol.cur_score;\n            for (int mask = 0; mask < 64; ++mask) {\n                array<int, 3> cmd;\n                int t = mask;\n                cmd[2] = t % 4; t /= 4;\n                cmd[1] = t % 4; t /= 4;\n                cmd[0] = t % 4;\n                double sc = try_window(sol, i, cmd);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    for (int k = 0; k < 3; ++k) best_cmd[k] = cmd[k];\n                }\n            }\n            if (best_cmd[0] != cur_cmd[0] || best_cmd[1] != cur_cmd[1] || best_cmd[2] != cur_cmd[2]) {\n                array<int, 3> cmd{best_cmd[0], best_cmd[1], best_cmd[2]};\n                apply_window(sol, i, cmd);\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n\n    // w = 4, up to 2 passes\n    for (int pass = 0; pass < 2; ++pass) {\n        if (elapsed() > time_limit) break;\n        bool improved = false;\n        for (int i = 0; i <= L - 4; ++i) {\n            if (elapsed() > time_limit) break;\n            int cur_cmd[4];\n            for (int k = 0; k < 4; ++k) cur_cmd[k] = CMDMAP[(unsigned char)sol.cur[i + k]];\n            int best_cmd[4];\n            memcpy(best_cmd, cur_cmd, sizeof(cur_cmd));\n            double best_sc = sol.cur_score;\n            for (int mask = 0; mask < 256; ++mask) {\n                array<int, 4> cmd;\n                int t = mask;\n                cmd[3] = t % 4; t /= 4;\n                cmd[2] = t % 4; t /= 4;\n                cmd[1] = t % 4; t /= 4;\n                cmd[0] = t % 4;\n                double sc = try_window(sol, i, cmd);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    for (int k = 0; k < 4; ++k) best_cmd[k] = cmd[k];\n                }\n            }\n            if (memcmp(best_cmd, cur_cmd, sizeof(cur_cmd)) != 0) {\n                array<int, 4> cmd;\n                for (int k = 0; k < 4; ++k) cmd[k] = best_cmd[k];\n                apply_window(sol, i, cmd);\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n}\n\n// ------------------------------------------------------------\nstring perturb(const string& s, int k) {\n    string r = s;\n    for (int i = 0; i < k; ++i) {\n        int pos = rng() % L;\n        r[pos] = DIRCHAR[rng() % 4];\n    }\n    return r;\n}\n\nvoid run_sa(Solver& sol, int max_iter, double time_limit,\n            const function<double()>& elapsed, double T0) {\n    const double T_end = 1e-4;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        if ((iter & 1023) == 0 && elapsed() > time_limit) break;\n        double T = T0 * pow(T_end / T0, (double)iter / max_iter);\n        int pos = rng() % L;\n        int cur_cmd = CMDMAP[(unsigned char)sol.cur[pos]];\n        int best_cmd = cur_cmd;\n        double best_mut_sc = sol.cur_score;\n        for (int d = 0; d < 3; ++d) {\n            int nc = (cur_cmd + 1 + d) & 3;\n            double sc = sol.try_mutate(pos, nc);\n            if (sc > best_mut_sc) {\n                best_mut_sc = sc;\n                best_cmd = nc;\n            }\n        }\n        if (best_cmd != cur_cmd) {\n            bool accept = false;\n            if (best_mut_sc >= sol.cur_score) {\n                accept = true;\n            } else if (T > 1e-12) {\n                if (uniform01(rng) < exp((best_mut_sc - sol.cur_score) / T))\n                    accept = true;\n            }\n            if (accept) sol.apply_mutate(pos, best_cmd);\n        }\n    }\n}\n\n// ------------------------------------------------------------\n// Beam search with closed-loop upper bound\nstring beam_search(const vector<array<double, N>>& V) {\n    const int MAX_B = 1000;\n\n    struct Cand {\n        double pref;\n        double ub;\n        int par_id;\n        char c;\n    };\n\n    vector<double> node_pref;\n    vector<int> parent;\n    vector<char> pcmd;\n    vector<int> layer_start;\n\n    node_pref.reserve((L + 1) * MAX_B);\n    parent.reserve((L + 1) * MAX_B);\n    pcmd.reserve((L + 1) * MAX_B);\n\n    node_pref.push_back(0.0);\n    parent.push_back(-1);\n    pcmd.push_back(0);\n    layer_start.push_back(0);\n    layer_start.push_back(1);\n\n    vector<int> cur_id(1, 0);\n    vector<array<double, N>> cur_fw(1);\n    cur_fw[0].fill(0.0);\n    cur_fw[0][start_id] = 1.0;\n\n    for (int t = 0; t < L; ++t) {\n        int cur_sz = (int)cur_id.size();\n        const double* vt = V[t + 1].data();\n        double reward = 401.0 - (t + 1);\n\n        vector<Cand> cands;\n        cands.reserve(cur_sz * 4);\n\n        for (int idx = 0; idx < cur_sz; ++idx) {\n            int gid = cur_id[idx];\n            const array<double, N>& fw = cur_fw[idx];\n            double sum_base = 0.0;\n            for (int v = 0; v < N; ++v) sum_base += fw[v] * vt[v];\n            for (int cmd = 0; cmd < 4; ++cmd) {\n                double dot_move = 0.0;\n                double goal_mass = 0.0;\n                for (int v = 0; v < N; ++v) {\n                    int to = nxt_id[v][cmd];\n                    if (to == goal_id) goal_mass += fw[v];\n                    else dot_move += fw[v] * vt[to];\n                }\n                double pref_new = node_pref[gid] + goal_mass * ONE_MINUS_P * reward;\n                double ub = pref_new + P * sum_base + ONE_MINUS_P * dot_move;\n                cands.push_back({pref_new, ub, gid, DIRCHAR[cmd]});\n            }\n        }\n\n        int keep = min((int)cands.size(), MAX_B);\n        nth_element(cands.begin(), cands.begin() + keep, cands.end(),\n                    [](const Cand& a, const Cand& b) { return a.ub > b.ub; });\n\n        vector<int> next_id;\n        next_id.reserve(keep);\n        vector<array<double, N>> next_fw;\n        next_fw.reserve(keep);\n\n        for (int i = 0; i < keep; ++i) {\n            const Cand& lc = cands[i];\n            int new_id = (int)node_pref.size();\n            node_pref.push_back(lc.pref);\n            parent.push_back(lc.par_id);\n            pcmd.push_back(lc.c);\n            next_id.push_back(new_id);\n\n            int par_idx = lc.par_id - layer_start[t];\n            const array<double, N>& pfw = cur_fw[par_idx];\n            array<double, N> ndp;\n            ndp.fill(0.0);\n            int cmd = CMDMAP[(unsigned char)lc.c];\n            for (int v = 0; v < N; ++v) {\n                double x = pfw[v];\n                ndp[v] += x * P;\n                int to = nxt_id[v][cmd];\n                if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n            }\n            next_fw.push_back(ndp);\n        }\n\n        cur_id.swap(next_id);\n        cur_fw.swap(next_fw);\n        layer_start.push_back((int)node_pref.size());\n    }\n\n    double best_score = -1.0;\n    int best_leaf = -1;\n    for (int gid : cur_id) {\n        if (node_pref[gid] > best_score) {\n            best_score = node_pref[gid];\n            best_leaf = gid;\n        }\n    }\n    if (best_leaf == -1) return string(L, 'D');\n\n    string beam_str(L, '?');\n    int cur = best_leaf;\n    for (int t = L - 1; t >= 0; --t) {\n        beam_str[t] = pcmd[cur];\n        cur = parent[cur];\n    }\n    return beam_str;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    CMDMAP['U'] = 0; CMDMAP['D'] = 1; CMDMAP['L'] = 2; CMDMAP['R'] = 3;\n\n    int si, sj, ti, tj;\n    double p_input;\n    if (!(cin >> si >> sj >> ti >> tj >> p_input)) return 0;\n    P = p_input;\n    ONE_MINUS_P = 1.0 - P;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; ++i) cin >> hwall[i];\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; ++i) cin >> vwall[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int v = i * W + j;\n            if (i > 0 && vwall[i - 1][j] == '0') nxt_id[v][0] = (i - 1) * W + j;\n            else nxt_id[v][0] = v;\n            if (i + 1 < H && vwall[i][j] == '0') nxt_id[v][1] = (i + 1) * W + j;\n            else nxt_id[v][1] = v;\n            if (j > 0 && hwall[i][j - 1] == '0') nxt_id[v][2] = i * W + (j - 1);\n            else nxt_id[v][2] = v;\n            if (j + 1 < W && hwall[i][j] == '0') nxt_id[v][3] = i * W + (j + 1);\n            else nxt_id[v][3] = v;\n        }\n    }\n\n    // distances to goal\n    {\n        queue<int> q;\n        vector<int> dist(N, -1);\n        dist[goal_id] = 0;\n        q.push(goal_id);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int u = nxt_id[v][d];\n                if (u != v && dist[u] == -1) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) dist_to_goal[i] = dist[i];\n    }\n\n    // closed-loop upper bound V[t][v]\n    vector<array<double, N>> V(L + 1);\n    for (int v = 0; v < N; ++v) V[L][v] = 0.0;\n    for (int t = L - 1; t >= 0; --t) {\n        double reward = 401.0 - (t + 1);\n        for (int v = 0; v < N; ++v) {\n            if (v == goal_id) {\n                V[t][v] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int c = 0; c < 4; ++c) {\n                int to = nxt_id[v][c];\n                double val = P * V[t + 1][v];\n                if (to == goal_id) val += ONE_MINUS_P * reward;\n                else val += ONE_MINUS_P * V[t + 1][to];\n                if (val > best) best = val;\n            }\n            V[t][v] = best;\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    // ---------- candidates ----------\n    vector<string> candidates;\n    auto make_repeat = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        string s;\n        while ((int)s.size() < L) s += string(path.begin(), path.end());\n        s.resize(L);\n        return s;\n    };\n    auto make_stretch = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        int rep = max(1, L / (int)path.size());\n        string s;\n        for (char c : path) s += string(rep, c);\n        while ((int)s.size() < L) s.push_back(path[s.size() % path.size()]);\n        s.resize(L);\n        return s;\n    };\n\n    vector<char> sp = bfs_shortest_path();\n    if (!sp.empty()) {\n        candidates.push_back(make_repeat(sp));\n        candidates.push_back(make_stretch(sp));\n    }\n    vector<char> mono = monotone_path(hwall, vwall, si, sj, ti, tj);\n    if (!mono.empty()) {\n        candidates.push_back(make_repeat(mono));\n        candidates.push_back(make_stretch(mono));\n    }\n    candidates.push_back(greedy_path());\n\n    {\n        string s(L, 'D');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needD); ++i) s[i] = 'D';\n        for (; i < min(L, needD + needR); ++i) s[i] = 'R';\n        candidates.push_back(s);\n    }\n    {\n        string s(L, 'R');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needR); ++i) s[i] = 'R';\n        for (; i < min(L, needR + needD); ++i) s[i] = 'D';\n        candidates.push_back(s);\n    }\n    for (int k = 0; k < 20; ++k) {\n        string s;\n        for (int i = 0; i < L; ++i) {\n            int r = rng() % 100;\n            if (r < 45) s += 'D';\n            else if (r < 90) s += 'R';\n            else if (r < 95) s += 'L';\n            else s += 'U';\n        }\n        candidates.push_back(s);\n    }\n\n    candidates.push_back(beam_search(V));\n\n    // evaluate\n    string best_str(L, 'R');\n    double best_score = -1.0;\n    for (auto& s : candidates) {\n        if ((int)s.size() != L) continue;\n        double sc = full_evaluate(s);\n        if (sc > best_score) {\n            best_score = sc;\n            best_str = s;\n        }\n    }\n\n    // ---------- local search ----------\n    Solver solver;\n    solver.init(best_str);\n\n    hill_climb(solver, elapsed, 1.0);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    optimize_windows(solver, elapsed, 1.3);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    hill_climb(solver, elapsed, 1.4);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    // SA temperature calibration\n    vector<double> diffs;\n    for (int k = 0; k < 1000; ++k) {\n        int pos = rng() % L;\n        int cur_cmd = CMDMAP[(unsigned char)solver.cur[pos]];\n        int nd = (cur_cmd + 1 + (rng() % 3)) & 3;\n        double sc = solver.try_mutate(pos, nd);\n        if (sc < solver.cur_score) diffs.push_back(solver.cur_score - sc);\n    }\n    sort(diffs.begin(), diffs.end());\n    double T0 = 1.0;\n    if (!diffs.empty()) {\n        T0 = diffs[min((int)diffs.size() - 1, (int)(diffs.size() * 9 / 10))];\n        if (T0 < 1.0) T0 = 1.0;\n    }\n\n    run_sa(solver, 350000, 1.85, elapsed, T0);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    // ---------- safe restarts ----------\n    for (int rep = 0; rep < 3; ++rep) {\n        if (elapsed() > 1.92) break;\n        string p = perturb(best_str, 5 + rep);\n        Solver rs;\n        rs.init(p);\n        hill_climb(rs, elapsed, 1.94);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n            solver.init(best_str);\n        }\n        if (elapsed() > 1.94) break;\n\n        optimize_windows(rs, elapsed, 1.96);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n            solver.init(best_str);\n        }\n        if (elapsed() > 1.96) break;\n\n        run_sa(rs, 25000, 1.98, elapsed, T0);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n            solver.init(best_str);\n        }\n    }\n\n    cout << best_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static const int N = 30;\n    static const int V = N * N;          // 900\n    static const int S = V * 4;          // 3600\n\n    struct Vec4 {\n        int v[4];\n        int sz;\n        void clear() { sz = 0; }\n        void push(int x) { v[sz++] = x; }\n        int sum() const {\n            int s = 0;\n            for (int i = 0; i < sz; ++i) s += v[i];\n            return s;\n        }\n    };\n\n    int base[V];\n    unsigned char rot[V];\n    unsigned char best_rot[V];\n\n    // precomputed successor: cell idx, rotation r, entry dir d\n    int16_t pre_nxt[V][4][4];\n\n    int8_t to_tbl[8][4];\n    int ft[8][4];\n    const int di[4] = {0, -1, 0, 1};\n    const int dj[4] = {-1, 0, 1, 0};\n\n    // current graph\n    int16_t nxt[S];\n\n    // cycle statistics\n    int cnt[3601];\n    int total_len;\n    set<int> active_lens;\n    int best1, best2;\n    int best_score;\n\n    // visited arrays for cycle detection\n    int state_vis[S];\n    int cycle_vis[S];\n    int vis_token;\n    int cycle_token;\n\n    // random\n    uint64_t rng;\n    uint64_t rand64() {\n        uint64_t z = (rng += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int rand_int(int m) { return (int)(rand64() % (uint64_t)m); }\n\n    // ------------------------------------------------------------\n    // count of length 'len' after removing oldv and adding newv\n    // ------------------------------------------------------------\n    inline int adj_cnt(int len, const Vec4& oldv, const Vec4& newv) const {\n        int c = cnt[len];\n        for (int i = 0; i < oldv.sz; ++i) if (oldv.v[i] == len) --c;\n        for (int i = 0; i < newv.sz; ++i) if (newv.v[i] == len) ++c;\n        return c;\n    }\n\n    int find_best1(const Vec4& oldv, const Vec4& newv) const {\n        int max_new = 0;\n        for (int i = 0; i < newv.sz; ++i) max_new = max(max_new, newv.v[i]);\n        for (auto it = active_lens.rbegin(); it != active_lens.rend(); ++it) {\n            int len = *it;\n            if (len < max_new) break;\n            if (adj_cnt(len, oldv, newv) > 0) return len;\n        }\n        return max_new;\n    }\n\n    int find_best2(int b1, const Vec4& oldv, const Vec4& newv) const {\n        if (b1 == 0) return 0;\n        if (adj_cnt(b1, oldv, newv) >= 2) return b1;\n        int b2 = 0;\n        for (int i = 0; i < newv.sz; ++i) {\n            int L = newv.v[i];\n            if (L != b1 && L > b2) b2 = L;\n        }\n        for (auto it = active_lens.rbegin(); it != active_lens.rend(); ++it) {\n            int len = *it;\n            if (len <= b2) break;\n            if (len == b1) continue;\n            if (adj_cnt(len, oldv, newv) > 0) {\n                b2 = len;\n                break;\n            }\n        }\n        return b2;\n    }\n\n    void update_globals(const Vec4& oldv, const Vec4& newv) {\n        for (int i = 0; i < oldv.sz; ++i) {\n            int L = oldv.v[i];\n            if (--cnt[L] == 0) active_lens.erase(L);\n            total_len -= L;\n        }\n        for (int i = 0; i < newv.sz; ++i) {\n            int L = newv.v[i];\n            if (cnt[L]++ == 0) active_lens.insert(L);\n            total_len += L;\n        }\n        if (active_lens.empty()) {\n            best1 = best2 = 0;\n        } else {\n            auto it = active_lens.rbegin();\n            best1 = *it;\n            if (cnt[best1] >= 2) best2 = best1;\n            else {\n                ++it;\n                best2 = (it == active_lens.rend()) ? 0 : *it;\n            }\n        }\n    }\n\n    inline int get_score() const { return best1 * best2; }\n    inline int64_t eval_val(int b1, int b2, int tot) const {\n        return (int64_t)b1 * b2 * 1000LL + tot;\n    }\n\n    // ------------------------------------------------------------\n    // find all cycles that contain at least one of st[0..3]\n    // each cycle is reported exactly once\n    // ------------------------------------------------------------\n    Vec4 find_cycles(const int st[4]) {\n        Vec4 res;\n        res.clear();\n        int my_cycle = ++cycle_token;\n\n        for (int k = 0; k < 4; ++k) {\n            int s = st[k];\n            if (nxt[s] == -1) continue;\n            if (cycle_vis[s] == my_cycle) continue;\n\n            int my_vis = ++vis_token;\n            int cur = s;\n            int len = 0;\n            while (cur != -1 && state_vis[cur] != my_vis) {\n                state_vis[cur] = my_vis;\n                cur = nxt[cur];\n                ++len;\n                if (len > S) break;\n            }\n            if (cur == s) {\n                res.push(len);\n                int c = s;\n                do {\n                    cycle_vis[c] = my_cycle;\n                    c = nxt[c];\n                } while (c != s);\n            }\n        }\n        return res;\n    }\n\n    // ------------------------------------------------------------\n    // full rebuild of graph and cycle statistics from rot[]\n    // ------------------------------------------------------------\n    void rebuild_from_rot() {\n        for (int s = 0; s < S; ++s) nxt[s] = -1;\n        for (int idx = 0; idx < V; ++idx) {\n            int s0 = idx * 4;\n            int r = rot[idx];\n            for (int d = 0; d < 4; ++d) nxt[s0 + d] = pre_nxt[idx][r][d];\n        }\n\n        memset(cnt, 0, sizeof(cnt));\n        total_len = 0;\n        active_lens.clear();\n\n        static uint8_t mark[S];\n        static int path_nodes[S];\n        memset(mark, 0, sizeof(mark));\n\n        for (int s = 0; s < S; ++s) {\n            if (nxt[s] == -1 || mark[s]) continue;\n            int cur = s;\n            int path_len = 0;\n            while (cur != -1 && mark[cur] == 0) {\n                mark[cur] = 1;\n                path_nodes[path_len++] = cur;\n                cur = nxt[cur];\n            }\n            if (cur != -1 && mark[cur] == 1) {\n                int cycle_len = 0;\n                for (int i = path_len - 1; i >= 0; --i) {\n                    ++cycle_len;\n                    if (path_nodes[i] == cur) break;\n                }\n                cnt[cycle_len]++;\n                total_len += cycle_len;\n                active_lens.insert(cycle_len);\n            }\n            for (int i = 0; i < path_len; ++i) mark[path_nodes[i]] = 2;\n        }\n\n        if (active_lens.empty()) {\n            best1 = best2 = 0;\n        } else {\n            auto it = active_lens.rbegin();\n            best1 = *it;\n            if (cnt[best1] >= 2) best2 = best1;\n            else {\n                ++it;\n                best2 = (it == active_lens.rend()) ? 0 : *it;\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    void solve() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n        for (int i = 0; i < N; ++i) {\n            string line;\n            cin >> line;\n            for (int j = 0; j < N; ++j) base[i * N + j] = line[j] - '0';\n        }\n\n        const int8_t to_arr[8][4] = {\n            {1,0,-1,-1}, {3,-1,-1,0}, {-1,-1,3,2}, {-1,2,1,-1},\n            {1,0,3,2},   {3,2,1,0},   {2,-1,0,-1}, {-1,3,-1,1}\n        };\n        memcpy(to_tbl, to_arr, sizeof(to_arr));\n        for (int b = 0; b < 8; ++b) {\n            for (int r = 0; r < 4; ++r) {\n                if (b < 4) ft[b][r] = (b + r) & 3;\n                else if (b < 6) ft[b][r] = 4 + ((b - 4 + r) & 1);\n                else ft[b][r] = 6 + ((b - 6 + r) & 1);\n            }\n        }\n\n        for (int idx = 0; idx < V; ++idx) {\n            int i = idx / N, j = idx % N;\n            for (int r = 0; r < 4; ++r) {\n                int t = ft[base[idx]][r];\n                for (int d = 0; d < 4; ++d) {\n                    int d2 = to_tbl[t][d];\n                    if (d2 == -1) {\n                        pre_nxt[idx][r][d] = -1;\n                    } else {\n                        int ni = i + di[d2];\n                        int nj = j + dj[d2];\n                        if (ni < 0 || ni >= N || nj < 0 || nj >= N)\n                            pre_nxt[idx][r][d] = -1;\n                        else\n                            pre_nxt[idx][r][d] = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                    }\n                }\n            }\n        }\n\n        rng = chrono::steady_clock::now().time_since_epoch().count();\n        vis_token = 0;\n        cycle_token = 0;\n\n        // ----- greedy init : avoid edges leaving the board ----------------\n        for (int idx = 0; idx < V; ++idx) {\n            int b = base[idx];\n            int best_r = 0, best_sc = -1;\n            if (b < 4) {\n                for (int r = 0; r < 4; ++r) {\n                    int sc = 0;\n                    for (int d = 0; d < 4; ++d) if (pre_nxt[idx][r][d] != -1) ++sc;\n                    if (sc > best_sc) { best_sc = sc; best_r = r; }\n                }\n            } else {\n                for (int r = 0; r < 2; ++r) {\n                    int sc = 0;\n                    for (int d = 0; d < 4; ++d) if (pre_nxt[idx][r][d] != -1) ++sc;\n                    if (sc > best_sc) { best_sc = sc; best_r = r; }\n                }\n            }\n            rot[idx] = (unsigned char)best_r;\n        }\n\n        rebuild_from_rot();\n        best_score = get_score();\n        memcpy(best_rot, rot, V);\n\n        const double TL = 1.9;\n        clock_t start = clock();\n        auto elapsed = [&]() { return double(clock() - start) / CLOCKS_PER_SEC; };\n\n        // ----- Simulated Annealing ------------------------------------\n        double T0 = 1e7;\n        double T1 = 1.0;\n        double logT0 = log(T0);\n        double logT1 = log(T1);\n\n        while (elapsed() < TL - 0.2) {\n            double p = elapsed() / (TL - 0.2);\n            double T = exp(logT0 + (logT1 - logT0) * p);\n\n            int idx = rand_int(V);\n            int s0 = idx * 4;\n            int st[4] = {s0, s0 + 1, s0 + 2, s0 + 3};\n\n            Vec4 oldv = find_cycles(st);\n            int sum_old = oldv.sum();\n\n            // detach\n            int orig_nxt[4];\n            for (int k = 0; k < 4; ++k) {\n                orig_nxt[k] = nxt[st[k]];\n                nxt[st[k]] = -1;\n            }\n\n            int cur_r = rot[idx];\n            int best_r = cur_r;\n            int64_t best_val = -(1LL << 60);\n            Vec4 best_newv;\n            best_newv.clear();\n\n            int alts[3], nalt = 0;\n            if (base[idx] < 4) {\n                for (int d = 1; d < 4; ++d) alts[nalt++] = (cur_r + d) & 3;\n            } else {\n                alts[nalt++] = cur_r ^ 1;\n            }\n\n            for (int a = 0; a < nalt; ++a) {\n                int nr = alts[a];\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][nr][k];\n\n                Vec4 newv = find_cycles(st);\n                int sum_new = newv.sum();\n                int b1 = find_best1(oldv, newv);\n                int b2 = find_best2(b1, oldv, newv);\n                int alt_tot = total_len - sum_old + sum_new;\n                int64_t val = eval_val(b1, b2, alt_tot);\n\n                if (val > best_val) {\n                    best_val = val;\n                    best_r = nr;\n                    best_newv = newv;\n                }\n\n                // detach for next alternative\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = -1;\n            }\n\n            // restore original edges\n            for (int k = 0; k < 4; ++k) nxt[st[k]] = (int16_t)orig_nxt[k];\n\n            if (best_r != cur_r) {\n                int64_t cur_val = eval_val(best1, best2, total_len);\n                int64_t delta = best_val - cur_val;\n                bool accept = false;\n                if (delta > 0) {\n                    accept = true;\n                } else {\n                    double prob = exp((double)delta / T);\n                    double r = (rand64() >> 11) * (1.0 / (1ULL << 53));\n                    if (r < prob) accept = true;\n                }\n\n                if (accept) {\n                    update_globals(oldv, best_newv);\n                    rot[idx] = (unsigned char)best_r;\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][best_r][k];\n                    int sc = get_score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        memcpy(best_rot, rot, V);\n                    }\n                }\n            }\n        }\n\n        // ----- Hill climbing polish -----------------------------------\n        memcpy(rot, best_rot, V);\n        rebuild_from_rot();\n\n        bool improved = true;\n        while (improved && elapsed() < TL) {\n            improved = false;\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine((unsigned)rand64()));\n\n            for (int idx : order) {\n                if (elapsed() >= TL) break;\n                int s0 = idx * 4;\n                int st[4] = {s0, s0 + 1, s0 + 2, s0 + 3};\n\n                Vec4 oldv = find_cycles(st);\n                int sum_old = oldv.sum();\n\n                int orig_nxt[4];\n                for (int k = 0; k < 4; ++k) {\n                    orig_nxt[k] = nxt[st[k]];\n                    nxt[st[k]] = -1;\n                }\n\n                int cur_r = rot[idx];\n                int best_r = cur_r;\n                int64_t best_val = eval_val(best1, best2, total_len);\n                Vec4 best_newv;\n                best_newv.clear();\n\n                int alts[3], nalt = 0;\n                if (base[idx] < 4) {\n                    for (int d = 1; d < 4; ++d) alts[nalt++] = (cur_r + d) & 3;\n                } else {\n                    alts[nalt++] = cur_r ^ 1;\n                }\n\n                for (int a = 0; a < nalt; ++a) {\n                    int nr = alts[a];\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][nr][k];\n\n                    Vec4 newv = find_cycles(st);\n                    int sum_new = newv.sum();\n                    int b1 = find_best1(oldv, newv);\n                    int b2 = find_best2(b1, oldv, newv);\n                    int alt_tot = total_len - sum_old + sum_new;\n                    int64_t val = eval_val(b1, b2, alt_tot);\n\n                    if (val > best_val) {\n                        best_val = val;\n                        best_r = nr;\n                        best_newv = newv;\n                    }\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = -1;\n                }\n\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = (int16_t)orig_nxt[k];\n\n                if (best_r != cur_r) {\n                    update_globals(oldv, best_newv);\n                    rot[idx] = (unsigned char)best_r;\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][best_r][k];\n                    int sc = get_score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        memcpy(best_rot, rot, V);\n                    }\n                    improved = true;\n                }\n            }\n        }\n\n        // ----- output -------------------------------------------------\n        string out;\n        out.reserve(V);\n        for (int i = 0; i < V; ++i) out.push_back(char('0' + best_rot[i]));\n        cout << out << '\\n';\n    }\n};\n\nint main() {\n    Solver s;\n    s.solve();\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T, SZ, TARGET;\n\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dc[4] = {'U', 'D', 'L', 'R'};\nconst int opp[4] = {1, 0, 3, 2};\n\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\ninline bool inside(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N;\n}\n\nstruct State {\n    array<uint8_t, 100> b;\n    int epos;\n};\n\nstruct Eval {\n    int actual;     // largest true tree\n    int potential;  // V - max(0, E-(V-1)) of best component\n    int edges;      // total good edges\n};\n\n/* ------------------------------------------------------------------ */\n/*  One\u2011pass evaluation                                               */\n/* ------------------------------------------------------------------ */\ninline Eval evaluate(const array<uint8_t, 100>& b) {\n    int edges = 0;\n\n    for (int i = 0; i < N; ++i) {\n        int base = i * N;\n        for (int j = 0; j + 1 < N; ++j) {\n            int a = b[base + j];\n            int c = b[base + j + 1];\n            if (a && c && (a & 4) && (c & 1)) ++edges;\n        }\n    }\n    for (int i = 0; i + 1 < N; ++i) {\n        int base = i * N;\n        for (int j = 0; j < N; ++j) {\n            int a = b[base + j];\n            int c = b[base + j + N];\n            if (a && c && (a & 8) && (c & 2)) ++edges;\n        }\n    }\n\n    uint8_t vis[100] = {0};\n    int q[100];\n    int actual = 0;\n    int best_potential = 0;\n\n    for (int idx = 0; idx < SZ; ++idx) {\n        if (!b[idx] || vis[idx]) continue;\n        int qs = 0, qe = 0;\n        q[qe++] = idx;\n        vis[idx] = 1;\n        int vcnt = 0;\n        while (qs < qe) {\n            int u = q[qs++];\n            ++vcnt;\n            int ui = u / N;\n            int uj = u % N;\n            int t = b[u];\n            if (ui && !vis[u - N] && b[u - N] && (t & 2) && (b[u - N] & 8)) {\n                vis[u - N] = 1; q[qe++] = u - N;\n            }\n            if (ui + 1 < N && !vis[u + N] && b[u + N] && (t & 8) && (b[u + N] & 2)) {\n                vis[u + N] = 1; q[qe++] = u + N;\n            }\n            if (uj && !vis[u - 1] && b[u - 1] && (t & 1) && (b[u - 1] & 4)) {\n                vis[u - 1] = 1; q[qe++] = u - 1;\n            }\n            if (uj + 1 < N && !vis[u + 1] && b[u + 1] && (t & 4) && (b[u + 1] & 1)) {\n                vis[u + 1] = 1; q[qe++] = u + 1;\n            }\n        }\n        int ecnt = 0;\n        for (int k = 0; k < vcnt; ++k) {\n            int u = q[k];\n            int ui = u / N;\n            int uj = u % N;\n            int t = b[u];\n            if (uj + 1 < N && b[u + 1] && (t & 4) && (b[u + 1] & 1)) ++ecnt;\n            if (ui + 1 < N && b[u + N] && (t & 8) && (b[u + N] & 2)) ++ecnt;\n        }\n        if (ecnt == vcnt - 1 && vcnt > actual) actual = vcnt;\n        int excess = ecnt - (vcnt - 1);\n        if (excess < 0) excess = 0;\n        int potential = vcnt - excess;\n        if (potential > best_potential) best_potential = potential;\n    }\n    return {actual, best_potential, edges};\n}\n\n/* ------------------------------------------------------------------ */\ninline int combined(const Eval& e) {\n    return (e.potential << 11) + (e.actual << 4) + e.edges;\n}\n\n/* ------------------------------------------------------------------ */\nState apply_move(const State& s, int d) {\n    State ns = s;\n    int ei = s.epos / N;\n    int ej = s.epos % N;\n    int ni = ei + di[d];\n    int nj = ej + dj[d];\n    int npos = ni * N + nj;\n    ns.b[s.epos] = s.b[npos];\n    ns.b[npos] = 0;\n    ns.epos = npos;\n    return ns;\n}\n\ninline int char2dir(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Bounded DFS escape                                                */\n/*  hard limit on nodes; strong potential bound prune                 */\n/* ------------------------------------------------------------------ */\nconst int MAX_DFS_NODES = 80000;\nint g_dfs_nodes;\nint g_dfs_target_actual;\nint g_dfs_best_actual;\nchar g_dfs_path[20];\nint  g_dfs_path_len;\nint  g_dfs_max_depth;\n\nbool dfs_escape(const State& s, int depth, int last_dir) {\n    if (g_dfs_nodes >= MAX_DFS_NODES) return false;\n    if (depth == g_dfs_max_depth) return false;\n\n    int order[4] = {0, 1, 2, 3};\n    for (int i = 3; i > 0; --i) swap(order[i], order[(int)(rng() % (i + 1))]);\n\n    for (int k = 0; k < 4; ++k) {\n        int d = order[k];\n        if (last_dir != -1 && d == opp[last_dir]) continue;\n        int ei = s.epos / N;\n        int ej = s.epos % N;\n        if (!inside(ei + di[d], ej + dj[d])) continue;\n\n        State ns = apply_move(s, d);\n        Eval ev = evaluate(ns.b);\n        ++g_dfs_nodes;\n\n        if (ev.actual > g_dfs_best_actual) {\n            g_dfs_best_actual = ev.actual;\n            g_dfs_path[depth] = dc[d];\n            g_dfs_path_len = depth + 1;\n            if (g_dfs_best_actual > g_dfs_target_actual) return true;\n        }\n\n        int remaining = g_dfs_max_depth - depth - 1;\n        if (remaining >= 0 && ev.potential + remaining * 3 >= g_dfs_target_actual + 1) {\n            g_dfs_path[depth] = dc[d];\n            if (dfs_escape(ns, depth + 1, d)) return true;\n        }\n    }\n    return false;\n}\n\n/* ------------------------------------------------------------------ */\nstring try_escape(const State& s, const Eval& ev, int max_depth, int& best_actual) {\n    g_dfs_nodes = 0;\n    g_dfs_target_actual = ev.actual;\n    g_dfs_best_actual = ev.actual;\n    g_dfs_max_depth = max_depth;\n    g_dfs_path_len = 0;\n    if (dfs_escape(s, 0, -1)) {\n        best_actual = g_dfs_best_actual;\n        return string(g_dfs_path, g_dfs_path_len);\n    }\n    if (g_dfs_best_actual > ev.actual) {\n        best_actual = g_dfs_best_actual;\n        return string(g_dfs_path, g_dfs_path_len);\n    }\n    return \"\";\n}\n\n/* ------------------------------------------------------------------ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    SZ = N * N;\n    TARGET = SZ - 1;\n\n    State init{};\n    init.epos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int v = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;\n            init.b[i * N + j] = static_cast<uint8_t>(v);\n            if (v == 0) init.epos = i * N + j;\n        }\n    }\n\n    Eval ev0 = evaluate(init.b);\n    int best_actual = ev0.actual;\n    if (best_actual == TARGET) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    State best_state = init;\n    string best_path;\n\n    State cur = init;\n    string cur_path;\n    Eval cur_ev = ev0;\n\n    auto start_tp = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.85;\n\n    auto time_left = [&]() {\n        return TIME_LIMIT - chrono::duration<double>(\n                               chrono::steady_clock::now() - start_tp).count();\n    };\n\n    int stuck = 0;\n\n    while (time_left() > 0.0) {\n        if (best_actual == TARGET) break;\n\n        bool improved = false;\n\n        /* -------- greedy hill climbing -------- */\n        while ((int)cur_path.size() < T) {\n            int last_dir = cur_path.empty() ? -1 : char2dir(cur_path.back());\n            int order[4] = {0, 1, 2, 3};\n            for (int i = 3; i > 0; --i) swap(order[i], order[(int)(rng() % (i + 1))]);\n\n            int best_d = -1;\n            int best_sc = combined(cur_ev);\n            State best_ns = cur;\n            Eval best_ev = cur_ev;\n\n            for (int k = 0; k < 4; ++k) {\n                int d = order[k];\n                if (last_dir != -1 && d == opp[last_dir]) continue;\n                int ei = cur.epos / N;\n                int ej = cur.epos % N;\n                if (!inside(ei + di[d], ej + dj[d])) continue;\n\n                State ns = apply_move(cur, d);\n                Eval ev = evaluate(ns.b);\n                int sc = combined(ev);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    best_d = d;\n                    best_ns = ns;\n                    best_ev = ev;\n                }\n            }\n\n            if (best_d != -1 && best_sc > combined(cur_ev)) {\n                cur = best_ns;\n                cur_path.push_back(dc[best_d]);\n                cur_ev = best_ev;\n                if (cur_ev.actual > best_actual) {\n                    best_actual = cur_ev.actual;\n                    best_state = cur;\n                    best_path = cur_path;\n                    improved = true;\n                }\n            } else {\n                break;\n            }\n        }\n\n        if (best_actual == TARGET) break;\n\n        /* -------- bounded DFS escape -------- */\n        if ((int)cur_path.size() < T && time_left() > 0.15) {\n            int remain = T - (int)cur_path.size();\n            int depth = min(12, remain);\n            if (cur_ev.actual >= TARGET - 10) depth = min(16, remain);\n\n            int found_actual = cur_ev.actual;\n            string seq = try_escape(cur, cur_ev, depth, found_actual);\n            if (!seq.empty() && (int)cur_path.size() + (int)seq.size() <= T) {\n                for (char c : seq) {\n                    int d = char2dir(c);\n                    cur = apply_move(cur, d);\n                    cur_path.push_back(c);\n                }\n                cur_ev = evaluate(cur.b);\n                if (cur_ev.actual > best_actual) {\n                    best_actual = cur_ev.actual;\n                    best_state = cur;\n                    best_path = cur_path;\n                }\n                stuck = 0;\n                continue;\n            }\n        }\n\n        /* -------- random kick / restart -------- */\n        ++stuck;\n        int kick_len = 8 + stuck * 4;\n        if (kick_len > 100) kick_len = 100;\n\n        if (stuck % 3 == 0 && !best_path.empty()\n            && (int)best_path.size() + kick_len + 20 <= T) {\n            cur = best_state;\n            cur_path = best_path;\n            cur_ev = evaluate(cur.b);\n        } else if (stuck % 7 == 0 || (int)cur_path.size() + kick_len > T) {\n            cur = init;\n            cur_path.clear();\n            cur_ev = ev0;\n            stuck = 0;\n        }\n\n        kick_len = min(kick_len, T - (int)cur_path.size());\n        for (int k = 0; k < kick_len; ++k) {\n            int ld = cur_path.empty() ? -1 : char2dir(cur_path.back());\n            int ei = cur.epos / N;\n            int ej = cur.epos % N;\n            int order[4] = {0, 1, 2, 3};\n            for (int i = 3; i > 0; --i) swap(order[i], order[(int)(rng() % (i + 1))]);\n\n            bool moved = false;\n            for (int d : order) {\n                if (ld != -1 && d == opp[ld]) continue;\n                if (!inside(ei + di[d], ej + dj[d])) continue;\n                cur = apply_move(cur, d);\n                cur_path.push_back(dc[d]);\n                moved = true;\n                break;\n            }\n            if (!moved) {\n                for (int d = 0; d < 4; ++d) {\n                    if (!inside(ei + di[d], ej + dj[d])) continue;\n                    cur = apply_move(cur, d);\n                    cur_path.push_back(dc[d]);\n                    break;\n                }\n            }\n        }\n\n        if ((int)cur_path.size() <= T) {\n            cur_ev = evaluate(cur.b);\n            if (cur_ev.actual > best_actual) {\n                best_actual = cur_ev.actual;\n                best_state = cur;\n                best_path = cur_path;\n            }\n        }\n    }\n\n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ------------------------------------------------------------\n// Random (xoshiro256++)\n// ------------------------------------------------------------\nuint64_t rng_seed() {\n    return chrono::steady_clock::now().time_since_epoch().count();\n}\nstruct xoshiro256ss {\n    uint64_t s[4];\n    xoshiro256ss(uint64_t seed) {\n        s[0] = splitmix64(seed);\n        s[1] = splitmix64(s[0]);\n        s[2] = splitmix64(s[1]);\n        s[3] = splitmix64(s[2]);\n    }\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;\n        return x ^ (x >> 31);\n    }\n    uint64_t operator()() {\n        uint64_t r = rotl(s[1] * 5, 7) * 9;\n        uint64_t t = s[1] << 17;\n        s[2] ^= s[0];\n        s[3] ^= s[1];\n        s[1] ^= s[2];\n        s[0] ^= s[3];\n        s[2] ^= t;\n        s[3] = rotl(s[3], 45);\n        return r;\n    }\n    static uint64_t rotl(uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n};\nxoshiro256ss rng(rng_seed());\n\nlong long rnd_ll(long long l, long long r) {\n    if (l >= r) return l;\n    return l + (long long)(rng() % (uint64_t)(r - l + 1));\n}\nint rnd_int(int l, int r) {\n    if (l >= r) return l;\n    return l + (int)(rng() % (uint64_t)(r - l + 1));\n}\ndouble rnd_double() {\n    return (rng() >> 11) * (1.0 / (1ull << 53));\n}\n\n// ------------------------------------------------------------\n// Problem data\n// ------------------------------------------------------------\nstruct Line {\n    long long px, py, qx, qy;\n    long long A, B, C;\n};\n\nint N, K;\narray<int,11> need{};\nvector<long long> xs, ys;\nint target_score = 0;\n\nLine make_line_pts(long long px, long long py, long long qx, long long qy) {\n    Line L;\n    L.px = px; L.py = py; L.qx = qx; L.qy = qy;\n    L.A = qy - py;\n    L.B = px - qx;\n    L.C = qx*py - px*qy;\n    return L;\n}\n\n// extended gcd, returns g = gcd(a,b), finds x,y with ax+by=g\nlong long egcd(long long a, long long b, long long &x, long long &y) {\n    if (b == 0) { x = (a >= 0 ? 1 : -1); y = 0; return std::abs(a); }\n    long long x1, y1;\n    long long g = egcd(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\n// Find two integer points on Ax+By+C=0 inside [-1e9,1e9]\nbool get_two_points(long long A, long long B, long long C,\n                    long long &x1, long long &y1, long long &x2, long long &y2) {\n    const long long LIM = 1000000000LL;\n    if (B == 0) {\n        if (A == 0) return false;\n        if (C % A != 0) return false;\n        x1 = -C / A;\n        if (x1 < -LIM || x1 > LIM) return false;\n        y1 = 0;\n        x2 = x1; y2 = 1;\n        if (y2 < -LIM || y2 > LIM) return false;\n        return true;\n    }\n    long long g = std::gcd(std::abs(A), std::abs(B));\n    if (C % g != 0) return false;\n    long long a = A / g;\n    long long b = B / g;\n    long long c = -C / g;               // a*x + b*y = c\n    long long mod = std::abs(b);\n    long long a_mod = ((a % mod) + mod) % mod;\n    long long c_mod = ((c % mod) + mod) % mod;\n    long long inv, tmp;\n    egcd(a_mod, mod, inv, tmp);\n    inv = ((inv % mod) + mod) % mod;\n    long long x0 = (long long)((__int128)c_mod * inv % mod);\n\n    long long t = 0;\n    if (x0 < -LIM) t = (-LIM - x0 + mod - 1) / mod;\n    else if (x0 > LIM) t = -(x0 - LIM + mod - 1) / mod;\n\n    long long x = x0 + mod * t;\n    __int128 num = -(__int128)C - (__int128)A * x;\n    long long y = (long long)(num / B);\n\n    long long step_y = (b > 0) ? -a : a;   // change of y when x increases by mod\n    if (y < -LIM) {\n        long long need_up = -LIM - y;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need_up + abs_sy - 1) / abs_sy;\n            x += mod * dt;\n            y += step_y * dt;\n        }\n    } else if (y > LIM) {\n        long long need_down = y - LIM;\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (need_down + abs_sy - 1) / abs_sy;\n            x -= mod * dt;\n            y -= step_y * dt;\n        }\n    }\n    if (x < -LIM || x > LIM || y < -LIM || y > LIM) return false;\n\n    x1 = x; y1 = y;\n    x2 = x1 + mod;\n    if (x2 > LIM) x2 = x1 - mod;\n    __int128 num2 = -(__int128)C - (__int128)A * x2;\n    y2 = (long long)(num2 / B);\n\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) return false;\n    if (x1 == x2 && y1 == y2) return false;\n    return true;\n}\n\nbool intersects_disk(const Line& L) {\n    __int128 c2 = (__int128)L.C * L.C;\n    __int128 ab2 = (__int128)L.A * L.A + (__int128)L.B * L.B;\n    return c2 < ab2 * 100000000LL;   // radius 1e4  =>  r^2 = 1e8\n}\n\nbool valid_line(const Line& L) {\n    const long long LIM = 1000000000LL;\n    if (L.px < -LIM || L.px > LIM || L.py < -LIM || L.py > LIM) return false;\n    if (L.qx < -LIM || L.qx > LIM || L.qy < -LIM || L.qy > LIM) return false;\n    if (L.px == L.qx && L.py == L.qy) return false;\n    if (!intersects_disk(L)) return false;\n    for (int i = 0; i < N; ++i) {\n        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n        if (v == 0) return false;\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// Signature and hash table (must appear before functions that use them)\n// ------------------------------------------------------------\nstruct Sig {\n    uint64_t a, b;\n};\n\nstruct FastHT {\n    struct Node {\n        uint64_t a, b;\n        int cnt;\n    };\n    int n;\n    vector<Node> nodes;\n    vector<int> seen;\n    vector<int> occ;\n    int timer;\n    FastHT(int n_ = 1 << 14) {\n        n = n_;\n        nodes.resize(n);\n        seen.assign(n, 0);\n        timer = 1;\n    }\n    inline void next_timer() {\n        ++timer;\n        occ.clear();\n        if (timer > 2000000000) {\n            fill(seen.begin(), seen.end(), 0);\n            timer = 1;\n        }\n    }\n    inline void add(uint64_t a, uint64_t b) {\n        size_t h = a ^ (b * 11400714819323198485ull);\n        size_t idx = h & (n - 1);\n        while (seen[idx] == timer) {\n            if (nodes[idx].a == a && nodes[idx].b == b) {\n                ++nodes[idx].cnt;\n                return;\n            }\n            idx = (idx + 1) & (n - 1);\n        }\n        seen[idx] = timer;\n        nodes[idx].a = a;\n        nodes[idx].b = b;\n        nodes[idx].cnt = 1;\n        occ.push_back((int)idx);\n    }\n    inline int get_score(const array<int,11>& need) const {\n        int have[11] = {0};\n        for (int idx : occ) {\n            int c = nodes[idx].cnt;\n            if (c >= 1 && c <= 10) ++have[c];\n        }\n        int s = 0;\n        for (int d = 1; d <= 10; ++d) s += min(need[d], have[d]);\n        return s;\n    }\n};\n\nFastHT ht;\n\ninline int evaluate_sigs(const vector<Sig>& sigs) {\n    ht.next_timer();\n    for (const auto& s : sigs) ht.add(s.a, s.b);\n    return ht.get_score(need);\n}\n\nvector<Sig> recompute_sigs(const vector<Line>& ls) {\n    vector<Sig> s(N, {0, 0});\n    for (int j = 0; j < (int)ls.size(); ++j) {\n        if (j < 64) {\n            uint64_t mask = 1ULL << j;\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)ls[j].A * xs[i] + (__int128)ls[j].B * ys[i] + (__int128)ls[j].C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                s[i].a = (s[i].a & ~mask) | (bit << j);\n            }\n        } else {\n            uint64_t mask = 1ULL << (j - 64);\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)ls[j].A * xs[i] + (__int128)ls[j].B * ys[i] + (__int128)ls[j].C;\n                uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                s[i].b = (s[i].b & ~mask) | (bit << (j - 64));\n            }\n        }\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Candidate generators (Sig is now known)\n// ------------------------------------------------------------\nLine gen_random_line() {\n    const long long LIM = 200000;\n    while (true) {\n        long long x1 = rnd_ll(-LIM, LIM);\n        long long y1 = rnd_ll(-LIM, LIM);\n        long long x2 = rnd_ll(-LIM, LIM);\n        long long y2 = rnd_ll(-LIM, LIM);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n}\n\nLine gen_separator_line() {\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        int i = rnd_int(0, N - 1);\n        int j = rnd_int(0, N - 1);\n        if (i == j) continue;\n        long long xi = xs[i], yi = ys[i];\n        long long xj = xs[j], yj = ys[j];\n        long long A = xj - xi;\n        long long B = yj - yi;\n        if (A == 0 && B == 0) continue;\n        __int128 rhs = (__int128)xj*xj + (__int128)yj*yj - (__int128)xi*xi - (__int128)yi*yi;\n        long long T = (long long)(rhs / 2);\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        for (int d = -10; d <= 10; ++d) {\n            long long C = T + d;\n            if (C % g != 0) continue;\n            long long px, py, qx, qy;\n            if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\nLine gen_gap_line() {\n    static vector<long long> vals;\n    vals.assign(N, 0);\n    for (int attempt = 0; attempt < 20; ++attempt) {\n        long long A = rnd_ll(-1000, 1000);\n        long long B = rnd_ll(-1000, 1000);\n        if (A == 0 && B == 0) continue;\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        A /= g; B /= g;\n        for (int i = 0; i < N; ++i) vals[i] = A * xs[i] + B * ys[i];\n        sort(vals.begin(), vals.end());\n        vector<long long> uniq;\n        for (long long v : vals) {\n            if (uniq.empty() || uniq.back() != v) uniq.push_back(v);\n        }\n        if (uniq.size() <= 1) continue;\n        int idx = rnd_int(0, (int)uniq.size() - 2);\n        long long lo = uniq[idx];\n        long long hi = uniq[idx + 1];\n        if (hi <= lo + 1) continue;\n        long long C;\n        if (hi - lo > 2000000) C = lo + 1 + rnd_ll(0, 2000000);\n        else C = lo + 1 + rnd_ll(0, hi - lo - 1);\n        long long px, py, qx, qy;\n        if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n        Line L = make_line_pts(px, py, qx, qy);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\nLine perturb_line(const Line& L0) {\n    const long long D = 5;\n    for (int attempt = 0; attempt < 10; ++attempt) {\n        long long x1 = L0.px + rnd_ll(-D, D);\n        long long y1 = L0.py + rnd_ll(-D, D);\n        long long x2 = L0.qx + rnd_ll(-D, D);\n        long long y2 = L0.qy + rnd_ll(-D, D);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line(L)) return L;\n    }\n    return gen_random_line();\n}\n\n// Split a random piece into two parts; target size t\nLine gen_split_line(const vector<Sig>& sigs) {\n    static vector<int> bucket;\n    static vector<pair<long long,int>> proj;\n    bucket.reserve(64);\n    proj.reserve(64);\n\n    // First try to find a piece with >10 points (high priority)\n    for (int attempt = 0; attempt < 3; ++attempt) {\n        int idx = rnd_int(0, N - 1);\n        uint64_t ta = sigs[idx].a, tb = sigs[idx].b;\n        bucket.clear();\n        for (int i = 0; i < N; ++i) {\n            if (sigs[i].a == ta && sigs[i].b == tb) bucket.push_back(i);\n        }\n        int c = (int)bucket.size();\n        if (c <= 1) continue;\n        int t;\n        if (c > 10) {\n            t = rnd_int(1, 10);\n        } else {\n            t = rnd_int(1, c - 1);\n        }\n        for (int dir = 0; dir < 20; ++dir) {\n            long long dx = rnd_ll(-200, 200);\n            long long dy = rnd_ll(-200, 200);\n            if (dx == 0 && dy == 0) continue;\n            proj.clear();\n            for (int id : bucket) {\n                proj.emplace_back(dx * xs[id] + dy * ys[id], id);\n            }\n            sort(proj.begin(), proj.end());\n            if (proj[t - 1].first == proj[t].first) continue;\n            long long C = proj[t - 1].first + 1;\n            long long px, py, qx, qy;\n            if (!get_two_points(dx, dy, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n\n    // Fallback: any piece\n    for (int attempt = 0; attempt < 2; ++attempt) {\n        int idx = rnd_int(0, N - 1);\n        uint64_t ta = sigs[idx].a, tb = sigs[idx].b;\n        bucket.clear();\n        for (int i = 0; i < N; ++i) {\n            if (sigs[i].a == ta && sigs[i].b == tb) bucket.push_back(i);\n        }\n        int c = (int)bucket.size();\n        if (c <= 1) continue;\n        int t = rnd_int(1, c - 1);\n        for (int dir = 0; dir < 15; ++dir) {\n            long long dx = rnd_ll(-200, 200);\n            long long dy = rnd_ll(-200, 200);\n            if (dx == 0 && dy == 0) continue;\n            proj.clear();\n            for (int id : bucket) {\n                proj.emplace_back(dx * xs[id] + dy * ys[id], id);\n            }\n            sort(proj.begin(), proj.end());\n            if (proj[t - 1].first == proj[t].first) continue;\n            long long C = proj[t - 1].first + 1;\n            long long px, py, qx, qy;\n            if (!get_two_points(dx, dy, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\n// ------------------------------------------------------------\n// Main solver\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; ++d) {\n        cin >> need[d];\n        target_score += need[d];\n    }\n    xs.resize(N); ys.resize(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    const double TIME_LIMIT = 2.88;\n\n    vector<Line> best_lines;\n    int best_score = -1;\n\n    // We do one greedy build then SA; if time remains we restart.\n    int pass = 0;\n    while (elapsed() < TIME_LIMIT) {\n        ++pass;\n        // ---------- Greedy construction ----------\n        vector<Line> lines;\n        vector<Sig> sig(N, {0, 0});\n        int cur_score = 0;\n        const int GREEDY_CANDS = 100;\n        vector<Sig> tmp(N), best_sig;\n\n        for (int step = 0; step < K; ++step) {\n            Line best_line;\n            int best_score_local = cur_score;\n\n            for (int cand = 0; cand < GREEDY_CANDS; ++cand) {\n                int type = rnd_int(0, 3);\n                Line L;\n                if (type == 0) L = gen_random_line();\n                else if (type == 1) L = gen_gap_line();\n                else if (type == 2) L = gen_separator_line();\n                else L = gen_split_line(sig);\n                if (!valid_line(L)) continue;\n\n                int pj = step;\n                if (pj < 64) {\n                    uint64_t mask = 1ULL << pj;\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = (sig[i].a & ~mask) | (bit << pj);\n                        tmp[i].b = sig[i].b;\n                    }\n                } else {\n                    uint64_t mask = 1ULL << (pj - 64);\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        tmp[i].a = sig[i].a;\n                        tmp[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                    }\n                }\n                int sc = evaluate_sigs(tmp);\n                if (sc > best_score_local) {\n                    best_score_local = sc;\n                    best_line = L;\n                    best_sig = tmp;\n                }\n            }\n\n            if (best_score_local > cur_score) {\n                lines.push_back(best_line);\n                sig.swap(best_sig);\n                cur_score = best_score_local;\n            } else {\n                Line L = gen_random_line();\n                while (!valid_line(L)) L = gen_random_line();\n                lines.push_back(L);\n                int pj = step;\n                if (pj < 64) {\n                    uint64_t mask = 1ULL << pj;\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n                    }\n                } else {\n                    uint64_t mask = 1ULL << (pj - 64);\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                        uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                        sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                    }\n                }\n                cur_score = evaluate_sigs(sig);\n            }\n            if (cur_score == target_score) break;\n        }\n\n        while ((int)lines.size() < K) {\n            Line L = gen_random_line();\n            lines.push_back(L);\n            int pj = (int)lines.size() - 1;\n            if (pj < 64) {\n                uint64_t mask = 1ULL << pj;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].a = (sig[i].a & ~mask) | (bit << pj);\n                }\n            } else {\n                uint64_t mask = 1ULL << (pj - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    sig[i].b = (sig[i].b & ~mask) | (bit << (pj - 64));\n                }\n            }\n        }\n        cur_score = evaluate_sigs(sig);\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_lines = lines;\n        }\n\n        // ---------- Simulated Annealing ----------\n        double T = 2.0;\n        int last_improve = 0;\n        int iter = 0;\n        while (elapsed() < TIME_LIMIT) {\n            ++iter;\n            int j = rnd_int(0, K - 1);\n            int r = rnd_int(0, 99);\n            Line L;\n            if (r < 35) L = gen_split_line(sig);\n            else if (r < 55) L = gen_gap_line();\n            else if (r < 75) L = gen_random_line();\n            else if (r < 90) L = gen_separator_line();\n            else L = perturb_line(lines[j]);\n\n            if (!valid_line(L)) continue;\n\n            if (j < 64) {\n                uint64_t mask = 1ULL << j;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = (sig[i].a & ~mask) | (bit << j);\n                    tmp[i].b = sig[i].b;\n                }\n            } else {\n                uint64_t mask = 1ULL << (j - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    uint64_t bit = (v > 0) ? 1ULL : 0ULL;\n                    tmp[i].a = sig[i].a;\n                    tmp[i].b = (sig[i].b & ~mask) | (bit << (j - 64));\n                }\n            }\n            int new_score = evaluate_sigs(tmp);\n            int delta = new_score - cur_score;\n            if (delta > 0 || exp(delta / T) > rnd_double()) {\n                lines[j] = L;\n                sig.swap(tmp);\n                cur_score = new_score;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_lines = lines;\n                    last_improve = iter;\n                }\n            }\n\n            T *= 0.9997;\n            if (T < 0.0005) T = 0.0005;\n\n            // Kick if stuck for a while\n            if (iter - last_improve > 5000) {\n                T = 2.0;\n                last_improve = iter;\n                // Randomize 20 lines\n                for (int rep = 0; rep < 20; ++rep) {\n                    int jj = rnd_int(0, K - 1);\n                    Line RL = gen_random_line();\n                    lines[jj] = RL;\n                }\n                sig = recompute_sigs(lines);\n                cur_score = evaluate_sigs(sig);\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_lines = lines;\n                }\n            }\n        }\n\n        // If we have little time left, don't start another greedy\n        if (elapsed() >= TIME_LIMIT - 0.3) break;\n    }\n\n    // Final validation\n    for (int j = 0; j < K; ++j) {\n        if (!valid_line(best_lines[j])) {\n            best_lines[j] = gen_random_line();\n        }\n    }\n\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << best_lines[i].px << \" \" << best_lines[i].py << \" \"\n             << best_lines[i].qx << \" \" << best_lines[i].qy << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 64;\nconst int INF_P = 1e9;\n\nusing Record = array<int,8>;\n\nstruct Solver {\n    int N, M, cx;\n    int wgt[MAXN][MAXN];\n    bool init_dot[MAXN][MAXN];\n    long long init_sum = 0;\n\n    // per-run\n    bool dot[MAXN][MAXN];\n    bool horiz[MAXN][MAXN];\n    bool vert[MAXN][MAXN];\n    bool diag1[MAXN][MAXN];\n    bool diag2[MAXN][MAXN];\n    int best_peri[MAXN][MAXN];\n\n    priority_queue<tuple<long long,int,int,int>> pq; // (pri, rnd, x, y)\n    mt19937 rng;\n\n    inline bool seg_drawn(int x, int y, int dx, int dy) const {\n        if (dx == 1 && dy == 0) return horiz[x][y];\n        if (dx == -1 && dy == 0) return horiz[x-1][y];\n        if (dx == 0 && dy == 1) return vert[x][y];\n        if (dx == 0 && dy == -1) return vert[x][y-1];\n        if (dx == 1 && dy == 1) return diag1[x][y];\n        if (dx == -1 && dy == -1) return diag1[x-1][y-1];\n        if (dx == 1 && dy == -1) return diag2[x][y];\n        if (dx == -1 && dy == 1) return diag2[x-1][y+1];\n        return true;\n    }\n    inline void set_seg(int x, int y, int dx, int dy) {\n        if (dx == 1 && dy == 0) horiz[x][y] = true;\n        else if (dx == -1 && dy == 0) horiz[x-1][y] = true;\n        else if (dx == 0 && dy == 1) vert[x][y] = true;\n        else if (dx == 0 && dy == -1) vert[x][y-1] = true;\n        else if (dx == 1 && dy == 1) diag1[x][y] = true;\n        else if (dx == -1 && dy == -1) diag1[x-1][y-1] = true;\n        else if (dx == 1 && dy == -1) diag2[x][y] = true;\n        else if (dx == -1 && dy == 1) diag2[x-1][y+1] = true;\n    }\n\n    bool check_edge(int x1, int y1, int x2, int y2) const {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int x = x1, y = y1;\n        while (x != x2 || y != y2) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (nx != x2 || ny != y2) {\n                if (dot[nx][ny]) return false;\n            }\n            if (seg_drawn(x, y, dx, dy)) return false;\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void draw_edge(int x1, int y1, int x2, int y2) {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int x = x1, y = y1;\n        while (x != x2 || y != y2) {\n            set_seg(x, y, dx, dy);\n            x += dx; y += dy;\n        }\n    }\n\n    bool check_rect(int x1, int y1, int x2, int y2,\n                    int x3, int y3, int x4, int y4) const {\n        if (dot[x1][y1]) return false;\n        if (!dot[x2][y2] || !dot[x3][y3] || !dot[x4][y4]) return false;\n        if (!check_edge(x1,y1,x2,y2)) return false;\n        if (!check_edge(x2,y2,x3,y3)) return false;\n        if (!check_edge(x3,y3,x4,y4)) return false;\n        if (!check_edge(x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void draw_rect(const Record &r) {\n        draw_edge(r[0],r[1],r[2],r[3]);\n        draw_edge(r[2],r[3],r[4],r[5]);\n        draw_edge(r[4],r[5],r[6],r[7]);\n        draw_edge(r[6],r[7],r[0],r[1]);\n    }\n\n    // enumerate all rectangles for p1=(x,y); pick minimum perimeter\n    bool choose_rect(int x, int y, Record &out, int &out_peri) const {\n        bool found = false;\n        int best_p = 0;\n        Record best;\n\n        // axis-aligned\n        for (int x2 = 0; x2 < N; ++x2) if (dot[x2][y]) {\n            int dx = abs(x2 - x);\n            for (int y2 = 0; y2 < N; ++y2) if (dot[x][y2] && dot[x2][y2]) {\n                int peri = 2 * (dx + abs(y2 - y));\n                if (found && peri >= best_p) continue;\n                Record r = {x,y,x2,y,x2,y2,x,y2};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                found = true; best_p = peri; best = r;\n                if (best_p == 4) { out = best; out_peri = 4; return true; }\n            }\n        }\n\n        // 45-degree\n        int dmin = -min(x, y);\n        int dmax = N - max(x, y);\n        for (int d = dmin; d < dmax; ++d) if (d != 0) {\n            int x2 = x + d, y2 = y + d;\n            if (!dot[x2][y2]) continue;\n            int ad = abs(d);\n            int emin = max(-x, -(N - 1 - y));\n            int emax = min(N - 1 - x, y);\n            for (int e = emin; e <= emax; ++e) if (e != 0) {\n                int x4 = x + e, y4 = y - e;\n                if (!dot[x4][y4]) continue;\n                int peri = 2 * (ad + abs(e));\n                if (found && peri >= best_p) continue;\n                int x3 = x2 + x4 - x;\n                int y3 = y2 + y4 - y;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                Record r = {x,y,x2,y2,x3,y3,x4,y4};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                found = true; best_p = peri; best = r;\n                if (best_p == 4) { out = best; out_peri = 4; return true; }\n            }\n        }\n\n        if (found) { out = best; out_peri = best_p; }\n        return found;\n    }\n\n    long long calc_pri(int w, int p, int mode, int A, int B) {\n        if (p <= 0) p = 1;\n        long long wl = w;\n        long long pl = p;\n        switch (mode) {\n            case 0: return A * wl / pl;\n            case 1: return A * wl - B * pl;\n            case 2: return A * wl;\n            case 3: return -A * pl + wl;\n            case 4: return A * wl - B * pl * pl;\n            case 5: return A * wl / (pl * pl);\n            case 6: return A * wl / (pl + B);\n            case 7: return A * wl * wl / pl;\n            case 8: return A * wl / pl + (rng() & 0xFFFF);\n            case 9: return A * wl - B * pl * pl * pl;\n        }\n        return A * wl / pl;\n    }\n\n    void try_push(int x, int y, int peri, int mode, int A, int B) {\n        if (dot[x][y]) return;\n        if (peri >= best_peri[x][y]) return;\n        best_peri[x][y] = peri;\n        int rnd = rng() & 0x7FFF;\n        pq.emplace(calc_pri(wgt[x][y], peri, mode, A, B), rnd, x, y);\n    }\n\n    void find_new_candidates(int x, int y, int mode, int A, int B) {\n        // axis: P is p2, p1 same row\n        for (int x1 = 0; x1 < N; ++x1) if (!dot[x1][y]) {\n            int base = 2 * abs(x1 - x);\n            for (int y1 = 0; y1 < N; ++y1) if (dot[x][y1] && dot[x1][y1]) {\n                int peri = base + 2 * abs(y1 - y);\n                if (peri >= best_peri[x1][y]) continue;\n                if (check_rect(x1,y, x,y, x,y1, x1,y1))\n                    try_push(x1, y, peri, mode, A, B);\n            }\n        }\n\n        // axis: P is p2, p1 same column\n        for (int y1 = 0; y1 < N; ++y1) if (!dot[x][y1]) {\n            int base = 2 * abs(y1 - y);\n            for (int x2 = 0; x2 < N; ++x2) if (dot[x2][y] && dot[x2][y1]) {\n                int peri = base + 2 * abs(x2 - x);\n                if (peri >= best_peri[x][y1]) continue;\n                if (check_rect(x,y1, x,y, x2,y, x2,y1))\n                    try_push(x, y1, peri, mode, A, B);\n            }\n        }\n\n        // axis: P is p4, p1 same row\n        for (int x1 = 0; x1 < N; ++x1) if (!dot[x1][y]) {\n            int base = 2 * abs(x1 - x);\n            for (int y2 = 0; y2 < N; ++y2) if (dot[x1][y2] && dot[x][y2]) {\n                int peri = base + 2 * abs(y2 - y);\n                if (peri >= best_peri[x1][y]) continue;\n                if (check_rect(x1,y, x1,y2, x,y2, x,y))\n                    try_push(x1, y, peri, mode, A, B);\n            }\n        }\n\n        // axis: P is p4, p1 same column\n        for (int y1 = 0; y1 < N; ++y1) if (!dot[x][y1]) {\n            int base = 2 * abs(y1 - y);\n            for (int x2 = 0; x2 < N; ++x2) if (dot[x2][y1] && dot[x2][y]) {\n                int peri = base + 2 * abs(x2 - x);\n                if (peri >= best_peri[x][y1]) continue;\n                if (check_rect(x,y1, x2,y1, x2,y, x,y))\n                    try_push(x, y1, peri, mode, A, B);\n            }\n        }\n\n        // axis: P is p3 (opposite)\n        for (int x1 = 0; x1 < N; ++x1) if (dot[x1][y]) {\n            for (int y1 = 0; y1 < N; ++y1) if (dot[x][y1]) {\n                if (dot[x1][y1]) continue;\n                int peri = 2 * (abs(x1 - x) + abs(y1 - y));\n                if (peri >= best_peri[x1][y1]) continue;\n                if (check_rect(x1,y1, x1,y, x,y, x,y1))\n                    try_push(x1, y1, peri, mode, A, B);\n            }\n        }\n\n        // 45: P is p2, p1 on diag+1\n        int dmin = -min(x, y);\n        int dmax = N - max(x, y);\n        for (int d = dmin; d < dmax; ++d) if (d != 0) {\n            int x1 = x + d, y1 = y + d;\n            if (dot[x1][y1]) continue;\n            int ad = abs(d);\n            int emin = max(-x, -(N - 1 - y));\n            int emax = min(N - 1 - x, y);\n            for (int e = emin; e <= emax; ++e) if (e != 0) {\n                int x3 = x + e, y3 = y - e;\n                if (!dot[x3][y3]) continue;\n                int peri = 2 * (ad + abs(e));\n                if (peri >= best_peri[x1][y1]) continue;\n                int x4 = x1 + x3 - x;\n                int y4 = y1 + y3 - y;\n                if (x4 < 0 || x4 >= N || y4 < 0 || y4 >= N) continue;\n                if (!dot[x4][y4]) continue;\n                if (check_rect(x1,y1, x,y, x3,y3, x4,y4))\n                    try_push(x1, y1, peri, mode, A, B);\n            }\n        }\n\n        // 45: P is p2, p1 on diag-1\n        int s0 = x + y;\n        for (int i = max(0, s0-(N-1)); i <= min(N-1, s0); ++i) {\n            int j = s0 - i;\n            if (i == x && j == y) continue;\n            if (dot[i][j]) continue;\n            int ae = abs(i - x);\n            int dmin2 = -min(x, y);\n            int dmax2 = N - max(x, y);\n            for (int d = dmin2; d < dmax2; ++d) if (d != 0) {\n                int x3 = x + d, y3 = y + d;\n                if (!dot[x3][y3]) continue;\n                int peri = 2 * (ae + abs(d));\n                if (peri >= best_peri[i][j]) continue;\n                int x4 = i + x3 - x;\n                int y4 = j + y3 - y;\n                if (x4 < 0 || x4 >= N || y4 < 0 || y4 >= N) continue;\n                if (!dot[x4][y4]) continue;\n                if (check_rect(i,j, x,y, x3,y3, x4,y4))\n                    try_push(i, j, peri, mode, A, B);\n            }\n        }\n\n        // 45: P is p4, p1 on diag+1\n        int diff = x - y;\n        for (int x3 = max(0, diff), y3 = x3 - diff; x3 < N && y3 < N; ++x3, ++y3) {\n            if (x3 == x && y3 == y) continue;\n            if (!dot[x3][y3]) continue;\n            int ad = abs(x3 - x);\n            for (int i = max(0, s0-(N-1)); i <= min(N-1, s0); ++i) {\n                int j = s0 - i;\n                if (i == x && j == y) continue;\n                if (dot[i][j]) continue;\n                int peri = 2 * (ad + abs(i - x));\n                if (peri >= best_peri[i][j]) continue;\n                int x2 = i + x3 - x;\n                int y2 = j + y3 - y;\n                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N) continue;\n                if (!dot[x2][y2]) continue;\n                if (check_rect(i,j, x2,y2, x3,y3, x,y))\n                    try_push(i, j, peri, mode, A, B);\n            }\n        }\n\n        // 45: P is p4, p1 on diag-1\n        for (int x3 = max(0, s0-(N-1)); x3 <= min(N-1, s0); ++x3) {\n            int y3 = s0 - x3;\n            if (x3 == x && y3 == y) continue;\n            if (!dot[x3][y3]) continue;\n            int ae = abs(x3 - x);\n            for (int i = max(0, diff), j = i - diff; i < N && j < N; ++i, ++j) {\n                if (i == x && j == y) continue;\n                if (dot[i][j]) continue;\n                int peri = 2 * (ae + abs(i - x));\n                if (peri >= best_peri[i][j]) continue;\n                int x2 = i + x3 - x;\n                int y2 = j + y3 - y;\n                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N) continue;\n                if (!dot[x2][y2]) continue;\n                if (check_rect(i,j, x2,y2, x3,y3, x,y))\n                    try_push(i, j, peri, mode, A, B);\n            }\n        }\n\n        // 45: P is p3 (opposite)\n        int off = N - 1;\n        int id1 = x - y + off;\n        int id2 = x + y;\n        for (int d = dmin; d < dmax; ++d) if (d != 0) {\n            int x2 = x + d, y2 = y + d;\n            if (!dot[x2][y2]) continue;\n            int ad = abs(d);\n            int emin2 = max(-x, -(N - 1 - y));\n            int emax2 = min(N - 1 - x, y);\n            for (int e = emin2; e <= emax2; ++e) if (e != 0) {\n                int x4 = x + e, y4 = y - e;\n                if (!dot[x4][y4]) continue;\n                int peri = 2 * (ad + abs(e));\n                int x1 = x2 + x4 - x;\n                int y1 = y2 + y4 - y;\n                if (x1 < 0 || x1 >= N || y1 < 0 || y1 >= N) continue;\n                if (dot[x1][y1]) continue;\n                if (peri >= best_peri[x1][y1]) continue;\n                if (check_rect(x1,y1, x2,y2, x,y, x4,y4))\n                    try_push(x1, y1, peri, mode, A, B);\n            }\n        }\n    }\n\n    pair<long long, vector<Record>> solve_run(int mode, int A, int B, int seed,\n                                              const vector<Record>* pref = nullptr,\n                                              int pref_len = 0) {\n        rng.seed(seed);\n\n        memcpy(dot, init_dot, sizeof(dot));\n        memset(horiz, 0, sizeof(horiz));\n        memset(vert, 0, sizeof(vert));\n        memset(diag1, 0, sizeof(diag1));\n        memset(diag2, 0, sizeof(diag2));\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j)\n            best_peri[i][j] = INF_P;\n        while (!pq.empty()) pq.pop();\n\n        long long cur_sum = init_sum;\n        vector<Record> ops;\n        ops.reserve(N * N);\n\n        // replay prefix\n        if (pref && pref_len > 0) {\n            ops.insert(ops.end(), pref->begin(), pref->begin() + pref_len);\n            for (int i = 0; i < pref_len; ++i) {\n                const Record &r = (*pref)[i];\n                dot[r[0]][r[1]] = true;\n                draw_rect(r);\n                cur_sum += wgt[r[0]][r[1]];\n            }\n        }\n\n        // initial heap scan\n        Record rec;\n        int p;\n        for (int x = 0; x < N; ++x) {\n            for (int y = 0; y < N; ++y) if (!dot[x][y]) {\n                if (choose_rect(x, y, rec, p)) {\n                    best_peri[x][y] = p;\n                    int rnd = rng() & 0x7FFF;\n                    pq.emplace(calc_pri(wgt[x][y], p, mode, A, B), rnd, x, y);\n                }\n            }\n        }\n\n        while (!pq.empty()) {\n            auto [pri, rnd, x, y] = pq.top();\n            pq.pop();\n            if (dot[x][y]) continue;\n\n            Record r;\n            int peri;\n            if (!choose_rect(x, y, r, peri)) {\n                best_peri[x][y] = INF_P;\n                continue;\n            }\n            if (peri != best_peri[x][y]) {\n                best_peri[x][y] = peri;\n                rnd = rng() & 0x7FFF;\n                pq.emplace(calc_pri(wgt[x][y], peri, mode, A, B), rnd, x, y);\n                continue;\n            }\n\n            dot[x][y] = true;\n            cur_sum += wgt[x][y];\n            draw_rect(r);\n            ops.push_back(r);\n\n            find_new_candidates(x, y, mode, A, B);\n        }\n        return {cur_sum, ops};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n\n    Solver sol;\n    sol.N = N; sol.M = M;\n    sol.cx = (N - 1) / 2;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sol.wgt[i][j] = (i - sol.cx)*(i - sol.cx) + (j - sol.cx)*(j - sol.cx) + 1;\n\n    memset(sol.init_dot, 0, sizeof(sol.init_dot));\n    for (int i = 0; i < M; ++i) {\n        int x, y; cin >> x >> y;\n        sol.init_dot[x][y] = true;\n        sol.init_sum += sol.wgt[x][y];\n    }\n\n    const double TIME_LIMIT = 4.5;\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    long long best_score = -1;\n    vector<Record> best_moves;\n    vector<pair<long long, vector<Record>>> elite;\n\n    auto update_best = [&](long long sc, vector<Record> &mv) {\n        if (sc > best_score) {\n            best_score = sc;\n            best_moves = mv;\n        }\n        elite.push_back({sc, std::move(mv)});\n        sort(elite.begin(), elite.end(),\n             [](const auto &a, const auto &b){ return a.first > b.first; });\n        if ((int)elite.size() > 3) elite.resize(3);\n    };\n\n    // deterministic seeding\n    vector<tuple<int,int,int>> det = {\n        {0, 1000000, 0},\n        {1, 10000, 500},\n        {4, 10000, 500},\n        {6, 1000000, 10},\n        {7, 100, 0},\n        {3, 10000, 0},\n    };\n    for (auto &[md, A, B] : det) {\n        if (elapsed() > TIME_LIMIT) break;\n        auto [sc, mv] = sol.solve_run(md, A, B, 0);\n        update_best(sc, mv);\n    }\n\n    unsigned seed = 1;\n    while (elapsed() < TIME_LIMIT) {\n        int md = sol.rng() % 10;\n        int A = 0, B = 0;\n        switch (md) {\n            case 0: case 5: case 8:\n                A = 100000 + (sol.rng() % 1900000);\n                B = 0;\n                break;\n            case 6:\n                A = 100000 + (sol.rng() % 1900000);\n                B = sol.rng() % 200;\n                break;\n            case 1: case 4:\n                A = 1000 + (sol.rng() % 19000);\n                B = 1 + (sol.rng() % 2000);\n                break;\n            case 9:\n                A = 1000 + (sol.rng() % 19000);\n                B = 1 + (sol.rng() % 500);\n                break;\n            case 2:\n                A = 1000 + (sol.rng() % 19000);\n                B = 0;\n                break;\n            case 3:\n                A = 1000 + (sol.rng() % 19000);\n                B = 0;\n                break;\n            case 7:\n                A = 10 + (sol.rng() % 500);\n                B = 0;\n                break;\n        }\n\n        long long sc;\n        vector<Record> mv;\n        if (elite.empty() || (sol.rng() & 0x3) == 0) {\n            tie(sc, mv) = sol.solve_run(md, A, B, seed++);\n        } else {\n            const auto &pref_sol = elite[sol.rng() % elite.size()].second;\n            int t = pref_sol.empty() ? 0 : (sol.rng() % (int)pref_sol.size());\n            tie(sc, mv) = sol.solve_run(md, A, B, seed++, &pref_sol, t);\n        }\n        update_best(sc, mv);\n\n        if (sc == best_score && !best_moves.empty()) {\n            for (int rep = 0; rep < 2 && elapsed() < TIME_LIMIT; ++rep) {\n                int t = best_moves.empty() ? 0 : (sol.rng() % (int)best_moves.size());\n                int md2 = sol.rng() % 10;\n                int A2 = 100000 + (sol.rng() % 1900000);\n                int B2 = sol.rng() % 200;\n                auto [sc2, mv2] = sol.solve_run(md2, A2, B2, seed++, &best_moves, t);\n                update_best(sc2, mv2);\n            }\n        }\n    }\n\n    cout << best_moves.size() << \"\\n\";\n    for (auto &r : best_moves) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << r[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    uint8_t a[100];\n    State() { memset(a, 0, sizeof(a)); }\n};\n\n/* 4-neighbour table: 0=up,1=down,2=left,3=right, -1=out of bounds */\nint NBR[100][4];\n\n/* ------------------------------------------------------------------ */\n/* tilt the whole box                                                 */\ninline State tilt(const State& s, int dir) {\n    State ns;\n    if (dir == 0) {                 // Forward / Up\n        for (int c = 0; c < 10; ++c) {\n            int w = 0;\n            for (int r = 0; r < 10; ++r) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[w++ * 10 + c] = x;\n            }\n        }\n    } else if (dir == 1) {          // Backward / Down\n        for (int c = 0; c < 10; ++c) {\n            int w = 9;\n            for (int r = 9; r >= 0; --r) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[w-- * 10 + c] = x;\n            }\n        }\n    } else if (dir == 2) {          // Left\n        for (int r = 0; r < 10; ++r) {\n            int w = 0;\n            for (int c = 0; c < 10; ++c) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[r * 10 + w++] = x;\n            }\n        }\n    } else {                         // Right\n        for (int r = 0; r < 10; ++r) {\n            int w = 9;\n            for (int c = 9; c >= 0; --c) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[r * 10 + w--] = x;\n            }\n        }\n    }\n    return ns;\n}\n\n/* where does the candy at 'pos' end up after tilting 'dir'?          */\ninline int new_pos_after_tilt(const State& s, int pos, int dir) {\n    int r = pos / 10;\n    int c = pos % 10;\n    if (dir == 0) {\n        int cnt = 0;\n        for (int i = 0; i < r; ++i) if (s.a[i * 10 + c]) ++cnt;\n        return cnt * 10 + c;\n    } else if (dir == 1) {\n        int cnt = 0;\n        for (int i = r + 1; i < 10; ++i) if (s.a[i * 10 + c]) ++cnt;\n        return (9 - cnt) * 10 + c;\n    } else if (dir == 2) {\n        int cnt = 0;\n        for (int i = 0; i < c; ++i) if (s.a[r * 10 + i]) ++cnt;\n        return r * 10 + cnt;\n    } else {\n        int cnt = 0;\n        for (int i = c + 1; i < 10; ++i) if (s.a[r * 10 + i]) ++cnt;\n        return r * 10 + (9 - cnt);\n    }\n}\n\n/* exact score = sum of n_i^2                                         */\ninline int eval_state(const State& s) {\n    uint64_t vis[2] = {0, 0};\n    int q[100];\n    int score = 0;\n    for (int i = 0; i < 100; ++i) {\n        uint8_t f = s.a[i];\n        if (f == 0 || ((vis[i >> 6] >> (i & 63)) & 1ULL)) continue;\n        int qt = 0;\n        q[qt++] = i;\n        vis[i >> 6] |= 1ULL << (i & 63);\n        int sz = 0;\n        while (qt) {\n            int u = q[--qt];\n            ++sz;\n            for (int d = 0; d < 4; ++d) {\n                int v = NBR[u][d];\n                if (v >= 0 && ((vis[v >> 6] >> (v & 63)) & 1ULL) == 0 && s.a[v] == f) {\n                    vis[v >> 6] |= 1ULL << (v & 63);\n                    q[qt++] = v;\n                }\n            }\n        }\n        score += sz * sz;\n    }\n    return score;\n}\n\n/* component size of the cell 'start' (flavour f); local bitset       */\ninline int comp_size(const State& s, int start, uint8_t f) {\n    uint64_t vis[2] = {0, 0};\n    int stack[100];\n    int sp = 0;\n    stack[sp++] = start;\n    vis[start >> 6] |= 1ULL << (start & 63);\n    int cnt = 0;\n    while (sp) {\n        int u = stack[--sp];\n        ++cnt;\n        for (int d = 0; d < 4; ++d) {\n            int v = NBR[u][d];\n            if (v >= 0 && ((vis[v >> 6] >> (v & 63)) & 1ULL) == 0 && s.a[v] == f) {\n                vis[v >> 6] |= 1ULL << (v & 63);\n                stack[sp++] = v;\n            }\n        }\n    }\n    return cnt;\n}\n\n/* ------------------------------------------------------------------ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; ++i) {\n        NBR[i][0] = (i >= 10) ? i - 10 : -1;\n        NBR[i][1] = (i < 90) ? i + 10 : -1;\n        NBR[i][2] = (i % 10 != 0) ? i - 1 : -1;\n        NBR[i][3] = (i % 10 != 9) ? i + 1 : -1;\n    }\n\n    uint8_t flav[100];\n    for (int i = 0; i < 100; ++i) {\n        int x;\n        if (!(cin >> x)) return 0;\n        flav[i] = (uint8_t)x;\n    }\n\n    const char dname[4] = {'F', 'B', 'L', 'R'};\n    State cur;\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        --p;\n\n        int pos = -1;\n        for (int i = 0; i < 100; ++i) {\n            if (cur.a[i] == 0) {\n                if (p == 0) { pos = i; break; }\n                --p;\n            }\n        }\n        cur.a[pos] = flav[t];\n\n        if (t == 99) {                 // last candy: tilt does nothing\n            cout << \"F\\n\";\n            cout.flush();\n            break;\n        }\n\n        State base[4];\n        for (int d = 0; d < 4; ++d) base[d] = tilt(cur, d);\n\n        int remaining = 100 - t;\n        int K = max(10, min(100, 5000 / remaining));\n\n        long long total[4] = {0, 0, 0, 0};\n\n        for (int k = 0; k < K; ++k) {\n            unsigned seed = 123456789u + t * 10007u + k * 9973u;\n            mt19937 rng(seed);\n            int perm[100];\n            iota(perm, perm + 100, 0);\n            shuffle(perm, perm + 100, rng);\n\n            for (int d = 0; d < 4; ++d) {\n                State sim = base[d];\n                int ptr = 0;\n\n                for (int s = t + 1; s < 100; ++s) {\n                    while (ptr < 100 && sim.a[perm[ptr]] != 0) ++ptr;\n                    int idx;\n                    if (ptr >= 100) {\n                        for (int i = 0; i < 100; ++i)\n                            if (sim.a[i] == 0) { idx = i; break; }\n                    } else {\n                        idx = perm[ptr];\n                        ++ptr;\n                    }\n\n                    uint8_t f = flav[s];\n                    sim.a[idx] = f;\n\n                    if (s == 99) break; // no tilt after the final candy\n\n                    State ts[4];\n                    int np[4];\n                    int sz[4];\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        ts[d2] = tilt(sim, d2);\n                        np[d2] = new_pos_after_tilt(sim, idx, d2);\n                        sz[d2] = comp_size(ts[d2], np[d2], f);\n                    }\n\n                    int nb[4];\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        int cnt = 0;\n                        for (int dir = 0; dir < 4; ++dir) {\n                            int v = NBR[np[d2]][dir];\n                            if (v >= 0 && ts[d2].a[v] == f) ++cnt;\n                        }\n                        nb[d2] = cnt;\n                    }\n\n                    int best_dir = 0;\n                    for (int d2 = 1; d2 < 4; ++d2) {\n                        if (sz[d2] > sz[best_dir] ||\n                            (sz[d2] == sz[best_dir] && nb[d2] > nb[best_dir])) {\n                            best_dir = d2;\n                        }\n                    }\n\n                    sim = ts[best_dir];\n                }\n                total[d] += eval_state(sim);\n            }\n        }\n\n        int best = 0;\n        for (int d = 1; d < 4; ++d)\n            if (total[d] > total[best]) best = d;\n\n        cur = base[best];\n        cout << dname[best] << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\nusing Feature = vector<double>;\n\nint M;\ndouble eps;\nmt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// Graph with up to 100 vertices (stored as two 64-bit rows)\n// ------------------------------------------------------------\nstruct Graph {\n    ull a[100][2];\n};\n\ninline void initGraph(Graph& g, int n) {\n    for (int i = 0; i < n; ++i) g.a[i][0] = g.a[i][1] = 0;\n}\n\ninline void setBit(Graph& g, int u, int v) {\n    int idx = v >> 6;\n    int bit = v & 63;\n    g.a[u][idx] |= (1ULL << bit);\n}\n\ninline bool getBit(const Graph& g, int u, int v) {\n    int idx = v >> 6;\n    int bit = v & 63;\n    return (g.a[u][idx] >> bit) & 1ULL;\n}\n\n// generate a random graph with exactly wantEdges edges\nGraph randomGraphWithEdges(int n, int wantEdges) {\n    Graph g;\n    initGraph(g, n);\n    int L = n * (n - 1) / 2;\n    vector<pair<int,int>> edges;\n    edges.reserve(L);\n    for (int i = 0; i < n; ++i)\n        for (int j = i + 1; j < n; ++j)\n            edges.emplace_back(i, j);\n    shuffle(edges.begin(), edges.end(), rng);\n    wantEdges = max(0, min(L, wantEdges));\n    for (int e = 0; e < wantEdges; ++e) {\n        auto [u, v] = edges[e];\n        setBit(g, u, v);\n        setBit(g, v, u);\n    }\n    return g;\n}\n\n// channel: random permutation + BSC(eps)\nGraph addNoise(const Graph& g, int n, double ep) {\n    vector<int> perm(n);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    Graph h;\n    initGraph(h, n);\n    uniform_real_distribution<double> d(0.0, 1.0);\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            int pi = perm[i];\n            int pj = perm[j];\n            bool has = getBit(g, pi, pj);\n            if (d(rng) < ep) has = !has;\n            if (has) {\n                setBit(h, i, j);\n                setBit(h, j, i);\n            }\n        }\n    }\n    return h;\n}\n\n// ------------------------------------------------------------\n// Fast permutation-invariant feature extraction\n// ------------------------------------------------------------\nFeature extract(const Graph& g, int n) {\n    ull mask[2];\n    if (n >= 64) {\n        mask[0] = ~0ULL;\n        int r = n - 64;\n        mask[1] = (1ULL << r) - 1ULL;\n    } else {\n        mask[0] = (1ULL << n) - 1ULL;\n        mask[1] = 0;\n    }\n\n    int deg[100] = {};\n    for (int i = 0; i < n; ++i) {\n        deg[i] = __builtin_popcountll(g.a[i][0] & mask[0])\n               + __builtin_popcountll(g.a[i][1] & mask[1]);\n    }\n\n    double tri = 0.0;\n    double tri_pv[100] = {};\n    long long c4h = 0;\n    long long trace4 = 0;\n\n    for (int i = 0; i < n; ++i) {\n        trace4 += 1LL * deg[i] * deg[i];\n        for (int j = i + 1; j < n; ++j) {\n            int c = __builtin_popcountll(g.a[i][0] & g.a[j][0] & mask[0])\n                  + __builtin_popcountll(g.a[i][1] & g.a[j][1] & mask[1]);\n            if (getBit(g, i, j)) {\n                tri += c;\n                tri_pv[i] += c;\n                tri_pv[j] += c;\n            }\n            c4h += 1LL * c * (c - 1) / 2;\n            trace4 += 2LL * c * c;\n        }\n    }\n    tri /= 3.0;\n    for (int i = 0; i < n; ++i) tri_pv[i] *= 0.5;\n\n    double t2[100] = {};\n    double w3[100] = {};\n    for (int i = 0; i < n; ++i) {\n        long long s2 = 0;\n        for (int j = 0; j < n; ++j) if (getBit(g, i, j)) s2 += deg[j];\n        t2[i] = (double)s2;\n    }\n    for (int i = 0; i < n; ++i) {\n        double s3 = 0;\n        for (int j = 0; j < n; ++j) if (getBit(g, i, j)) s3 += t2[j];\n        w3[i] = s3;\n    }\n\n    long long p2 = 0;\n    long long sum_deg2 = 0, sum_deg3 = 0;\n    long long sum_tri = 0, sum_t2 = 0;\n    for (int i = 0; i < n; ++i) {\n        p2 += 1LL * deg[i] * (deg[i] - 1) / 2;\n        sum_deg2 += 1LL * deg[i] * deg[i];\n        sum_deg3 += 1LL * deg[i] * deg[i] * deg[i];\n        sum_tri += (long long)tri_pv[i];\n        sum_t2 += (long long)t2[i];\n    }\n\n    double darr[100], tarr[100], t2arr[100], w3arr[100];\n    for (int i = 0; i < n; ++i) {\n        darr[i] = deg[i];\n        tarr[i] = tri_pv[i];\n        t2arr[i] = t2[i];\n        w3arr[i] = w3[i];\n    }\n    sort(darr, darr + n);\n    sort(tarr, tarr + n);\n    sort(t2arr, t2arr + n);\n    sort(w3arr, w3arr + n);\n\n    double m = 0;\n    for (int i = 0; i < n; ++i) m += deg[i];\n    m *= 0.5;\n\n    Feature f;\n    f.reserve(10 + 4 * n);\n    f.push_back(m);\n    f.push_back(tri);\n    f.push_back(6.0 * tri);          // trace(A^3)\n    f.push_back((double)trace4);     // trace(A^4)\n    f.push_back((double)p2);         // # 2-paths\n    f.push_back((double)c4h);        // helper for 4-cycles\n    f.push_back((double)sum_deg2);\n    f.push_back((double)sum_deg3);\n    f.push_back((double)sum_tri);\n    f.push_back((double)sum_t2);\n    for (int i = 0; i < n; ++i) f.push_back(darr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(tarr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(t2arr[i]);\n    for (int i = 0; i < n; ++i) f.push_back(w3arr[i]);\n    return f;\n}\n\n// ------------------------------------------------------------\n// Decoder\n// ------------------------------------------------------------\nint predict(const Feature& f, const vector<Feature>& F, const vector<double>& w) {\n    int best = 0;\n    double bestv = 1e300;\n    int D = (int)f.size();\n    for (int k = 0; k < (int)F.size(); ++k) {\n        double d = 0.0;\n        for (int i = 0; i < D; ++i) {\n            double diff = f[i] - F[k][i];\n            d += diff * diff * w[i];\n        }\n        if (d < bestv) {\n            bestv = d;\n            best = k;\n        }\n    }\n    return best;\n}\n\n// ------------------------------------------------------------\n// Utilities\n// ------------------------------------------------------------\ndouble binaryEntropy(double p) {\n    if (p <= 0.0 || p >= 1.0) return 0.0;\n    return -(p * log2(p) + (1.0 - p) * log2(1.0 - p));\n}\n\n// Lightweight greedy farthest-point codebook construction\nvector<Graph> generateCodebook(int n, int m) {\n    int L = n * (n - 1) / 2;\n    int poolSize = max(200, m * 2);\n    vector<Graph> pool;\n    pool.reserve(poolSize);\n    uniform_real_distribution<double> pDist(0.05, 0.95);\n\n    for (int i = 0; i < poolSize; ++i) {\n        int want = (int)(L * pDist(rng));\n        want = max(0, min(L, want));\n        pool.push_back(randomGraphWithEdges(n, want));\n    }\n\n    vector<Feature> poolF(poolSize);\n    for (int i = 0; i < poolSize; ++i) poolF[i] = extract(pool[i], n);\n    int D = (int)poolF[0].size();\n\n    // normalize for distance computation\n    vector<double> mean(D, 0.0), stdv(D, 0.0);\n    for (int i = 0; i < poolSize; ++i)\n        for (int d = 0; d < D; ++d) mean[d] += poolF[i][d];\n    for (int d = 0; d < D; ++d) mean[d] /= poolSize;\n    for (int i = 0; i < poolSize; ++i) {\n        for (int d = 0; d < D; ++d) {\n            double diff = poolF[i][d] - mean[d];\n            stdv[d] += diff * diff;\n        }\n    }\n    for (int d = 0; d < D; ++d) stdv[d] = sqrt(stdv[d] / poolSize + 1e-12);\n\n    vector<Graph> cb;\n    vector<Feature> selF;\n    cb.reserve(m);\n    selF.reserve(m);\n\n    int first = (int)(rng() % poolSize);\n    cb.push_back(pool[first]);\n    selF.push_back(poolF[first]);\n\n    vector<double> minDist(poolSize, 1e300);\n    while ((int)cb.size() < m) {\n        int last = (int)cb.size() - 1;\n        for (int j = 0; j < poolSize; ++j) {\n            double d = 0.0;\n            for (int k = 0; k < D; ++k) {\n                double diff = (poolF[j][k] - selF[last][k]) / stdv[k];\n                d += diff * diff;\n            }\n            if (d < minDist[j]) minDist[j] = d;\n        }\n        int best = 0;\n        for (int j = 1; j < poolSize; ++j)\n            if (minDist[j] > minDist[best]) best = j;\n        cb.push_back(pool[best]);\n        selF.push_back(poolF[best]);\n    }\n    return cb;\n}\n\nvector<double> learnWeights(const vector<Graph>& Gs, const vector<Feature>& F, int n) {\n    int D = (int)F[0].size();\n    vector<double> var(D, 0.0);\n    uniform_int_distribution<int> sdist(0, M - 1);\n    int S = 80;\n    for (int b = 0; b < S; ++b) {\n        int s = sdist(rng);\n        Graph h = addNoise(Gs[s], n, eps);\n        Feature f = extract(h, n);\n        for (int d = 0; d < D; ++d) {\n            double diff = f[d] - F[s][d];\n            var[d] += diff * diff;\n        }\n    }\n    vector<double> w(D);\n    for (int d = 0; d < D; ++d) {\n        var[d] /= S;\n        w[d] = 1.0 / (var[d] + 1e-6);\n    }\n    return w;\n}\n\nint validate(const vector<Graph>& Gs, const vector<Feature>& F,\n             const vector<double>& w, int n) {\n    int err = 0;\n    uniform_int_distribution<int> sdist(0, M - 1);\n    for (int b = 0; b < 80; ++b) {\n        int s = sdist(rng);\n        Graph h = addNoise(Gs[s], n, eps);\n        Feature f = extract(h, n);\n        if (predict(f, F, w) != s) ++err;\n    }\n    return err;\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> M >> eps)) return 0;\n\n    double cap = 1.0 - binaryEntropy(eps);\n    double needBits = log2((double)M) + 20.0;          // generous margin\n    double needEdges = needBits / max(cap, 1e-9);\n    int startN = 4;\n    while (startN * (startN - 1) / 2.0 < needEdges && startN < 100) ++startN;\n    startN = max(startN, 8);\n    startN = min(startN, 100);\n\n    vector<Graph> bestG;\n    vector<Feature> bestF;\n    vector<double> bestW;\n    int bestN = 100;\n    bool found = false;\n\n    for (int delta = 0; delta <= 8; delta += 2) {\n        int n = startN + delta;\n        if (n > 100) n = 100;\n        for (int attempt = 0; attempt < 3; ++attempt) {\n            auto Gs = generateCodebook(n, M);\n            vector<Feature> F(M);\n            for (int k = 0; k < M; ++k) F[k] = extract(Gs[k], n);\n            auto w = learnWeights(Gs, F, n);\n            int err = validate(Gs, F, w, n);\n            if (err == 0) {\n                bestN = n;\n                bestG = move(Gs);\n                bestF = move(F);\n                bestW = move(w);\n                found = true;\n                break;\n            }\n        }\n        if (found) break;\n        if (n == 100) break;\n    }\n\n    if (!found) {\n        bestN = 100;\n        bestG = generateCodebook(100, M);\n        bestF.resize(M);\n        for (int k = 0; k < M; ++k) bestF[k] = extract(bestG[k], 100);\n        bestW = learnWeights(bestG, bestF, 100);\n    }\n\n    // output codebook\n    cout << bestN << \"\\n\";\n    for (int k = 0; k < M; ++k) {\n        string s;\n        s.reserve(bestN * (bestN - 1) / 2);\n        for (int i = 0; i < bestN; ++i) {\n            for (int j = i + 1; j < bestN; ++j) {\n                s.push_back(getBit(bestG[k], i, j) ? '1' : '0');\n            }\n        }\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // answer 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string hs;\n        cin >> hs;\n        Graph h;\n        initGraph(h, bestN);\n        int pos = 0;\n        for (int i = 0; i < bestN; ++i) {\n            for (int j = i + 1; j < bestN; ++j) {\n                if (hs[pos++] == '1') {\n                    setBit(h, i, j);\n                    setBit(h, j, i);\n                }\n            }\n        }\n        Feature f = extract(h, bestN);\n        int ans = predict(f, bestF, bestW);\n        cout << ans << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst int INF_INT = 1000000000;\nconst ll INF_LL = (1LL<<60);\n\nstruct SimpleHeap {\n    static const int MAXN = 10005;\n    pair<int,int> a[MAXN];\n    int n;\n    void clear(){ n=0; }\n    void push(pair<int,int> x){\n        int i=n++;\n        while(i>0){\n            int p=(i-1)>>1;\n            if(a[p].first <= x.first) break;\n            a[i]=a[p];\n            i=p;\n        }\n        a[i]=x;\n    }\n    pair<int,int> top() const { return a[0]; }\n    void pop(){\n        pair<int,int> x = a[--n];\n        int i=0;\n        while(true){\n            int l=(i<<1)|1;\n            if(l>=n) break;\n            int r=l+1, c=l;\n            if(r<n && a[r].first < a[l].first) c=r;\n            if(x.first <= a[c].first) break;\n            a[i]=a[c];\n            i=c;\n        }\n        a[i]=x;\n    }\n    bool empty() const { return n==0; }\n};\n\nint N, M, D, K;\nstruct Edge {int u, v, w;};\nvector<Edge> edges;\nvector<vector<tuple<int,int,int>>> adj;\nvector<int> rem_stamp;\nint cur_stamp = 1;\n\ninline pair<int,ll> dijkstra(int s, int stamp, vector<int>& dist, SimpleHeap& pq){\n    fill(dist.begin(), dist.end(), INF_INT);\n    dist[s] = 0;\n    pq.clear();\n    pq.push({0, s});\n    ll sum = 0;\n    int visited = 0;\n    while(!pq.empty()){\n        auto [d,u] = pq.top(); pq.pop();\n        if(d != dist[u]) continue;\n        visited++;\n        sum += d;\n        for(const auto& [v,w,eid] : adj[u]){\n            if(rem_stamp[eid] == stamp) continue;\n            if(dist[v] > d + w){\n                dist[v] = d + w;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {visited, sum};\n}\n\n// Evaluate proxy score of a day. exact=false -> INF if disconnected. exact=true -> add penalty.\nll eval_day(int day, int out_eid, int in_eid, const vector<int>& samples,\n            const vector<vector<int>>& day_edges,\n            vector<int>& dist, SimpleHeap& pq, bool exact=false){\n    int stamp = cur_stamp++;\n    for(int eid : day_edges[day]){\n        if(eid == out_eid) continue;\n        rem_stamp[eid] = stamp;\n    }\n    if(in_eid != -1) rem_stamp[in_eid] = stamp;\n    ll total = 0;\n    for(int s : samples){\n        auto [vis, sum] = dijkstra(s, stamp, dist, pq);\n        if(vis < N){\n            if(!exact) return INF_LL;\n            total += sum + (ll)(N - vis) * INF_INT;\n        } else {\n            total += sum;\n        }\n    }\n    return total;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    cin >> N >> M >> D >> K;\n    edges.resize(M);\n    adj.assign(N, {});\n    vector<int> xs(N), ys(N);\n    for(int i=0;i<M;i++){\n        int u,v,w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u,v,w};\n        adj[u].push_back({v,w,i});\n        adj[v].push_back({u,w,i});\n    }\n    for(int i=0;i<N;i++) cin >> xs[i] >> ys[i];\n\n    rem_stamp.assign(M, 0);\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // ----- approximate edge importance (shortest path tree usage) -----\n    vector<int> imp(M, 0);\n    vector<int> dist0(N);\n    vector<int> parent(N);\n    SimpleHeap pq0;\n    for(int it=0; it<100; it++){\n        int s = rng() % N;\n        fill(dist0.begin(), dist0.end(), INF_INT);\n        dist0[s] = 0;\n        fill(parent.begin(), parent.end(), -1);\n        pq0.clear();\n        pq0.push({0, s});\n        while(!pq0.empty()){\n            auto [d,u] = pq0.top(); pq0.pop();\n            if(d != dist0[u]) continue;\n            for(const auto& [v,w,eid] : adj[u]){\n                if(dist0[v] > d + w){\n                    dist0[v] = d + w;\n                    parent[v] = eid;\n                    pq0.push({dist0[v], v});\n                }\n            }\n        }\n        for(int v=0; v<N; v++){\n            if(v != s && parent[v] != -1) imp[parent[v]]++;\n        }\n    }\n\n    // ----- greedy initialization (balance importance) -----\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        if(imp[a] != imp[b]) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    vector<int> edge_day(M);\n    vector<vector<int>> day_edges(D);\n    vector<ll> day_imp_sum(D, 0);\n    vector<int> day_load(D, 0);\n    for(int eid : order){\n        int best_d = -1;\n        ll best_val = INF_LL;\n        for(int d=0; d<D; d++){\n            if(day_load[d] >= K) continue;\n            if(day_imp_sum[d] < best_val){\n                best_val = day_imp_sum[d];\n                best_d = d;\n            }\n        }\n        if(best_d == -1){\n            for(int d=0; d<D; d++) if(day_load[d] < K){ best_d = d; break; }\n        }\n        edge_day[eid] = best_d;\n        day_edges[best_d].push_back(eid);\n        day_load[best_d]++;\n        day_imp_sum[best_d] += imp[eid];\n    }\n\n    // ----- ensure every day is connected -----\n    vector<int> dist(N);\n    SimpleHeap pq;\n    auto is_conn = [&](int d)->bool{\n        static vector<int> dummy = {0};\n        return eval_day(d, -1, -1, dummy, day_edges, dist, pq) < INF_LL;\n    };\n\n    for(int d=0; d<D; d++){\n        int attempts = 0;\n        while(!is_conn(d)){\n            int d2 = rng() % D;\n            if(d2 == d) continue;\n            if(day_edges[d].empty() || day_edges[d2].empty()) continue;\n            int i1 = rng() % (int)day_edges[d].size();\n            int i2 = rng() % (int)day_edges[d2].size();\n            int e1 = day_edges[d][i1];\n            int e2 = day_edges[d2][i2];\n            swap(day_edges[d][i1], day_edges[d2][i2]);\n            edge_day[e1] = d2;\n            edge_day[e2] = d;\n            if(is_conn(d) && is_conn(d2)){\n                // keep swap\n            } else {\n                swap(day_edges[d][i1], day_edges[d2][i2]);\n                edge_day[e1] = d;\n                edge_day[e2] = d2;\n            }\n            if(++attempts > 20000) break;\n        }\n    }\n\n    // ----- stratified sample sources -----\n    vector<pair<int,int>> nodes_by_x;\n    for(int i=0;i<N;i++) nodes_by_x.push_back({xs[i], i});\n    sort(nodes_by_x.begin(), nodes_by_x.end());\n    const int NS = 20;\n    vector<int> samples;\n    for(int i=0;i<NS;i++){\n        int L = i * N / NS;\n        int R = (i+1) * N / NS;\n        if(L >= R) continue;\n        int idx = L + (int)(rng() % (R - L));\n        samples.push_back(nodes_by_x[idx].second);\n    }\n    while((int)samples.size() < NS) samples.push_back(rng() % N);\n\n    // ----- compute initial proxy scores -----\n    vector<ll> day_score(D);\n    auto recompute_day = [&](int d){\n        day_score[d] = eval_day(d, -1, -1, samples, day_edges, dist, pq);\n    };\n    for(int d=0; d<D; d++) recompute_day(d);\n    ll cur_total = 0;\n    for(ll v : day_score) cur_total += v;\n\n    vector<int> best_edge_day = edge_day;\n    vector<vector<int>> best_day_edges = day_edges;\n    ll best_total = cur_total;\n\n    const double TIME_LIMIT = 5.4;\n    int stagnant = 0;\n\n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if(elapsed > TIME_LIMIT) break;\n\n        int d1 = rng() % D;\n        int d2 = rng() % D;\n        if(d1 == d2) continue;\n        if(day_edges[d1].empty() || day_edges[d2].empty()) continue;\n        int i1 = rng() % (int)day_edges[d1].size();\n        int i2 = rng() % (int)day_edges[d2].size();\n        int e1 = day_edges[d1][i1];\n        int e2 = day_edges[d2][i2];\n\n        ll s1 = eval_day(d1, e1, e2, samples, day_edges, dist, pq);\n        if(s1 >= INF_LL) continue;\n        ll s2 = eval_day(d2, e2, e1, samples, day_edges, dist, pq);\n        if(s2 >= INF_LL) continue;\n\n        ll new_total = cur_total - day_score[d1] - day_score[d2] + s1 + s2;\n        if(new_total < cur_total){\n            edge_day[e1] = d2;\n            edge_day[e2] = d1;\n            day_edges[d1][i1] = e2;\n            day_edges[d2][i2] = e1;\n            day_score[d1] = s1;\n            day_score[d2] = s2;\n            cur_total = new_total;\n            stagnant = 0;\n            if(cur_total < best_total){\n                best_total = cur_total;\n                best_edge_day = edge_day;\n                best_day_edges = day_edges;\n            }\n        } else {\n            stagnant++;\n            if(stagnant > 300){\n                // perturb from best and continue\n                bool ok = false;\n                for(int attempt=0; attempt<10; attempt++){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                    int num_swaps = 10 + (int)(rng() % 10);\n                    for(int k=0; k<num_swaps; k++){\n                        int a = rng() % D;\n                        int b = rng() % D;\n                        if(a == b) continue;\n                        if(day_edges[a].empty() || day_edges[b].empty()) continue;\n                        int ai = rng() % (int)day_edges[a].size();\n                        int bi = rng() % (int)day_edges[b].size();\n                        int ae = day_edges[a][ai];\n                        int be = day_edges[b][bi];\n                        swap(day_edges[a][ai], day_edges[b][bi]);\n                        edge_day[ae] = b;\n                        edge_day[be] = a;\n                    }\n                    bool all_conn = true;\n                    for(int d=0; d<D; d++){\n                        if(!is_conn(d)){\n                            all_conn = false;\n                            break;\n                        }\n                    }\n                    if(all_conn){\n                        ok = true;\n                        break;\n                    }\n                }\n                if(!ok){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                }\n                for(int d=0; d<D; d++) recompute_day(d);\n                cur_total = 0;\n                for(ll v : day_score) cur_total += v;\n                stagnant = 0;\n                if(cur_total < best_total){\n                    best_total = cur_total;\n                    best_edge_day = edge_day;\n                    best_day_edges = day_edges;\n                }\n            }\n        }\n    }\n\n    for(int i=0;i<M;i++){\n        if(i) cout << ' ';\n        cout << best_edge_day[i] + 1;\n    }\n    cout << '\\n';\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nvector<string> F[2], R[2];\n\nusing BS = bitset<196>;\nBS validMask[2][16];\nBS occ[2][16];\nbool needF[2][16][16] = {};\nbool needR[2][16][16] = {};\n\nint prefFree[2][17][17][17];\nint needPrefF[2][16][17];\nint needPrefR[2][16][17];\n\nstruct Block {\n    int id;\n    vector<array<int,3>> c[2];\n};\nvector<Block> blocks;\nint nextId = 1;\n\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nchrono::steady_clock::time_point startT;\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startT).count();\n}\n\n/* ---------- 3D prefix sums of free valid cells ---------- */\nvoid rebuildPrefFree(int idx) {\n    for (int x = 0; x < D; ++x)\n        for (int y = 0; y < D; ++y)\n            for (int z = 0; z < D; ++z) {\n                int v = (validMask[idx][z].test(x * D + y) && !occ[idx][z].test(x * D + y)) ? 1 : 0;\n                prefFree[idx][x + 1][y + 1][z + 1] =\n                    v\n                    + prefFree[idx][x][y + 1][z + 1]\n                    + prefFree[idx][x + 1][y][z + 1]\n                    + prefFree[idx][x + 1][y + 1][z]\n                    - prefFree[idx][x][y][z + 1]\n                    - prefFree[idx][x][y + 1][z]\n                    - prefFree[idx][x + 1][y][z]\n                    + prefFree[idx][x][y][z];\n            }\n}\n\ninline int boxFreeSum(int idx, int x, int y, int z, int dx, int dy, int dz) {\n    auto &p = prefFree[idx];\n    int x1 = x, y1 = y, z1 = z;\n    int x2 = x + dx, y2 = y + dy, z2 = z + dz;\n    return p[x2][y2][z2] - p[x1][y2][z2] - p[x2][y1][z2] - p[x2][y2][z1]\n         + p[x1][y1][z2] + p[x1][y2][z1] + p[x2][y1][z1] - p[x1][y1][z1];\n}\n\n/* ---------- need prefix sums per layer ---------- */\nvoid rebuildNeedPref(int idx) {\n    for (int z = 0; z < D; ++z) {\n        needPrefF[idx][z][0] = 0;\n        needPrefR[idx][z][0] = 0;\n        for (int i = 0; i < D; ++i) {\n            needPrefF[idx][z][i + 1] = needPrefF[idx][z][i] + (needF[idx][z][i] ? 1 : 0);\n            needPrefR[idx][z][i + 1] = needPrefR[idx][z][i] + (needR[idx][z][i] ? 1 : 0);\n        }\n    }\n}\n\ninline int boxBenefit(int idx, int x, int y, int z, int dx, int dy, int dz) {\n    int ben = 0;\n    for (int k = 0; k < dz; ++k) {\n        ben += needPrefF[idx][z + k][x + dx] - needPrefF[idx][z + k][x];\n        ben += needPrefR[idx][z + k][y + dy] - needPrefR[idx][z + k][y];\n    }\n    return ben;\n}\n\n/* ---------- place a shared block ---------- */\nvoid placeShared(const vector<array<int,3>> &c1, const vector<array<int,3>> &c2) {\n    int id = nextId++;\n    for (auto [x, y, z] : c1) {\n        occ[0][z].set(x * D + y);\n        needF[0][z][x] = false;\n        needR[0][z][y] = false;\n    }\n    for (auto [x, y, z] : c2) {\n        occ[1][z].set(x * D + y);\n        needF[1][z][x] = false;\n        needR[1][z][y] = false;\n    }\n    blocks.push_back({id, c1, c2});\n}\n\n/* ---------- 24 proper rotations ---------- */\nvector<array<array<int,3>,3>> genRotations() {\n    vector<array<array<int,3>,3>> res;\n    array<int,3> p = {0, 1, 2};\n    do {\n        int signPerm = ((p[0] == 0 && p[1] == 1 && p[2] == 2) ||\n                        (p[0] == 1 && p[1] == 2 && p[2] == 0) ||\n                        (p[0] == 2 && p[1] == 0 && p[2] == 1)) ? 1 : -1;\n        for (int sx : {1, -1}) {\n            for (int sy : {1, -1}) {\n                int sz = sx * sy * signPerm;\n                array<array<int,3>,3> m = {};\n                m[0][p[0]] = sx;\n                m[1][p[1]] = sy;\n                m[2][p[2]] = sz;\n                res.push_back(m);\n            }\n        }\n    } while (next_permutation(p.begin(), p.end()));\n    return res;\n}\n\n/* ================================================================ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    startT = chrono::steady_clock::now();\n\n    /* ---- input ---- */\n    if (!(cin >> D)) return 0;\n    for (int i = 0; i < 2; ++i) {\n        F[i].resize(D); R[i].resize(D);\n        for (int z = 0; z < D; ++z) cin >> F[i][z];\n        for (int z = 0; z < D; ++z) cin >> R[i][z];\n    }\n\n    auto rots = genRotations();\n\n    /* ---- valid masks and needs ---- */\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            for (int x = 0; x < D; ++x) {\n                needF[i][z][x] = (F[i][z][x] == '1');\n                for (int y = 0; y < D; ++y) {\n                    bool ok = (F[i][z][x] == '1' && R[i][z][y] == '1');\n                    if (ok) validMask[i][z].set(x * D + y);\n                    needR[i][z][y] = (R[i][z][y] == '1');\n                }\n            }\n        }\n    }\n\n    /* ---- ordered box shapes (volume >= 2) ---- */\n    struct Shape { int dx, dy, dz, vol; };\n    vector<Shape> shapes;\n    for (int dx = 1; dx <= D; ++dx)\n        for (int dy = 1; dy <= D; ++dy)\n            for (int dz = 1; dz <= D; ++dz)\n                if (dx * dy * dz >= 2)\n                    shapes.push_back({dx, dy, dz, dx * dy * dz});\n    sort(shapes.begin(), shapes.end(),\n         [](const Shape &a, const Shape &b) { return a.vol > b.vol; });\n\n    const double BOX_TIME = 3.5;\n    const double TIME_LIMIT = 5.8;\n    const int DIRS[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};\n\n    /* ============================================================\n       PHASE 1 : Greedy shared boxes (ordered shapes, top-K + random)\n       ============================================================ */\n    while (elapsed() < BOX_TIME) {\n        rebuildPrefFree(0); rebuildPrefFree(1);\n        rebuildNeedPref(0); rebuildNeedPref(1);\n\n        long long bestScore = -1;\n        int best_x1 = 0, best_y1 = 0, best_z1 = 0;\n        int best_x2 = 0, best_y2 = 0, best_z2 = 0;\n        int best_dx = 0, best_dy = 0, best_dz = 0;\n        int best_px = 0, best_py = 0, best_pz = 0;\n\n        int limitShapes = min((int)shapes.size(), 300);\n        for (int si = 0; si < limitShapes; ++si) {\n            int dx = shapes[si].dx, dy = shapes[si].dy, dz = shapes[si].dz;\n            int vol = shapes[si].vol;\n\n            struct Cand { int x, y, z, ben; };\n            vector<Cand> pos1, zero1;\n            for (int x = 0; x + dx <= D; ++x)\n                for (int y = 0; y + dy <= D; ++y)\n                    for (int z = 0; z + dz <= D; ++z)\n                        if (boxFreeSum(0, x, y, z, dx, dy, dz) == vol) {\n                            int b = boxBenefit(0, x, y, z, dx, dy, dz);\n                            if (b > 0) pos1.push_back({x, y, z, b});\n                            else if ((int)zero1.size() < 15) zero1.push_back({x, y, z, 0});\n                        }\n\n            if (pos1.empty() && zero1.empty()) continue;\n            if ((int)pos1.size() > 50) {\n                shuffle(pos1.begin(), pos1.end(), rng);\n                pos1.resize(50);\n            }\n\n            array<int,3> dim = {dx, dy, dz};\n            sort(dim.begin(), dim.end());\n            do {\n                int px = dim[0], py = dim[1], pz = dim[2];\n                vector<Cand> pos2, zero2;\n                for (int x = 0; x + px <= D; ++x)\n                    for (int y = 0; y + py <= D; ++y)\n                        for (int z = 0; z + pz <= D; ++z)\n                            if (boxFreeSum(1, x, y, z, px, py, pz) == vol) {\n                                int b = boxBenefit(1, x, y, z, px, py, pz);\n                                if (b > 0) pos2.push_back({x, y, z, b});\n                                else if ((int)zero2.size() < 15) zero2.push_back({x, y, z, 0});\n                            }\n\n                if (pos2.empty() && zero2.empty()) continue;\n                if ((int)pos2.size() > 50) {\n                    shuffle(pos2.begin(), pos2.end(), rng);\n                    pos2.resize(50);\n                }\n\n                auto consider = [&](const Cand &a, const Cand &b, int b1, int b2) {\n                    if (b1 + b2 == 0) return;\n                    long long score = (long long)(b1 + b2) * 1000LL + vol;\n                    if (score > bestScore) {\n                        bestScore = score;\n                        best_x1 = a.x; best_y1 = a.y; best_z1 = a.z;\n                        best_x2 = b.x; best_y2 = b.y; best_z2 = b.z;\n                        best_dx = dx; best_dy = dy; best_dz = dz;\n                        best_px = px; best_py = py; best_pz = pz;\n                    }\n                };\n\n                for (auto &a : pos1)\n                    for (auto &b : pos2)\n                        consider(a, b, a.ben, b.ben);\n                for (auto &a : pos1)\n                    for (auto &b : zero2)\n                        consider(a, b, a.ben, 0);\n                for (auto &a : zero1)\n                    for (auto &b : pos2)\n                        consider(a, b, 0, b.ben);\n            } while (next_permutation(dim.begin(), dim.end()));\n        }\n\n        if (bestScore <= 0) break;\n\n        vector<array<int,3>> c1, c2;\n        c1.reserve(best_dx * best_dy * best_dz);\n        c2.reserve(best_px * best_py * best_pz);\n        for (int k = 0; k < best_dz; ++k)\n            for (int i = 0; i < best_dx; ++i)\n                for (int j = 0; j < best_dy; ++j)\n                    c1.push_back({best_x1 + i, best_y1 + j, best_z1 + k});\n        for (int k = 0; k < best_pz; ++k)\n            for (int i = 0; i < best_px; ++i)\n                for (int j = 0; j < best_py; ++j)\n                    c2.push_back({best_x2 + i, best_y2 + j, best_z2 + k});\n        placeShared(c1, c2);\n    }\n\n    /* ============================================================\n       PHASE 2 : Random BFS shared polycubes\n       ============================================================ */\n    while (elapsed() < TIME_LIMIT) {\n        long long bestScore = -1;\n        vector<array<int,3>> bestC1, bestC2;\n\n        for (int it = 0; it < 4000; ++it) {\n            array<int,3> s1 = {-1,-1,-1}, s2 = {-1,-1,-1};\n            for (int att = 0; att < 30; ++att) {\n                int x = (int)(rng() % D), y = (int)(rng() % D), z = (int)(rng() % D);\n                if (validMask[0][z].test(x * D + y) && !occ[0][z].test(x * D + y)) {\n                    s1 = {x, y, z}; break;\n                }\n            }\n            if (s1[0] < 0) continue;\n            for (int att = 0; att < 30; ++att) {\n                int x = (int)(rng() % D), y = (int)(rng() % D), z = (int)(rng() % D);\n                if (validMask[1][z].test(x * D + y) && !occ[1][z].test(x * D + y)) {\n                    s2 = {x, y, z}; break;\n                }\n            }\n            if (s2[0] < 0) continue;\n\n            for (int rc = 0; rc < 3; ++rc) {\n                const auto &rot = rots[rng() % rots.size()];\n\n                bool inObj1[14][14][14] = {};\n                vector<array<int,3>> shape, q;\n                shape.reserve(30);\n                q.reserve(30);\n\n                auto tryAdd = [&](int x, int y, int z) {\n                    if (x < 0 || x >= D || y < 0 || y >= D || z < 0 || z >= D) return;\n                    if (inObj1[x][y][z]) return;\n                    if (!validMask[0][z].test(x * D + y) || occ[0][z].test(x * D + y)) return;\n                    int rx = x - s1[0], ry = y - s1[1], rz = z - s1[2];\n                    int ax2 = s2[0] + rot[0][0] * rx + rot[0][1] * ry + rot[0][2] * rz;\n                    int ay2 = s2[1] + rot[1][0] * rx + rot[1][1] * ry + rot[1][2] * rz;\n                    int az2 = s2[2] + rot[2][0] * rx + rot[2][1] * ry + rot[2][2] * rz;\n                    if (ax2 < 0 || ax2 >= D || ay2 < 0 || ay2 >= D || az2 < 0 || az2 >= D) return;\n                    if (!validMask[1][az2].test(ax2 * D + ay2) || occ[1][az2].test(ax2 * D + ay2)) return;\n                    inObj1[x][y][z] = true;\n                    shape.push_back({x, y, z});\n                    q.push_back({x, y, z});\n                };\n\n                inObj1[s1[0]][s1[1]][s1[2]] = true;\n                shape.push_back(s1);\n                q.push_back(s1);\n\n                while (!q.empty() && (int)shape.size() < 30) {\n                    int qi = (int)(rng() % q.size());\n                    auto cur = q[qi];\n                    q[qi] = q.back();\n                    q.pop_back();\n\n                    array<int,6> ord = {0, 1, 2, 3, 4, 5};\n                    shuffle(ord.begin(), ord.end(), rng);\n                    for (int d : ord) {\n                        tryAdd(cur[0] + DIRS[d][0], cur[1] + DIRS[d][1], cur[2] + DIRS[d][2]);\n                        if ((int)shape.size() >= 30) break;\n                    }\n                }\n\n                if ((int)shape.size() < 2) continue;\n\n                bool seenF1[16][16] = {}, seenR1[16][16] = {};\n                int ben1 = 0;\n                for (auto &v : shape) {\n                    int x = v[0], y = v[1], z = v[2];\n                    if (!seenF1[z][x] && needF[0][z][x]) { seenF1[z][x] = true; ++ben1; }\n                    if (!seenR1[z][y] && needR[0][z][y]) { seenR1[z][y] = true; ++ben1; }\n                }\n\n                bool seenF2[16][16] = {}, seenR2[16][16] = {};\n                int ben2 = 0;\n                for (auto &v : shape) {\n                    int rx = v[0] - s1[0], ry = v[1] - s1[1], rz = v[2] - s1[2];\n                    int x = s2[0] + rot[0][0] * rx + rot[0][1] * ry + rot[0][2] * rz;\n                    int y = s2[1] + rot[1][0] * rx + rot[1][1] * ry + rot[1][2] * rz;\n                    int z = s2[2] + rot[2][0] * rx + rot[2][1] * ry + rot[2][2] * rz;\n                    if (!seenF2[z][x] && needF[1][z][x]) { seenF2[z][x] = true; ++ben2; }\n                    if (!seenR2[z][y] && needR[1][z][y]) { seenR2[z][y] = true; ++ben2; }\n                }\n\n                if (ben1 + ben2 == 0) continue;\n                long long score = (long long)(ben1 + ben2) * 1000LL + (int)shape.size();\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestC1.clear(); bestC2.clear();\n                    for (auto &v : shape) bestC1.push_back(v);\n                    for (auto &v : shape) {\n                        int rx = v[0] - s1[0], ry = v[1] - s1[1], rz = v[2] - s1[2];\n                        int x = s2[0] + rot[0][0] * rx + rot[0][1] * ry + rot[0][2] * rz;\n                        int y = s2[1] + rot[1][0] * rx + rot[1][1] * ry + rot[1][2] * rz;\n                        int z = s2[2] + rot[2][0] * rx + rot[2][1] * ry + rot[2][2] * rz;\n                        bestC2.push_back({x, y, z});\n                    }\n                }\n            }\n        }\n\n        if (bestScore > 0) placeShared(bestC1, bestC2);\n        else break;\n    }\n\n    /* ============================================================\n       PHASE 3 : Fatten every shared block (simultaneous BFS)\n       ============================================================ */\n    for (auto &bl : blocks) {\n        // recover the rotation that maps c[0] to c[1]\n        array<array<int,3>,3> R;\n        bool found = false;\n        for (const auto &rot : rots) {\n            bool ok = true;\n            for (size_t i = 0; i < bl.c[0].size(); ++i) {\n                int rx = bl.c[0][i][0] - bl.c[0][0][0];\n                int ry = bl.c[0][i][1] - bl.c[0][0][1];\n                int rz = bl.c[0][i][2] - bl.c[0][0][2];\n                int x2 = bl.c[1][0][0] + rot[0][0]*rx + rot[0][1]*ry + rot[0][2]*rz;\n                int y2 = bl.c[1][0][1] + rot[1][0]*rx + rot[1][1]*ry + rot[1][2]*rz;\n                int z2 = bl.c[1][0][2] + rot[2][0]*rx + rot[2][1]*ry + rot[2][2]*rz;\n                if (x2 != bl.c[1][i][0] || y2 != bl.c[1][i][1] || z2 != bl.c[1][i][2]) {\n                    ok = false; break;\n                }\n            }\n            if (ok) { R = rot; found = true; break; }\n        }\n        if (!found) continue;\n\n        bool inBlock1[14][14][14] = {};\n        queue<array<int,3>> q;\n        for (auto &c : bl.c[0]) {\n            inBlock1[c[0]][c[1]][c[2]] = true;\n            q.push(c);\n        }\n\n        while (!q.empty()) {\n            auto cur = q.front(); q.pop();\n            for (int d = 0; d < 6; ++d) {\n                int nx = cur[0] + DIRS[d][0];\n                int ny = cur[1] + DIRS[d][1];\n                int nz = cur[2] + DIRS[d][2];\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n                if (inBlock1[nx][ny][nz]) continue;\n                if (!validMask[0][nz].test(nx * D + ny) || occ[0][nz].test(nx * D + ny)) continue;\n\n                int rx = nx - bl.c[0][0][0];\n                int ry = ny - bl.c[0][0][1];\n                int rz = nz - bl.c[0][0][2];\n                int ax2 = bl.c[1][0][0] + R[0][0]*rx + R[0][1]*ry + R[0][2]*rz;\n                int ay2 = bl.c[1][0][1] + R[1][0]*rx + R[1][1]*ry + R[1][2]*rz;\n                int az2 = bl.c[1][0][2] + R[2][0]*rx + R[2][1]*ry + R[2][2]*rz;\n                if (ax2 < 0 || ax2 >= D || ay2 < 0 || ay2 >= D || az2 < 0 || az2 >= D) continue;\n                if (!validMask[1][az2].test(ax2 * D + ay2) || occ[1][az2].test(ax2 * D + ay2)) continue;\n\n                inBlock1[nx][ny][nz] = true;\n                occ[0][nz].set(nx * D + ny);\n                occ[1][az2].set(ax2 * D + ay2);\n                if (needF[0][nz][nx]) needF[0][nz][nx] = false;\n                if (needR[0][nz][ny]) needR[0][nz][ny] = false;\n                if (needF[1][az2][ax2]) needF[1][az2][ax2] = false;\n                if (needR[1][az2][ay2]) needR[1][az2][ay2] = false;\n                bl.c[0].push_back({nx, ny, nz});\n                bl.c[1].push_back({ax2, ay2, az2});\n                q.push({nx, ny, nz});\n            }\n        }\n    }\n\n    /* ============================================================\n       PHASE 4 : Minimum edge cover for remaining unique needs\n       ============================================================ */\n    vector<array<int,3>> uniq[2];\n\n    for (int idx = 0; idx < 2; ++idx) {\n        for (int z = 0; z < D; ++z) {\n            vector<int> xs, ys;\n            for (int x = 0; x < D; ++x) if (needF[idx][z][x]) xs.push_back(x);\n            for (int y = 0; y < D; ++y) if (needR[idx][z][y]) ys.push_back(y);\n            int nL = (int)xs.size(), nR = (int)ys.size();\n            if (nL == 0 && nR == 0) continue;\n\n            if (nL == 0) {\n                for (int y : ys) {\n                    for (int x = 0; x < D; ++x) {\n                        int c = x * D + y;\n                        if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                            occ[idx][z].set(c);\n                            uniq[idx].push_back({x, y, z});\n                            break;\n                        }\n                    }\n                }\n                continue;\n            }\n            if (nR == 0) {\n                for (int x : xs) {\n                    for (int y = 0; y < D; ++y) {\n                        int c = x * D + y;\n                        if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                            occ[idx][z].set(c);\n                            uniq[idx].push_back({x, y, z});\n                            break;\n                        }\n                    }\n                }\n                continue;\n            }\n\n            int yId[16];\n            fill(begin(yId), end(yId), -1);\n            for (int i = 0; i < nR; ++i) yId[ys[i]] = i;\n            vector<vector<int>> adj(nL);\n            for (int i = 0; i < nL; ++i) {\n                int x = xs[i];\n                for (int y : ys) {\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c))\n                        adj[i].push_back(yId[y]);\n                }\n            }\n\n            vector<int> matchR(nR, -1);\n            function<bool(int, vector<char>&)> dfs = [&](int v, vector<char> &seen) -> bool {\n                for (int to : adj[v]) {\n                    if (seen[to]) continue;\n                    seen[to] = 1;\n                    if (matchR[to] == -1 || dfs(matchR[to], seen)) {\n                        matchR[to] = v;\n                        return true;\n                    }\n                }\n                return false;\n            };\n            for (int v = 0; v < nL; ++v) {\n                vector<char> seen(nR, 0);\n                dfs(v, seen);\n            }\n\n            vector<char> matchedL(nL, 0), matchedR(nR, 0);\n            vector<pair<int,int>> cover;\n            for (int j = 0; j < nR; ++j) if (matchR[j] != -1) {\n                cover.push_back({matchR[j], j});\n                matchedL[matchR[j]] = 1;\n                matchedR[j] = 1;\n            }\n            for (int i = 0; i < nL; ++i) if (!matchedL[i]) {\n                for (int to : adj[i]) {\n                    cover.push_back({i, to});\n                    break;\n                }\n            }\n            for (int j = 0; j < nR; ++j) if (!matchedR[j]) {\n                int y = ys[j];\n                for (int i = 0; i < nL; ++i) {\n                    int x = xs[i];\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                        cover.push_back({i, j});\n                        break;\n                    }\n                }\n            }\n\n            sort(cover.begin(), cover.end());\n            cover.erase(unique(cover.begin(), cover.end()), cover.end());\n\n            for (auto &e : cover) {\n                int x = xs[e.first];\n                int y = ys[e.second];\n                int c = x * D + y;\n                if (!validMask[idx][z].test(c) || occ[idx][z].test(c)) continue;\n                occ[idx][z].set(c);\n                uniq[idx].push_back({x, y, z});\n            }\n        }\n    }\n\n    /* ============================================================\n       PHASE 5 : Pair leftover unit cubes between the two objects\n       ============================================================ */\n    int common = min((int)uniq[0].size(), (int)uniq[1].size());\n    vector<int> id0(uniq[0].size()), id1(uniq[1].size());\n    int curId = 1;\n    for (auto &bl : blocks) bl.id = curId++;\n    for (int i = 0; i < common; ++i) {\n        id0[i] = curId;\n        id1[i] = curId;\n        ++curId;\n    }\n    for (int i = common; i < (int)uniq[0].size(); ++i) id0[i] = curId++;\n    for (int i = common; i < (int)uniq[1].size(); ++i) id1[i] = curId++;\n\n    /* ============================================================\n       Output\n       ============================================================ */\n    vector<int> b0(D * D * D, 0), b1(D * D * D, 0);\n    for (auto &bl : blocks) {\n        for (auto [x, y, z] : bl.c[0]) b0[x * D * D + y * D + z] = bl.id;\n        for (auto [x, y, z] : bl.c[1]) b1[x * D * D + y * D + z] = bl.id;\n    }\n    for (int i = 0; i < (int)uniq[0].size(); ++i) {\n        auto [x, y, z] = uniq[0][i];\n        b0[x * D * D + y * D + z] = id0[i];\n    }\n    for (int i = 0; i < (int)uniq[1].size(); ++i) {\n        auto [x, y, z] = uniq[1][i];\n        b1[x * D * D + y * D + z] = id1[i];\n    }\n\n    cout << (curId - 1) << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b0[i];\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b1[i];\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = (1LL << 60);\n\nint N, M, K;\nlong long xs[100], ys[100];\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nEdge edges[300];\nEdge esort[300];\nint edgeIdMat[100][100];\nvector<pair<int,int>> adj[100];\n\n// need[k][v] : ceil(euclidean distance) between resident k and vertex v\nstatic int need[5000][100];\n\n// ---------- DSU ----------\nstruct DSU {\n    int p[100];\n    int rnk[100];\n    void init(int n) {\n        for (int i = 0; i < n; ++i) {\n            p[i] = i;\n            rnk[i] = 0;\n        }\n    }\n    int find(int x) { return p[x]==x ? x : p[x]=find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a,b);\n        p[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n};\n\n// ---------- MST of induced subgraph ----------\nlong long mst(const char inV[100], pair<int,int> te[100], int& teCnt) {\n    teCnt = 0;\n    int nV = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) ++nV;\n    if (nV == 0) return INF;\n    if (nV == 1) return 0;\n    DSU dsu;\n    dsu.init(N);\n    long long cost = 0;\n    int used = 0;\n    for (int j = 0; j < M; ++j) {\n        int u = esort[j].u, v = esort[j].v;\n        if (!inV[u] || !inV[v]) continue;\n        if (dsu.unite(u, v)) {\n            te[teCnt++] = {u, v};\n            cost += esort[j].w;\n            if (++used == nV - 1) break;\n        }\n    }\n    if (used != nV - 1) return INF;\n    return cost;\n}\n\n// ---------- Greedy power cost (fast) ----------\nlong long calc_power_fast(const char inV[100], int outP[100], int assign[5000]) {\n    int act[100];\n    int R = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) act[R++] = i;\n    if (R == 0) return INF;\n\n    static int minNeed[5000];\n    for (int k = 0; k < K; ++k) {\n        int mn = 100000;\n        for (int i = 0; i < R; ++i) {\n            int d = need[k][act[i]];\n            if (d < mn) mn = d;\n        }\n        if (mn > 5000) return INF;\n        minNeed[k] = mn;\n    }\n\n    static int bucketHead[5001];\n    static int bucketNext[5000];\n    memset(bucketHead, -1, sizeof(bucketHead));\n    for (int k = 0; k < K; ++k) {\n        int d = minNeed[k];\n        bucketNext[k] = bucketHead[d];\n        bucketHead[d] = k;\n    }\n\n    static int Plocal[100];\n    for (int i = 0; i < R; ++i) Plocal[i] = 0;\n\n    for (int d = 5000; d >= 0; --d) {\n        for (int k = bucketHead[d]; k != -1; k = bucketNext[k]) {\n            int bestIdx = -1;\n            long long bestInc = LLONG_MAX;\n            for (int i = 0; i < R; ++i) {\n                int dist = need[k][act[i]];\n                if (dist > 5000) continue;\n                if (Plocal[i] >= dist) {\n                    bestIdx = i;\n                    bestInc = 0;\n                    break;\n                }\n                long long inc = 1LL*dist*dist - 1LL*Plocal[i]*Plocal[i];\n                if (inc < bestInc) {\n                    bestInc = inc;\n                    bestIdx = i;\n                }\n            }\n            if (bestIdx == -1) return INF;\n            int dist = need[k][act[bestIdx]];\n            if (dist > Plocal[bestIdx]) Plocal[bestIdx] = dist;\n            assign[k] = act[bestIdx];\n        }\n    }\n\n    for (int i = 0; i < N; ++i) outP[i] = 0;\n    long long cost = 0;\n    for (int i = 0; i < R; ++i) {\n        outP[act[i]] = Plocal[i];\n        cost += 1LL*Plocal[i]*Plocal[i];\n    }\n    return cost;\n}\n\n// ---------- Refine assignment (critical moves) ----------\nlong long refine_assignment(const char inV[100], int P[100], int assign[5000]) {\n    int act[100];\n    int pos[100];\n    int R = 0;\n    for (int i = 0; i < N; ++i) {\n        if (inV[i]) {\n            pos[i] = R;\n            act[R++] = i;\n        }\n    }\n    if (R == 0) return INF;\n\n    static int Plocal[100];\n    for (int i = 0; i < R; ++i) Plocal[i] = P[act[i]];\n\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        static int max1[100], max2[100], who[100];\n        for (int i = 0; i < R; ++i) {\n            max1[i] = max2[i] = -1;\n            who[i] = -1;\n        }\n        for (int k = 0; k < K; ++k) {\n            int v = assign[k];\n            int idx = pos[v];\n            int d = need[k][v];\n            if (d > max1[idx]) {\n                max2[idx] = max1[idx];\n                max1[idx] = d;\n                who[idx] = k;\n            } else if (d > max2[idx]) {\n                max2[idx] = d;\n            }\n        }\n        for (int idx = 0; idx < R; ++idx) {\n            if (who[idx] == -1) continue;\n            int k = who[idx];\n            int dik = need[k][act[idx]];\n            long long saving = 1LL*dik*dik - (max2[idx] <= 0 ? 0LL : 1LL*max2[idx]*max2[idx]);\n            for (int jdx = 0; jdx < R; ++jdx) {\n                if (jdx == idx) continue;\n                int djk = need[k][act[jdx]];\n                if (djk > 5000) continue;\n                int newP = max(Plocal[jdx], djk);\n                if (newP > 5000) continue;\n                long long costj = 1LL*newP*newP - 1LL*Plocal[jdx]*Plocal[jdx];\n                if (costj < saving) {\n                    assign[k] = act[jdx];\n                    Plocal[idx] = max2[idx] <= 0 ? 0 : max2[idx];\n                    Plocal[jdx] = newP;\n                    changed = true;\n                    break;\n                }\n            }\n            if (changed) break;\n        }\n    }\n\n    long long cost = 0;\n    for (int i = 0; i < N; ++i) P[i] = 0;\n    for (int i = 0; i < R; ++i) {\n        P[act[i]] = Plocal[i];\n        cost += 1LL*Plocal[i]*Plocal[i];\n    }\n    return cost;\n}\n\n// ---------- First-improvement descent ----------\nvoid descent(char inV[100], long long& cost,\n             pair<int,int> te[100], int& teCnt, int P[100],\n             int assign[5000], mt19937& rng) {\n    while (true) {\n        int deg[100] = {0};\n        for (int i = 0; i < teCnt; ++i) {\n            ++deg[te[i].first];\n            ++deg[te[i].second];\n        }\n        int leaves[100], leafCnt = 0;\n        for (int i = 1; i < N; ++i)\n            if (inV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n\n        if (leafCnt > 0) {\n            shuffle(leaves, leaves + leafCnt, rng);\n            bool improved = false;\n            for (int idx = 0; idx < leafCnt; ++idx) {\n                int u = leaves[idx];\n                inV[u] = 0;\n                pair<int,int> nte[100]; int nteCnt;\n                int nP[100]; int nassign[5000];\n                long long ec = mst(inV, nte, nteCnt);\n                if (ec < INF) {\n                    long long pc = calc_power_fast(inV, nP, nassign);\n                    if (pc < INF && ec + pc < cost) {\n                        cost = ec + pc;\n                        teCnt = nteCnt;\n                        memcpy(te, nte, sizeof(pair<int,int>) * teCnt);\n                        memcpy(P, nP, sizeof(int) * N);\n                        memcpy(assign, nassign, sizeof(int) * K);\n                        improved = true;\n                        break;\n                    }\n                }\n                inV[u] = 1;\n            }\n            if (improved) continue;\n        }\n\n        bool seen[100] = {false};\n        int cand[100], candCnt = 0;\n        for (int i = 0; i < N; ++i) if (inV[i]) {\n            for (auto& [to, id] : adj[i]) {\n                if (!inV[to] && !seen[to]) {\n                    seen[to] = true;\n                    cand[candCnt++] = to;\n                }\n            }\n        }\n\n        if (candCnt > 0) {\n            shuffle(cand, cand + candCnt, rng);\n            bool improved = false;\n            for (int idx = 0; idx < candCnt; ++idx) {\n                int v = cand[idx];\n                inV[v] = 1;\n                pair<int,int> nte[100]; int nteCnt;\n                int nP[100]; int nassign[5000];\n                long long ec = mst(inV, nte, nteCnt);\n                if (ec < INF) {\n                    long long pc = calc_power_fast(inV, nP, nassign);\n                    if (pc < INF && ec + pc < cost) {\n                        cost = ec + pc;\n                        teCnt = nteCnt;\n                        memcpy(te, nte, sizeof(pair<int,int>) * teCnt);\n                        memcpy(P, nP, sizeof(int) * N);\n                        memcpy(assign, nassign, sizeof(int) * K);\n                        improved = true;\n                        break;\n                    }\n                }\n                inV[v] = 0;\n            }\n            if (improved) continue;\n        }\n\n        break;\n    }\n}\n\n// ---------- Random connected starting state ----------\nvoid randomState(char inV[100], mt19937& rng) {\n    for (int i = 0; i < N; ++i) inV[i] = 1;\n    uniform_int_distribution<int> dist_step(1, N / 2);\n    int steps = dist_step(rng);\n    for (int s = 0; s < steps; ++s) {\n        pair<int,int> te[100]; int teCnt;\n        if (mst(inV, te, teCnt) >= INF) break;\n        int deg[100] = {0};\n        for (int i = 0; i < teCnt; ++i) {\n            ++deg[te[i].first];\n            ++deg[te[i].second];\n        }\n        int leaves[100], leafCnt = 0;\n        for (int i = 1; i < N; ++i)\n            if (inV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n        if (leafCnt == 0) break;\n        uniform_int_distribution<int> d(0, leafCnt - 1);\n        inV[leaves[d(rng)]] = 0;\n    }\n}\n\n// ---------- Random neighbor ----------\nvoid randomNeighbor(const char curV[100], const pair<int,int> curTe[100], int curTeCnt,\n                    char nxtV[100], mt19937& rng) {\n    memcpy(nxtV, curV, 100);\n\n    int deg[100] = {0};\n    for (int i = 0; i < curTeCnt; ++i) {\n        ++deg[curTe[i].first];\n        ++deg[curTe[i].second];\n    }\n    int leaves[100], leafCnt = 0;\n    for (int i = 1; i < N; ++i)\n        if (curV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n\n    bool seen[100] = {false};\n    int cand[100], candCnt = 0;\n    for (int i = 0; i < N; ++i) if (curV[i]) {\n        for (auto& [to, id] : adj[i]) {\n            if (!curV[to] && !seen[to]) {\n                seen[to] = true;\n                cand[candCnt++] = to;\n            }\n        }\n    }\n\n    int typ;\n    if (leafCnt == 0 && candCnt == 0) return;\n    if (leafCnt == 0) typ = 1;\n    else if (candCnt == 0) typ = 0;\n    else typ = (int)(rng() % 3);\n\n    if (typ == 0) {\n        uniform_int_distribution<int> d(0, leafCnt - 1);\n        nxtV[leaves[d(rng)]] = 0;\n    } else if (typ == 1) {\n        uniform_int_distribution<int> d(0, candCnt - 1);\n        nxtV[cand[d(rng)]] = 1;\n    } else {\n        // swap: remove leaf, add neighbor of remaining set\n        uniform_int_distribution<int> d1(0, leafCnt - 1);\n        int u = leaves[d1(rng)];\n        nxtV[u] = 0;\n        bool seen2[100] = {false};\n        int cand2[100], cand2Cnt = 0;\n        for (int i = 0; i < N; ++i) if (nxtV[i]) {\n            for (auto& [to, id] : adj[i]) {\n                if (!nxtV[to] && !seen2[to]) {\n                    seen2[to] = true;\n                    cand2[cand2Cnt++] = to;\n                }\n            }\n        }\n        if (cand2Cnt > 0) {\n            uniform_int_distribution<int> d2(0, cand2Cnt - 1);\n            nxtV[cand2[d2(rng)]] = 1;\n        } else {\n            nxtV[u] = 1; // revert\n        }\n    }\n}\n\n// ============================================================\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto time_start = chrono::steady_clock::now();\n    const double TL = 1.80;\n\n    cin >> N >> M >> K;\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    memset(edgeIdMat, -1, sizeof(edgeIdMat));\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n        edgeIdMat[u][v] = edgeIdMat[v][u] = j;\n    }\n\n    for (int k = 0; k < K; ++k) {\n        long long a, b;\n        cin >> a >> b;\n        for (int i = 0; i < N; ++i) {\n            long long dx = xs[i] - a;\n            long long dy = ys[i] - b;\n            long long sq = dx*dx + dy*dy;\n            int d = (int)ceil(sqrt((double)sq));\n            while (1LL*d*d < sq) ++d;\n            while (d > 0 && 1LL*(d-1)*(d-1) >= sq) --d;\n            need[k][i] = d;\n        }\n    }\n\n    memcpy(esort, edges, sizeof(Edge) * M);\n    sort(esort, esort + M, [](const Edge& a, const Edge& b){ return a.w < b.w; });\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // Global best\n    char best_inV[100];\n    pair<int,int> best_te[100];\n    int best_teCnt = 0;\n    int best_P[100];\n    int best_assign[5000];\n    long long best_cost = INF;\n\n    // Temporary assign buffer\n    int tmp_assign[5000];\n\n    auto accept_if_better = [&](char inV[100], pair<int,int> te[100], int teCnt,\n                                int P[100], int assign[5000], long long cost) {\n        if (cost < best_cost) {\n            best_cost = cost;\n            memcpy(best_inV, inV, 100);\n            best_teCnt = teCnt;\n            memcpy(best_te, te, sizeof(pair<int,int>) * teCnt);\n            memcpy(best_P, P, sizeof(int) * N);\n            memcpy(best_assign, assign, sizeof(int) * K);\n        }\n    };\n\n    // 1) Start from all vertices\n    char curV[100];\n    for (int i = 0; i < N; ++i) curV[i] = 1;\n    pair<int,int> curTe[100]; int curTeCnt;\n    int curP[100];\n    long long ec = mst(curV, curTe, curTeCnt);\n    long long pc = calc_power_fast(curV, curP, tmp_assign);\n    if (ec < INF && pc < INF) {\n        long long curCost = ec + pc;\n        descent(curV, curCost, curTe, curTeCnt, curP, tmp_assign, rng);\n        accept_if_better(curV, curTe, curTeCnt, curP, tmp_assign, curCost);\n    }\n\n    // 2) Calibrate initial temperature\n    double T;\n    {\n        long long sumPos = 0;\n        int cntPos = 0;\n        for (int trial = 0; trial < 60; ++trial) {\n            char nxtV[100];\n            randomNeighbor(best_inV, best_te, best_teCnt, nxtV, rng);\n            long long nec = mst(nxtV, curTe, curTeCnt);\n            if (nec >= INF) continue;\n            long long npc = calc_power_fast(nxtV, curP, tmp_assign);\n            if (npc >= INF) continue;\n            long long ncost = nec + npc;\n            if (ncost > best_cost) {\n                sumPos += ncost - best_cost;\n                ++cntPos;\n            }\n        }\n        if (cntPos > 0) T = (double)sumPos / cntPos;\n        else T = best_cost * 0.02;\n        if (T < 1.0) T = 1.0;\n    }\n\n    const double alpha = 0.9995;\n    int iter = 0;\n    int lastImproveIter = 0;\n\n    // Current SA state starts from best\n    memcpy(curV, best_inV, 100);\n    memcpy(curTe, best_te, sizeof(pair<int,int>) * best_teCnt);\n    curTeCnt = best_teCnt;\n    memcpy(curP, best_P, sizeof(int) * N);\n    long long curCost = best_cost;\n    int cur_assign[5000];\n    memcpy(cur_assign, best_assign, sizeof(int) * K);\n\n    // 3) Simulated Annealing + reheats\n    while (true) {\n        if (++iter % 128 == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n            if (elapsed > TL) break;\n        }\n\n        char nxtV[100];\n        randomNeighbor(curV, curTe, curTeCnt, nxtV, rng);\n\n        pair<int,int> nxtTe[100]; int nxtTeCnt;\n        int nxtP[100];\n        long long nec = mst(nxtV, nxtTe, nxtTeCnt);\n        if (nec >= INF) continue;\n        long long npc = calc_power_fast(nxtV, nxtP, tmp_assign);\n        if (npc >= INF) continue;\n        long long nxtCost = nec + npc;\n\n        long long delta = nxtCost - curCost;\n        if (delta < 0 || uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) {\n            memcpy(curV, nxtV, 100);\n            memcpy(curTe, nxtTe, sizeof(pair<int,int>) * nxtTeCnt);\n            curTeCnt = nxtTeCnt;\n            memcpy(curP, nxtP, sizeof(int) * N);\n            memcpy(cur_assign, tmp_assign, sizeof(int) * K);\n            curCost = nxtCost;\n\n            if (curCost < best_cost) {\n                best_cost = curCost;\n                memcpy(best_inV, curV, 100);\n                memcpy(best_te, curTe, sizeof(pair<int,int>) * curTeCnt);\n                best_teCnt = curTeCnt;\n                memcpy(best_P, curP, sizeof(int) * N);\n                memcpy(best_assign, cur_assign, sizeof(int) * K);\n                lastImproveIter = iter;\n            }\n        }\n\n        T *= alpha;\n\n        // Reheat if stuck\n        if (iter - lastImproveIter > 4000) {\n            randomState(curV, rng);\n            long long ec2 = mst(curV, curTe, curTeCnt);\n            if (ec2 < INF) {\n                long long pc2 = calc_power_fast(curV, curP, tmp_assign);\n                if (pc2 < INF) {\n                    curCost = ec2 + pc2;\n                    memcpy(cur_assign, tmp_assign, sizeof(int) * K);\n                    if (curCost < best_cost) {\n                        best_cost = curCost;\n                        memcpy(best_inV, curV, 100);\n                        memcpy(best_te, curTe, sizeof(pair<int,int>) * curTeCnt);\n                        best_teCnt = curTeCnt;\n                        memcpy(best_P, curP, sizeof(int) * N);\n                        memcpy(best_assign, cur_assign, sizeof(int) * K);\n                    }\n                }\n            }\n            T = max(1.0, (double)best_cost * 0.02);\n            lastImproveIter = iter;\n        }\n    }\n\n    // 4) Final descent + refinement\n    {\n        char finV[100];\n        memcpy(finV, best_inV, 100);\n        pair<int,int> finTe[100];\n        memcpy(finTe, best_te, sizeof(pair<int,int>) * best_teCnt);\n        int finTeCnt = best_teCnt;\n        int finP[100];\n        memcpy(finP, best_P, sizeof(int) * N);\n        int fin_assign[5000];\n        memcpy(fin_assign, best_assign, sizeof(int) * K);\n        long long finCost = best_cost;\n\n        descent(finV, finCost, finTe, finTeCnt, finP, fin_assign, rng);\n\n        // re-evaluate with refinement\n        long long rpc = refine_assignment(finV, finP, fin_assign);\n        if (rpc < INF) {\n            long long rec = mst(finV, finTe, finTeCnt);\n            if (rec < INF) {\n                long long rcost = rec + rpc;\n                if (rcost < best_cost) {\n                    best_cost = rcost;\n                    memcpy(best_inV, finV, 100);\n                    memcpy(best_te, finTe, sizeof(pair<int,int>) * finTeCnt);\n                    best_teCnt = finTeCnt;\n                    memcpy(best_P, finP, sizeof(int) * N);\n                    memcpy(best_assign, fin_assign, sizeof(int) * K);\n                }\n            }\n        }\n    }\n\n    // ---------- Output ----------\n    int Pout[100] = {0};\n    for (int i = 0; i < N; ++i)\n        if (best_inV[i]) Pout[i] = best_P[i];\n\n    int Bout[300] = {0};\n    for (int i = 0; i < best_teCnt; ++i) {\n        int u = best_te[i].first;\n        int v = best_te[i].second;\n        Bout[edgeIdMat[u][v]] = 1;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << Pout[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << Bout[j];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static constexpr int N = 30;\n    static constexpr int TOTAL = N * (N + 1) / 2;   // 465\n\n    using State = array<int, TOTAL>;\n\n    State init_state{};\n    mt19937 rng;\n\n    // geometry\n    int ch1[TOTAL];\n    int ch2[TOTAL];\n    int X[TOTAL];\n    int Y[TOTAL];\n\n    Solver() : rng(123456789) {\n        for (int x = 0; x < N; ++x) {\n            int base = x * (x + 1) / 2;\n            for (int y = 0; y <= x; ++y) {\n                int id = base + y;\n                X[id] = x;\n                Y[id] = y;\n                if (x + 1 < N) {\n                    int base2 = (x + 1) * (x + 2) / 2;\n                    ch1[id] = base2 + y;       // (x+1, y)\n                    ch2[id] = base2 + y + 1;   // (x+1, y+1)\n                } else {\n                    ch1[id] = -1;\n                    ch2[id] = -1;\n                }\n            }\n        }\n    }\n\n    // process one layer, abort if swaps > limit\n    int process_layer_limit(int x, const vector<int> &ord, int *val, int limit) const {\n        int swaps = 0;\n        int base = x * (x + 1) / 2;\n        for (int y : ord) {\n            int cur = base + y;\n            while (true) {\n                int c1 = ch1[cur];\n                if (c1 == -1) break;               // leaf\n                int c2 = ch2[cur];\n                int vc = val[cur];\n                int v1 = val[c1];\n                int v2 = val[c2];\n                if (vc <= v1 && vc <= v2) break;   // heap ok\n                int nxt = (v1 < v2) ? c1 : c2;\n                int tmp = val[cur];\n                val[cur] = val[nxt];\n                val[nxt] = tmp;\n                cur = nxt;\n                if (++swaps > limit) return limit + 1;\n            }\n        }\n        return swaps;\n    }\n\n    // full build-heap from scratch\n    int eval_full(const vector<vector<int>> &order) const {\n        State val = init_state;\n        int swaps = 0;\n        for (int x = N - 2; x >= 0; --x) {\n            swaps += process_layer_limit(x, order[x], val.data(), INT_MAX);\n        }\n        return swaps;\n    }\n\n    // evaluate a candidate order for layer x, assuming layers > x are fixed\n    // (pref[x+1] holds the state after them).  limit = best known - 1.\n    int eval_from(int x, const vector<int> &cand,\n                  const vector<vector<int>> &order,\n                  const vector<State> &pref, int limit) const {\n        if (limit < 0) return 1;\n        State val = pref[x + 1];\n        int swaps = process_layer_limit(x, cand, val.data(), limit);\n        if (swaps > limit) return limit + 1;\n        for (int xx = x - 1; xx >= 0; --xx) {\n            swaps += process_layer_limit(xx, order[xx], val.data(), limit - swaps);\n            if (swaps > limit) return limit + 1;\n        }\n        return swaps;\n    }\n\n    // recompute pref[0..N-1] from scratch\n    void recompute_pref(const vector<vector<int>> &order, vector<State> &pref) const {\n        pref[N - 1] = init_state;\n        for (int x = N - 2; x >= 0; --x) {\n            pref[x] = pref[x + 1];\n            process_layer_limit(x, order[x], pref[x].data(), INT_MAX);\n        }\n    }\n\n    // update pref after layer x changed (and possibly layers above improved)\n    void apply_change(int x, const vector<vector<int>> &order,\n                      vector<State> &pref) const {\n        pref[x] = pref[x + 1];\n        process_layer_limit(x, order[x], pref[x].data(), INT_MAX);\n        for (int xx = x - 1; xx >= 0; --xx) {\n            pref[xx] = pref[xx + 1];\n            process_layer_limit(xx, order[xx], pref[xx].data(), INT_MAX);\n        }\n    }\n\n    // record the actual swap sequence\n    vector<tuple<int, int, int, int>> record(const vector<vector<int>> &order) const {\n        State val = init_state;\n        vector<tuple<int, int, int, int>> ops;\n        ops.reserve(5000);\n        for (int x = N - 2; x >= 0; --x) {\n            int base = x * (x + 1) / 2;\n            for (int y : order[x]) {\n                int cur = base + y;\n                while (true) {\n                    int c1 = ch1[cur];\n                    if (c1 == -1) break;\n                    int c2 = ch2[cur];\n                    int vc = val[cur];\n                    int v1 = val[c1];\n                    int v2 = val[c2];\n                    if (vc <= v1 && vc <= v2) break;\n                    int nxt = (v1 < v2) ? c1 : c2;\n                    ops.emplace_back(X[cur], Y[cur], X[nxt], Y[nxt]);\n                    int tmp = val[cur];\n                    val[cur] = val[nxt];\n                    val[nxt] = tmp;\n                    cur = nxt;\n                }\n            }\n        }\n        return ops;\n    }\n\n    vector<tuple<int, int, int, int>> solve() {\n        // ---------- deterministic starting orders ----------\n        vector<vector<int>> best(N - 1);\n        for (int x = 0; x < N - 1; ++x) {\n            best[x].resize(x + 1);\n            iota(best[x].begin(), best[x].end(), 0);\n        }\n        int best_swaps = eval_full(best);\n\n        auto consider = [&](const vector<vector<int>> &ord) {\n            int s = eval_full(ord);\n            if (s < best_swaps) {\n                best_swaps = s;\n                best = ord;\n            }\n        };\n\n        // right-to-left\n        {\n            vector<vector<int>> ord(N - 1);\n            for (int x = 0; x < N - 1; ++x) {\n                ord[x].resize(x + 1);\n                iota(ord[x].begin(), ord[x].end(), 0);\n                reverse(ord[x].begin(), ord[x].end());\n            }\n            consider(ord);\n        }\n        // descending by value\n        {\n            vector<vector<int>> ord(N - 1);\n            for (int x = 0; x < N - 1; ++x) {\n                ord[x].resize(x + 1);\n                iota(ord[x].begin(), ord[x].end(), 0);\n                sort(ord[x].begin(), ord[x].end(),\n                     [&](int a, int b) {\n                         return init_state[x * (x + 1) / 2 + a] >\n                                init_state[x * (x + 1) / 2 + b];\n                     });\n            }\n            consider(ord);\n        }\n        // ascending by value\n        {\n            vector<vector<int>> ord(N - 1);\n            for (int x = 0; x < N - 1; ++x) {\n                ord[x].resize(x + 1);\n                iota(ord[x].begin(), ord[x].end(), 0);\n                sort(ord[x].begin(), ord[x].end(),\n                     [&](int a, int b) {\n                         return init_state[x * (x + 1) / 2 + a] <\n                                init_state[x * (x + 1) / 2 + b];\n                     });\n            }\n            consider(ord);\n        }\n        // descending by excess (val - min_child)\n        {\n            vector<vector<int>> ord(N - 1);\n            for (int x = 0; x < N - 1; ++x) {\n                ord[x].resize(x + 1);\n                iota(ord[x].begin(), ord[x].end(), 0);\n                sort(ord[x].begin(), ord[x].end(),\n                     [&](int a, int b) {\n                         int ida = x * (x + 1) / 2 + a;\n                         int idb = x * (x + 1) / 2 + b;\n                         int mina = min(init_state[ch1[ida]], init_state[ch2[ida]]);\n                         int minb = min(init_state[ch1[idb]], init_state[ch2[idb]]);\n                         int exa = init_state[ida] - mina;\n                         int exb = init_state[idb] - minb;\n                         if (exa != exb) return exa > exb;\n                         return init_state[ida] > init_state[idb];\n                     });\n            }\n            consider(ord);\n        }\n        // violations first, then excess descending\n        {\n            vector<vector<int>> ord(N - 1);\n            for (int x = 0; x < N - 1; ++x) {\n                ord[x].resize(x + 1);\n                iota(ord[x].begin(), ord[x].end(), 0);\n                sort(ord[x].begin(), ord[x].end(),\n                     [&](int a, int b) {\n                         int ida = x * (x + 1) / 2 + a;\n                         int idb = x * (x + 1) / 2 + b;\n                         int mina = min(init_state[ch1[ida]], init_state[ch2[ida]]);\n                         int minb = min(init_state[ch1[idb]], init_state[ch2[idb]]);\n                         bool va = init_state[ida] > mina;\n                         bool vb = init_state[idb] > minb;\n                         if (va != vb) return va > vb;\n                         int exa = init_state[ida] - mina;\n                         int exb = init_state[idb] - minb;\n                         if (exa != exb) return exa > exb;\n                         return init_state[ida] > init_state[idb];\n                     });\n            }\n            consider(ord);\n        }\n\n        // ---------- local search ----------\n        vector<vector<int>> cur = best;\n        int cur_swaps = best_swaps;\n        vector<State> pref(N);\n        recompute_pref(cur, pref);\n\n        // pairwise-swap hill climbing (steepest descent per layer)\n        for (int rep = 0; rep < 3; ++rep) {\n            for (int x = N - 2; x >= 0; --x) {\n                auto best_o = cur[x];\n                int best_s = cur_swaps;\n                for (int i = 0; i <= x; ++i) {\n                    for (int j = i + 1; j <= x; ++j) {\n                        swap(cur[x][i], cur[x][j]);\n                        int s = eval_from(x, cur[x], cur, pref, best_s - 1);\n                        if (s < best_s) {\n                            best_s = s;\n                            best_o = cur[x];\n                        }\n                        swap(cur[x][i], cur[x][j]);\n                    }\n                }\n                if (best_s < cur_swaps) {\n                    cur_swaps = best_s;\n                    cur[x] = best_o;\n                    apply_change(x, cur, pref);\n                    if (cur_swaps < best_swaps) {\n                        best_swaps = cur_swaps;\n                        best = cur;\n                    }\n                }\n            }\n        }\n\n        // random-shuffle exploration\n        for (int pass = 0; pass < 10; ++pass) {\n            for (int x = N - 2; x >= 0; --x) {\n                auto best_o = cur[x];\n                int best_s = cur_swaps;\n                for (int t = 0; t < 1000; ++t) {\n                    auto tmp = cur[x];\n                    shuffle(tmp.begin(), tmp.end(), rng);\n                    int s = eval_from(x, tmp, cur, pref, best_s - 1);\n                    if (s < best_s) {\n                        best_s = s;\n                        best_o = tmp;\n                    }\n                }\n                if (best_s < cur_swaps) {\n                    cur_swaps = best_s;\n                    cur[x] = best_o;\n                    apply_change(x, cur, pref);\n                    if (cur_swaps < best_swaps) {\n                        best_swaps = cur_swaps;\n                        best = cur;\n                    }\n                }\n            }\n        }\n\n        // final pairwise pass\n        for (int x = N - 2; x >= 0; --x) {\n            auto best_o = cur[x];\n            int best_s = cur_swaps;\n            for (int i = 0; i <= x; ++i) {\n                for (int j = i + 1; j <= x; ++j) {\n                    swap(cur[x][i], cur[x][j]);\n                    int s = eval_from(x, cur[x], cur, pref, best_s - 1);\n                    if (s < best_s) {\n                        best_s = s;\n                        best_o = cur[x];\n                    }\n                    swap(cur[x][i], cur[x][j]);\n                }\n            }\n            if (best_s < cur_swaps) {\n                cur_swaps = best_s;\n                cur[x] = best_o;\n                apply_change(x, cur, pref);\n                if (cur_swaps < best_swaps) {\n                    best_swaps = cur_swaps;\n                    best = cur;\n                }\n            }\n        }\n\n        return record(best);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 30;\n    constexpr int TOTAL = N * (N + 1) / 2;\n\n    Solver solver;\n    for (int x = 0; x < N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            if (!(cin >> v)) return 0;\n            solver.init_state[x * (x + 1) / 2 + y] = v;\n        }\n    }\n\n    auto ops = solver.solve();\n    cout << ops.size() << '\\n';\n    for (auto &[x1, y1, x2, y2] : ops) {\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*----- global data -----*/\nint D, N, M;\nint si, sj;\nchar obs[9][9];\nchar dist_arr[9][9];\nvector<pair<int,int>> cells;\nint cid[9][9];\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\n\n/*----- articulation-point DFS globals -----*/\nint disc_g[9][9];\nint low_g[9][9];\nchar vis_g[9][9];\nchar ap_g[9][9];\nint timer_g;\n\n/*----- helpers -----*/\nbool is_free(int i, int j, const char filled[9][9]) {\n    if (i == si && j == sj) return true;\n    if (i < 0 || i >= D || j < 0 || j >= D) return false;\n    if (obs[i][j]) return false;\n    return !filled[i][j];\n}\n\nvoid dfs_ap(int i, int j, int pi, int pj, const char filled[9][9]) {\n    vis_g[i][j] = 1;\n    disc_g[i][j] = low_g[i][j] = ++timer_g;\n    int child_cnt = 0;\n    for (int dir = 0; dir < 4; ++dir) {\n        int ni = i + di[dir], nj = j + dj[dir];\n        if (!is_free(ni, nj, filled)) continue;\n        if (ni == pi && nj == pj) continue;\n        if (!vis_g[ni][nj]) {\n            ++child_cnt;\n            dfs_ap(ni, nj, i, j, filled);\n            low_g[i][j] = min(low_g[i][j], low_g[ni][nj]);\n            if (pi != -1 && low_g[ni][nj] >= disc_g[i][j]) ap_g[i][j] = 1;\n        } else {\n            low_g[i][j] = min(low_g[i][j], disc_g[ni][nj]);\n        }\n    }\n    if (pi == -1 && child_cnt > 1) ap_g[i][j] = 1;\n}\n\nvector<int> find_safe(const char filled[9][9]) {\n    memset(vis_g, 0, sizeof(vis_g));\n    memset(ap_g, 0, sizeof(ap_g));\n    timer_g = 0;\n    dfs_ap(si, sj, -1, -1, filled);\n    vector<int> safe;\n    safe.reserve(M);\n    for (int k = 0; k < M; ++k) {\n        int i = cells[k].first, j = cells[k].second;\n        if (filled[i][j]) continue;\n        if (vis_g[i][j] && !ap_g[i][j]) safe.push_back(k);\n    }\n    if (safe.empty()) {               // theoretical safety net\n        for (int k = 0; k < M; ++k) {\n            int i = cells[k].first, j = cells[k].second;\n            if (filled[i][j]) continue;\n            if (vis_g[i][j]) safe.push_back(k);\n        }\n    }\n    return safe;\n}\n\nint degree_of(int id, const char filled[9][9]) {\n    int i = cells[id].first, j = cells[id].second;\n    int deg = 0;\n    for (int dir = 0; dir < 4; ++dir) {\n        int ni = i + di[dir], nj = j + dj[dir];\n        if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n        if (obs[ni][nj]) continue;\n        if (ni == si && nj == sj) ++deg;\n        else if (!filled[ni][nj]) ++deg;\n    }\n    return deg;\n}\n\n/*----- generate one candidate elimination order -----*/\nvector<int> generate_order(int policy, mt19937& rng) {\n    char f[9][9] = {};\n    vector<int> elim;\n    elim.reserve(M);\n    for (int step = 0; step < M; ++step) {\n        auto safe = find_safe(f);\n        int best_id = -1;\n        int best_score = INT_MIN;\n        for (int id : safe) {\n            int i = cells[id].first, j = cells[id].second;\n            int d = dist_arr[i][j];\n            int deg = degree_of(id, f);\n            int score;\n            if (policy == 0) score = d * 1000 - deg;\n            else if (policy == 1) score = d * 1000 + deg;\n            else if (policy == 2) score = -deg * 1000 + d;\n            else if (policy == 3) score = -deg * 1000 - d;\n            else if (policy == 4) score = uniform_int_distribution<int>(0, 1000000)(rng);\n            else if (policy == 5) score = d * 1000 + uniform_int_distribution<int>(0, 999)(rng);\n            else if (policy == 6) score = -deg * 1000 + uniform_int_distribution<int>(0, 999)(rng);\n            else score = d * 1000 - deg * 10 + uniform_int_distribution<int>(0, 99)(rng);\n            if (score > best_score) {\n                best_score = score;\n                best_id = id;\n            }\n        }\n        auto [bi, bj] = cells[best_id];\n        f[bi][bj] = 1;\n        elim.push_back(best_id);\n    }\n    vector<int> ideal(M);\n    for (int i = 0; i < M; ++i) ideal[elim[i]] = M - 1 - i;\n    return ideal;\n}\n\n/*----- fast evaluation of one candidate on one label sequence -----*/\nlong long evaluate(const vector<int>& ideal, const vector<int>& seq) {\n    char f[9][9] = {};\n    int lab[9][9];\n    memset(lab, -1, sizeof(lab));\n    char seen[81] = {};\n\n    for (int step = 0; step < M; ++step) {\n        int t = seq[step];\n        seen[t] = 1;\n        auto safe = find_safe(f);\n        int best_id = -1, best_cat = -1, best_sub = INT_MAX, best_deg = 100;\n        for (int id : safe) {\n            int ide = ideal[id];\n            int cat, sub;\n            if (ide == t) { cat = 3; sub = 0; }\n            else if (ide > t) { cat = 2; sub = ide - t; }\n            else if (seen[ide]) { cat = 1; sub = t - ide; }\n            else { cat = 0; sub = t - ide; }\n            int deg = degree_of(id, f);\n            if (cat > best_cat ||\n                (cat == best_cat && sub < best_sub) ||\n                (cat == best_cat && sub == best_sub && deg < best_deg)) {\n                best_cat = cat; best_sub = sub; best_deg = deg; best_id = id;\n            }\n        }\n        auto [bi, bj] = cells[best_id];\n        f[bi][bj] = 1;\n        lab[bi][bj] = t;\n    }\n\n    // greedy removal\n    char emp[9][9] = {};\n    emp[si][sj] = 1;\n    using T = tuple<int,int,int>;\n    priority_queue<T, vector<T>, greater<T>> pq;\n    char in_pq[9][9] = {};\n    auto add_nei = [&](int i, int j) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obs[ni][nj]) continue;\n            if (emp[ni][nj]) continue;\n            if (in_pq[ni][nj]) continue;\n            pq.emplace(lab[ni][nj], ni, nj);\n            in_pq[ni][nj] = 1;\n        }\n    };\n    add_nei(si, sj);\n    int rem[81], rcnt = 0;\n    while (!pq.empty()) {\n        auto [v, i, j] = pq.top(); pq.pop();\n        rem[rcnt++] = v;\n        emp[i][j] = 1;\n        add_nei(i, j);\n    }\n\n    // O(M^2) inversion count (M \u2264 80)\n    long long inv = 0;\n    for (int i = 0; i < rcnt; ++i)\n        for (int j = i + 1; j < rcnt; ++j)\n            if (rem[i] > rem[j]) ++inv;\n    return inv;\n}\n\n/*============================================================*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> D >> N;\n    si = 0; sj = (D - 1) / 2;\n    memset(obs, 0, sizeof(obs));\n    for (int k = 0; k < N; ++k) {\n        int r, c; cin >> r >> c;\n        obs[r][c] = 1;\n    }\n\n    /* BFS distances */\n    memset(dist_arr, -1, sizeof(dist_arr));\n    queue<pair<int,int>> q;\n    dist_arr[si][sj] = 0;\n    q.push({si, sj});\n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obs[ni][nj]) continue;\n            if (dist_arr[ni][nj] != -1) continue;\n            dist_arr[ni][nj] = dist_arr[i][j] + 1;\n            q.push({ni, nj});\n        }\n    }\n\n    /* collect cells */\n    memset(cid, -1, sizeof(cid));\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            if (!(i == si && j == sj) && !obs[i][j]) {\n                cid[i][j] = (int)cells.size();\n                cells.emplace_back(i, j);\n            }\n    M = (int)cells.size();\n\n    /*----- offline search for a good ideal assignment -----*/\n    mt19937 rng(123456789);\n    vector<int> seq(M);\n    iota(seq.begin(), seq.end(), 0);\n\n    vector<vector<int>> candidates;\n    for (int pol = 0; pol < 8; ++pol) candidates.push_back(generate_order(pol, rng));\n    for (int rep = 0; rep < 4; ++rep) candidates.push_back(generate_order(4, rng));\n\n    const int NUM_SEQ = 3;\n    vector<long long> scores(candidates.size(), 0);\n    for (size_t idx = 0; idx < candidates.size(); ++idx) {\n        for (int s = 0; s < NUM_SEQ; ++s) {\n            shuffle(seq.begin(), seq.end(), rng);\n            scores[idx] += evaluate(candidates[idx], seq);\n        }\n    }\n    int best_idx = (int)(min_element(scores.begin(), scores.end()) - scores.begin());\n    vector<int> ideal = candidates[best_idx];\n    /*------------------------------------------------------*/\n\n    /*----- online placement -----*/\n    char filled[9][9] = {};\n    int lab[9][9];\n    memset(lab, -1, sizeof(lab));\n    char seen[81] = {};\n\n    for (int step = 0; step < M; ++step) {\n        int t; cin >> t;\n        seen[t] = 1;\n        auto safe = find_safe(filled);\n        int best_id = -1, best_cat = -1, best_sub = INT_MAX, best_deg = 100;\n        for (int id : safe) {\n            int ide = ideal[id];\n            int cat, sub;\n            if (ide == t) { cat = 3; sub = 0; }\n            else if (ide > t) { cat = 2; sub = ide - t; }\n            else if (seen[ide]) { cat = 1; sub = t - ide; }\n            else { cat = 0; sub = t - ide; }\n            int deg = degree_of(id, filled);\n            if (cat > best_cat ||\n                (cat == best_cat && sub < best_sub) ||\n                (cat == best_cat && sub == best_sub && deg < best_deg)) {\n                best_cat = cat; best_sub = sub; best_deg = deg; best_id = id;\n            }\n        }\n        auto [bi, bj] = cells[best_id];\n        filled[bi][bj] = 1;\n        lab[bi][bj] = t;\n        cout << bi << ' ' << bj << '\\n' << flush;\n    }\n\n    /*----- output greedy removal order -----*/\n    char emp[9][9] = {};\n    emp[si][sj] = 1;\n    using T = tuple<int,int,int>;\n    priority_queue<T, vector<T>, greater<T>> pq;\n    char in_pq[9][9] = {};\n    auto add_nei = [&](int i, int j) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obs[ni][nj]) continue;\n            if (emp[ni][nj]) continue;\n            if (in_pq[ni][nj]) continue;\n            pq.emplace(lab[ni][nj], ni, nj);\n            in_pq[ni][nj] = 1;\n        }\n    };\n    add_nei(si, sj);\n    while (!pq.empty()) {\n        auto [v, i, j] = pq.top(); pq.pop();\n        cout << i << ' ' << j << '\\n';\n        emp[i][j] = 1;\n        add_nei(i, j);\n    }\n    cout << flush;\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nint n, m;\nint orig_g[50][50];\nint need[101][101];\nbool isB[101];\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\ninline bool inside(int i, int j) { return i >= 0 && i < n && j >= 0 && j < n; }\n\nstruct State {\n    int g[50][50];\n    int sz[101];\n    int adjCnt[101][101];\n    int vis[50][50];\n    int visToken;\n    mt19937 rng;\n\n    State(unsigned seed) : visToken(1), rng(seed) {\n        memset(vis, 0, sizeof(vis));\n    }\n\n    void recompute() {\n        memset(sz, 0, sizeof(sz));\n        memset(adjCnt, 0, sizeof(adjCnt));\n        for (int i = 0; i < n; ++i) {\n            for (int j = 0; j < n; ++j) {\n                int c = g[i][j];\n                ++sz[c];\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    if (inside(ni, nj)) {\n                        int d = g[ni][nj];\n                        if (c != d) ++adjCnt[c][d];\n                    } else {\n                        ++adjCnt[c][0];\n                    }\n                }\n            }\n        }\n    }\n\n    void init() {\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                g[i][j] = orig_g[i][j];\n        recompute();\n    }\n\n    void load(const vector<vector<int>> &gr) {\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                g[i][j] = gr[i][j];\n        recompute();\n    }\n\n    vector<vector<int>> get_grid() const {\n        vector<vector<int>> res(n, vector<int>(n));\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                res[i][j] = g[i][j];\n        return res;\n    }\n\n    // Quick connectivity test for color c after removing cell (i,j).\n    // same_c = number of 4-neighbors of (i,j) that already have color c.\n    bool connectedWithout(int i, int j, int c, int szc, int same_c) {\n        if (szc <= 1) return false;\n        if (szc == 2) return true;          // one other cell remains\n        if (same_c == 0) return false;      // should never happen for a valid state\n        if (same_c == 1) return true;       // leaf: removing it cannot disconnect the rest\n\n        int si = -1, sj = -1;\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (inside(ni, nj) && g[ni][nj] == c) {\n                si = ni; sj = nj; break;\n            }\n        }\n        if (si == -1) return false;\n\n        int cnt = 1;\n        queue<pair<int, int>> q;\n        q.emplace(si, sj);\n        vis[si][sj] = visToken;\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + di[dir], ny = y + dj[dir];\n                if (!inside(nx, ny)) continue;\n                if (g[nx][ny] != c) continue;\n                if (nx == i && ny == j) continue;\n                if (vis[nx][ny] == visToken) continue;\n                vis[nx][ny] = visToken;\n                ++cnt;\n                if (cnt == szc - 1) {       // early stop\n                    ++visToken;\n                    return true;\n                }\n                q.emplace(nx, ny);\n            }\n        }\n        ++visToken;\n        return cnt == szc - 1;\n    }\n\n    void applyRecolor(int i, int j, int d) {\n        int c = g[i][j];\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            int e = inside(ni, nj) ? g[ni][nj] : 0;\n            if (e != c) {\n                --adjCnt[c][e];\n                --adjCnt[e][c];\n            }\n            if (e != d) {\n                ++adjCnt[d][e];\n                ++adjCnt[e][d];\n            }\n        }\n        g[i][j] = d;\n        --sz[c];\n        ++sz[d];\n    }\n\n    int solve(int heuristic) {\n        for (int iter = 0; iter < 500; ++iter) {\n            bool changed = false;\n\n            // Build list of non-zero cells\n            vector<pair<int, int>> cells;\n            cells.reserve(2500);\n            for (int i = 0; i < n; ++i)\n                for (int j = 0; j < n; ++j)\n                    if (g[i][j] > 0) cells.emplace_back(i, j);\n\n            // Order cells according to heuristic\n            if (heuristic & 1) {\n                // Bucket by number of 0-neighbors (including outside), higher first\n                vector<pair<int, int>> bucket[5];\n                for (auto [i, j] : cells) {\n                    int key = 0;\n                    for (int dir = 0; dir < 4; ++dir) {\n                        int ni = i + di[dir], nj = j + dj[dir];\n                        if (!inside(ni, nj) || g[ni][nj] == 0) ++key;\n                    }\n                    bucket[key].push_back({i, j});\n                }\n                cells.clear();\n                for (int k = 4; k >= 0; --k) {\n                    shuffle(bucket[k].begin(), bucket[k].end(), rng);\n                    cells.insert(cells.end(), bucket[k].begin(), bucket[k].end());\n                }\n            } else {\n                shuffle(cells.begin(), cells.end(), rng);\n            }\n\n            for (auto [i, j] : cells) {\n                int c = g[i][j];\n                if (c == 0) continue;\n                if (sz[c] <= 1) continue;\n\n                int neigh[4];\n                int same_c = 0;\n                int contrib_c[101] = {};\n                bool hasZero = false;\n                bool isBorder = (i == 0 || i == n - 1 || j == 0 || j == n - 1);\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    int e = inside(ni, nj) ? g[ni][nj] : 0;\n                    neigh[dir] = e;\n                    if (e == c) ++same_c;\n                    else ++contrib_c[e];\n                    if (e == 0) hasZero = true;\n                }\n\n                if (!connectedWithout(i, j, c, sz[c], same_c)) continue;\n\n                // ----- try delete -----\n                if (isB[c] && (isBorder || hasZero)) {\n                    bool ok = true;\n                    for (int e = 1; e <= m; ++e)\n                        if (contrib_c[e] && !isB[e]) { ok = false; break; }\n                    if (ok) {\n                        for (int e = 0; e <= m; ++e) {\n                            if (contrib_c[e] == 0) continue;\n                            if (!need[c][e]) continue;\n                            int rem = adjCnt[c][e] - contrib_c[e];\n                            if (e == 0) rem += same_c; // c-neighbors become adjacent to 0\n                            if (rem <= 0) { ok = false; break; }\n                        }\n                    }\n                    if (ok) {\n                        applyRecolor(i, j, 0);\n                        changed = true;\n                        continue;\n                    }\n                }\n\n                // ----- try recolor to a neighbor color -----\n                int bestD = -1;\n                int bestScore = INT_MIN;\n                for (int dir = 0; dir < 4; ++dir) {\n                    int d = neigh[dir];\n                    if (d == 0 || d == c) continue;\n\n                    // Border cells are adjacent to the outside (color 0)\n                    if (isBorder && !need[d][0]) continue;\n\n                    // d must be allowed to touch all current neighbors\n                    bool ok = true;\n                    for (int k = 0; k < 4; ++k) {\n                        int e = neigh[k];\n                        if (e == d) continue;\n                        if (!need[d][e]) { ok = false; break; }\n                    }\n                    if (!ok) continue;\n\n                    // old color c must keep all required adjacencies\n                    ok = true;\n                    for (int e = 0; e <= m; ++e) {\n                        if (contrib_c[e] == 0) continue;\n                        if (!need[c][e]) continue;\n                        int rem = adjCnt[c][e] - contrib_c[e];\n                        if (e == d) rem += same_c; // c-neighbors are now adjacent to d\n                        if (rem <= 0) { ok = false; break; }\n                    }\n                    if (!ok) continue;\n\n                    int score;\n                    switch (heuristic % 6) {\n                        case 0: score = (isB[d] ? 10000 : 0) - sz[d] * 10; break;\n                        case 1: score = (isB[d] ? 10000 : 0) + sz[d] * 10; break;\n                        case 2: score = (isB[d] ? 10000 : 0) + adjCnt[d][0] * 10; break;\n                        case 3: score = -sz[d] * 10; break;\n                        case 4: score = (isB[d] ? 10000 : 0) - sz[d] * 10 + adjCnt[d][0] * 5; break;\n                        default: score = 0; break;\n                    }\n                    score += int(rng() & 0xF); // small random tie-break\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestD = d;\n                    }\n                }\n\n                if (bestD != -1) {\n                    applyRecolor(i, j, bestD);\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n        return sz[0];\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig_g[i][j];\n\n    memset(need, 0, sizeof(need));\n    memset(isB, 0, sizeof(isB));\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = orig_g[i][j];\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (inside(ni, nj)) {\n                    int d = orig_g[ni][nj];\n                    if (c != d) need[c][d] = 1;\n                } else {\n                    need[c][0] = 1;\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) isB[c] = need[c][0];\n    for (int c = 1; c <= m; ++c) need[0][c] = isB[c];\n\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int best_zero = -1;\n    vector<vector<int>> best_grid;\n\n    // One deterministic trial\n    {\n        State s(1234567u);\n        s.init();\n        int z = s.solve(0);\n        if (z > best_zero) {\n            best_zero = z;\n            best_grid = s.get_grid();\n        }\n    }\n\n    // Keep restarting until we run out of time\n    for (int trial = 0; ; ++trial) {\n        if (elapsed() > 1.85) break;\n\n        int h = trial % 6;\n        State s((unsigned)trial + 1000u);\n        s.init();\n        int z = s.solve(h);\n        if (z > best_zero) {\n            best_zero = z;\n            best_grid = s.get_grid();\n        }\n\n        // Occasionally try to improve the current best map\n        if (trial % 3 == 0 && best_zero > 0) {\n            State s2((unsigned)trial + 2000000u);\n            s2.load(best_grid);\n            int z2 = s2.solve((h + 1) % 6);\n            if (z2 > best_zero) {\n                best_zero = z2;\n                best_grid = s2.get_grid();\n            }\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p;\n    DSU(int n = 0) { init(n); }\n    void init(int n) { p.resize(n); iota(p.begin(), p.end(), 0); }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a != b) p[a] = b;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    vector<bitset<128>> gt(N);\n    vector<vector<char>> direct_done(N, vector<char>(N, 0));\n    DSU dsu(N);\n    \n    vector<int> assign(N);\n    for (int i = 0; i < N; ++i) assign[i] = i % D;\n    \n    const double LAMBDA = 1e-5;\n    double M_cap = 100000.0 * N / D;\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0 / i;\n    vector<long long> est(N, 100000);\n    \n    auto recompute_est = [&]() {\n        vector<int> num_gt(N, 0);\n        for (int i = 0; i < N; ++i) num_gt[i] = (int)gt[i].count();\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (num_gt[a] != num_gt[b]) return num_gt[a] > num_gt[b];\n            return a < b;\n        });\n        for (int idx = 0; idx < N; ++idx) {\n            int i = ord[idx];\n            double val = (H[N] - H[idx]) / LAMBDA;\n            if (val > M_cap) val = M_cap;\n            est[i] = max(1LL, (long long)llround(val));\n        }\n    };\n    \n    auto improve_partition = [&](vector<int>& as) {\n        vector<long long> gsum(D, 0);\n        for (int i = 0; i < N; ++i) gsum[as[i]] += est[i];\n        vector<vector<int>> groups(D);\n        for (int i = 0; i < N; ++i) groups[as[i]].push_back(i);\n        \n        bool improved = true;\n        while (improved) {\n            improved = false;\n            long long bestDelta = 0;\n            int best_type = 0;\n            int best_i = -1, best_j = -1, best_to = -1;\n            \n            for (int i = 0; i < N; ++i) {\n                int a = as[i];\n                for (int b = 0; b < D; ++b) {\n                    if (a == b) continue;\n                    long long sa = gsum[a], sb = gsum[b], wi = est[i];\n                    long long nsa = sa - wi, nsb = sb + wi;\n                    long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        best_type = 2;\n                        best_i = i; best_to = b;\n                    }\n                }\n            }\n            \n            for (int i = 0; i < N; ++i) {\n                int a = as[i];\n                for (int j = i + 1; j < N; ++j) {\n                    int b = as[j];\n                    if (a == b) continue;\n                    long long sa = gsum[a], sb = gsum[b];\n                    long long wi = est[i], wj = est[j];\n                    long long nsa = sa - wi + wj;\n                    long long nsb = sb - wj + wi;\n                    long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        best_type = 1;\n                        best_i = i; best_j = j;\n                    }\n                }\n            }\n            \n            if (bestDelta < 0) {\n                improved = true;\n                if (best_type == 2) {\n                    int i = best_i, a = as[i], b = best_to;\n                    as[i] = b;\n                    gsum[a] -= est[i];\n                    gsum[b] += est[i];\n                    auto& ga = groups[a];\n                    for (size_t k = 0; k < ga.size(); ++k) if (ga[k] == i) { ga[k] = ga.back(); ga.pop_back(); break; }\n                    groups[b].push_back(i);\n                } else {\n                    int i = best_i, j = best_j;\n                    int a = as[i], b = as[j];\n                    as[i] = b; as[j] = a;\n                    gsum[a] = gsum[a] - est[i] + est[j];\n                    gsum[b] = gsum[b] - est[j] + est[i];\n                    for (auto& x : groups[a]) if (x == i) { x = j; break; }\n                    for (auto& x : groups[b]) if (x == j) { x = i; break; }\n                }\n            }\n        }\n    };\n    \n    for (int q = 0; q < Q; ++q) {\n        if (q % 50 == 0 || q >= Q - 200) {\n            recompute_est();\n            improve_partition(assign);\n        }\n        \n        vector<int> direct_deg(N, 0);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (direct_done[i][j]) direct_deg[i]++;\n        \n        vector<int> num_gt(N);\n        for (int i = 0; i < N; ++i) num_gt[i] = (int)gt[i].count();\n        \n        int best_i = -1, best_j = -1;\n        int best_val = INT_MAX;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (direct_done[i][j]) continue;\n                if (dsu.find(i) == dsu.find(j)) continue;\n                if (gt[i].test(j) || gt[j].test(i)) continue;\n                \n                int diff = abs(num_gt[i] - num_gt[j]);\n                int deg = direct_deg[i] + direct_deg[j];\n                int cross = (assign[i] != assign[j]) ? -100 : 0;\n                int val = diff * 10 + deg + cross;\n                if (val < best_val) {\n                    best_val = val;\n                    best_i = i; best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (direct_done[i][j]) continue;\n                    if (dsu.find(i) == dsu.find(j)) continue;\n                    \n                    int diff = abs(num_gt[i] - num_gt[j]);\n                    int deg = direct_deg[i] + direct_deg[j];\n                    int cross = (assign[i] != assign[j]) ? -100 : 0;\n                    int val = diff * 10 + deg + cross;\n                    if (val < best_val) {\n                        best_val = val;\n                        best_i = i; best_j = j;\n                    }\n                }\n            }\n        }\n        \n        if (best_i == -1) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (assign[i] != assign[j]) {\n                        best_i = i; best_j = j;\n                        break;\n                    }\n                }\n                if (best_i != -1) break;\n            }\n        }\n        \n        if (best_i == -1) {\n            best_i = 0; best_j = 1;\n        }\n        \n        cout << \"1 1 \" << best_i << \" \" << best_j << '\\n' << flush;\n        string res;\n        cin >> res;\n        \n        direct_done[best_i][best_j] = direct_done[best_j][best_i] = 1;\n        if (res == \">\") {\n            int u = best_i, v = best_j;\n            gt[u].set(v);\n            auto old_u = gt[u];\n            gt[u] |= gt[v];\n            if (gt[u] != old_u) {\n                for (int i = 0; i < N; ++i) {\n                    if (gt[i].test(u)) gt[i] |= gt[u];\n                }\n            }\n        } else if (res == \"<\") {\n            int u = best_j, v = best_i;\n            gt[u].set(v);\n            auto old_u = gt[u];\n            gt[u] |= gt[v];\n            if (gt[u] != old_u) {\n                for (int i = 0; i < N; ++i) {\n                    if (gt[i].test(u)) gt[i] |= gt[u];\n                }\n            }\n        } else {\n            dsu.unite(best_i, best_j);\n        }\n    }\n    \n    recompute_est();\n    improve_partition(assign);\n    \n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    vector<long long> gsum(D, 0);\n    for (int i = 0; i < N; ++i) gsum[assign[i]] += est[i];\n    auto cur_obj = [&]() {\n        long long s = 0;\n        for (long long x : gsum) s += x * x;\n        return s;\n    };\n    \n    long long bestObj = cur_obj();\n    vector<int> bestAssign = assign;\n    vector<vector<int>> groups(D);\n    for (int i = 0; i < N; ++i) groups[assign[i]].push_back(i);\n    \n    double T = 1e12;\n    for (int iter = 0; iter < 200000; ++iter) {\n        T *= 0.99997;\n        int type = uniform_int_distribution<int>(0, 1)(rng);\n        int a = uniform_int_distribution<int>(0, D - 1)(rng);\n        int b = uniform_int_distribution<int>(0, D - 1)(rng);\n        if (a == b) continue;\n        \n        if (type == 0) {\n            if (groups[a].empty()) continue;\n            int idx = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n            int i = groups[a][idx];\n            long long sa = gsum[a], sb = gsum[b];\n            long long wi = est[i];\n            long long nsa = sa - wi, nsb = sb + wi;\n            long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n            bool accept = delta < 0;\n            if (!accept) {\n                if (uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) accept = true;\n            }\n            if (accept) {\n                assign[i] = b;\n                gsum[a] = nsa; gsum[b] = nsb;\n                groups[a][idx] = groups[a].back(); groups[a].pop_back();\n                groups[b].push_back(i);\n                long long obj = cur_obj();\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestAssign = assign;\n                }\n            }\n        } else {\n            if (groups[a].empty() || groups[b].empty()) continue;\n            int idx1 = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n            int idx2 = uniform_int_distribution<int>(0, (int)groups[b].size() - 1)(rng);\n            int i = groups[a][idx1], j = groups[b][idx2];\n            long long sa = gsum[a], sb = gsum[b];\n            long long wi = est[i], wj = est[j];\n            long long nsa = sa - wi + wj, nsb = sb - wj + wi;\n            long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n            bool accept = delta < 0;\n            if (!accept) {\n                if (uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) accept = true;\n            }\n            if (accept) {\n                assign[i] = b; assign[j] = a;\n                gsum[a] = nsa; gsum[b] = nsb;\n                swap(groups[a][idx1], groups[b][idx2]);\n                long long obj = cur_obj();\n                if (obj < bestObj) {\n                    bestObj = obj;\n                    bestAssign = assign;\n                }\n            }\n        }\n    }\n    \n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestAssign[i];\n    }\n    cout << endl;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nint n, m;\n\nstruct Result {\n    long long energy = (1LL << 60);\n    vector<pair<int,int>> ops;\n};\n\nResult simulate(const vector<vector<int>>& init, int bulkVar, int peelMode) {\n    vector<vector<int>> st = init;\n    vector<int> pos(n + 1, -1);\n    for (int i = 0; i < m; ++i)\n        for (int x : st[i]) pos[x] = i;\n\n    const int INF = 1e9;\n    vector<int> mn(m, INF);\n    auto recomp = [&](int idx) {\n        if (st[idx].empty()) mn[idx] = INF;\n        else {\n            mn[idx] = INF;\n            for (int x : st[idx]) mn[idx] = min(mn[idx], x);\n        }\n    };\n    for (int i = 0; i < m; ++i) recomp(i);\n\n    Result res;\n    res.energy = 0;\n    res.ops.reserve(5000);\n\n    for (int v = 1; v <= n; ++v) {\n        if ((int)res.ops.size() >= 5000) {\n            res.energy = (1LL << 60);\n            return res;\n        }\n\n        int s = pos[v];\n        int vpos = 0;\n        while (vpos < (int)st[s].size() && st[s][vpos] != v) ++vpos;\n\n        /* ---------- peeling phase ---------- */\n        if (peelMode != 0) {\n            while ((int)res.ops.size() < 5000) {\n                if (st[s].back() == v) break;\n                int tailSz = (int)st[s].size() - vpos - 1;\n                if (tailSz <= 0) break;\n\n                int x = st[s].back();\n                vector<int> T(st[s].begin() + vpos + 1, st[s].end());\n                int mnTail = *min_element(T.begin(), T.end());\n                int mxTail = *max_element(T.begin(), T.end());\n\n                bool hasSafeBulk = false;\n                for (int d = 0; d < m; ++d) if (d != s) {\n                    if (st[d].empty() || mn[d] >= mxTail) {\n                        hasSafeBulk = true;\n                        break;\n                    }\n                }\n\n                bool shouldPeel = false;\n                if (peelMode == 1) {               // smart\n                    if (!hasSafeBulk) shouldPeel = true;\n                } else if (peelMode == 2) {        // smart limited\n                    if (!hasSafeBulk && tailSz >= 3) shouldPeel = true;\n                } else if (peelMode == 3) {        // aggressive\n                    if (tailSz >= 2) shouldPeel = true;\n                } else if (peelMode == 4) {        // aggressive limited\n                    if (tailSz >= 3) shouldPeel = true;\n                } else if (peelMode == 5) {        // smart empty-only\n                    if (!hasSafeBulk) shouldPeel = true;\n                } else if (peelMode == 6) {        // aggressive empty-only\n                    if (tailSz >= 2) shouldPeel = true;\n                } else if (peelMode == 7) {        // dumb\n                    if (x != mnTail) shouldPeel = true;\n                }\n\n                if (!shouldPeel) break;\n\n                // choose destination: empty first, then best-fit non-empty safe\n                int best_d = -1, best_mn = INF, empty_d = -1;\n                for (int d = 0; d < m; ++d) if (d != s) {\n                    if (st[d].empty()) {\n                        if (empty_d == -1) empty_d = d;\n                    } else if (mn[d] > x) {\n                        if (mn[d] < best_mn) {\n                            best_mn = mn[d];\n                            best_d = d;\n                        }\n                    }\n                }\n\n                int d = -1;\n                if (peelMode == 5 || peelMode == 6) {\n                    if (empty_d != -1) d = empty_d;\n                    else break;\n                } else {\n                    if (empty_d != -1) d = empty_d;\n                    else if (best_d != -1) d = best_d;\n                    else break;\n                }\n\n                // execute peel of single box x (cost 2)\n                res.ops.emplace_back(x, d + 1);\n                res.energy += 2;\n                st[d].push_back(x);\n                pos[x] = d;\n                st[s].pop_back();\n                recomp(d);\n                // mn[s] remains v, no need to recompute\n            }\n        }\n\n        if ((int)res.ops.size() >= 5000) {\n            res.energy = (1LL << 60);\n            return res;\n        }\n\n        /* ---------- direct removal ---------- */\n        if (st[s].back() == v) {\n            res.ops.emplace_back(v, 0);\n            st[s].pop_back();\n            pos[v] = -1;\n            recomp(s);\n            continue;\n        }\n\n        /* ---------- forced bulk move ---------- */\n        int vpos2 = 0;\n        while (vpos2 < (int)st[s].size() && st[s][vpos2] != v) ++vpos2;\n        vector<int> T(st[s].begin() + vpos2 + 1, st[s].end());\n        int w = T[0];\n        int k = (int)T.size();\n        int mxT = *max_element(T.begin(), T.end());\n\n        tuple<int,int,int,int> bestScore = {INF, INF, INF, INF};\n        int best_d = -1;\n        for (int d = 0; d < m; ++d) if (d != s) {\n            tuple<int,int,int,int> sc;\n            bool empty = st[d].empty();\n            bool safe = !empty && mn[d] >= mxT;\n\n            if (empty) {\n                if (bulkVar == 2 || bulkVar == 7) sc = make_tuple(0, 0, 0, 0);\n                else sc = make_tuple(1, 0, 0, 0);\n            } else if (safe) {\n                if (bulkVar == 0) {\n                    sc = make_tuple(0, st[d].back(), 0, 0);\n                } else if (bulkVar == 1 || bulkVar == 3 || bulkVar == 4) {\n                    sc = make_tuple(0, mn[d], 0, 0);          // best fit\n                } else if (bulkVar == 5) {\n                    sc = make_tuple(0, (int)st[d].size(), mn[d], 0);\n                } else if (bulkVar == 6 || bulkVar == 7) {\n                    sc = make_tuple(0, -mn[d], 0, 0);          // worst fit\n                } else {\n                    sc = make_tuple(0, mn[d], 0, 0);\n                }\n            } else {\n                int invc = 0, blockers = 0;\n                for (int t : T) {\n                    if (t > mn[d]) ++blockers;\n                    for (int x : st[d]) if (t > x) ++invc;\n                }\n                if (bulkVar == 3) {\n                    sc = make_tuple(2, blockers, -mn[d], 0);\n                } else if (bulkVar == 4) {\n                    sc = make_tuple(2, blockers, invc, -mn[d]);\n                } else {\n                    sc = make_tuple(2, invc, -mn[d], 0);\n                }\n            }\n            if (sc < bestScore) {\n                bestScore = sc;\n                best_d = d;\n            }\n        }\n\n        // execute bulk move\n        res.ops.emplace_back(w, best_d + 1);\n        res.energy += k + 1;\n        for (int t : T) {\n            st[best_d].push_back(t);\n            pos[t] = best_d;\n        }\n        st[s].resize(vpos2 + 1);   // keep v temporarily\n        st[s].pop_back();           // carry out v\n        pos[v] = -1;\n        res.ops.emplace_back(v, 0);\n        recomp(s);\n        recomp(best_d);\n    }\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> n >> m)) return 0;\n\n    vector<vector<int>> init(m, vector<int>(n / m));\n    for (int i = 0; i < m; ++i)\n        for (int j = 0; j < n / m; ++j)\n            cin >> init[i][j];\n\n    Result best;\n    best.energy = (1LL << 60);\n\n    for (int bulk = 0; bulk < 8; ++bulk) {\n        for (int peel = 0; peel < 8; ++peel) {\n            Result cur = simulate(init, bulk, peel);\n            if ((int)cur.ops.size() <= 5000 && cur.energy < best.energy) {\n                best = std::move(cur);\n            }\n        }\n    }\n\n    for (auto &p : best.ops)\n        cout << p.first << ' ' << p.second << '\\n';\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> h(N - 1);\n    vector<string> vwall(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> vwall[i];\n    vector<vector<int>> dmat(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> dmat[i][j];\n\n    const int V = N * N;\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto geti = [&](int v) { return v / N; };\n    auto getj = [&](int v) { return v % N; };\n\n    vector<int> dval(V);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dval[id(i, j)] = dmat[i][j];\n\n    vector<pair<int,int>> edges;\n    vector<vector<pair<int,int>>> adj(V);\n    auto add_edge = [&](int u, int v) {\n        int eid = edges.size();\n        edges.emplace_back(u, v);\n        adj[u].push_back({v, eid});\n        adj[v].push_back({u, eid});\n    };\n    for (int i = 0; i < N - 1; ++i)\n        for (int j = 0; j < N; ++j)\n            if (h[i][j] == '0') add_edge(id(i, j), id(i + 1, j));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N - 1; ++j)\n            if (vwall[i][j] == '0') add_edge(id(i, j), id(i, j + 1));\n    const int E = edges.size();\n\n    const long long L = 100000;\n\n    // Greedy multigraph construction\n    vector<long long> mult(E, 0);\n    vector<char> vis(V, 0);\n    queue<int> q;\n    vis[0] = 1; q.push(0);\n    while (!q.empty()) {\n        int u = q.front(); q.pop();\n        for (auto [v, eid] : adj[u]) {\n            if (!vis[v]) {\n                vis[v] = 1;\n                mult[eid] = 2;\n                q.push(v);\n            }\n        }\n    }\n\n    vector<long long> k(V, 0);\n    for (int eid = 0; eid < E; ++eid) if (mult[eid]) {\n        k[edges[eid].first] += mult[eid];\n        k[edges[eid].second] += mult[eid];\n    }\n    for (int v = 0; v < V; ++v) k[v] /= 2;\n    long long Lcur = 0;\n    for (int v = 0; v < V; ++v) Lcur += k[v];\n\n    vector<double> escore(E);\n    auto recompute = [&](int eid) {\n        int u = edges[eid].first, v = edges[eid].second;\n        escore[eid] = (double)dval[u] / ((double)k[u] * (k[u] + 1.0))\n                    + (double)dval[v] / ((double)k[v] * (k[v] + 1.0));\n    };\n    for (int eid = 0; eid < E; ++eid) recompute(eid);\n\n    while (Lcur + 2 <= L) {\n        int bestEid = 0;\n        double bestSc = escore[0];\n        for (int eid = 1; eid < E; ++eid) {\n            if (escore[eid] > bestSc) {\n                bestSc = escore[eid];\n                bestEid = eid;\n            }\n        }\n        mult[bestEid] += 2;\n        int u = edges[bestEid].first, v = edges[bestEid].second;\n        k[u]++; k[v]++;\n        Lcur += 2;\n        for (auto [w, eid2] : adj[u]) recompute(eid2);\n        for (auto [w, eid2] : adj[v]) recompute(eid2);\n    }\n\n    auto move_char = [&](int u, int v) -> char {\n        int i1 = geti(u), j1 = getj(u);\n        int i2 = geti(v), j2 = getj(v);\n        if (i2 == i1 - 1) return 'U';\n        if (i2 == i1 + 1) return 'D';\n        if (j2 == j1 - 1) return 'L';\n        return 'R';\n    };\n\n    long long bestCost = LLONG_MAX;\n    string bestRoute;\n    bestRoute.reserve((size_t)L);\n\n    vector<long long> rem(E);\n    vector<int> lastVisit(V);\n    vector<int> path;\n    path.reserve((size_t)L + 1);\n    vector<int> stk;\n    stk.reserve((size_t)L + 1);\n\n    vector<uint32_t> seeds = {12345, 77777, 99999, 42, 2023, 31415, 27182, 16180};\n\n    for (uint32_t seed : seeds) {\n        mt19937 rng(seed);\n        vector<vector<pair<int,int>>> adj2 = adj;\n        for (auto& lst : adj2) shuffle(lst.begin(), lst.end(), rng);\n\n        for (int i = 0; i < E; ++i) rem[i] = mult[i];\n        fill(lastVisit.begin(), lastVisit.end(), -1000000);\n        lastVisit[0] = 0;\n        path.clear();\n        stk.clear();\n        stk.push_back(0);\n        int curTime = 0;\n\n        while (!stk.empty()) {\n            int u = stk.back();\n            int bestEid = -1, bestV = -1;\n            long long bestScore = LLONG_MIN;\n            for (auto [v, eid] : adj2[u]) {\n                if (rem[eid] == 0) continue;\n                long long score = (curTime + 1 - lastVisit[v]) * 1LL * dval[v];\n                score += (long long)(rng() & 2047);\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestV = v;\n                    bestEid = eid;\n                }\n            }\n            if (bestEid == -1) {\n                path.push_back(u);\n                stk.pop_back();\n            } else {\n                rem[bestEid]--;\n                curTime++;\n                lastVisit[bestV] = curTime;\n                stk.push_back(bestV);\n            }\n        }\n\n        reverse(path.begin(), path.end());\n        if ((long long)path.size() != L + 1) continue;\n\n        long long cost = 0;\n        vector<long long> acc(V, 0);\n        vector<int> ftime(V, -1);\n        vector<int> ltime(V, -1);\n        for (int t = 1; t < L; ++t) {\n            int v = path[t];\n            if (ftime[v] == -1) {\n                ftime[v] = t;\n            } else {\n                long long gap = t - ltime[v];\n                acc[v] += gap * gap;\n            }\n            ltime[v] = t;\n        }\n        for (int v = 0; v < V; ++v) {\n            if (ftime[v] != -1) {\n                long long gap = L - ltime[v] + ftime[v];\n                cost += 1LL * dval[v] * (acc[v] + gap * gap);\n            }\n        }\n\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestRoute.clear();\n            for (int i = 0; i < L; ++i)\n                bestRoute.push_back(move_char(path[i], path[i + 1]));\n        }\n    }\n\n    cout << bestRoute << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint start_cell;\nstring targets[200];\nvector<int> pos[26];\nint dist_arr[225][225];\n\nint last_cells[200][225];\nint last_sz[200];\n// cost_tbl[t][k][c * last_sz[t] + e]\nvector<int16_t> cost_tbl[200][5];\nint16_t best_cost_full[200][225];\n\ninline int manhattan(int a, int b) { return dist_arr[a][b]; }\n\n/*--------------- suffix state (last up to 5 chars) ---------------*/\nstruct State {\n    char s[5];\n    uint8_t len;\n    State() : len(0) {}\n    int overlap(const string& t) const {\n        int mk = min<int>(len, (int)t.size());\n        for (int k = mk; k >= 1; --k) {\n            bool ok = true;\n            for (int i = 0; i < k; ++i)\n                if (s[len - k + i] != t[i]) { ok = false; break; }\n            if (ok) return k;\n        }\n        return 0;\n    }\n    void append(const string& t, int k) {\n        for (int i = k; i < (int)t.size(); ++i) {\n            if (len < 5) {\n                s[len++] = t[i];\n            } else {\n                s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; s[3] = s[4]; s[4] = t[i];\n            }\n        }\n    }\n};\n\n/*--------------- exact evaluation of a permutation ---------------*/\nint evaluate(const vector<int>& ord) {\n    int ks[200];\n    State suf;\n    for (int i = 0; i < M; ++i) {\n        ks[i] = suf.overlap(targets[ord[i]]);\n        suf.append(targets[ord[i]], ks[i]);\n    }\n\n    int dp_prev[225];\n    int prev_t = -1;\n    int sza = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int t = ord[i];\n        int k = ks[i];\n        if (k == 5) continue;\n        int sz = last_sz[t];\n        if (prev_t == -1) {\n            for (int e = 0; e < sz; ++e)\n                dp_prev[e] = (int)cost_tbl[t][k][start_cell * sz + e];\n            sza = sz;\n            prev_t = t;\n        } else {\n            int dp_cur[225];\n            for (int e2 = 0; e2 < sz; ++e2) {\n                int best = INT_MAX;\n                for (int e1 = 0; e1 < sza; ++e1) {\n                    int c = last_cells[prev_t][e1];\n                    int cand = dp_prev[e1] + (int)cost_tbl[t][k][c * sz + e2];\n                    if (cand < best) best = cand;\n                }\n                dp_cur[e2] = best;\n            }\n            for (int e2 = 0; e2 < sz; ++e2) dp_prev[e2] = dp_cur[e2];\n            sza = sz;\n            prev_t = t;\n        }\n    }\n    if (prev_t == -1) return 0;\n    int ans = INT_MAX;\n    for (int e = 0; e < sza; ++e) ans = min(ans, dp_prev[e]);\n    return ans;\n}\n\n/*--------------- GRASP construction ---------------*/\nvector<int> grasp_construct(mt19937& rng, bool randomized, int rcl_size) {\n    vector<int> ord;\n    ord.reserve(M);\n    vector<char> used(M, 0);\n    State suf;\n    int cur = start_cell;\n\n    for (int step = 0; step < M; ++step) {\n        int16_t best1[225];\n        int16_t best2[225];\n        int best1t[225];\n        for (int d = 0; d < 225; ++d) {\n            best1[d] = INT16_MAX;\n            best2[d] = INT16_MAX;\n            best1t[d] = -1;\n        }\n\n        for (int t = 0; t < M; ++t) if (!used[t]) {\n            for (int d = 0; d < 225; ++d) {\n                int16_t v = best_cost_full[t][d];\n                if (v < best1[d]) {\n                    best2[d] = best1[d];\n                    best1[d] = v;\n                    best1t[d] = t;\n                } else if (v < best2[d]) {\n                    best2[d] = v;\n                }\n            }\n        }\n\n        struct Cand { int t, e, val; };\n        Cand top[20];\n        int tcnt = 0;\n\n        for (int t = 0; t < M; ++t) if (!used[t]) {\n            int k = suf.overlap(targets[t]);\n            int sz = last_sz[t];\n            for (int e = 0; e < sz; ++e) {\n                int d = last_cells[t][e];\n                int here = (int)cost_tbl[t][k][cur * sz + e];\n                int future = (step == M - 1) ? 0\n                             : (best1t[d] == t ? best2[d] : best1[d]);\n                int val = here + future;\n                if (tcnt < rcl_size) {\n                    top[tcnt++] = {t, e, val};\n                    for (int x = tcnt - 1; x > 0; --x)\n                        if (top[x].val < top[x - 1].val) swap(top[x], top[x - 1]);\n                } else if (val < top[tcnt - 1].val) {\n                    top[tcnt - 1] = {t, e, val};\n                    for (int x = tcnt - 1; x > 0; --x)\n                        if (top[x].val < top[x - 1].val) swap(top[x], top[x - 1]);\n                }\n            }\n        }\n\n        Cand distinct[20];\n        int dcnt = 0;\n        for (int i = 0; i < tcnt; ++i) {\n            bool ok = true;\n            for (int j = 0; j < dcnt; ++j)\n                if (distinct[j].t == top[i].t) { ok = false; break; }\n            if (ok) distinct[dcnt++] = top[i];\n        }\n        if (dcnt == 0) { // should never happen\n            for (int t = 0; t < M; ++t) if (!used[t]) {\n                distinct[0] = {t, 0, 0};\n                dcnt = 1;\n                break;\n            }\n        }\n\n        int pick = randomized ? (rng() % dcnt) : 0;\n        int chosen_t = distinct[pick].t;\n        int chosen_e = distinct[pick].e;\n\n        ord.push_back(chosen_t);\n        used[chosen_t] = 1;\n        int kk = suf.overlap(targets[chosen_t]);\n        suf.append(targets[chosen_t], kk);\n        cur = last_cells[chosen_t][chosen_e];\n    }\n    return ord;\n}\n\n/*--------------- reconstruct best order ---------------*/\nvector<pair<int,int>> reconstruct(const vector<int>& ord) {\n    vector<pair<int,int>> answer;\n    int ks[200];\n    State suf;\n    for (int i = 0; i < M; ++i) {\n        ks[i] = suf.overlap(targets[ord[i]]);\n        suf.append(targets[ord[i]], ks[i]);\n    }\n\n    vector<vector<uint8_t>> back_ptrs;\n    vector<int> chunk_t;\n    vector<int> chunk_k;\n    int dp_prev[225];\n    int prev_t = -1;\n    int sza = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int t = ord[i];\n        int k = ks[i];\n        if (k == 5) continue;\n        int sz = last_sz[t];\n        if (prev_t == -1) {\n            for (int e = 0; e < sz; ++e)\n                dp_prev[e] = (int)cost_tbl[t][k][start_cell * sz + e];\n            sza = sz;\n            prev_t = t;\n            chunk_t.push_back(t);\n            chunk_k.push_back(k);\n        } else {\n            vector<uint8_t> bp(sz);\n            int dp_cur[225];\n            for (int e2 = 0; e2 < sz; ++e2) {\n                int best = INT_MAX;\n                uint8_t best_e1 = 0;\n                for (int e1 = 0; e1 < sza; ++e1) {\n                    int c = last_cells[prev_t][e1];\n                    int cand = dp_prev[e1] + (int)cost_tbl[t][k][c * sz + e2];\n                    if (cand < best) {\n                        best = cand;\n                        best_e1 = (uint8_t)e1;\n                    }\n                }\n                dp_cur[e2] = best;\n                bp[e2] = best_e1;\n            }\n            for (int e2 = 0; e2 < sz; ++e2) dp_prev[e2] = dp_cur[e2];\n            back_ptrs.push_back(std::move(bp));\n            sza = sz;\n            prev_t = t;\n            chunk_t.push_back(t);\n            chunk_k.push_back(k);\n        }\n    }\n\n    int Cn = (int)chunk_t.size();\n    if (Cn == 0) return answer;\n\n    int best_e = 0;\n    for (int e = 1; e < sza; ++e)\n        if (dp_prev[e] < dp_prev[best_e]) best_e = e;\n\n    vector<int> end_idx(Cn);\n    end_idx[Cn - 1] = best_e;\n    for (int i = Cn - 1; i >= 1; --i)\n        end_idx[i - 1] = back_ptrs[i - 1][end_idx[i]];\n\n    int cur_cell = start_cell;\n    for (int idx = 0; idx < Cn; ++idx) {\n        int t = chunk_t[idx];\n        int k = chunk_k[idx];\n        int ej = end_idx[idx];\n        int L = 5 - k;\n        vector<int> layers[5];\n        for (int l = 0; l < L; ++l)\n            layers[l] = pos[targets[t][k + l] - 'A'];\n\n        int dp_p[225], dp_c[225];\n        uint8_t par[5][225];\n\n        int sz0 = (int)layers[0].size();\n        for (int i = 0; i < sz0; ++i)\n            dp_p[i] = manhattan(cur_cell, layers[0][i]);\n\n        for (int l = 1; l < L; ++l) {\n            int szp = (int)layers[l - 1].size();\n            int szc = (int)layers[l].size();\n            for (int j = 0; j < szc; ++j) {\n                int best = INT_MAX;\n                uint8_t best_i = 0;\n                for (int i = 0; i < szp; ++i) {\n                    int val = dp_p[i] + manhattan(layers[l - 1][i], layers[l][j]);\n                    if (val < best) {\n                        best = val;\n                        best_i = (uint8_t)i;\n                    }\n                }\n                dp_c[j] = best;\n                par[l][j] = best_i;\n            }\n            for (int j = 0; j < szc; ++j) dp_p[j] = dp_c[j];\n        }\n\n        int cells[5];\n        int cur_j = ej;\n        cells[L - 1] = layers[L - 1][cur_j];\n        for (int l = L - 1; l >= 1; --l) {\n            cur_j = par[l][cur_j];\n            cells[l - 1] = layers[l - 1][cur_j];\n        }\n\n        for (int l = 0; l < L; ++l) {\n            int id = cells[l];\n            answer.emplace_back(id / N, id % N);\n        }\n        cur_cell = cells[L - 1];\n    }\n    return answer;\n}\n\n/*--------------- strong perturbation (ILS kick) ---------------*/\nvector<int> kick(const vector<int>& ord, mt19937& rng) {\n    vector<int> res = ord;\n    int type = rng() % 3;\n    if (type == 0) {\n        // reverse segment\n        int i = rng() % max(1, M - 1);\n        int len = 10 + (int)(rng() % 21); // 10..30\n        int j = min(M - 1, i + len);\n        reverse(res.begin() + i, res.begin() + j + 1);\n    } else if (type == 1) {\n        // move block\n        int len = 5 + (int)(rng() % 11); // 5..15\n        if (len > M) len = M;\n        int i = rng() % max(1, M - len + 1);\n        int j = i + len;\n        vector<int> block(res.begin() + i, res.begin() + j);\n        res.erase(res.begin() + i, res.begin() + j);\n        int pos = rng() % ((int)res.size() + 1);\n        res.insert(res.begin() + pos, block.begin(), block.end());\n    } else {\n        // scramble segment\n        int len = 8 + (int)(rng() % 13); // 8..20\n        if (len > M) len = M;\n        int i = rng() % max(1, M - len + 1);\n        shuffle(res.begin() + i, res.begin() + i + len, rng);\n    }\n    return res;\n}\n\n/*--------------- main ---------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    start_cell = si * N + sj;\n    const int C = N * N;\n\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            pos[s[j] - 'A'].push_back(id);\n        }\n    }\n    for (int k = 0; k < M; ++k) cin >> targets[k];\n\n    for (int i = 0; i < C; ++i) {\n        int i1 = i / N, j1 = i % N;\n        for (int j = 0; j < C; ++j) {\n            int i2 = j / N, j2 = j % N;\n            dist_arr[i][j] = abs(i1 - i2) + abs(j1 - j2);\n        }\n    }\n\n    /* precompute suffix costs */\n    for (int t = 0; t < M; ++t) {\n        char last_ch = targets[t][4];\n        last_sz[t] = (int)pos[last_ch - 'A'].size();\n        for (int i = 0; i < last_sz[t]; ++i)\n            last_cells[t][i] = pos[last_ch - 'A'][i];\n\n        for (int k = 0; k < 5; ++k) {\n            int L = 5 - k;\n            vector<int> cells[5];\n            for (int l = 0; l < L; ++l)\n                cells[l] = pos[targets[t][k + l] - 'A'];\n\n            int sz_last = (int)cells[L - 1].size();\n            cost_tbl[t][k].assign(C * sz_last, 0);\n            vector<int> dp_prev(225), dp_cur(225);\n            for (int c = 0; c < C; ++c) {\n                int sz0 = (int)cells[0].size();\n                for (int i = 0; i < sz0; ++i)\n                    dp_prev[i] = manhattan(c, cells[0][i]) + 1;\n                for (int l = 1; l < L; ++l) {\n                    int szp = (int)cells[l - 1].size();\n                    int szc = (int)cells[l].size();\n                    for (int j = 0; j < szc; ++j) {\n                        int best = INT_MAX;\n                        for (int i = 0; i < szp; ++i) {\n                            int val = dp_prev[i] + manhattan(cells[l - 1][i], cells[l][j]);\n                            if (val < best) best = val;\n                        }\n                        dp_cur[j] = best + 1;\n                    }\n                    for (int j = 0; j < szc; ++j) dp_prev[j] = dp_cur[j];\n                }\n                for (int e = 0; e < sz_last; ++e)\n                    cost_tbl[t][k][c * sz_last + e] = (int16_t)dp_prev[e];\n            }\n        }\n\n        int sz = last_sz[t];\n        for (int c = 0; c < C; ++c) {\n            int best = INT_MAX;\n            for (int e = 0; e < sz; ++e)\n                best = min(best, (int)cost_tbl[t][0][c * sz + e]);\n            best_cost_full[t][c] = (int16_t)best;\n        }\n    }\n\n    /* generate initial solutions with GRASP */\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    vector<int> best_order;\n    int best_val = INT_MAX;\n\n    // deterministic greedy\n    {\n        vector<int> ord = grasp_construct(rng, false, 1);\n        int v = evaluate(ord);\n        if (v < best_val) { best_val = v; best_order = ord; }\n    }\n\n    // randomized GRASP runs with varying RCL sizes\n    for (int run = 0; run < 25; ++run) {\n        int rcl = (run < 8) ? 3 : (run < 16) ? 5 : 7;\n        vector<int> ord = grasp_construct(rng, true, rcl);\n        if ((int)ord.size() != M) continue;\n        int v = evaluate(ord);\n        if (v < best_val) { best_val = v; best_order = ord; }\n    }\n\n    /* iterated local search around the best known solution */\n    vector<int> cur_order = best_order;\n    int cur_val = best_val;\n\n    const double TL = 1.97;\n    const int PATIENCE = 6000;\n    int iter = 0, last_improve = 0;\n\n    while (elapsed() < TL) {\n        ++iter;\n        int type = rng() % 4;\n        int i = rng() % M;\n        int j = rng() % M;\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<int> nxt = cur_order;\n        if (type == 0) {\n            swap(nxt[i], nxt[j]);\n        } else if (type == 1) {\n            int v = nxt[i];\n            nxt.erase(nxt.begin() + i);\n            nxt.insert(nxt.begin() + j, v);\n        } else if (type == 2) {\n            reverse(nxt.begin() + i, nxt.begin() + j + 1);\n        } else {\n            int len = 2 + (int)(rng() % 3);\n            if (i + len > M) len = M - i;\n            vector<int> block(nxt.begin() + i, nxt.begin() + i + len);\n            nxt.erase(nxt.begin() + i, nxt.begin() + i + len);\n            int pos = rng() % ((int)nxt.size() + 1);\n            nxt.insert(nxt.begin() + pos, block.begin(), block.end());\n        }\n\n        int nxt_val = evaluate(nxt);\n        if (nxt_val <= cur_val) {\n            cur_order = std::move(nxt);\n            cur_val = nxt_val;\n            last_improve = iter;\n            if (cur_val < best_val) {\n                best_val = cur_val;\n                best_order = cur_order;\n            }\n        } else if (iter - last_improve > PATIENCE) {\n            cur_order = kick(best_order, rng);\n            cur_val = evaluate(cur_order);\n            last_improve = iter;\n        }\n    }\n\n    vector<pair<int,int>> ans = reconstruct(best_order);\n    for (auto &p : ans) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, MAX_OPS;\ndouble eps;\nconst int MAXC = 400;          // max cells (20*20)\nconst int MAXT = 400;          // max translations per field\n\nvector<vector<bitset<MAXC>>> masks;                 // masks[field][trans]\nvector<vector<bitset<MAXT>>> trans_cover_cell;      // candidates covering cell p\nvector<vector<bitset<MAXT>>> not_cover_cell;        // candidates NOT covering cell p\nvector<bitset<MAXT>> all_valid;                     // all translations of a field\n\nvector<int> drilled_val;        // -1 = unknown\nvector<int> drilled_cells;\nmt19937 rng;\n\n/* ---------- safe fixed\u2011point propagation ---------- */\nvoid global_propagate(vector<bitset<MAXT>>& cand) {\n    bool changed = true;\n    int it = 0;\n    while (changed && it++ < 25) {\n        changed = false;\n        for (int k = 0; k < M; k++) if (!cand[k].any()) return;\n\n        vector<vector<char>> any(M, vector<char>(N * N, 0));\n        vector<vector<char>> all(M, vector<char>(N * N, 0));\n        vector<int> tot_any(N * N, 0), tot_all(N * N, 0);\n\n        for (int k = 0; k < M; k++) {\n            for (int p : drilled_cells) {\n                bool a = (cand[k] & trans_cover_cell[k][p]).any();\n                bool b = false;\n                if (cand[k].any()) b = (cand[k] & not_cover_cell[k][p]).none();\n                any[k][p] = a;  all[k][p] = b;\n                if (a) ++tot_any[p];\n                if (b) ++tot_all[p];\n            }\n        }\n\n        for (int k = 0; k < M; k++) {\n            for (int t = 0; t < (int)masks[k].size(); t++) if (cand[k].test(t)) {\n                bool ok = true;\n                for (int p : drilled_cells) {\n                    int need = drilled_val[p] - (masks[k][t].test(p) ? 1 : 0);\n                    int minRem = tot_all[p] - (all[k][p] ? 1 : 0);\n                    int maxRem = tot_any[p] - (any[k][p] ? 1 : 0);\n                    if (need < minRem || need > maxRem) { ok = false; break; }\n                }\n                if (!ok) {\n                    cand[k].reset(t);\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\n/* ---------- free deductions (0 or M) from candidate counts ---------- */\nvoid deduce(vector<bitset<MAXT>>& cand) {\n    for (int k = 0; k < M; k++) if (!cand[k].any()) return;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) {\n            int any_cnt = 0, all_cnt = 0;\n            for (int k = 0; k < M; k++) {\n                bool a = (cand[k] & trans_cover_cell[k][p]).any();\n                bool b = false;\n                if (cand[k].any()) b = (cand[k] & not_cover_cell[k][p]).none();\n                if (a) ++any_cnt;\n                if (b) ++all_cnt;\n            }\n            if (any_cnt == 0) {\n                drilled_val[p] = 0;\n                drilled_cells.push_back(p);\n                for (int k = 0; k < M; k++) cand[k] &= not_cover_cell[k][p];\n                changed = true;\n            } else if (all_cnt == M) {\n                drilled_val[p] = M;\n                drilled_cells.push_back(p);\n                for (int k = 0; k < M; k++) cand[k] &= trans_cover_cell[k][p];\n                changed = true;\n            }\n        }\n        if (changed) global_propagate(cand);\n    }\n}\n\n/* ---------- DFS with strong pruning ---------- */\nstruct Sol {\n    bitset<MAXC> uni;\n    vector<int> assigned;\n};\n\nstruct State {\n    vector<int> assigned;\n    array<short, MAXC> cur;\n    array<short, MAXC> rem_forced;\n    array<short, MAXC> rem_possible;\n    int depth;\n};\n\nstruct DFSHelper {\n    const vector<bitset<MAXT>>& cand;\n    int limit_sol;\n    chrono::steady_clock::time_point deadline;\n    int nodes;\n    bool aborted;\n    vector<Sol> sols;\n    vector<vector<char>> can_cover;\n    vector<vector<char>> must_cover;\n\n    DFSHelper(const vector<bitset<MAXT>>& c, int ls, double tl_sec)\n        : cand(c), limit_sol(ls), nodes(0), aborted(false) {\n        auto ms = chrono::milliseconds((long long)(tl_sec * 1000.0));\n        deadline = chrono::steady_clock::now() + ms;\n\n        can_cover.assign(M, vector<char>(N * N, 0));\n        must_cover.assign(M, vector<char>(N * N, 0));\n        for (int k = 0; k < M; k++) {\n            if (!cand[k].any()) continue;\n            for (int p = 0; p < N * N; p++) {\n                if ((cand[k] & trans_cover_cell[k][p]).any()) can_cover[k][p] = 1;\n                if ((cand[k] & not_cover_cell[k][p]).none()) must_cover[k][p] = 1;\n            }\n        }\n    }\n\n    void rec(State st) {\n        if (aborted) return;\n        if ((int)sols.size() >= limit_sol) return;\n        if (++nodes % 64 == 0) {\n            if (chrono::steady_clock::now() > deadline) { aborted = true; return; }\n        }\n        if (st.depth == M) {\n            bitset<MAXC> uni;\n            for (int k = 0; k < M; k++) uni |= masks[k][st.assigned[k]];\n            sols.push_back({uni, st.assigned});\n            return;\n        }\n\n        vector<int> fields;\n        for (int i = 0; i < M; i++) if (st.assigned[i] == -1) fields.push_back(i);\n        sort(fields.begin(), fields.end(),\n             [&](int a, int b) { return cand[a].count() < cand[b].count(); });\n\n        int pick = min((int)fields.size(), max(1, (int)fields.size() / 2 + 1));\n        int k = fields[rng() % pick];\n\n        vector<int> ts;\n        for (int t = 0; t < (int)masks[k].size(); t++)\n            if (cand[k].test(t)) ts.push_back(t);\n        shuffle(ts.begin(), ts.end(), rng);\n\n        for (int t : ts) {\n            State nst = st;\n            nst.assigned[k] = t;\n            ++nst.depth;\n\n            bool ok = true;\n            for (int p : drilled_cells) {\n                if (masks[k][t].test(p)) ++nst.cur[p];\n                if (must_cover[k][p]) --nst.rem_forced[p];\n                if (can_cover[k][p]) --nst.rem_possible[p];\n\n                if (nst.cur[p] + nst.rem_forced[p] > drilled_val[p]) { ok = false; break; }\n                if (nst.cur[p] + nst.rem_possible[p] < drilled_val[p]) { ok = false; break; }\n            }\n            if (!ok) continue;\n\n            rec(nst);\n        }\n    }\n\n    void run() {\n        State init;\n        init.assigned.assign(M, -1);\n        init.cur.fill(0);\n        init.rem_forced.fill(0);\n        init.rem_possible.fill(0);\n        init.depth = 0;\n        for (int p = 0; p < N * N; p++) {\n            for (int k = 0; k < M; k++) {\n                if (must_cover[k][p]) ++init.rem_forced[p];\n                if (can_cover[k][p]) ++init.rem_possible[p];\n            }\n        }\n        rec(init);\n    }\n};\n\n/* ---------- fast candidate\u2011entropy cell picker ---------- */\nint pick_entropy_cell(const vector<bitset<MAXT>>& cand) {\n    int best = -1;\n    double best_score = -1.0;\n    for (int p = 0; p < N * N; ++p) if (drilled_val[p] == -1) {\n        double score = 0.0;\n        for (int k = 0; k < M; ++k) {\n            int total = (int)cand[k].count();\n            if (total <= 1) continue;\n            int cnt = (int)(cand[k] & trans_cover_cell[k][p]).count();\n            if (cnt == 0 || cnt == total) continue;\n            double pk = cnt / (double)total;\n            score += pk * log2(1.0 / pk) + (1.0 - pk) * log2(1.0 / (1.0 - pk));\n        }\n        if (score > best_score + 1e-9) {\n            best_score = score;\n            best = p;\n        }\n    }\n    return best;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    if (!(cin >> N >> M >> eps)) return 0;\n    vector<vector<pair<int,int>>> shapes(M);\n    for (int k = 0; k < M; k++) {\n        int d; cin >> d;\n        shapes[k].resize(d);\n        for (int i = 0; i < d; i++) cin >> shapes[k][i].first >> shapes[k][i].second;\n    }\n    MAX_OPS = 2 * N * N;\n\n    /* pre\u2011compute translations */\n    masks.assign(M, {});\n    all_valid.assign(M, {});\n    for (int k = 0; k < M; k++) {\n        int hi = 0, hj = 0;\n        for (auto &c : shapes[k]) {\n            hi = max(hi, c.first);\n            hj = max(hj, c.second);\n        }\n        int h = hi + 1, w = hj + 1;\n        for (int di = 0; di + h <= N; di++) {\n            for (int dj = 0; dj + w <= N; dj++) {\n                bitset<MAXC> bs;\n                for (auto &c : shapes[k]) {\n                    int i = di + c.first;\n                    int j = dj + c.second;\n                    bs.set(i * N + j);\n                }\n                masks[k].push_back(bs);\n            }\n        }\n        for (int t = 0; t < (int)masks[k].size(); t++) all_valid[k].set(t);\n    }\n\n    trans_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    not_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    for (int k = 0; k < M; k++) {\n        for (int p = 0; p < N * N; p++) {\n            for (int t = 0; t < (int)masks[k].size(); t++)\n                if (masks[k][t].test(p)) trans_cover_cell[k][p].set(t);\n            not_cover_cell[k][p] = all_valid[k] & ~trans_cover_cell[k][p];\n        }\n    }\n\n    drilled_val.assign(N * N, -1);\n    rng = mt19937((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<bitset<MAXT>> cand(M);\n    for (int k = 0; k < M; k++) cand[k] = all_valid[k];\n\n    int ops = 0;\n\n    auto do_drill = [&](int p) -> bool {\n        int i = p / N, j = p % N;\n        cout << \"q 1 \" << i << ' ' << j << endl;\n        int v;\n        if (!(cin >> v)) return false;\n        ++ops;\n        drilled_val[p] = v;\n        drilled_cells.push_back(p);\n        if (v == 0) {\n            for (int k = 0; k < M; k++) cand[k] &= not_cover_cell[k][p];\n        } else if (v == M) {\n            for (int k = 0; k < M; k++) cand[k] &= trans_cover_cell[k][p];\n        }\n        global_propagate(cand);\n        deduce(cand);\n        return true;\n    };\n\n    auto do_guess = [&](const bitset<MAXC>& uni) -> bool {\n        bitset<MAXC> guess = uni;\n        for (int p = 0; p < N * N; p++) {\n            if (drilled_val[p] > 0) guess.set(p);\n            else if (drilled_val[p] == 0) guess.reset(p);\n        }\n        vector<pair<int,int>> ans;\n        for (int p = 0; p < N * N; p++) if (guess.test(p)) ans.emplace_back(p / N, p % N);\n        cout << \"a \" << ans.size();\n        for (auto &pr : ans) cout << ' ' << pr.first << ' ' << pr.second;\n        cout << endl;\n        int resp;\n        if (!(cin >> resp)) return false;\n        ++ops;\n        return resp == 1;\n    };\n\n    auto pick_random_undrilled = [&]() -> int {\n        int p = uniform_int_distribution<int>(0, N * N - 1)(rng);\n        for (int i = 0; i < N * N; ++i) {\n            int q = (p + i) % (N * N);\n            if (drilled_val[q] == -1) return q;\n        }\n        return -1;\n    };\n\n    /* initial random drilling */\n    int init_drills = min(N * N, max(N, 4));\n    for (int i = 0; i < init_drills && ops < MAX_OPS - 20; i++) {\n        int p = pick_random_undrilled();\n        if (p == -1) break;\n        if (!do_drill(p)) return 0;\n    }\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start).count() / 1000.0;\n\n        /* hard time guard: finish exactly */\n        if (elapsed > 2.45) {\n            for (int p = 0; p < N * N && ops < MAX_OPS - 1; p++)\n                if (drilled_val[p] == -1)\n                    if (!do_drill(p)) return 0;\n            bitset<MAXC> exact;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            do_guess(exact);\n            return 0;\n        }\n\n        deduce(cand);\n\n        int undrilled = N * N - (int)drilled_cells.size();\n\n        /* budget guard */\n        if (undrilled + 1 > MAX_OPS - ops) {\n            bitset<MAXC> guess;\n            for (int k = 0; k < M; k++)\n                for (int t = 0; t < (int)masks[k].size(); t++)\n                    if (cand[k].test(t)) guess |= masks[k][t];\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) guess.set(p);\n            do_guess(guess);\n            return 0;\n        }\n\n        /* few cells left -> exact finish */\n        if (undrilled <= 12) {\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) {\n                    if (!do_drill(p)) return 0;\n                }\n            bitset<MAXC> exact;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            do_guess(exact);\n            return 0;\n        }\n\n        /* contradiction guard */\n        bool feasible = true;\n        for (int k = 0; k < M; k++) if (!cand[k].any()) { feasible = false; break; }\n        if (!feasible) {\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) if (!do_drill(p)) return 0;\n            bitset<MAXC> exact;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            do_guess(exact);\n            return 0;\n        }\n\n        /* if every field is pinned, answer is known */\n        bool all_one = true;\n        for (int k = 0; k < M; k++) if (cand[k].count() != 1) { all_one = false; break; }\n        if (all_one) {\n            bitset<MAXC> uni;\n            for (int k = 0; k < M; k++) {\n                for (int t = 0; t < (int)masks[k].size(); t++) if (cand[k].test(t)) {\n                    uni |= masks[k][t];\n                    break;\n                }\n            }\n            if (do_guess(uni)) return 0;\n            /* should not happen, but keep going */\n        }\n\n        int total_cand = 0;\n        for (int k = 0; k < M; k++) total_cand += (int)cand[k].count();\n\n        vector<bitset<MAXC>> sol_unions;\n        bool exhaustive = false;\n\n        /* DFS only when the search space is small enough to likely finish quickly */\n        if (total_cand <= 600) {\n            double tl = (total_cand <= 150) ? 0.40 : 0.18;\n            int lim = (total_cand <= 150) ? 800 : 300;\n            DFSHelper dfs(cand, lim, tl);\n            dfs.run();\n            for (auto &s : dfs.sols) {\n                bool seen = false;\n                for (auto &u : sol_unions) if (u == s.uni) { seen = true; break; }\n                if (!seen) sol_unions.push_back(s.uni);\n            }\n            exhaustive = !dfs.aborted && (int)dfs.sols.size() < lim;\n        }\n\n        if (exhaustive) {\n            if (sol_unions.empty()) {\n                for (int p = 0; p < N * N; p++)\n                    if (drilled_val[p] == -1) if (!do_drill(p)) return 0;\n                bitset<MAXC> exact;\n                for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n                do_guess(exact);\n                return 0;\n            }\n            bool agree = true;\n            for (size_t i = 1; i < sol_unions.size(); i++)\n                if (sol_unions[i] != sol_unions[0]) { agree = false; break; }\n\n            if (agree) {\n                if (do_guess(sol_unions[0])) return 0;\n                for (int p = 0; p < N * N; p++)\n                    if (drilled_val[p] == -1) if (!do_drill(p)) return 0;\n                bitset<MAXC> exact;\n                for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n                do_guess(exact);\n                return 0;\n            } else {\n                /* drill a cell where found solutions disagree */\n                int best = -1, best_score = -1;\n                for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) {\n                    int cnt = 0;\n                    for (auto &u : sol_unions) if (u.test(p)) ++cnt;\n                    int score = min(cnt, (int)sol_unions.size() - cnt);\n                    if (score > best_score) { best_score = score; best = p; }\n                }\n                if (best != -1) {\n                    if (!do_drill(best)) return 0;\n                } else {\n                    int p = pick_random_undrilled();\n                    if (p != -1) { if (!do_drill(p)) return 0; }\n                }\n            }\n        } else {\n            /* no guaranteed exhaustive search: use fast entropy heuristic */\n            int best = pick_entropy_cell(cand);\n            if (best != -1) {\n                if (!do_drill(best)) return 0;\n            } else {\n                int p = pick_random_undrilled();\n                if (p != -1) { if (!do_drill(p)) return 0; }\n                else {\n                    bitset<MAXC> exact;\n                    for (int c = 0; c < N * N; c++) if (drilled_val[c] > 0) exact.set(c);\n                    do_guess(exact);\n                    return 0;\n                }\n            }\n        }\n    }\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect {\n    int x, y; // x=column (j), y=row (i)\n    int w, h;\n};\n\nstruct Cand {\n    vector<Rect> r;\n    vector<ull> mask;\n    ll acost;\n};\n\nstatic int W, D, N;\nstatic int G_WORDS;\nstatic vector<vector<ll>> a;\n\n/* ---------- mask utilities ---------- */\nstatic void build_mask(const vector<Rect>& rects, vector<ull>& mask) {\n    fill(mask.begin(), mask.end(), 0ULL);\n    auto set_bit = [&](int pos) {\n        mask[pos >> 6] |= (1ULL << (pos & 63));\n    };\n    for (const auto& rc : rects) {\n        int x = rc.x, y = rc.y, w = rc.w, h = rc.h;\n        if (y > 0 && y < W)\n            for (int j = x; j < x + w; ++j) set_bit((y - 1) * W + j);\n        if (y + h > 0 && y + h < W)\n            for (int j = x; j < x + w; ++j) set_bit((y + h - 1) * W + j);\n        if (x > 0 && x < W)\n            for (int i = y; i < y + h; ++i)\n                set_bit((W - 1) * W + i * (W - 1) + (x - 1));\n        if (x + w > 0 && x + w < W)\n            for (int i = y; i < y + h; ++i)\n                set_bit((W - 1) * W + i * (W - 1) + (x + w - 1));\n    }\n}\n\nstatic ll trans_cost(const vector<ull>& A, const vector<ull>& B) {\n    ll s = 0;\n    for (int i = 0; i < G_WORDS; ++i)\n        s += __builtin_popcountll(A[i] ^ B[i]);\n    return s;\n}\n\nstatic ll area_cost(const vector<Rect>& r, const vector<ll>& area) {\n    ll c = 0;\n    for (int k = 0; k < N; ++k) {\n        ll A = 1LL * r[k].w * r[k].h;\n        if (area[k] > A) c += 100LL * (area[k] - A);\n    }\n    return c;\n}\n\n/* ---------- guillotine packer (very fast) ---------- */\nstatic vector<Rect> pack_guillotine(const vector<ll>& area, mt19937& rng,\n                                    int order_type, int dim_mode) {\n    int n = (int)area.size();\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    if (order_type == 0) {\n        sort(ord.begin(), ord.end(),\n             [&](int i, int j){ return area[i] > area[j]; });\n    } else if (order_type == 1) {\n        sort(ord.begin(), ord.end(),\n             [&](int i, int j){ return area[i] < area[j]; });\n    } else {\n        shuffle(ord.begin(), ord.end(), rng);\n    }\n\n    vector<pair<int,int>> dim(n);\n    for (int idx : ord) {\n        ll A = area[idx];\n        int w, h;\n        if (dim_mode == 0) {\n            w = max(1, (int)std::sqrt((double)A));\n            h = (int)((A + w - 1) / w);\n        } else if (dim_mode == 1) {\n            h = max(1, (int)std::sqrt((double)A));\n            w = (int)((A + h - 1) / h);\n        } else if (dim_mode == 2) {\n            w = (int)max(1LL, (A + W - 1) / W);\n            h = (int)((A + w - 1) / w);\n        } else if (dim_mode == 3) {\n            h = (int)max(1LL, (A + W - 1) / W);\n            w = (int)((A + h - 1) / h);\n        } else {\n            ll lo = max(1LL, (A + W - 1) / W);\n            ll hi = min((ll)W, A);\n            if (lo >= hi) w = (int)lo;\n            else w = uniform_int_distribution<int>((int)lo, (int)hi)(rng);\n            h = (int)((A + w - 1) / w);\n        }\n        if (h > W) { h = W; w = (int)((A + h - 1) / h); }\n        if (w > W) { w = W; h = (int)((A + w - 1) / w); }\n        if (w < 1) w = 1;\n        if (h < 1) h = 1;\n        dim[idx] = {w, h};\n    }\n\n    vector<Rect> cur(n);\n    struct F { int x, y, w, h; };\n    vector<F> freeList;\n    freeList.reserve(2 * n + 2);\n    freeList.push_back({0, 0, W, W});\n\n    for (int idx : ord) {\n        int w = dim[idx].first;\n        int h = dim[idx].second;\n        int bestPos = -1;\n        ll bestScore = (1LL<<60);\n        int bw = w, bh = h;\n\n        for (int i = 0; i < (int)freeList.size(); ++i) {\n            const F& f = freeList[i];\n            if (f.w >= w && f.h >= h) {\n                ll sc = 1LL * (f.w - w) * (f.h - h);\n                if (sc < bestScore) { bestScore = sc; bestPos = i; bw = w; bh = h; }\n            }\n            if (f.w >= h && f.h >= w) {\n                ll sc = 1LL * (f.w - h) * (f.h - w);\n                if (sc < bestScore) { bestScore = sc; bestPos = i; bw = h; bh = w; }\n            }\n        }\n        if (bestPos == -1) return {};\n\n        F f = freeList[bestPos];\n        cur[idx] = {f.x, f.y, bw, bh};\n        freeList[bestPos] = freeList.back();\n        freeList.pop_back();\n\n        if (f.w > bw && f.h > bh) {\n            if (f.w - bw >= f.h - bh) {\n                freeList.push_back({f.x + bw, f.y, f.w - bw, f.h});\n                freeList.push_back({f.x, f.y + bh, bw, f.h - bh});\n            } else {\n                freeList.push_back({f.x + bw, f.y, f.w - bw, bh});\n                freeList.push_back({f.x, f.y + bh, f.w, f.h - bh});\n            }\n        } else if (f.w > bw) {\n            freeList.push_back({f.x + bw, f.y, f.w - bw, f.h});\n        } else if (f.h > bh) {\n            freeList.push_back({f.x, f.y + bh, f.w, f.h - bh});\n        }\n    }\n    return cur;\n}\n\n/* ---------- candidate generation for one day ---------- */\nstatic vector<Cand> gen_day_rects(int day, int want, mt19937& rng) {\n    const vector<ll>& area = a[day];\n    vector<Cand> pool;\n    pool.reserve(want + 20);\n\n    auto add = [&](vector<Rect> r) {\n        if (!r.empty() && (int)pool.size() < pool.capacity()) {\n            Cand c;\n            c.r = std::move(r);\n            c.mask.resize(G_WORDS);\n            build_mask(c.r, c.mask);\n            c.acost = area_cost(c.r, area);\n            pool.push_back(std::move(c));\n        }\n    };\n\n    // 1. randomised guillotine (the workhorse)\n    for (int trial = 0; trial < 400; ++trial) {\n        int order = (trial < 2) ? trial : 2;\n        int dim = trial % 5;\n        add(pack_guillotine(area, rng, order, dim));\n    }\n\n    // 2. full-height zero-deficit strips (if possible)\n    {\n        ll sum_min = 0;\n        for (int k = 0; k < N; ++k) sum_min += max(1LL, (area[k] + W - 1) / W);\n        if (sum_min <= W) {\n            vector<int> w(N);\n            for (int k = 0; k < N; ++k) w[k] = (int)max(1LL, (area[k] + W - 1) / W);\n            int rem = W - (int)sum_min;\n            ll S = accumulate(area.begin(), area.end(), 0LL);\n            for (int k = 0; k < N && rem > 0; ++k) {\n                int addw = (int)(rem * area[k] / S);\n                w[k] += addw; rem -= addw;\n            }\n            for (int k = N - 1; k >= 0 && rem > 0; --k) { w[k]++; rem--; }\n            vector<Rect> r(N);\n            int x = 0;\n            for (int k = 0; k < N; ++k) { r[k] = {x, 0, w[k], W}; x += w[k]; }\n            add(std::move(r));\n        }\n    }\n\n    // 3. greedy deficit-minimizing variable strips\n    {\n        vector<int> w(N, 1);\n        int rem = W - N;\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int i, int j){ return area[i] > area[j]; });\n        for (int k : ord) {\n            if (rem <= 0) break;\n            ll need = (area[k] + W - 1) / W;\n            int give = (int)min((ll)rem, max(0LL, need - 1));\n            w[k] += give; rem -= give;\n        }\n        for (int k : ord) {\n            if (rem <= 0) break;\n            int give = min(rem, W - w[k]);\n            w[k] += give; rem -= give;\n        }\n        vector<Rect> r(N);\n        int x = 0;\n        for (int k = 0; k < N; ++k) {\n            int h = (int)min((ll)W, (area[k] + w[k] - 1) / w[k]);\n            if (h < 1) h = 1;\n            r[k] = {x, 0, w[k], h};\n            x += w[k];\n        }\n        add(std::move(r));\n    }\n\n    // 4. a few purely random strips\n    for (int rep = 0; rep < 5; ++rep) {\n        vector<int> w(N, 1);\n        int rem = W - N;\n        for (int k = 0; k < N - 1 && rem > 0; ++k) {\n            int give = (int)(rng() % (rem + 1));\n            w[k] += give; rem -= give;\n        }\n        w[N - 1] += rem;\n        vector<Rect> r(N);\n        int x = 0;\n        for (int k = 0; k < N; ++k) {\n            int h = (int)min((ll)W, (area[k] + w[k] - 1) / w[k]);\n            if (h < 1) h = 1;\n            r[k] = {x, 0, w[k], h};\n            x += w[k];\n        }\n        add(std::move(r));\n    }\n\n    // ultimate safe fallback (should never be needed)\n    if (pool.empty()) {\n        vector<Rect> r(N);\n        int w = max(1, W / N);\n        int x = 0;\n        for (int k = 0; k < N; ++k) {\n            if (x + w > W) w = max(1, W - x);\n            int h = min(W, (int)((area[k] + w - 1) / w));\n            if (h < 1) h = 1;\n            r[k] = {x, 0, w, h};\n            x += w;\n        }\n        add(std::move(r));\n    }\n\n    if ((int)pool.size() <= want) return pool;\n\n    // keep best by area cost + diverse samples\n    vector<pair<ll,int>> scored;\n    scored.reserve(pool.size());\n    for (int i = 0; i < (int)pool.size(); ++i) scored.push_back({pool[i].acost, i});\n    sort(scored.begin(), scored.end());\n\n    vector<char> used(pool.size(), 0);\n    vector<Cand> res;\n    res.reserve(want);\n\n    for (int i = 0; i < (int)scored.size() && (int)res.size() < want/2; ++i) {\n        int idx = scored[i].second;\n        if (!used[idx]) {\n            used[idx] = 1;\n            res.push_back(std::move(pool[idx]));\n        }\n    }\n    int step = max(1, (int)scored.size() / (want - (int)res.size() + 1));\n    for (int i = 0; i < (int)scored.size() && (int)res.size() < want; i += step) {\n        int idx = scored[i].second;\n        if (!used[idx]) {\n            used[idx] = 1;\n            res.push_back(std::move(pool[idx]));\n        }\n    }\n    return res;\n}\n\n/* ---------- local search (greedy + random) ---------- */\nstatic void local_search(vector<int>& seq,\n                         const vector<vector<Cand>>& cands,\n                         vector<vector<vector<ll>>>& memo) {\n    auto get_trans = [&](int d, int i, int j) -> ll {\n        ll& v = memo[d][i][j];\n        if (v < 0) v = trans_cost(cands[d][i].mask, cands[d+1][j].mask);\n        return v;\n    };\n\n    mt19937 rng(1234567);\n\n    // greedy forward-backward passes\n    for (int rep = 0; rep < 3; ++rep) {\n        bool improved = false;\n        for (int d = 0; d < D; ++d) {\n            ll best = cands[d][seq[d]].acost;\n            if (d > 0) best += get_trans(d-1, seq[d-1], seq[d]);\n            if (d + 1 < D) best += get_trans(d, seq[d], seq[d+1]);\n            int best_j = seq[d];\n            for (int j = 0; j < (int)cands[d].size(); ++j) {\n                if (j == seq[d]) continue;\n                ll c = cands[d][j].acost;\n                if (d > 0) c += get_trans(d-1, seq[d-1], j);\n                if (d + 1 < D) c += get_trans(d, j, seq[d+1]);\n                if (c < best) { best = c; best_j = j; }\n            }\n            if (best_j != seq[d]) { seq[d] = best_j; improved = true; }\n        }\n        for (int d = D-1; d >= 0; --d) {\n            ll best = cands[d][seq[d]].acost;\n            if (d > 0) best += get_trans(d-1, seq[d-1], seq[d]);\n            if (d + 1 < D) best += get_trans(d, seq[d], seq[d+1]);\n            int best_j = seq[d];\n            for (int j = 0; j < (int)cands[d].size(); ++j) {\n                if (j == seq[d]) continue;\n                ll c = cands[d][j].acost;\n                if (d > 0) c += get_trans(d-1, seq[d-1], j);\n                if (d + 1 < D) c += get_trans(d, j, seq[d+1]);\n                if (c < best) { best = c; best_j = j; }\n            }\n            if (best_j != seq[d]) { seq[d] = best_j; improved = true; }\n        }\n        if (!improved) break;\n    }\n\n    // random perturbations\n    ll cur_cost = 0;\n    for (int d = 0; d < D; ++d) {\n        cur_cost += cands[d][seq[d]].acost;\n        if (d > 0) cur_cost += get_trans(d-1, seq[d-1], seq[d]);\n    }\n\n    for (int iter = 0; iter < 600; ++iter) {\n        int d = uniform_int_distribution<int>(0, D-1)(rng);\n        if (cands[d].size() <= 1) continue;\n        int j = uniform_int_distribution<int>(0, (int)cands[d].size() - 1)(rng);\n        if (j == seq[d]) continue;\n\n        ll old_part = cands[d][seq[d]].acost;\n        if (d > 0) old_part += get_trans(d-1, seq[d-1], seq[d]);\n        if (d + 1 < D) old_part += get_trans(d, seq[d], seq[d+1]);\n\n        ll new_part = cands[d][j].acost;\n        if (d > 0) new_part += get_trans(d-1, seq[d-1], j);\n        if (d + 1 < D) new_part += get_trans(d, j, seq[d+1]);\n\n        if (new_part < old_part) {\n            seq[d] = j;\n            cur_cost += new_part - old_part;\n        }\n    }\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> W >> D >> N)) return 0;\n    a.assign(D, vector<ll>(N));\n    for (int d = 0; d < D; ++d)\n        for (int k = 0; k < N; ++k)\n            cin >> a[d][k];\n\n    G_WORDS = (2 * W * (W - 1) + 63) >> 6;\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    /* ---- 1. strict fixed packing (absolute optimum, cost 0) ---- */\n    vector<ll> b(N, 0);\n    for (int k = 0; k < N; ++k)\n        for (int d = 0; d < D; ++d)\n            b[k] = max(b[k], a[d][k]);\n\n    {\n        vector<Rect> fixed;\n        for (int trial = 0; trial < 10000 && fixed.empty(); ++trial) {\n            int order = (trial < 2) ? trial : 2;\n            int dim = trial % 5;\n            fixed = pack_guillotine(b, rng, order, dim);\n        }\n        if (!fixed.empty()) {\n            for (int d = 0; d < D; ++d)\n                for (int k = 0; k < N; ++k) {\n                    const Rect& r = fixed[k];\n                    cout << r.y << ' ' << r.x << ' '\n                         << r.y + r.h << ' ' << r.x + r.w << '\\n';\n                }\n            return 0;\n        }\n    }\n\n    const int WANT = 40;\n    const int BEAM = 30;\n\n    /* ---- 2. generate daily candidates ---- */\n    vector<vector<Cand>> cands(D);\n    for (int d = 0; d < D; ++d) cands[d] = gen_day_rects(d, WANT, rng);\n\n    /* ---- 3. beam search ---- */\n    vector<vector<ll>> beam_cost(D, vector<ll>(BEAM, (1LL<<60)));\n    vector<vector<int>> beam_cidx(D, vector<int>(BEAM, -1));\n    vector<vector<int>> beam_parent(D, vector<int>(BEAM, -1));\n\n    int prev_size = min(BEAM, (int)cands[0].size());\n    for (int i = 0; i < prev_size; ++i) {\n        beam_cost[0][i] = cands[0][i].acost;\n        beam_cidx[0][i] = i;\n        beam_parent[0][i] = -1;\n    }\n\n    for (int d = 1; d < D; ++d) {\n        int C = cands[d].size();\n        vector<tuple<ll,int,int>> all;\n        all.reserve(C * prev_size);\n        for (int ci = 0; ci < C; ++ci) {\n            for (int pi = 0; pi < prev_size; ++pi) {\n                ll c = beam_cost[d-1][pi] + cands[d][ci].acost\n                     + trans_cost(cands[d-1][beam_cidx[d-1][pi]].mask, cands[d][ci].mask);\n                all.emplace_back(c, ci, pi);\n            }\n        }\n        sort(all.begin(), all.end(),\n             [](const auto& p, const auto& q){ return get<0>(p) < get<0>(q); });\n\n        vector<char> used_cand(C, 0);\n        int taken = 0;\n        for (auto& tup : all) {\n            if (taken >= BEAM) break;\n            int ci = get<1>(tup);\n            if (used_cand[ci]) continue;\n            used_cand[ci] = 1;\n            beam_cost[d][taken] = get<0>(tup);\n            beam_cidx[d][taken] = ci;\n            beam_parent[d][taken] = get<2>(tup);\n            ++taken;\n        }\n        prev_size = taken;\n    }\n\n    // traceback\n    vector<int> seq(D, -1);\n    int bidx = 0;\n    for (int d = D - 1; d >= 0; --d) {\n        seq[d] = beam_cidx[d][bidx];\n        bidx = beam_parent[d][bidx];\n    }\n\n    /* ---- 4. local search ---- */\n    vector<vector<vector<ll>>> memo(D-1);\n    for (int d = 0; d < D-1; ++d) {\n        memo[d].assign(cands[d].size(), vector<ll>(cands[d+1].size(), -1));\n    }\n    local_search(seq, cands, memo);\n\n    /* ---- 5. output ---- */\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const Rect& r = cands[d][seq[d]].r[k];\n            cout << r.y << ' ' << r.x << ' '\n                 << r.y + r.h << ' ' << r.x + r.w << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr int POS = (N - 2) * (N - 2);          // 49\nconstexpr int TOTAL_OPS = M * POS;               // 980\nconstexpr int CELLS = N * N;                     // 81\nconstexpr int MOD = 998244353;\nconstexpr int NOP = TOTAL_OPS;                   // sentinel for empty slot\n\nstruct Operation {\n    uint8_t cell[9];\n    uint32_t val[9];\n};\nOperation ops[TOTAL_OPS];\n\n// ------------------------------------------------------------------\n// fast board primitives\ninline ll delta_add(const uint32_t *board, int op) {\n    ll d = 0;\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[o.cell[i]];\n        uint32_t s = o.val[i];\n        d += (v >= MOD - s) ? (ll)s - MOD : s;\n    }\n    return d;\n}\n\ninline ll delta_remove(const uint32_t *board, int op) {\n    ll d = 0;\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[o.cell[i]];\n        uint32_t s = o.val[i];\n        d += (v < s) ? (ll)MOD - s : -(ll)s;\n    }\n    return d;\n}\n\ninline void apply_add(uint32_t *board, int op) {\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        int c = o.cell[i];\n        uint32_t v = board[c] + o.val[i];\n        if (v >= MOD) v -= MOD;\n        board[c] = v;\n    }\n}\n\ninline void apply_remove(uint32_t *board, int op) {\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        int c = o.cell[i];\n        uint32_t v = board[c];\n        uint32_t s = o.val[i];\n        board[c] = (v >= s) ? v - s : v + MOD - s;\n    }\n}\n\n// ------------------------------------------------------------------\nusing Board = array<uint32_t, CELLS>;\nusing Slots = array<int, K>;\n\n// exact steepest-ascent 1-opt hill climbing\nvoid hill_climb(Slots &sl, Board &board, ll &score) {\n    while (true) {\n        ll best_d = 0;\n        int best_i = -1, best_a = -1;\n        for (int i = 0; i < K; ++i) {\n            int old = sl[i];\n            ll d;\n            int a;\n            if (old == NOP) {\n                ll bd = 0;\n                int ba = NOP;\n                for (int op = 0; op < TOTAL_OPS; ++op) {\n                    ll dd = delta_add(board.data(), op);\n                    if (dd > bd) {\n                        bd = dd;\n                        ba = op;\n                    }\n                }\n                d = bd;\n                a = ba;\n            } else {\n                ll drem = delta_remove(board.data(), old);\n                apply_remove(board.data(), old);\n                ll bd = 0;\n                int ba = NOP;\n                for (int op = 0; op < TOTAL_OPS; ++op) {\n                    if (op == old) continue;\n                    ll dd = delta_add(board.data(), op);\n                    if (dd > bd) {\n                        bd = dd;\n                        ba = op;\n                    }\n                }\n                d = drem + bd;\n                a = ba;\n                apply_add(board.data(), old);\n            }\n            if (d > best_d) {\n                best_d = d;\n                best_i = i;\n                best_a = a;\n            }\n        }\n        if (best_d <= 0) break;\n        if (sl[best_i] != NOP) apply_remove(board.data(), sl[best_i]);\n        if (best_a != NOP) apply_add(board.data(), best_a);\n        sl[best_i] = best_a;\n        score += best_d;\n    }\n}\n\n// random 2-slot probing: sample many pairs, apply the best improving one\nbool probe2(Slots &sl, Board &board, ll &score, mt19937_64 &rng) {\n    ll best_d = 0;\n    int best_i = -1, best_j = -1, best_a = -1, best_b = -1;\n    for (int t = 0; t < 300; ++t) {\n        int i = (int)(rng() % K);\n        int j = (int)(rng() % (K - 1));\n        if (j >= i) ++j;\n        int a = (int)(rng() % (TOTAL_OPS + 1));\n        int b = (int)(rng() % (TOTAL_OPS + 1));\n        if (a == sl[i] && b == sl[j]) continue;\n\n        ll d = 0;\n        if (sl[i] != NOP) {\n            d += delta_remove(board.data(), sl[i]);\n            apply_remove(board.data(), sl[i]);\n        }\n        if (sl[j] != NOP) {\n            d += delta_remove(board.data(), sl[j]);\n            apply_remove(board.data(), sl[j]);\n        }\n        if (a != NOP) {\n            d += delta_add(board.data(), a);\n            apply_add(board.data(), a);\n        }\n        if (b != NOP) {\n            d += delta_add(board.data(), b);\n            apply_add(board.data(), b);\n        }\n\n        // revert board\n        if (b != NOP) apply_remove(board.data(), b);\n        if (a != NOP) apply_remove(board.data(), a);\n        if (sl[j] != NOP) apply_add(board.data(), sl[j]);\n        if (sl[i] != NOP) apply_add(board.data(), sl[i]);\n\n        if (d > best_d) {\n            best_d = d;\n            best_i = i; best_j = j; best_a = a; best_b = b;\n        }\n    }\n\n    if (best_d > 0) {\n        if (sl[best_i] != NOP) apply_remove(board.data(), sl[best_i]);\n        if (sl[best_j] != NOP) apply_remove(board.data(), sl[best_j]);\n        if (best_a != NOP) apply_add(board.data(), best_a);\n        if (best_b != NOP) apply_add(board.data(), best_b);\n        sl[best_i] = best_a;\n        sl[best_j] = best_b;\n        score += best_d;\n        return true;\n    }\n    return false;\n}\n\n// greedy reconstruction of empty slots\nvoid reconstruct(Slots &sl, Board &board, ll &score, bool randomized, mt19937_64 &rng) {\n    int filled = 0;\n    for (int i = 0; i < K; ++i) if (sl[i] != NOP) ++filled;\n    while (filled < K) {\n        int best_a = -1;\n        ll best_d = 0;\n        if (!randomized) {\n            for (int op = 0; op < TOTAL_OPS; ++op) {\n                ll d = delta_add(board.data(), op);\n                if (d > best_d) {\n                    best_d = d;\n                    best_a = op;\n                }\n            }\n            if (best_d <= 0) break;\n        } else {\n            // keep top 10 positive candidates in a tiny rolling buffer\n            pair<ll,int> top[10];\n            int tn = 0;\n            for (int op = 0; op < TOTAL_OPS; ++op) {\n                ll d = delta_add(board.data(), op);\n                if (d <= 0) continue;\n                if (tn < 10) {\n                    top[tn++] = {d, op};\n                } else {\n                    int mi = 0;\n                    for (int k = 1; k < 10; ++k)\n                        if (top[k].first < top[mi].first) mi = k;\n                    if (d > top[mi].first) top[mi] = {d, op};\n                }\n            }\n            if (tn == 0) break;\n            sort(top, top + tn,\n                 [](const pair<ll,int> &x, const pair<ll,int> &y){ return x.first > y.first; });\n            int t = min(5, tn);\n            int idx = (int)(rng() % (uint64_t)t);\n            best_a = top[idx].second;\n            best_d = top[idx].first;\n        }\n        int slot = -1;\n        for (int i = 0; i < K; ++i) if (sl[i] == NOP) { slot = i; break; }\n        if (slot == -1) break;\n        apply_add(board.data(), best_a);\n        sl[slot] = best_a;\n        score += best_d;\n        ++filled;\n    }\n}\n\n// ------------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k_input;\n    if (!(cin >> n >> m >> k_input)) return 0;\n\n    Board init_board{};\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            uint32_t x; cin >> x;\n            init_board[i * N + j] = x;\n        }\n\n    vector<vector<vector<uint32_t>>> stamp(M,\n        vector<vector<uint32_t>>(3, vector<uint32_t>(3)));\n    for (int s = 0; s < M; ++s)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamp[s][i][j];\n\n    int id = 0;\n    for (int s = 0; s < M; ++s)\n        for (int p = 0; p <= N - 3; ++p)\n            for (int q = 0; q <= N - 3; ++q) {\n                int t = 0;\n                for (int di = 0; di < 3; ++di)\n                    for (int dj = 0; dj < 3; ++dj) {\n                        ops[id].cell[t] = (p + di) * N + (q + dj);\n                        ops[id].val[t] = stamp[s][di][dj];\n                        ++t;\n                    }\n                ++id;\n            }\n\n    ll initial_score = 0;\n    for (int i = 0; i < CELLS; ++i) initial_score += init_board[i];\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.92;\n\n    Slots best; best.fill(NOP);\n    Board best_board = init_board;\n    ll best_score = initial_score;\n\n    // ----- diverse initial solutions -----\n    for (int attempt = 0; attempt < 10; ++attempt) {\n        Slots sl; Board bd; ll sc;\n        if (attempt == 0) {\n            sl.fill(NOP); bd = init_board; sc = initial_score;\n            reconstruct(sl, bd, sc, false, rng);\n        } else if (attempt < 6) {\n            sl.fill(NOP); bd = init_board; sc = initial_score;\n            reconstruct(sl, bd, sc, true, rng);\n        } else {\n            sl.fill(NOP); bd = init_board; sc = initial_score;\n            for (int i = 0; i < K; ++i) {\n                int a = (int)(rng() % TOTAL_OPS);\n                ll d = delta_add(bd.data(), a);\n                apply_add(bd.data(), a);\n                sl[i] = a;\n                sc += d;\n            }\n        }\n        hill_climb(sl, bd, sc);\n        while (probe2(sl, bd, sc, rng)) hill_climb(sl, bd, sc);\n        if (sc > best_score) {\n            best_score = sc;\n            best = sl;\n            best_board = bd;\n        }\n    }\n\n    // ----- fast Ruin-and-Recreate ILS -----\n    Slots cur = best;\n    Board cur_board = best_board;\n    ll cur_score = best_score;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        if (chrono::duration<double>(now - start).count() > TIME_LIMIT) break;\n\n        int used = 0;\n        for (int i = 0; i < K; ++i) if (cur[i] != NOP) ++used;\n        if (used == 0) {\n            cur = best;\n            cur_board = best_board;\n            cur_score = best_score;\n            continue;\n        }\n\n        // adaptive ruin size\n        int r;\n        int mode = (int)(rng() % 10);\n        if (mode < 5)       r = 1 + (int)(rng() % 3);\n        else if (mode < 8)  r = 2 + (int)(rng() % 5);\n        else                r = 6 + (int)(rng() % 10);\n        if (r > used) r = used;\n\n        // ruin: random removal\n        for (int t = 0; t < r; ++t) {\n            int idx;\n            do { idx = (int)(rng() % K); } while (cur[idx] == NOP);\n            int op = cur[idx];\n            cur_score += delta_remove(cur_board.data(), op);\n            apply_remove(cur_board.data(), op);\n            cur[idx] = NOP;\n        }\n\n        // reconstruct (deterministic most of the time, occasionally randomized)\n        bool use_rand = (rng() % 4 == 0);\n        reconstruct(cur, cur_board, cur_score, use_rand, rng);\n\n        // intensify: 1-opt hill climb + 2-opt probing\n        hill_climb(cur, cur_board, cur_score);\n        while (probe2(cur, cur_board, cur_score, rng))\n            hill_climb(cur, cur_board, cur_score);\n\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best = cur;\n            best_board = cur_board;\n        } else {\n            // strict acceptance: revert to best known for next kick\n            cur = best;\n            cur_board = best_board;\n            cur_score = best_score;\n        }\n    }\n\n    // final polish on absolute best\n    hill_climb(best, best_board, best_score);\n    while (probe2(best, best_board, best_score, rng))\n        hill_climb(best, best_board, best_score);\n\n    int L = 0;\n    for (int i = 0; i < K; ++i) if (best[i] != NOP) ++L;\n    cout << L << '\\n';\n    for (int i = 0; i < K; ++i) {\n        if (best[i] == NOP) continue;\n        int op = best[i];\n        int mm = op / POS;\n        int rest = op % POS;\n        int p = rest / 7;\n        int q = rest % 7;\n        cout << mm << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    int A[5][5];\n    for (int i = 0; i < 5; ++i)\n        for (int j = 0; j < 5; ++j)\n            cin >> A[i][j];\n\n    int grid[5][5];\n    memset(grid, -1, sizeof(grid));\n\n    int cr = 0, cc = 0;          // large crane\n    int hold = -1;               // held container\n    int dispatched[5] = {0};\n    int next_in[5] = {0};\n\n    vector<char> op0;\n    const int MAX_TURN = 10000;\n\n    auto need_of_row = [&](int r) -> int {\n        return 5 * r + dispatched[r];\n    };\n\n    auto move_toward = [&](int r, int c, int tr, int tc) -> char {\n        if (r == tr && c == tc) return '.';\n        if (r < tr) return 'D';\n        if (r > tr) return 'U';\n        if (c < tc) return 'R';\n        return 'L';\n    };\n\n    // find a buffer cell for a container destined for row 'dest_row'\n    auto find_buffer = [&](int dest_row) -> pair<int,int> {\n        int best = 1e9, br = -1, bc = -1;\n        // prefer same row, higher column (closer to dispatch gate)\n        for (int c = 3; c >= 1; --c) {\n            if (grid[dest_row][c] == -1) {\n                int d = abs(cr - dest_row) + abs(cc - c);\n                if (d < best) { best = d; br = dest_row; bc = c; }\n            }\n        }\n        if (br != -1) return {br, bc};\n        // same row full -> any row, still prefer higher columns\n        for (int c = 3; c >= 1; --c) {\n            for (int r = 0; r < 5; ++r) if (r != dest_row) {\n                if (grid[r][c] == -1) {\n                    int d = abs(cr - r) + abs(cc - c);\n                    // small penalty for wrong row\n                    d += abs(r - dest_row);\n                    if (d < best) { best = d; br = r; bc = c; }\n                }\n            }\n        }\n        if (br != -1) return {br, bc};\n        // emergency: any non-dispatch empty cell (may include col 0)\n        for (int c = 3; c >= 0; --c) {\n            for (int r = 0; r < 5; ++r) {\n                if (grid[r][c] == -1) {\n                    int d = abs(cr - r) + abs(cc - c);\n                    if (d < best) { best = d; br = r; bc = c; }\n                }\n            }\n        }\n        return {br, bc};\n    };\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        /* ---- 1. receiving ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (next_in[i] < 5 && grid[i][0] == -1) {\n                if (!(cr == i && cc == 0 && hold != -1)) {\n                    grid[i][0] = A[i][next_in[i]++];\n                }\n            }\n        }\n\n        char act = '.';\n\n        /* ---- 2. decide action ---- */\n        if (hold != -1) {\n            int row = hold / 5;\n            int need = need_of_row(row);\n            if (hold == need) {\n                // deliver\n                if (cr == row && cc == 4) {\n                    act = (grid[row][4] == -1) ? 'Q' : '.';\n                } else {\n                    act = move_toward(cr, cc, row, 4);\n                }\n            } else {\n                // buffer it, preferably near its destination\n                auto [tr, tc] = find_buffer(row);\n                if (tr == -1) {\n                    act = '.'; // should never happen\n                } else if (cr == tr && cc == tc) {\n                    act = 'Q';\n                } else {\n                    act = move_toward(cr, cc, tr, tc);\n                }\n            }\n        } else {\n            // empty-handed: look for a needed container already on the board\n            int tr = -1, tc = -1, best = 1e9;\n            for (int row = 0; row < 5; ++row) {\n                if (dispatched[row] >= 5) continue;\n                int need = need_of_row(row);\n                for (int r = 0; r < 5; ++r)\n                    for (int c = 0; c <= 3; ++c)\n                        if (grid[r][c] == need) {\n                            int d = abs(cr - r) + abs(cc - c);\n                            if (d < best) { best = d; tr = r; tc = c; }\n                        }\n            }\n\n            if (tr != -1) {\n                act = (cr == tr && cc == tc) ? 'P' : move_toward(cr, cc, tr, tc);\n            } else {\n                // nothing needed visible: \"dig\" at the most promising gate\n                int best_score = -1e9;\n                for (int i = 0; i < 5; ++i) {\n                    if (grid[i][0] == -1) continue; // nothing to pick here now\n                    int dist = abs(cr - i) + abs(cc - 0);\n                    int depth = 100; // large = not useful\n                    for (int d = 0; next_in[i] + d < 5; ++d) {\n                        int cid = A[i][next_in[i] + d];\n                        int r = cid / 5;\n                        if (cid == need_of_row(r)) {\n                            depth = d;\n                            break;\n                        }\n                    }\n                    int score;\n                    if (depth < 100) score = 10000 - depth * 100 - dist;\n                    else              score = -dist;\n                    if (score > best_score) {\n                        best_score = score;\n                        tr = i; tc = 0;\n                    }\n                }\n                if (tr != -1) {\n                    act = (cr == tr && cc == tc) ? 'P' : move_toward(cr, cc, tr, tc);\n                } else {\n                    act = '.';\n                }\n            }\n        }\n\n        /* ---- 3. apply action ---- */\n        if (act == 'P') {\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n        } else if (act == 'Q') {\n            grid[cr][cc] = hold;\n            hold = -1;\n        } else if (act == 'U') {\n            --cr;\n        } else if (act == 'D') {\n            ++cr;\n        } else if (act == 'L') {\n            --cc;\n        } else if (act == 'R') {\n            ++cc;\n        }\n        op0.push_back(act);\n\n        /* ---- 4. dispatch ---- */\n        for (int i = 0; i < 5; ++i) {\n            if (grid[i][4] != -1) {\n                ++dispatched[i];\n                grid[i][4] = -1;\n            }\n        }\n\n        bool done = true;\n        for (int i = 0; i < 5; ++i)\n            if (dispatched[i] < 5) done = false;\n        if (done) break;\n    }\n\n    size_t T = op0.size();\n    string s0(op0.begin(), op0.end());\n    cout << s0 << '\\n';\n    for (int k = 1; k < 5; ++k) {\n        cout << 'B';\n        for (size_t i = 1; i < T; ++i) cout << '.';\n        cout << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Result {\n    long long cost = 0;\n    vector<string> ops;\n    bool valid = false;\n};\n\n/* =============================================================\n   Deterministic helpers\n   ============================================================= */\nResult solve_given_order(const vector<vector<int>>& h,\n                         const vector<pair<int,int>>& order)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n    for (auto [tr, tc] : order) {\n        if (r == tr && c == tc) continue;\n        move_to(tr, tc);\n    }\n    while (load > 0) {\n        int tr = -1, tc = -1, best = 1e9;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] < 0) {\n                    int d = abs(r - i) + abs(c - j);\n                    if (d < best) { best = d; tr = i; tc = j; }\n                }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\nResult solve_greedy(const vector<vector<int>>& h) {\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n        int tr = -1, tc = -1, best = 1e9;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\nResult solve_lookahead(const vector<vector<int>>& h,\n                       const vector<vector<int>>& nearest_snk,\n                       const vector<vector<int>>& nearest_src,\n                       double w_empty, double w_loaded)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n        int tr = -1, tc = -1;\n        double best = 1e100;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        double sc = abs(r - i) + abs(c - j) + w_empty * nearest_snk[i][j];\n                        if (sc < best) { best = sc; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        double sc = abs(r - i) + abs(c - j) + w_loaded * nearest_src[i][j];\n                        if (sc < best) { best = sc; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\nResult solve_weighted(const vector<vector<int>>& h) {\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n        int tr = -1, tc = -1;\n        double best = -1.0;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        double sc = need[i][j] / double(abs(r - i) + abs(c - j) + 1);\n                        if (sc > best) { best = sc; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        double sc = (-need[i][j]) / double(abs(r - i) + abs(c - j) + 1);\n                        if (sc > best) { best = sc; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* =============================================================\n   Path generators\n   ============================================================= */\nvector<pair<int,int>> spiral_snake(int N, bool row_first) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    int r = 0, c = 0, dr = row_first ? 0 : 1, dc = row_first ? 1 : 0;\n    for (int step = 0; step < N * N; ++step) {\n        res.emplace_back(r, c);\n        vis[r][c] = true;\n        int nr = r + dr, nc = c + dc;\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N || vis[nr][nc]) {\n            int ndr = row_first ? dc : -dc;\n            int ndc = row_first ? -dr : dr;\n            dr = ndr; dc = ndc;\n            nr = r + dr; nc = c + dc;\n        }\n        r = nr; c = nc;\n    }\n    return res;\n}\n\nvector<pair<int,int>> diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int s = 0; s <= 2 * (N - 1); ++s) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = s - i;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        bool revflag = (s % 2 == (rev ? 0 : 1));\n        if (revflag) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nvector<pair<int,int>> anti_diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int d = -(N - 1); d <= N - 1; ++d) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = i - d;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        int parity = d & 1;\n        bool revflag = (parity == (rev ? 1 : 0));\n        if (revflag) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nstatic uint32_t spread(uint32_t x) {\n    x = (x | (x << 8)) & 0x00FF00FFu;\n    x = (x | (x << 4)) & 0x0F0F0F0Fu;\n    x = (x | (x << 2)) & 0x33333333u;\n    x = (x | (x << 1)) & 0x55555555u;\n    return x;\n}\nstatic uint32_t morton2(uint32_t x, uint32_t y) {\n    return spread(x) | (spread(y) << 1);\n}\nvector<pair<int,int>> zorder_snake(int N) {\n    vector<pair<int,int>> cells;\n    cells.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cells.emplace_back(i, j);\n    sort(cells.begin(), cells.end(),\n         [](const pair<int,int>& a, const pair<int,int>& b){\n             return morton2((uint32_t)a.first, (uint32_t)a.second)\n                  < morton2((uint32_t)b.first, (uint32_t)b.second);\n         });\n    return cells;\n}\n\n/* =============================================================\n   Fast random evaluator (pure NN + smart NN)\n   ============================================================= */\nstruct FastEval {\n    int N, n2;\n    const vector<vector<int>> &dist;\n    vector<int> need;\n    vector<int> pos, neg;\n    vector<int> pos_of, neg_of;\n    int load = 0, r = 0, c = 0, steps = 0;\n    long long cost = 0;\n    mt19937_64 rng;\n    bool smart;\n    double w_amt, w_pot;\n    const vector<int> *pot_src;\n    const vector<int> *pot_snk;\n\n    FastEval(const vector<vector<int>>& h,\n             const vector<vector<int>>& d,\n             uint64_t seed,\n             bool sm = false,\n             double wa = 0, double wp = 0,\n             const vector<int>* ps = nullptr,\n             const vector<int>* pn = nullptr)\n        : dist(d), rng(seed), smart(sm), w_amt(wa), w_pot(wp),\n          pot_src(ps), pot_snk(pn)\n    {\n        N = (int)h.size(); n2 = N * N;\n        need.resize(n2);\n        pos_of.assign(n2, -1); neg_of.assign(n2, -1);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j) {\n                int id = i * N + j;\n                need[id] = h[i][j];\n                if (need[id] > 0) {\n                    pos_of[id] = (int)pos.size();\n                    pos.push_back(id);\n                } else if (need[id] < 0) {\n                    neg_of[id] = (int)neg.size();\n                    neg.push_back(id);\n                }\n            }\n        process(0);\n    }\n\n    inline void remove_pos(int id) {\n        int p = pos_of[id], back = pos.back();\n        pos[p] = back; pos_of[back] = p;\n        pos.pop_back(); pos_of[id] = -1;\n    }\n    inline void remove_neg(int id) {\n        int p = neg_of[id], back = neg.back();\n        neg[p] = back; neg_of[back] = p;\n        neg.pop_back(); neg_of[id] = -1;\n    }\n    inline void process(int id) {\n        int v = need[id];\n        if (v > 0) {\n            cost += v; load += v; need[id] = 0;\n            remove_pos(id); ++steps;\n        } else if (v < 0 && load > 0) {\n            int d = min(load, -v);\n            cost += d; load -= d; need[id] += d; ++steps;\n            if (need[id] == 0) remove_neg(id);\n        }\n    }\n\n    inline int choose_target(bool want_pos) {\n        const auto& vec = want_pos ? pos : neg;\n        if (vec.empty()) return -1;\n        int cur = r * N + c;\n        if (!smart) {\n            int best = INT_MAX, ch = -1, cnt = 0;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                if (d < best) { best = d; ch = id; cnt = 1; }\n                else if (d == best) {\n                    ++cnt;\n                    if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                }\n            }\n            return ch;\n        } else {\n            double best = 1e100;\n            int ch = -1, cnt = 0;\n            const vector<int> *pot = want_pos ? pot_src : pot_snk;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                double amt = want_pos ? need[id] : -need[id];\n                double score = d - w_amt * amt + w_pot * (*pot)[id];\n                if (score < best - 1e-9) {\n                    best = score; ch = id; cnt = 1;\n                } else if (fabs(score - best) <= 1e-9) {\n                    ++cnt;\n                    if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                }\n            }\n            return ch;\n        }\n    }\n\n    inline void move_to(int tr, int tc, long long limit) {\n        while (r != tr || c != tc) {\n            bool mv_r = (r != tr), mv_c = (c != tc);\n            if (mv_r && mv_c) {\n                if (rng() & 1ULL) {\n                    if (r < tr) ++r; else --r;\n                } else {\n                    if (c < tc) ++c; else --c;\n                }\n            } else if (mv_r) {\n                if (r < tr) ++r; else --r;\n            } else {\n                if (c < tc) ++c; else --c;\n            }\n            cost += 100 + load;\n            ++steps;\n            process(r * N + c);\n            if (steps > 100000 || cost >= limit) {\n                steps = 100001;\n                return;\n            }\n        }\n    }\n\n    long long evaluate(long long limit) {\n        while (!pos.empty() || load > 0) {\n            int tid = (load == 0) ? choose_target(true) : choose_target(false);\n            if (tid == -1) break;\n            move_to(tid / N, tid % N, limit);\n            if (steps > 100000) return LLONG_MAX;\n        }\n        if (load != 0 || !pos.empty() || steps > 100000) return LLONG_MAX;\n        return cost;\n    }\n};\n\n/* =============================================================\n   Build full operation list from a FastEval seed\n   ============================================================= */\nResult build_fast(const vector<vector<int>>& h,\n                  const vector<vector<int>>& dist,\n                  uint64_t seed,\n                  bool smart,\n                  double w_amt, double w_pot,\n                  const vector<int>& pot_src,\n                  const vector<int>& pot_snk)\n{\n    int N = (int)h.size(), n2 = N * N;\n    vector<int> need(n2);\n    vector<int> pos, neg;\n    vector<int> pos_of(n2, -1), neg_of(n2, -1);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            need[id] = h[i][j];\n            if (need[id] > 0) {\n                pos_of[id] = (int)pos.size();\n                pos.push_back(id);\n            } else if (need[id] < 0) {\n                neg_of[id] = (int)neg.size();\n                neg.push_back(id);\n            }\n        }\n    int load = 0, r = 0, c = 0, steps = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n    mt19937_64 rng(seed);\n\n    auto remove_pos = [&](int id) {\n        int p = pos_of[id], back = pos.back();\n        pos[p] = back; pos_of[back] = p;\n        pos.pop_back(); pos_of[id] = -1;\n    };\n    auto remove_neg = [&](int id) {\n        int p = neg_of[id], back = neg.back();\n        neg[p] = back; neg_of[back] = p;\n        neg.pop_back(); neg_of[id] = -1;\n    };\n    auto process = [&](int id) {\n        int v = need[id];\n        if (v > 0) {\n            ops.push_back(\"+\" + to_string(v));\n            cost += v; load += v; need[id] = 0;\n            remove_pos(id); ++steps;\n        } else if (v < 0 && load > 0) {\n            int d = min(load, -v);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d; load -= d; need[id] += d; ++steps;\n            if (need[id] == 0) remove_neg(id);\n        }\n    };\n    auto choose_target = [&](bool want_pos) -> int {\n        const auto& vec = want_pos ? pos : neg;\n        if (vec.empty()) return -1;\n        int cur = r * N + c;\n        if (!smart) {\n            int best = INT_MAX, ch = -1, cnt = 0;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                if (d < best) { best = d; ch = id; cnt = 1; }\n                else if (d == best) {\n                    ++cnt;\n                    if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                }\n            }\n            return ch;\n        } else {\n            double best = 1e100;\n            int ch = -1, cnt = 0;\n            const vector<int> *pot = want_pos ? &pot_src : &pot_snk;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                double amt = want_pos ? need[id] : -need[id];\n                double score = d - w_amt * amt + w_pot * (*pot)[id];\n                if (score < best - 1e-9) {\n                    best = score; ch = id; cnt = 1;\n                } else if (fabs(score - best) <= 1e-9) {\n                    ++cnt;\n                    if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                }\n            }\n            return ch;\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            bool mv_r = (r != tr), mv_c = (c != tc);\n            if (mv_r && mv_c) {\n                if (rng() & 1ULL) {\n                    if (r < tr) { ops.push_back(\"D\"); ++r; }\n                    else        { ops.push_back(\"U\"); --r; }\n                } else {\n                    if (c < tc) { ops.push_back(\"R\"); ++c; }\n                    else        { ops.push_back(\"L\"); --c; }\n                }\n            } else if (mv_r) {\n                if (r < tr) { ops.push_back(\"D\"); ++r; }\n                else        { ops.push_back(\"U\"); --r; }\n            } else {\n                if (c < tc) { ops.push_back(\"R\"); ++c; }\n                else        { ops.push_back(\"L\"); --c; }\n            }\n            cost += 100 + load;\n            ++steps;\n            process(r * N + c);\n            if (steps > 100000) return;\n        }\n    };\n\n    process(0);\n    while (!pos.empty() || load > 0) {\n        int tid = (load == 0) ? choose_target(true) : choose_target(false);\n        if (tid == -1) break;\n        move_to(tid / N, tid % N);\n        if (steps > 100000) return Result{0, {}, false};\n    }\n    bool ok = (load == 0 && pos.empty());\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* =============================================================\n   Main\n   ============================================================= */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&](){\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    int N2 = N * N;\n    vector<vector<int>> dist(N2, vector<int>(N2));\n    for (int i = 0; i < N2; ++i) {\n        int r = i / N, c = i % N;\n        for (int j = 0; j < N2; ++j) {\n            int rr = j / N, cc = j % N;\n            dist[i][j] = abs(r - rr) + abs(c - cc);\n        }\n    }\n\n    vector<vector<int>> nearest_src(N, vector<int>(N, INT_MAX));\n    vector<vector<int>> nearest_snk(N, vector<int>(N, INT_MAX));\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {\n        if (h[i][j] > 0) {\n            for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y)\n                nearest_snk[x][y] = min(nearest_snk[x][y], abs(x - i) + abs(y - j));\n        } else if (h[i][j] < 0) {\n            for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y)\n                nearest_src[x][y] = min(nearest_src[x][y], abs(x - i) + abs(y - j));\n        }\n    }\n\n    /* flat copies for the fast evaluator */\n    vector<int> pot_src(N2, INT_MAX), pot_snk(N2, INT_MAX);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            pot_src[i * N + j] = nearest_src[i][j];\n            pot_snk[i * N + j] = nearest_snk[i][j];\n        }\n\n    Result best; best.valid = false; best.cost = LLONG_MAX;\n    auto upd = [&](const Result& res){\n        if (res.valid && res.cost < best.cost) best = res;\n    };\n\n    /* --- row / column snakes --- */\n    vector<pair<int,int>> ord;\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else            for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    ord.clear();\n    for (int i = N - 1; i >= 0; --i) {\n        if ((N - 1 - i) % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else                      for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    ord.clear();\n    for (int j = 0; j < N; ++j) {\n        if (j % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else            for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    ord.clear();\n    for (int j = N - 1; j >= 0; --j) {\n        if ((N - 1 - j) % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else                      for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    /* --- spirals / diagonals / z-order --- */\n    upd(solve_given_order(h, spiral_snake(N, true)));\n    upd(solve_given_order(h, spiral_snake(N, false)));\n    upd(solve_given_order(h, diagonal_snake(N, false)));\n    upd(solve_given_order(h, diagonal_snake(N, true)));\n    upd(solve_given_order(h, anti_diagonal_snake(N, false)));\n    upd(solve_given_order(h, anti_diagonal_snake(N, true)));\n    auto z = zorder_snake(N);\n    upd(solve_given_order(h, z));\n    std::reverse(z.begin(), z.end());\n    upd(solve_given_order(h, z));\n\n    /* --- deterministic greedy variants --- */\n    upd(solve_greedy(h));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.0, 0.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.5, 0.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.0, 0.5));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 1.0, 1.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 2.0, 2.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 3.0, 0.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.0, 3.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 1.0, 2.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 2.0, 1.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 5.0, 0.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.0, 5.0));\n    upd(solve_weighted(h));\n\n    /* --- random greedy search (time-guarded) --- */\n    long long prune = best.valid ? best.cost : LLONG_MAX;\n    uint64_t best_seed = 0;\n    bool best_smart = false;\n    double best_wa = 0, best_wp = 0;\n\n    mt19937_64 param_rng(20240518u);\n    const vector<double> w_vals = {0.0, 0.5, 1.0, 2.0, 4.0};\n    uniform_int_distribution<int> widx(0, (int)w_vals.size() - 1);\n\n    for (int s = 0; elapsed() < 1.85; ++s) {\n        uint64_t seed = 1234567ULL + (uint64_t)s;\n        if (s % 2 == 0) {\n            FastEval eval(h, dist, seed, false);\n            long long c = eval.evaluate(prune);\n            if (c < prune) {\n                prune = c;\n                best_seed = seed;\n                best_smart = false;\n            }\n        } else {\n            double wa = w_vals[widx(param_rng)];\n            double wp = w_vals[widx(param_rng)];\n            FastEval eval(h, dist, seed, true, wa, wp, &pot_src, &pot_snk);\n            long long c = eval.evaluate(prune);\n            if (c < prune) {\n                prune = c;\n                best_seed = seed;\n                best_smart = true;\n                best_wa = wa;\n                best_wp = wp;\n            }\n        }\n    }\n\n    if (prune < (best.valid ? best.cost : LLONG_MAX)) {\n        upd(build_fast(h, dist, best_seed, best_smart, best_wa, best_wp, pot_src, pot_snk));\n    }\n\n    if (!best.valid) best = solve_greedy(h);\n    for (auto &s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int S = 2 * N * (N - 1); // 60 seeds\nconstexpr int P = N * N;            // 36 cells\n\nint X[S][M];\n\n// grid topology\nint nbr[P][4];\nint nbr_cnt[P];\nint deg[P];\nbool is_corner_cell[P];\nint cells_by_deg[P];\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- pre\u2011compute grid topology -----\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            int k = 0;\n            if (r > 0)     nbr[id][k++] = (r - 1) * N + c;\n            if (r < N - 1) nbr[id][k++] = (r + 1) * N + c;\n            if (c > 0)     nbr[id][k++] = r * N + (c - 1);\n            if (c < N - 1) nbr[id][k++] = r * N + (c + 1);\n            nbr_cnt[id] = k;\n            deg[id] = k;\n            is_corner_cell[id] = (k == 2);\n        }\n    }\n    iota(cells_by_deg, cells_by_deg + P, 0);\n    sort(cells_by_deg, cells_by_deg + P,\n         [&](int a, int b){ return deg[a] > deg[b]; });\n\n    int N_in, M_in, T;\n    while (cin >> N_in >> M_in >> T) {\n        for (int i = 0; i < S; ++i)\n            for (int l = 0; l < M; ++l)\n                cin >> X[i][l];\n\n        for (int turn = 0; turn < T; ++turn) {\n            // ---- 1. statistics per coordinate ----\n            int mx[M];\n            fill(mx, mx + M, 0);\n            for (int i = 0; i < S; ++i)\n                for (int l = 0; l < M; ++l)\n                    if (X[i][l] > mx[l]) mx[l] = X[i][l];\n\n            int V[S];\n            int mask[S];\n            int cnt_all[M] = {0};\n            for (int i = 0; i < S; ++i) {\n                int s = 0, m = 0;\n                for (int l = 0; l < M; ++l) {\n                    s += X[i][l];\n                    if (X[i][l] == mx[l]) {\n                        m |= (1 << l);\n                        ++cnt_all[l];\n                    }\n                }\n                V[i] = s;\n                mask[i] = m;\n            }\n\n            // ---- 2. seed scores ----\n            int rare_bonus[S] = {0};\n            for (int i = 0; i < S; ++i) {\n                int rb = 0;\n                for (int l = 0; l < M; ++l)\n                    if ((mask[i] >> l & 1) && cnt_all[l] <= 2)\n                        ++rb;\n                rare_bonus[i] = rb * 5000;          // strong but not overwhelming\n            }\n\n            int score[S];\n            for (int i = 0; i < S; ++i)\n                score[i] = V[i] * 10 + __builtin_popcount(mask[i]) * 100 + rare_bonus[i];\n\n            // ---- 3. select 36 seeds (coverage guaranteed) ----\n            bool in_sel[S] = {false};\n            int sel[P];\n            int sel_cnt = 0;\n\n            // force unique carriers\n            for (int l = 0; l < M; ++l) {\n                if (cnt_all[l] == 1) {\n                    for (int i = 0; i < S; ++i)\n                        if ((mask[i] >> l & 1) && !in_sel[i]) {\n                            in_sel[i] = true;\n                            sel[sel_cnt++] = i;\n                            break;\n                        }\n                }\n            }\n\n            // fill rest by score\n            vector<pair<int,int>> cand;\n            for (int i = 0; i < S; ++i)\n                if (!in_sel[i]) cand.emplace_back(score[i], i);\n            sort(cand.begin(), cand.end(),\n                 [&](const auto& a, const auto& b){\n                     if (a.first != b.first) return a.first > b.first;\n                     return V[a.second] > V[b.second];\n                 });\n            for (auto &p : cand) {\n                if (sel_cnt == P) break;\n                in_sel[p.second] = true;\n                sel[sel_cnt++] = p.second;\n            }\n\n            // repair: ensure every coordinate is covered\n            auto recompute_covered = [&]() {\n                int covered = 0;\n                for (int s = 0; s < sel_cnt; ++s) covered |= mask[sel[s]];\n                return covered;\n            };\n            const int FULL = (1 << M) - 1;\n            int covered = recompute_covered();\n\n            while (covered != FULL) {\n                int miss = FULL & ~covered;\n                int l = __builtin_ctz(miss);\n\n                // best unscored carrier of l\n                int best_i = -1, best_sc = -1;\n                for (int i = 0; i < S; ++i)\n                    if (!in_sel[i] && (mask[i] >> l & 1))\n                        if (score[i] > best_sc) { best_sc = score[i]; best_i = i; }\n\n                if (best_i == -1) break; // should never happen\n\n                // selected\u2011carrier counts per coordinate\n                int sel_car[M] = {0};\n                for (int s = 0; s < sel_cnt; ++s)\n                    for (int ll = 0; ll < M; ++ll)\n                        if (mask[sel[s]] >> ll & 1) ++sel_car[ll];\n\n                // drop worst seed that is not a unique pool carrier\n                // and not the sole selected carrier of any coordinate\n                int worst_pos = -1, worst_sc = INT_MAX;\n                for (int s = 0; s < sel_cnt; ++s) {\n                    int i = sel[s];\n                    bool bad = false;\n                    for (int ll = 0; ll < M; ++ll) {\n                        if ((mask[i] >> ll & 1) && cnt_all[ll] == 1) { bad = true; break; }\n                        if ((mask[i] >> ll & 1) && sel_car[ll] == 1) { bad = true; break; }\n                    }\n                    if (!bad && score[i] < worst_sc) {\n                        worst_sc = score[i];\n                        worst_pos = s;\n                    }\n                }\n                if (worst_pos == -1) { // fallback: any non\u2011unique\u2011in\u2011pool seed\n                    for (int s = 0; s < sel_cnt; ++s) {\n                        int i = sel[s];\n                        bool unique = false;\n                        for (int ll = 0; ll < M; ++ll)\n                            if ((mask[i] >> ll & 1) && cnt_all[ll] == 1) { unique = true; break; }\n                        if (!unique && score[i] < worst_sc) {\n                            worst_sc = score[i];\n                            worst_pos = s;\n                        }\n                    }\n                }\n                if (worst_pos == -1) break; // safety\n\n                in_sel[sel[worst_pos]] = false;\n                in_sel[best_i] = true;\n                sel[worst_pos] = best_i;\n                covered = recompute_covered();\n            }\n\n            // ---- 4. which selected seeds are critical? ----\n            bool is_crit[P];\n            for (int s = 0; s < P; ++s) {\n                int i = sel[s];\n                bool c = false;\n                for (int l = 0; l < M; ++l)\n                    if ((mask[i] >> l & 1) && cnt_all[l] <= 2) { c = true; break; }\n                is_crit[s] = c;\n            }\n\n            // ---- 5. pair potential matrix ----\n            static int pot[P][P];\n            for (int i = 0; i < P; ++i) {\n                int a = sel[i];\n                for (int j = i + 1; j < P; ++j) {\n                    int b = sel[j];\n                    int s = 0;\n                    for (int l = 0; l < M; ++l) s += max(X[a][l], X[b][l]);\n                    pot[i][j] = pot[j][i] = s;\n                }\n            }\n\n            // ---- 6. greedy initial placement (respect corner ban) ----\n            int pos2idx[P];\n            for (int i = 0; i < P; ++i) pos2idx[i] = -1;\n            bool used_seed[P] = {false};\n\n            for (int ci = 0; ci < P; ++ci) {\n                int cell = cells_by_deg[ci];\n                bool corner = is_corner_cell[cell];\n                int best_s = -1;\n                int best_gain = -1;\n                int best_sc = -1;\n                for (int s = 0; s < P; ++s) if (!used_seed[s]) {\n                    if (corner && is_crit[s]) continue;\n                    int gain = 0;\n                    for (int k = 0; k < nbr_cnt[cell]; ++k) {\n                        int nb = nbr[cell][k];\n                        if (pos2idx[nb] != -1) gain += pot[s][pos2idx[nb]];\n                    }\n                    int sc = score[sel[s]];\n                    if (gain > best_gain || (gain == best_gain && sc > best_sc)) {\n                        best_gain = gain;\n                        best_s = s;\n                        best_sc = sc;\n                    }\n                }\n                if (best_s == -1) { // safety fallback\n                    for (int s = 0; s < P; ++s)\n                        if (!used_seed[s]) { best_s = s; break; }\n                }\n                used_seed[best_s] = true;\n                pos2idx[cell] = best_s;\n            }\n\n            // ---- 7. hill climbing (best improvement) ----\n            for (int it = 0; it < 200; ++it) {\n                int best_delta = 0;\n                int best_a = -1, best_b = -1;\n                for (int a = 0; a < P; ++a) {\n                    int ia = pos2idx[a];\n                    for (int b = a + 1; b < P; ++b) {\n                        int ib = pos2idx[b];\n                        if (is_crit[ia] && is_corner_cell[b]) continue;\n                        if (is_crit[ib] && is_corner_cell[a]) continue;\n\n                        int delta = 0;\n                        for (int k = 0; k < nbr_cnt[a]; ++k) {\n                            int w = nbr[a][k];\n                            if (w == b) continue;\n                            delta += pot[ib][pos2idx[w]] - pot[ia][pos2idx[w]];\n                        }\n                        for (int k = 0; k < nbr_cnt[b]; ++k) {\n                            int w = nbr[b][k];\n                            if (w == a) continue;\n                            delta += pot[ia][pos2idx[w]] - pot[ib][pos2idx[w]];\n                        }\n                        if (delta > best_delta) {\n                            best_delta = delta;\n                            best_a = a;\n                            best_b = b;\n                        }\n                    }\n                }\n                if (best_delta > 0)\n                    swap(pos2idx[best_a], pos2idx[best_b]);\n                else\n                    break;\n            }\n\n            // ---- 8. output ----\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (c) cout << ' ';\n                    int cell = r * N + c;\n                    cout << sel[pos2idx[cell]];\n                }\n                cout << '\\n';\n            }\n            cout.flush();\n\n            // ---- 9. read next generation ----\n            for (int i = 0; i < S; ++i)\n                for (int l = 0; l < M; ++l)\n                    cin >> X[i][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<char> has_src;   // size N*N\nvector<char> need_tgt;  // size N*N\ninline int ID(int r, int c) { return r * N + c; }\n\nvector<int> len;\nint reach_id[15][30][30][4]; // -1 if out of bounds\nvector<int> cur_dir;\nvector<char> holding;\nint cur_r, cur_c;\n\nvector<string> ans;\nint hold_cnt = 0;\nint rem_src = 0;\nint rem_tgt = 0;\n\nconst int dr[4] = {0, 1, 0, -1};\nconst int dc[4] = {1, 0, -1, 0};\n\ninline int rotcost(int a, int b) {\n    int d = abs(a - b);\n    return min(d, 4 - d);\n}\ninline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstruct Batch {\n    int size = 0;\n    int turns = 0;\n    int dist = 0;\n    int r = -1, c = -1;\n    int ndir[15];\n    int tr[15], tc[15];\n    Batch() {\n        memset(ndir, -1, sizeof(ndir));\n        memset(tr, -1, sizeof(tr));\n        memset(tc, -1, sizeof(tc));\n    }\n};\n\nbool isBetter(int sz, int turn, int dst, const Batch& b) {\n    if (b.size == 0) return true;\n    long long lhs = 1LL * sz * b.turns;\n    long long rhs = 1LL * b.size * turn;\n    if (lhs != rhs) return lhs > rhs;\n    if (sz != b.size) return sz > b.size;\n    if (turn != b.turns) return turn < b.turns;\n    return dst < b.dist;\n}\n\nBatch find_batch() {\n    Batch best;\n    int ndir[15];\n    int ncost[15];\n    int ntr[15], ntc[15];\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int dist = manhattan(cur_r, cur_c, r, c);\n            int cnt_le1 = 0; // cost 0 or 1\n            int cnt_eq2 = 0; // cost 2\n            \n            for (int i = 1; i < V; ++i) {\n                ndir[i] = -1;\n                if (holding[i]) {\n                    if (rem_tgt == 0) continue;\n                } else {\n                    if (rem_src == 0) continue;\n                }\n                for (int d = 0; d < 4; ++d) {\n                    int nid = reach_id[i][r][c][d];\n                    if (nid == -1) continue;\n                    if (holding[i] ? !need_tgt[nid] : !has_src[nid]) continue;\n                    int cost = rotcost(cur_dir[i], d);\n                    if (ndir[i] == -1 || cost < ncost[i]) {\n                        ndir[i] = d;\n                        ncost[i] = cost;\n                        ntr[i] = nid / N;\n                        ntc[i] = nid % N;\n                    }\n                }\n                if (ndir[i] != -1) {\n                    if (ncost[i] <= 1) ++cnt_le1;\n                    else ++cnt_eq2;\n                }\n            }\n            \n            auto upd = [&](int L, int sz, int turns) {\n                if (sz == 0) return;\n                if (isBetter(sz, turns, dist, best)) {\n                    best.size = sz;\n                    best.turns = turns;\n                    best.dist = dist;\n                    best.r = r;\n                    best.c = c;\n                    for (int i = 1; i < V; ++i) {\n                        if (ndir[i] != -1 && ncost[i] <= L) {\n                            best.ndir[i] = ndir[i];\n                            best.tr[i] = ntr[i];\n                            best.tc[i] = ntc[i];\n                        } else {\n                            best.ndir[i] = -1;\n                        }\n                    }\n                }\n            };\n            \n            if (dist >= 2) {\n                upd(2, cnt_le1 + cnt_eq2, dist);\n            } else {\n                // dist 0 or 1\n                upd(1, cnt_le1, 1);\n                upd(2, cnt_le1 + cnt_eq2, 2);\n            }\n        }\n    }\n    return best;\n}\n\nvoid execute_batch(const Batch& b) {\n    int travel = b.turns;\n    for (int step = 0; step < travel; ++step) {\n        char move = '.';\n        if (cur_r < b.r)       { move = 'D'; ++cur_r; }\n        else if (cur_r > b.r)  { move = 'U'; --cur_r; }\n        else if (cur_c < b.c)  { move = 'R'; ++cur_c; }\n        else if (cur_c > b.c)  { move = 'L'; --cur_c; }\n\n        string S(2 * V, '.');\n        S[0] = move;\n\n        for (int i = 1; i < V; ++i) {\n            if (b.ndir[i] == -1) continue;\n            if (cur_dir[i] == b.ndir[i]) continue;\n            int diff = (b.ndir[i] - cur_dir[i] + 4) % 4;\n            if (diff == 1) {\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            } else if (diff == 3) {\n                S[i] = 'L';\n                cur_dir[i] = (cur_dir[i] + 3) & 3;\n            } else { // diff == 2\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            }\n        }\n\n        if (step == travel - 1) {\n            for (int i = 1; i < V; ++i) {\n                if (b.ndir[i] == -1) continue;\n                S[V + i] = 'P';\n                if (holding[i]) {\n                    need_tgt[ID(b.tr[i], b.tc[i])] = 0;\n                    holding[i] = 0;\n                    --hold_cnt;\n                    --rem_tgt;\n                } else {\n                    has_src[ID(b.tr[i], b.tc[i])] = 0;\n                    holding[i] = 1;\n                    ++hold_cnt;\n                    --rem_src;\n                }\n            }\n        }\n        ans.push_back(S);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n    for (int i = 0; i < N; ++i) cin >> t[i];\n\n    has_src.assign(N * N, 0);\n    need_tgt.assign(N * N, 0);\n    long long sumr = 0, sumc = 0, work = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s[i][j] == '1' && t[i][j] == '1') {\n                // already satisfied\n            } else if (s[i][j] == '1') {\n                has_src[ID(i, j)] = 1;\n                ++rem_src;\n                sumr += i; sumc += j; ++work;\n            } else if (t[i][j] == '1') {\n                need_tgt[ID(i, j)] = 1;\n                ++rem_tgt;\n                sumr += i; sumc += j; ++work;\n            }\n        }\n    }\n\n    /*--- design the arm (star with distinct lengths 1..V-1) ---*/\n    cout << V << '\\n';\n    len.assign(V, 0);\n    for (int u = 1; u < V; ++u) {\n        int L = u;\n        if (L > N - 1) L = N - 1;\n        len[u] = L;\n        cout << 0 << ' ' << L << '\\n';\n    }\n\n    if (work > 0) {\n        cur_r = int(sumr / work);\n        cur_c = int(sumc / work);\n    } else {\n        cur_r = N / 2;\n        cur_c = N / 2;\n    }\n    cur_r = max(0, min(N - 1, cur_r));\n    cur_c = max(0, min(N - 1, cur_c));\n    cout << cur_r << ' ' << cur_c << '\\n';\n\n    cur_dir.assign(V, 0);\n    holding.assign(V, 0);\n    ans.reserve(200000);\n\n    /*--- precompute reach_id ---*/\n    memset(reach_id, -1, sizeof(reach_id));\n    for (int i = 1; i < V; ++i) {\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d] * len[i];\n                    int nc = c + dc[d] * len[i];\n                    if (0 <= nr && nr < N && 0 <= nc && nc < N) {\n                        reach_id[i][r][c][d] = ID(nr, nc);\n                    }\n                }\n            }\n        }\n    }\n\n    /*--- main greedy loop ---*/\n    while (rem_src > 0 || hold_cnt > 0) {\n        Batch b = find_batch();\n        if (b.size > 0) {\n            execute_batch(b);\n        } else {\n            // Fallback: move toward nearest remaining work\n            int tr = -1, tc = -1, bestd = 1e9;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (has_src[ID(i, j)] || need_tgt[ID(i, j)]) {\n                        int d = manhattan(cur_r, cur_c, i, j);\n                        if (d < bestd) {\n                            bestd = d;\n                            tr = i; tc = j;\n                        }\n                    }\n                }\n            }\n            if (tr == -1) break;\n            char move = '.';\n            if (cur_r < tr) { move = 'D'; ++cur_r; }\n            else if (cur_r > tr) { move = 'U'; --cur_r; }\n            else if (cur_c < tc) { move = 'R'; ++cur_c; }\n            else if (cur_c > tc) { move = 'L'; --cur_c; }\n            string S(2 * V, '.');\n            S[0] = move;\n            ans.push_back(S);\n        }\n    }\n\n    for (const string& str : ans) cout << str << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    int w;          // +1 = mackerel, -1 = sardine\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    const int MAXC = 100000;\n    int N;\n    if (!(cin >> N)) return 0;\n    const int M = 2 * N;\n\n    vector<Point> pts(M);\n    unordered_set<unsigned long long> occ;\n    occ.reserve(M * 2);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n        pts[i].w = +1;\n        occ.insert(((unsigned long long)pts[i].x << 32) | (unsigned long long)pts[i].y);\n    }\n    for (int i = N; i < M; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n        pts[i].w = -1;\n        occ.insert(((unsigned long long)pts[i].x << 32) | (unsigned long long)pts[i].y);\n    }\n\n    /* coordinate compression */\n    vector<int> ux, uy;\n    ux.reserve(M);\n    uy.reserve(M);\n    for (auto &p : pts) {\n        ux.push_back(p.x);\n        uy.push_back(p.y);\n    }\n    sort(ux.begin(), ux.end());\n    ux.erase(unique(ux.begin(), ux.end()), ux.end());\n    sort(uy.begin(), uy.end());\n    uy.erase(unique(uy.begin(), uy.end()), uy.end());\n    const int X = (int)ux.size();\n    const int Y = (int)uy.size();\n\n    unordered_map<int,int> yid;\n    yid.reserve(Y * 2);\n    for (int i = 0; i < Y; ++i) yid[uy[i]] = i;\n\n    vector<int> py_id(M);\n    for (int i = 0; i < M; ++i) py_id[i] = yid[pts[i].y];\n\n    /* sort points by x */\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(),\n         [&](int a, int b){ return pts[a].x < pts[b].x; });\n    vector<int> spx(M), spy(M), spw(M);\n    for (int i = 0; i < M; ++i) {\n        spx[i] = pts[ord[i]].x;\n        spy[i] = py_id[ord[i]];\n        spw[i] = pts[ord[i]].w;\n    }\n\n    /* reusable buffer */\n    vector<int> ysum(Y);\n\n    auto eval_interval = [&](int x1, int x2, int &out_y1, int &out_y2) -> int {\n        memset(ysum.data(), 0, Y * sizeof(int));\n        int l = lower_bound(spx.begin(), spx.end(), x1) - spx.begin();\n        int r = upper_bound(spx.begin(), spx.end(), x2) - spx.begin();\n        for (int i = l; i < r; ++i) ysum[spy[i]] += spw[i];\n\n        int best = 0, cur = 0;\n        int best_l = 0, best_r = -1;\n        int cur_l = 0;\n        for (int i = 0; i < Y; ++i) {\n            if (cur + ysum[i] < ysum[i]) {\n                cur = ysum[i];\n                cur_l = i;\n            } else {\n                cur += ysum[i];\n            }\n            if (cur > best) {\n                best = cur;\n                best_l = cur_l;\n                best_r = i;\n            }\n        }\n        if (best <= 0) {\n            out_y1 = 0; out_y2 = 0;\n            return 0;\n        }\n        out_y1 = uy[best_l];\n        out_y2 = uy[best_r];\n        return best;\n    };\n\n    auto eval_rect = [&](const Rect &r) -> int {\n        int a = 0, b = 0;\n        for (auto &p : pts) {\n            if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) {\n                if (p.w == 1) ++a; else ++b;\n            }\n        }\n        return a - b;\n    };\n\n    /* fallback empty 1x1 */\n    Rect best_rect{0, 0, 1, 1};\n    int best_score = 0;\n    {\n        mt19937 rng(123456789);\n        uniform_int_distribution<int> dx(0, MAXC - 1);\n        uniform_int_distribution<int> dy(0, MAXC - 1);\n        for (int t = 0; t < 20000; ++t) {\n            int x = dx(rng), y = dy(rng);\n            unsigned long long c1 = ((unsigned long long)x << 32) | (unsigned long long)y;\n            unsigned long long c2 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)y;\n            unsigned long long c3 = ((unsigned long long)x << 32) | (unsigned long long)(y + 1);\n            unsigned long long c4 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)(y + 1);\n            if (!occ.count(c1) && !occ.count(c2) && !occ.count(c3) && !occ.count(c4)) {\n                best_rect = {x, y, x + 1, y + 1};\n                best_score = 0;\n                break;\n            }\n        }\n    }\n\n    /* ---------- coarse grid seeds ---------- */\n    auto grid_search = [&](int S, int K) {\n        int G = (MAXC + S) / S;\n        vector<vector<int>> grid(G, vector<int>(G, 0));\n        for (auto &p : pts) {\n            int cx = min(p.x / S, G - 1);\n            int cy = min(p.y / S, G - 1);\n            grid[cy][cx] += p.w;\n        }\n        using T = tuple<int,int,int,int,int>;          // val, y1, y2, x1, x2\n        priority_queue<T, vector<T>, greater<T>> pq;\n        for (int y1 = 0; y1 < G; ++y1) {\n            vector<int> col(G, 0);\n            for (int y2 = y1; y2 < G; ++y2) {\n                for (int x = 0; x < G; ++x) col[x] += grid[y2][x];\n                int cur = col[0], cur_l = 0;\n                int best = col[0], best_l = 0, best_r = 0;\n                for (int x = 1; x < G; ++x) {\n                    if (cur + col[x] < col[x]) {\n                        cur = col[x];\n                        cur_l = x;\n                    } else {\n                        cur += col[x];\n                    }\n                    if (cur > best) {\n                        best = cur;\n                        best_l = cur_l;\n                        best_r = x;\n                    }\n                }\n                if ((int)pq.size() < K) {\n                    pq.emplace(best, y1, y2, best_l, best_r);\n                } else if (best > get<0>(pq.top())) {\n                    pq.pop();\n                    pq.emplace(best, y1, y2, best_l, best_r);\n                }\n            }\n        }\n        vector<tuple<int,int,int,int,int>> res;\n        while (!pq.empty()) {\n            auto v = pq.top(); pq.pop();\n            res.emplace_back(S, get<1>(v), get<2>(v), get<3>(v), get<4>(v));\n        }\n        return res;\n    };\n\n    vector<tuple<int,int,int,int,int>> seeds;\n    for (int S : {500, 1000, 2000}) {\n        auto v = grid_search(S, 5);\n        seeds.insert(seeds.end(), v.begin(), v.end());\n    }\n\n    for (auto &sd : seeds) {\n        int S, gy1, gy2, gx1, gx2;\n        tie(S, gy1, gy2, gx1, gx2) = sd;\n        int x1 = gx1 * S;\n        int x2 = min(MAXC, (gx2 + 1) * S);\n        if (x1 > x2) swap(x1, x2);\n        int yy1, yy2;\n        int sc = eval_interval(x1, x2, yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {x1, yy1, x2, yy2};\n        }\n    }\n\n    /* snap best rectangle to actual point coordinates to obtain start indices */\n    int ix1 = 0, ix2 = X - 1;\n    if (best_score > 0) {\n        int minx = MAXC, maxx = 0, miny = MAXC, maxy = 0;\n        for (auto &p : pts) {\n            if (best_rect.x1 <= p.x && p.x <= best_rect.x2 &&\n                best_rect.y1 <= p.y && p.y <= best_rect.y2) {\n                minx = min(minx, p.x);\n                maxx = max(maxx, p.x);\n                miny = min(miny, p.y);\n                maxy = max(maxy, p.y);\n            }\n        }\n        if (minx <= maxx) {\n            best_rect = {minx, miny, maxx, maxy};\n            best_score = eval_rect(best_rect);\n            ix1 = lower_bound(ux.begin(), ux.end(), minx) - ux.begin();\n            ix2 = lower_bound(ux.begin(), ux.end(), maxx) - ux.begin();\n        }\n    }\n\n    {\n        int yy1, yy2;\n        int sc = eval_interval(ux[ix1], ux[ix2], yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {ux[ix1], yy1, ux[ix2], yy2};\n        }\n    }\n\n    /* ---------- helper to try an interval ---------- */\n    auto try_interval = [&](int i1, int i2) -> bool {\n        if (i1 < 0 || i2 >= X || i1 > i2) return false;\n        int yy1, yy2;\n        int sc = eval_interval(ux[i1], ux[i2], yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {ux[i1], yy1, ux[i2], yy2};\n            ix1 = i1; ix2 = i2;\n            return true;\n        }\n        return false;\n    };\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_local(-30, 30);\n    uniform_int_distribution<int> dist_global(0, X - 1);\n\n    auto hill_climb = [&]() {\n        while (true) {\n            int local_best = best_score;\n            int li1 = -1, li2 = -1;\n            int ly1 = 0, ly2 = 0;\n            for (int d1 = -1; d1 <= 1; ++d1) {\n                for (int d2 = -1; d2 <= 1; ++d2) {\n                    if (d1 == 0 && d2 == 0) continue;\n                    int ti1 = ix1 + d1;\n                    int ti2 = ix2 + d2;\n                    if (ti1 < 0 || ti2 >= X || ti1 > ti2) continue;\n                    int ty1, ty2;\n                    int tsc = eval_interval(ux[ti1], ux[ti2], ty1, ty2);\n                    if (tsc > local_best) {\n                        local_best = tsc;\n                        li1 = ti1; li2 = ti2;\n                        ly1 = ty1; ly2 = ty2;\n                    }\n                }\n            }\n            if (local_best <= best_score) break;\n            best_score = local_best;\n            best_rect = {ux[li1], ly1, ux[li2], ly2};\n            ix1 = li1; ix2 = li2;\n        }\n    };\n\n    /* Phase 1: pure random exploration */\n    for (int it = 0; it < 4000; ++it) {\n        int ni1, ni2;\n        if ((rng() & 1) && X > 1) {\n            ni1 = ix1 + dist_local(rng);\n            ni2 = ix2 + dist_local(rng);\n        } else {\n            ni1 = dist_global(rng);\n            ni2 = dist_global(rng);\n        }\n        if (ni1 < 0) ni1 = 0;\n        if (ni2 < 0) ni2 = 0;\n        if (ni1 >= X) ni1 = X - 1;\n        if (ni2 >= X) ni2 = X - 1;\n        if (ni1 > ni2) swap(ni1, ni2);\n        try_interval(ni1, ni2);\n    }\n\n    /* Phase 2: hill climb from the best found so far */\n    hill_climb();\n\n    /* Phase 3: more random jumps, hill climbing only on real improvement */\n    for (int it = 0; it < 2000; ++it) {\n        int ni1, ni2;\n        if ((rng() & 1) && X > 1) {\n            ni1 = ix1 + dist_local(rng);\n            ni2 = ix2 + dist_local(rng);\n        } else {\n            ni1 = dist_global(rng);\n            ni2 = dist_global(rng);\n        }\n        if (ni1 < 0) ni1 = 0;\n        if (ni2 < 0) ni2 = 0;\n        if (ni1 >= X) ni1 = X - 1;\n        if (ni2 >= X) ni2 = X - 1;\n        if (ni1 > ni2) swap(ni1, ni2);\n        if (try_interval(ni1, ni2))\n            hill_climb();\n    }\n\n    /* final safety: non\u2011zero area */\n    if (best_score <= 0) {\n        best_rect = {0, 0, 1, 1};   // empty fallback\n    } else {\n        if (best_rect.x1 == best_rect.x2) {\n            if (best_rect.x2 < MAXC) ++best_rect.x2;\n            else --best_rect.x1;\n        }\n        if (best_rect.y1 == best_rect.y2) {\n            if (best_rect.y2 < MAXC) ++best_rect.y2;\n            else --best_rect.y1;\n        }\n    }\n\n    cout << 4 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y2 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y2 << \"\\n\";\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nlong long SIGMA;\nlong long Wobs[100], Hobs[100];\n\nstruct Packing {\n    int r[100];\n    char d[100];\n    int b[100];\n    long long x[100], y[100], w[100], h[100];\n    long long score;\n};\n\ninline long long simulate(Packing& p, int start) {\n    long long W = 0, H = 0;\n    for (int j = 0; j < start; ++j) {\n        if (p.x[j] + p.w[j] > W) W = p.x[j] + p.w[j];\n        if (p.y[j] + p.h[j] > H) H = p.y[j] + p.h[j];\n    }\n    for (int i = start; i < N; ++i) {\n        long long wi = p.r[i] ? Hobs[i] : Wobs[i];\n        long long hi = p.r[i] ? Wobs[i] : Hobs[i];\n        long long xx, yy;\n        if (p.d[i] == 'U') {\n            xx = (p.b[i] == -1) ? 0LL : p.x[p.b[i]] + p.w[p.b[i]];\n            yy = 0;\n            for (int j = 0; j < i; ++j) {\n                if (xx < p.x[j] + p.w[j] && p.x[j] < xx + wi)\n                    yy = max(yy, p.y[j] + p.h[j]);\n            }\n        } else {\n            yy = (p.b[i] == -1) ? 0LL : p.y[p.b[i]] + p.h[p.b[i]];\n            xx = 0;\n            for (int j = 0; j < i; ++j) {\n                if (yy < p.y[j] + p.h[j] && p.y[j] < yy + hi)\n                    xx = max(xx, p.x[j] + p.w[j]);\n            }\n        }\n        p.x[i] = xx; p.y[i] = yy; p.w[i] = wi; p.h[i] = hi;\n        if (xx + wi > W) W = xx + wi;\n        if (yy + hi > H) H = yy + hi;\n    }\n    p.score = W + H;\n    return p.score;\n}\n\nlong long greedy_build(Packing& p, int start, int objective, bool stochastic, mt19937& rng) {\n    long long W = 0, H = 0;\n    for (int j = 0; j < start; ++j) {\n        W = max(W, p.x[j] + p.w[j]);\n        H = max(H, p.y[j] + p.h[j]);\n    }\n    struct Cand {\n        int r, b;\n        char d;\n        long long x, y, w, h, sc;\n    } cands[404];\n    int cand_cnt;\n    for (int i = start; i < N; ++i) {\n        cand_cnt = 0;\n        for (int rot = 0; rot < 2; ++rot) {\n            long long wi = rot ? Hobs[i] : Wobs[i];\n            long long hi = rot ? Wobs[i] : Hobs[i];\n            for (int di = 0; di < 2; ++di) {\n                char dd = di ? 'L' : 'U';\n                for (int bv = -1; bv < i; ++bv) {\n                    long long xx, yy;\n                    if (dd == 'U') {\n                        xx = (bv == -1) ? 0LL : p.x[bv] + p.w[bv];\n                        yy = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (xx < p.x[j] + p.w[j] && p.x[j] < xx + wi)\n                                yy = max(yy, p.y[j] + p.h[j]);\n                    } else {\n                        yy = (bv == -1) ? 0LL : p.y[bv] + p.h[bv];\n                        xx = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (yy < p.y[j] + p.h[j] && p.y[j] < yy + hi)\n                                xx = max(xx, p.x[j] + p.w[j]);\n                    }\n                    long long nW = max(W, xx + wi);\n                    long long nH = max(H, yy + hi);\n                    long long sc;\n                    if (objective == 0) sc = nW + nH;\n                    else if (objective == 1) sc = max(nW, nH);\n                    else if (objective == 2) sc = nW * nH;\n                    else sc = nW + nH + llabs(nW - nH) / 10;\n                    cands[cand_cnt++] = {rot, bv, dd, xx, yy, wi, hi, sc};\n                }\n            }\n        }\n        long long best_sc = cands[0].sc;\n        for (int k = 1; k < cand_cnt; ++k)\n            if (cands[k].sc < best_sc) best_sc = cands[k].sc;\n        int idx = 0;\n        if (stochastic) {\n            long long thr = best_sc + max(1LL, best_sc / 50);\n            int good[404], gcnt = 0;\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc <= thr) good[gcnt++] = k;\n            idx = good[rng() % gcnt];\n        } else {\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc == best_sc) { idx = k; break; }\n        }\n        const Cand& c = cands[idx];\n        p.r[i] = c.r; p.d[i] = c.d; p.b[i] = c.b;\n        p.x[i] = c.x; p.y[i] = c.y; p.w[i] = c.w; p.h[i] = c.h;\n        W = max(W, c.x + c.w);\n        H = max(H, c.y + c.h);\n    }\n    p.score = W + H;\n    return p.score;\n}\n\ninline void exhaustive_move(Packing& p, int i) {\n    long long bak_x[100], bak_y[100], bak_w[100], bak_h[100];\n    memcpy(bak_x, p.x + i, (N - i) * sizeof(long long));\n    memcpy(bak_y, p.y + i, (N - i) * sizeof(long long));\n    memcpy(bak_w, p.w + i, (N - i) * sizeof(long long));\n    memcpy(bak_h, p.h + i, (N - i) * sizeof(long long));\n    int orig_r = p.r[i], orig_b = p.b[i];\n    char orig_d = p.d[i];\n    long long orig_sc = p.score;\n\n    long long best_sc = orig_sc;\n    int best_r = orig_r, best_b = orig_b;\n    char best_d = orig_d;\n\n    for (int rot = 0; rot < 2; ++rot) {\n        for (int di = 0; di < 2; ++di) {\n            char dd = di ? 'L' : 'U';\n            for (int bv = -1; bv < i; ++bv) {\n                p.r[i] = rot; p.d[i] = dd; p.b[i] = bv;\n                long long sc = simulate(p, i);\n                if (sc < best_sc) {\n                    best_sc = sc;\n                    best_r = rot; best_d = dd; best_b = bv;\n                }\n            }\n        }\n    }\n    if (best_sc < orig_sc) {\n        p.r[i] = best_r; p.d[i] = best_d; p.b[i] = best_b;\n        p.score = best_sc;\n        simulate(p, i);\n    } else {\n        p.r[i] = orig_r; p.d[i] = orig_d; p.b[i] = orig_b;\n        memcpy(p.x + i, bak_x, (N - i) * sizeof(long long));\n        memcpy(p.y + i, bak_y, (N - i) * sizeof(long long));\n        memcpy(p.w + i, bak_w, (N - i) * sizeof(long long));\n        memcpy(p.h + i, bak_h, (N - i) * sizeof(long long));\n        p.score = orig_sc;\n    }\n}\n\ninline bool random_move(Packing& p, int i, mt19937& rng) {\n    long long bak_x[100], bak_y[100], bak_w[100], bak_h[100];\n    memcpy(bak_x, p.x + i, (N - i) * sizeof(long long));\n    memcpy(bak_y, p.y + i, (N - i) * sizeof(long long));\n    memcpy(bak_w, p.w + i, (N - i) * sizeof(long long));\n    memcpy(bak_h, p.h + i, (N - i) * sizeof(long long));\n    int orig_r = p.r[i], orig_b = p.b[i];\n    char orig_d = p.d[i];\n    long long orig_sc = p.score;\n\n    p.r[i] = (int)(rng() & 1);\n    p.d[i] = (rng() & 1) ? 'L' : 'U';\n    p.b[i] = (int)(rng() % (i + 1)) - 1;\n    long long sc = simulate(p, i);\n    if (sc < orig_sc) {\n        p.score = sc;\n        return true;\n    }\n    p.r[i] = orig_r; p.d[i] = orig_d; p.b[i] = orig_b;\n    memcpy(p.x + i, bak_x, (N - i) * sizeof(long long));\n    memcpy(p.y + i, bak_y, (N - i) * sizeof(long long));\n    memcpy(p.w + i, bak_w, (N - i) * sizeof(long long));\n    memcpy(p.h + i, bak_h, (N - i) * sizeof(long long));\n    p.score = orig_sc;\n    return false;\n}\n\ninline Packing crossover(const Packing& A, const Packing& B, int k) {\n    Packing C = A;\n    for (int i = k; i < N; ++i) {\n        C.r[i] = B.r[i];\n        C.d[i] = B.d[i];\n        C.b[i] = B.b[i];\n    }\n    simulate(C, k);\n    return C;\n}\n\nPacking beam_search(int B, int objective) {\n    struct Mini {\n        long long W, H;\n        long long x[100], y[100], w[100], h[100];\n        int r[100], b[100];\n        char d[100];\n    };\n    struct Cand {\n        long long sc;\n        int pid, r, b;\n        char d;\n        long long x, y, w, h, W, H;\n    };\n\n    vector<Mini> cur;\n    cur.reserve(B);\n    Mini empty;\n    memset(&empty, 0, sizeof(empty));\n    empty.W = empty.H = 0;\n    cur.push_back(empty);\n    vector<Cand> cands;\n    cands.reserve(B * 404);\n\n    for (int i = 0; i < N; ++i) {\n        cands.clear();\n        int psz = (int)cur.size();\n        for (int pid = 0; pid < psz; ++pid) {\n            const Mini& par = cur[pid];\n            for (int rot = 0; rot < 2; ++rot) {\n                long long wi = rot ? Hobs[i] : Wobs[i];\n                long long hi = rot ? Wobs[i] : Hobs[i];\n                for (int di = 0; di < 2; ++di) {\n                    char dd = di ? 'L' : 'U';\n                    for (int bv = -1; bv < i; ++bv) {\n                        long long xx, yy;\n                        if (dd == 'U') {\n                            xx = (bv == -1) ? 0LL : par.x[bv] + par.w[bv];\n                            yy = 0;\n                            for (int j = 0; j < i; ++j)\n                                if (xx < par.x[j] + par.w[j] && par.x[j] < xx + wi)\n                                    yy = max(yy, par.y[j] + par.h[j]);\n                        } else {\n                            yy = (bv == -1) ? 0LL : par.y[bv] + par.h[bv];\n                            xx = 0;\n                            for (int j = 0; j < i; ++j)\n                                if (yy < par.y[j] + par.h[j] && par.y[j] < yy + hi)\n                                    xx = max(xx, par.x[j] + par.w[j]);\n                        }\n                        long long nW = max(par.W, xx + wi);\n                        long long nH = max(par.H, yy + hi);\n                        long long sc = (objective == 0) ? nW + nH\n                                       : nW + nH + llabs(nW - nH) / 10;\n                        cands.push_back({sc, pid, rot, bv, dd,\n                                         xx, yy, wi, hi, nW, nH});\n                    }\n                }\n            }\n        }\n        int keep = min(B, (int)cands.size());\n        nth_element(cands.begin(), cands.begin() + keep, cands.end(),\n                    [](const Cand& a, const Cand& b) { return a.sc < b.sc; });\n        vector<Mini> nxt;\n        nxt.reserve(keep);\n        for (int k = 0; k < keep; ++k) {\n            const Cand& c = cands[k];\n            const Mini& par = cur[c.pid];\n            Mini ns;\n            memcpy(ns.x, par.x, sizeof(long long) * i);\n            memcpy(ns.y, par.y, sizeof(long long) * i);\n            memcpy(ns.w, par.w, sizeof(long long) * i);\n            memcpy(ns.h, par.h, sizeof(long long) * i);\n            memcpy(ns.r, par.r, sizeof(int) * i);\n            memcpy(ns.b, par.b, sizeof(int) * i);\n            memcpy(ns.d, par.d, sizeof(char) * i);\n            ns.x[i] = c.x; ns.y[i] = c.y; ns.w[i] = c.w; ns.h[i] = c.h;\n            ns.r[i] = c.r; ns.b[i] = c.b; ns.d[i] = c.d;\n            ns.W = c.W; ns.H = c.H;\n            nxt.push_back(ns);\n        }\n        cur.swap(nxt);\n    }\n    Packing res;\n    memset(&res, 0, sizeof(res));\n    const Mini& s = cur[0];\n    for (int i = 0; i < N; ++i) {\n        res.r[i] = s.r[i]; res.d[i] = s.d[i]; res.b[i] = s.b[i];\n        res.x[i] = s.x[i]; res.y[i] = s.y[i]; res.w[i] = s.w[i]; res.h[i] = s.h[i];\n    }\n    simulate(res, 0);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> T >> SIGMA;\n    for (int i = 0; i < N; ++i) cin >> Wobs[i] >> Hobs[i];\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    const double TIME_LIMIT = 2.88;\n    auto start_clock = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_clock).count();\n    };\n\n    /* ---- initialization ---- */\n    Packing pred_best;\n    memset(&pred_best, 0, sizeof(pred_best));\n    pred_best.score = (1LL << 60);\n\n    for (int t = 0; t < 40 && elapsed() < 0.25; ++t) {\n        Packing p;\n        memset(&p, 0, sizeof(p));\n        long long sc = greedy_build(p, 0, (int)(rng() % 4), true, rng);\n        if (sc < pred_best.score) pred_best = p;\n    }\n    for (int obj = 0; obj < 4 && elapsed() < 0.40; ++obj) {\n        Packing p;\n        memset(&p, 0, sizeof(p));\n        long long sc = greedy_build(p, 0, obj, false, rng);\n        if (sc < pred_best.score) pred_best = p;\n    }\n    if (elapsed() < 0.55) {\n        Packing b = beam_search(80, 1);\n        if (b.score < pred_best.score) pred_best = b;\n    }\n    if (elapsed() < 0.70) {\n        Packing b = beam_search(80, 0);\n        if (b.score < pred_best.score) pred_best = b;\n    }\n\n    {\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        for (int pass = 0; pass < 5 && elapsed() < 0.90; ++pass) {\n            shuffle(order.begin(), order.end(), rng);\n            bool improved = false;\n            for (int idx = 0; idx < N && elapsed() < 0.90; ++idx) {\n                long long old_sc = pred_best.score;\n                exhaustive_move(pred_best, order[idx]);\n                if (pred_best.score < old_sc) improved = true;\n            }\n            if (!improved) break;\n        }\n    }\n\n    // observed-score population (initially seeded with pred_best variants)\n    vector<pair<long long, Packing>> obs_pop;\n    auto add_obs = [&](long long obs, const Packing& p) {\n        obs_pop.push_back({obs, p});\n        sort(obs_pop.begin(), obs_pop.end(),\n             [](const auto& a, const auto& b) { return a.first < b.first; });\n        if ((int)obs_pop.size() > 8) obs_pop.pop_back();\n    };\n\n    // seed with a few diverse predicted-good packings\n    {\n        Packing p; memset(&p,0,sizeof(p));\n        greedy_build(p, 0, 0, false, rng);\n        add_obs(p.score, p);\n    }\n    {\n        Packing p; memset(&p,0,sizeof(p));\n        greedy_build(p, 0, 1, false, rng);\n        add_obs(p.score, p);\n    }\n    add_obs(pred_best.score, pred_best);\n\n    Packing obs_best = pred_best;\n    long long best_observed = (1LL << 60);\n\n    /* ---- turn loop ---- */\n    for (int turn = 0; turn < T; ++turn) {\n        if (elapsed() >= TIME_LIMIT - 0.05) {\n            cout << N << '\\n';\n            for (int i = 0; i < N; ++i)\n                cout << i << ' ' << obs_best.r[i] << ' ' << obs_best.d[i] << ' ' << obs_best.b[i] << '\\n';\n            cout.flush();\n            long long Wp, Hp;\n            cin >> Wp >> Hp;\n            continue;\n        }\n\n        double remain = TIME_LIMIT - elapsed();\n        double turn_budget = remain / max(1, T - turn) * 0.85;\n        auto deadline = chrono::steady_clock::now() + chrono::duration<double>(turn_budget);\n\n        // choose starting parent\n        Packing cur;\n        int rc = (int)(rng() % 100);\n        if (rc < 35) cur = pred_best;\n        else if (rc < 65) cur = obs_best;\n        else if (!obs_pop.empty() && rc < 85) cur = obs_pop[rng() % min((int)obs_pop.size(), 4)].second;\n        else {\n            memset(&cur, 0, sizeof(cur));\n            greedy_build(cur, 0, (int)(rng() % 4), true, rng);\n        }\n\n        // iterative local search\n        int no_improve = 0;\n        while (true) {\n            if ((no_improve & 7) == 0) {\n                if (chrono::steady_clock::now() >= deadline) break;\n            }\n\n            Packing nxt = cur;\n            int op = (int)(rng() % 100);\n            if (op < 15) {\n                exhaustive_move(nxt, (int)(rng() % N));\n            } else if (op < 55) {\n                random_move(nxt, (int)(rng() % N), rng);\n            } else if (op < 75 && !obs_pop.empty()) {\n                int other = rng() % obs_pop.size();\n                int k = rng() % (N - 1) + 1;\n                nxt = crossover(cur, obs_pop[other].second, k);\n            } else if (op < 90) {\n                int k = rng() % N;\n                greedy_build(nxt, k, (int)(rng() % 4), true, rng);\n            } else {\n                int k = 2 + (int)(rng() % 5);\n                int min_i = N;\n                for (int t = 0; t < k; ++t) {\n                    int i = rng() % N;\n                    if (i < min_i) min_i = i;\n                    nxt.r[i] = (int)(rng() & 1);\n                    nxt.d[i] = (rng() & 1) ? 'L' : 'U';\n                    nxt.b[i] = (int)(rng() % (i + 1)) - 1;\n                }\n                simulate(nxt, min_i);\n            }\n\n            if (nxt.score < cur.score) {\n                cur = nxt;\n                no_improve = 0;\n            } else {\n                ++no_improve;\n                if (no_improve > 80 && (rng() & 255) < 40) {\n                    cur = nxt;\n                    no_improve = 0;\n                }\n            }\n        }\n\n        // epsilon exploration\n        Packing cand = cur;\n        if ((rng() % 16) == 0) {\n            Packing tmp = cur;\n            int i = rng() % N;\n            tmp.r[i] = (int)(rng() & 1);\n            tmp.d[i] = (rng() & 1) ? 'L' : 'U';\n            tmp.b[i] = (int)(rng() % (i + 1)) - 1;\n            simulate(tmp, i);\n            if (tmp.score < cand.score) cand = tmp;\n        }\n\n        if (cand.score < pred_best.score) pred_best = cand;\n\n        cout << N << '\\n';\n        for (int i = 0; i < N; ++i) {\n            cout << i << ' ' << cand.r[i] << ' ' << cand.d[i] << ' ' << cand.b[i] << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        long long obs = Wp + Hp;\n\n        add_obs(obs, cand);\n        if (obs < best_observed) {\n            best_observed = obs;\n            obs_best = cand;\n        }\n    }\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    if (!(cin >> N >> M >> H)) return 0;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v; cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    // coordinates are not needed for the algorithm\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n    }\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    auto rand01 = [&]() -> double {\n        return (rng() & 0x7FFFFFFF) / 2147483648.0;\n    };\n\n    // sup[v][k] = #neighbours of v with depth k-1  (1..H)\n    vector<array<int, 13>> sup(N);\n    vector<int> d(N);\n    vector<int> best_d(N, 0);\n    long long best_score = 0;\n\n    auto recompute_sup = [&]() {\n        for (int i = 0; i < N; ++i) sup[i].fill(0);\n        for (int v = 0; v < N; ++v) {\n            for (int w : adj[v]) {\n                int k = d[w] + 1;\n                if (k <= H) ++sup[v][k];\n            }\n        }\n    };\n\n    auto calc_score = [&]() -> long long {\n        long long s = 0;\n        for (int i = 0; i < N; ++i) s += 1LL * (d[i] + 1) * A[i];\n        return s;\n    };\n\n    auto apply_move = [&](int v, int k) {\n        int old = d[v];\n        if (old == k) return;\n        for (int w : adj[v]) {\n            if (old + 1 <= H) --sup[w][old + 1];\n            if (k + 1 <= H) ++sup[w][k + 1];\n        }\n        d[v] = k;\n    };\n\n    auto can_move = [&](int v, int k) -> bool {\n        if (k == d[v]) return false;\n        if (k > 0 && sup[v][k] == 0) return false;\n        int old = d[v];\n        if (old + 1 <= H) {\n            for (int w : adj[v]) {\n                if (d[w] == old + 1 && sup[w][old + 1] == 1) return false;\n            }\n        }\n        return true;\n    };\n\n    // Greedy ascent from all-zero with a given scan order\n    auto greedy_ascent = [&](const vector<int>& order) -> long long {\n        fill(d.begin(), d.end(), 0);\n        for (int i = 0; i < N; ++i) sup[i].fill(0);\n        for (int v = 0; v < N; ++v) {\n            for (int w : adj[v]) ++sup[v][1];\n        }\n        vector<int> ord = order;\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int v : ord) {\n                int dv = d[v];\n                if (dv == H) continue;\n                bool locked = false;\n                if (dv + 1 <= H) {\n                    for (int w : adj[v]) {\n                        if (d[w] == dv + 1 && sup[w][dv + 1] == 1) {\n                            locked = true; break;\n                        }\n                    }\n                }\n                if (locked) continue;\n                for (int k = H; k > dv; --k) {\n                    if (sup[v][k] > 0) {\n                        for (int w : adj[v]) {\n                            --sup[w][dv + 1];\n                            if (k + 1 <= H) ++sup[w][k + 1];\n                        }\n                        d[v] = k;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n        return calc_score();\n    };\n\n    // Monotonic raising polish on the current (valid) state\n    auto polish = [&]() {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int v : ord) {\n                int dv = d[v];\n                if (dv == H) continue;\n                bool locked = false;\n                if (dv + 1 <= H) {\n                    for (int w : adj[v]) {\n                        if (d[w] == dv + 1 && sup[w][dv + 1] == 1) {\n                            locked = true; break;\n                        }\n                    }\n                }\n                if (locked) continue;\n                for (int k = H; k > dv; --k) {\n                    if (sup[v][k] > 0) {\n                        for (int w : adj[v]) {\n                            --sup[w][dv + 1];\n                            if (k + 1 <= H) ++sup[w][k + 1];\n                        }\n                        d[v] = k;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n    };\n\n    const double TL = 1.96;\n    double start = (double)clock() / CLOCKS_PER_SEC;\n    auto elapsed = [&]() { return (double)clock() / CLOCKS_PER_SEC - start; };\n\n    vector<pair<long long, vector<int>>> tops;\n    auto add_top = [&](long long sc, const vector<int>& state) {\n        tops.push_back({sc, state});\n        sort(tops.begin(), tops.end(),\n             [](const auto& a, const auto& b){ return a.first > b.first; });\n        if ((int)tops.size() > 5) tops.resize(5);\n    };\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    // Low-beauty first: they become the spine/roots\n    sort(ord.begin(), ord.end(), [&](int a, int b){ return A[a] < A[b]; });\n    add_top(greedy_ascent(ord), d);\n\n    // High-beauty first\n    sort(ord.begin(), ord.end(), [&](int a, int b){ return A[a] > A[b]; });\n    add_top(greedy_ascent(ord), d);\n\n    // Low-degree first: leaves attach early, hubs come later as supporters\n    sort(ord.begin(), ord.end(), [&](int a, int b){ return adj[a].size() < adj[b].size(); });\n    add_top(greedy_ascent(ord), d);\n\n    // Many random-order restarts\n    while (elapsed() < 0.60) {\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n        add_top(greedy_ascent(ord), d);\n    }\n\n    best_score = tops[0].first;\n    best_d = tops[0].second;\n\n    // Multi-start SA from the top candidates\n    const double alpha = 0.99997;\n    int candidate_idx = 0;\n\n    while (elapsed() < TL) {\n        if (candidate_idx >= (int)tops.size()) candidate_idx = 0;\n        d = tops[candidate_idx].second;\n        long long cur_score = tops[candidate_idx].first;\n        recompute_sup();\n\n        double T = 1000.0;\n        int last_improve = 0;\n        int iter = 0;\n\n        while (elapsed() < TL) {\n            if ((iter & 1023) == 0 && elapsed() >= TL) break;\n\n            int v = rng() % N;\n            int r = (int)(rng() % 100);\n            int k = -1;\n\n            if (r < 40) {\n                // Best valid depth for this vertex\n                long long best_gain = LLONG_MIN;\n                int best_k = d[v];\n                if (can_move(v, 0)) {\n                    long long g = -1LL * d[v] * A[v];\n                    if (g > best_gain) { best_gain = g; best_k = 0; }\n                }\n                for (int k2 = 1; k2 <= H; ++k2) {\n                    if (k2 == d[v] || sup[v][k2] == 0) continue;\n                    if (!can_move(v, k2)) continue;\n                    long long g = 1LL * (k2 - d[v]) * A[v];\n                    if (g > best_gain) { best_gain = g; best_k = k2; }\n                }\n                k = best_k;\n            } else if (r < 65) {\n                // Random supported depth\n                int cands[11];\n                int cn = 0;\n                for (int k2 = 1; k2 <= H; ++k2) {\n                    if (k2 != d[v] && sup[v][k2] > 0 && can_move(v, k2))\n                        cands[cn++] = k2;\n                }\n                if (cn > 0) k = cands[rng() % cn];\n                else if (can_move(v, 0)) k = 0;\n            } else if (r < 80) {\n                // One step down\n                if (d[v] > 0 && can_move(v, d[v] - 1)) k = d[v] - 1;\n            } else if (r < 90) {\n                // Deepest neighbour supporter\n                int best_k = -1;\n                for (int u : adj[v]) {\n                    int cand = d[u] + 1;\n                    if (cand <= H && cand > best_k && can_move(v, cand))\n                        best_k = cand;\n                }\n                if (best_k >= 0) k = best_k;\n                else if (can_move(v, 0)) k = 0;\n            } else {\n                // Jump to root\n                if (can_move(v, 0)) k = 0;\n            }\n\n            if (k < 0 || k == d[v]) { ++iter; continue; }\n\n            long long gain = 1LL * (k - d[v]) * A[v];\n            bool accept = (gain > 0);\n            if (!accept) {\n                double prob = exp((double)gain / T);\n                accept = prob > rand01();\n            }\n\n            if (accept) {\n                apply_move(v, k);\n                cur_score += gain;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_d = d;\n                    last_improve = iter;\n                }\n            }\n\n            T *= alpha;\n            if (T < 0.01) T = 0.01;\n\n            // Frequent monotonic polish\n            if (iter % 20000 == 0) {\n                polish();\n                cur_score = calc_score();\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_d = d;\n                    last_improve = iter;\n                }\n            }\n\n            // Reheat when stuck\n            if (iter - last_improve > 150000) {\n                if (cur_score < best_score) {\n                    d = best_d;\n                    cur_score = best_score;\n                    recompute_sup();\n                }\n                T = 1000.0;\n                last_improve = iter;\n            }\n            ++iter;\n        }\n        ++candidate_idx;\n    }\n\n    // Final polish on the best known solution\n    d = best_d;\n    recompute_sup();\n    polish();\n    long long final_score = calc_score();\n    if (final_score > best_score) {\n        best_score = final_score;\n        best_d = d;\n    }\n\n    // Reconstruct parents from the best depth labeling\n    vector<int> parent(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (best_d[v] > 0) {\n            for (int u : adj[v]) {\n                if (best_d[u] == best_d[v] - 1) {\n                    parent[v] = u;\n                    break;\n                }\n            }\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n/* -------------------------------------------------------------\n   Board state (N <= 20, row bitmasks)\n   ------------------------------------------------------------- */\nstruct State {\n    array<unsigned int, 20> oni{}, fuku{};\n    int oni_cnt = 0;\n};\n\n/* -------------------------------------------------------------\n   Non\u2011restoring sweeps (return false if a Fukunokami would fall)\n   ------------------------------------------------------------- */\nbool sweep_L(State &s, int i, int k, int N) {\n    unsigned int dm = (1u << k) - 1;\n    if (s.fuku[i] & dm) return false;\n    s.oni_cnt -= __builtin_popcount(s.oni[i] & dm);\n    s.oni[i] >>= k;\n    s.fuku[i] >>= k;\n    return true;\n}\nbool sweep_R(State &s, int i, int k, int N) {\n    unsigned int keep = (1u << (N - k)) - 1;\n    unsigned int dm   = (~keep) & ((1u << N) - 1);\n    if (s.fuku[i] & dm) return false;\n    s.oni_cnt -= __builtin_popcount(s.oni[i] & dm);\n    s.oni[i] = (s.oni[i] & keep) << k;\n    s.fuku[i] = (s.fuku[i] & keep) << k;\n    return true;\n}\nbool sweep_U(State &s, int j, int k, int N) {\n    unsigned int fcol = 0, ocol = 0;\n    for (int i = 0; i < N; ++i) {\n        if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n        if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n    }\n    unsigned int dm = (1u << k) - 1;\n    if (fcol & dm) return false;\n    s.oni_cnt -= __builtin_popcount(ocol & dm);\n    for (int i = 0; i < N - k; ++i) {\n        unsigned int vo = (s.oni[i + k] >> j) & 1u;\n        unsigned int vf = (s.fuku[i + k] >> j) & 1u;\n        s.oni[i]  = (s.oni[i]  & ~(1u << j)) | (vo << j);\n        s.fuku[i] = (s.fuku[i] & ~(1u << j)) | (vf << j);\n    }\n    for (int i = N - k; i < N; ++i) {\n        s.oni[i]  &= ~(1u << j);\n        s.fuku[i] &= ~(1u << j);\n    }\n    return true;\n}\nbool sweep_D(State &s, int j, int k, int N) {\n    unsigned int fcol = 0, ocol = 0;\n    for (int i = 0; i < N; ++i) {\n        if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n        if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n    }\n    unsigned int keep = (1u << (N - k)) - 1;\n    unsigned int dm   = (~keep) & ((1u << N) - 1);\n    if (fcol & dm) return false;\n    s.oni_cnt -= __builtin_popcount(ocol & dm);\n    for (int i = N - 1; i >= k; --i) {\n        unsigned int vo = (s.oni[i - k] >> j) & 1u;\n        unsigned int vf = (s.fuku[i - k] >> j) & 1u;\n        s.oni[i]  = (s.oni[i]  & ~(1u << j)) | (vo << j);\n        s.fuku[i] = (s.fuku[i] & ~(1u << j)) | (vf << j);\n    }\n    for (int i = 0; i < k; ++i) {\n        s.oni[i]  &= ~(1u << j);\n        s.fuku[i] &= ~(1u << j);\n    }\n    return true;\n}\n\n/* -------------------------------------------------------------\n   Fast feasibility test for restoring blocks\n   ------------------------------------------------------------- */\nbool feasible_for_exact(const State &s, int N) {\n    unsigned int all = (1u << N) - 1;\n    for (int i = 0; i < N; ++i) {\n        unsigned int m = s.oni[i];\n        while (m) {\n            int j = __builtin_ctz(m);\n            bool ok = false;\n            if ((s.fuku[i] & ((1u << (j + 1)) - 1)) == 0) ok = true;\n            unsigned int rmask = (~((1u << j) - 1)) & all;\n            if ((s.fuku[i] & rmask) == 0) ok = true;\n            bool up = true;\n            for (int r = 0; r <= i; ++r)\n                if (s.fuku[r] >> j & 1u) { up = false; break; }\n            if (up) ok = true;\n            bool down = true;\n            for (int r = i; r < N; ++r)\n                if (s.fuku[r] >> j & 1u) { down = false; break; }\n            if (down) ok = true;\n            if (!ok) return false;\n            m &= m - 1;\n        }\n    }\n    return true;\n}\n\n/* -------------------------------------------------------------\n   Exact restoring\u2011block solver (weighted set cover, optimal)\n   ------------------------------------------------------------- */\nstruct Block {\n    uint64_t mask;\n    int cost;\n    char dir;\n    int idx;\n    int k;\n};\n\nstatic vector<Block> g_blocks;\nstatic vector<int> g_sol;\n\nuint64_t state_hash(const State& s, int N) {\n    uint64_t h = 14695981039346656037ull;\n    for (int i = 0; i < N; ++i) {\n        h ^= s.oni[i] + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n        h ^= s.fuku[i] + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n    }\n    return h;\n}\n\nstatic unordered_map<uint64_t, int> exact_cache;\n\nint exact_cost_raw(const State &s, int N) {\n    g_blocks.clear();\n    g_sol.clear();\n\n    int id_of[20][20];\n    memset(id_of, -1, sizeof(id_of));\n    vector<pair<int,int>> onis;\n    for (int i = 0; i < N; ++i) {\n        unsigned int m = s.oni[i];\n        while (m) {\n            int j = __builtin_ctz(m);\n            id_of[i][j] = (int)onis.size();\n            onis.emplace_back(i, j);\n            m &= m - 1;\n        }\n    }\n    int M = (int)onis.size();\n    if (M == 0) return 0;\n    const uint64_t FULL = (M == 64) ? ~0ULL : ((1ULL << M) - 1ULL);\n\n    vector<Block> ops;\n    auto add = [&](uint64_t mask, int cost, char d, int idx, int k) {\n        if (mask) ops.push_back({mask, cost, d, idx, k});\n    };\n\n    // rows\n    for (int i = 0; i < N; ++i) {\n        int L = N, R = -1;\n        unsigned int fm = s.fuku[i];\n        if (fm) {\n            L = __builtin_ctz(fm);\n            R = 31 - __builtin_clz(fm);\n        }\n        uint64_t m = 0;\n        for (int j = 0; j < L; ++j)\n            if (s.oni[i] >> j & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (j + 1), 'L', i, j + 1);\n            }\n        m = 0;\n        for (int j = N - 1; j > R; --j)\n            if (s.oni[i] >> j & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (N - j), 'R', i, N - j);\n            }\n    }\n    // columns\n    for (int j = 0; j < N; ++j) {\n        unsigned int fcol = 0, ocol = 0;\n        for (int i = 0; i < N; ++i) {\n            if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n            if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n        }\n        int T = N, Bot = -1;\n        if (fcol) {\n            T  = __builtin_ctz(fcol);\n            Bot = 31 - __builtin_clz(fcol);\n        }\n        uint64_t m = 0;\n        for (int i = 0; i < T; ++i)\n            if (ocol >> i & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (i + 1), 'U', j, i + 1);\n            }\n        m = 0;\n        for (int i = N - 1; i > Bot; --i)\n            if (ocol >> i & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (N - i), 'D', j, N - i);\n            }\n    }\n\n    // dominance pruning\n    vector<Block> pruned;\n    for (auto &op : ops) {\n        bool dominated = false;\n        for (auto &p : pruned)\n            if ((p.mask | op.mask) == p.mask && p.cost <= op.cost) {\n                dominated = true; break;\n            }\n        if (dominated) continue;\n        vector<Block> nxt;\n        for (auto &p : pruned)\n            if (!((op.mask | p.mask) == op.mask && op.cost <= p.cost))\n                nxt.push_back(p);\n        nxt.push_back(op);\n        pruned.swap(nxt);\n    }\n    ops.swap(pruned);\n    int S = (int)ops.size();\n\n    vector<vector<int>> cover(M);\n    for (int i = 0; i < S; ++i) {\n        uint64_t m = ops[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            cover[b].push_back(i);\n            m &= m - 1;\n        }\n    }\n\n    for (int o = 0; o < M; ++o)\n        if (cover[o].empty()) return INF;\n\n    // greedy upper bound\n    int greedy_cost = 0;\n    uint64_t uncovered = FULL;\n    vector<int> greedy_sol;\n    while (uncovered) {\n        int best = -1;\n        double best_r = 1e300;\n        for (int i = 0; i < S; ++i) {\n            uint64_t nw = ops[i].mask & uncovered;\n            int cnt = __builtin_popcountll(nw);\n            if (cnt == 0) continue;\n            double r = (double)ops[i].cost / cnt;\n            if (r < best_r) { best_r = r; best = i; }\n        }\n        if (best == -1) return INF;\n        greedy_cost += ops[best].cost;\n        uncovered &= ~ops[best].mask;\n        greedy_sol.push_back(best);\n    }\n\n    int best_cost = greedy_cost;\n    vector<int> best_sol = greedy_sol;\n\n    static unordered_map<uint64_t, int> memo;\n    memo.clear();\n    memo.reserve(20000);\n\n    function<void(uint64_t,int,vector<int>&)> dfs = [&](uint64_t unc, int cur, vector<int> &vec) {\n        if (unc == 0) {\n            if (cur < best_cost) {\n                best_cost = cur;\n                best_sol = vec;\n            }\n            return;\n        }\n        if (cur >= best_cost) return;\n        auto it = memo.find(unc);\n        if (it != memo.end() && it->second <= cur) return;\n        memo[unc] = cur;\n\n        int lb = cur;\n        uint64_t tmp = unc;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int mn = INF;\n            for (int id : cover[o])\n                if (ops[id].mask & unc) mn = min(mn, ops[id].cost);\n            if (mn == INF) return;\n            lb += mn;\n            if (lb >= best_cost) return;\n            tmp &= tmp - 1;\n        }\n\n        int target = -1, mindeg = INT_MAX;\n        tmp = unc;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int deg = 0;\n            for (int id : cover[o]) if (ops[id].mask & unc) ++deg;\n            if (deg < mindeg) { mindeg = deg; target = o; }\n            tmp &= tmp - 1;\n        }\n\n        vector<pair<int,int>> cands;\n        for (int id : cover[target])\n            if (ops[id].mask & unc) cands.emplace_back(ops[id].cost, id);\n        sort(cands.begin(), cands.end());\n        for (auto &[c, id] : cands) {\n            if (cur + c >= best_cost) continue;\n            vec.push_back(id);\n            dfs(unc & ~ops[id].mask, cur + c, vec);\n            vec.pop_back();\n        }\n    };\n\n    vector<int> vec;\n    dfs(FULL, 0, vec);\n\n    // remove redundant blocks\n    vector<int> sol = best_sol;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < sol.size(); ++i) {\n            uint64_t u = 0;\n            for (size_t j = 0; j < sol.size(); ++j)\n                if (j != i) u |= ops[sol[j]].mask;\n            if ((u & FULL) == FULL) {\n                sol.erase(sol.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    g_blocks = ops;\n    g_sol = sol;\n    int total = 0;\n    for (int id : sol) total += ops[id].cost;\n    return total;\n}\n\nint exact_cost_memo(const State &s, int N) {\n    uint64_t h = state_hash(s, N);\n    auto it = exact_cache.find(h);\n    if (it != exact_cache.end()) return it->second;\n    int res = exact_cost_raw(s, N);\n    exact_cache[h] = res;\n    return res;\n}\n\n/* emit restoring moves for the last exact_cost_raw() call */\nvoid exact_seq(vector<pair<char,int>> &out) {\n    for (int id : g_sol) {\n        const Block &op = g_blocks[id];\n        for (int t = 0; t < op.k; ++t) out.emplace_back(op.dir, op.idx);\n        char rev = 0;\n        if (op.dir == 'L') rev = 'R';\n        else if (op.dir == 'R') rev = 'L';\n        else if (op.dir == 'U') rev = 'D';\n        else rev = 'U';\n        for (int t = 0; t < op.k; ++t) out.emplace_back(rev, op.idx);\n    }\n}\n\n/* -------------------------------------------------------------\n   Generate all safe non\u2011restoring sweeps\n   ------------------------------------------------------------- */\nstruct Cand { char d; int idx, k, cnt; };\n\nvector<Cand> gen_cands(const State &s, int N) {\n    vector<Cand> c;\n    unsigned int all = (1u << N) - 1;\n    for (int i = 0; i < N; ++i) {\n        unsigned int orow = s.oni[i], frow = s.fuku[i];\n        int L = N, R = -1;\n        if (frow) {\n            L = __builtin_ctz(frow);\n            R = 31 - __builtin_clz(frow);\n        }\n        for (int j = 0; j < L; ++j)\n            if (orow >> j & 1u) {\n                int k = j + 1;\n                int cnt = __builtin_popcount(orow & ((1u << k) - 1));\n                if (cnt) c.push_back({'L', i, k, cnt});\n            }\n        for (int j = N - 1; j > R; --j)\n            if (orow >> j & 1u) {\n                int k = N - j;\n                int cnt = __builtin_popcount(orow >> j);\n                if (cnt) c.push_back({'R', i, k, cnt});\n            }\n    }\n    for (int j = 0; j < N; ++j) {\n        unsigned int fcol = 0, ocol = 0;\n        for (int i = 0; i < N; ++i) {\n            if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n            if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n        }\n        int T = N, Bot = -1;\n        if (fcol) {\n            T  = __builtin_ctz(fcol);\n            Bot = 31 - __builtin_clz(fcol);\n        }\n        for (int i = 0; i < T; ++i)\n            if (ocol >> i & 1u) {\n                int k = i + 1;\n                int cnt = __builtin_popcount(ocol & ((1u << k) - 1));\n                if (cnt) c.push_back({'U', j, k, cnt});\n            }\n        for (int i = N - 1; i > Bot; --i)\n            if (ocol >> i & 1u) {\n                int k = N - i;\n                int cnt = __builtin_popcount(ocol >> i);\n                if (cnt) c.push_back({'D', j, k, cnt});\n            }\n    }\n    return c;\n}\n\n/* -------------------------------------------------------------\n   Pure safe solution (restoring blocks only)\n   ------------------------------------------------------------- */\nvector<pair<char,int>> pure_safe(const vector<string> &B, int N) {\n    State init;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { init.oni[i] |= 1u << j; ++init.oni_cnt; }\n            else if (B[i][j] == 'o') init.fuku[i] |= 1u << j;\n        }\n    exact_cost_raw(init, N);\n    vector<pair<char,int>> moves;\n    exact_seq(moves);\n    return moves;\n}\n\n/* -------------------------------------------------------------\n   Full simulation validator\n   ------------------------------------------------------------- */\nbool validate(const vector<string> &B, const vector<pair<char,int>> &moves, int N) {\n    State s;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { s.oni[i] |= 1u << j; ++s.oni_cnt; }\n            else if (B[i][j] == 'o') s.fuku[i] |= 1u << j;\n        }\n    for (auto &p : moves) {\n        bool ok = false;\n        if (p.first == 'L') ok = sweep_L(s, p.second, 1, N);\n        else if (p.first == 'R') ok = sweep_R(s, p.second, 1, N);\n        else if (p.first == 'U') ok = sweep_U(s, p.second, 1, N);\n        else if (p.first == 'D') ok = sweep_D(s, p.second, 1, N);\n        if (!ok) return false;\n    }\n    return s.oni_cnt == 0;\n}\n\n/* -------------------------------------------------------------\n   2\u2011ply exact lookahead solver\n   ------------------------------------------------------------- */\nvector<pair<char,int>> solve_2ply(const State &init, int N, int best_cost) {\n    vector<pair<char,int>> moves;\n    State s = init;\n    const int W1 = 25;\n\n    while (s.oni_cnt > 0) {\n        int base = exact_cost_memo(s, N);\n        if (base >= INF) { moves.clear(); return moves; }\n\n        auto cands = gen_cands(s, N);\n        struct Item1 { Cand c; int total1; };\n        vector<Item1> items1;\n\n        for (auto &c : cands) {\n            if ((int)moves.size() + c.k >= best_cost) continue;\n            State s1 = s;\n            bool ok = false;\n            if (c.d == 'L') ok = sweep_L(s1, c.idx, c.k, N);\n            else if (c.d == 'R') ok = sweep_R(s1, c.idx, c.k, N);\n            else if (c.d == 'U') ok = sweep_U(s1, c.idx, c.k, N);\n            else ok = sweep_D(s1, c.idx, c.k, N);\n            if (!ok) continue;\n            if (!feasible_for_exact(s1, N)) continue;\n            int tail1 = exact_cost_memo(s1, N);\n            if (tail1 >= INF) continue;\n            int total1 = c.k + tail1;\n            if ((int)moves.size() + total1 >= best_cost) continue;\n            items1.push_back({c, total1});\n        }\n\n        if (items1.empty()) break;\n\n        sort(items1.begin(), items1.end(),\n             [](const Item1 &a, const Item1 &b){ return a.total1 < b.total1; });\n\n        int limit = min(W1, (int)items1.size());\n        int best_total = base;          // must strictly beat this\n        Cand best_c;\n        bool found = false;\n\n        for (int i = 0; i < limit; ++i) {\n            const Cand &c = items1[i].c;\n            // 1\u2011ply option (stop after this sweep and restore)\n            if (items1[i].total1 < best_total) {\n                best_total = items1[i].total1;\n                best_c = c;\n                found = true;\n            }\n\n            // 2\u2011ply continuation\n            State s1 = s;\n            if (c.d == 'L') sweep_L(s1, c.idx, c.k, N);\n            else if (c.d == 'R') sweep_R(s1, c.idx, c.k, N);\n            else if (c.d == 'U') sweep_U(s1, c.idx, c.k, N);\n            else sweep_D(s1, c.idx, c.k, N);\n\n            auto cands2 = gen_cands(s1, N);\n            for (auto &c2 : cands2) {\n                if ((int)moves.size() + c.k + c2.k >= best_cost) continue;\n                State s2 = s1;\n                bool ok = false;\n                if (c2.d == 'L') ok = sweep_L(s2, c2.idx, c2.k, N);\n                else if (c2.d == 'R') ok = sweep_R(s2, c2.idx, c2.k, N);\n                else if (c2.d == 'U') ok = sweep_U(s2, c2.idx, c2.k, N);\n                else ok = sweep_D(s2, c2.idx, c2.k, N);\n                if (!ok) continue;\n                if (!feasible_for_exact(s2, N)) continue;\n                int tail2 = exact_cost_memo(s2, N);\n                if (tail2 >= INF) continue;\n                int total2 = c.k + c2.k + tail2;\n                if ((int)moves.size() + total2 >= best_cost) continue;\n                if (total2 < best_total) {\n                    best_total = total2;\n                    best_c = c;\n                    found = true;\n                }\n            }\n        }\n\n        if (!found) break; // no improving move at 1\u2011 or 2\u2011ply\n\n        bool ok = false;\n        if (best_c.d == 'L') ok = sweep_L(s, best_c.idx, best_c.k, N);\n        else if (best_c.d == 'R') ok = sweep_R(s, best_c.idx, best_c.k, N);\n        else if (best_c.d == 'U') ok = sweep_U(s, best_c.idx, best_c.k, N);\n        else ok = sweep_D(s, best_c.idx, best_c.k, N);\n        if (!ok) { moves.clear(); return moves; }\n\n        for (int t = 0; t < best_c.k; ++t)\n            moves.emplace_back(best_c.d, best_c.idx);\n    }\n\n    if (s.oni_cnt > 0) {\n        int tail = exact_cost_memo(s, N);\n        if (tail >= INF) { moves.clear(); return moves; }\n        if ((int)moves.size() + tail >= best_cost) { moves.clear(); return moves; }\n        exact_cost_raw(s, N);\n        exact_seq(moves);\n    }\n    return moves;\n}\n\n/* -------------------------------------------------------------\n   Stochastic 1\u2011ply greedy with slack\n   ------------------------------------------------------------- */\nvector<pair<char,int>> greedy_stoch(const State &init, int N, int trial_id,\n                                    int best_cost, const chrono::steady_clock::time_point &deadline) {\n    vector<pair<char,int>> moves;\n    State s = init;\n    mt19937 rng(123456789 + trial_id * 1000003);\n    const int SLACK = 4;\n\n    while (s.oni_cnt > 0) {\n        if (chrono::steady_clock::now() > deadline) { moves.clear(); return moves; }\n\n        int base = exact_cost_memo(s, N);\n        if (base >= INF) { moves.clear(); return moves; }\n\n        auto cands = gen_cands(s, N);\n        struct Item { Cand c; int total; };\n        vector<Item> items;\n\n        for (auto &c : cands) {\n            if ((int)moves.size() + c.k >= best_cost) continue;\n            State nxt = s;\n            bool ok = false;\n            if (c.d == 'L') ok = sweep_L(nxt, c.idx, c.k, N);\n            else if (c.d == 'R') ok = sweep_R(nxt, c.idx, c.k, N);\n            else if (c.d == 'U') ok = sweep_U(nxt, c.idx, c.k, N);\n            else ok = sweep_D(nxt, c.idx, c.k, N);\n            if (!ok) continue;\n            if (!feasible_for_exact(nxt, N)) continue;\n            int rem = exact_cost_memo(nxt, N);\n            if (rem >= INF) continue;\n            int total = c.k + rem;\n            if ((int)moves.size() + total >= best_cost) continue;\n            if (total < base + SLACK) items.push_back({c, total});\n        }\n\n        if (items.empty()) break;\n\n        sort(items.begin(), items.end(),\n             [](const Item &a, const Item &b){ return a.total < b.total; });\n\n        int top = min(3, (int)items.size());\n        uniform_int_distribution<int> dist(0, top - 1);\n        Cand chosen = items[dist(rng)].c;\n\n        bool ok = false;\n        if (chosen.d == 'L') ok = sweep_L(s, chosen.idx, chosen.k, N);\n        else if (chosen.d == 'R') ok = sweep_R(s, chosen.idx, chosen.k, N);\n        else if (chosen.d == 'U') ok = sweep_U(s, chosen.idx, chosen.k, N);\n        else ok = sweep_D(s, chosen.idx, chosen.k, N);\n        if (!ok) { moves.clear(); return moves; }\n\n        for (int t = 0; t < chosen.k; ++t)\n            moves.emplace_back(chosen.d, chosen.idx);\n    }\n\n    if (s.oni_cnt > 0) {\n        int tail = exact_cost_memo(s, N);\n        if (tail >= INF) { moves.clear(); return moves; }\n        if ((int)moves.size() + tail >= best_cost) { moves.clear(); return moves; }\n        exact_cost_raw(s, N);\n        exact_seq(moves);\n    }\n    return moves;\n}\n\n/* -------------------------------------------------------------\n   Main\n   ------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> B(N);\n    for (int i = 0; i < N; ++i) cin >> B[i];\n\n    const int LIMIT = 4 * N * N;\n\n    // fallback\n    vector<pair<char,int>> best = pure_safe(B, N);\n    int best_cost = (int)best.size();\n\n    auto consider = [&](const vector<pair<char,int>> &moves) {\n        if ((int)moves.size() > LIMIT) return;\n        if (!validate(B, moves, N)) return;\n        if ((int)moves.size() < best_cost) {\n            best_cost = (int)moves.size();\n            best = moves;\n        }\n    };\n\n    State init;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { init.oni[i] |= 1u << j; ++init.oni_cnt; }\n            else if (B[i][j] == 'o') init.fuku[i] |= 1u << j;\n        }\n\n    auto start = chrono::steady_clock::now();\n    auto deadline = start + chrono::milliseconds(1950);\n\n    // primary: 2\u2011ply exact lookahead\n    auto ans = solve_2ply(init, N, best_cost);\n    consider(ans);\n\n    // remaining time: stochastic greedy trials\n    for (int trial = 1; trial <= 5000; ++trial) {\n        if (chrono::steady_clock::now() > deadline) break;\n        ans = greedy_stoch(init, N, trial, best_cost, deadline);\n        consider(ans);\n    }\n\n    // final safety\n    if (!validate(B, best, N)) {\n        best = pure_safe(B, N);\n    }\n\n    for (auto &p : best)\n        cout << p.first << ' ' << p.second << '\\n';\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    if (!(cin >> N >> L)) return 0;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    vector<double> p(N);\n    for (int i = 0; i < N; ++i) p[i] = (double)T[i] / (double)L;\n\n    /*------------------------------------------------------------\n        Phase 1 : greedy init + fast proxy local search\n      ------------------------------------------------------------*/\n    vector<int> a(N), b(N);\n    vector<double> in(N, 0.0);\n\n    auto pick_best_deficit = [&]() {\n        int best = 0;\n        double bestDef = -1e100;\n        for (int i = 0; i < N; ++i) {\n            double def = p[i] - in[i];\n            if (def > bestDef) {\n                bestDef = def;\n                best = i;\n            }\n        }\n        return best;\n    };\n\n    for (int j = 0; j < N; ++j) {\n        int u = pick_best_deficit();\n        a[j] = u;\n        in[u] += p[j] * 0.5;\n        int v = pick_best_deficit();\n        b[j] = v;\n        in[v] += p[j] * 0.5;\n    }\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto proxy_delta = [&](int j, int typ, int newv) -> double {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return 0.0;\n        double d = 0.0;\n        double afterOld = in[oldv] - p[j] * 0.5;\n        d += fabs(afterOld - p[oldv]) - fabs(in[oldv] - p[oldv]);\n        double afterNew = in[newv] + p[j] * 0.5;\n        d += fabs(afterNew - p[newv]) - fabs(in[newv] - p[newv]);\n        return d;\n    };\n\n    auto apply_proxy = [&](int j, int typ, int newv) {\n        int oldv = typ ? b[j] : a[j];\n        if (oldv == newv) return;\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ) b[j] = newv;\n        else     a[j] = newv;\n    };\n\n    for (int iter = 0; iter < 500000; ++iter) {\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int newv = (int)(rng() % N);\n        double d = proxy_delta(j, typ, newv);\n        if (d < -1e-12) {\n            apply_proxy(j, typ, newv);\n        }\n    }\n\n    /*------------------------------------------------------------\n        Phase 2 : simulation + SA with proxy-guided neighbours\n      ------------------------------------------------------------*/\n    vector<array<uint8_t,2>> nxt(N);\n    for (int i = 0; i < N; ++i) {\n        nxt[i][0] = (uint8_t)b[i];\n        nxt[i][1] = (uint8_t)a[i];\n    }\n\n    vector<int> simCnt(N);\n    auto simulate_fill = [&]() -> int {\n        fill(simCnt.begin(), simCnt.end(), 0);\n        uint8_t cur = 0;\n        simCnt[0] = 1;\n        for (int step = 1; step < L; ++step) {\n            cur = nxt[cur][simCnt[cur] & 1];\n            ++simCnt[cur];\n        }\n        int err = 0;\n        for (int i = 0; i < N; ++i) err += abs(simCnt[i] - T[i]);\n        return err;\n    };\n\n    int bestE = simulate_fill();\n    vector<int> bestA = a, bestB = b;\n    int curE = bestE;\n\n    vector<int> diff(N);\n    for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n\n    double temp = max(100.0, (double)bestE * 0.2);\n    const double COOL = 0.9995;\n    int iter = 0, lastBestIter = 0;\n\n    auto curTime = [&]() {\n        return (double)clock() / (double)CLOCKS_PER_SEC;\n    };\n\n    while (curTime() < 1.85) {\n        ++iter;\n\n        /*--- kick when stuck ------------------------------------*/\n        if (iter - lastBestIter > 150) {\n            a = bestA; b = bestB;\n            fill(in.begin(), in.end(), 0.0);\n            for (int j = 0; j < N; ++j) {\n                in[a[j]] += p[j] * 0.5;\n                in[b[j]] += p[j] * 0.5;\n            }\n            for (int k = 0; k < 5; ++k) {\n                int jj = (int)(rng() % N);\n                int tt = (int)(rng() % 2);\n                int nv = (int)(rng() % N);\n                apply_proxy(jj, tt, nv);\n            }\n            for (int i = 0; i < N; ++i) {\n                nxt[i][0] = (uint8_t)b[i];\n                nxt[i][1] = (uint8_t)a[i];\n            }\n            curE = simulate_fill();\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n            if (curE < bestE) {\n                bestE = curE;\n                bestA = a; bestB = b;\n                lastBestIter = iter;\n            }\n            temp = max(100.0, (double)curE * 0.2);\n            continue;\n        }\n\n        /*--- choose a neighbour ---------------------------------*/\n        int j = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int oldv = typ ? b[j] : a[j];\n        int newv = oldv;\n\n        int mode = (int)(rng() % 4);\n        if (mode < 2) {                     // exploitation : best proxy\n            double bestD = 1e100;\n            for (int v = 0; v < N; ++v) {\n                if (v == oldv) continue;\n                double d = proxy_delta(j, typ, v);\n                if (d < bestD) {\n                    bestD = d;\n                    newv = v;\n                }\n            }\n            if (newv == oldv) continue;\n        } else if (mode == 2) {             // pure random\n            newv = (int)(rng() % N);\n            if (newv == oldv) continue;\n        } else {                            // targeted by diff\n            vector<int> over, under;\n            for (int i = 0; i < N; ++i) {\n                if (diff[i] > 0) over.push_back(i);\n                else if (diff[i] < 0) under.push_back(i);\n            }\n            if (over.empty() || under.empty()) {\n                newv = (int)(rng() % N);\n                if (newv == oldv) continue;\n            } else {\n                int to = over[(int)(rng() % over.size())];\n                vector<pair<int,int>> preds;\n                for (int x = 0; x < N; ++x) {\n                    if (a[x] == to) preds.emplace_back(x, 0);\n                    if (b[x] == to) preds.emplace_back(x, 1);\n                }\n                if (preds.empty()) {\n                    newv = (int)(rng() % N);\n                    if (newv == oldv) continue;\n                } else {\n                    auto pr = preds[(int)(rng() % preds.size())];\n                    j = pr.first;\n                    typ = pr.second;\n                    oldv = typ ? b[j] : a[j];\n                    newv = under[(int)(rng() % under.size())];\n                    if (newv == oldv) continue;\n                }\n            }\n        }\n\n        /*--- apply and simulate ---------------------------------*/\n        in[oldv] -= p[j] * 0.5;\n        in[newv] += p[j] * 0.5;\n        if (typ == 0) {\n            a[j] = newv;\n            nxt[j][1] = (uint8_t)newv;\n        } else {\n            b[j] = newv;\n            nxt[j][0] = (uint8_t)newv;\n        }\n\n        int newE = simulate_fill();\n        bool accept = false;\n\n        if (newE < bestE) {\n            bestE = newE;\n            bestA = a; bestB = b;\n            lastBestIter = iter;\n            accept = true;\n        }\n        if (!accept) {\n            int dE = newE - curE;\n            if (dE <= 0) {\n                accept = true;\n            } else {\n                uniform_real_distribution<double> dist(0.0, 1.0);\n                if (dist(rng) < exp(-dE / temp)) accept = true;\n            }\n        }\n\n        if (accept) {\n            curE = newE;\n            for (int i = 0; i < N; ++i) diff[i] = simCnt[i] - T[i];\n        } else {\n            // revert\n            in[newv] -= p[j] * 0.5;\n            in[oldv] += p[j] * 0.5;\n            if (typ == 0) {\n                a[j] = oldv;\n                nxt[j][1] = (uint8_t)oldv;\n            } else {\n                b[j] = oldv;\n                nxt[j][0] = (uint8_t)oldv;\n            }\n        }\n        temp *= COOL;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (r[a] < r[b]) swap(a, b);\n        p[b] = a;\n        if (r[a] == r[b]) ++r[a];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    vector<double> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) * 0.5;\n        cy[i] = (ly[i] + ry[i]) * 0.5;\n    }\n\n    vector<vector<double>> est(N, vector<double>(N));\n    for (int i = 0; i < N; ++i) {\n        est[i][i] = 0.0;\n        for (int j = i + 1; j < N; ++j) {\n            double dx = cx[i] - cx[j];\n            double dy = cy[i] - cy[j];\n            est[i][j] = est[j][i] = sqrt(dx * dx + dy * dy);\n        }\n    }\n\n    auto expand_bits = [&](uint32_t x) -> uint64_t {\n        uint64_t z = 0;\n        for (int i = 0; i < 15; ++i)\n            z |= ((uint64_t)((x >> i) & 1U)) << (2 * i);\n        return z;\n    };\n    auto morton_key = [&](int v) -> uint64_t {\n        uint32_t x = (uint32_t)(lx[v] + rx[v]);\n        uint32_t y = (uint32_t)(ly[v] + ry[v]);\n        return expand_bits(x) | (expand_bits(y) << 1);\n    };\n\n    auto group_mst_cost = [&](const vector<int> &nodes) -> double {\n        int g = (int)nodes.size();\n        if (g <= 1) return 0.0;\n        if (g == 2) return est[nodes[0]][nodes[1]];\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        double total = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            total += mincost[v];\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) mincost[i] = d;\n            }\n        }\n        return total;\n    };\n\n    auto group_mst_edges = [&](const vector<int> &nodes) -> vector<pair<int,int>> {\n        int g = (int)nodes.size();\n        vector<pair<int,int>> edges;\n        if (g <= 1) return edges;\n        if (g == 2) {\n            edges.emplace_back(nodes[0], nodes[1]);\n            return edges;\n        }\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<int> parent(g, -1);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            if (parent[v] != -1) edges.emplace_back(nodes[parent[v]], nodes[v]);\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) {\n                    mincost[i] = d;\n                    parent[i] = v;\n                }\n            }\n        }\n        return edges;\n    };\n\n    auto mst_order = [&](const vector<int> &nodes) -> vector<int> {\n        int g = (int)nodes.size();\n        if (g <= 1) return nodes;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<int> parent(g, -1);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double d = est[nodes[v]][nodes[i]];\n                if (d < mincost[i]) {\n                    mincost[i] = d;\n                    parent[i] = v;\n                }\n            }\n        }\n        vector<vector<int>> adj(g);\n        for (int i = 1; i < g; ++i) {\n            adj[i].push_back(parent[i]);\n            adj[parent[i]].push_back(i);\n        }\n        vector<int> ord;\n        ord.reserve(g);\n        stack<int> st;\n        st.push(0);\n        vector<char> vis(g, 0);\n        vis[0] = 1;\n        while (!st.empty()) {\n            int u = st.top(); st.pop();\n            ord.push_back(nodes[u]);\n            for (int v : adj[u]) if (!vis[v]) {\n                vis[v] = 1;\n                st.push(v);\n            }\n        }\n        return ord;\n    };\n\n    /* ---------- Build initial partition ---------- */\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) {\n             if (G[a] != G[b]) return G[a] > G[b];\n             return a < b;\n         });\n\n    vector<vector<int>> group_nodes(M);\n    vector<char> assigned(N, 0);\n    vector<int> unassigned;\n    unassigned.reserve(N);\n    for (int i = 0; i < N; ++i) unassigned.push_back(i);\n    sort(unassigned.begin(), unassigned.end(),\n         [&](int a, int b) { return morton_key(a) < morton_key(b); });\n\n    for (int idx : order) {\n        int g = G[idx];\n        if (g < 3) continue;\n        int U = (int)unassigned.size();\n        int K = min(30, U);\n        vector<int> best_cluster;\n        double best_cost = 1e100;\n        for (int s = 0; s < K; ++s) {\n            int seed = unassigned[s * U / K];\n            vector<int> cluster;\n            cluster.reserve(g);\n            cluster.push_back(seed);\n            vector<char> in_cluster(N, 0);\n            in_cluster[seed] = 1;\n            vector<double> d(N, 1e100);\n            for (int v : unassigned) if (v != seed) d[v] = est[seed][v];\n            while ((int)cluster.size() < g) {\n                int best_u = -1;\n                double best_du = 1e100;\n                for (int v : unassigned) {\n                    if (in_cluster[v]) continue;\n                    if (d[v] < best_du) {\n                        best_du = d[v];\n                        best_u = v;\n                    }\n                }\n                cluster.push_back(best_u);\n                in_cluster[best_u] = 1;\n                for (int v : unassigned) if (!in_cluster[v]) {\n                    double nd = est[best_u][v];\n                    if (nd < d[v]) d[v] = nd;\n                }\n            }\n            double cost = group_mst_cost(cluster);\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_cluster = move(cluster);\n            }\n        }\n        group_nodes[idx] = best_cluster;\n        for (int v : best_cluster) assigned[v] = 1;\n        vector<int> nxt;\n        nxt.reserve(unassigned.size() - g);\n        for (int v : unassigned) if (!assigned[v]) nxt.push_back(v);\n        unassigned.swap(nxt);\n    }\n\n    for (int idx : order) {\n        if (G[idx] != 2) continue;\n        int U = (int)unassigned.size();\n        double best_d = 1e100;\n        int best_a = -1, best_b = -1;\n        for (int i = 0; i < U; ++i)\n            for (int j = i + 1; j < U; ++j) {\n                double d = est[unassigned[i]][unassigned[j]];\n                if (d < best_d) {\n                    best_d = d;\n                    best_a = i;\n                    best_b = j;\n                }\n            }\n        int a = unassigned[best_a];\n        int b = unassigned[best_b];\n        group_nodes[idx] = {a, b};\n        assigned[a] = assigned[b] = 1;\n        vector<int> nxt;\n        nxt.reserve(U - 2);\n        for (int i = 0; i < U; ++i)\n            if (i != best_a && i != best_b) nxt.push_back(unassigned[i]);\n        unassigned.swap(nxt);\n    }\n\n    for (int idx : order) {\n        if (G[idx] != 1) continue;\n        int v = unassigned.back(); unassigned.pop_back();\n        group_nodes[idx] = {v};\n        assigned[v] = 1;\n    }\n\n    /* ---------- Query allocation ---------- */\n    vector<int> alloc(M, 0);\n    int sum_alloc = 0;\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (g > L) alloc[k] = (g - 1 + L - 2) / (L - 1);\n        else if (g >= 3) alloc[k] = 1;\n        else alloc[k] = 0;\n        sum_alloc += alloc[k];\n    }\n    int surplus = Q - sum_alloc;\n    if (surplus > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) if (G[k] > L) large.push_back(k);\n        sort(large.begin(), large.end(),\n             [&](int a, int b) { return G[a] > G[b]; });\n        while (surplus > 0) {\n            bool changed = false;\n            for (int k : large) {\n                int max_q = G[k] - L + 1;\n                if (alloc[k] < max_q) {\n                    ++alloc[k];\n                    --surplus;\n                    changed = true;\n                    if (surplus == 0) break;\n                }\n            }\n            if (!changed) break;\n        }\n    }\n\n    /* ---------- Perform queries ---------- */\n    vector<vector<pair<int,int>>> raw_edges(M);\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (alloc[k] == 0) continue;\n        const auto &nodes = group_nodes[k];\n        if (g > L) {\n            auto ordered = mst_order(nodes);\n            int q = alloc[k];\n            for (int i = 0; i < q; ++i) {\n                int start = (int)((long long)i * (g - L) / (q - 1));\n                cout << \"? \" << L;\n                for (int j = 0; j < L; ++j) cout << ' ' << ordered[start + j];\n                cout << '\\n' << flush;\n                for (int j = 0; j < L - 1; ++j) {\n                    int a, b; cin >> a >> b;\n                    raw_edges[k].push_back({a, b});\n                }\n            }\n        } else {\n            cout << \"? \" << g;\n            for (int v : nodes) cout << ' ' << v;\n            cout << '\\n' << flush;\n            for (int i = 0; i < g - 1; ++i) {\n                int a, b; cin >> a >> b;\n                raw_edges[k].push_back({a, b});\n            }\n        }\n    }\n\n    /* ---------- Output answer ---------- */\n    cout << \"!\\n\";\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        const auto &nodes = group_nodes[k];\n        for (int i = 0; i < g; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n\n        if (g <= 1) {\n            continue;\n        } else if (g == 2) {\n            cout << nodes[0] << ' ' << nodes[1] << '\\n';\n        } else if (g <= L) {\n            for (auto &e : raw_edges[k])\n                cout << e.first << ' ' << e.second << '\\n';\n        } else {\n            // Kruskal on queried edges only (all are real edges)\n            vector<int> pos(N, -1);\n            for (int i = 0; i < g; ++i) pos[nodes[i]] = i;\n            set<pair<int,int>> seen;\n            vector<tuple<double,int,int>> cand;\n            for (auto &e : raw_edges[k]) {\n                int u = e.first, v = e.second;\n                if (u > v) swap(u, v);\n                if (!seen.insert({u, v}).second) continue;\n                int iu = pos[u], iv = pos[v];\n                if (iu == -1 || iv == -1) continue;\n                cand.emplace_back(est[u][v], u, v);\n            }\n            sort(cand.begin(), cand.end());\n            DSU dsu(g);\n            vector<pair<int,int>> tree_edges;\n            for (auto &t : cand) {\n                int u = get<1>(t), v = get<2>(t);\n                if (dsu.unite(pos[u], pos[v])) {\n                    tree_edges.emplace_back(u, v);\n                    if ((int)tree_edges.size() == g - 1) break;\n                }\n            }\n            if ((int)tree_edges.size() < g - 1) {\n                // fallback to estimated MST\n                auto est_edges = group_mst_edges(nodes);\n                for (auto &e : est_edges) {\n                    int u = e.first, v = e.second;\n                    if (dsu.unite(pos[u], pos[v])) {\n                        tree_edges.push_back(e);\n                        if ((int)tree_edges.size() == g - 1) break;\n                    }\n                }\n            }\n            for (auto &e : tree_edges)\n                cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 0x3F3F3F3F;\nconst int MAXN = 20;\nconst int MAX_ACTIONS = 1600;          // 2 * N * M\nconst int TOP_K = 60;                  // finalists evaluated with exact suffix\n\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\nconst char dname[4] = {'U', 'D', 'L', 'R'};\n\ninline int opp(int d) { return d ^ 1; }\n\nint N, M;\nvector<pair<int,int>> pts;\nusing Grid = array<array<char, MAXN>, MAXN>;\nGrid blocks;\narray<array<int, MAXN>, MAXN> target_id;\nvector<pair<char,char>> ans;\n\n/*---------- fast early-stop distance BFS ----------*/\nint dist_one(int sr, int sc, int tr, int tc, const Grid& blk) {\n    if (sr == tr && sc == tc) return 0;\n    int dist[MAXN][MAXN];\n    pair<int,int> q[MAXN * MAXN];\n    memset(dist, 0x3F, sizeof(dist));\n    int qs = 0, qe = 0;\n    q[qe++] = {sr, sc};\n    dist[sr][sc] = 0;\n    while (qs < qe) {\n        auto [r, c] = q[qs++];\n        int nd = dist[r][c] + 1;\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (blk[nr][nc]) continue;\n            if (dist[nr][nc] > nd) {\n                if (nr == tr && nc == tc) return nd;\n                dist[nr][nc] = nd;\n                q[qe++] = {nr, nc};\n            }\n        }\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            while (nr >= 0 && nr < N && nc >= 0 && nc < N && !blk[nr][nc]) {\n                nr += dr[d];\n                nc += dc[d];\n            }\n            int rr = nr - dr[d];\n            int cc = nc - dc[d];\n            if (rr == r && cc == c) continue;\n            if (dist[rr][cc] > nd) {\n                if (rr == tr && cc == tc) return nd;\n                dist[rr][cc] = nd;\n                q[qe++] = {rr, cc};\n            }\n        }\n    }\n    return INF;\n}\n\n/*---------- exact suffix cost from (sr,sc) over pts[idx..M-1] ----------*/\nint suffix_cost(int sr, int sc, int idx, const Grid& blk) {\n    if (idx >= M) return 0;\n    long long sum = 0;\n    int r = sr, c = sc;\n    for (int k = idx; k < M; ++k) {\n        int d = dist_one(r, c, pts[k].first, pts[k].second, blk);\n        if (d >= INF) return INF;\n        sum += d;\n        if (sum > MAX_ACTIONS) return INF;\n        r = pts[k].first;\n        c = pts[k].second;\n    }\n    return (int)sum;\n}\n\n/*---------- full BFS with parent storage ----------*/\nvoid bfs_full(int sr, int sc, const Grid& blk,\n              array<array<int,MAXN>,MAXN>& dist,\n              array<array<pair<int,int>,MAXN>,MAXN>& par,\n              array<array<char,MAXN>,MAXN>& act,\n              array<array<char,MAXN>,MAXN>& dirc)\n{\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dist[i][j] = INF;\n\n    queue<pair<int,int>> q;\n    dist[sr][sc] = 0;\n    par[sr][sc] = {-1, -1};\n    act[sr][sc] = 0;\n    dirc[sr][sc] = 0;\n    q.emplace(sr, sc);\n\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        int d = dist[r][c];\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (blk[nr][nc]) continue;\n            if (dist[nr][nc] > d + 1) {\n                dist[nr][nc] = d + 1;\n                par[nr][nc] = {r, c};\n                act[nr][nc] = 'M';\n                dirc[nr][nc] = dname[dir];\n                q.emplace(nr, nc);\n            }\n        }\n\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            while (nr >= 0 && nr < N && nc >= 0 && nc < N && !blk[nr][nc]) {\n                nr += dr[dir];\n                nc += dc[dir];\n            }\n            int rr = nr - dr[dir];\n            int cc = nc - dc[dir];\n            if (rr == r && cc == c) continue;\n            if (dist[rr][cc] > d + 1) {\n                dist[rr][cc] = d + 1;\n                par[rr][cc] = {r, c};\n                act[rr][cc] = 'S';\n                dirc[rr][cc] = dname[dir];\n                q.emplace(rr, cc);\n            }\n        }\n    }\n}\n\n/*---------- reconstruct action sequence ----------*/\nvector<pair<char,char>> reconstruct(int sr, int sc, int gr, int gc,\n                                    const array<array<pair<int,int>,MAXN>,MAXN>& par,\n                                    const array<array<char,MAXN>,MAXN>& act,\n                                    const array<array<char,MAXN>,MAXN>& dirc)\n{\n    vector<pair<char,char>> res;\n    int r = gr, c = gc;\n    while (r != sr || c != sc) {\n        res.push_back({act[r][c], dirc[r][c]});\n        auto [pr, pc] = par[r][c];\n        r = pr; c = pc;\n        if (r == -1 && c == -1) break;\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\n/*============================================================*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N >> M)) return 0;\n    pts.resize(M);\n    for (int i = 0; i < M; ++i) cin >> pts[i].first >> pts[i].second;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            blocks[i][j] = 0;\n            target_id[i][j] = -1;\n        }\n    for (int i = 0; i < M; ++i)\n        target_id[pts[i].first][pts[i].second] = i;\n\n    ans.clear();\n    int cur_r = pts[0].first;\n    int cur_c = pts[0].second;\n\n    for (int t = 1; t < M; ++t) {\n        int tr = pts[t].first;\n        int tc = pts[t].second;\n\n        /*--- baseline: one full BFS from current position ---*/\n        array<array<int,MAXN>,MAXN> dist0;\n        array<array<pair<int,int>,MAXN>,MAXN> par0;\n        array<array<char,MAXN>,MAXN> act0, dirc0;\n        bfs_full(cur_r, cur_c, blocks, dist0, par0, act0, dirc0);\n\n        int base_seg0 = dist0[tr][tc];\n        int base_rem  = suffix_cost(tr, tc, t + 1, blocks);\n        int base_total = (base_seg0 >= INF || base_rem >= INF) ? INF : base_seg0 + base_rem;\n\n        struct Cand {\n            int sr, sc, pr, pc;\n            int lb;          // quick lower bound using dist0[pr][pc]\n            int next_seg;    // dist(target -> next) in modified grid\n            char dir;        // alter direction\n            bool remove;\n        };\n        vector<Cand> cands;\n        cands.reserve(2000);\n\n        auto generate = [&](int sr, int sc, bool remove) {\n            if (sr == tr && sc == tc) return;\n            int id = target_id[sr][sc];\n            if (!remove && id > t) return;   // do not block a future target\n            if (remove && id > t) return;    // safety\n\n            Grid mod = blocks;\n            mod[sr][sc] ^= 1;\n\n            for (int pd = 0; pd < 4; ++pd) {\n                int pr = sr + dr[pd];\n                int pc = sc + dc[pd];\n                if (pr < 0 || pr >= N || pc < 0 || pc >= N) continue;\n                if (mod[pr][pc]) continue;   // must stand on empty cell after alter\n                if (dist0[pr][pc] >= INF) continue;\n\n                int d_pt = dist_one(pr, pc, tr, tc, mod);\n                if (d_pt >= INF) continue;\n                int lb = dist0[pr][pc] + 1 + d_pt;\n\n                int next_seg = 0;\n                if (t + 1 < M) {\n                    next_seg = dist_one(tr, tc, pts[t+1].first, pts[t+1].second, mod);\n                    if (next_seg >= INF) continue;\n                }\n\n                cands.push_back({sr, sc, pr, pc, lb, next_seg, dname[opp(pd)], remove});\n            }\n        };\n\n        for (int sr = 0; sr < N; ++sr)\n            for (int sc = 0; sc < N; ++sc)\n                if (!blocks[sr][sc])\n                    generate(sr, sc, false);\n\n        for (int sr = 0; sr < N; ++sr)\n            for (int sc = 0; sc < N; ++sc)\n                if (blocks[sr][sc])\n                    generate(sr, sc, true);\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.lb + a.next_seg < b.lb + b.next_seg;\n        });\n\n        /*--- exact evaluation for top-K finalists ---*/\n        int best_total = base_total;\n        int best_seg0  = base_seg0;\n        int best_sr = -1, best_sc = -1, best_pr = -1, best_pc = -1;\n        char best_alter_dir = 0;\n        bool best_remove = false;\n\n        int limit = min((int)cands.size(), TOP_K);\n        for (int i = 0; i < limit; ++i) {\n            const auto& c = cands[i];\n\n            Grid mod = blocks;\n            mod[c.sr][c.sc] ^= 1;\n\n            int d_cur_P = dist_one(cur_r, cur_c, c.pr, c.pc, mod);\n            if (d_cur_P >= INF) continue;\n            int d_P_target = dist_one(c.pr, c.pc, tr, tc, mod);\n            if (d_P_target >= INF) continue;\n\n            int exact_seg = d_cur_P + 1 + d_P_target;\n            if ((int)ans.size() + exact_seg > MAX_ACTIONS) continue;\n\n            int rem = suffix_cost(tr, tc, t + 1, mod);\n            if (rem >= INF) continue;\n            if ((int)ans.size() + exact_seg + rem > MAX_ACTIONS) continue;\n\n            int total = exact_seg + rem;\n            if (total < best_total || (total == best_total && exact_seg < best_seg0)) {\n                best_total = total;\n                best_seg0  = exact_seg;\n                best_sr = c.sr; best_sc = c.sc;\n                best_pr = c.pr; best_pc = c.pc;\n                best_alter_dir = c.dir;\n                best_remove = c.remove;\n            }\n        }\n\n        /*--- execute best action sequence ---*/\n        if (best_sr != -1 && (best_total < base_total || base_total >= INF)) {\n            // cur -> P\n            auto path1 = reconstruct(cur_r, cur_c, best_pr, best_pc, par0, act0, dirc0);\n            for (auto &ac : path1) ans.push_back(ac);\n            // Alter\n            ans.push_back({'A', best_alter_dir});\n            // Commit block change\n            blocks[best_sr][best_sc] ^= 1;\n            // P -> target (skip if already standing on it)\n            if (best_pr != tr || best_pc != tc) {\n                array<array<int,MAXN>,MAXN> distP;\n                array<array<pair<int,int>,MAXN>,MAXN> parP;\n                array<array<char,MAXN>,MAXN> actP, dircP;\n                bfs_full(best_pr, best_pc, blocks, distP, parP, actP, dircP);\n                auto path2 = reconstruct(best_pr, best_pc, tr, tc, parP, actP, dircP);\n                for (auto &ac : path2) ans.push_back(ac);\n            }\n        } else {\n            // Baseline without altering\n            auto path = reconstruct(cur_r, cur_c, tr, tc, par0, act0, dirc0);\n            for (auto &ac : path) ans.push_back(ac);\n        }\n\n        cur_r = tr;\n        cur_c = tc;\n    }\n\n    for (auto &ac : ans) {\n        cout << ac.first << ' ' << ac.second << '\\n';\n    }\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\nusing ll = long long;\n\nint n;\nvector<int> X, Y, desiredR;\nvector<int> a, b, c, d;\nvector<ll> area;\nvector<double> pval;\ndouble cur_score = 0.0;\ndouble best_score = -1.0;\nvector<int> best_a, best_b, best_c, best_d;\n\nchrono::steady_clock::time_point g_start;\n\ninline double calc_p(int idx, ll s) {\n    if (s <= 0) return 0.0;\n    double t = (s < desiredR[idx]) ? (double)s / desiredR[idx] : (double)desiredR[idx] / s;\n    return 1.0 - (1.0 - t) * (1.0 - t);\n}\n\n// Hilbert curve order for spatial locality\nint hilbertOrder(int x, int y, int pow_=21, int rot=0) {\n    if (pow_ == 0) return 0;\n    int hpow = 1 << (pow_-1);\n    int seg = (x < hpow) ? ((y < hpow) ? 0 : 3) : ((y < hpow) ? 1 : 2);\n    seg = (seg + rot) & 3;\n    const int rotateDelta[4] = {3, 0, 0, 1};\n    int nx = x & (hpow - 1), ny = y & (hpow - 1);\n    int nrot = (rot + rotateDelta[seg]) & 3;\n    int subSquareSize = 1 << (2*pow_ - 2);\n    int ans = seg * subSquareSize;\n    int add = hilbertOrder(nx, ny, pow_-1, nrot);\n    ans += (seg==1 || seg==2) ? add : (subSquareSize - add - 1);\n    return ans;\n}\n\npair<int,int> get_range(int i, int side) {\n    int Lo = 0, Hi = 10000;\n    if (side == 0) {\n        Lo = 0;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) Lo = max(Lo, c[j]);\n        }\n        Hi = X[i];\n    } else if (side == 1) {\n        Lo = X[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) Hi = min(Hi, a[j]);\n        }\n    } else if (side == 2) {\n        Lo = 0;\n        Hi = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) Lo = max(Lo, d[j]);\n        }\n    } else {\n        Lo = Y[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) Hi = min(Hi, b[j]);\n        }\n    }\n    return {Lo, Hi};\n}\n\npair<int,int> get_range_ignore(int i, int side, int ign) {\n    int Lo = 0, Hi = 10000;\n    if (side == 0) {\n        Lo = 0;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (b[j] < d[i] && d[j] > b[i] && a[j] < c[i]) Lo = max(Lo, c[j]);\n        }\n        Hi = X[i];\n    } else if (side == 1) {\n        Lo = X[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (b[j] < d[i] && d[j] > b[i] && c[j] > a[i]) Hi = min(Hi, a[j]);\n        }\n    } else if (side == 2) {\n        Lo = 0;\n        Hi = Y[i];\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (a[j] < c[i] && c[j] > a[i] && b[j] < d[i]) Lo = max(Lo, d[j]);\n        }\n    } else {\n        Lo = Y[i] + 1;\n        Hi = 10000;\n        for (int j = 0; j < n; ++j) if (j != i && j != ign) {\n            if (a[j] < c[i] && c[j] > a[i] && d[j] > b[i]) Hi = min(Hi, b[j]);\n        }\n    }\n    return {Lo, Hi};\n}\n\ninline int get_cur(int i, int side) {\n    return side == 0 ? a[i] : (side == 1 ? c[i] : (side == 2 ? b[i] : d[i]));\n}\n\ninline int get_opt1d(int i, int side, int Lo, int Hi) {\n    int opt;\n    if (side == 0) {\n        ll h = d[i] - b[i];\n        int w = max(1, (int)round((double)desiredR[i] / (double)h));\n        opt = c[i] - w;\n    } else if (side == 1) {\n        ll h = d[i] - b[i];\n        int w = max(1, (int)round((double)desiredR[i] / (double)h));\n        opt = a[i] + w;\n    } else if (side == 2) {\n        ll w = c[i] - a[i];\n        int h = max(1, (int)round((double)desiredR[i] / (double)w));\n        opt = d[i] - h;\n    } else {\n        ll w = c[i] - a[i];\n        int h = max(1, (int)round((double)desiredR[i] / (double)w));\n        opt = b[i] + h;\n    }\n    if (opt < Lo) opt = Lo;\n    if (opt > Hi) opt = Hi;\n    return opt;\n}\n\ninline void apply_single(int i, int side, int v) {\n    if (side == 0) a[i] = v;\n    else if (side == 1) c[i] = v;\n    else if (side == 2) b[i] = v;\n    else d[i] = v;\n    ll na = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np;\n    area[i] = na;\n}\n\ninline bool overlap_others(int i, int na, int nb, int nc, int nd) {\n    for (int j = 0; j < n; ++j) if (j != i) {\n        if (max(na, a[j]) < min(nc, c[j]) && max(nb, b[j]) < min(nd, d[j])) return true;\n    }\n    return false;\n}\n\ninline void apply_corner(int i, int corner, int v1, int v2) {\n    if (corner == 0) { c[i] = v1; d[i] = v2; }\n    else if (corner == 1) { a[i] = v1; d[i] = v2; }\n    else if (corner == 2) { c[i] = v1; b[i] = v2; }\n    else { a[i] = v1; b[i] = v2; }\n    ll na = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np;\n    area[i] = na;\n}\n\nvoid save_best() {\n    if (cur_score > best_score) {\n        best_score = cur_score;\n        best_a = a; best_b = b; best_c = c; best_d = d;\n    }\n}\n\nvoid restore_best() {\n    a = best_a; b = best_b; c = best_c; d = best_d;\n    cur_score = 0.0;\n    for (int i = 0; i < n; ++i) {\n        area[i] = 1LL * (c[i] - a[i]) * (d[i] - b[i]);\n        pval[i] = calc_p(i, area[i]);\n        cur_score += pval[i];\n    }\n}\n\nvoid reset_1x1() {\n    for (int i = 0; i < n; ++i) {\n        a[i] = X[i]; b[i] = Y[i]; c[i] = X[i] + 1; d[i] = Y[i] + 1;\n        area[i] = 1;\n        pval[i] = calc_p(i, 1);\n    }\n    cur_score = 0.0;\n    for (int i = 0; i < n; ++i) cur_score += pval[i];\n}\n\nvoid greedy_single_pass(const vector<int>& ord) {\n    for (int i : ord) {\n        double best_delta = 1e-12;\n        int best_side = -1, best_v = -1;\n        for (int side = 0; side < 4; ++side) {\n            auto [Lo, Hi] = get_range(i, side);\n            int cur = get_cur(i, side);\n            int opt = get_opt1d(i, side, Lo, Hi);\n            if (opt == cur) continue;\n            ll na;\n            if (side == 0) na = 1LL * (c[i] - opt) * (d[i] - b[i]);\n            else if (side == 1) na = 1LL * (opt - a[i]) * (d[i] - b[i]);\n            else if (side == 2) na = 1LL * (c[i] - a[i]) * (d[i] - opt);\n            else na = 1LL * (c[i] - a[i]) * (opt - b[i]);\n            double np = calc_p(i, na);\n            double delta = np - pval[i];\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_side = side;\n                best_v = opt;\n            }\n        }\n        if (best_side != -1) apply_single(i, best_side, best_v);\n    }\n}\n\nvoid greedy_single_pass_rng(mt19937_64& rng) {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    shuffle(ord.begin(), ord.end(), rng);\n    greedy_single_pass(ord);\n}\n\nvector<int> ord_by_p_asc() {\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int x, int y){ return pval[x] < pval[y]; });\n    return ord;\n}\n\nvoid greedy_init_fast(mt19937_64& rng, int max_pass) {\n    for (int pass = 0; pass < max_pass; ++pass) {\n        double old = cur_score;\n        greedy_single_pass_rng(rng);\n        if (cur_score <= old + 1e-9) break;\n    }\n}\n\nvoid greedy_init_full(const vector<int>& ord) {\n    for (int pass = 0; pass < 100; ++pass) {\n        double old = cur_score;\n        greedy_single_pass(ord);\n        if (cur_score <= old + 1e-9) break;\n    }\n}\n\n// ---------- corner evaluation ----------\ntuple<double,int,int> eval_corner(int i, int corner) {\n    if (corner == 0) { // TR: c,d\n        auto [cL, cR] = get_range(i, 1);\n        if (cL >= cR) return {-1.0, -1, -1};\n        vector<int> cvals = {cL, cR};\n        int csq = a[i] + max(1, (int)round(sqrt((double)desiredR[i])));\n        int copt = a[i] + max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (csq > cL && csq < cR) cvals.push_back(csq);\n        if (copt > cL && copt < cR) cvals.push_back(copt);\n        sort(cvals.begin(), cvals.end());\n        cvals.erase(unique(cvals.begin(), cvals.end()), cvals.end());\n        double best_delta = -1.0;\n        int best_c = -1, best_d = -1;\n        for (int cc : cvals) {\n            int old_c = c[i]; c[i] = cc;\n            auto [dL, dR] = get_range(i, 3);\n            c[i] = old_c;\n            if (dL > dR) continue;\n            int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n            vector<int> dvals = {dL, dR, clamp(dtgt, dL, dR)};\n            sort(dvals.begin(), dvals.end());\n            dvals.erase(unique(dvals.begin(), dvals.end()), dvals.end());\n            for (int dd : dvals) {\n                if (overlap_others(i, a[i], b[i], cc, dd)) continue;\n                ll na = 1LL * (cc - a[i]) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_c = cc; best_d = dd;\n                }\n            }\n        }\n        return {best_delta, best_c, best_d};\n    } else if (corner == 1) { // TL: a,d\n        auto [aL, aR] = get_range(i, 0);\n        if (aL >= aR) return {-1.0, -1, -1};\n        vector<int> avals = {aL, aR};\n        int asq = c[i] - max(1, (int)round(sqrt((double)desiredR[i])));\n        int aopt = c[i] - max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (asq > aL && asq < aR) avals.push_back(asq);\n        if (aopt > aL && aopt < aR) avals.push_back(aopt);\n        sort(avals.begin(), avals.end());\n        avals.erase(unique(avals.begin(), avals.end()), avals.end());\n        double best_delta = -1.0;\n        int best_a2 = -1, best_d2 = -1;\n        for (int aa : avals) {\n            int old_a = a[i]; a[i] = aa;\n            auto [dL, dR] = get_range(i, 3);\n            a[i] = old_a;\n            if (dL > dR) continue;\n            int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n            vector<int> dvals = {dL, dR, clamp(dtgt, dL, dR)};\n            sort(dvals.begin(), dvals.end());\n            dvals.erase(unique(dvals.begin(), dvals.end()), dvals.end());\n            for (int dd : dvals) {\n                if (overlap_others(i, aa, b[i], c[i], dd)) continue;\n                ll na = 1LL * (c[i] - aa) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_a2 = aa; best_d2 = dd;\n                }\n            }\n        }\n        return {best_delta, best_a2, best_d2};\n    } else if (corner == 2) { // BR: c,b\n        auto [cL, cR] = get_range(i, 1);\n        if (cL >= cR) return {-1.0, -1, -1};\n        vector<int> cvals = {cL, cR};\n        int csq = a[i] + max(1, (int)round(sqrt((double)desiredR[i])));\n        int copt = a[i] + max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (csq > cL && csq < cR) cvals.push_back(csq);\n        if (copt > cL && copt < cR) cvals.push_back(copt);\n        sort(cvals.begin(), cvals.end());\n        cvals.erase(unique(cvals.begin(), cvals.end()), cvals.end());\n        double best_delta = -1.0;\n        int best_c = -1, best_b2 = -1;\n        for (int cc : cvals) {\n            int old_c = c[i]; c[i] = cc;\n            auto [bL, bR] = get_range(i, 2);\n            c[i] = old_c;\n            if (bL > bR) continue;\n            int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n            vector<int> bvals = {bL, bR, clamp(btgt, bL, bR)};\n            sort(bvals.begin(), bvals.end());\n            bvals.erase(unique(bvals.begin(), bvals.end()), bvals.end());\n            for (int bb : bvals) {\n                if (overlap_others(i, a[i], bb, cc, d[i])) continue;\n                ll na = 1LL * (cc - a[i]) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_c = cc; best_b2 = bb;\n                }\n            }\n        }\n        return {best_delta, best_c, best_b2};\n    } else { // BL: a,b\n        auto [aL, aR] = get_range(i, 0);\n        if (aL >= aR) return {-1.0, -1, -1};\n        vector<int> avals = {aL, aR};\n        int asq = c[i] - max(1, (int)round(sqrt((double)desiredR[i])));\n        int aopt = c[i] - max(1, (int)round((double)desiredR[i] / (double)(d[i] - b[i])));\n        if (asq > aL && asq < aR) avals.push_back(asq);\n        if (aopt > aL && aopt < aR) avals.push_back(aopt);\n        sort(avals.begin(), avals.end());\n        avals.erase(unique(avals.begin(), avals.end()), avals.end());\n        double best_delta = -1.0;\n        int best_a2 = -1, best_b2 = -1;\n        for (int aa : avals) {\n            int old_a = a[i]; a[i] = aa;\n            auto [bL, bR] = get_range(i, 2);\n            a[i] = old_a;\n            if (bL > bR) continue;\n            int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n            vector<int> bvals = {bL, bR, clamp(btgt, bL, bR)};\n            sort(bvals.begin(), bvals.end());\n            bvals.erase(unique(bvals.begin(), bvals.end()), bvals.end());\n            for (int bb : bvals) {\n                if (overlap_others(i, aa, bb, c[i], d[i])) continue;\n                ll na = 1LL * (c[i] - aa) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > best_delta) {\n                    best_delta = delta;\n                    best_a2 = aa; best_b2 = bb;\n                }\n            }\n        }\n        return {best_delta, best_a2, best_b2};\n    }\n}\n\nvoid greedy_corner_pass(const vector<int>& ord) {\n    for (int i : ord) {\n        double best_delta = 1e-12;\n        int best_corner = -1, best_v1 = -1, best_v2 = -1;\n        for (int corner = 0; corner < 4; ++corner) {\n            auto [delta, v1, v2] = eval_corner(i, corner);\n            if (delta > best_delta) {\n                best_delta = delta;\n                best_corner = corner;\n                best_v1 = v1; best_v2 = v2;\n            }\n        }\n        if (best_corner != -1) apply_corner(i, best_corner, best_v1, best_v2);\n    }\n}\n\n// ---------- pair wall ----------\nint find_neighbor(int i, int dir) {\n    int best = -1;\n    int best_gap = 100000;\n    for (int j = 0; j < n; ++j) if (j != i) {\n        bool xov = (a[j] < c[i] && c[j] > a[i]);\n        bool yov = (b[j] < d[i] && d[j] > b[i]);\n        if (dir == 0 && yov && c[j] <= a[i]) {\n            int gap = a[i] - c[j];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 1 && yov && a[j] >= c[i]) {\n            int gap = a[j] - c[i];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 2 && xov && d[j] <= b[i]) {\n            int gap = b[i] - d[j];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        } else if (dir == 3 && xov && b[j] >= d[i]) {\n            int gap = b[j] - d[i];\n            if (gap < best_gap) { best_gap = gap; best = j; }\n        }\n    }\n    return (best_gap == 0) ? best : -1;\n}\n\ntuple<double,int> eval_pair_wall(int i, int dir, int j) {\n    int Lo, Hi;\n    if (dir == 0) {\n        auto r1 = get_range_ignore(i, 0, j);\n        auto r2 = get_range_ignore(j, 1, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else if (dir == 1) {\n        auto r1 = get_range_ignore(i, 1, j);\n        auto r2 = get_range_ignore(j, 0, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else if (dir == 2) {\n        auto r1 = get_range_ignore(i, 2, j);\n        auto r2 = get_range_ignore(j, 3, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    } else {\n        auto r1 = get_range_ignore(i, 3, j);\n        auto r2 = get_range_ignore(j, 2, i);\n        Lo = max(r1.first, r2.first);\n        Hi = min(r1.second, r2.second);\n    }\n    if (Lo > Hi) return {-1.0, Lo};\n\n    auto compute_g = [&](int v) -> double {\n        if (dir <= 1) {\n            ll ai = 1LL * ((dir==0 ? (c[i]-v) : (v-a[i]))) * (d[i]-b[i]);\n            ll aj = 1LL * ((dir==0 ? (v-a[j]) : (c[j]-v))) * (d[j]-b[j]);\n            return calc_p(i, ai) + calc_p(j, aj);\n        } else {\n            ll ai = 1LL * (c[i]-a[i]) * ((dir==2 ? (d[i]-v) : (v-b[i])));\n            ll aj = 1LL * (c[j]-a[j]) * ((dir==2 ? (v-b[j]) : (d[j]-v)));\n            return calc_p(i, ai) + calc_p(j, aj);\n        }\n    };\n\n    vector<int> cand = {Lo, Hi};\n    if (dir <= 1) {\n        int x1 = a[i] + (int)round((double)desiredR[i] / (double)(d[i] - b[i]));\n        int x2 = c[j] - (int)round((double)desiredR[j] / (double)(d[j] - b[j]));\n        cand.push_back(clamp(x1, Lo, Hi));\n        cand.push_back(clamp(x2, Lo, Hi));\n        cand.push_back((Lo + Hi) / 2);\n    } else {\n        int y1 = b[i] + (int)round((double)desiredR[i] / (double)(c[i] - a[i]));\n        int y2 = d[j] - (int)round((double)desiredR[j] / (double)(c[j] - a[j]));\n        cand.push_back(clamp(y1, Lo, Hi));\n        cand.push_back(clamp(y2, Lo, Hi));\n        cand.push_back((Lo + Hi) / 2);\n    }\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n    double best_sc = -1e300;\n    int best_coord = Lo;\n    for (int v : cand) {\n        double g = compute_g(v);\n        if (g > best_sc) {\n            best_sc = g;\n            best_coord = v;\n        }\n    }\n\n    // local refinement around best coarse candidate\n    for (int dv = -15; dv <= 15; ++dv) {\n        int vv = best_coord + dv;\n        if (vv < Lo || vv > Hi || vv == best_coord) continue;\n        double g = compute_g(vv);\n        if (g > best_sc) {\n            best_sc = g;\n            best_coord = vv;\n        }\n    }\n\n    double delta = best_sc - (pval[i] + pval[j]);\n    return {delta, best_coord};\n}\n\ninline void apply_pair_wall(int i, int dir, int j, int v) {\n    if (dir == 0) { a[i] = v; c[j] = v; }\n    else if (dir == 1) { c[i] = v; a[j] = v; }\n    else if (dir == 2) { b[i] = v; d[j] = v; }\n    else { d[i] = v; b[j] = v; }\n    ll na = 1LL * (c[i]-a[i]) * (d[i]-b[i]);\n    double np = calc_p(i, na);\n    cur_score += np - pval[i];\n    pval[i] = np; area[i] = na;\n    ll na2 = 1LL * (c[j]-a[j]) * (d[j]-b[j]);\n    double np2 = calc_p(j, na2);\n    cur_score += np2 - pval[j];\n    pval[j] = np2; area[j] = na2;\n}\n\nvoid greedy_pair_pass(mt19937_64& rng) {\n    vector<pair<int,int>> vec;\n    for (int i = 0; i < n; ++i) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int j = find_neighbor(i, dir);\n            if (j >= 0) vec.emplace_back(i, dir);\n        }\n    }\n    shuffle(vec.begin(), vec.end(), rng);\n    for (auto [i, dir] : vec) {\n        int j = find_neighbor(i, dir);\n        if (j < 0) continue;\n        auto [delta, v] = eval_pair_wall(i, dir, j);\n        if (delta > 1e-12) apply_pair_wall(i, dir, j, v);\n    }\n}\n\nvoid greedy_pair_pass_ordered(const vector<int>& ord) {\n    for (int i : ord) {\n        for (int dir = 0; dir < 4; ++dir) {\n            int j = find_neighbor(i, dir);\n            if (j < 0) continue;\n            auto [delta, v] = eval_pair_wall(i, dir, j);\n            if (delta > 1e-12) apply_pair_wall(i, dir, j, v);\n        }\n    }\n}\n\n// ---------- SA ----------\nvoid run_sa(mt19937_64& rng, double time_limit) {\n    uniform_real_distribution<double> dist01(0.0, 1.0);\n    long long iter = 0;\n    while (true) {\n        ++iter;\n        if ((iter & 2047) == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - g_start).count();\n            if (elapsed > time_limit) break;\n        }\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - g_start).count();\n        double T = 0.08 * pow(1e-5 / 0.08, elapsed / time_limit);\n\n        int i;\n        if (dist01(rng) < 0.30) {\n            vector<int> low;\n            for (int k = 0; k < n; ++k) if (pval[k] < 0.95) low.push_back(k);\n            if (low.empty()) i = (int)(rng() % n);\n            else i = low[(int)(rng() % low.size())];\n        } else {\n            i = (int)(rng() % n);\n        }\n\n        int mtype = (int)(rng() % 100);\n        if (mtype < 70) {\n            // single-side move\n            int side = (int)(rng() % 4);\n            auto [Lo, Hi] = get_range(i, side);\n            if (Lo >= Hi) continue;\n            int cur = get_cur(i, side);\n            int opt = get_opt1d(i, side, Lo, Hi);\n            int nv;\n            double r = dist01(rng);\n            if (r < 0.5) nv = opt;\n            else if (r < 0.8) {\n                int delta = (int)(dist01(rng) * 201) - 100;\n                nv = opt + delta;\n            } else {\n                nv = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n            }\n            if (nv < Lo) nv = Lo;\n            if (nv > Hi) nv = Hi;\n            if (nv == cur) continue;\n            ll na;\n            if (side == 0) na = 1LL * (c[i] - nv) * (d[i] - b[i]);\n            else if (side == 1) na = 1LL * (nv - a[i]) * (d[i] - b[i]);\n            else if (side == 2) na = 1LL * (c[i] - a[i]) * (d[i] - nv);\n            else na = 1LL * (c[i] - a[i]) * (nv - b[i]);\n            double np = calc_p(i, na);\n            double delta = np - pval[i];\n            if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                apply_single(i, side, nv);\n                save_best();\n            }\n        } else if (mtype < 85) {\n            // pair-wall move\n            int dir = (int)(rng() % 4);\n            int j = find_neighbor(i, dir);\n            if (j < 0) continue;\n            auto [delta, v] = eval_pair_wall(i, dir, j);\n            if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                apply_pair_wall(i, dir, j, v);\n                save_best();\n            }\n        } else {\n            // corner-resize move\n            int corner = (int)(rng() % 4);\n            if (corner == 0) { // TR: c,d\n                auto [Lo, Hi] = get_range(i, 1);\n                if (Lo >= Hi) continue;\n                int cc = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_c = c[i]; c[i] = cc;\n                auto [dL, dR] = get_range(i, 3);\n                c[i] = old_c;\n                if (dL > dR) continue;\n                int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n                int dd = dtgt;\n                if (dd < dL) dd = dL;\n                if (dd > dR) dd = dR;\n                if (dist01(rng) < 0.5) dd = dL + (int)(dist01(rng) * (dR - dL + 1));\n                if (overlap_others(i, a[i], b[i], cc, dd)) continue;\n                ll na = 1LL * (cc - a[i]) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 0, cc, dd);\n                    save_best();\n                }\n            } else if (corner == 1) { // TL: a,d\n                auto [Lo, Hi] = get_range(i, 0);\n                if (Lo >= Hi) continue;\n                int aa = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_a = a[i]; a[i] = aa;\n                auto [dL, dR] = get_range(i, 3);\n                a[i] = old_a;\n                if (dL > dR) continue;\n                int dtgt = b[i] + max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n                int dd = dtgt;\n                if (dd < dL) dd = dL;\n                if (dd > dR) dd = dR;\n                if (dist01(rng) < 0.5) dd = dL + (int)(dist01(rng) * (dR - dL + 1));\n                if (overlap_others(i, aa, b[i], c[i], dd)) continue;\n                ll na = 1LL * (c[i] - aa) * (dd - b[i]);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 1, aa, dd);\n                    save_best();\n                }\n            } else if (corner == 2) { // BR: c,b\n                auto [Lo, Hi] = get_range(i, 1);\n                if (Lo >= Hi) continue;\n                int cc = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_c = c[i]; c[i] = cc;\n                auto [bL, bR] = get_range(i, 2);\n                c[i] = old_c;\n                if (bL > bR) continue;\n                int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(cc - a[i])));\n                int bb = btgt;\n                if (bb < bL) bb = bL;\n                if (bb > bR) bb = bR;\n                if (dist01(rng) < 0.5) bb = bL + (int)(dist01(rng) * (bR - bL + 1));\n                if (overlap_others(i, a[i], bb, cc, d[i])) continue;\n                ll na = 1LL * (cc - a[i]) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 2, cc, bb);\n                    save_best();\n                }\n            } else { // BL: a,b\n                auto [Lo, Hi] = get_range(i, 0);\n                if (Lo >= Hi) continue;\n                int aa = Lo + (int)(dist01(rng) * (Hi - Lo + 1));\n                int old_a = a[i]; a[i] = aa;\n                auto [bL, bR] = get_range(i, 2);\n                a[i] = old_a;\n                if (bL > bR) continue;\n                int btgt = d[i] - max(1, (int)round((double)desiredR[i] / (double)(c[i] - aa)));\n                int bb = btgt;\n                if (bb < bL) bb = bL;\n                if (bb > bR) bb = bR;\n                if (dist01(rng) < 0.5) bb = bL + (int)(dist01(rng) * (bR - bL + 1));\n                if (overlap_others(i, aa, bb, c[i], d[i])) continue;\n                ll na = 1LL * (c[i] - aa) * (d[i] - bb);\n                double np = calc_p(i, na);\n                double delta = np - pval[i];\n                if (delta > 0.0 || dist01(rng) < exp(delta / T)) {\n                    apply_corner(i, 3, aa, bb);\n                    save_best();\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n;\n    X.resize(n); Y.resize(n); desiredR.resize(n);\n    for (int i = 0; i < n; ++i) cin >> X[i] >> Y[i] >> desiredR[i];\n    a.resize(n); b.resize(n); c.resize(n); d.resize(n);\n    area.resize(n); pval.resize(n);\n\n    mt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    g_start = chrono::steady_clock::now();\n\n    best_score = -1.0;\n\n    // deterministic large-first\n    vector<int> ord_desc(n);\n    iota(ord_desc.begin(), ord_desc.end(), 0);\n    sort(ord_desc.begin(), ord_desc.end(),\n         [&](int x, int y){ return desiredR[x] > desiredR[y]; });\n    reset_1x1();\n    greedy_init_full(ord_desc);\n    save_best();\n\n    // deterministic Hilbert (spatial) order\n    vector<int> ord_hilbert(n);\n    iota(ord_hilbert.begin(), ord_hilbert.end(), 0);\n    sort(ord_hilbert.begin(), ord_hilbert.end(),\n         [&](int x, int y){ return hilbertOrder(X[x], Y[x]) < hilbertOrder(X[y], Y[y]); });\n    reset_1x1();\n    greedy_init_full(ord_hilbert);\n    save_best();\n\n    // many fast random restarts\n    for (int trial = 0; trial < 80; ++trial) {\n        reset_1x1();\n        greedy_init_fast(rng, 5);\n        save_best();\n    }\n    restore_best();\n\n    // SA\n    run_sa(rng, 4.93);\n    restore_best();\n\n    // Final polish\n    for (int pass = 0; pass < 100; ++pass) {\n        double old = cur_score;\n        vector<int> ord = ord_by_p_asc();\n        greedy_single_pass(ord);\n        greedy_corner_pass(ord);\n        greedy_pair_pass(rng);\n        if (cur_score <= old + 1e-9) break;\n    }\n\n    // deterministic pair sweep on low-p rectangles\n    {\n        vector<int> ord = ord_by_p_asc();\n        greedy_pair_pass_ordered(ord);\n    }\n\n    save_best();\n    restore_best();\n\n    for (int i = 0; i < n; ++i) {\n        cout << a[i] << ' ' << b[i] << ' ' << c[i] << ' ' << d[i] << '\\n';\n    }\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int H = 50, W = 50, N = 2500;\n\nint cell_tile[N];\nint cell_val[N];\nint nxt_cell[N][4];\nunsigned char used[2500];\nunsigned char deg[N];\nint tile_cell[2500][2];\nunsigned char tile_cell_cnt[2500];\n\nstatic uint64_t fstate;\ninline uint32_t fnoise() {\n    fstate = fstate * 6364136223846793005ULL + 1442695040888963407ULL;\n    return (uint32_t)(fstate >> 33);\n}\n\ninline void mark_tile(int t) {\n    used[t] = 1;\n    for (int k = 0; k < tile_cell_cnt[t]; ++k) {\n        int c = tile_cell[t][k];\n        int n0 = nxt_cell[c][0]; if (n0 != -1) deg[n0]--;\n        int n1 = nxt_cell[c][1]; if (n1 != -1) deg[n1]--;\n        int n2 = nxt_cell[c][2]; if (n2 != -1) deg[n2]--;\n        int n3 = nxt_cell[c][3]; if (n3 != -1) deg[n3]--;\n    }\n}\n\ninline void unmark_tile(int t) {\n    used[t] = 0;\n    for (int k = 0; k < tile_cell_cnt[t]; ++k) {\n        int c = tile_cell[t][k];\n        int n0 = nxt_cell[c][0]; if (n0 != -1) deg[n0]++;\n        int n1 = nxt_cell[c][1]; if (n1 != -1) deg[n1]++;\n        int n2 = nxt_cell[c][2]; if (n2 != -1) deg[n2]++;\n        int n3 = nxt_cell[c][3]; if (n3 != -1) deg[n3]++;\n    }\n}\n\n/* Greedy rollout from start_pos. Tile at start_pos must NOT be marked. */\ninline int simulate(int start_pos, int dw, int vw, bool noise) {\n    int stack[2500];\n    int sp = 0;\n    int t0 = cell_tile[start_pos];\n    mark_tile(t0);\n    stack[sp++] = t0;\n    int cur = start_pos;\n    int gain = 0;\n\n    while (true) {\n        int best_nxt = -1;\n        int best_pri = -1000000000;\n\n        for (int d = 0; d < 4; ++d) {\n            int np = nxt_cell[cur][d];\n            if (np == -1) continue;\n            int nt = cell_tile[np];\n            if (used[nt]) continue;\n\n            int d_np = deg[np];\n            int bad = 0;\n            for (int d2 = 0; d2 < 4; ++d2) {\n                int w = nxt_cell[np][d2];\n                if (w == -1) continue;\n                int tw = cell_tile[w];\n                if (tw == nt) continue;\n                if (used[tw]) continue;\n                int dw2 = deg[w];\n                if (dw2 <= 1) bad += 5;\n                else if (dw2 == 2) bad += 1;\n            }\n\n            int pri = cell_val[np] * vw;\n            if (d_np == 0) pri -= 500000;\n            else pri -= d_np * dw + bad * 10000;\n            if (noise) pri += (int)(fnoise() & 127u);\n\n            if (pri > best_pri) {\n                best_pri = pri;\n                best_nxt = np;\n            }\n        }\n\n        if (best_nxt == -1) break;\n        int nt = cell_tile[best_nxt];\n        mark_tile(nt);\n        stack[sp++] = nt;\n        gain += cell_val[best_nxt];\n        cur = best_nxt;\n    }\n\n    while (sp > 0) unmark_tile(stack[--sp]);\n    return gain;\n}\n\n/* 2-ply evaluation. Tile at pos must NOT be marked. */\ninline int eval_2ply(int pos, int dw, int vw) {\n    int tp = cell_tile[pos];\n    mark_tile(tp);\n    int best_future = 0;\n    for (int d = 0; d < 4; ++d) {\n        int c2 = nxt_cell[pos][d];\n        if (c2 == -1) continue;\n        int t2 = cell_tile[c2];\n        if (used[t2]) continue;\n        int future = cell_val[c2] + simulate(c2, dw, vw, false);\n        if (future > best_future) best_future = future;\n    }\n    unmark_tile(tp);\n    return cell_val[pos] + best_future;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int si, sj;\n    cin >> si >> sj;\n\n    int M = 0;\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int x; cin >> x;\n            cell_tile[i * W + j] = x;\n            M = max(M, x + 1);\n        }\n    }\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            cin >> cell_val[i * W + j];\n        }\n    }\n\n    for (int i = 0; i < M; ++i) tile_cell_cnt[i] = 0;\n    for (int c = 0; c < N; ++c) {\n        int t = cell_tile[c];\n        tile_cell[t][tile_cell_cnt[t]++] = c;\n    }\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int id = i * W + j;\n            nxt_cell[id][0] = (i > 0)     ? id - W : -1;\n            nxt_cell[id][1] = (i + 1 < H) ? id + W : -1;\n            nxt_cell[id][2] = (j > 0)     ? id - 1 : -1;\n            nxt_cell[id][3] = (j + 1 < W) ? id + 1 : -1;\n        }\n    }\n\n    const char dch[4] = {'U', 'D', 'L', 'R'};\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    string best_path;\n    int best_score = -1;\n\n    const int NUM_FIXED = 14;\n    int fixed_dw[NUM_FIXED] = {3000, 2000, 1500, 1000, 800, 600, 400, 200, 100, 50, 2000, 100, 500, 300};\n    int fixed_vw[NUM_FIXED] = {0,    0,    1,    1,   1,   1,   2,   2,   5,   10, 1,    0,   3,   4};\n\n    int iter = 0;\n    while (true) {\n        if ((iter & 15) == 0 && elapsed() > 1.97) break;\n\n        int dw, vw;\n        bool noise;\n        if (iter < NUM_FIXED) {\n            dw = fixed_dw[iter];\n            vw = fixed_vw[iter];\n            noise = false;\n            fstate = 123456789ULL + (uint64_t)iter * 1000003ULL;\n        } else {\n            dw = 50 + (int)(rng() & 2047);\n            vw = (int)(rng() & 31);\n            noise = true;\n            fstate = ((uint64_t)rng() << 32) | (uint64_t)rng();\n        }\n\n        memset(used, 0, M);\n        for (int c = 0; c < N; ++c) {\n            int tc = cell_tile[c];\n            int d = 0;\n            int n0 = nxt_cell[c][0]; if (n0 != -1 && cell_tile[n0] != tc) ++d;\n            int n1 = nxt_cell[c][1]; if (n1 != -1 && cell_tile[n1] != tc) ++d;\n            int n2 = nxt_cell[c][2]; if (n2 != -1 && cell_tile[n2] != tc) ++d;\n            int n3 = nxt_cell[c][3]; if (n3 != -1 && cell_tile[n3] != tc) ++d;\n            deg[c] = (unsigned char)d;\n        }\n\n        int pos = si * W + sj;\n        mark_tile(cell_tile[pos]);\n        int cur_score = cell_val[pos];\n        string path;\n        path.reserve(2500);\n\n        while (true) {\n            int cand_pos[4];\n            int cand_dir[4];\n            int cand_cnt = 0;\n            for (int d = 0; d < 4; ++d) {\n                int np = nxt_cell[pos][d];\n                if (np != -1 && !used[cell_tile[np]]) {\n                    cand_pos[cand_cnt] = np;\n                    cand_dir[cand_cnt] = d;\n                    ++cand_cnt;\n                }\n            }\n            if (cand_cnt == 0) break;\n\n            int best_eval = -1;\n            int best_idx = 0;\n            if (cand_cnt == 1) {\n                best_idx = 0;\n            } else {\n                bool use_2ply = ((int)path.size() < 25 || cand_cnt == 2);\n                for (int i = 0; i < cand_cnt; ++i) {\n                    int eval = use_2ply\n                        ? eval_2ply(cand_pos[i], dw, vw)\n                        : cell_val[cand_pos[i]] + simulate(cand_pos[i], dw, vw, noise);\n                    \n                    // connectivity bonus: prefer moves adjacent to well-connected cells\n                    if (!use_2ply) {\n                        int conn = 0;\n                        int t = cell_tile[cand_pos[i]];\n                        for (int d = 0; d < 4; ++d) {\n                            int n = nxt_cell[cand_pos[i]][d];\n                            if (n == -1) continue;\n                            int tn = cell_tile[n];\n                            if (tn == t) continue;\n                            if (used[tn]) continue;\n                            conn += deg[n];\n                        }\n                        eval += conn;\n                    }\n                    \n                    if (noise && !use_2ply) eval += (int)(fnoise() & 127u);\n                    if (eval > best_eval) {\n                        best_eval = eval;\n                        best_idx = i;\n                    }\n                }\n            }\n\n            int np = cand_pos[best_idx];\n            int nd = cand_dir[best_idx];\n            mark_tile(cell_tile[np]);\n            cur_score += cell_val[np];\n            path.push_back(dch[nd]);\n            pos = np;\n        }\n\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_path = path;\n        }\n        ++iter;\n    }\n\n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct SplitInfo {\n    bool use = false;\n    int s = -1;\n    double ml = 0.0, mr = 0.0;\n    double mean_single = 0.0;\n    bool has_obs = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 30;\n    const double MINW = 1000.0;\n    const double MAXW = 9000.0;\n    const double LR   = 0.5;\n\n    vector<vector<double>> est_h(N, vector<double>(N - 1, 5000.0));\n    vector<vector<double>> est_v(N - 1, vector<double>(N, 5000.0));\n    vector<vector<int>>    cnt_h(N, vector<int>(N - 1, 0));\n    vector<vector<int>>    cnt_v(N - 1, vector<int>(N, 0));\n\n    double global_mean = 5000.0;\n    bool likely_m2 = false;\n\n    for (int query = 0; query < 1000; ++query) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) break;\n\n        /* ---- exploration and safety-margin schedules ---- */\n        double explore = 0.0;\n        if      (query < 200) explore = 0.50;\n        else if (query < 400) explore = 0.25;\n        else if (query < 700) explore = 0.10;\n\n        double margin = (query < 150) ? 0.50\n                      : (query < 350) ? 0.30\n                      : (query < 650) ? 0.15 : 0.0;\n\n        /* ---- L2 split fit with BIC + variance-reduction override ---- */\n        auto fit_split = [&](const vector<pair<int,double>>& obs) -> SplitInfo {\n            SplitInfo info;\n            int n = (int)obs.size();\n            if (n == 0) return info;\n            info.has_obs = true;\n            double sum = 0.0;\n            for (auto &p : obs) sum += p.second;\n            info.mean_single = sum / n;\n\n            double sse_single = 0.0;\n            for (auto &p : obs) {\n                double d = p.second - info.mean_single;\n                sse_single += d * d;\n            }\n\n            if (n >= 4) {\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl < 2 || cr < 2) continue;\n                    double ml = sl / cl;\n                    double mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse;\n                        best_s   = s;\n                        best_ml  = ml;\n                        best_mr  = mr;\n                    }\n                }\n                if (best_s != -1) {\n                    double bic_single = n * log(sse_single / n + 1e-9) + 2.0 * log((double)n);\n                    double bic_split  = n * log(best_sse  / n + 1e-9) + 3.0 * log((double)n);\n                    bool accept = bic_split < bic_single;\n                    if (!accept && best_sse < sse_single * 0.30) accept = true;\n                    if (accept) {\n                        info.use = true;\n                        info.s = best_s;\n                        info.ml = best_ml;\n                        info.mr = best_mr;\n                    }\n                }\n            }\n            return info;\n        };\n\n        /* ---- fit rows ---- */\n        vector<SplitInfo> row_info(N);\n        int strong_split_rows = 0;\n        for (int i = 0; i < N; ++i) {\n            vector<pair<int,double>> obs;\n            for (int j = 0; j < N - 1; ++j)\n                if (cnt_h[i][j] > 0) obs.emplace_back(j, est_h[i][j]);\n            row_info[i] = fit_split(obs);\n            if (row_info[i].use) ++strong_split_rows;\n        }\n\n        /* ---- fit columns ---- */\n        vector<SplitInfo> col_info(N);\n        int strong_split_cols = 0;\n        for (int j = 0; j < N; ++j) {\n            vector<pair<int,double>> obs;\n            for (int i = 0; i < N - 1; ++i)\n                if (cnt_v[i][j] > 0) obs.emplace_back(i, est_v[i][j]);\n            col_info[j] = fit_split(obs);\n            if (col_info[j].use) ++strong_split_cols;\n        }\n\n        /* ---- conservative M=2 trigger ---- */\n        if (!likely_m2 && (strong_split_rows >= 5 || strong_split_cols >= 5))\n            likely_m2 = true;\n\n        /* ---- relaxed re-fit for likely M=2 ---- */\n        if (likely_m2) {\n            for (int i = 0; i < N; ++i) {\n                if (row_info[i].use || !row_info[i].has_obs) continue;\n                vector<pair<int,double>> obs;\n                for (int j = 0; j < N - 1; ++j)\n                    if (cnt_h[i][j] > 0) obs.emplace_back(j, est_h[i][j]);\n                int n = (int)obs.size();\n                if (n < 3) continue;\n                double sum = 0.0;\n                for (auto &p : obs) sum += p.second;\n                double mean = sum / n;\n                double sse_single = 0.0;\n                for (auto &p : obs) {\n                    double d = p.second - mean;\n                    sse_single += d * d;\n                }\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl < 2 || cr < 2) continue;\n                    double ml = sl / cl;\n                    double mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse; best_s = s; best_ml = ml; best_mr = mr;\n                    }\n                }\n                if (best_s != -1 && best_sse < sse_single * 0.50) {\n                    row_info[i].use = true;\n                    row_info[i].s = best_s;\n                    row_info[i].ml = best_ml;\n                    row_info[i].mr = best_mr;\n                }\n            }\n\n            for (int j = 0; j < N; ++j) {\n                if (col_info[j].use || !col_info[j].has_obs) continue;\n                vector<pair<int,double>> obs;\n                for (int i = 0; i < N - 1; ++i)\n                    if (cnt_v[i][j] > 0) obs.emplace_back(i, est_v[i][j]);\n                int n = (int)obs.size();\n                if (n < 3) continue;\n                double sum = 0.0;\n                for (auto &p : obs) sum += p.second;\n                double mean = sum / n;\n                double sse_single = 0.0;\n                for (auto &p : obs) {\n                    double d = p.second - mean;\n                    sse_single += d * d;\n                }\n                double best_sse = 1e100;\n                int best_s = -1;\n                double best_ml = 0.0, best_mr = 0.0;\n                for (int s = 1; s < N - 1; ++s) {\n                    double sl = 0.0, sr = 0.0;\n                    int cl = 0, cr = 0;\n                    for (auto &p : obs) {\n                        if (p.first < s) { sl += p.second; ++cl; }\n                        else             { sr += p.second; ++cr; }\n                    }\n                    if (cl < 2 || cr < 2) continue;\n                    double ml = sl / cl;\n                    double mr = sr / cr;\n                    double sse = 0.0;\n                    for (auto &p : obs) {\n                        double d = (p.first < s) ? (p.second - ml) : (p.second - mr);\n                        sse += d * d;\n                    }\n                    if (sse < best_sse) {\n                        best_sse = sse; best_s = s; best_ml = ml; best_mr = mr;\n                    }\n                }\n                if (best_s != -1 && best_sse < sse_single * 0.50) {\n                    col_info[j].use = true;\n                    col_info[j].s = best_s;\n                    col_info[j].ml = best_ml;\n                    col_info[j].mr = best_mr;\n                }\n            }\n        }\n\n        /* ---- prior accessor: trust learned est when available ---- */\n        auto base_cost = [&](int i, int j, bool is_h) -> double {\n            if (is_h) {\n                if (cnt_h[i][j] > 0) return est_h[i][j];\n                const SplitInfo &ri = row_info[i];\n                if (!ri.has_obs) return global_mean;\n                if (ri.use) return (j < ri.s) ? ri.ml : ri.mr;\n                return ri.mean_single;\n            } else {\n                if (cnt_v[i][j] > 0) return est_v[i][j];\n                const SplitInfo &ci = col_info[j];\n                if (!ci.has_obs) return global_mean;\n                if (ci.use) return (i < ci.s) ? ci.ml : ci.mr;\n                return ci.mean_single;\n            }\n        };\n\n        /* ---- global shrinkage pass toward structural prior ---- */\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N - 1; ++j) if (cnt_h[i][j] > 0) {\n                double structural = row_info[i].has_obs\n                    ? (row_info[i].use ? (j < row_info[i].s ? row_info[i].ml : row_info[i].mr) : row_info[i].mean_single)\n                    : global_mean;\n                double shrink = 0.025 / (1.0 + cnt_h[i][j] / 5.0);\n                est_h[i][j] = est_h[i][j] * (1.0 - shrink) + structural * shrink;\n                if (est_h[i][j] < MINW) est_h[i][j] = MINW;\n                if (est_h[i][j] > MAXW) est_h[i][j] = MAXW;\n            }\n\n        for (int i = 0; i < N - 1; ++i)\n            for (int j = 0; j < N; ++j) if (cnt_v[i][j] > 0) {\n                double structural = col_info[j].has_obs\n                    ? (col_info[j].use ? (i < col_info[j].s ? col_info[j].ml : col_info[j].mr) : col_info[j].mean_single)\n                    : global_mean;\n                double shrink = 0.025 / (1.0 + cnt_v[i][j] / 5.0);\n                est_v[i][j] = est_v[i][j] * (1.0 - shrink) + structural * shrink;\n                if (est_v[i][j] < MINW) est_v[i][j] = MINW;\n                if (est_v[i][j] > MAXW) est_v[i][j] = MAXW;\n            }\n\n        /* ---- Dijkstra helper ---- */\n        auto dijkstra = [&](bool use_explore, string &out_path, double &out_cost) {\n            int S = si * N + sj;\n            int T = ti * N + tj;\n            const int V = N * N;\n            const double INF = 1e100;\n            vector<double> dist(V, INF);\n            vector<pair<int,char>> prv(V, {-1, 0});\n            using State = pair<double,int>;\n            priority_queue<State, vector<State>, greater<State>> pq;\n\n            dist[S] = 0.0;\n            pq.emplace(0.0, S);\n\n            while (!pq.empty()) {\n                auto [d, v] = pq.top(); pq.pop();\n                if (d > dist[v] + 1e-9) continue;\n                if (v == T) break;\n                int i = v / N;\n                int j = v % N;\n\n                auto relax = [&](int ni, int nj, bool is_h, int ei, int ej, char dir) {\n                    int u = ni * N + nj;\n                    double base = base_cost(ei, ej, is_h);\n                    int c = is_h ? cnt_h[ei][ej] : cnt_v[ei][ej];\n                    double w = base;\n                    if (use_explore) {\n                        w = base * (1.0 - explore / sqrt((double)c + 1.0));\n                        if (w < MINW) w = MINW;\n                    }\n                    if (dist[u] > d + w) {\n                        dist[u] = d + w;\n                        prv[u] = {v, dir};\n                        pq.emplace(dist[u], u);\n                    }\n                };\n\n                if (i > 0)     relax(i - 1, j,     false, i - 1, j,     'U');\n                if (i + 1 < N) relax(i + 1, j,     false, i,     j,     'D');\n                if (j > 0)     relax(i,     j - 1, true,  i,     j - 1, 'L');\n                if (j + 1 < N) relax(i,     j + 1, true,  i,     j,     'R');\n            }\n\n            out_path.clear();\n            int cur = T;\n            while (cur != S) {\n                auto [p, c] = prv[cur];\n                out_path.push_back(c);\n                cur = p;\n            }\n            reverse(out_path.begin(), out_path.end());\n\n            out_cost = 0.0;\n            int ci = si, cj = sj;\n            for (char c : out_path) {\n                if (c == 'U') { out_cost += base_cost(ci - 1, cj, false); --ci; }\n                else if (c == 'D') { out_cost += base_cost(ci, cj, false); ++ci; }\n                else if (c == 'L') { out_cost += base_cost(ci, cj - 1, true); --cj; }\n                else if (c == 'R') { out_cost += base_cost(ci, cj, true); ++cj; }\n            }\n        };\n\n        /* ---- exploitation Dijkstra ---- */\n        string path_exploit;\n        double cost_exploit;\n        dijkstra(false, path_exploit, cost_exploit);\n\n        string path = path_exploit;\n\n        /* ---- exploration safety check ---- */\n        if (explore > 0.0) {\n            string path_explore;\n            double cost_explore;\n            dijkstra(true, path_explore, cost_explore);\n            if (cost_explore <= cost_exploit * (1.0 + margin))\n                path = path_explore;\n        }\n\n        cout << path << '\\n' << flush;\n\n        /* ---- read noisy observation ---- */\n        long long y;\n        cin >> y;\n        int L = (int)path.size();\n        if (L == 0) continue;\n\n        /* ---- update global mean ---- */\n        double avg_step = (double)y / (double)L;\n        global_mean = global_mean * 0.95 + avg_step * 0.05;\n        if (global_mean < MINW) global_mean = MINW;\n        if (global_mean > MAXW) global_mean = MAXW;\n\n        /* ---- list edges, init unseen to structural prior ---- */\n        struct Eref { bool h; int i, j; };\n        vector<Eref> edges;\n        edges.reserve(L);\n        double pred = 0.0;\n        int ci = si, cj = sj;\n\n        for (char c : path) {\n            if (c == 'U') {\n                if (cnt_v[ci-1][cj] == 0) est_v[ci-1][cj] = base_cost(ci-1, cj, false);\n                pred += est_v[ci-1][cj];\n                edges.push_back({false, ci-1, cj});\n                --ci;\n            } else if (c == 'D') {\n                if (cnt_v[ci][cj] == 0) est_v[ci][cj] = base_cost(ci, cj, false);\n                pred += est_v[ci][cj];\n                edges.push_back({false, ci, cj});\n                ++ci;\n            } else if (c == 'L') {\n                if (cnt_h[ci][cj-1] == 0) est_h[ci][cj-1] = base_cost(ci, cj-1, true);\n                pred += est_h[ci][cj-1];\n                edges.push_back({true, ci, cj-1});\n                --cj;\n            } else if (c == 'R') {\n                if (cnt_h[ci][cj] == 0) est_h[ci][cj] = base_cost(ci, cj, true);\n                pred += est_h[ci][cj];\n                edges.push_back({true, ci, cj});\n                ++cj;\n            }\n        }\n\n        double diff = (double)y - pred;\n        double total_inv = 0.0;\n        for (auto &e : edges) {\n            int c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            total_inv += 1.0 / ((double)c + 1.0);\n        }\n\n        /* ---- weighted LMS update + per-edge shrinkage ---- */\n        for (auto &e : edges) {\n            int &c = e.h ? cnt_h[e.i][e.j] : cnt_v[e.i][e.j];\n            double &est = e.h ? est_h[e.i][e.j] : est_v[e.i][e.j];\n            double structural = base_cost(e.i, e.j, e.h);\n\n            double w = (1.0 / ((double)c + 1.0)) / total_inv;\n            est += diff * w * LR;\n\n            double shrink = 0.08 / (1.0 + (double)c / 3.0);\n            est = est * (1.0 - shrink) + structural * shrink;\n\n            if (est < MINW) est = MINW;\n            if (est > MAXW) est = MAXW;\n            ++c;\n        }\n    }\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nvector<string> S;\n\nstruct Placement {\n    uint16_t cell[12];\n    uint8_t len;\n};\n\nvector<Placement> placements;\nvector<int> pid_sid;\nvector<uint8_t> pid_len;\nint P;\nvector<vector<int>> cell_pids_by_char;\n\n/* current board state */\nvector<uint8_t> board;\nvector<int> pid_match;\nvector<int> sid_ok;\nint total_matched;\n\nchrono::steady_clock::time_point start_time;\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n/* ---------- build all structures ---------- */\nvoid build() {\n    P = M * 800;\n    placements.resize(P);\n    pid_sid.resize(P);\n    pid_len.resize(P);\n    for (int sid = 0; sid < M; ++sid) {\n        int len = (int)S[sid].size();\n        int base = sid * 800;\n        int idx = 0;\n        for (int dir = 0; dir < 2; ++dir) {\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    Placement p;\n                    p.len = (uint8_t)len;\n                    for (int k = 0; k < len; ++k) {\n                        int rr = (dir == 0) ? r : (r + k) % N;\n                        int cc = (dir == 0) ? (c + k) % N : c;\n                        p.cell[k] = (uint16_t)(rr * N + cc);\n                    }\n                    placements[base + idx] = p;\n                    pid_sid[base + idx] = sid;\n                    pid_len[base + idx] = (uint8_t)len;\n                    ++idx;\n                }\n            }\n        }\n    }\n\n    cell_pids_by_char.assign(400 * 8, {});\n    for (int pid = 0; pid < P; ++pid) {\n        int sid = pid_sid[pid];\n        const Placement &p = placements[pid];\n        for (int i = 0; i < p.len; ++i) {\n            int cell = p.cell[i];\n            int ch = S[sid][i] - 'A';\n            cell_pids_by_char[cell * 8 + ch].push_back(pid);\n        }\n    }\n\n    board.resize(400);\n    pid_match.assign(P, 0);\n    sid_ok.assign(M, 0);\n}\n\n/* ---------- evaluate board from scratch ---------- */\nvoid eval_board(const vector<uint8_t> &b) {\n    board = b;\n    fill(pid_match.begin(), pid_match.end(), 0);\n    for (int cell = 0; cell < 400; ++cell) {\n        int ch = board[cell];\n        for (int pid : cell_pids_by_char[cell * 8 + ch]) {\n            ++pid_match[pid];\n        }\n    }\n    fill(sid_ok.begin(), sid_ok.end(), 0);\n    for (int pid = 0; pid < P; ++pid) {\n        if (pid_match[pid] == pid_len[pid]) {\n            ++sid_ok[pid_sid[pid]];\n        }\n    }\n    total_matched = 0;\n    for (int i = 0; i < M; ++i)\n        if (sid_ok[i] > 0) ++total_matched;\n}\n\n/* ---------- incremental move ---------- */\ninline void apply_move(int cell, int new_ch) {\n    int old_ch = board[cell];\n    if (old_ch == new_ch) return;\n    board[cell] = (uint8_t)new_ch;\n\n    for (int pid : cell_pids_by_char[cell * 8 + old_ch]) {\n        if (pid_match[pid] == pid_len[pid]) {\n            int sid = pid_sid[pid];\n            if (--sid_ok[sid] == 0) --total_matched;\n        }\n        --pid_match[pid];\n    }\n\n    for (int pid : cell_pids_by_char[cell * 8 + new_ch]) {\n        ++pid_match[pid];\n        if (pid_match[pid] == pid_len[pid]) {\n            int sid = pid_sid[pid];\n            if (++sid_ok[sid] == 1) ++total_matched;\n        }\n    }\n}\n\n/* ---------- initial board constructors ---------- */\nvector<uint8_t> greedy_board() {\n    int cell_cnt[400][8] = {};\n    uint8_t cell_mask[400] = {};\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n\n    for (int sid : order) {\n        int base = sid * 800;\n        int best_k = 0;\n        int best_conf = INT_MAX;\n        int best_cov = INT_MAX;\n        for (int k = 0; k < 800; ++k) {\n            const Placement &p = placements[base + k];\n            int add_conf = 0;\n            int add_cov = 0;\n            for (int i = 0; i < p.len; ++i) {\n                int cell = p.cell[i];\n                int ch = S[sid][i] - 'A';\n                if (cell_mask[cell] == 0) {\n                    ++add_cov;\n                } else if ( ((cell_mask[cell] >> ch) & 1) == 0 ) {\n                    if ((cell_mask[cell] & (cell_mask[cell] - 1)) == 0) ++add_conf;\n                }\n            }\n            if (add_conf < best_conf ||\n                (add_conf == best_conf && add_cov < best_cov) ||\n                (add_conf == best_conf && add_cov == best_cov && (rng() & 1))) {\n                best_conf = add_conf;\n                best_cov = add_cov;\n                best_k = k;\n            }\n        }\n        const Placement &p = placements[base + best_k];\n        for (int i = 0; i < p.len; ++i) {\n            int cell = p.cell[i];\n            int ch = S[sid][i] - 'A';\n            ++cell_cnt[cell][ch];\n            cell_mask[cell] |= (1 << ch);\n        }\n    }\n\n    vector<uint8_t> b(400);\n    for (int cell = 0; cell < 400; ++cell) {\n        int best_ch = 0;\n        for (int ch = 1; ch < 8; ++ch) {\n            if (cell_cnt[cell][ch] > cell_cnt[cell][best_ch]) best_ch = ch;\n        }\n        b[cell] = (uint8_t)best_ch;\n    }\n    return b;\n}\n\nvector<uint8_t> majority_board() {\n    vector<uint8_t> b(400);\n    for (int cell = 0; cell < 400; ++cell) {\n        int best_ch = 0;\n        int best_cnt = (int)cell_pids_by_char[cell * 8 + 0].size();\n        for (int ch = 1; ch < 8; ++ch) {\n            int cnt = (int)cell_pids_by_char[cell * 8 + ch].size();\n            if (cnt > best_cnt) {\n                best_cnt = cnt;\n                best_ch = ch;\n            }\n        }\n        b[cell] = (uint8_t)best_ch;\n    }\n    return b;\n}\n\n/* ---------- dotting by placement-set optimisation ---------- */\npair<vector<string>, int> optimize_placements(double deadline) {\n    vector<vector<int>> mp(M);\n    for (int pid = 0; pid < P; ++pid) {\n        if (pid_match[pid] == pid_len[pid]) {\n            mp[pid_sid[pid]].push_back(pid);\n        }\n    }\n    for (int sid = 0; sid < M; ++sid) {\n        if (mp[sid].empty()) return {vector<string>(), -1};\n    }\n\n    int sel[800];\n    int cell_cov[400] = {0};\n    int covered = 0;\n\n    /* greedy initial selection */\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    shuffle(order.begin(), order.end(), rng);\n    for (int sid : order) {\n        int best_pid = mp[sid][0];\n        int best_add = INT_MAX;\n        for (int pid : mp[sid]) {\n            const Placement &p = placements[pid];\n            int add = 0;\n            for (int i = 0; i < p.len; ++i) {\n                if (cell_cov[p.cell[i]] == 0) ++add;\n            }\n            if (add < best_add) {\n                best_add = add;\n                best_pid = pid;\n            }\n        }\n        sel[sid] = best_pid;\n        const Placement &p = placements[best_pid];\n        for (int i = 0; i < p.len; ++i) {\n            if (cell_cov[p.cell[i]]++ == 0) ++covered;\n        }\n    }\n\n    /* greedy cell elimination */\n    vector<int> cells(400);\n    iota(cells.begin(), cells.end(), 0);\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        shuffle(cells.begin(), cells.end(), rng);\n        for (int cell : cells) {\n            if (cell_cov[cell] == 0) continue;\n\n            vector<int> affected;\n            for (int sid = 0; sid < M; ++sid) {\n                const Placement &p = placements[sel[sid]];\n                for (int i = 0; i < p.len; ++i) {\n                    if (p.cell[i] == cell) {\n                        affected.push_back(sid);\n                        break;\n                    }\n                }\n            }\n\n            vector<int> alts;\n            bool ok = true;\n            for (int sid : affected) {\n                bool found = false;\n                for (int pid : mp[sid]) {\n                    if (pid == sel[sid]) continue;\n                    const Placement &p = placements[pid];\n                    bool uses = false;\n                    for (int i = 0; i < p.len; ++i) {\n                        if (p.cell[i] == cell) {\n                            uses = true;\n                            break;\n                        }\n                    }\n                    if (!uses) {\n                        found = true;\n                        alts.push_back(pid);\n                        break;\n                    }\n                }\n                if (!found) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) {\n                for (int i = 0; i < (int)affected.size(); ++i) {\n                    int sid = affected[i];\n                    const Placement &old_p = placements[sel[sid]];\n                    for (int j = 0; j < old_p.len; ++j) {\n                        if (--cell_cov[old_p.cell[j]] == 0) --covered;\n                    }\n                    sel[sid] = alts[i];\n                    const Placement &new_p = placements[sel[sid]];\n                    for (int j = 0; j < new_p.len; ++j) {\n                        if (++cell_cov[new_p.cell[j]] == 1) ++covered;\n                    }\n                }\n                changed = true;\n            }\n        }\n    }\n\n    int best_covered = covered;\n    int best_sel[800];\n    memcpy(best_sel, sel, M * sizeof(int));\n\n    /* SA on placement selection */\n    double T = 1.0;\n    while (elapsed() < deadline) {\n        int sid = (int)(rng() % M);\n        int old_pid = sel[sid];\n        const Placement &old_p = placements[old_pid];\n        int nc = (int)mp[sid].size();\n        if (nc <= 1) continue;\n\n        int best_pid = old_pid;\n        int best_delta = 0;\n        int try_cnt = min(nc, 50);\n        for (int t = 0; t < try_cnt; ++t) {\n            int new_pid = mp[sid][rng() % nc];\n            if (new_pid == old_pid) continue;\n            const Placement &new_p = placements[new_pid];\n\n            int delta = 0;\n            for (int i = 0; i < old_p.len; ++i) {\n                int c = old_p.cell[i];\n                if (--cell_cov[c] == 0) --delta;\n            }\n            for (int i = 0; i < new_p.len; ++i) {\n                int c = new_p.cell[i];\n                if (++cell_cov[c] == 1) ++delta;\n            }\n            for (int i = 0; i < new_p.len; ++i) --cell_cov[new_p.cell[i]];\n            for (int i = 0; i < old_p.len; ++i) ++cell_cov[old_p.cell[i]];\n\n            if (delta < best_delta) {\n                best_delta = delta;\n                best_pid = new_pid;\n            }\n        }\n\n        bool accept = (best_delta < 0) ||\n                      (best_delta > 0 && (double)rng() / numeric_limits<uint32_t>::max() < exp(-best_delta / T));\n        if (accept && best_pid != old_pid) {\n            const Placement &new_p = placements[best_pid];\n            for (int i = 0; i < old_p.len; ++i) {\n                if (--cell_cov[old_p.cell[i]] == 0) --covered;\n            }\n            for (int i = 0; i < new_p.len; ++i) {\n                if (++cell_cov[new_p.cell[i]] == 1) ++covered;\n            }\n            sel[sid] = best_pid;\n        }\n\n        if (covered < best_covered) {\n            best_covered = covered;\n            memcpy(best_sel, sel, M * sizeof(int));\n        }\n\n        T *= 0.99998;\n        if (T < 1e-9) T = 1e-9;\n    }\n\n    memset(cell_cov, 0, sizeof(cell_cov));\n    for (int sid = 0; sid < M; ++sid) {\n        const Placement &p = placements[best_sel[sid]];\n        for (int i = 0; i < p.len; ++i) {\n            cell_cov[p.cell[i]] = 1;\n        }\n    }\n\n    vector<string> ans(N, string(N, '.'));\n    for (int cell = 0; cell < 400; ++cell) {\n        if (cell_cov[cell]) {\n            ans[cell / N][cell % N] = char('A' + board[cell]);\n        }\n    }\n    return {ans, 400 - best_covered};\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N >> M)) return 0;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    start_time = chrono::steady_clock::now();\n    build();\n\n    int best_dots = -1;\n    vector<string> best_ans;\n    vector<uint8_t> best_perfect_board;\n    vector<uint8_t> fallback_board;\n    int fallback_matched = -1;\n\n    while (elapsed() < 2.65) {\n        vector<uint8_t> b;\n        int mode = rng() % 5;\n        if (mode == 0) {\n            b = greedy_board();\n        } else if (mode == 1) {\n            b = majority_board();\n        } else if (mode == 2 && !best_perfect_board.empty()) {\n            b = best_perfect_board;\n            for (int i = 0; i < 20; ++i) b[rng() % 400] = (uint8_t)(rng() % 8);\n        } else {\n            b.resize(400);\n            for (int i = 0; i < 400; ++i) b[i] = (uint8_t)(rng() % 8);\n        }\n\n        eval_board(b);\n        if (total_matched > fallback_matched) {\n            fallback_matched = total_matched;\n            fallback_board = board;\n        }\n\n        /* board-space SA */\n        double T = 2.0;\n        int last_matched = total_matched;\n        int since_improve = 0;\n\n        while (elapsed() < 2.65 && total_matched < M) {\n            int cell, new_ch;\n            bool targeted = (rng() % 100 < 75);\n\n            if (targeted) {\n                int sid = -1;\n                for (int t = 0; t < 20; ++t) {\n                    int ts = (int)(rng() % M);\n                    if (sid_ok[ts] == 0) {\n                        sid = ts;\n                        break;\n                    }\n                }\n                if (sid != -1) {\n                    int pid = sid * 800 + (int)(rng() % 800);\n                    const Placement &p = placements[pid];\n                    int mis[12], mc = 0;\n                    for (int i = 0; i < p.len; ++i) {\n                        if (board[p.cell[i]] != (uint8_t)(S[sid][i] - 'A')) {\n                            mis[mc++] = i;\n                        }\n                    }\n                    if (mc > 0) {\n                        int idx = mis[rng() % mc];\n                        cell = p.cell[idx];\n                        new_ch = S[sid][idx] - 'A';\n                    } else {\n                        targeted = false;\n                    }\n                } else {\n                    targeted = false;\n                }\n            }\n\n            if (!targeted) {\n                cell = (int)(rng() % 400);\n                new_ch = (int)(rng() % 8);\n            }\n\n            int old_ch = board[cell];\n            if (new_ch == old_ch) continue;\n\n            int old_matched = total_matched;\n            apply_move(cell, new_ch);\n            int delta = total_matched - old_matched;\n\n            bool accept = (delta >= 0) ||\n                          ((double)rng() / numeric_limits<uint32_t>::max() < exp(delta / T));\n            if (!accept) {\n                apply_move(cell, old_ch);\n            }\n\n            if (total_matched > last_matched) {\n                last_matched = total_matched;\n                since_improve = 0;\n            } else {\n                ++since_improve;\n            }\n            if (since_improve > 50000) {\n                T = min(T * 3.0, 20.0);\n                since_improve = 0;\n            }\n            T *= 0.99997;\n            if (T < 1e-9) T = 1e-9;\n        }\n\n        if (total_matched > fallback_matched) {\n            fallback_matched = total_matched;\n            fallback_board = board;\n        }\n\n        if (total_matched == M) {\n            if (best_perfect_board.empty()) best_perfect_board = board;\n            double limit = min(2.80, elapsed() + 0.08);\n            auto [ans, dots] = optimize_placements(limit);\n            if (dots > best_dots) {\n                best_dots = dots;\n                best_ans = ans;\n                best_perfect_board = board;\n            }\n        }\n    }\n\n    /* final thorough dotting on the best perfect board */\n    if (!best_perfect_board.empty() && elapsed() < 2.95) {\n        eval_board(best_perfect_board);\n        auto [ans, dots] = optimize_placements(2.98);\n        if (dots > best_dots) {\n            best_dots = dots;\n            best_ans = ans;\n        }\n    }\n\n    if (best_dots < 0) {\n        vector<string> ans(N, string(N, 'A'));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                ans[i][j] = char('A' + fallback_board[i * N + j]);\n        best_ans = ans;\n    }\n\n    for (const string &row : best_ans) {\n        cout << row << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, si, sj;\n    int V = 0, S = -1;\n    int Hreq = 0, Vreq = 0, R = 0;\n    vector<string> g;\n    vector<vector<int>> w;\n    vector<int> ui, uj;\n    vector<vector<int>> adj;\n    vector< bitset<1024> > cellMask;\n    vector<vector<int>> groupCells;\n    bitset<1024> allReq;\n    mt19937 rng;\n\n    const int di[4] = {-1, 1, 0, 0};\n    const int dj[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n    const int INF = 1e9;\n\n    vector<int> dist, parent, heapPos, order;\n    vector< bitset<1024> > pathMask;\n    struct IntHeap {\n        vector<int> h;\n        vector<int> *d, *pos;\n        void init(vector<int> *dist, vector<int> *position) { d = dist; pos = position; }\n        void clear() { for (int v : h) (*pos)[v] = -1; h.clear(); }\n        bool empty() const { return h.empty(); }\n        void push(int v) {\n            if ((*pos)[v] == -1) { (*pos)[v] = (int)h.size(); h.push_back(v); }\n            siftup((*pos)[v]);\n        }\n        int pop() {\n            int res = h[0]; (*pos)[res] = -1;\n            int v = h.back(); h.pop_back();\n            if (!h.empty()) { h[0] = v; (*pos)[v] = 0; siftdown(0); }\n            return res;\n        }\n        void siftup(int i) {\n            int v = h[i], dv = (*d)[v];\n            while (i > 0) {\n                int p = (i - 1) >> 1, u = h[p];\n                if ((*d)[u] <= dv) break;\n                h[i] = u; (*pos)[u] = i; i = p;\n            }\n            h[i] = v; (*pos)[v] = i;\n        }\n        void siftdown(int i) {\n            int v = h[i], dv = (*d)[v], n = (int)h.size();\n            while (true) {\n                int l = i * 2 + 1; if (l >= n) break;\n                int r = l + 1, best = l;\n                if (r < n && (*d)[h[r]] < (*d)[h[l]]) best = r;\n                if ((*d)[h[best]] >= dv) break;\n                int u = h[best]; h[i] = u; (*pos)[u] = i; i = best;\n            }\n            h[i] = v; (*pos)[v] = i;\n        }\n    };\n    IntHeap dijHeap;\n\n    vector<vector<int>> swapAdj;\n    vector<char> swapMark;\n    vector<int> swapTouched;\n    vector<int> vertId;\n\n    vector<pair<int,int>> bestEdges;\n    long long bestCost = LLONG_MAX;\n\n    inline int dirMove(int u, int v) const {\n        int i1 = ui[u], j1 = uj[u];\n        int i2 = ui[v], j2 = uj[v];\n        if (i2 == i1 - 1) return 0;\n        if (i2 == i1 + 1) return 1;\n        if (j2 == j1 - 1) return 2;\n        return 3;\n    }\n\n    void dijkstraRun(const vector<char> &srcMask, vector<int> *orderPtr) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(parent.begin(), parent.end(), -1);\n        dijHeap.clear();\n        for (int u = 0; u < V; ++u) if (srcMask[u]) {\n            dist[u] = 0; dijHeap.push(u);\n        }\n        if (orderPtr) orderPtr->clear();\n        while (!dijHeap.empty()) {\n            int u = dijHeap.pop();\n            if (orderPtr) orderPtr->push_back(u);\n            int du = dist[u];\n            int wu = w[ui[u]][uj[u]];\n            for (int v : adj[u]) {\n                int nd = du + wu + w[ui[v]][uj[v]];\n                if (nd < dist[v]) {\n                    dist[v] = nd; parent[v] = u; dijHeap.push(v);\n                }\n            }\n        }\n    }\n\n    long long pruneAndCost(vector<pair<int,int>> &edges, bitset<1024> &outCov) {\n        vector<int> verts;\n        verts.reserve(edges.size() * 2);\n        for (auto &e : edges) {\n            if (vertId[e.first] == -1) { vertId[e.first] = (int)verts.size(); verts.push_back(e.first); }\n            if (vertId[e.second] == -1) { vertId[e.second] = (int)verts.size(); verts.push_back(e.second); }\n        }\n        int nV = (int)verts.size();\n        vector<vector<int>> localAdj(nV);\n        for (auto &e : edges) {\n            int a = vertId[e.first], b = vertId[e.second];\n            localAdj[a].push_back(b);\n            localAdj[b].push_back(a);\n        }\n        vector<char> alive(nV, 1);\n        vector<int> deg(nV);\n        for (int i = 0; i < nV; ++i) deg[i] = (int)localAdj[i].size();\n        vector<int> coverCnt(R, 0);\n        for (int i = 0; i < nV; ++i) {\n            int u = verts[i];\n            for (int r = 0; r < R; ++r) if (cellMask[u].test(r)) ++coverCnt[r];\n        }\n        queue<int> q;\n        for (int i = 0; i < nV; ++i)\n            if (deg[i] == 1 && verts[i] != S) q.push(i);\n\n        while (!q.empty()) {\n            int li = q.front(); q.pop();\n            if (!alive[li] || deg[li] != 1 || verts[li] == S) continue;\n            bool ok = true;\n            int u = verts[li];\n            for (int r = 0; r < R; ++r) {\n                if (cellMask[u].test(r) && coverCnt[r] <= 1) { ok = false; break; }\n            }\n            if (!ok) continue;\n            alive[li] = 0; deg[li] = 0;\n            for (int r = 0; r < R; ++r) if (cellMask[u].test(r)) --coverCnt[r];\n            for (int v : localAdj[li]) {\n                if (!alive[v]) continue;\n                if (--deg[v] == 1 && verts[v] != S) q.push(v);\n            }\n        }\n\n        long long cost = 0;\n        vector<pair<int,int>> pruned;\n        outCov.reset();\n        for (int i = 0; i < nV; ++i) if (alive[i]) {\n            int u = verts[i];\n            outCov |= cellMask[u];\n            for (int v : localAdj[i]) if (i < v) {\n                pruned.emplace_back(u, verts[v]);\n                cost += w[ui[u]][uj[u]] + w[ui[verts[v]]][uj[verts[v]]];\n            }\n        }\n        for (int v : verts) vertId[v] = -1;\n        edges.swap(pruned);\n        return cost;\n    }\n\n    void improveTree(vector<pair<int,int>> &edges, long long &cost, bitset<1024> &cov) {\n        while (true) {\n            vector<char> inU(V, 0);\n            for (auto &e : edges) {\n                inU[e.first] = 1;\n                inU[e.second] = 1;\n            }\n            vector<int> dvec(V, INF), par(V, -1);\n            vector<char> used(V, 0);\n            vector<int> pos(V, -1);\n            IntHeap heap;\n            heap.init(&dvec, &pos);\n            dvec[S] = 0; heap.push(S);\n            vector<pair<int,int>> newEdges;\n            while (!heap.empty()) {\n                int u = heap.pop();\n                if (used[u]) continue;\n                used[u] = 1;\n                if (par[u] != -1) newEdges.emplace_back(u, par[u]);\n                for (int v : adj[u]) {\n                    if (!inU[v] || used[v]) continue;\n                    int c = w[ui[u]][uj[u]] + w[ui[v]][uj[v]];\n                    if (c < dvec[v]) {\n                        dvec[v] = c; par[v] = u; heap.push(v);\n                    }\n                }\n            }\n            bitset<1024> newCov;\n            long long newCost = pruneAndCost(newEdges, newCov);\n            if (newCov != allReq || newCost >= cost) break;\n            cost = newCost;\n            edges.swap(newEdges);\n            cov = newCov;\n        }\n    }\n\n    void consider(vector<pair<int,int>> &edges, long long cost) {\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestEdges = edges;\n        }\n    }\n\n    long long greedyBuild(const vector<pair<int,int>> &initEdges, int strategy,\n                          vector<pair<int,int>> &outEdges, bitset<1024> &outCov) {\n        vector<char> inTree(V, 0);\n        for (auto &e : initEdges) {\n            inTree[e.first] = 1;\n            inTree[e.second] = 1;\n        }\n        inTree[S] = 1;\n        bitset<1024> covered;\n        for (int u = 0; u < V; ++u) if (inTree[u]) covered |= cellMask[u];\n\n        vector<pair<int,int>> edges = initEdges;\n        struct Cand { int v, d, g; };\n\n        while (covered != allReq) {\n            dijkstraRun(inTree, &order);\n            for (int u : order) {\n                if (inTree[u]) pathMask[u].reset();\n                else {\n                    int p = parent[u];\n                    if (p >= 0) pathMask[u] = pathMask[p];\n                    else pathMask[u].reset();\n                    pathMask[u] |= cellMask[u];\n                }\n            }\n            vector<Cand> cands;\n            for (int u = 0; u < V; ++u) {\n                if (inTree[u]) continue;\n                bitset<1024> add = pathMask[u] & ~covered;\n                int gain = (int)add.count();\n                if (gain > 0) cands.push_back({u, dist[u], gain});\n            }\n            if (cands.empty()) return LLONG_MAX;\n\n            int bestV = -1;\n            if (strategy == 0) { // best ratio\n                sort(cands.begin(), cands.end(),\n                    [](const Cand& a, const Cand& b) {\n                        return (long long)a.d * b.g < (long long)b.d * a.g;\n                    });\n                int K = min(3, (int)cands.size());\n                bestV = cands[rng() % K].v;\n            } else if (strategy == 1) { // largest gain\n                sort(cands.begin(), cands.end(),\n                    [](const Cand& a, const Cand& b) {\n                        if (a.g != b.g) return a.g > b.g;\n                        return a.d < b.d;\n                    });\n                bestV = cands[0].v;\n            } else if (strategy == 2) { // random uncovered group\n                vector<int> urg;\n                for (int r = 0; r < R; ++r) if (!covered.test(r)) urg.push_back(r);\n                int rg = urg[rng() % urg.size()];\n                vector<Cand> rc;\n                for (auto &c : cands) if (pathMask[c.v].test(rg)) rc.push_back(c);\n                if (!rc.empty()) {\n                    sort(rc.begin(), rc.end(),\n                        [](const Cand& a, const Cand& b) { return a.d < b.d; });\n                    int K = min(3, (int)rc.size());\n                    bestV = rc[rng() % K].v;\n                } else {\n                    bestV = cands[0].v;\n                }\n            } else { // farthest first\n                sort(cands.begin(), cands.end(),\n                    [](const Cand& a, const Cand& b) {\n                        return a.d > b.d;\n                    });\n                int K = min(3, (int)cands.size());\n                bestV = cands[rng() % K].v;\n            }\n\n            int cur = bestV;\n            while (!inTree[cur]) {\n                int p = parent[cur];\n                edges.emplace_back(cur, p);\n                inTree[cur] = 1;\n                covered |= cellMask[cur];\n                cur = p;\n            }\n        }\n        outCov.reset();\n        long long cost = pruneAndCost(edges, outCov);\n        outEdges.swap(edges);\n        return cost;\n    }\n\n    long long sphBuild(vector<pair<int,int>> &outEdges, bitset<1024> &outCov,\n                       bool perturb = false) {\n        vector<char> inTree(V, 0);\n        inTree[S] = 1;\n        bitset<1024> covered = cellMask[S];\n        vector<pair<int,int>> edges;\n\n        while (covered != allReq) {\n            dijkstraRun(inTree, nullptr);\n            int bestG = -1, bestD = INF, bestV = -1;\n            for (int g = 0; g < R; ++g) {\n                if (covered.test(g)) continue;\n                for (int v : groupCells[g]) {\n                    int d = dist[v] + (perturb ? (int)(rng() % 20) : 0);\n                    if (d < bestD) {\n                        bestD = d; bestV = v; bestG = g;\n                    }\n                }\n            }\n            if (bestV == -1) return LLONG_MAX;\n\n            int cur = bestV;\n            while (!inTree[cur]) {\n                int p = parent[cur];\n                edges.emplace_back(cur, p);\n                inTree[cur] = 1;\n                covered |= cellMask[cur];\n                cur = p;\n            }\n        }\n        outCov.reset();\n        long long cost = pruneAndCost(edges, outCov);\n        outEdges.swap(edges);\n        return cost;\n    }\n\n    long long permBuild(const vector<int> &perm,\n                        vector<pair<int,int>> &outEdges, bitset<1024> &outCov) {\n        vector<char> inTree(V, 0);\n        inTree[S] = 1;\n        bitset<1024> covered = cellMask[S];\n        vector<pair<int,int>> edges;\n\n        for (int g : perm) {\n            if (covered.test(g)) continue;\n            dijkstraRun(inTree, nullptr);\n            int bestV = -1, bestD = INF;\n            for (int v : groupCells[g]) {\n                if (dist[v] < bestD) {\n                    bestD = dist[v]; bestV = v;\n                }\n            }\n            if (bestV == -1) return LLONG_MAX;\n\n            int cur = bestV;\n            while (!inTree[cur]) {\n                int p = parent[cur];\n                edges.emplace_back(cur, p);\n                inTree[cur] = 1;\n                covered |= cellMask[cur];\n                cur = p;\n            }\n        }\n        outCov.reset();\n        long long cost = pruneAndCost(edges, outCov);\n        outEdges.swap(edges);\n        return cost;\n    }\n\n    long long mstGuidedBuild(vector<pair<int,int>> &outEdges, bitset<1024> &outCov) {\n        int M = R + 1;\n        vector<vector<int>> gdist(M, vector<int>(V, INF));\n        vector<char> srcMask(V, 0);\n        for (int g = 0; g < R; ++g) {\n            fill(srcMask.begin(), srcMask.end(), 0);\n            for (int v : groupCells[g]) srcMask[v] = 1;\n            dijkstraRun(srcMask, nullptr);\n            gdist[g] = dist;\n        }\n        fill(srcMask.begin(), srcMask.end(), 0);\n        srcMask[S] = 1;\n        dijkstraRun(srcMask, nullptr);\n        gdist[R] = dist;\n\n        vector<vector<int>> md(M, vector<int>(M, INF));\n        for (int i = 0; i < M; ++i) {\n            for (int j = i + 1; j < M; ++j) {\n                int best = INF;\n                if (j == R) {\n                    for (int v : groupCells[i]) best = min(best, gdist[R][v]);\n                } else if (i == R) {\n                    for (int v : groupCells[j]) best = min(best, gdist[R][v]);\n                } else {\n                    for (int v : groupCells[j]) best = min(best, gdist[i][v]);\n                    for (int v : groupCells[i]) best = min(best, gdist[j][v]);\n                }\n                md[i][j] = md[j][i] = best;\n            }\n        }\n\n        vector<int> mincost(M, INF), used(M, 0), sel(M, -1);\n        vector<vector<int>> mstAdj(M);\n        mincost[R] = 0;\n        for (int it = 0; it < M; ++it) {\n            int v = -1;\n            for (int j = 0; j < M; ++j)\n                if (!used[j] && (v == -1 || mincost[j] < mincost[v])) v = j;\n            used[v] = 1;\n            if (sel[v] != -1) {\n                mstAdj[v].push_back(sel[v]);\n                mstAdj[sel[v]].push_back(v);\n            }\n            for (int j = 0; j < M; ++j)\n                if (!used[j] && md[v][j] < mincost[j]) {\n                    mincost[j] = md[v][j];\n                    sel[j] = v;\n                }\n        }\n\n        vector<int> parentT(M, -1);\n        queue<int> qq;\n        qq.push(R);\n        vector<char> visMeta(M, 0);\n        visMeta[R] = 1;\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            for (int v : mstAdj[u]) if (!visMeta[v]) {\n                visMeta[v] = 1;\n                parentT[v] = u;\n                qq.push(v);\n            }\n        }\n\n        vector<char> inTree(V, 0);\n        inTree[S] = 1;\n        bitset<1024> covered = cellMask[S];\n        vector<pair<int,int>> edges;\n\n        function<void(int)> dfsMeta = [&](int g) {\n            for (int child : mstAdj[g]) {\n                if (parentT[child] != g) continue;\n                if (!covered.test(child)) {\n                    dijkstraRun(inTree, nullptr);\n                    int bestV = -1, bestD = INF;\n                    for (int v : groupCells[child]) {\n                        if (dist[v] < bestD) {\n                            bestD = dist[v]; bestV = v;\n                        }\n                    }\n                    if (bestV != -1) {\n                        int cur = bestV;\n                        while (!inTree[cur]) {\n                            int p = parent[cur];\n                            edges.emplace_back(cur, p);\n                            inTree[cur] = 1;\n                            covered |= cellMask[cur];\n                            cur = p;\n                        }\n                    }\n                }\n                dfsMeta(child);\n            }\n        };\n        dfsMeta(R);\n\n        outCov.reset();\n        long long cost = pruneAndCost(edges, outCov);\n        outEdges.swap(edges);\n        return cost;\n    }\n\n    pair<vector<pair<int,int>>, long long> primFull(int perturb) {\n        vector<int> dvec(V, INF), par(V, -1);\n        vector<char> used(V, 0);\n        vector<int> pos(V, -1);\n        IntHeap heap;\n        heap.init(&dvec, &pos);\n        dvec[S] = 0; heap.push(S);\n        vector<pair<int,int>> edges;\n        while (!heap.empty()) {\n            int u = heap.pop();\n            if (used[u]) continue;\n            used[u] = 1;\n            if (par[u] != -1) edges.emplace_back(u, par[u]);\n            int wu = w[ui[u]][uj[u]];\n            for (int v : adj[u]) {\n                if (used[v]) continue;\n                int c = wu + w[ui[v]][uj[v]] + (perturb ? (int)(rng() % 3) : 0);\n                if (c < dvec[v]) {\n                    dvec[v] = c; par[v] = u; heap.push(v);\n                }\n            }\n        }\n        bitset<1024> cov;\n        long long cost = pruneAndCost(edges, cov);\n        return {edges, cost};\n    }\n\n    bool trySwapImprove() {\n        vector<int> treeVerts;\n        treeVerts.reserve(bestEdges.size() * 2);\n        for (auto &e : bestEdges) {\n            if (!swapMark[e.first]) { swapMark[e.first] = 1; treeVerts.push_back(e.first); }\n            if (!swapMark[e.second]) { swapMark[e.second] = 1; treeVerts.push_back(e.second); }\n            if (swapAdj[e.first].empty()) swapTouched.push_back(e.first);\n            if (swapAdj[e.second].empty()) swapTouched.push_back(e.second);\n            swapAdj[e.first].push_back(e.second);\n            swapAdj[e.second].push_back(e.first);\n        }\n        unordered_set<int> treeSet;\n        treeSet.reserve(bestEdges.size() * 2);\n        for (auto &e : bestEdges) {\n            int a = e.first, b = e.second;\n            if (a > b) swap(a, b);\n            treeSet.insert(a * V + b);\n        }\n        vector<pair<int,int>> cand;\n        for (int u : treeVerts) {\n            for (int v : adj[u]) {\n                if (!swapMark[v]) continue;\n                if (u < v && !treeSet.count(u * V + v)) cand.emplace_back(u, v);\n            }\n        }\n        if (cand.empty()) {\n            for (int v : swapTouched) swapAdj[v].clear();\n            swapTouched.clear();\n            for (int v : treeVerts) swapMark[v] = 0;\n            return false;\n        }\n        shuffle(cand.begin(), cand.end(), rng);\n        for (auto &e : cand) {\n            int u = e.first, v = e.second;\n            vector<int> path;\n            function<bool(int,int)> dfsP = [&](int x, int p) -> bool {\n                if (x == v) { path.push_back(x); return true; }\n                for (int y : swapAdj[x]) if (y != p) {\n                    if (dfsP(y, x)) { path.push_back(x); return true; }\n                }\n                return false;\n            };\n            dfsP(u, -1);\n            reverse(path.begin(), path.end());\n            vector<pair<int,int>> pw;\n            for (int i = 0; i < (int)path.size() - 1; ++i) {\n                int a = path[i], b = path[i+1];\n                pw.push_back({w[ui[a]][uj[a]] + w[ui[b]][uj[b]], i});\n            }\n            sort(pw.begin(), pw.end(), greater<pair<int,int>>());\n            int tryCnt = min(3, (int)pw.size());\n            for (int ti = 0; ti < tryCnt; ++ti) {\n                int idx = pw[ti].second;\n                int a = path[idx], b = path[idx+1];\n                vector<pair<int,int>> newEdges = bestEdges;\n                newEdges.push_back(e);\n                bool removed = false;\n                for (int i = 0; i < (int)newEdges.size(); ++i) {\n                    int x = newEdges[i].first, y = newEdges[i].second;\n                    if ((x==a && y==b) || (x==b && y==a)) {\n                        newEdges[i] = newEdges.back(); newEdges.pop_back(); removed = true; break;\n                    }\n                }\n                if (!removed) continue;\n                bitset<1024> cov;\n                long long cost = pruneAndCost(newEdges, cov);\n                if (cov == allReq) {\n                    improveTree(newEdges, cost, cov);\n                    if (cov == allReq && cost < bestCost) {\n                        bestCost = cost;\n                        bestEdges.swap(newEdges);\n                        for (int vv : swapTouched) swapAdj[vv].clear();\n                        swapTouched.clear();\n                        for (int vv : treeVerts) swapMark[vv] = 0;\n                        return true;\n                    }\n                }\n            }\n        }\n        for (int v : swapTouched) swapAdj[v].clear();\n        swapTouched.clear();\n        for (int v : treeVerts) swapMark[v] = 0;\n        return false;\n    }\n\n    bool tryShake(bool aggressive) {\n        vector<int> treeVerts;\n        treeVerts.reserve(bestEdges.size() * 2);\n        for (auto &e : bestEdges) {\n            if (!swapMark[e.first]) { swapMark[e.first] = 1; treeVerts.push_back(e.first); }\n            if (!swapMark[e.second]) { swapMark[e.second] = 1; treeVerts.push_back(e.second); }\n            if (swapAdj[e.first].empty()) swapTouched.push_back(e.first);\n            if (swapAdj[e.second].empty()) swapTouched.push_back(e.second);\n            swapAdj[e.first].push_back(e.second);\n            swapAdj[e.second].push_back(e.first);\n        }\n        vector<int> parentT(V, -1);\n        vector<char> inT(V, 0);\n        queue<int> qq;\n        qq.push(S); inT[S] = 1;\n        vector<int> bfsOrder;\n        while (!qq.empty()) {\n            int u = qq.front(); qq.pop();\n            bfsOrder.push_back(u);\n            for (int v : swapAdj[u]) if (!inT[v]) {\n                inT[v] = 1; parentT[v] = u; qq.push(v);\n            }\n        }\n        vector<int> deg(V, 0);\n        for (int u : treeVerts) deg[u] = (int)swapAdj[u].size();\n\n        vector<pair<int,int>> keep;\n        bool ok = true;\n        if ((rng() & 1) && bestEdges.size() > 1) {\n            vector<int> childs;\n            for (int u : bfsOrder) if (parentT[u] != -1) childs.push_back(u);\n            if (childs.empty()) ok = false;\n            else {\n                int child = childs[rng() % childs.size()];\n                vector<int> stack = {child};\n                vector<char> sub(V, 0);\n                sub[child] = 1;\n                for (size_t i = 0; i < stack.size(); ++i) {\n                    int u = stack[i];\n                    for (int v : swapAdj[u]) {\n                        if (v == parentT[u]) continue;\n                        if (!sub[v]) { sub[v] = 1; stack.push_back(v); }\n                    }\n                }\n                size_t limit = aggressive ? treeVerts.size() : treeVerts.size() * 2 / 3;\n                if (stack.size() > limit) ok = false;\n                else {\n                    for (auto &e : bestEdges)\n                        if (!sub[e.first] && !sub[e.second]) keep.push_back(e);\n                }\n            }\n        } else {\n            vector<int> leaves;\n            for (int u : treeVerts) if (deg[u] == 1 && u != S) leaves.push_back(u);\n            if (leaves.empty()) ok = false;\n            else {\n                int leaf = leaves[rng() % leaves.size()];\n                vector<char> sub(V, 0);\n                int cur = leaf, prev = -1;\n                while (true) {\n                    sub[cur] = 1;\n                    int nxt = -1;\n                    for (int v : swapAdj[cur]) if (v != prev) { nxt = v; break; }\n                    if (nxt == -1 || nxt == S) break;\n                    if (deg[nxt] > 2) break;\n                    prev = cur; cur = nxt;\n                }\n                for (auto &e : bestEdges)\n                    if (!sub[e.first] && !sub[e.second]) keep.push_back(e);\n            }\n        }\n        for (int v : swapTouched) swapAdj[v].clear();\n        swapTouched.clear();\n        for (int v : treeVerts) swapMark[v] = 0;\n        if (!ok) return false;\n\n        vector<pair<int,int>> newEdges;\n        bitset<1024> newCov;\n        long long c = greedyBuild(keep, rng() % 4, newEdges, newCov);\n        if (newCov == allReq) {\n            improveTree(newEdges, c, newCov);\n            if (c < bestCost) {\n                bestCost = c;\n                bestEdges.swap(newEdges);\n                return true;\n            }\n        }\n        return false;\n    }\n\n    void run() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n        rng = mt19937(chrono::steady_clock::now().time_since_epoch().count());\n        auto startTime = chrono::steady_clock::now();\n        auto elapsed = [&]() {\n            return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        };\n\n        if (!(cin >> N >> si >> sj)) return;\n        g.resize(N);\n        for (int i = 0; i < N; ++i) cin >> g[i];\n        w.assign(N, vector<int>(N, 0));\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (g[i][j] != '#') w[i][j] = g[i][j] - '0';\n\n        vector<vector<int>> id(N, vector<int>(N, -1));\n        queue<pair<int,int>> q;\n        q.emplace(si, sj);\n        id[si][sj] = 0;\n        ui.push_back(si); uj.push_back(sj);\n        while (!q.empty()) {\n            auto [i, j] = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                if (g[ni][nj] == '#') continue;\n                if (id[ni][nj] == -1) {\n                    id[ni][nj] = (int)ui.size();\n                    ui.push_back(ni);\n                    uj.push_back(nj);\n                    q.emplace(ni, nj);\n                }\n            }\n        }\n        V = (int)ui.size();\n        S = id[si][sj];\n        adj.assign(V, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            for (int d = 0; d < 4; ++d) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (ni >= 0 && ni < N && nj >= 0 && nj < N && id[ni][nj] != -1)\n                    adj[u].push_back(id[ni][nj]);\n            }\n        }\n\n        vector<vector<int>> hId(N, vector<int>(N, -1));\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ) {\n                if (g[i][j] == '#') { ++j; continue; }\n                int j0 = j;\n                while (j < N && g[i][j] != '#') ++j;\n                if (j - j0 >= 2) {\n                    for (int k = j0; k < j; ++k) hId[i][k] = Hreq;\n                    ++Hreq;\n                }\n            }\n        }\n        vector<vector<int>> vId(N, vector<int>(N, -1));\n        for (int j = 0; j < N; ++j) {\n            for (int i = 0; i < N; ) {\n                if (g[i][j] == '#') { ++i; continue; }\n                int i0 = i;\n                while (i < N && g[i][j] != '#') ++i;\n                if (i - i0 >= 2) {\n                    for (int k = i0; k < i; ++k) vId[k][j] = Vreq;\n                    ++Vreq;\n                }\n            }\n        }\n        R = Hreq + Vreq;\n        allReq.reset();\n        for (int i = 0; i < R; ++i) allReq.set(i);\n        cellMask.assign(V, bitset<1024>());\n        groupCells.assign(R, {});\n        for (int u = 0; u < V; ++u) {\n            int i = ui[u], j = uj[u];\n            if (hId[i][j] != -1) {\n                cellMask[u].set(hId[i][j]);\n                groupCells[hId[i][j]].push_back(u);\n            }\n            if (vId[i][j] != -1) {\n                cellMask[u].set(Hreq + vId[i][j]);\n                groupCells[Hreq + vId[i][j]].push_back(u);\n            }\n        }\n\n        if (R == 0) {\n            cout << \"\\n\";\n            return;\n        }\n\n        dist.assign(V, INF);\n        parent.assign(V, -1);\n        heapPos.assign(V, -1);\n        order.reserve(V);\n        pathMask.assign(V, bitset<1024>());\n        dijHeap.init(&dist, &heapPos);\n\n        swapAdj.assign(V, {});\n        swapMark.assign(V, 0);\n        swapTouched.reserve(V);\n        vertId.assign(V, -1);\n\n        /* Phase 1: Fast baselines */\n        for (int iter = 0; iter < 10; ++iter) {\n            if (elapsed() > 0.2) break;\n            auto [edges, cost] = primFull(iter > 0);\n            if (cost < LLONG_MAX) {\n                bitset<1024> cov;\n                improveTree(edges, cost, cov);\n                consider(edges, cost);\n            }\n        }\n\n        if (elapsed() < 0.4) {\n            vector<pair<int,int>> edges;\n            bitset<1024> cov;\n            long long c = mstGuidedBuild(edges, cov);\n            if (cov == allReq) {\n                improveTree(edges, c, cov);\n                consider(edges, c);\n            }\n        }\n\n        for (int iter = 0; iter < 30; ++iter) {\n            if (elapsed() > 0.6) break;\n            vector<pair<int,int>> edges;\n            bitset<1024> cov;\n            long long c = sphBuild(edges, cov, iter > 0);\n            if (cov == allReq) {\n                improveTree(edges, c, cov);\n                consider(edges, c);\n            }\n        }\n\n        vector<int> perm(R);\n        iota(perm.begin(), perm.end(), 0);\n        for (int iter = 0; iter < 40; ++iter) {\n            if (elapsed() > 1.0) break;\n            shuffle(perm.begin(), perm.end(), rng);\n            vector<pair<int,int>> edges;\n            bitset<1024> cov;\n            long long c = permBuild(perm, edges, cov);\n            if (cov == allReq) {\n                improveTree(edges, c, cov);\n                consider(edges, c);\n            }\n        }\n\n        for (int iter = 0; iter < 60; ++iter) {\n            if (elapsed() > 1.4) break;\n            vector<pair<int,int>> edges;\n            bitset<1024> cov;\n            long long c = greedyBuild({}, iter % 4, edges, cov);\n            if (cov == allReq) {\n                improveTree(edges, c, cov);\n                consider(edges, c);\n            }\n        }\n\n        /* Phase 2: ILS */\n        const double TL = 2.95;\n        int fail = 0;\n        while (elapsed() < TL) {\n            if (trySwapImprove()) {\n                fail = 0;\n            } else {\n                ++fail;\n                if (fail >= 5) {\n                    bool improved = tryShake(false);\n                    if (improved) {\n                        fail = 0;\n                    } else if (fail >= 10) {\n                        improved = tryShake(true);\n                        if (improved) {\n                            fail = 0;\n                        } else if (elapsed() < TL - 0.15) {\n                            vector<pair<int,int>> edges;\n                            bitset<1024> cov;\n                            long long c = greedyBuild({}, rng() % 4, edges, cov);\n                            if (cov == allReq) {\n                                improveTree(edges, c, cov);\n                                consider(edges, c);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        /* Output doubled DFS tour */\n        vector<vector<int>> finalAdj(V);\n        for (auto &e : bestEdges) {\n            finalAdj[e.first].push_back(e.second);\n            finalAdj[e.second].push_back(e.first);\n        }\n        string tour;\n        function<void(int,int)> dfs = [&](int u, int p) {\n            for (int v : finalAdj[u]) if (v != p) {\n                tour.push_back(dc[dirMove(u, v)]);\n                dfs(v, u);\n                tour.push_back(dc[dirMove(v, u)]);\n            }\n        };\n        dfs(S, -1);\n        cout << tour << \"\\n\";\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.run();\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, K, R;\nvector<vector<int>> task_d;\nvector<int> task_sumd;\nvector<int> task_dom;\nvector<double> task_purity;\nvector<vector<int>> dag_out;\nvector<int> out_deg;\nvector<int> indeg0;\n\nvector<double> down_len;\nvector<int> wait_cnt;\n\nvector<vector<double>> skill_est;\nvector<vector<pair<int,int>>> history;\n\nvector<int> worker_task;\nvector<int> worker_start;\nvector<int> worker_done_cnt;\nvector<int> worker_explore_dim;\n\nvector<int> rem_indeg;\nvector<int> ready;\n\nmt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\ninline double pred_dur(int task, int w) {\n    double wsum = 0.0;\n    const auto &td = task_d[task];\n    const auto &sk = skill_est[w];\n    for (int k = 0; k < K; ++k) {\n        if (td[k] > sk[k]) wsum += td[k] - sk[k];\n    }\n    return wsum < 1.0 ? 1.0 : wsum;\n}\n\nvoid recompute_down_len() {\n    vector<double> mindur(N);\n    for (int i = 0; i < N; ++i) {\n        double best = 1e100;\n        for (int j = 0; j < M; ++j)\n            best = min(best, pred_dur(i, j));\n        mindur[i] = best;\n    }\n    for (int i = N - 1; i >= 0; --i) {\n        double child = 0.0;\n        for (int v : dag_out[i]) child = max(child, down_len[v]);\n        down_len[i] = mindur[i] + child;\n    }\n}\n\n/* Hungarian for n rows, m cols (n <= m), minimisation, 1-indexed inside */\nvector<int> hungarian(const vector<vector<double>>& a) {\n    int n = (int)a.size() - 1;\n    int m = (int)a[0].size() - 1;\n    const double INF = 1e100;\n    vector<double> u(n + 1), v(m + 1);\n    vector<int> p(m + 1), way(m + 1);\n    for (int i = 1; i <= n; ++i) {\n        p[0] = i;\n        int j0 = 0;\n        vector<double> minv(m + 1, INF);\n        vector<char> used(m + 1, false);\n        do {\n            used[j0] = true;\n            int i0 = p[j0], j1 = 0;\n            double delta = INF;\n            for (int j = 1; j <= m; ++j) if (!used[j]) {\n                double cur = a[i0][j] - u[i0] - v[j];\n                if (cur < minv[j]) {\n                    minv[j] = cur;\n                    way[j] = j0;\n                }\n                if (minv[j] < delta) {\n                    delta = minv[j];\n                    j1 = j;\n                }\n            }\n            for (int j = 0; j <= m; ++j) {\n                if (used[j]) {\n                    u[p[j]] += delta;\n                    v[j] -= delta;\n                } else {\n                    minv[j] -= delta;\n                }\n            }\n            j0 = j1;\n        } while (p[j0] != 0);\n        do {\n            int j1 = way[j0];\n            p[j0] = p[j1];\n            j0 = j1;\n        } while (j0);\n    }\n    vector<int> ans(n + 1);\n    for (int j = 1; j <= m; ++j)\n        if (p[j] != 0)\n            ans[p[j]] = j;\n    return ans;\n}\n\n/* Update skill estimate using proper posterior mean targets */\nvoid update_skills(int w) {\n    auto &hist = history[w];\n    if (hist.empty()) return;\n    double lr = max(0.015, 0.4 / sqrt((double)hist.size()));\n    const double LR2 = 0.03;\n    const int EPOCHS = 15;\n    for (int ep = 0; ep < EPOCHS; ++ep) {\n        shuffle(hist.begin(), hist.end(), rng);\n        for (auto &ob : hist) {\n            int tid = ob.first;\n            int odur = ob.second;\n            const auto &td = task_d[tid];\n\n            // Posterior mean of w given observed duration t (uniform prior on w)\n            double target, weight;\n            if (odur == 1) {\n                target = 1.0;    weight = 0.4;\n            } else if (odur == 2) {\n                target = 2.4;    weight = 0.6;\n            } else if (odur == 3) {\n                target = 3.1;    weight = 0.8;\n            } else if (odur == 4) {\n                target = 4.0;    weight = 0.95;\n            } else {\n                target = (double)odur;  weight = 1.0;\n            }\n\n            double wpred = 0.0;\n            vector<int> active;\n            active.reserve(K);\n            for (int k = 0; k < K; ++k) {\n                if (td[k] > skill_est[w][k] + 1e-12) {\n                    wpred += td[k] - skill_est[w][k];\n                    active.push_back(k);\n                }\n            }\n\n            double err = wpred - target;\n            if (fabs(err) < 1e-9) continue;\n\n            if (!active.empty()) {\n                double delta = lr * err * weight / active.size();\n                if (delta >  5.0) delta =  5.0;\n                if (delta < -5.0) delta = -5.0;\n                for (int k : active) {\n                    skill_est[w][k] += delta;\n                    if (skill_est[w][k] < 0.0) skill_est[w][k] = 0.0;\n                }\n            } else if (err < 0.0) {\n                // Need to increase wpred by decreasing skills\n                // Focus on dimensions with smallest positive margin\n                vector<pair<double,int>> margins;\n                for (int k = 0; k < K; ++k) {\n                    if (skill_est[w][k] > 0.0)\n                        margins.emplace_back(skill_est[w][k] - td[k], k);\n                }\n                if (margins.empty()) continue;\n                sort(margins.begin(), margins.end());\n                int nfocus = max(1, K / 3);\n                double dec = LR2 * (-err) * weight / nfocus;\n                if (dec > 5.0) dec = 5.0;\n                for (int i = 0; i < nfocus && i < (int)margins.size(); ++i) {\n                    int k = margins[i].second;\n                    skill_est[w][k] -= dec;\n                    if (skill_est[w][k] < 0.0) skill_est[w][k] = 0.0;\n                }\n            }\n        }\n    }\n}\n\n/* assign tasks for the coming day */\nvector<pair<int,int>> assign_day(int day) {\n    vector<pair<int,int>> out_pairs;\n    vector<int> idle;\n    for (int j = 0; j < M; ++j)\n        if (worker_task[j] == -1) idle.push_back(j);\n\n    if (idle.empty() || ready.empty()) return out_pairs;\n\n    vector<int> avail = ready;\n\n    /* ---- exploration: first 2 tasks per worker ---- */\n    vector<int> explorers;\n    for (int j : idle)\n        if (worker_done_cnt[j] < 2) explorers.push_back(j);\n\n    if (!explorers.empty() && !avail.empty()) {\n        vector<vector<int>> pool_by_dim(K);\n        for (int t : avail) {\n            if (task_sumd[t] > 0 && task_sumd[t] < 50 && task_purity[t] > 0.65) {\n                pool_by_dim[task_dom[t]].push_back(t);\n            }\n        }\n        for (int k = 0; k < K; ++k) {\n            sort(pool_by_dim[k].begin(), pool_by_dim[k].end(),\n                 [&](int a, int b){ return task_sumd[a] < task_sumd[b]; });\n        }\n\n        for (int j : explorers) {\n            if (avail.empty()) break;\n            int dim = worker_explore_dim[j] % K;\n            worker_explore_dim[j]++;\n            int chosen = -1;\n            if (!pool_by_dim[dim].empty()) {\n                chosen = pool_by_dim[dim][0];\n                for (int k = 0; k < K; ++k) {\n                    auto it = find(pool_by_dim[k].begin(), pool_by_dim[k].end(), chosen);\n                    if (it != pool_by_dim[k].end()) pool_by_dim[k].erase(it);\n                }\n            } else {\n                for (int k = 0; k < K && chosen == -1; ++k) {\n                    if (!pool_by_dim[k].empty()) {\n                        chosen = pool_by_dim[k][0];\n                        for (int kk = 0; kk < K; ++kk) {\n                            auto it = find(pool_by_dim[kk].begin(), pool_by_dim[kk].end(), chosen);\n                            if (it != pool_by_dim[kk].end()) pool_by_dim[kk].erase(it);\n                        }\n                    }\n                }\n            }\n            if (chosen == -1) {\n                chosen = *min_element(avail.begin(), avail.end(),\n                    [&](int a, int b){ return task_sumd[a] < task_sumd[b]; });\n            }\n            auto it = find(avail.begin(), avail.end(), chosen);\n            if (it != avail.end()) avail.erase(it);\n            out_pairs.emplace_back(j, chosen);\n            worker_task[j] = chosen;\n            worker_start[j] = day;\n        }\n    }\n\n    /* ---- exploitation: Hungarian matching ---- */\n    vector<int> idle2;\n    for (int j : idle)\n        if (worker_task[j] == -1) idle2.push_back(j);\n\n    if (!idle2.empty() && !avail.empty()) {\n        int nW = (int)idle2.size();\n        int nT = (int)avail.size();\n\n        vector<pair<int,int>> matched;\n        if (nW <= nT) {\n            vector<vector<double>> cost(nW + 1, vector<double>(nT + 1));\n            for (int i = 1; i <= nW; ++i) {\n                for (int j = 1; j <= nT; ++j) {\n                    double pd = pred_dur(avail[j - 1], idle2[i - 1]);\n                    double c = pd\n                             - 0.14 * down_len[avail[j - 1]]\n                             - 0.32 * min(wait_cnt[avail[j - 1]], 50)\n                             - 0.03 * out_deg[avail[j - 1]];\n                    c += uniform_real_distribution<double>(-1e-9, 1e-9)(rng);\n                    cost[i][j] = c;\n                }\n            }\n            auto ans = hungarian(cost);\n            for (int i = 1; i <= nW; ++i) {\n                int t = avail[ans[i] - 1];\n                matched.emplace_back(idle2[i - 1], t);\n            }\n        } else {\n            vector<vector<double>> cost(nT + 1, vector<double>(nW + 1));\n            for (int i = 1; i <= nT; ++i) {\n                for (int j = 1; j <= nW; ++j) {\n                    double pd = pred_dur(avail[i - 1], idle2[j - 1]);\n                    double c = pd\n                             - 0.14 * down_len[avail[i - 1]]\n                             - 0.32 * min(wait_cnt[avail[i - 1]], 50)\n                             - 0.03 * out_deg[avail[i - 1]];\n                    c += uniform_real_distribution<double>(-1e-9, 1e-9)(rng);\n                    cost[i][j] = c;\n                }\n            }\n            auto ans = hungarian(cost);\n            for (int i = 1; i <= nT; ++i) {\n                int w = idle2[ans[i] - 1];\n                matched.emplace_back(w, avail[i - 1]);\n            }\n        }\n\n        for (auto &p : matched) {\n            int j = p.first, t = p.second;\n            out_pairs.emplace_back(j, t);\n            worker_task[j] = t;\n            worker_start[j] = day;\n        }\n    }\n\n    vector<char> mark(N, 0);\n    for (auto &p : out_pairs) mark[p.second] = 1;\n    vector<int> new_ready;\n    new_ready.reserve(ready.size());\n    for (int t : ready)\n        if (!mark[t]) new_ready.push_back(t);\n    ready.swap(new_ready);\n    return out_pairs;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    if (!(cin >> N >> M >> K >> R)) return 0;\n\n    task_d.assign(N, vector<int>(K));\n    task_sumd.assign(N, 0);\n    task_dom.assign(N, 0);\n    task_purity.assign(N, 0.0);\n    for (int i = 0; i < N; ++i) {\n        int s = 0, mx = 0, mk = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> task_d[i][k];\n            s += task_d[i][k];\n            if (task_d[i][k] > mx) {\n                mx = task_d[i][k];\n                mk = k;\n            }\n        }\n        task_sumd[i] = s;\n        task_dom[i] = mk;\n        task_purity[i] = (s == 0) ? 0.0 : (double)mx / s;\n    }\n\n    dag_out.assign(N, {});\n    indeg0.assign(N, 0);\n    out_deg.assign(N, 0);\n    for (int i = 0; i < R; ++i) {\n        int u, v; cin >> u >> v; --u; --v;\n        dag_out[u].push_back(v);\n        ++indeg0[v];\n        ++out_deg[u];\n    }\n\n    wait_cnt.assign(N, 0);\n    skill_est.assign(M, vector<double>(K, 0.0));\n\n    /* initialise with mean difficulty * 1.2 */\n    vector<double> mean_d(K, 0.0);\n    for (int i = 0; i < N; ++i)\n        for (int k = 0; k < K; ++k)\n            mean_d[k] += task_d[i][k];\n    for (int k = 0; k < K; ++k) mean_d[k] /= N;\n    for (int j = 0; j < M; ++j)\n        for (int k = 0; k < K; ++k)\n            skill_est[j][k] = mean_d[k] * 1.2;\n\n    history.assign(M, {});\n    worker_task.assign(M, -1);\n    worker_start.assign(M, -1);\n    worker_done_cnt.assign(M, 0);\n    worker_explore_dim.assign(M, 0);\n    rem_indeg = indeg0;\n    ready.clear();\n    for (int i = 0; i < N; ++i)\n        if (rem_indeg[i] == 0) ready.push_back(i);\n\n    down_len.assign(N, 1.0);\n    recompute_down_len();\n\n    int day = 1;\n    auto assignments = assign_day(day);\n\n    while (true) {\n        cout << assignments.size();\n        for (auto &p : assignments)\n            cout << ' ' << p.first + 1 << ' ' << p.second + 1;\n        cout << '\\n';\n        cout.flush();\n\n        int n;  cin >> n;\n        if (n == -1) break;\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int t : ready) ++wait_cnt[t];\n\n        bool updated = false;\n        for (int j : finished) {\n            int t = worker_task[j];\n            int dur = day - worker_start[j] + 1;\n\n            history[j].emplace_back(t, dur);\n            update_skills(j);\n\n            worker_task[j] = -1;\n            worker_start[j] = -1;\n            ++worker_done_cnt[j];\n            updated = true;\n\n            for (int v : dag_out[t]) {\n                if (--rem_indeg[v] == 0)\n                    ready.push_back(v);\n            }\n        }\n\n        if (updated) recompute_down_len();\n\n        ++day;\n        if (day > 2000) break;\n        assignments = assign_day(day);\n    }\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nint Xc[2001];\nint Yc[2001];\nint dist_mat[2001][2001];\ninline int D(int u, int v) { return dist_mat[u][v]; }\n\n/* node 0 = depot (400,400)\n   order i (0-based): pickup = 2*i+1, delivery = 2*i+2 */\ninline int partner(int v) {\n    if (v & 1) return v + 1;   // pickup -> delivery\n    return v - 1;              // delivery -> pickup\n}\n\n/* ---------- insertion helpers ---------- */\nvoid eval_insert(const vector<int>& route, int oid, int& best_delta, int& best_ip, int& best_id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    int L = (int)route.size();\n    best_delta = INT_MAX;\n    for (int ip = 0; ip < L - 1; ++ip) {\n        int cost_p = D(route[ip], p) + D(p, route[ip + 1]) - D(route[ip], route[ip + 1]);\n        int left = p;\n        for (int id = ip; id < L - 1; ++id) {\n            if (id > ip) left = route[id];\n            int cost_d = D(left, d) + D(d, route[id + 1]) - D(left, route[id + 1]);\n            int delta = cost_p + cost_d;\n            if (delta < best_delta) {\n                best_delta = delta;\n                best_ip = ip;\n                best_id = id;\n            }\n        }\n    }\n}\n\nvoid eval_insert_regret(const vector<int>& route, int oid,\n                        int& best_delta, int& best_ip, int& best_id, int& second_delta) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    int L = (int)route.size();\n    best_delta = INT_MAX;\n    second_delta = INT_MAX;\n    for (int ip = 0; ip < L - 1; ++ip) {\n        int cost_p = D(route[ip], p) + D(p, route[ip + 1]) - D(route[ip], route[ip + 1]);\n        int left = p;\n        for (int id = ip; id < L - 1; ++id) {\n            if (id > ip) left = route[id];\n            int cost_d = D(left, d) + D(d, route[id + 1]) - D(left, route[id + 1]);\n            int delta = cost_p + cost_d;\n            if (delta < best_delta) {\n                second_delta = best_delta;\n                best_delta = delta;\n                best_ip = ip;\n                best_id = id;\n            } else if (delta < second_delta) {\n                second_delta = delta;\n            }\n        }\n    }\n}\n\nvoid apply_insert(vector<int>& route, int oid, int ip, int id) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() + 2);\n    for (int k = 0; k <= ip; ++k) res.push_back(route[k]);\n    res.push_back(p);\n    for (int k = ip + 1; k <= id; ++k) res.push_back(route[k]);\n    res.push_back(d);\n    for (int k = id + 1; k < (int)route.size(); ++k) res.push_back(route[k]);\n    route.swap(res);\n}\n\nvector<int> remove_order(const vector<int>& route, int oid) {\n    int p = 2 * oid + 1;\n    int d = 2 * oid + 2;\n    vector<int> res;\n    res.reserve(route.size() - 2);\n    for (int node : route) if (node != p && node != d) res.push_back(node);\n    return res;\n}\n\nint route_cost(const vector<int>& route) {\n    int sum = 0;\n    for (int i = 0; i + 1 < (int)route.size(); ++i) sum += D(route[i], route[i + 1]);\n    return sum;\n}\n\n/* ---------- local search ---------- */\nbool optimize_pass(vector<int>& route, int& cost) {\n    int n = (int)route.size();\n    vector<int> pos(2001, -1);\n    for (int i = 0; i < n; ++i) pos[route[i]] = i;\n\n    vector<int> pp(n);\n    for (int i = 1; i < n - 1; ++i) pp[i] = pos[partner(route[i])];\n\n    int best_delta = 0;\n    int best_type = -1;          // 0 swap, 1 2opt, 2 relocate\n    int b_i = 0, b_j = 0, b_l = 0, b_r = 0;\n\n    // 1. swap two internal nodes\n    for (int i = 1; i < n - 1; ++i) {\n        for (int j = i + 1; j < n - 1; ++j) {\n            int u = route[i], v = route[j];\n            if (partner(u) == v) continue;               // same order\n            if ((u & 1) && pp[i] <= j) continue;         // pickup must stay before delivery\n            if (!(v & 1) && pp[j] >= i) continue;        // delivery must stay after pickup\n            int delta;\n            if (j == i + 1) {\n                delta = D(route[i - 1], v) + D(v, u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, v) - D(v, route[j + 1]);\n            } else {\n                delta = D(route[i - 1], v) + D(v, route[i + 1])\n                      + D(route[j - 1], u) + D(u, route[j + 1])\n                      - D(route[i - 1], u) - D(u, route[i + 1])\n                      - D(route[j - 1], v) - D(v, route[j + 1]);\n            }\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 0; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    // 2. 2-opt (segment reversal)\n    for (int l = 1; l < n - 1; ++l) {\n        for (int r = l + 1; r < n - 1; ++r) {\n            bool ok = true;\n            for (int k = l; k <= r; ++k) {\n                if (pp[k] >= l && pp[k] <= r) { ok = false; break; }\n            }\n            if (!ok) continue;\n            int delta = D(route[l - 1], route[r]) + D(route[l], route[r + 1])\n                      - D(route[l - 1], route[l]) - D(route[r], route[r + 1]);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 1; b_l = l; b_r = r;\n            }\n        }\n    }\n\n    // 3. relocate a single node\n    for (int i = 1; i < n - 1; ++i) {\n        int u = route[i];\n        int A = route[i - 1], B = route[i + 1];\n        int delta_remove = D(A, B) - D(A, u) - D(u, B);\n        // move left: j < i\n        for (int j = 1; j < i; ++j) {\n            if (!(u & 1) && j <= pp[i]) continue; // delivery cannot pass its pickup\n            int left = route[j - 1], right = route[j];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n        // move right: j > i\n        for (int j = i + 1; j < n - 1; ++j) {\n            if ((u & 1) && j >= pp[i]) continue; // pickup cannot pass its delivery\n            int left = route[j], right = route[j + 1];\n            int delta = delta_remove + D(left, u) + D(u, right) - D(left, right);\n            if (delta < best_delta) {\n                best_delta = delta; best_type = 2; b_i = i; b_j = j;\n            }\n        }\n    }\n\n    if (best_type == -1) return false;\n\n    if (best_type == 0) {\n        swap(route[b_i], route[b_j]);\n    } else if (best_type == 1) {\n        reverse(route.begin() + b_l, route.begin() + b_r + 1);\n    } else {\n        int u = route[b_i];\n        route.erase(route.begin() + b_i);\n        route.insert(route.begin() + b_j, u);\n    }\n    cost += best_delta;\n    return true;\n}\n\nvoid optimize_route(vector<int>& route, int& cost) {\n    while (optimize_pass(route, cost)) {}\n}\n\n/* ---------- construction ---------- */\nstruct State {\n    vector<int> route;\n    vector<int> selected;\n    int cost;\n};\n\nState greedy_build_rand(int rand_k, mt19937& rng) {\n    State st;\n    st.route = {0, 0};\n    st.selected.reserve(50);\n    vector<char> used(1000, 0);\n    struct Cand { int delta, oid, ip, id; };\n    for (int step = 0; step < 50; ++step) {\n        vector<Cand> cands;\n        cands.reserve(1000);\n        for (int oid = 0; oid < 1000; ++oid) if (!used[oid]) {\n            int d, ip, id;\n            eval_insert(st.route, oid, d, ip, id);\n            cands.push_back({d, oid, ip, id});\n        }\n        sort(cands.begin(), cands.end(),\n             [](const Cand& a, const Cand& b){ return a.delta < b.delta; });\n        int k = min(rand_k, max(1, (int)cands.size()));\n        int pick = uniform_int_distribution<int>(0, k - 1)(rng);\n        const Cand& c = cands[pick];\n        apply_insert(st.route, c.oid, c.ip, c.id);\n        used[c.oid] = 1;\n        st.selected.push_back(c.oid);\n    }\n    st.cost = route_cost(st.route);\n    return st;\n}\n\nState greedy_build_regret(mt19937& rng) {\n    State st;\n    st.route = {0, 0};\n    st.selected.reserve(50);\n    vector<char> used(1000, 0);\n    for (int step = 0; step < 50; ++step) {\n        int best_oid = -1, best_ip = 0, best_id = 0;\n        int max_regret = -1;\n        for (int oid = 0; oid < 1000; ++oid) if (!used[oid]) {\n            int d1, ip1, id1, d2;\n            eval_insert_regret(st.route, oid, d1, ip1, id1, d2);\n            int regret = (d2 >= INT_MAX / 2) ? 0 : (d2 - d1);\n            if (regret > max_regret) {\n                max_regret = regret;\n                best_oid = oid;\n                best_ip = ip1;\n                best_id = id1;\n            }\n        }\n        apply_insert(st.route, best_oid, best_ip, best_id);\n        used[best_oid] = 1;\n        st.selected.push_back(best_oid);\n    }\n    st.cost = route_cost(st.route);\n    return st;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    vector<int> ax(1000), ay(1000), cx(1000), cy(1000);\n    for (int i = 0; i < 1000; ++i) {\n        cin >> ax[i] >> ay[i] >> cx[i] >> cy[i];\n    }\n\n    Xc[0] = Yc[0] = 400;\n    for (int i = 0; i < 1000; ++i) {\n        Xc[2 * i + 1] = ax[i]; Yc[2 * i + 1] = ay[i];\n        Xc[2 * i + 2] = cx[i]; Yc[2 * i + 2] = cy[i];\n    }\n    for (int i = 0; i < 2001; ++i)\n        for (int j = 0; j < 2001; ++j)\n            dist_mat[i][j] = abs(Xc[i] - Xc[j]) + abs(Yc[i] - Yc[j]);\n\n    vector<int> standalone(1000);\n    for (int i = 0; i < 1000; ++i)\n        standalone[i] = D(0, 2 * i + 1) + D(2 * i + 1, 2 * i + 2) + D(2 * i + 2, 0);\n\n    vector<int> order_ids(1000);\n    iota(order_ids.begin(), order_ids.end(), 0);\n    sort(order_ids.begin(), order_ids.end(),\n         [&](int a, int b){ return standalone[a] < standalone[b]; });\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]()->double {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n    const double TL = 1.95;\n\n    State best;\n    best.cost = INT_MAX;\n\n    /* ---- Phase 1: many diversified constructions ---- */\n    int attempt = 0;\n    while (elapsed() < TL * 0.70) {\n        ++attempt;\n        State cur;\n        if (attempt % 5 == 0) {\n            cur = greedy_build_regret(rng);\n        } else {\n            int k = 2 + (attempt % 4); // 2..5\n            cur = greedy_build_rand(k, rng);\n        }\n        optimize_route(cur.route, cur.cost);\n        if (cur.cost < best.cost) best = cur;\n    }\n\n    /* ---- Phase 2: intensive 1-swap on the best set ---- */\n    {\n        bool improved = true;\n        while (improved && elapsed() < TL * 0.88) {\n            improved = false;\n            vector<char> in_sel(1000, 0);\n            for (int oid : best.selected) in_sel[oid] = 1;\n            vector<int> cand_out;\n            for (int oid : order_ids) {\n                if (!in_sel[oid]) {\n                    cand_out.push_back(oid);\n                    if ((int)cand_out.size() >= 300) break;\n                }\n            }\n            int best_in = -1, best_out = -1, best_ip = -1, best_id = -1;\n            int best_new_cost = best.cost;\n            for (int oid_in : best.selected) {\n                if (elapsed() > TL * 0.88) break;\n                vector<int> tmp = remove_order(best.route, oid_in);\n                int tmp_cost = route_cost(tmp);\n                for (int oid_out : cand_out) {\n                    int dlt, ip, id;\n                    eval_insert(tmp, oid_out, dlt, ip, id);\n                    int ncost = tmp_cost + dlt;\n                    if (ncost < best_new_cost) {\n                        best_new_cost = ncost;\n                        best_in = oid_in;\n                        best_out = oid_out;\n                        best_ip = ip;\n                        best_id = id;\n                    }\n                }\n            }\n            if (best_in != -1) {\n                vector<int> nr = remove_order(best.route, best_in);\n                apply_insert(nr, best_out, best_ip, best_id);\n                best.route = move(nr);\n                best.cost = best_new_cost;\n                for (int& oid : best.selected) if (oid == best_in) { oid = best_out; break; }\n                optimize_route(best.route, best.cost);\n                improved = true;\n            }\n        }\n    }\n\n    /* ---- Phase 3: iterated local search by random 1-swap ---- */\n    State cur = best;\n    while (elapsed() < TL) {\n        int rem_idx = uniform_int_distribution<int>(0, 49)(rng);\n        int rem_oid = cur.selected[rem_idx];\n        vector<int> base = remove_order(cur.route, rem_oid);\n        int base_cost = route_cost(base);\n\n        vector<char> in_sel(1000, 0);\n        for (int oid : cur.selected) in_sel[oid] = 1;\n        in_sel[rem_oid] = 0;\n\n        int best_add = -1, best_ip = 0, best_id = 0;\n        int best_add_delta = INT_MAX;\n        for (int t = 0; t < 50; ++t) {\n            int add_oid = uniform_int_distribution<int>(0, 999)(rng);\n            if (in_sel[add_oid]) continue;\n            int dlt, ip, id;\n            eval_insert(base, add_oid, dlt, ip, id);\n            if (dlt < best_add_delta) {\n                best_add_delta = dlt;\n                best_add = add_oid;\n                best_ip = ip;\n                best_id = id;\n            }\n        }\n        if (best_add == -1) continue;\n\n        vector<int> nr = base;\n        apply_insert(nr, best_add, best_ip, best_id);\n        int nc = base_cost + best_add_delta;\n        optimize_route(nr, nc);\n        if (nc < cur.cost) {\n            cur.route = move(nr);\n            cur.cost = nc;\n            cur.selected[rem_idx] = best_add;\n            if (nc < best.cost) best = cur;\n        } else {\n            if (uniform_int_distribution<int>(0, 4)(rng) == 0) cur = best;\n        }\n    }\n\n    cout << best.selected.size();\n    for (int oid : best.selected) cout << ' ' << (oid + 1);\n    cout << \"\\n\";\n    cout << best.route.size();\n    for (int node : best.route) cout << ' ' << Xc[node] << ' ' << Yc[node];\n    cout << \"\\n\";\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*** DSU ***/\nstruct DSU {\n    unsigned short p[400];\n    unsigned char r[400];\n    void init() {\n        for (int i = 0; i < 400; ++i) {\n            p[i] = (unsigned short)i;\n            r[i] = 0;\n        }\n    }\n    int find(int x) {\n        unsigned short *pp = p;\n        while (pp[x] != x) {\n            pp[x] = pp[pp[x]];\n            x = pp[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (r[a] < r[b]) swap(a, b);\n        p[b] = (unsigned short)a;\n        if (r[a] == r[b]) ++r[a];\n        return true;\n    }\n    bool same(int a, int b) { return find(a) == find(b); }\n};\n\n/*** LCA with MAX edge weight on tier-0 tree ***/\nstruct LCA {\n    int n, LOG;\n    vector<vector<pair<int,int>>> adj;\n    vector<vector<int>> up;\n    vector<vector<int>> mx;\n    vector<int> dep;\n    LCA(int n = 0) { init(n); }\n    void init(int n_) {\n        n = n_;\n        LOG = 1;\n        while ((1 << LOG) <= n) ++LOG;\n        adj.assign(n, {});\n        up.assign(LOG, vector<int>(n, -1));\n        mx.assign(LOG, vector<int>(n, 0));\n        dep.assign(n, 0);\n    }\n    void add_edge(int u, int v, int w) {\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n    void dfs(int v, int p, int d) {\n        up[0][v] = p;\n        dep[v] = d;\n        for (auto [to, w] : adj[v]) {\n            if (to == p) continue;\n            mx[0][to] = w;\n            dfs(to, v, d + 1);\n        }\n    }\n    void build(int root = 0) {\n        dfs(root, -1, 0);\n        for (int k = 1; k < LOG; ++k) {\n            for (int v = 0; v < n; ++v) {\n                if (up[k-1][v] != -1) {\n                    up[k][v] = up[k-1][ up[k-1][v] ];\n                    mx[k][v] = max(mx[k-1][v], mx[k-1][ up[k-1][v] ]);\n                }\n            }\n        }\n    }\n    int query(int u, int v) const {\n        if (u == v) return 0;\n        if (dep[u] < dep[v]) swap(u, v);\n        int res = 0;\n        int diff = dep[u] - dep[v];\n        for (int k = 0; k < LOG; ++k) {\n            if (diff >> k & 1) {\n                res = max(res, mx[k][u]);\n                u = up[k][u];\n            }\n        }\n        if (u == v) return res;\n        for (int k = LOG - 1; k >= 0; --k) {\n            if (up[k][u] != -1 && up[k][u] != up[k][v]) {\n                res = max(res, mx[k][u]);\n                res = max(res, mx[k][v]);\n                u = up[k][u];\n                v = up[k][v];\n            }\n        }\n        res = max(res, mx[0][u]);\n        res = max(res, mx[0][v]);\n        return res;\n    }\n};\n\n/*** LCA with MIN edge weight on tier-0 tree ***/\nstruct LCA_MIN {\n    int n, LOG;\n    vector<vector<pair<int,int>>> adj;\n    vector<vector<int>> up;\n    vector<vector<int>> mn;\n    vector<int> dep;\n    LCA_MIN(int n = 0) { init(n); }\n    void init(int n_) {\n        n = n_;\n        LOG = 1;\n        while ((1 << LOG) <= n) ++LOG;\n        adj.assign(n, {});\n        up.assign(LOG, vector<int>(n, -1));\n        mn.assign(LOG, vector<int>(n, INT_MAX));\n        dep.assign(n, 0);\n    }\n    void add_edge(int u, int v, int w) {\n        adj[u].push_back({v, w});\n        adj[v].push_back({u, w});\n    }\n    void dfs(int v, int p, int d) {\n        up[0][v] = p;\n        dep[v] = d;\n        for (auto [to, w] : adj[v]) {\n            if (to == p) continue;\n            mn[0][to] = w;\n            dfs(to, v, d + 1);\n        }\n    }\n    void build(int root = 0) {\n        dfs(root, -1, 0);\n        for (int k = 1; k < LOG; ++k) {\n            for (int v = 0; v < n; ++v) {\n                if (up[k-1][v] != -1) {\n                    up[k][v] = up[k-1][ up[k-1][v] ];\n                    mn[k][v] = min(mn[k-1][v], mn[k-1][ up[k-1][v] ]);\n                }\n            }\n        }\n    }\n    int query(int u, int v) const {\n        if (u == v) return INT_MAX;\n        if (dep[u] < dep[v]) swap(u, v);\n        int res = INT_MAX;\n        int diff = dep[u] - dep[v];\n        for (int k = 0; k < LOG; ++k) {\n            if (diff >> k & 1) {\n                res = min(res, mn[k][u]);\n                u = up[k][u];\n            }\n        }\n        if (u == v) return res;\n        for (int k = LOG - 1; k >= 0; --k) {\n            if (up[k][u] != -1 && up[k][u] != up[k][v]) {\n                res = min(res, mn[k][u]);\n                res = min(res, mn[k][v]);\n                u = up[k][u];\n                v = up[k][v];\n            }\n        }\n        res = min(res, mn[0][u]);\n        res = min(res, mn[0][v]);\n        return res;\n    }\n};\n\n/*** Fast bucket Kruskal (weights <= 3600) ***/\nstruct Solver {\n    static const int MAXW = 3600;\n    static const int MAXE = 2005;\n    static const int MAXV = 400;\n    short U[MAXE];\n    short V[MAXE];\n    int nxt[MAXE];\n    int head[MAXW];\n    int vis[MAXW];\n    int ecnt;\n    int curVis;\n    int minW, maxW;\n    int par[MAXV];\n    unsigned char rnk[MAXV];\n    Solver() {\n        memset(vis, 0, sizeof(vis));\n        curVis = 1;\n    }\n    inline void clear() {\n        ecnt = 0;\n        ++curVis;\n        minW = MAXW;\n        maxW = 0;\n    }\n    inline void add(int w, short u, short v) {\n        if (vis[w] != curVis) {\n            vis[w] = curVis;\n            head[w] = -1;\n        }\n        U[ecnt] = u;\n        V[ecnt] = v;\n        nxt[ecnt] = head[w];\n        head[w] = ecnt++;\n        if (w < minW) minW = w;\n        if (w > maxW) maxW = w;\n    }\n    inline int find(int x) {\n        int root = x;\n        while (par[root] != root) root = par[root];\n        while (par[x] != x) {\n            int p = par[x];\n            par[x] = root;\n            x = p;\n        }\n        return root;\n    }\n    inline bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a, b);\n        par[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n    long long solve(int need) {\n        if (need <= 0) return 0;\n        for (int i = 0; i < MAXV; ++i) {\n            par[i] = i;\n            rnk[i] = 0;\n        }\n        int taken = 0;\n        long long sum = 0;\n        for (int w = minW; w <= maxW; ++w) {\n            if (vis[w] != curVis) continue;\n            for (int e = head[w]; e != -1; e = nxt[e]) {\n                if (unite(U[e], V[e])) {\n                    sum += w;\n                    if (++taken == need) return sum;\n                }\n            }\n        }\n        return sum;\n    }\n};\n\n/*** fast bounded RNG ***/\nstatic inline uint32_t rand_range(uint64_t &state, uint32_t range) {\n    state = state * 6364136223846793005ULL + 1;\n    return (uint32_t)(((state >> 32) * (uint64_t)range) >> 32);\n}\n\nint main() {\n    const int N = 400;\n    const int M = 1995;\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; ++i) scanf(\"%d %d\", &xs[i], &ys[i]);\n    vector<int> U(M), V(M);\n    for (int i = 0; i < M; ++i) scanf(\"%d %d\", &U[i], &V[i]);\n\n    vector<int> d(M);\n    for (int i = 0; i < M; ++i) {\n        long long dx = (long long)xs[U[i]] - xs[V[i]];\n        long long dy = (long long)ys[U[i]] - ys[V[i]];\n        long long dist2 = dx * dx + dy * dy;\n        d[i] = (int)llround(sqrt((double)dist2));\n    }\n\n    /*--- tiers 0..4 by repeated Kruskal on d ---*/\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) { return d[a] < d[b]; });\n\n    vector<char> used(M, 0);\n    vector<int> tier(M, -1);\n    for (int t = 0; t < 5; ++t) {\n        DSU dsu_tier;\n        dsu_tier.init();\n        int cnt = 0;\n        for (int idx : order) {\n            if (used[idx]) continue;\n            if (dsu_tier.unite(U[idx], V[idx])) {\n                used[idx] = 1;\n                tier[idx] = t;\n                if (++cnt == N - 1) break;\n            }\n        }\n    }\n\n    /*--- tier-0 tree structures ---*/\n    LCA lca(N);\n    LCA_MIN lca_min(N);\n    vector<vector<pair<int,int>>> tree_adj(N);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) {\n            lca.add_edge(U[i], V[i], d[i]);\n            lca_min.add_edge(U[i], V[i], d[i]);\n            tree_adj[U[i]].push_back({V[i], i});\n            tree_adj[V[i]].push_back({U[i], i});\n        }\n    }\n    lca.build(0);\n    lca_min.build(0);\n\n    vector<int> maxd_path(M, 0);\n    vector<int> mind_path(M, 0);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) {\n            maxd_path[i] = d[i];\n            mind_path[i] = d[i];\n        } else {\n            maxd_path[i] = lca.query(U[i], V[i]);\n            mind_path[i] = lca_min.query(U[i], V[i]);\n        }\n    }\n\n    int parent[400];\n    int parent_edge[400];\n    int depth[400];\n    function<void(int,int)> dfs = [&](int v, int p) {\n        for (auto [to, eidx] : tree_adj[v]) {\n            if (to == p) continue;\n            parent[to] = v;\n            parent_edge[to] = eidx;\n            depth[to] = depth[v] + 1;\n            dfs(to, v);\n        }\n    };\n    parent[0] = -1;\n    parent_edge[0] = -1;\n    depth[0] = 0;\n    dfs(0, -1);\n\n    const int INF = 1e9;\n    vector<int> rep_d(M, INF);\n    vector<int> max_cross_d(M, 0);\n    for (int i = 0; i < M; ++i) {\n        if (tier[i] == 0) continue;\n        int u = U[i], v = V[i];\n        while (depth[u] > depth[v]) {\n            int eidx = parent_edge[u];\n            if (d[i] < rep_d[eidx]) rep_d[eidx] = d[i];\n            if (d[i] > max_cross_d[eidx]) max_cross_d[eidx] = d[i];\n            u = parent[u];\n        }\n        while (depth[v] > depth[u]) {\n            int eidx = parent_edge[v];\n            if (d[i] < rep_d[eidx]) rep_d[eidx] = d[i];\n            if (d[i] > max_cross_d[eidx]) max_cross_d[eidx] = d[i];\n            v = parent[v];\n        }\n        while (u != v) {\n            int eidx_u = parent_edge[u];\n            if (d[i] < rep_d[eidx_u]) rep_d[eidx_u] = d[i];\n            if (d[i] > max_cross_d[eidx_u]) max_cross_d[eidx_u] = d[i];\n            u = parent[u];\n            int eidx_v = parent_edge[v];\n            if (d[i] < rep_d[eidx_v]) rep_d[eidx_v] = d[i];\n            if (d[i] > max_cross_d[eidx_v]) max_cross_d[eidx_v] = d[i];\n            v = parent[v];\n        }\n    }\n\n    /*--- online decisions ---*/\n    DSU dsu;\n    dsu.init();\n    int comp = N;\n\n    Solver solver_rej, solver_acc;\n    uint64_t rng = 123456789123456789ULL;\n\n    short buf_a[M];\n    short buf_b[M];\n    short buf_d[M];\n    uint16_t buf_r[M];\n\n    short acc_a[M];\n    short acc_b[M];\n    int acc_idx[M];\n    int wbuf[M];\n    int comp_of[400];\n\n    const double ACC_QUICK[5] = {1.12, 1.10, 1.08, 1.04, 1.02};\n    const double REJ_QUICK[5] = {2.90, 2.80, 2.70, 2.60, 2.50};\n\n    for (int i = 0; i < M; ++i) {\n        long long l;\n        scanf(\"%lld\", &l);\n        int u = U[i], v = V[i];\n\n        if (dsu.same(u, v)) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        for (int x = 0; x < N; ++x) comp_of[x] = dsu.find(x);\n        int cu = comp_of[u];\n        int cv = comp_of[v];\n\n        /* bridge check + build future cross-edge buffer */\n        DSU tmp = dsu;\n        int E = 0;\n        bool connected = false;\n        for (int j = i + 1; j < M; ++j) {\n            int a = comp_of[U[j]];\n            int b = comp_of[V[j]];\n            if (a == b) continue;\n            buf_a[E] = (short)a;\n            buf_b[E] = (short)b;\n            buf_d[E] = (short)d[j];\n            buf_r[E] = (uint16_t)(2 * d[j] + 1);\n            ++E;\n            if (!connected) {\n                tmp.unite(a, b);\n                if (tmp.same(cu, cv)) connected = true;\n            }\n        }\n\n        if (!connected) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n\n        /* rigorous guaranteed accepts */\n        if (tier[i] == 0 && l < rep_d[i]) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n        if (tier[i] > 0 && l < mind_path[i]) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n\n        /* rigorous guaranteed rejects */\n        if (tier[i] == 0 && max_cross_d[i] > 0 && l > 3LL * max_cross_d[i]) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n        if (tier[i] > 0 && l > 3LL * maxd_path[i]) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        /* quick heuristic filters */\n        double ratio = (double)l / (double)d[i];\n        if (ratio <= ACC_QUICK[tier[i]]) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n            continue;\n        }\n        if (ratio >= REJ_QUICK[tier[i]]) {\n            printf(\"0\\n\");\n            fflush(stdout);\n            continue;\n        }\n\n        /* precompute contracted endpoints for accept solver */\n        int E_acc = 0;\n        for (int k = 0; k < E; ++k) {\n            int a2 = buf_a[k];\n            int b2 = buf_b[k];\n            if (a2 == cv) a2 = cu;\n            if (b2 == cv) b2 = cu;\n            if (a2 != b2) {\n                acc_idx[E_acc] = k;\n                acc_a[E_acc] = (short)a2;\n                acc_b[E_acc] = (short)b2;\n                ++E_acc;\n            }\n        }\n\n        /* adaptive Monte-Carlo with increased late-game samples */\n        int K;\n        if (comp > 300) K = 28;\n        else if (comp > 200) K = 50;\n        else if (comp > 100) K = 80;\n        else if (comp > 50) K = 110;\n        else if (comp > 20) K = 155;\n        else K = 200;\n\n        long long total = 0;\n        for (int s = 0; s < K; ++s) {\n            solver_rej.clear();\n            solver_acc.clear();\n            for (int k = 0; k < E; ++k) {\n                wbuf[k] = buf_d[k] + (int)rand_range(rng, (uint32_t)buf_r[k]);\n                solver_rej.add(wbuf[k], buf_a[k], buf_b[k]);\n            }\n            for (int k = 0; k < E_acc; ++k) {\n                int idx = acc_idx[k];\n                solver_acc.add(wbuf[idx], acc_a[k], acc_b[k]);\n            }\n            long long w_rej = solver_rej.solve(comp - 1);\n            long long w_acc = l + solver_acc.solve(comp - 2);\n            total += w_acc - w_rej;\n        }\n\n        if (total < 0) {\n            printf(\"1\\n\");\n            fflush(stdout);\n            dsu.unite(u, v);\n            --comp;\n        } else {\n            printf(\"0\\n\");\n            fflush(stdout);\n        }\n    }\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int H = 30;\nconstexpr int W = 30;\nconstexpr int MAX_TURN = 300;\nconst int dx[4] = {-1, 1, 0, 0};\nconst int dy[4] = {0, 0, -1, 1};\nconst char BUILD[4] = {'u', 'd', 'l', 'r'};\nconst char MOVE[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int x, y;\n};\n\nbool in_bounds(int x, int y) {\n    return x >= 0 && x < H && y >= 0 && y < W;\n}\n\nchar build_action(int hx, int hy, int wx, int wy) {\n    if (wx == hx - 1 && wy == hy) return 'u';\n    if (wx == hx + 1 && wy == hy) return 'd';\n    if (wx == hx && wy == hy - 1) return 'l';\n    if (wx == hx && wy == hy + 1) return 'r';\n    return '.';\n}\n\nchar move_action(int hx, int hy, int nx, int ny) {\n    if (nx == hx - 1 && ny == hy) return 'U';\n    if (nx == hx + 1 && ny == hy) return 'D';\n    if (nx == hx && ny == hy - 1) return 'L';\n    if (nx == hx && ny == hy + 1) return 'R';\n    return '.';\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Pos> pet_pos(N);\n    vector<int> pet_type(N);\n    for (int i = 0; i < N; ++i) {\n        cin >> pet_pos[i].x >> pet_pos[i].y >> pet_type[i];\n        --pet_pos[i].x; --pet_pos[i].y;\n    }\n\n    int M;\n    cin >> M;\n    vector<Pos> human_pos(M);\n    for (int i = 0; i < M; ++i) {\n        cin >> human_pos[i].x >> human_pos[i].y;\n        --human_pos[i].x; --human_pos[i].y;\n    }\n\n    vector<vector<bool>> passable(H, vector<bool>(W, true));\n    vector<vector<bool>> has_pet(H, vector<bool>(W, false));\n    vector<vector<bool>> has_human(H, vector<bool>(W, false));\n\n    auto update_occupancy = [&]() {\n        for (int i = 0; i < H; ++i) {\n            fill(has_pet[i].begin(), has_pet[i].end(), false);\n            fill(has_human[i].begin(), has_human[i].end(), false);\n        }\n        for (auto &p : pet_pos) has_pet[p.x][p.y] = true;\n        for (auto &h : human_pos) has_human[h.x][h.y] = true;\n    };\n    update_occupancy();\n\n    // Prefix sum of initial pets\n    vector<vector<int>> pet_ps(H + 1, vector<int>(W + 1, 0));\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            pet_ps[i + 1][j + 1] = pet_ps[i][j + 1] + pet_ps[i + 1][j] - pet_ps[i][j] + (has_pet[i][j] ? 1 : 0);\n        }\n    }\n    auto rect_pet_cnt = [&](int r1, int c1, int r2, int c2) -> int {\n        if (r1 > r2 || c1 > c2) return 0;\n        return pet_ps[r2 + 1][c2 + 1] - pet_ps[r1][c2 + 1] - pet_ps[r2 + 1][c1] + pet_ps[r1][c1];\n    };\n\n    // Find best rectangle\n    long long best_score = LLONG_MIN;\n    int best_r1 = 0, best_c1 = 0, best_r2 = 0, best_c2 = 0;\n    for (int r1 = 0; r1 < H; ++r1) {\n        for (int r2 = r1; r2 < H; ++r2) {\n            for (int c1 = 0; c1 < W; ++c1) {\n                for (int c2 = c1; c2 < W; ++c2) {\n                    int area = (r2 - r1 + 1) * (c2 - c1 + 1);\n                    int petcnt = rect_pet_cnt(r1, c1, r2, c2);\n                    if (petcnt > 5) continue; // too many pets, not worth it\n\n                    int walls = 0;\n                    if (r1 > 0) walls += (c2 - c1 + 1);\n                    if (r2 < H - 1) walls += (c2 - c1 + 1);\n                    if (c1 > 0) walls += (r2 - r1 + 1);\n                    if (c2 < W - 1) walls += (r2 - r1 + 1);\n\n                    int sumd = 0;\n                    for (auto &h : human_pos) {\n                        int tx = max(r1, min(h.x, r2));\n                        int ty = max(c1, min(h.y, c2));\n                        sumd += abs(h.x - tx) + abs(h.y - ty);\n                    }\n\n                    long long value = (long long)area * 1000000LL / (1LL << petcnt);\n                    long long score = value - (long long)walls * 100 - (long long)sumd * 10;\n                    if (score > best_score) {\n                        best_score = score;\n                        best_r1 = r1; best_c1 = c1;\n                        best_r2 = r2; best_c2 = c2;\n                    }\n                }\n            }\n        }\n    }\n\n    int R1 = best_r1, C1 = best_c1, R2 = best_r2, C2 = best_c2;\n\n    // Generate wall cells\n    vector<Pos> all_walls;\n    if (R1 > 0) for (int c = C1; c <= C2; ++c) all_walls.push_back({R1 - 1, c});\n    if (R2 < H - 1) for (int c = C1; c <= C2; ++c) all_walls.push_back({R2 + 1, c});\n    if (C1 > 0) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C1 - 1});\n    if (C2 < W - 1) for (int r = R1; r <= R2; ++r) all_walls.push_back({r, C2 + 1});\n\n    // Choose gate farthest from initial pets\n    Pos gate = {-1, -1};\n    if (!all_walls.empty()) {\n        int best = -1;\n        for (auto &w : all_walls) {\n            int mind = 1e9;\n            for (auto &p : pet_pos) mind = min(mind, abs(w.x - p.x) + abs(w.y - p.y));\n            if (mind > best) {\n                best = mind;\n                gate = w;\n            }\n        }\n    }\n\n    vector<Pos> pre_walls;\n    set<pair<int,int>> gate_set;\n    if (gate.x != -1) gate_set.insert({gate.x, gate.y});\n    for (auto &w : all_walls) {\n        if (!gate_set.count({w.x, w.y})) pre_walls.push_back(w);\n    }\n\n    Pos gate_inside = {-1, -1};\n    if (gate.x != -1) {\n        for (int d = 0; d < 4; ++d) {\n            int nx = gate.x + dx[d], ny = gate.y + dy[d];\n            if (nx >= R1 && nx <= R2 && ny >= C1 && ny <= C2) {\n                gate_inside = {nx, ny};\n                break;\n            }\n        }\n    }\n\n    auto can_build = [&](int wx, int wy) -> bool {\n        if (!passable[wx][wy]) return false;\n        if (has_pet[wx][wy] || has_human[wx][wy]) return false;\n        for (int d = 0; d < 4; ++d) {\n            int ax = wx + dx[d], ay = wy + dy[d];\n            if (in_bounds(ax, ay) && has_pet[ax][ay]) return false;\n        }\n        return true;\n    };\n\n    for (int turn = 0; turn < MAX_TURN; ++turn) {\n        update_occupancy();\n\n        string action(M, '.');\n        vector<vector<bool>> blocked(H, vector<bool>(W, false));\n        for (int x = 0; x < H; ++x)\n            for (int y = 0; y < W; ++y)\n                blocked[x][y] = !passable[x][y];\n\n        vector<bool> prewall_built(pre_walls.size(), false);\n        for (int i = 0; i < (int)pre_walls.size(); ++i)\n            prewall_built[i] = !passable[pre_walls[i].x][pre_walls[i].y];\n        bool all_prewalls_done = true;\n        for (bool b : prewall_built) if (!b) { all_prewalls_done = false; break; }\n\n        vector<bool> is_inside(M, false);\n        for (int i = 0; i < M; ++i)\n            is_inside[i] = (human_pos[i].x >= R1 && human_pos[i].x <= R2 && human_pos[i].y >= C1 && human_pos[i].y <= C2);\n        bool all_inside = true;\n        for (bool b : is_inside) if (!b) { all_inside = false; break; }\n\n        set<pair<int,int>> being_built;\n        set<pair<int,int>> move_targets;\n        vector<bool> acted(M, false);\n\n        // 1. Try to build pre-walls or gate\n        for (int i = 0; i < M; ++i) {\n            if (acted[i]) continue;\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n\n            // Build a pre-wall\n            int chosen_j = -1;\n            for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                if (prewall_built[j]) continue;\n                int wx = pre_walls[j].x, wy = pre_walls[j].y;\n                if (abs(hx - wx) + abs(hy - wy) != 1) continue;\n                if (being_built.count({wx, wy})) continue;\n                if (move_targets.count({wx, wy})) continue;\n                if (!can_build(wx, wy)) continue;\n                chosen_j = j;\n                break;\n            }\n            if (chosen_j != -1) {\n                int wx = pre_walls[chosen_j].x, wy = pre_walls[chosen_j].y;\n                action[i] = build_action(hx, hy, wx, wy);\n                acted[i] = true;\n                being_built.insert({wx, wy});\n                blocked[wx][wy] = true;\n                continue;\n            }\n\n            // Build gate if ready\n            if (all_prewalls_done && all_inside && gate.x != -1 && passable[gate.x][gate.y]) {\n                if (abs(hx - gate.x) + abs(hy - gate.y) == 1 && can_build(gate.x, gate.y) && !being_built.count({gate.x, gate.y}) && !move_targets.count({gate.x, gate.y})) {\n                    action[i] = build_action(hx, hy, gate.x, gate.y);\n                    acted[i] = true;\n                    being_built.insert({gate.x, gate.y});\n                    blocked[gate.x][gate.y] = true;\n                    continue;\n                }\n            }\n        }\n\n        // 2. Move\n        for (int i = 0; i < M; ++i) {\n            if (acted[i]) continue;\n\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n\n            // BFS\n            vector<vector<int>> dist(H, vector<int>(W, -1));\n            vector<vector<pair<int,int>>> par(H, vector<pair<int,int>>(W, {-1, -1}));\n            queue<pair<int,int>> q;\n            dist[hx][hy] = 0;\n            q.push({hx, hy});\n            while (!q.empty()) {\n                auto [x, y] = q.front(); q.pop();\n                for (int d = 0; d < 4; ++d) {\n                    int nx = x + dx[d], ny = y + dy[d];\n                    if (!in_bounds(nx, ny)) continue;\n                    if (blocked[nx][ny]) continue;\n                    if (dist[nx][ny] != -1) continue;\n                    dist[nx][ny] = dist[x][y] + 1;\n                    par[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n\n            Pos move_target = {-1, -1};\n\n            if (!all_prewalls_done) {\n                // Move toward nearest unbuilt pre-wall (prefer buildable)\n                int best_d = 1e9;\n                bool best_buildable = false;\n                Pos best_pos = {-1, -1};\n                for (int j = 0; j < (int)pre_walls.size(); ++j) {\n                    if (prewall_built[j]) continue;\n                    int wx = pre_walls[j].x, wy = pre_walls[j].y;\n                    bool buildable = can_build(wx, wy);\n                    for (int d = 0; d < 4; ++d) {\n                        int ax = wx + dx[d], ay = wy + dy[d];\n                        if (!in_bounds(ax, ay)) continue;\n                        if (dist[ax][ay] == -1) continue;\n                        if (buildable && !best_buildable) {\n                            best_buildable = true;\n                            best_d = dist[ax][ay];\n                            best_pos = {ax, ay};\n                        } else if (buildable == best_buildable && dist[ax][ay] < best_d) {\n                            best_d = dist[ax][ay];\n                            best_pos = {ax, ay};\n                        }\n                    }\n                }\n                if (best_pos.x != -1) {\n                    if (best_d == 0) {\n                        // Already adjacent but cannot build now (blocked by pet, etc). Wait.\n                        action[i] = '.';\n                        acted[i] = true;\n                        continue;\n                    } else {\n                        move_target = best_pos;\n                    }\n                }\n            } else if (!is_inside[i]) {\n                // Need to enter\n                if (gate.x != -1) {\n                    if (hx == gate.x && hy == gate.y && gate_inside.x != -1) {\n                        // Standing on gate, move inside\n                        action[i] = move_action(hx, hy, gate_inside.x, gate_inside.y);\n                        acted[i] = true;\n                        move_targets.insert({gate_inside.x, gate_inside.y});\n                        continue;\n                    } else if (dist[gate.x][gate.y] != -1) {\n                        if (dist[gate.x][gate.y] == 0) {\n                            // At gate? Already handled above.\n                            action[i] = '.';\n                            acted[i] = true;\n                            continue;\n                        } else {\n                            move_target = gate;\n                        }\n                    }\n                }\n            } else {\n                // Inside, pre-walls done. Just wait (gate will be closed by someone else or wait for all)\n                action[i] = '.';\n                acted[i] = true;\n                continue;\n            }\n\n            if (!acted[i] && move_target.x != -1 && dist[move_target.x][move_target.y] > 0) {\n                int cx = move_target.x, cy = move_target.y;\n                while (par[cx][cy] != make_pair(hx, hy)) {\n                    auto p = par[cx][cy];\n                    cx = p.first;\n                    cy = p.second;\n                }\n                action[i] = move_action(hx, hy, cx, cy);\n                acted[i] = true;\n                move_targets.insert({cx, cy});\n            } else if (!acted[i]) {\n                action[i] = '.';\n                acted[i] = true;\n            }\n        }\n\n        cout << action << endl;\n\n        // Apply human actions\n        for (int i = 0; i < M; ++i) {\n            char c = action[i];\n            int hx = human_pos[i].x, hy = human_pos[i].y;\n            if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                int wx = hx, wy = hy;\n                if (c == 'u') wx--;\n                else if (c == 'd') wx++;\n                else if (c == 'l') wy--;\n                else if (c == 'r') wy++;\n                if (in_bounds(wx, wy)) passable[wx][wy] = false;\n            } else if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                int nx = hx, ny = hy;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    human_pos[i] = {nx, ny};\n                }\n            }\n        }\n\n        // Read pet movements\n        for (int i = 0; i < N; ++i) {\n            string s;\n            cin >> s;\n            for (char c : s) {\n                int nx = pet_pos[i].x, ny = pet_pos[i].y;\n                if (c == 'U') nx--;\n                else if (c == 'D') nx++;\n                else if (c == 'L') ny--;\n                else if (c == 'R') ny++;\n                if (in_bounds(nx, ny) && passable[nx][ny]) {\n                    pet_pos[i] = {nx, ny};\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int H = 20;\nconst int W = 20;\nconst int N = H * W;\nconst int L = 200;\n\nint start_id, goal_id;\ndouble P, ONE_MINUS_P;\nint nxt_id[N][4];               // 0:U 1:D 2:L 3:R\nint dist_to_goal[N];\nchar DIRCHAR[4] = {'U', 'D', 'L', 'R'};\nint CMDMAP[256];\n\n// RNG\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nuniform_real_distribution<double> uniform01(0.0, 1.0);\n\n// ------------------------------------------------------------\n// full evaluation (standalone)\ndouble full_evaluate(const string& s) {\n    array<double, N> dp{}, ndp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    double score = 0.0;\n    for (int t = 0; t < (int)s.size(); ++t) {\n        int c = CMDMAP[(unsigned char)s[t]];\n        ndp.fill(0.0);\n        double imm = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            double stay = x * P;\n            double move = x * ONE_MINUS_P;\n            ndp[v] += stay;\n            int to = nxt_id[v][c];\n            if (to == goal_id) {\n                imm += move * (401 - (t + 1));\n            } else {\n                ndp[to] += move;\n            }\n        }\n        score += imm;\n        dp.swap(ndp);\n    }\n    return score;\n}\n\n// ------------------------------------------------------------\n// BFS shortest path\nvector<char> bfs_shortest_path() {\n    queue<int> q;\n    vector<int> dist(N, -1), par(N, -1), pc(N, -1);\n    dist[start_id] = 0;\n    q.push(start_id);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == goal_id) break;\n        for (int d = 0; d < 4; ++d) {\n            int u = nxt_id[v][d];\n            if (u != v && dist[u] == -1) {\n                dist[u] = dist[v] + 1;\n                par[u] = v;\n                pc[u] = d;\n                q.push(u);\n            }\n        }\n    }\n    if (dist[goal_id] == -1) return {};\n    vector<char> path;\n    int cur = goal_id;\n    while (cur != start_id) {\n        path.push_back(DIRCHAR[pc[cur]]);\n        cur = par[cur];\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// monotone D/R path\nvector<char> monotone_path(const vector<string>& hwall,\n                           const vector<string>& vwall,\n                           int si, int sj, int ti, int tj) {\n    vector<vector<bool>> reach(H, vector<bool>(W, false));\n    vector<vector<char>> from(H, vector<char>(W, 0));\n    reach[si][sj] = true;\n    for (int i = si; i <= ti; ++i) {\n        for (int j = sj; j <= tj; ++j) {\n            if (!reach[i][j]) continue;\n            if (i < ti && vwall[i][j] == '0' && !reach[i + 1][j]) {\n                reach[i + 1][j] = true;\n                from[i + 1][j] = 'D';\n            }\n            if (j < tj && hwall[i][j] == '0' && !reach[i][j + 1]) {\n                reach[i][j + 1] = true;\n                from[i][j + 1] = 'R';\n            }\n        }\n    }\n    if (!reach[ti][tj]) return {};\n    vector<char> path;\n    int i = ti, j = tj;\n    while (i != si || j != sj) {\n        char c = from[i][j];\n        path.push_back(c);\n        if (c == 'D') --i;\n        else --j;\n    }\n    reverse(path.begin(), path.end());\n    return path;\n}\n\n// greedy open-loop (distance-based)\nstring greedy_path() {\n    array<double, N> dp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    string s;\n    s.reserve(L);\n    for (int t = 0; t < L; ++t) {\n        int best_c = 3;\n        double best_cost = 1e100;\n        for (int c = 0; c < 4; ++c) {\n            double cost = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = dp[v];\n                if (x == 0.0) continue;\n                int to = nxt_id[v][c];\n                double d = (to == goal_id) ? 0.0 : (double)dist_to_goal[to];\n                cost += x * (P * (double)dist_to_goal[v] + ONE_MINUS_P * d);\n            }\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_c = c;\n            }\n        }\n        s.push_back(DIRCHAR[best_c]);\n        array<double, N> ndp{};\n        ndp.fill(0.0);\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            ndp[v] += x * P;\n            int to = nxt_id[v][best_c];\n            if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n        }\n        dp.swap(ndp);\n    }\n    return s;\n}\n\n// greedy path guided by closed-loop bound V\nstring v_greedy_path(const vector<array<double, N>>& V) {\n    array<double, N> dp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    string s;\n    s.reserve(L);\n    for (int t = 0; t < L; ++t) {\n        int best_c = 0;\n        double best_val = -1e100;\n        for (int c = 0; c < 4; ++c) {\n            double val = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = dp[v];\n                if (x == 0.0) continue;\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += x * (401.0 - (t + 1));\n                else val += x * V[t + 1][to];\n            }\n            if (val > best_val) {\n                best_val = val;\n                best_c = c;\n            }\n        }\n        s.push_back(DIRCHAR[best_c]);\n        array<double, N> ndp{};\n        ndp.fill(0.0);\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            ndp[v] += x * P;\n            int to = nxt_id[v][best_c];\n            if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n        }\n        dp.swap(ndp);\n    }\n    return s;\n}\n\n// noisy closed-loop greedy: with probability eps pick 2nd best action\nstring noisy_v_greedy_path(const vector<array<double, N>>& V, double eps) {\n    array<double, N> dp{};\n    dp.fill(0.0);\n    dp[start_id] = 1.0;\n    string s;\n    s.reserve(L);\n    for (int t = 0; t < L; ++t) {\n        int best_c = 0, second_c = 0;\n        double best_val = -1e100, second_val = -1e100;\n        for (int c = 0; c < 4; ++c) {\n            double val = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = dp[v];\n                if (x == 0.0) continue;\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += x * (401.0 - (t + 1));\n                else val += x * V[t + 1][to];\n            }\n            if (val > best_val) {\n                second_val = best_val;\n                second_c = best_c;\n                best_val = val;\n                best_c = c;\n            } else if (val > second_val) {\n                second_val = val;\n                second_c = c;\n            }\n        }\n        int chosen = best_c;\n        if (uniform01(rng) < eps && second_val > -1e90) chosen = second_c;\n        s.push_back(DIRCHAR[chosen]);\n        array<double, N> ndp{};\n        ndp.fill(0.0);\n        for (int v = 0; v < N; ++v) {\n            double x = dp[v];\n            if (x == 0.0) continue;\n            ndp[v] += x * P;\n            int to = nxt_id[v][chosen];\n            if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n        }\n        dp.swap(ndp);\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Local search structure\nstruct Solver {\n    string cur;\n    double cur_score;\n    vector<array<double, N>> fw;\n    vector<array<double, N>> b;\n    vector<double> pref;\n\n    void init(const string& s) {\n        cur = s;\n        fw.assign(L + 1, {});\n        b.assign(L + 1, {});\n        pref.assign(L + 1, 0.0);\n        fw[0].fill(0.0);\n        fw[0][start_id] = 1.0;\n        for (int t = 0; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        b[L].fill(0.0);\n        for (int t = L - 1; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n\n    // O(N) evaluation of changing position pos to command cmd (0..3)\n    double try_mutate(int pos, int cmd) const {\n        double reward = (401 - (pos + 1)) * ONE_MINUS_P;\n        double dot = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double val = P * b[pos + 1][v];\n            int to = nxt_id[v][cmd];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * b[pos + 1][to];\n            dot += fw[pos][v] * val;\n        }\n        return pref[pos] + dot;\n    }\n\n    // apply single mutation and incrementally update tables\n    void apply_mutate(int pos, int cmd) {\n        cur[pos] = DIRCHAR[cmd];\n        for (int t = pos; t < L; ++t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            fw[t + 1].fill(0.0);\n            double imm = 0.0;\n            for (int v = 0; v < N; ++v) {\n                double x = fw[t][v];\n                double stay = x * P;\n                double move = x * ONE_MINUS_P;\n                fw[t + 1][v] += stay;\n                int to = nxt_id[v][c];\n                if (to == goal_id) {\n                    imm += move * (401 - (t + 1));\n                } else {\n                    fw[t + 1][to] += move;\n                }\n            }\n            pref[t + 1] = pref[t] + imm;\n        }\n        for (int t = pos; t >= 0; --t) {\n            int c = CMDMAP[(unsigned char)cur[t]];\n            double reward = (401 - (t + 1)) * ONE_MINUS_P;\n            for (int v = 0; v < N; ++v) {\n                double val = P * b[t + 1][v];\n                int to = nxt_id[v][c];\n                if (to == goal_id) val += reward;\n                else val += ONE_MINUS_P * b[t + 1][to];\n                b[t][v] = val;\n            }\n        }\n        cur_score = pref[L];\n    }\n};\n\n// ------------------------------------------------------------\n// Window evaluation (exact brute force over 4^W strings)\ntemplate<std::size_t W>\ndouble try_window(const Solver& sol, int pos, const array<int, W>& cmd) {\n    double buf0[N];\n    double buf1[N];\n    double *cur = buf0;\n    double *nxt = buf1;\n    memcpy(cur, sol.b[pos + (int)W].data(), sizeof(double) * N);\n    for (int k = (int)W - 1; k >= 0; --k) {\n        int c = cmd[k];\n        double reward = (401 - (pos + k + 1)) * ONE_MINUS_P;\n        for (int v = 0; v < N; ++v) {\n            double val = P * cur[v];\n            int to = nxt_id[v][c];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * cur[to];\n            nxt[v] = val;\n        }\n        swap(cur, nxt);\n    }\n    double dot = 0.0;\n    for (int v = 0; v < N; ++v) dot += sol.fw[pos][v] * cur[v];\n    return sol.pref[pos] + dot;\n}\n\ntemplate<std::size_t W>\nvoid apply_window(Solver& sol, int pos, const array<int, W>& cmd) {\n    for (int k = 0; k < (int)W; ++k) sol.cur[pos + k] = DIRCHAR[cmd[k]];\n    for (int t = pos; t < L; ++t) {\n        int c = CMDMAP[(unsigned char)sol.cur[t]];\n        sol.fw[t + 1].fill(0.0);\n        double imm = 0.0;\n        for (int v = 0; v < N; ++v) {\n            double x = sol.fw[t][v];\n            double stay = x * P;\n            double move = x * ONE_MINUS_P;\n            sol.fw[t + 1][v] += stay;\n            int to = nxt_id[v][c];\n            if (to == goal_id) {\n                imm += move * (401 - (t + 1));\n            } else {\n                sol.fw[t + 1][to] += move;\n            }\n        }\n        sol.pref[t + 1] = sol.pref[t] + imm;\n    }\n    for (int t = pos + (int)W - 1; t >= 0; --t) {\n        int c = CMDMAP[(unsigned char)sol.cur[t]];\n        double reward = (401 - (t + 1)) * ONE_MINUS_P;\n        for (int v = 0; v < N; ++v) {\n            double val = P * sol.b[t + 1][v];\n            int to = nxt_id[v][c];\n            if (to == goal_id) val += reward;\n            else val += ONE_MINUS_P * sol.b[t + 1][to];\n            sol.b[t][v] = val;\n        }\n    }\n    sol.cur_score = sol.pref[L];\n}\n\n// ------------------------------------------------------------\n// Hill climbing\nvoid hill_climb(Solver& sol, const function<double()>& elapsed, double time_limit) {\n    bool improved = true;\n    while (improved) {\n        if (elapsed() > time_limit) break;\n        improved = false;\n        for (int i = 0; i < L; ++i) {\n            int cur_cmd = CMDMAP[(unsigned char)sol.cur[i]];\n            int best_cmd = cur_cmd;\n            double best_sc = sol.cur_score;\n            for (int d = 0; d < 3; ++d) {\n                int nc = (cur_cmd + 1 + d) & 3;\n                double sc = sol.try_mutate(i, nc);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    best_cmd = nc;\n                }\n            }\n            if (best_cmd != cur_cmd) {\n                sol.apply_mutate(i, best_cmd);\n                improved = true;\n            }\n        }\n    }\n}\n\n// Generic window-size exact optimisation\ntemplate<std::size_t W>\nvoid optimize_window_size(Solver& sol, const function<double()>& elapsed,\n                          double time_limit, int max_passes, bool reverse) {\n    const int limit = L - (int)W + 1;\n    const int total = 1 << (2 * (int)W); // 4^W\n    for (int pass = 0; pass < max_passes; ++pass) {\n        if (elapsed() > time_limit) break;\n        bool improved = false;\n        if (!reverse) {\n            for (int i = 0; i < limit; ++i) {\n                if (elapsed() > time_limit) break;\n                int cur_cmd[W];\n                for (int k = 0; k < (int)W; ++k) cur_cmd[k] = CMDMAP[(unsigned char)sol.cur[i + k]];\n                int best_cmd[W];\n                memcpy(best_cmd, cur_cmd, sizeof(cur_cmd));\n                double best_sc = sol.cur_score;\n                for (int mask = 0; mask < total; ++mask) {\n                    array<int, W> cmd;\n                    int t = mask;\n                    for (int k = (int)W - 1; k >= 0; --k) {\n                        cmd[k] = t & 3;\n                        t >>= 2;\n                    }\n                    double sc = try_window(sol, i, cmd);\n                    if (sc > best_sc) {\n                        best_sc = sc;\n                        for (int k = 0; k < (int)W; ++k) best_cmd[k] = cmd[k];\n                    }\n                }\n                if (memcmp(best_cmd, cur_cmd, sizeof(cur_cmd)) != 0) {\n                    array<int, W> cmd;\n                    for (int k = 0; k < (int)W; ++k) cmd[k] = best_cmd[k];\n                    apply_window(sol, i, cmd);\n                    improved = true;\n                }\n            }\n        } else {\n            for (int i = limit - 1; i >= 0; --i) {\n                if (elapsed() > time_limit) break;\n                int cur_cmd[W];\n                for (int k = 0; k < (int)W; ++k) cur_cmd[k] = CMDMAP[(unsigned char)sol.cur[i + k]];\n                int best_cmd[W];\n                memcpy(best_cmd, cur_cmd, sizeof(cur_cmd));\n                double best_sc = sol.cur_score;\n                for (int mask = 0; mask < total; ++mask) {\n                    array<int, W> cmd;\n                    int t = mask;\n                    for (int k = (int)W - 1; k >= 0; --k) {\n                        cmd[k] = t & 3;\n                        t >>= 2;\n                    }\n                    double sc = try_window(sol, i, cmd);\n                    if (sc > best_sc) {\n                        best_sc = sc;\n                        for (int k = 0; k < (int)W; ++k) best_cmd[k] = cmd[k];\n                    }\n                }\n                if (memcmp(best_cmd, cur_cmd, sizeof(cur_cmd)) != 0) {\n                    array<int, W> cmd;\n                    for (int k = 0; k < (int)W; ++k) cmd[k] = best_cmd[k];\n                    apply_window(sol, i, cmd);\n                    improved = true;\n                }\n            }\n        }\n        if (!improved) break;\n    }\n}\n\nvoid optimize_windows(Solver& sol, const function<double()>& elapsed, double time_limit) {\n    optimize_window_size<3>(sol, elapsed, time_limit, 5, false);\n    optimize_window_size<3>(sol, elapsed, time_limit, 2, true);\n    optimize_window_size<4>(sol, elapsed, time_limit, 2, false);\n    optimize_window_size<4>(sol, elapsed, time_limit, 1, true);\n}\n\n// ------------------------------------------------------------\nstring perturb(const string& s, int k) {\n    string r = s;\n    for (int i = 0; i < k; ++i) {\n        int pos = rng() % L;\n        r[pos] = DIRCHAR[rng() % 4];\n    }\n    return r;\n}\n\n// Fast SA: only applies strictly improving moves (cheap)\nvoid run_fast_sa(Solver& sol, int max_iter, double time_limit,\n                 const function<double()>& elapsed) {\n    for (int iter = 0; iter < max_iter; ++iter) {\n        if ((iter & 1023) == 0 && elapsed() > time_limit) break;\n        int pos = rng() % L;\n        int cur_cmd = CMDMAP[(unsigned char)sol.cur[pos]];\n        int best_cmd = cur_cmd;\n        double best_sc = sol.cur_score;\n        for (int d = 0; d < 3; ++d) {\n            int nc = (cur_cmd + 1 + d) & 3;\n            double sc = sol.try_mutate(pos, nc);\n            if (sc > best_sc) {\n                best_sc = sc;\n                best_cmd = nc;\n            }\n        }\n        if (best_cmd != cur_cmd) {\n            sol.apply_mutate(pos, best_cmd);\n        }\n    }\n}\n\n// Sparse SA: many evaluations, few expensive applications.\n// Accepts all improving moves.  When stuck, tries a random neighbour and\n// accepts it with Metropolis probability until worsening budget exhausted.\nvoid run_sparse_sa(Solver& sol, int max_iter, int max_worsening, double time_limit,\n                   const function<double()>& elapsed, double T0) {\n    const double T_end = 1e-4;\n    int worsening_applied = 0;\n    for (int iter = 0; iter < max_iter; ++iter) {\n        if ((iter & 2047) == 0 && elapsed() > time_limit) break;\n        double T = T0 * pow(T_end / T0, (double)iter / max_iter);\n        int pos = rng() % L;\n        int cur_cmd = CMDMAP[(unsigned char)sol.cur[pos]];\n        int best_cmd = cur_cmd;\n        double best_sc = sol.cur_score;\n        for (int d = 0; d < 3; ++d) {\n            int nc = (cur_cmd + 1 + d) & 3;\n            double sc = sol.try_mutate(pos, nc);\n            if (sc > best_sc) {\n                best_sc = sc;\n                best_cmd = nc;\n            }\n        }\n\n        int chosen_cmd = best_cmd;\n        double chosen_sc = best_sc;\n\n        // If no improving move exists, propose a random escape\n        if (best_cmd == cur_cmd) {\n            int rd = rng() % 3;\n            chosen_cmd = (cur_cmd + 1 + rd) & 3;\n            chosen_sc = sol.try_mutate(pos, chosen_cmd);\n        }\n\n        if (chosen_sc >= sol.cur_score) {\n            sol.apply_mutate(pos, chosen_cmd);\n        } else if (worsening_applied < max_worsening && T > 1e-12) {\n            if (uniform01(rng) < exp((chosen_sc - sol.cur_score) / T)) {\n                sol.apply_mutate(pos, chosen_cmd);\n                ++worsening_applied;\n            }\n        }\n    }\n}\n\n// ------------------------------------------------------------\n// Beam search with closed-loop upper bound\nstring beam_search(const vector<array<double, N>>& V) {\n    const int MAX_B = 1000;\n\n    struct Cand {\n        double pref;\n        double ub;\n        int par_id;\n        char c;\n    };\n\n    vector<double> node_pref;\n    vector<int> parent;\n    vector<char> pcmd;\n    vector<int> layer_start;\n\n    node_pref.reserve((L + 1) * MAX_B);\n    parent.reserve((L + 1) * MAX_B);\n    pcmd.reserve((L + 1) * MAX_B);\n\n    node_pref.push_back(0.0);\n    parent.push_back(-1);\n    pcmd.push_back(0);\n    layer_start.push_back(0);\n    layer_start.push_back(1);\n\n    vector<int> cur_id(1, 0);\n    vector<array<double, N>> cur_fw(1);\n    cur_fw[0].fill(0.0);\n    cur_fw[0][start_id] = 1.0;\n\n    for (int t = 0; t < L; ++t) {\n        int cur_sz = (int)cur_id.size();\n        const double* vt = V[t + 1].data();\n        double reward = 401.0 - (t + 1);\n\n        vector<Cand> cands;\n        cands.reserve(cur_sz * 4);\n\n        for (int idx = 0; idx < cur_sz; ++idx) {\n            int gid = cur_id[idx];\n            const array<double, N>& fw = cur_fw[idx];\n            double sum_base = 0.0;\n            for (int v = 0; v < N; ++v) sum_base += fw[v] * vt[v];\n            for (int cmd = 0; cmd < 4; ++cmd) {\n                double dot_move = 0.0;\n                double goal_mass = 0.0;\n                for (int v = 0; v < N; ++v) {\n                    int to = nxt_id[v][cmd];\n                    if (to == goal_id) goal_mass += fw[v];\n                    else dot_move += fw[v] * vt[to];\n                }\n                double pref_new = node_pref[gid] + goal_mass * ONE_MINUS_P * reward;\n                double ub = pref_new + P * sum_base + ONE_MINUS_P * dot_move;\n                cands.push_back({pref_new, ub, gid, DIRCHAR[cmd]});\n            }\n        }\n\n        int keep = min((int)cands.size(), MAX_B);\n        nth_element(cands.begin(), cands.begin() + keep, cands.end(),\n                    [](const Cand& a, const Cand& b) { return a.ub > b.ub; });\n\n        vector<int> next_id;\n        next_id.reserve(keep);\n        vector<array<double, N>> next_fw;\n        next_fw.reserve(keep);\n\n        for (int i = 0; i < keep; ++i) {\n            const Cand& lc = cands[i];\n            int new_id = (int)node_pref.size();\n            node_pref.push_back(lc.pref);\n            parent.push_back(lc.par_id);\n            pcmd.push_back(lc.c);\n            next_id.push_back(new_id);\n\n            int par_idx = lc.par_id - layer_start[t];\n            const array<double, N>& pfw = cur_fw[par_idx];\n            array<double, N> ndp;\n            ndp.fill(0.0);\n            int cmd = CMDMAP[(unsigned char)lc.c];\n            for (int v = 0; v < N; ++v) {\n                double x = pfw[v];\n                ndp[v] += x * P;\n                int to = nxt_id[v][cmd];\n                if (to != goal_id) ndp[to] += x * ONE_MINUS_P;\n            }\n            next_fw.push_back(ndp);\n        }\n\n        cur_id.swap(next_id);\n        cur_fw.swap(next_fw);\n        layer_start.push_back((int)node_pref.size());\n    }\n\n    double best_score = -1.0;\n    int best_leaf = -1;\n    for (int gid : cur_id) {\n        if (node_pref[gid] > best_score) {\n            best_score = node_pref[gid];\n            best_leaf = gid;\n        }\n    }\n    if (best_leaf == -1) return string(L, 'D');\n\n    string beam_str(L, '?');\n    int cur = best_leaf;\n    for (int t = L - 1; t >= 0; --t) {\n        beam_str[t] = pcmd[cur];\n        cur = parent[cur];\n    }\n    return beam_str;\n}\n\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    CMDMAP['U'] = 0; CMDMAP['D'] = 1; CMDMAP['L'] = 2; CMDMAP['R'] = 3;\n\n    int si, sj, ti, tj;\n    double p_input;\n    if (!(cin >> si >> sj >> ti >> tj >> p_input)) return 0;\n    P = p_input;\n    ONE_MINUS_P = 1.0 - P;\n\n    vector<string> hwall(H);\n    for (int i = 0; i < H; ++i) cin >> hwall[i];\n    vector<string> vwall(H - 1);\n    for (int i = 0; i < H - 1; ++i) cin >> vwall[i];\n\n    start_id = si * W + sj;\n    goal_id  = ti * W + tj;\n\n    for (int i = 0; i < H; ++i) {\n        for (int j = 0; j < W; ++j) {\n            int v = i * W + j;\n            if (i > 0 && vwall[i - 1][j] == '0') nxt_id[v][0] = (i - 1) * W + j;\n            else nxt_id[v][0] = v;\n            if (i + 1 < H && vwall[i][j] == '0') nxt_id[v][1] = (i + 1) * W + j;\n            else nxt_id[v][1] = v;\n            if (j > 0 && hwall[i][j - 1] == '0') nxt_id[v][2] = i * W + (j - 1);\n            else nxt_id[v][2] = v;\n            if (j + 1 < W && hwall[i][j] == '0') nxt_id[v][3] = i * W + (j + 1);\n            else nxt_id[v][3] = v;\n        }\n    }\n\n    // distances to goal\n    {\n        queue<int> q;\n        vector<int> dist(N, -1);\n        dist[goal_id] = 0;\n        q.push(goal_id);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            for (int d = 0; d < 4; ++d) {\n                int u = nxt_id[v][d];\n                if (u != v && dist[u] == -1) {\n                    dist[u] = dist[v] + 1;\n                    q.push(u);\n                }\n            }\n        }\n        for (int i = 0; i < N; ++i) dist_to_goal[i] = dist[i];\n    }\n\n    // closed-loop upper bound V[t][v]\n    vector<array<double, N>> V(L + 1);\n    for (int v = 0; v < N; ++v) V[L][v] = 0.0;\n    for (int t = L - 1; t >= 0; --t) {\n        double reward = 401.0 - (t + 1);\n        for (int v = 0; v < N; ++v) {\n            if (v == goal_id) {\n                V[t][v] = 0.0;\n                continue;\n            }\n            double best = 0.0;\n            for (int c = 0; c < 4; ++c) {\n                int to = nxt_id[v][c];\n                double val = P * V[t + 1][v];\n                if (to == goal_id) val += ONE_MINUS_P * reward;\n                else val += ONE_MINUS_P * V[t + 1][to];\n                if (val > best) best = val;\n            }\n            V[t][v] = best;\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    // ---------- adaptive stretch factors ----------\n    vector<int> stretch_factors;\n    if (P < 0.20) stretch_factors = {2, 3};\n    else if (P < 0.35) stretch_factors = {3, 5, 8};\n    else stretch_factors = {5, 8, 12, 15, 20};\n\n    // ---------- generate candidates ----------\n    vector<string> candidates;\n    auto make_repeat = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        string s;\n        while ((int)s.size() < L) s += string(path.begin(), path.end());\n        s.resize(L);\n        return s;\n    };\n    auto make_stretch = [&](const vector<char>& path) {\n        if (path.empty()) return string();\n        int rep = max(1, L / (int)path.size());\n        string s;\n        for (char c : path) s += string(rep, c);\n        while ((int)s.size() < L) s.push_back(path[s.size() % path.size()]);\n        s.resize(L);\n        return s;\n    };\n    auto make_stretch_rep = [&](const vector<char>& path, int rep) {\n        if (path.empty()) return string();\n        string s;\n        for (char c : path) {\n            s += string(rep, c);\n            if ((int)s.size() >= L) break;\n        }\n        int psz = (int)path.size();\n        int idx = 0;\n        while ((int)s.size() < L) {\n            s.push_back(path[idx % psz]);\n            ++idx;\n        }\n        s.resize(L);\n        return s;\n    };\n\n    vector<char> sp = bfs_shortest_path();\n    if (!sp.empty()) {\n        candidates.push_back(make_repeat(sp));\n        candidates.push_back(make_stretch(sp));\n        for (int r : stretch_factors) {\n            candidates.push_back(make_stretch_rep(sp, r));\n        }\n    }\n    vector<char> mono = monotone_path(hwall, vwall, si, sj, ti, tj);\n    if (!mono.empty()) {\n        candidates.push_back(make_repeat(mono));\n        candidates.push_back(make_stretch(mono));\n        for (int r : stretch_factors) {\n            candidates.push_back(make_stretch_rep(mono, r));\n        }\n    }\n    candidates.push_back(greedy_path());\n    candidates.push_back(v_greedy_path(V));\n    for (int k = 0; k < 5; ++k) {\n        candidates.push_back(noisy_v_greedy_path(V, 0.10));\n    }\n\n    {\n        string s(L, 'D');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needD); ++i) s[i] = 'D';\n        for (; i < min(L, needD + needR); ++i) s[i] = 'R';\n        candidates.push_back(s);\n    }\n    {\n        string s(L, 'R');\n        int needR = max(0, tj - sj);\n        int needD = max(0, ti - si);\n        int i = 0;\n        for (; i < min(L, needR); ++i) s[i] = 'R';\n        for (; i < min(L, needR + needD); ++i) s[i] = 'D';\n        candidates.push_back(s);\n    }\n    for (int k = 0; k < 15; ++k) {\n        string s;\n        for (int i = 0; i < L; ++i) {\n            int r = rng() % 100;\n            if (r < 45) s += 'D';\n            else if (r < 90) s += 'R';\n            else if (r < 95) s += 'L';\n            else s += 'U';\n        }\n        candidates.push_back(s);\n    }\n\n    candidates.push_back(beam_search(V));\n\n    // evaluate all candidates\n    string best_str(L, 'R');\n    double best_score = -1.0;\n    for (auto& s : candidates) {\n        if ((int)s.size() != L) continue;\n        double sc = full_evaluate(s);\n        if (sc > best_score) {\n            best_score = sc;\n            best_str = s;\n        }\n    }\n\n    // ---------- local search ----------\n    Solver solver;\n    solver.init(best_str);\n\n    hill_climb(solver, elapsed, 0.5);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    optimize_windows(solver, elapsed, 1.0);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    hill_climb(solver, elapsed, 1.1);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    // calibrate SA temperature (80th percentile of random worsening moves)\n    vector<double> diffs;\n    for (int k = 0; k < 1000; ++k) {\n        int pos = rng() % L;\n        int cur_cmd = CMDMAP[(unsigned char)solver.cur[pos]];\n        int nd = (cur_cmd + 1 + (rng() % 3)) & 3;\n        double sc = solver.try_mutate(pos, nd);\n        if (sc < solver.cur_score) diffs.push_back(solver.cur_score - sc);\n    }\n    sort(diffs.begin(), diffs.end());\n    double T0 = 1.0;\n    if (!diffs.empty()) {\n        T0 = diffs[min((int)diffs.size() - 1, (int)(diffs.size() * 8 / 10))];\n        if (T0 < 1.0) T0 = 1.0;\n    }\n\n    // Phase 1: sparse SA with exploration\n    run_sparse_sa(solver, 300000, 100, 1.55, elapsed, T0);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    hill_climb(solver, elapsed, 1.65);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    // Phase 2: smaller sparse SA\n    run_sparse_sa(solver, 150000, 50, 1.78, elapsed, T0);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    hill_climb(solver, elapsed, 1.83);\n    if (solver.cur_score > best_score) {\n        best_score = solver.cur_score;\n        best_str = solver.cur;\n    }\n\n    // ---------- adaptive restarts ----------\n    for (int rep = 0; rep < 10; ++rep) {\n        if (elapsed() > 1.93) break;\n        string p = perturb(best_str, 5 + rep);\n        Solver rs;\n        rs.init(p);\n        hill_climb(rs, elapsed, 1.94);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n            solver.init(best_str);\n        }\n        if (elapsed() > 1.94) break;\n\n        run_sparse_sa(rs, 25000, 20, 1.97, elapsed, T0);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n            solver.init(best_str);\n        }\n        if (elapsed() > 1.97) break;\n\n        hill_climb(rs, elapsed, 1.98);\n        if (rs.cur_score > best_score) {\n            best_score = rs.cur_score;\n            best_str = rs.cur;\n            solver.init(best_str);\n        }\n    }\n\n    cout << best_str << \"\\n\";\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static const int N = 30;\n    static const int V = N * N;          // 900\n    static const int S = V * 4;          // 3600\n\n    struct Vec4 {\n        int v[4];\n        int sz;\n        void clear() { sz = 0; }\n        void push(int x) { v[sz++] = x; }\n        int sum() const {\n            int s = 0;\n            for (int i = 0; i < sz; ++i) s += v[i];\n            return s;\n        }\n    };\n\n    int base[V];\n    unsigned char rot[V];\n    unsigned char best_rot[V];\n\n    // precomputed successor: cell idx, rotation r, entry dir d\n    int16_t pre_nxt[V][4][4];\n\n    int8_t to_tbl[8][4];\n    int ft[8][4];\n    const int di[4] = {0, -1, 0, 1};\n    const int dj[4] = {-1, 0, 1, 0};\n\n    // current graph\n    int16_t nxt[S];\n\n    // cycle statistics\n    int cnt[3601];\n    int total_len;\n    set<int> active_lens;\n    int best1, best2;\n    int best_score;\n\n    // visited arrays for cycle detection\n    int state_vis[S];\n    int cycle_vis[S];\n    int vis_token;\n    int cycle_token;\n\n    // random\n    uint64_t rng;\n    uint64_t rand64() {\n        uint64_t z = (rng += 0x9e3779b97f4a7c15ULL);\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n    int rand_int(int m) { return (int)(rand64() % (uint64_t)m); }\n\n    // ------------------------------------------------------------\n    // count of length 'len' after removing oldv and adding newv\n    // ------------------------------------------------------------\n    inline int adj_cnt(int len, const Vec4& oldv, const Vec4& newv) const {\n        int c = cnt[len];\n        for (int i = 0; i < oldv.sz; ++i) if (oldv.v[i] == len) --c;\n        for (int i = 0; i < newv.sz; ++i) if (newv.v[i] == len) ++c;\n        return c;\n    }\n\n    int find_best1(const Vec4& oldv, const Vec4& newv) const {\n        int max_new = 0;\n        for (int i = 0; i < newv.sz; ++i) max_new = max(max_new, newv.v[i]);\n        for (auto it = active_lens.rbegin(); it != active_lens.rend(); ++it) {\n            int len = *it;\n            if (len < max_new) break;\n            if (adj_cnt(len, oldv, newv) > 0) return len;\n        }\n        return max_new;\n    }\n\n    int find_best2(int b1, const Vec4& oldv, const Vec4& newv) const {\n        if (b1 == 0) return 0;\n        if (adj_cnt(b1, oldv, newv) >= 2) return b1;\n        int b2 = 0;\n        for (int i = 0; i < newv.sz; ++i) {\n            int L = newv.v[i];\n            if (L != b1 && L > b2) b2 = L;\n        }\n        for (auto it = active_lens.rbegin(); it != active_lens.rend(); ++it) {\n            int len = *it;\n            if (len <= b2) break;\n            if (len == b1) continue;\n            if (adj_cnt(len, oldv, newv) > 0) {\n                b2 = len;\n                break;\n            }\n        }\n        return b2;\n    }\n\n    void update_globals(const Vec4& oldv, const Vec4& newv) {\n        for (int i = 0; i < oldv.sz; ++i) {\n            int L = oldv.v[i];\n            if (--cnt[L] == 0) active_lens.erase(L);\n            total_len -= L;\n        }\n        for (int i = 0; i < newv.sz; ++i) {\n            int L = newv.v[i];\n            if (cnt[L]++ == 0) active_lens.insert(L);\n            total_len += L;\n        }\n        if (active_lens.empty()) {\n            best1 = best2 = 0;\n        } else {\n            auto it = active_lens.rbegin();\n            best1 = *it;\n            if (cnt[best1] >= 2) best2 = best1;\n            else {\n                ++it;\n                best2 = (it == active_lens.rend()) ? 0 : *it;\n            }\n        }\n    }\n\n    inline int get_score() const { return best1 * best2; }\n    inline int64_t eval_val(int b1, int b2, int tot) const {\n        return (int64_t)b1 * b2 * 1000LL + tot;\n    }\n\n    // ------------------------------------------------------------\n    // find all cycles that contain at least one of st[0..3]\n    // each cycle is reported exactly once\n    // ------------------------------------------------------------\n    Vec4 find_cycles(const int st[4]) {\n        Vec4 res;\n        res.clear();\n        int my_cycle = ++cycle_token;\n\n        for (int k = 0; k < 4; ++k) {\n            int s = st[k];\n            if (nxt[s] == -1) continue;\n            if (cycle_vis[s] == my_cycle) continue;\n\n            int my_vis = ++vis_token;\n            int cur = s;\n            int len = 0;\n            while (cur != -1 && state_vis[cur] != my_vis) {\n                state_vis[cur] = my_vis;\n                cur = nxt[cur];\n                ++len;\n                if (len > S) break;\n            }\n            if (cur == s) {\n                res.push(len);\n                int c = s;\n                do {\n                    cycle_vis[c] = my_cycle;\n                    c = nxt[c];\n                } while (c != s);\n            }\n        }\n        return res;\n    }\n\n    // ------------------------------------------------------------\n    // full rebuild of graph and cycle statistics from rot[]\n    // ------------------------------------------------------------\n    void rebuild_from_rot() {\n        for (int s = 0; s < S; ++s) nxt[s] = -1;\n        for (int idx = 0; idx < V; ++idx) {\n            int s0 = idx * 4;\n            int r = rot[idx];\n            for (int d = 0; d < 4; ++d) nxt[s0 + d] = pre_nxt[idx][r][d];\n        }\n\n        memset(cnt, 0, sizeof(cnt));\n        total_len = 0;\n        active_lens.clear();\n\n        static uint8_t mark[S];\n        static int path_nodes[S];\n        memset(mark, 0, sizeof(mark));\n\n        for (int s = 0; s < S; ++s) {\n            if (nxt[s] == -1 || mark[s]) continue;\n            int cur = s;\n            int path_len = 0;\n            while (cur != -1 && mark[cur] == 0) {\n                mark[cur] = 1;\n                path_nodes[path_len++] = cur;\n                cur = nxt[cur];\n            }\n            if (cur != -1 && mark[cur] == 1) {\n                int cycle_len = 0;\n                for (int i = path_len - 1; i >= 0; --i) {\n                    ++cycle_len;\n                    if (path_nodes[i] == cur) break;\n                }\n                cnt[cycle_len]++;\n                total_len += cycle_len;\n                active_lens.insert(cycle_len);\n            }\n            for (int i = 0; i < path_len; ++i) mark[path_nodes[i]] = 2;\n        }\n\n        if (active_lens.empty()) {\n            best1 = best2 = 0;\n        } else {\n            auto it = active_lens.rbegin();\n            best1 = *it;\n            if (cnt[best1] >= 2) best2 = best1;\n            else {\n                ++it;\n                best2 = (it == active_lens.rend()) ? 0 : *it;\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    void solve() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n        for (int i = 0; i < N; ++i) {\n            string line;\n            cin >> line;\n            for (int j = 0; j < N; ++j) base[i * N + j] = line[j] - '0';\n        }\n\n        const int8_t to_arr[8][4] = {\n            {1,0,-1,-1}, {3,-1,-1,0}, {-1,-1,3,2}, {-1,2,1,-1},\n            {1,0,3,2},   {3,2,1,0},   {2,-1,0,-1}, {-1,3,-1,1}\n        };\n        memcpy(to_tbl, to_arr, sizeof(to_arr));\n        for (int b = 0; b < 8; ++b) {\n            for (int r = 0; r < 4; ++r) {\n                if (b < 4) ft[b][r] = (b + r) & 3;\n                else if (b < 6) ft[b][r] = 4 + ((b - 4 + r) & 1);\n                else ft[b][r] = 6 + ((b - 6 + r) & 1);\n            }\n        }\n\n        for (int idx = 0; idx < V; ++idx) {\n            int i = idx / N, j = idx % N;\n            for (int r = 0; r < 4; ++r) {\n                int t = ft[base[idx]][r];\n                for (int d = 0; d < 4; ++d) {\n                    int d2 = to_tbl[t][d];\n                    if (d2 == -1) {\n                        pre_nxt[idx][r][d] = -1;\n                    } else {\n                        int ni = i + di[d2];\n                        int nj = j + dj[d2];\n                        if (ni < 0 || ni >= N || nj < 0 || nj >= N)\n                            pre_nxt[idx][r][d] = -1;\n                        else\n                            pre_nxt[idx][r][d] = (int16_t)((ni * N + nj) * 4 + ((d2 + 2) & 3));\n                    }\n                }\n            }\n        }\n\n        rng = chrono::steady_clock::now().time_since_epoch().count();\n        vis_token = 0;\n        cycle_token = 0;\n\n        // ----- greedy init : avoid edges leaving the board ----------------\n        for (int idx = 0; idx < V; ++idx) {\n            int b = base[idx];\n            int best_r = 0, best_sc = -1;\n            if (b < 4) {\n                for (int r = 0; r < 4; ++r) {\n                    int sc = 0;\n                    for (int d = 0; d < 4; ++d) if (pre_nxt[idx][r][d] != -1) ++sc;\n                    if (sc > best_sc) { best_sc = sc; best_r = r; }\n                }\n            } else {\n                for (int r = 0; r < 2; ++r) {\n                    int sc = 0;\n                    for (int d = 0; d < 4; ++d) if (pre_nxt[idx][r][d] != -1) ++sc;\n                    if (sc > best_sc) { best_sc = sc; best_r = r; }\n                }\n            }\n            rot[idx] = (unsigned char)best_r;\n        }\n\n        rebuild_from_rot();\n        best_score = get_score();\n        memcpy(best_rot, rot, V);\n\n        const double TL = 1.9;\n        clock_t start = clock();\n        auto elapsed = [&]() { return double(clock() - start) / CLOCKS_PER_SEC; };\n\n        // ----- Simulated Annealing ------------------------------------\n        double T0 = 1e7;\n        double T1 = 1.0;\n        double logT0 = log(T0);\n        double logT1 = log(T1);\n\n        while (elapsed() < TL - 0.2) {\n            double p = elapsed() / (TL - 0.2);\n            double T = exp(logT0 + (logT1 - logT0) * p);\n\n            int idx = rand_int(V);\n            int s0 = idx * 4;\n            int st[4] = {s0, s0 + 1, s0 + 2, s0 + 3};\n\n            Vec4 oldv = find_cycles(st);\n            int sum_old = oldv.sum();\n\n            // detach\n            int orig_nxt[4];\n            for (int k = 0; k < 4; ++k) {\n                orig_nxt[k] = nxt[st[k]];\n                nxt[st[k]] = -1;\n            }\n\n            int cur_r = rot[idx];\n            int best_r = cur_r;\n            int64_t best_val = -(1LL << 60);\n            Vec4 best_newv;\n            best_newv.clear();\n\n            int alts[3], nalt = 0;\n            if (base[idx] < 4) {\n                for (int d = 1; d < 4; ++d) alts[nalt++] = (cur_r + d) & 3;\n            } else {\n                alts[nalt++] = cur_r ^ 1;\n            }\n\n            for (int a = 0; a < nalt; ++a) {\n                int nr = alts[a];\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][nr][k];\n\n                Vec4 newv = find_cycles(st);\n                int sum_new = newv.sum();\n                int b1 = find_best1(oldv, newv);\n                int b2 = find_best2(b1, oldv, newv);\n                int alt_tot = total_len - sum_old + sum_new;\n                int64_t val = eval_val(b1, b2, alt_tot);\n\n                if (val > best_val) {\n                    best_val = val;\n                    best_r = nr;\n                    best_newv = newv;\n                }\n\n                // detach for next alternative\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = -1;\n            }\n\n            // restore original edges\n            for (int k = 0; k < 4; ++k) nxt[st[k]] = (int16_t)orig_nxt[k];\n\n            if (best_r != cur_r) {\n                int64_t cur_val = eval_val(best1, best2, total_len);\n                int64_t delta = best_val - cur_val;\n                bool accept = false;\n                if (delta > 0) {\n                    accept = true;\n                } else {\n                    double prob = exp((double)delta / T);\n                    double r = (rand64() >> 11) * (1.0 / (1ULL << 53));\n                    if (r < prob) accept = true;\n                }\n\n                if (accept) {\n                    update_globals(oldv, best_newv);\n                    rot[idx] = (unsigned char)best_r;\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][best_r][k];\n                    int sc = get_score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        memcpy(best_rot, rot, V);\n                    }\n                }\n            }\n        }\n\n        // ----- Hill climbing polish -----------------------------------\n        memcpy(rot, best_rot, V);\n        rebuild_from_rot();\n\n        bool improved = true;\n        while (improved && elapsed() < TL) {\n            improved = false;\n            vector<int> order(V);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), default_random_engine((unsigned)rand64()));\n\n            for (int idx : order) {\n                if (elapsed() >= TL) break;\n                int s0 = idx * 4;\n                int st[4] = {s0, s0 + 1, s0 + 2, s0 + 3};\n\n                Vec4 oldv = find_cycles(st);\n                int sum_old = oldv.sum();\n\n                int orig_nxt[4];\n                for (int k = 0; k < 4; ++k) {\n                    orig_nxt[k] = nxt[st[k]];\n                    nxt[st[k]] = -1;\n                }\n\n                int cur_r = rot[idx];\n                int best_r = cur_r;\n                int64_t best_val = eval_val(best1, best2, total_len);\n                Vec4 best_newv;\n                best_newv.clear();\n\n                int alts[3], nalt = 0;\n                if (base[idx] < 4) {\n                    for (int d = 1; d < 4; ++d) alts[nalt++] = (cur_r + d) & 3;\n                } else {\n                    alts[nalt++] = cur_r ^ 1;\n                }\n\n                for (int a = 0; a < nalt; ++a) {\n                    int nr = alts[a];\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][nr][k];\n\n                    Vec4 newv = find_cycles(st);\n                    int sum_new = newv.sum();\n                    int b1 = find_best1(oldv, newv);\n                    int b2 = find_best2(b1, oldv, newv);\n                    int alt_tot = total_len - sum_old + sum_new;\n                    int64_t val = eval_val(b1, b2, alt_tot);\n\n                    if (val > best_val) {\n                        best_val = val;\n                        best_r = nr;\n                        best_newv = newv;\n                    }\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = -1;\n                }\n\n                for (int k = 0; k < 4; ++k) nxt[st[k]] = (int16_t)orig_nxt[k];\n\n                if (best_r != cur_r) {\n                    update_globals(oldv, best_newv);\n                    rot[idx] = (unsigned char)best_r;\n                    for (int k = 0; k < 4; ++k) nxt[st[k]] = pre_nxt[idx][best_r][k];\n                    int sc = get_score();\n                    if (sc > best_score) {\n                        best_score = sc;\n                        memcpy(best_rot, rot, V);\n                    }\n                    improved = true;\n                }\n            }\n        }\n\n        // ----- output -------------------------------------------------\n        string out;\n        out.reserve(V);\n        for (int i = 0; i < V; ++i) out.push_back(char('0' + best_rot[i]));\n        cout << out << '\\n';\n    }\n};\n\nint main() {\n    Solver s;\n    s.solve();\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T, SZ, TARGET;\n\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\nconst char dc[4] = {'U', 'D', 'L', 'R'};\nconst int opp[4] = {1, 0, 3, 2};\n\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\ninline bool inside(int i, int j) {\n    return i >= 0 && i < N && j >= 0 && j < N;\n}\n\nstruct State {\n    array<uint8_t, 100> b;\n    int epos;\n};\n\nstruct Eval {\n    int actual;     // largest true tree\n    int potential;  // V - max(0, E-(V-1)) of best component\n    int edges;      // total good edges\n};\n\n/* ------------------------------------------------------------------ */\n/*  One\u2011pass evaluation                                               */\n/* ------------------------------------------------------------------ */\ninline Eval evaluate(const array<uint8_t, 100>& b) {\n    int edges = 0;\n\n    for (int i = 0; i < N; ++i) {\n        int base = i * N;\n        for (int j = 0; j + 1 < N; ++j) {\n            int a = b[base + j];\n            int c = b[base + j + 1];\n            if (a && c && (a & 4) && (c & 1)) ++edges;\n        }\n    }\n    for (int i = 0; i + 1 < N; ++i) {\n        int base = i * N;\n        for (int j = 0; j < N; ++j) {\n            int a = b[base + j];\n            int c = b[base + j + N];\n            if (a && c && (a & 8) && (c & 2)) ++edges;\n        }\n    }\n\n    uint8_t vis[100] = {0};\n    int q[100];\n    int actual = 0;\n    int best_potential = 0;\n\n    for (int idx = 0; idx < SZ; ++idx) {\n        if (!b[idx] || vis[idx]) continue;\n        int qs = 0, qe = 0;\n        q[qe++] = idx;\n        vis[idx] = 1;\n        int vcnt = 0;\n        while (qs < qe) {\n            int u = q[qs++];\n            ++vcnt;\n            int ui = u / N;\n            int uj = u % N;\n            int t = b[u];\n            if (ui && !vis[u - N] && b[u - N] && (t & 2) && (b[u - N] & 8)) {\n                vis[u - N] = 1; q[qe++] = u - N;\n            }\n            if (ui + 1 < N && !vis[u + N] && b[u + N] && (t & 8) && (b[u + N] & 2)) {\n                vis[u + N] = 1; q[qe++] = u + N;\n            }\n            if (uj && !vis[u - 1] && b[u - 1] && (t & 1) && (b[u - 1] & 4)) {\n                vis[u - 1] = 1; q[qe++] = u - 1;\n            }\n            if (uj + 1 < N && !vis[u + 1] && b[u + 1] && (t & 4) && (b[u + 1] & 1)) {\n                vis[u + 1] = 1; q[qe++] = u + 1;\n            }\n        }\n        int ecnt = 0;\n        for (int k = 0; k < vcnt; ++k) {\n            int u = q[k];\n            int ui = u / N;\n            int uj = u % N;\n            int t = b[u];\n            if (uj + 1 < N && b[u + 1] && (t & 4) && (b[u + 1] & 1)) ++ecnt;\n            if (ui + 1 < N && b[u + N] && (t & 8) && (b[u + N] & 2)) ++ecnt;\n        }\n        if (ecnt == vcnt - 1 && vcnt > actual) actual = vcnt;\n        int excess = ecnt - (vcnt - 1);\n        if (excess < 0) excess = 0;\n        int potential = vcnt - excess;\n        if (potential > best_potential) best_potential = potential;\n    }\n    return {actual, best_potential, edges};\n}\n\n/* ------------------------------------------------------------------ */\ninline int combined(const Eval& e) {\n    return (e.potential << 11) + (e.actual << 4) + e.edges;\n}\n\n/* ------------------------------------------------------------------ */\nState apply_move(const State& s, int d) {\n    State ns = s;\n    int ei = s.epos / N;\n    int ej = s.epos % N;\n    int ni = ei + di[d];\n    int nj = ej + dj[d];\n    int npos = ni * N + nj;\n    ns.b[s.epos] = s.b[npos];\n    ns.b[npos] = 0;\n    ns.epos = npos;\n    return ns;\n}\n\ninline int char2dir(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    return 3;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Bounded DFS escape                                                */\n/*  hard limit on nodes; strong potential bound prune                 */\n/* ------------------------------------------------------------------ */\nconst int MAX_DFS_NODES = 80000;\nint g_dfs_nodes;\nint g_dfs_target_actual;\nint g_dfs_best_actual;\nchar g_dfs_path[20];\nint  g_dfs_path_len;\nint  g_dfs_max_depth;\n\nbool dfs_escape(const State& s, int depth, int last_dir) {\n    if (g_dfs_nodes >= MAX_DFS_NODES) return false;\n    if (depth == g_dfs_max_depth) return false;\n\n    int order[4] = {0, 1, 2, 3};\n    for (int i = 3; i > 0; --i) swap(order[i], order[(int)(rng() % (i + 1))]);\n\n    for (int k = 0; k < 4; ++k) {\n        int d = order[k];\n        if (last_dir != -1 && d == opp[last_dir]) continue;\n        int ei = s.epos / N;\n        int ej = s.epos % N;\n        if (!inside(ei + di[d], ej + dj[d])) continue;\n\n        State ns = apply_move(s, d);\n        Eval ev = evaluate(ns.b);\n        ++g_dfs_nodes;\n\n        if (ev.actual > g_dfs_best_actual) {\n            g_dfs_best_actual = ev.actual;\n            g_dfs_path[depth] = dc[d];\n            g_dfs_path_len = depth + 1;\n            if (g_dfs_best_actual > g_dfs_target_actual) return true;\n        }\n\n        int remaining = g_dfs_max_depth - depth - 1;\n        if (remaining >= 0 && ev.potential + remaining * 3 >= g_dfs_target_actual + 1) {\n            g_dfs_path[depth] = dc[d];\n            if (dfs_escape(ns, depth + 1, d)) return true;\n        }\n    }\n    return false;\n}\n\n/* ------------------------------------------------------------------ */\nstring try_escape(const State& s, const Eval& ev, int max_depth, int& best_actual) {\n    g_dfs_nodes = 0;\n    g_dfs_target_actual = ev.actual;\n    g_dfs_best_actual = ev.actual;\n    g_dfs_max_depth = max_depth;\n    g_dfs_path_len = 0;\n    if (dfs_escape(s, 0, -1)) {\n        best_actual = g_dfs_best_actual;\n        return string(g_dfs_path, g_dfs_path_len);\n    }\n    if (g_dfs_best_actual > ev.actual) {\n        best_actual = g_dfs_best_actual;\n        return string(g_dfs_path, g_dfs_path_len);\n    }\n    return \"\";\n}\n\n/* ------------------------------------------------------------------ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> T;\n    vector<string> grid(N);\n    for (int i = 0; i < N; ++i) cin >> grid[i];\n\n    SZ = N * N;\n    TARGET = SZ - 1;\n\n    State init{};\n    init.epos = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            char c = grid[i][j];\n            int v = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;\n            init.b[i * N + j] = static_cast<uint8_t>(v);\n            if (v == 0) init.epos = i * N + j;\n        }\n    }\n\n    Eval ev0 = evaluate(init.b);\n    int best_actual = ev0.actual;\n    if (best_actual == TARGET) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    State best_state = init;\n    string best_path;\n\n    State cur = init;\n    string cur_path;\n    Eval cur_ev = ev0;\n\n    auto start_tp = chrono::steady_clock::now();\n    const double TIME_LIMIT = 2.85;\n\n    auto time_left = [&]() {\n        return TIME_LIMIT - chrono::duration<double>(\n                               chrono::steady_clock::now() - start_tp).count();\n    };\n\n    int stuck = 0;\n\n    while (time_left() > 0.0) {\n        if (best_actual == TARGET) break;\n\n        bool improved = false;\n\n        /* -------- greedy hill climbing -------- */\n        while ((int)cur_path.size() < T) {\n            int last_dir = cur_path.empty() ? -1 : char2dir(cur_path.back());\n            int order[4] = {0, 1, 2, 3};\n            for (int i = 3; i > 0; --i) swap(order[i], order[(int)(rng() % (i + 1))]);\n\n            int best_d = -1;\n            int best_sc = combined(cur_ev);\n            State best_ns = cur;\n            Eval best_ev = cur_ev;\n\n            for (int k = 0; k < 4; ++k) {\n                int d = order[k];\n                if (last_dir != -1 && d == opp[last_dir]) continue;\n                int ei = cur.epos / N;\n                int ej = cur.epos % N;\n                if (!inside(ei + di[d], ej + dj[d])) continue;\n\n                State ns = apply_move(cur, d);\n                Eval ev = evaluate(ns.b);\n                int sc = combined(ev);\n                if (sc > best_sc) {\n                    best_sc = sc;\n                    best_d = d;\n                    best_ns = ns;\n                    best_ev = ev;\n                }\n            }\n\n            if (best_d != -1 && best_sc > combined(cur_ev)) {\n                cur = best_ns;\n                cur_path.push_back(dc[best_d]);\n                cur_ev = best_ev;\n                if (cur_ev.actual > best_actual) {\n                    best_actual = cur_ev.actual;\n                    best_state = cur;\n                    best_path = cur_path;\n                    improved = true;\n                }\n            } else {\n                break;\n            }\n        }\n\n        if (best_actual == TARGET) break;\n\n        /* -------- bounded DFS escape -------- */\n        if ((int)cur_path.size() < T && time_left() > 0.15) {\n            int remain = T - (int)cur_path.size();\n            int depth = min(12, remain);\n            if (cur_ev.actual >= TARGET - 10) depth = min(16, remain);\n\n            int found_actual = cur_ev.actual;\n            string seq = try_escape(cur, cur_ev, depth, found_actual);\n            if (!seq.empty() && (int)cur_path.size() + (int)seq.size() <= T) {\n                for (char c : seq) {\n                    int d = char2dir(c);\n                    cur = apply_move(cur, d);\n                    cur_path.push_back(c);\n                }\n                cur_ev = evaluate(cur.b);\n                if (cur_ev.actual > best_actual) {\n                    best_actual = cur_ev.actual;\n                    best_state = cur;\n                    best_path = cur_path;\n                }\n                stuck = 0;\n                continue;\n            }\n        }\n\n        /* -------- random kick / restart -------- */\n        ++stuck;\n        int kick_len = 8 + stuck * 4;\n        if (kick_len > 100) kick_len = 100;\n\n        if (stuck % 3 == 0 && !best_path.empty()\n            && (int)best_path.size() + kick_len + 20 <= T) {\n            cur = best_state;\n            cur_path = best_path;\n            cur_ev = evaluate(cur.b);\n        } else if (stuck % 7 == 0 || (int)cur_path.size() + kick_len > T) {\n            cur = init;\n            cur_path.clear();\n            cur_ev = ev0;\n            stuck = 0;\n        }\n\n        kick_len = min(kick_len, T - (int)cur_path.size());\n        for (int k = 0; k < kick_len; ++k) {\n            int ld = cur_path.empty() ? -1 : char2dir(cur_path.back());\n            int ei = cur.epos / N;\n            int ej = cur.epos % N;\n            int order[4] = {0, 1, 2, 3};\n            for (int i = 3; i > 0; --i) swap(order[i], order[(int)(rng() % (i + 1))]);\n\n            bool moved = false;\n            for (int d : order) {\n                if (ld != -1 && d == opp[ld]) continue;\n                if (!inside(ei + di[d], ej + dj[d])) continue;\n                cur = apply_move(cur, d);\n                cur_path.push_back(dc[d]);\n                moved = true;\n                break;\n            }\n            if (!moved) {\n                for (int d = 0; d < 4; ++d) {\n                    if (!inside(ei + di[d], ej + dj[d])) continue;\n                    cur = apply_move(cur, d);\n                    cur_path.push_back(dc[d]);\n                    break;\n                }\n            }\n        }\n\n        if ((int)cur_path.size() <= T) {\n            cur_ev = evaluate(cur.b);\n            if (cur_ev.actual > best_actual) {\n                best_actual = cur_ev.actual;\n                best_state = cur;\n                best_path = cur_path;\n            }\n        }\n    }\n\n    cout << best_path << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\n// ------------------------------------------------------------\n// Random (xoshiro256++)\n// ------------------------------------------------------------\nuint64_t rng_seed() {\n    return chrono::steady_clock::now().time_since_epoch().count();\n}\nstruct xoshiro256ss {\n    using result_type = uint64_t;\n    uint64_t s[4];\n    xoshiro256ss(uint64_t seed) {\n        s[0] = splitmix64(seed);\n        s[1] = splitmix64(s[0]);\n        s[2] = splitmix64(s[1]);\n        s[3] = splitmix64(s[2]);\n    }\n    static uint64_t splitmix64(uint64_t x) {\n        x += 0x9e3779b97f4a7c15;\n        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;\n        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;\n        return x ^ (x >> 31);\n    }\n    uint64_t operator()() {\n        uint64_t r = rotl(s[1] * 5, 7) * 9;\n        uint64_t t = s[1] << 17;\n        s[2] ^= s[0];\n        s[3] ^= s[1];\n        s[1] ^= s[2];\n        s[0] ^= s[3];\n        s[2] ^= t;\n        s[3] = rotl(s[3], 45);\n        return r;\n    }\n    static uint64_t rotl(uint64_t x, int k) {\n        return (x << k) | (x >> (64 - k));\n    }\n    static constexpr uint64_t min() { return 0; }\n    static constexpr uint64_t max() { return UINT64_MAX; }\n};\nxoshiro256ss rng(rng_seed());\n\ninline long long rnd_ll(long long l, long long r) {\n    if (l >= r) return l;\n    return l + (long long)(rng() % (uint64_t)(r - l + 1));\n}\ninline int rnd_int(int l, int r) {\n    if (l >= r) return l;\n    return l + (int)(rng() % (uint64_t)(r - l + 1));\n}\ninline double rnd_double() {\n    return (rng() >> 11) * (1.0 / (1ull << 53));\n}\n\n// ------------------------------------------------------------\n// Geometry\n// ------------------------------------------------------------\nstruct Line {\n    long long px, py, qx, qy, A, B, C;\n};\n\nint N, K;\narray<int,11> need{};\nvector<long long> xs, ys;\nint target_score = 0;\n\ninline Line make_line_pts(long long px, long long py, long long qx, long long qy) {\n    return Line{px, py, qx, qy, qy - py, px - qx, qx*py - px*qy};\n}\n\nlong long egcd(long long a, long long b, long long &x, long long &y) {\n    if (b == 0) { x = (a >= 0 ? 1 : -1); y = 0; return std::abs(a); }\n    long long x1, y1;\n    long long g = egcd(b, a % b, x1, y1);\n    x = y1;\n    y = x1 - (a / b) * y1;\n    return g;\n}\n\nbool get_two_points(long long A, long long B, long long C,\n                    long long &x1, long long &y1, long long &x2, long long &y2) {\n    const long long LIM = 1000000000LL;\n    if (B == 0) {\n        if (A == 0) return false;\n        if (C % A != 0) return false;\n        x1 = -C / A;\n        if (x1 < -LIM || x1 > LIM) return false;\n        y1 = 0; x2 = x1; y2 = 1;\n        if (y2 < -LIM || y2 > LIM) return false;\n        return true;\n    }\n    long long g = std::gcd(std::abs(A), std::abs(B));\n    if (C % g != 0) return false;\n    long long a = A / g, b = B / g, c = -C / g;\n    long long mod = std::abs(b);\n    long long a_mod = ((a % mod) + mod) % mod;\n    long long c_mod = ((c % mod) + mod) % mod;\n    long long inv, tmp;\n    egcd(a_mod, mod, inv, tmp);\n    inv = ((inv % mod) + mod) % mod;\n    long long x0 = (long long)((__int128)c_mod * inv % mod);\n\n    long long t = 0;\n    if (x0 < -LIM) t = (-LIM - x0 + mod - 1) / mod;\n    else if (x0 > LIM) t = -(x0 - LIM + mod - 1) / mod;\n\n    long long x = x0 + mod * t;\n    __int128 num = -(__int128)C - (__int128)A * x;\n    long long y = (long long)(num / B);\n\n    long long step_y = (b > 0) ? -a : a;\n    if (y < -LIM) {\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (-LIM - y + abs_sy - 1) / abs_sy;\n            x += mod * dt; y += step_y * dt;\n        }\n    } else if (y > LIM) {\n        long long abs_sy = std::abs(step_y);\n        if (abs_sy) {\n            long long dt = (y - LIM + abs_sy - 1) / abs_sy;\n            x -= mod * dt; y -= step_y * dt;\n        }\n    }\n    if (x < -LIM || x > LIM || y < -LIM || y > LIM) return false;\n\n    x1 = x; y1 = y;\n    x2 = x1 + mod;\n    if (x2 > LIM) x2 = x1 - mod;\n    __int128 num2 = -(__int128)C - (__int128)A * x2;\n    y2 = (long long)(num2 / B);\n\n    if (x2 < -LIM || x2 > LIM || y2 < -LIM || y2 > LIM) return false;\n    if (x1 == x2 && y1 == y2) return false;\n    return true;\n}\n\ninline bool valid_line_fast(const Line& L) {\n    const long long LIM = 1000000000LL;\n    if (L.px < -LIM || L.px > LIM || L.py < -LIM || L.py > LIM) return false;\n    if (L.qx < -LIM || L.qx > LIM || L.qy < -LIM || L.qy > LIM) return false;\n    if (L.px == L.qx && L.py == L.qy) return false;\n    for (int i = 0; i < N; ++i) {\n        __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n        if (v == 0) return false;\n    }\n    return true;\n}\n\n// ------------------------------------------------------------\n// Signature and hash table\n// ------------------------------------------------------------\nstruct Sig { uint64_t a, b; };\n\nstruct FastHT {\n    struct Node { uint64_t a, b; int cnt; };\n    int n;\n    vector<Node> nodes;\n    vector<int> seen;\n    vector<int> occ;\n    int timer;\n    FastHT(int n_ = 1 << 15) {\n        n = n_;\n        nodes.resize(n);\n        seen.assign(n, 0);\n        timer = 1;\n    }\n    inline void next_timer() {\n        ++timer;\n        occ.clear();\n        if (timer > 2000000000) { fill(seen.begin(), seen.end(), 0); timer = 1; }\n    }\n    inline void add(uint64_t a, uint64_t b) {\n        size_t h = a ^ (b * 11400714819323198485ull);\n        size_t idx = h & (n - 1);\n        while (seen[idx] == timer) {\n            if (nodes[idx].a == a && nodes[idx].b == b) { ++nodes[idx].cnt; return; }\n            idx = (idx + 1) & (n - 1);\n        }\n        seen[idx] = timer;\n        nodes[idx] = {a, b, 1};\n        occ.push_back((int)idx);\n    }\n    inline int get_score(const array<int,11>& need) const {\n        int have[11] = {0};\n        for (int idx : occ) {\n            int c = nodes[idx].cnt;\n            if (c >= 1 && c <= 10) ++have[c];\n        }\n        int s = 0;\n        for (int d = 1; d <= 10; ++d) s += min(need[d], have[d]);\n        return s;\n    }\n    inline void get_counts(int have[11]) const {\n        memset(have, 0, 11 * sizeof(int));\n        for (int idx : occ) {\n            int c = nodes[idx].cnt;\n            if (c >= 1 && c <= 10) ++have[c];\n        }\n    }\n};\n\nFastHT ht;\n\ninline int evaluate_sigs(const vector<Sig>& sigs) {\n    ht.next_timer();\n    for (const auto& s : sigs) ht.add(s.a, s.b);\n    return ht.get_score(need);\n}\n\nvector<Sig> recompute_sigs(const vector<Line>& ls) {\n    vector<Sig> s(N, {0, 0});\n    for (int j = 0; j < (int)ls.size(); ++j) {\n        if (j < 64) {\n            uint64_t mask = 1ULL << j;\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)ls[j].A * xs[i] + (__int128)ls[j].B * ys[i] + (__int128)ls[j].C;\n                s[i].a = (s[i].a & ~mask) | (((uint64_t)(v > 0)) << j);\n            }\n        } else {\n            uint64_t mask = 1ULL << (j - 64);\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)ls[j].A * xs[i] + (__int128)ls[j].B * ys[i] + (__int128)ls[j].C;\n                s[i].b = (s[i].b & ~mask) | (((uint64_t)(v > 0)) << (j - 64));\n            }\n        }\n    }\n    return s;\n}\n\n// ------------------------------------------------------------\n// Candidate generators (all return valid lines)\n// ------------------------------------------------------------\nLine gen_random_line() {\n    for (int att = 0; att < 10000; ++att) {\n        long long x1, y1;\n        do {\n            x1 = rnd_ll(-9999, 9999);\n            y1 = rnd_ll(-9999, 9999);\n        } while ((__int128)x1 * x1 + (__int128)y1 * y1 >= 99990000LL);\n        long long x2 = rnd_ll(-200000, 200000);\n        long long y2 = rnd_ll(-200000, 200000);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line_fast(L)) return L;\n    }\n    return make_line_pts(-1000000000LL, 0, -1000000000LL, 1);\n}\n\nLine gen_separator_line() {\n    for (int attempt = 0; attempt < 15; ++attempt) {\n        int i = rnd_int(0, N - 1), j = rnd_int(0, N - 1);\n        if (i == j) continue;\n        long long xi = xs[i], yi = ys[i];\n        long long xj = xs[j], yj = ys[j];\n        long long A = xj - xi, B = yj - yi;\n        if (A == 0 && B == 0) continue;\n        __int128 rhs = (__int128)xj * xj + (__int128)yj * yj - (__int128)xi * xi - (__int128)yi * yi;\n        long long T = (long long)(rhs / 2);\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        for (int d = -10; d <= 10; ++d) {\n            long long C = T + d;\n            if (C % g != 0) continue;\n            long long px, py, qx, qy;\n            if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line_fast(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\nLine gen_gap_line() {\n    static vector<long long> vals;\n    vals.assign(N, 0);\n    for (int attempt = 0; attempt < 15; ++attempt) {\n        long long A = rnd_ll(-1000, 1000), B = rnd_ll(-1000, 1000);\n        if (A == 0 && B == 0) continue;\n        long long g = std::gcd(std::abs(A), std::abs(B));\n        A /= g; B /= g;\n        for (int i = 0; i < N; ++i) vals[i] = A * xs[i] + B * ys[i];\n        sort(vals.begin(), vals.end());\n        vector<long long> uniq;\n        for (long long v : vals) if (uniq.empty() || uniq.back() != v) uniq.push_back(v);\n        if (uniq.size() <= 1) continue;\n        int idx = rnd_int(0, (int)uniq.size() - 2);\n        long long lo = uniq[idx], hi = uniq[idx + 1];\n        if (hi <= lo + 1) continue;\n        long long C = (hi - lo > 2000000) ? lo + 1 + rnd_ll(0, 2000000) : lo + 1 + rnd_ll(0, hi - lo - 1);\n        long long px, py, qx, qy;\n        if (!get_two_points(A, B, -C, px, py, qx, qy)) continue;\n        Line L = make_line_pts(px, py, qx, qy);\n        if (valid_line_fast(L)) return L;\n    }\n    return gen_random_line();\n}\n\nLine perturb_line(const Line& L0) {\n    const long long D = 5;\n    for (int attempt = 0; attempt < 10; ++attempt) {\n        long long x1 = L0.px + rnd_ll(-D, D), y1 = L0.py + rnd_ll(-D, D);\n        long long x2 = L0.qx + rnd_ll(-D, D), y2 = L0.qy + rnd_ll(-D, D);\n        if (x1 == x2 && y1 == y2) continue;\n        Line L = make_line_pts(x1, y1, x2, y2);\n        if (valid_line_fast(L)) return L;\n    }\n    return gen_random_line();\n}\n\nLine gen_split_line(const vector<Sig>& sigs, int prefer_target) {\n    static vector<int> bucket;\n    static vector<pair<long long,int>> proj;\n    bucket.reserve(128);\n    proj.reserve(128);\n\n    int best_idx = -1, best_sz = 0, best_pri = 0;\n    int samples = (prefer_target >= 0) ? 30 : 20;\n    for (int s = 0; s < samples; ++s) {\n        int idx = rnd_int(0, N - 1);\n        uint64_t ta = sigs[idx].a, tb = sigs[idx].b;\n        int cnt = 0;\n        for (int i = 0; i < N; ++i) if (sigs[i].a == ta && sigs[i].b == tb) ++cnt;\n        int pri = (cnt > 20) ? cnt * 5 : (cnt > 10) ? cnt * 3 : cnt;\n        if (pri > best_pri) { best_pri = pri; best_idx = idx; best_sz = cnt; }\n    }\n    if (best_idx == -1 || best_sz <= 1) return gen_random_line();\n\n    uint64_t ta = sigs[best_idx].a, tb = sigs[best_idx].b;\n    bucket.clear();\n    for (int i = 0; i < N; ++i) if (sigs[i].a == ta && sigs[i].b == tb) bucket.push_back(i);\n    int c = best_sz;\n\n    vector<int> targets;\n    if (prefer_target >= 1 && prefer_target < c) targets.push_back(prefer_target);\n    if (c > 10) {\n        for (int d = 1; d <= 10; ++d) if (d != prefer_target) targets.push_back(d);\n        targets.push_back(c / 2);\n    } else {\n        for (int t = 1; t < c; ++t) if (t != prefer_target) targets.push_back(t);\n    }\n    if ((int)targets.size() > 6) {\n        shuffle(targets.begin(), targets.end(), rng);\n        targets.resize(6);\n    }\n\n    long long cx = 0, cy = 0;\n    for (int id : bucket) { cx += xs[id]; cy += ys[id]; }\n\n    int dirs = (prefer_target >= 0) ? 35 : 25;\n    for (int t : targets) {\n        if (t <= 0 || t >= c) continue;\n        for (int dir = 0; dir < dirs; ++dir) {\n            long long dx, dy;\n            if (dir < 20) {\n                int pid = bucket[rnd_int(0, c - 1)];\n                dx = xs[pid] * (long long)c - cx;\n                dy = ys[pid] * (long long)c - cy;\n                if (dir & 1) { swap(dx, dy); dx = -dx; }\n            } else {\n                dx = rnd_ll(-500, 500);\n                dy = rnd_ll(-500, 500);\n            }\n            if (dx == 0 && dy == 0) continue;\n            proj.clear();\n            for (int id : bucket) proj.emplace_back(dx * xs[id] + dy * ys[id], id);\n            sort(proj.begin(), proj.end());\n            if (proj[t - 1].first == proj[t].first) continue;\n            long long C = proj[t - 1].first + 1;\n            long long px, py, qx, qy;\n            if (!get_two_points(dx, dy, -C, px, py, qx, qy)) continue;\n            Line L = make_line_pts(px, py, qx, qy);\n            if (valid_line_fast(L)) return L;\n        }\n    }\n    return gen_random_line();\n}\n\n// ------------------------------------------------------------\n// Main solver\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    cin >> N >> K;\n    for (int d = 1; d <= 10; ++d) { cin >> need[d]; target_score += need[d]; }\n    xs.resize(N); ys.resize(N);\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    const double TIME_LIMIT = 2.90;\n\n    vector<Line> best_lines;\n    vector<Sig> best_sig;\n    int best_score = -1;\n\n    vector<Sig> tmp(N), greedy_sig;\n\n    // ---------- Greedy construction ----------\n    vector<Line> lines;\n    vector<Sig> sig(N, {0, 0});\n    int cur_score = 0;\n    const int GREEDY_CANDS = 100;\n\n    for (int step = 0; step < K && elapsed() < TIME_LIMIT * 0.30; ++step) {\n        Line best_line;\n        int best_score_local = -1;\n\n        for (int cand = 0; cand < GREEDY_CANDS; ++cand) {\n            int type = rnd_int(0, 3);\n            Line L;\n            if (type == 0) L = gen_random_line();\n            else if (type == 1) L = gen_gap_line();\n            else if (type == 2) L = gen_separator_line();\n            else L = gen_split_line(sig, -1);\n\n            int pj = step;\n            if (pj < 64) {\n                uint64_t mask = 1ULL << pj;\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    tmp[i].a = (sig[i].a & ~mask) | (((uint64_t)(v > 0)) << pj);\n                    tmp[i].b = sig[i].b;\n                }\n            } else {\n                uint64_t mask = 1ULL << (pj - 64);\n                for (int i = 0; i < N; ++i) {\n                    __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                    tmp[i].a = sig[i].a;\n                    tmp[i].b = (sig[i].b & ~mask) | (((uint64_t)(v > 0)) << (pj - 64));\n                }\n            }\n            int sc = evaluate_sigs(tmp);\n            if (sc > best_score_local) {\n                best_score_local = sc;\n                best_line = L;\n                greedy_sig = tmp;\n            }\n        }\n\n        lines.push_back(best_line);\n        sig.swap(greedy_sig);\n        cur_score = best_score_local;\n        if (cur_score == target_score) break;\n    }\n\n    while ((int)lines.size() < K) {\n        Line L = gen_random_line();\n        lines.push_back(L);\n        int pj = (int)lines.size() - 1;\n        if (pj < 64) {\n            uint64_t mask = 1ULL << pj;\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                sig[i].a = (sig[i].a & ~mask) | (((uint64_t)(v > 0)) << pj);\n            }\n        } else {\n            uint64_t mask = 1ULL << (pj - 64);\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                sig[i].b = (sig[i].b & ~mask) | (((uint64_t)(v > 0)) << (pj - 64));\n            }\n        }\n    }\n    cur_score = evaluate_sigs(sig);\n    best_score = cur_score;\n    best_lines = lines;\n    best_sig = sig;\n\n    // ---------- Simulated Annealing ----------\n    double T = 2.0;\n    int last_improve = 0;\n    int iter = 0;\n    int have[11] = {0};\n    ht.get_counts(have);\n\n    while (elapsed() < TIME_LIMIT) {\n        ++iter;\n\n        // Pick preferred target based on current deficits\n        int pref = -1;\n        int total_def = 0;\n        for (int d = 1; d <= 10; ++d) if (have[d] < need[d]) total_def += need[d] - have[d];\n        if (total_def > 0 && rnd_int(0, 1) == 0) {\n            int r = rnd_int(1, total_def);\n            for (int d = 1; d <= 10; ++d) {\n                if (have[d] < need[d]) {\n                    r -= need[d] - have[d];\n                    if (r <= 0) { pref = d; break; }\n                }\n            }\n        }\n\n        int r2 = rnd_int(0, 99);\n        Line L;\n        if (r2 < 45) L = gen_split_line(sig, pref);\n        else if (r2 < 65) L = gen_gap_line();\n        else if (r2 < 85) L = gen_random_line();\n        else if (r2 < 95) L = gen_separator_line();\n        else L = perturb_line(lines[rnd_int(0, K - 1)]);\n\n        int j = rnd_int(0, K - 1);\n\n        if (j < 64) {\n            uint64_t mask = 1ULL << j;\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                tmp[i].a = (sig[i].a & ~mask) | (((uint64_t)(v > 0)) << j);\n                tmp[i].b = sig[i].b;\n            }\n        } else {\n            uint64_t mask = 1ULL << (j - 64);\n            for (int i = 0; i < N; ++i) {\n                __int128 v = (__int128)L.A * xs[i] + (__int128)L.B * ys[i] + (__int128)L.C;\n                tmp[i].a = sig[i].a;\n                tmp[i].b = (sig[i].b & ~mask) | (((uint64_t)(v > 0)) << (j - 64));\n            }\n        }\n        int new_score = evaluate_sigs(tmp);\n        int delta = new_score - cur_score;\n        if (delta > 0 || exp(delta / T) > rnd_double()) {\n            lines[j] = L;\n            sig.swap(tmp);\n            cur_score = new_score;\n            if (delta > 0) ht.get_counts(have);\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_lines = lines;\n                best_sig = sig;\n                last_improve = iter;\n            }\n        }\n\n        T *= 0.9997;\n        if (T < 0.0003) T = 0.0003;\n\n        if (iter - last_improve > 6000) {\n            T = 2.0;\n            last_improve = iter;\n            lines = best_lines;\n            sig = best_sig;\n            cur_score = best_score;\n            ht.get_counts(have);\n\n            for (int rep = 0; rep < 20; ++rep) {\n                int jj = rnd_int(0, K - 1);\n                Line RL = gen_random_line();\n                lines[jj] = RL;\n                if (jj < 64) {\n                    uint64_t mask = 1ULL << jj;\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)RL.A * xs[i] + (__int128)RL.B * ys[i] + (__int128)RL.C;\n                        sig[i].a = (sig[i].a & ~mask) | (((uint64_t)(v > 0)) << jj);\n                    }\n                } else {\n                    uint64_t mask = 1ULL << (jj - 64);\n                    for (int i = 0; i < N; ++i) {\n                        __int128 v = (__int128)RL.A * xs[i] + (__int128)RL.B * ys[i] + (__int128)RL.C;\n                        sig[i].b = (sig[i].b & ~mask) | (((uint64_t)(v > 0)) << (jj - 64));\n                    }\n                }\n            }\n            cur_score = evaluate_sigs(sig);\n            ht.get_counts(have);\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_lines = lines;\n                best_sig = sig;\n            }\n        }\n    }\n\n    for (int j = 0; j < K; ++j) {\n        if (!valid_line_fast(best_lines[j])) best_lines[j] = gen_random_line();\n    }\n\n    cout << K << \"\\n\";\n    for (int i = 0; i < K; ++i) {\n        cout << best_lines[i].px << \" \" << best_lines[i].py << \" \"\n             << best_lines[i].qx << \" \" << best_lines[i].qy << \"\\n\";\n    }\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 64;\nconst int MAXD = 2 * MAXN;\nconst int INF_P = 1e9;\n\nusing Record = array<int,8>;\n\nstruct Solver {\n    int N, M, cx;\n    int wgt[MAXN][MAXN];\n    bool init_dot[MAXN][MAXN];\n    long long init_sum = 0;\n\n    bool dot[MAXN][MAXN];\n    bool horiz[MAXN][MAXN];\n    bool vert[MAXN][MAXN];\n    bool diag1[MAXN][MAXN];\n    bool diag2[MAXN][MAXN];\n    int best_peri[MAXN][MAXN];\n\n    vector<int> row_dots[MAXN];\n    vector<int> col_dots[MAXN];\n    vector<pair<int,int>> diag1_dots[MAXD];\n    vector<pair<int,int>> diag2_dots[MAXD];\n\n    priority_queue<tuple<long long,int,int,int>> pq;\n    mt19937 rng;\n    int mode, A, B;\n\n    inline bool seg_drawn(int x, int y, int dx, int dy) const {\n        if (dx == 1 && dy == 0) return horiz[x][y];\n        if (dx == -1 && dy == 0) return horiz[x-1][y];\n        if (dx == 0 && dy == 1) return vert[x][y];\n        if (dx == 0 && dy == -1) return vert[x][y-1];\n        if (dx == 1 && dy == 1) return diag1[x][y];\n        if (dx == -1 && dy == -1) return diag1[x-1][y-1];\n        if (dx == 1 && dy == -1) return diag2[x][y];\n        if (dx == -1 && dy == 1) return diag2[x-1][y+1];\n        return true;\n    }\n    inline void set_seg(int x, int y, int dx, int dy) {\n        if (dx == 1 && dy == 0) horiz[x][y] = true;\n        else if (dx == -1 && dy == 0) horiz[x-1][y] = true;\n        else if (dx == 0 && dy == 1) vert[x][y] = true;\n        else if (dx == 0 && dy == -1) vert[x][y-1] = true;\n        else if (dx == 1 && dy == 1) diag1[x][y] = true;\n        else if (dx == -1 && dy == -1) diag1[x-1][y-1] = true;\n        else if (dx == 1 && dy == -1) diag2[x][y] = true;\n        else if (dx == -1 && dy == 1) diag2[x-1][y+1] = true;\n    }\n\n    bool check_edge(int x1, int y1, int x2, int y2) const {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int steps = max(abs(x2-x1), abs(y2-y1));\n        int x = x1, y = y1;\n        for (int s = 0; s < steps; ++s) {\n            int nx = x + dx;\n            int ny = y + dy;\n            if (nx != x2 || ny != y2) {\n                if (dot[nx][ny]) return false;\n            }\n            if (seg_drawn(x, y, dx, dy)) return false;\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void draw_edge(int x1, int y1, int x2, int y2) {\n        int dx = (x2 > x1) - (x2 < x1);\n        int dy = (y2 > y1) - (y2 < y1);\n        int x = x1, y = y1;\n        while (x != x2 || y != y2) {\n            set_seg(x, y, dx, dy);\n            x += dx; y += dy;\n        }\n    }\n\n    bool check_rect(int x1, int y1, int x2, int y2,\n                    int x3, int y3, int x4, int y4) const {\n        if (dot[x1][y1]) return false;\n        if (!dot[x2][y2] || !dot[x3][y3] || !dot[x4][y4]) return false;\n        if (!check_edge(x1,y1,x2,y2)) return false;\n        if (!check_edge(x2,y2,x3,y3)) return false;\n        if (!check_edge(x3,y3,x4,y4)) return false;\n        if (!check_edge(x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void draw_rect(const Record &r) {\n        draw_edge(r[0],r[1],r[2],r[3]);\n        draw_edge(r[2],r[3],r[4],r[5]);\n        draw_edge(r[4],r[5],r[6],r[7]);\n        draw_edge(r[6],r[7],r[0],r[1]);\n    }\n\n    // min perimeter, random tie-break\n    bool choose_rect(int x, int y, Record &out, int &out_peri) {\n        bool found = false;\n        int best_p = 0;\n        Record best;\n        int tie_cnt = 0;\n\n        for (int x2 : row_dots[y]) {\n            int dx = abs(x2 - x);\n            for (int y2 : col_dots[x]) {\n                if (!dot[x2][y2]) continue;\n                int peri = 2 * (dx + abs(y2 - y));\n                if (found && peri > best_p) continue;\n                Record r = {x,y,x2,y,x2,y2,x,y2};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                if (!found || peri < best_p) {\n                    found = true; best_p = peri; best = r; tie_cnt = 1;\n                } else {\n                    tie_cnt++;\n                    if ((int)(rng() % tie_cnt) == 0) best = r;\n                }\n                if (best_p == 4) { out = best; out_peri = 4; return true; }\n            }\n        }\n\n        int off = N - 1;\n        int idx1 = x - y + off;\n        int idx2 = x + y;\n        for (auto [x2,y2] : diag1_dots[idx1]) {\n            if (x2 == x && y2 == y) continue;\n            int ad = abs(x2 - x);\n            for (auto [x4,y4] : diag2_dots[idx2]) {\n                if (x4 == x && y4 == y) continue;\n                int peri = 2 * (ad + abs(x4 - x));\n                if (found && peri > best_p) continue;\n                int x3 = x2 + x4 - x;\n                int y3 = y2 + y4 - y;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                Record r = {x,y,x2,y2,x3,y3,x4,y4};\n                if (!check_rect(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7])) continue;\n                if (!found || peri < best_p) {\n                    found = true; best_p = peri; best = r; tie_cnt = 1;\n                } else {\n                    tie_cnt++;\n                    if ((int)(rng() % tie_cnt) == 0) best = r;\n                }\n                if (best_p == 4) { out = best; out_peri = 4; return true; }\n            }\n        }\n\n        if (found) { out = best; out_peri = best_p; }\n        return found;\n    }\n\n    long long calc_pri(int w, int p) {\n        if (p <= 0) p = 1;\n        long long wl = w;\n        long long pl = p;\n        switch (mode) {\n            case 0: return A * wl / pl;\n            case 1: return A * wl - B * pl;\n            case 2: return A * wl;\n            case 3: return -A * pl + wl;\n            case 4: return A * wl - B * pl * pl;\n            case 5: return A * wl / (pl * pl);\n            case 6: return A * wl / (pl + B);\n            case 7: return A * wl * wl / pl;\n            case 8: return A * wl / pl + (long long)(rng() & 0xFFFF);\n            case 9: return A * wl - B * pl * pl * pl;\n        }\n        return A * wl / pl;\n    }\n\n    void try_push(int x, int y, int peri) {\n        if (dot[x][y]) return;\n        if (peri >= best_peri[x][y]) return;\n        best_peri[x][y] = peri;\n        int rnd = rng() & 0x7FFF;\n        pq.emplace(calc_pri(wgt[x][y], peri), rnd, x, y);\n    }\n\n    void find_new_candidates(int x, int y) {\n        // axis: P is p2, p1 same row\n        for (int x1 = 0; x1 < N; ++x1) if (!dot[x1][y]) {\n            int base = 2 * abs(x1 - x);\n            for (int y1 : col_dots[x]) {\n                if (!dot[x1][y1]) continue;\n                int peri = base + 2 * abs(y1 - y);\n                if (peri >= best_peri[x1][y]) continue;\n                if (check_rect(x1,y, x,y, x,y1, x1,y1))\n                    try_push(x1, y, peri);\n            }\n        }\n\n        // axis: P is p2, p1 same column\n        for (int y1 = 0; y1 < N; ++y1) if (!dot[x][y1]) {\n            int base = 2 * abs(y1 - y);\n            for (int x2 : row_dots[y]) {\n                if (!dot[x2][y1]) continue;\n                int peri = base + 2 * abs(x2 - x);\n                if (peri >= best_peri[x][y1]) continue;\n                if (check_rect(x,y1, x,y, x2,y, x2,y1))\n                    try_push(x, y1, peri);\n            }\n        }\n\n        // axis: P is p4, p1 same row\n        for (int x1 = 0; x1 < N; ++x1) if (!dot[x1][y]) {\n            int base = 2 * abs(x1 - x);\n            for (int y2 : col_dots[x]) {\n                if (!dot[x1][y2]) continue;\n                int peri = base + 2 * abs(y2 - y);\n                if (peri >= best_peri[x1][y]) continue;\n                if (check_rect(x1,y, x1,y2, x,y2, x,y))\n                    try_push(x1, y, peri);\n            }\n        }\n\n        // axis: P is p4, p1 same column\n        for (int y1 = 0; y1 < N; ++y1) if (!dot[x][y1]) {\n            int base = 2 * abs(y1 - y);\n            for (int x2 : row_dots[y]) {\n                if (!dot[x2][y1]) continue;\n                int peri = base + 2 * abs(x2 - x);\n                if (peri >= best_peri[x][y1]) continue;\n                if (check_rect(x,y1, x2,y1, x2,y, x,y))\n                    try_push(x, y1, peri);\n            }\n        }\n\n        // axis: P is p3 (opposite)\n        for (int x1 : row_dots[y]) {\n            for (int y1 : col_dots[x]) {\n                if (dot[x1][y1]) continue;\n                int peri = 2 * (abs(x1 - x) + abs(y1 - y));\n                if (peri >= best_peri[x1][y1]) continue;\n                if (check_rect(x1,y1, x1,y, x,y, x,y1))\n                    try_push(x1, y1, peri);\n            }\n        }\n\n        int off = N - 1;\n\n        // 45: P is p2, p1 on diag+1\n        for (int d = -min(x,y); d < N - max(x,y); ++d) if (d != 0) {\n            int x1 = x + d, y1 = y + d;\n            if (dot[x1][y1]) continue;\n            int ad = abs(d);\n            for (auto [x4,y4] : diag2_dots[x1 + y1]) {\n                int peri = 2 * (ad + abs(x4 - x));\n                if (peri >= best_peri[x1][y1]) continue;\n                int x3 = x + x4 - x1;\n                int y3 = y + y4 - y1;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                if (check_rect(x1,y1, x,y, x3,y3, x4,y4))\n                    try_push(x1, y1, peri);\n            }\n        }\n\n        // 45: P is p2, p1 on diag-1\n        int s0 = x + y;\n        for (int i = max(0, s0-(N-1)); i <= min(N-1, s0); ++i) {\n            int j = s0 - i;\n            if (i == x && j == y) continue;\n            if (dot[i][j]) continue;\n            int ae = abs(i - x);\n            for (auto [x4,y4] : diag1_dots[i - j + off]) {\n                int peri = 2 * (ae + abs(x4 - x));\n                if (peri >= best_peri[i][j]) continue;\n                int x3 = x + x4 - i;\n                int y3 = y + y4 - j;\n                if (x3 < 0 || x3 >= N || y3 < 0 || y3 >= N) continue;\n                if (!dot[x3][y3]) continue;\n                if (check_rect(i,j, x,y, x3,y3, x4,y4))\n                    try_push(i, j, peri);\n            }\n        }\n\n        // 45: P is p4, p1 on diag+1\n        int diff = x - y;\n        for (int x3 = max(0, diff), y3 = x3 - diff; x3 < N && y3 < N; ++x3, ++y3) {\n            if (x3 == x && y3 == y) continue;\n            if (!dot[x3][y3]) continue;\n            int ad = abs(x3 - x);\n            for (int i = max(0, s0-(N-1)); i <= min(N-1, s0); ++i) {\n                int j = s0 - i;\n                if (i == x && j == y) continue;\n                if (dot[i][j]) continue;\n                int peri = 2 * (ad + abs(i - x));\n                if (peri >= best_peri[i][j]) continue;\n                int x2 = i + x3 - x;\n                int y2 = j + y3 - y;\n                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N) continue;\n                if (!dot[x2][y2]) continue;\n                if (check_rect(i,j, x2,y2, x3,y3, x,y))\n                    try_push(i, j, peri);\n            }\n        }\n\n        // 45: P is p4, p1 on diag-1\n        for (int x3 = max(0, s0-(N-1)); x3 <= min(N-1, s0); ++x3) {\n            int y3 = s0 - x3;\n            if (x3 == x && y3 == y) continue;\n            if (!dot[x3][y3]) continue;\n            int ae = abs(x3 - x);\n            for (int i = max(0, diff), j = i - diff; i < N && j < N; ++i, ++j) {\n                if (i == x && j == y) continue;\n                if (dot[i][j]) continue;\n                int peri = 2 * (ae + abs(i - x));\n                if (peri >= best_peri[i][j]) continue;\n                int x2 = i + x3 - x;\n                int y2 = j + y3 - y;\n                if (x2 < 0 || x2 >= N || y2 < 0 || y2 >= N) continue;\n                if (!dot[x2][y2]) continue;\n                if (check_rect(i,j, x2,y2, x3,y3, x,y))\n                    try_push(i, j, peri);\n            }\n        }\n\n        // 45: P is p3 (opposite)\n        int id1 = x - y + off;\n        int id2 = x + y;\n        for (auto [x2,y2] : diag1_dots[id1]) {\n            if (x2 == x && y2 == y) continue;\n            int ad = abs(x2 - x);\n            for (auto [x4,y4] : diag2_dots[id2]) {\n                if (x4 == x && y4 == y) continue;\n                int peri = 2 * (ad + abs(x4 - x));\n                int x1 = x2 + x4 - x;\n                int y1 = y2 + y4 - y;\n                if (x1 < 0 || x1 >= N || y1 < 0 || y1 >= N) continue;\n                if (dot[x1][y1]) continue;\n                if (peri >= best_peri[x1][y1]) continue;\n                if (check_rect(x1,y1, x2,y2, x,y, x4,y4))\n                    try_push(x1, y1, peri);\n            }\n        }\n    }\n\n    pair<long long, vector<Record>> solve_run(int md, int a, int b, int sd,\n                                              const vector<Record>* pref = nullptr,\n                                              int pref_len = 0) {\n        mode = md; A = a; B = b;\n        rng.seed(sd);\n\n        memcpy(dot, init_dot, sizeof(dot));\n        memset(horiz, 0, sizeof(horiz));\n        memset(vert, 0, sizeof(vert));\n        memset(diag1, 0, sizeof(diag1));\n        memset(diag2, 0, sizeof(diag2));\n        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) best_peri[i][j] = INF_P;\n        while (!pq.empty()) pq.pop();\n        for (int i = 0; i < N; ++i) { row_dots[i].clear(); col_dots[i].clear(); }\n        for (int i = 0; i < MAXD; ++i) { diag1_dots[i].clear(); diag2_dots[i].clear(); }\n\n        long long cur_sum = init_sum;\n        vector<Record> ops;\n        ops.reserve(N * N);\n\n        if (pref && pref_len > 0) {\n            ops.insert(ops.end(), pref->begin(), pref->begin() + pref_len);\n            for (int i = 0; i < pref_len; ++i) {\n                const Record &r = (*pref)[i];\n                dot[r[0]][r[1]] = true;\n                draw_rect(r);\n                cur_sum += wgt[r[0]][r[1]];\n            }\n        }\n\n        for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y) if (dot[x][y]) {\n            row_dots[y].push_back(x);\n            col_dots[x].push_back(y);\n            diag1_dots[x - y + N - 1].push_back({x,y});\n            diag2_dots[x + y].push_back({x,y});\n        }\n\n        Record rec;\n        int p;\n        for (int x = 0; x < N; ++x) {\n            for (int y = 0; y < N; ++y) if (!dot[x][y]) {\n                if (choose_rect(x, y, rec, p)) {\n                    best_peri[x][y] = p;\n                    int rnd = rng() & 0x7FFF;\n                    pq.emplace(calc_pri(wgt[x][y], p), rnd, x, y);\n                }\n            }\n        }\n\n        while (!pq.empty()) {\n            auto [pri, rnd, x, y] = pq.top();\n            pq.pop();\n            if (dot[x][y]) continue;\n\n            Record r;\n            int peri;\n            if (!choose_rect(x, y, r, peri)) {\n                best_peri[x][y] = INF_P;\n                continue;\n            }\n            if (peri != best_peri[x][y]) {\n                best_peri[x][y] = peri;\n                rnd = rng() & 0x7FFF;\n                pq.emplace(calc_pri(wgt[x][y], peri), rnd, x, y);\n                continue;\n            }\n\n            dot[x][y] = true;\n            cur_sum += wgt[x][y];\n            draw_rect(r);\n            ops.push_back(r);\n\n            row_dots[y].push_back(x);\n            col_dots[x].push_back(y);\n            diag1_dots[x - y + N - 1].push_back({x,y});\n            diag2_dots[x + y].push_back({x,y});\n\n            find_new_candidates(x, y);\n        }\n        return {cur_sum, ops};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N, M;\n    if (!(cin >> N >> M)) return 0;\n\n    Solver sol;\n    sol.N = N; sol.M = M;\n    sol.cx = (N - 1) / 2;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            sol.wgt[i][j] = (i - sol.cx)*(i - sol.cx) + (j - sol.cx)*(j - sol.cx) + 1;\n\n    memset(sol.init_dot, 0, sizeof(sol.init_dot));\n    for (int i = 0; i < M; ++i) {\n        int x, y; cin >> x >> y;\n        sol.init_dot[x][y] = true;\n        sol.init_sum += sol.wgt[x][y];\n    }\n\n    const double TIME_LIMIT = 4.5;\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    long long best_score = -1;\n    vector<Record> best_moves;\n    vector<pair<long long, vector<Record>>> elite;\n\n    auto update_best = [&](long long sc, vector<Record> &mv) {\n        if (sc > best_score) {\n            best_score = sc;\n            best_moves = mv;\n        }\n        elite.push_back({sc, std::move(mv)});\n        sort(elite.begin(), elite.end(),\n             [](const auto &a, const auto &b){ return a.first > b.first; });\n        if ((int)elite.size() > 10) elite.resize(10);\n    };\n\n    vector<tuple<int,int,int>> det = {\n        {0, 1000000, 0},\n        {1, 10000, 500},\n        {4, 10000, 500},\n        {6, 1000000, 10},\n        {7, 100, 0},\n        {3, 10000, 0},\n        {5, 1000000, 0},\n        {1, 10000, 2000},\n    };\n    for (auto &[md, A, B] : det) {\n        if (elapsed() > TIME_LIMIT) break;\n        auto [sc, mv] = sol.solve_run(md, A, B, 0);\n        update_best(sc, mv);\n    }\n\n    unsigned seed = 1;\n    while (elapsed() < TIME_LIMIT) {\n        int md = sol.rng() % 10;\n        int A = 0, B = 0;\n        switch (md) {\n            case 0: case 5: case 8:\n                A = 100000 + (sol.rng() % 1900000);\n                B = 0;\n                break;\n            case 6:\n                A = 100000 + (sol.rng() % 1900000);\n                B = sol.rng() % 200;\n                break;\n            case 1: case 4:\n                A = 1000 + (sol.rng() % 19000);\n                B = 1 + (sol.rng() % 2000);\n                break;\n            case 9:\n                A = 1000 + (sol.rng() % 19000);\n                B = 1 + (sol.rng() % 500);\n                break;\n            case 2:\n                A = 1000 + (sol.rng() % 19000);\n                B = 0;\n                break;\n            case 3:\n                A = 1000 + (sol.rng() % 19000);\n                B = 0;\n                break;\n            case 7:\n                A = 10 + (sol.rng() % 500);\n                B = 0;\n                break;\n        }\n\n        long long sc;\n        vector<Record> mv;\n        if (elite.empty() || (sol.rng() & 0x3) == 0) {\n            tie(sc, mv) = sol.solve_run(md, A, B, seed++);\n        } else {\n            const auto &pref_sol = elite[sol.rng() % elite.size()].second;\n            int L = (int)pref_sol.size();\n            int t;\n            if ((sol.rng() & 0x1) == 0) {\n                double frac = 0.5 + 0.5 * (sol.rng() / (double)mt19937::max());\n                t = max(1, (int)(L * frac));\n            } else {\n                t = (L == 0) ? 0 : (sol.rng() % L);\n            }\n            tie(sc, mv) = sol.solve_run(md, A, B, seed++, &pref_sol, t);\n        }\n        update_best(sc, mv);\n\n        if (sc == best_score && !best_moves.empty()) {\n            for (int rep = 0; rep < 5 && elapsed() < TIME_LIMIT; ++rep) {\n                int L = (int)best_moves.size();\n                int t = (L <= 1) ? 0 : (1 + sol.rng() % (L - 1));\n                int md2 = sol.rng() % 10;\n                int A2 = 100000 + (sol.rng() % 1900000);\n                int B2 = sol.rng() % 200;\n                auto [sc2, mv2] = sol.solve_run(md2, A2, B2, seed++, &best_moves, t);\n                update_best(sc2, mv2);\n            }\n        }\n    }\n\n    cout << best_moves.size() << \"\\n\";\n    for (auto &r : best_moves) {\n        for (int i = 0; i < 8; ++i) {\n            if (i) cout << ' ';\n            cout << r[i];\n        }\n        cout << \"\\n\";\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    uint8_t a[100];\n    State() { memset(a, 0, sizeof(a)); }\n};\n\nint NBR[100][4];\nint R[100], C[100];\n\n/* fast splitmix64 PRNG */\nstruct FastRNG {\n    uint64_t s;\n    explicit FastRNG(uint64_t seed = 0) : s(seed) {}\n    uint64_t operator()() {\n        s += 0x9e3779b97f4a7c15ULL;\n        uint64_t z = s;\n        z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;\n        z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;\n        return z ^ (z >> 31);\n    }\n};\n\n/* ------------------------------------------------------------------ */\ninline State tilt(const State& s, int dir) {\n    State ns;\n    if (dir == 0) {                 // Forward / Up\n        for (int c = 0; c < 10; ++c) {\n            int w = 0;\n            for (int r = 0; r < 10; ++r) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[w++ * 10 + c] = x;\n            }\n        }\n    } else if (dir == 1) {          // Backward / Down\n        for (int c = 0; c < 10; ++c) {\n            int w = 9;\n            for (int r = 9; r >= 0; --r) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[w-- * 10 + c] = x;\n            }\n        }\n    } else if (dir == 2) {          // Left\n        for (int r = 0; r < 10; ++r) {\n            int w = 0;\n            for (int c = 0; c < 10; ++c) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[r * 10 + w++] = x;\n            }\n        }\n    } else {                         // Right\n        for (int r = 0; r < 10; ++r) {\n            int w = 9;\n            for (int c = 9; c >= 0; --c) {\n                uint8_t x = s.a[r * 10 + c];\n                if (x) ns.a[r * 10 + w--] = x;\n            }\n        }\n    }\n    return ns;\n}\n\n/* final position of the candy currently at 'pos' after tilting 'dir'  */\ninline int new_pos_after_tilt(const State& s, int pos, int dir) {\n    int r = R[pos];\n    int c = C[pos];\n    if (dir == 0) {\n        int cnt = 0;\n        for (int i = 0; i < r; ++i) if (s.a[i * 10 + c]) ++cnt;\n        return cnt * 10 + c;\n    } else if (dir == 1) {\n        int cnt = 0;\n        for (int i = r + 1; i < 10; ++i) if (s.a[i * 10 + c]) ++cnt;\n        return (9 - cnt) * 10 + c;\n    } else if (dir == 2) {\n        int cnt = 0;\n        for (int i = 0; i < c; ++i) if (s.a[r * 10 + i]) ++cnt;\n        return r * 10 + cnt;\n    } else {\n        int cnt = 0;\n        for (int i = c + 1; i < 10; ++i) if (s.a[r * 10 + i]) ++cnt;\n        return r * 10 + (9 - cnt);\n    }\n}\n\n/* exact score = sum of n_i^2                                         */\ninline int eval_state(const State& s) {\n    uint8_t vis[100] = {};\n    int q[100];\n    int score = 0;\n    for (int i = 0; i < 100; ++i) {\n        uint8_t f = s.a[i];\n        if (!f || vis[i]) continue;\n        int qt = 0;\n        q[qt++] = i;\n        vis[i] = 1;\n        int sz = 0;\n        while (qt) {\n            int u = q[--qt];\n            ++sz;\n            for (int d = 0; d < 4; ++d) {\n                int v = NBR[u][d];\n                if (v >= 0 && !vis[v] && s.a[v] == f) {\n                    vis[v] = 1;\n                    q[qt++] = v;\n                }\n            }\n        }\n        score += sz * sz;\n    }\n    return score;\n}\n\n/* ------------------------------------------------------------------ */\n/*  Exact marginal gain of the newly placed candy + neighbour tie-break\n    packed into one integer.  Key = (delta << 3) + nb                */\ninline int tilt_score(const State& s, int np, uint8_t f) {\n    int nb = 0;\n    for (int d = 0; d < 4; ++d) {\n        int v = NBR[np][d];\n        if (v >= 0 && s.a[v] == f) ++nb;\n    }\n    if (!nb) return 8;               // delta=1, nb=0  \u2192  (1<<3)+0\n\n    uint64_t vis[2] = {0, 0};\n    int sum = 1;                     // the new candy itself\n    int sum_sq = 0;\n    int q[100];\n\n    for (int d = 0; d < 4; ++d) {\n        int v = NBR[np][d];\n        if (v < 0 || s.a[v] != f || ((vis[v >> 6] >> (v & 63)) & 1ULL)) continue;\n        int qt = 0;\n        q[qt++] = v;\n        vis[v >> 6] |= 1ULL << (v & 63);\n        int sz = 0;\n        while (qt) {\n            int u = q[--qt];\n            ++sz;\n            int w0 = NBR[u][0];\n            if (w0 >= 0 && s.a[w0] == f && ((vis[w0 >> 6] >> (w0 & 63)) & 1ULL) == 0) {\n                vis[w0 >> 6] |= 1ULL << (w0 & 63); q[qt++] = w0;\n            }\n            int w1 = NBR[u][1];\n            if (w1 >= 0 && s.a[w1] == f && ((vis[w1 >> 6] >> (w1 & 63)) & 1ULL) == 0) {\n                vis[w1 >> 6] |= 1ULL << (w1 & 63); q[qt++] = w1;\n            }\n            int w2 = NBR[u][2];\n            if (w2 >= 0 && s.a[w2] == f && ((vis[w2 >> 6] >> (w2 & 63)) & 1ULL) == 0) {\n                vis[w2 >> 6] |= 1ULL << (w2 & 63); q[qt++] = w2;\n            }\n            int w3 = NBR[u][3];\n            if (w3 >= 0 && s.a[w3] == f && ((vis[w3 >> 6] >> (w3 & 63)) & 1ULL) == 0) {\n                vis[w3 >> 6] |= 1ULL << (w3 & 63); q[qt++] = w3;\n            }\n        }\n        sum += sz;\n        sum_sq += sz * sz;\n    }\n    int delta = sum * sum - sum_sq;\n    return (delta << 3) + nb;\n}\n\n/* ------------------------------------------------------------------ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; ++i) {\n        R[i] = i / 10;\n        C[i] = i % 10;\n        NBR[i][0] = (i >= 10) ? i - 10 : -1;\n        NBR[i][1] = (i < 90) ? i + 10 : -1;\n        NBR[i][2] = (i % 10 != 0) ? i - 1 : -1;\n        NBR[i][3] = (i % 10 != 9) ? i + 1 : -1;\n    }\n\n    uint8_t flav[100];\n    for (int i = 0; i < 100; ++i) {\n        int x;\n        if (!(cin >> x)) return 0;\n        flav[i] = (uint8_t)x;\n    }\n\n    const char dname[4] = {'F', 'B', 'L', 'R'};\n    State cur;\n\n    for (int t = 0; t < 100; ++t) {\n        int p;\n        cin >> p;\n        --p;\n\n        int pos = -1;\n        for (int i = 0; i < 100; ++i) {\n            if (cur.a[i] == 0) {\n                if (p == 0) { pos = i; break; }\n                --p;\n            }\n        }\n        cur.a[pos] = flav[t];\n\n        if (t == 99) {                 // last candy: tilt does nothing\n            cout << \"F\\n\";\n            cout.flush();\n            break;\n        }\n\n        State base[4];\n        for (int d = 0; d < 4; ++d) base[d] = tilt(cur, d);\n\n        int remaining = 100 - t;\n        int K = max(20, min(100, 5000 / remaining));\n\n        long long total[4] = {0, 0, 0, 0};\n\n        for (int k = 0; k < K; ++k) {\n            uint64_t seed = 123456789ull + (uint64_t)t * 10007ull + (uint64_t)k * 9973ull;\n            FastRNG rng(seed);\n\n            for (int d = 0; d < 4; ++d) {\n                State sim = base[d];\n                for (int s = t + 1; s < 100; ++s) {\n                    int ecnt = 100 - s;\n                    uint32_t r = (uint32_t)(rng() >> 32);\n                    int nth = (int)((uint64_t)r * (uint32_t)ecnt >> 32);\n                    int idx = -1;\n                    for (int i = 0; i < 100; ++i) {\n                        if (sim.a[i] == 0) {\n                            if (nth == 0) { idx = i; break; }\n                            --nth;\n                        }\n                    }\n                    uint8_t f = flav[s];\n                    sim.a[idx] = f;\n\n                    if (s == 99) break;   // no tilt after the final candy\n\n                    State best_ns;\n                    int best_sc = -1;\n                    for (int d2 = 0; d2 < 4; ++d2) {\n                        State ns = tilt(sim, d2);\n                        int np = new_pos_after_tilt(sim, idx, d2);\n                        int sc = tilt_score(ns, np, f);\n                        if (sc > best_sc) {\n                            best_sc = sc;\n                            best_ns = ns;\n                        }\n                    }\n                    sim = best_ns;\n                }\n                total[d] += eval_state(sim);\n            }\n        }\n\n        int best = 0;\n        for (int d = 1; d < 4; ++d)\n            if (total[d] > total[best]) best = d;\n\n        cur = base[best];\n        cout << dname[best] << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ull = unsigned long long;\n\nint M;\ndouble eps;\nmt19937_64 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n// ------------------------------------------------------------\n// Graph representation (N <= 100)\n// ------------------------------------------------------------\nstruct Graph {\n    ull a[100][2];\n};\n\ninline void initGraph(Graph& g, int n) {\n    for (int i = 0; i < n; ++i) g.a[i][0] = g.a[i][1] = 0;\n}\n\ninline void setBit(Graph& g, int u, int v) {\n    if (u > v) swap(u, v);\n    int idx = v >> 6;\n    int bit = v & 63;\n    g.a[u][idx] |= (1ULL << bit);\n    g.a[v][idx] |= (1ULL << bit);\n}\n\ninline bool getBit(const Graph& g, int u, int v) {\n    if (u > v) swap(u, v);\n    int idx = v >> 6;\n    int bit = v & 63;\n    return (g.a[u][idx] >> bit) & 1ULL;\n}\n\n// ------------------------------------------------------------\n// Threshold graph: vertex i (i>=1) connects to all previous j<i iff code[i]==1\n// ------------------------------------------------------------\nGraph buildThreshold(int n, ull code0, ull code1) {\n    Graph g;\n    initGraph(g, n);\n    for (int i = 1; i < n; ++i) {\n        int idx = i >> 6;\n        int bit = i & 63;\n        bool dom = (idx == 0) ? ((code0 >> bit) & 1ULL) : ((code1 >> bit) & 1ULL);\n        if (dom) {\n            for (int j = 0; j < i; ++j) setBit(g, i, j);\n        }\n    }\n    return g;\n}\n\n// Channel: random permutation + BSC(eps)\nGraph addNoise(const Graph& g, int n, double ep) {\n    vector<int> perm(n);\n    iota(perm.begin(), perm.end(), 0);\n    shuffle(perm.begin(), perm.end(), rng);\n    Graph h;\n    initGraph(h, n);\n    uniform_real_distribution<double> d(0.0, 1.0);\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            int pi = perm[i];\n            int pj = perm[j];\n            bool has = getBit(g, pi, pj);\n            if (d(rng) < ep) has = !has;\n            if (has) {\n                setBit(h, i, j);\n                setBit(h, j, i);\n            }\n        }\n    }\n    return h;\n}\n\n// ------------------------------------------------------------\n// Degree sequence utilities\n// ------------------------------------------------------------\nvector<int> getSortedDegrees(const Graph& g, int n) {\n    vector<int> deg(n);\n    for (int i = 0; i < n; ++i) {\n        int d = 0;\n        for (int j = 0; j < n; ++j)\n            if (i != j && getBit(g, i, j)) ++d;\n        deg[i] = d;\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Hamming distance under a given matching (arrays idxH and idxG of size n)\n// match[i] = vertex in G corresponding to vertex idxH[i] in H\nint hammingDist(const Graph& H, const Graph& G, int n,\n                const vector<int>& idxH, const vector<int>& idxG) {\n    int dist = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = i + 1; j < n; ++j) {\n            bool h = getBit(H, idxH[i], idxH[j]);\n            bool g = getBit(G, idxG[i], idxG[j]);\n            if (h != g) ++dist;\n        }\n    }\n    return dist;\n}\n\n// One pass of adjacent-swap refinement. Returns improved distance.\nint refineDist(const Graph& H, const Graph& G, int n,\n               vector<int>& idxH, vector<int>& idxG, int curDist) {\n    for (int i = 0; i + 1 < n; ++i) {\n        int a = idxH[i];\n        int b = idxH[i + 1];\n        int ga = idxG[i];\n        int gb = idxG[i + 1];\n        int delta = 0;\n        // edges involving a or b with other vertices k\n        for (int k = 0; k < n; ++k) if (k != i && k != i + 1) {\n            bool h_ak = getBit(H, a, idxH[k]);\n            bool h_bk = getBit(H, b, idxH[k]);\n            bool g_gak = getBit(G, ga, idxG[k]);\n            bool g_gbk = getBit(G, gb, idxG[k]);\n            delta += (h_ak != g_gbk) + (h_bk != g_gak)\n                   - (h_ak != g_gak) - (h_bk != g_gbk);\n        }\n        // edge between a and b itself\n        bool h_ab = getBit(H, a, b);\n        bool g_gagb = getBit(G, ga, gb);\n        // swapping ga/gb doesn't change the edge between them since it's undirected\n        if (delta < 0) {\n            swap(idxG[i], idxG[i + 1]);\n            curDist += delta;\n        }\n    }\n    return curDist;\n}\n\n// ------------------------------------------------------------\n// Decoder\n// ------------------------------------------------------------\nint decode(const Graph& H, int n,\n           const vector<Graph>& codebook,\n           const vector<vector<int>>& degSeqs) {\n    vector<int> idxH(n);\n    iota(idxH.begin(), idxH.end(), 0);\n    sort(idxH.begin(), idxH.end(),\n         [&](int a, int b) {\n             int da = 0, db = 0;\n             for (int j = 0; j < n; ++j) {\n                 if (a != j && getBit(H, a, j)) ++da;\n                 if (b != j && getBit(H, b, j)) ++db;\n             }\n             return da < db;\n         });\n\n    int bestK = 0;\n    int bestDist = INT_MAX;\n    for (int k = 0; k < M; ++k) {\n        // pre-sorted order for Gk\n        vector<int> idxG(n);\n        iota(idxG.begin(), idxG.end(), 0);\n        sort(idxG.begin(), idxG.end(),\n             [&](int a, int b) {\n                 int da = 0, db = 0;\n                 for (int j = 0; j < n; ++j) {\n                     if (a != j && getBit(codebook[k], a, j)) ++da;\n                     if (b != j && getBit(codebook[k], b, j)) ++db;\n                 }\n                 return da < db;\n             });\n\n        int d = hammingDist(H, codebook[k], n, idxH, idxG);\n        d = refineDist(H, codebook[k], n, idxH, idxG, d);\n        if (d < bestDist) {\n            bestDist = d;\n            bestK = k;\n        }\n    }\n    return bestK;\n}\n\n// Faster decoder using cached sorted orders\nint decodeFast(const Graph& H, int n,\n               const vector<Graph>& codebook,\n               const vector<vector<int>>& orders) {\n    vector<int> degH(n);\n    for (int i = 0; i < n; ++i) {\n        int d = 0;\n        for (int j = 0; j < n; ++j)\n            if (i != j && getBit(H, i, j)) ++d;\n        degH[i] = d;\n    }\n    vector<int> idxH(n);\n    iota(idxH.begin(), idxH.end(), 0);\n    sort(idxH.begin(), idxH.end(),\n         [&](int a, int b) { return degH[a] < degH[b]; });\n\n    int bestK = 0;\n    int bestDist = INT_MAX;\n    for (int k = 0; k < M; ++k) {\n        const vector<int>& idxG = orders[k];\n        int d = hammingDist(H, codebook[k], n, idxH, idxG);\n        // make mutable copy for refinement\n        vector<int> idxG2 = idxG;\n        d = refineDist(H, codebook[k], n, idxH, idxG2, d);\n        if (d < bestDist) {\n            bestDist = d;\n            bestK = k;\n        }\n    }\n    return bestK;\n}\n\n// ------------------------------------------------------------\n// Codebook construction\n// ------------------------------------------------------------\nvector<Graph> buildCodebook(int n, int m, int poolSize,\n                            vector<vector<int>>& outOrders) {\n    vector<Graph> pool;\n    vector<vector<int>> poolDegs;\n    pool.reserve(poolSize);\n    poolDegs.reserve(poolSize);\n\n    for (int i = 0; i < poolSize; ++i) {\n        ull c0 = rng();\n        ull c1 = rng();\n        Graph g = buildThreshold(n, c0, c1);\n        pool.push_back(g);\n        poolDegs.push_back(getSortedDegrees(g, n));\n    }\n\n    // farthest-point sampling in sorted-degree space\n    vector<int> chosen;\n    vector<double> minDist(poolSize, 1e300);\n    chosen.push_back((int)(rng() % poolSize));\n\n    while ((int)chosen.size() < m) {\n        int last = chosen.back();\n        for (int j = 0; j < poolSize; ++j) {\n            double d = 0;\n            for (int v = 0; v < n; ++v) {\n                double diff = (double)poolDegs[j][v] - poolDegs[last][v];\n                d += diff * diff;\n            }\n            if (d < minDist[j]) minDist[j] = d;\n        }\n        int best = 0;\n        for (int j = 1; j < poolSize; ++j)\n            if (minDist[j] > minDist[best]) best = j;\n        chosen.push_back(best);\n    }\n\n    vector<Graph> cb(m);\n    outOrders.resize(m);\n    for (int i = 0; i < m; ++i) {\n        cb[i] = pool[chosen[i]];\n        outOrders[i] = poolDegs[chosen[i]];\n        // recompute orders as actual vertex permutations sorted by degree\n        vector<int>& ord = outOrders[i];\n        ord.resize(n);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(),\n             [&](int a, int b) {\n                 int da = 0, db = 0;\n                 for (int j = 0; j < n; ++j) {\n                     if (a != j && getBit(cb[i], a, j)) ++da;\n                     if (b != j && getBit(cb[i], b, j)) ++db;\n                 }\n                 return da < db;\n             });\n    }\n    return cb;\n}\n\n// ------------------------------------------------------------\n// Validation\n// ------------------------------------------------------------\nint validate(const vector<Graph>& cb, const vector<vector<int>>& orders,\n             int n, int trials) {\n    int err = 0;\n    uniform_int_distribution<int> sdist(0, M - 1);\n    for (int t = 0; t < trials; ++t) {\n        int s = sdist(rng);\n        Graph H = addNoise(cb[s], n, eps);\n        if (decodeFast(H, n, cb, orders) != s) ++err;\n    }\n    return err;\n}\n\n// ------------------------------------------------------------\n// Main\n// ------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> M >> eps)) return 0;\n\n    vector<int> candN = {8, 12, 16, 24, 32, 48, 100};\n\n    vector<Graph> bestCB;\n    vector<vector<int>> bestOrders;\n    int bestN = 100;\n    int bestErr = 1000000;\n\n    for (int n : candN) {\n        if (bestErr == 0 && n >= bestN) continue;\n        for (int attempt = 0; attempt < 2; ++attempt) {\n            vector<vector<int>> orders;\n            auto cb = buildCodebook(n, M, 400, orders);\n            int err = validate(cb, orders, n, 60);\n            if (err < bestErr || (err == bestErr && n < bestN)) {\n                bestErr = err;\n                bestN = n;\n                bestCB = move(cb);\n                bestOrders = move(orders);\n            }\n            if (err == 0) break;\n        }\n        if (bestErr == 0) break;\n    }\n\n    // Output codebook\n    cout << bestN << \"\\n\";\n    for (int k = 0; k < M; ++k) {\n        string s;\n        s.reserve(bestN * (bestN - 1) / 2);\n        for (int i = 0; i < bestN; ++i)\n            for (int j = i + 1; j < bestN; ++j)\n                s.push_back(getBit(bestCB[k], i, j) ? '1' : '0');\n        cout << s << \"\\n\";\n    }\n    cout.flush();\n\n    // Answer 100 queries\n    for (int q = 0; q < 100; ++q) {\n        string hs;\n        cin >> hs;\n        Graph H;\n        initGraph(H, bestN);\n        int pos = 0;\n        for (int i = 0; i < bestN; ++i) {\n            for (int j = i + 1; j < bestN; ++j) {\n                if (hs[pos++] == '1') {\n                    setBit(H, i, j);\n                    setBit(H, j, i);\n                }\n            }\n        }\n        int ans = decodeFast(H, bestN, bestCB, bestOrders);\n        cout << ans << \"\\n\";\n        cout.flush();\n    }\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst int INF_INT = 1000000000;\nconst ll INF_LL = (1LL<<60);\n\nstruct SimpleHeap {\n    static const int MAXN = 10005;\n    pair<int,int> a[MAXN];\n    int n;\n    void clear(){ n=0; }\n    void push(pair<int,int> x){\n        int i=n++;\n        while(i>0){\n            int p=(i-1)>>1;\n            if(a[p].first <= x.first) break;\n            a[i]=a[p];\n            i=p;\n        }\n        a[i]=x;\n    }\n    pair<int,int> top() const { return a[0]; }\n    void pop(){\n        pair<int,int> x = a[--n];\n        int i=0;\n        while(true){\n            int l=(i<<1)|1;\n            if(l>=n) break;\n            int r=l+1, c=l;\n            if(r<n && a[r].first < a[l].first) c=r;\n            if(x.first <= a[c].first) break;\n            a[i]=a[c];\n            i=c;\n        }\n        a[i]=x;\n    }\n    bool empty() const { return n==0; }\n};\n\nint N, M, D, K;\nstruct Edge {int u, v, w;};\nvector<Edge> edges;\nvector<vector<tuple<int,int,int>>> adj;\nvector<int> rem_stamp;\nint cur_stamp = 1;\n\ninline pair<int,ll> dijkstra(int s, int stamp, vector<int>& dist, SimpleHeap& pq){\n    fill(dist.begin(), dist.end(), INF_INT);\n    dist[s] = 0;\n    pq.clear();\n    pq.push({0, s});\n    ll sum = 0;\n    int visited = 0;\n    while(!pq.empty()){\n        auto [d,u] = pq.top(); pq.pop();\n        if(d != dist[u]) continue;\n        visited++;\n        sum += d;\n        for(const auto& [v,w,eid] : adj[u]){\n            if(rem_stamp[eid] == stamp) continue;\n            if(dist[v] > d + w){\n                dist[v] = d + w;\n                pq.push({dist[v], v});\n            }\n        }\n    }\n    return {visited, sum};\n}\n\n// Evaluate proxy score of a day. exact=false -> INF if disconnected. exact=true -> add penalty.\nll eval_day(int day, int out_eid, int in_eid, const vector<int>& samples,\n            const vector<vector<int>>& day_edges,\n            vector<int>& dist, SimpleHeap& pq, bool exact=false){\n    int stamp = cur_stamp++;\n    for(int eid : day_edges[day]){\n        if(eid == out_eid) continue;\n        rem_stamp[eid] = stamp;\n    }\n    if(in_eid != -1) rem_stamp[in_eid] = stamp;\n    ll total = 0;\n    for(int s : samples){\n        auto [vis, sum] = dijkstra(s, stamp, dist, pq);\n        if(vis < N){\n            if(!exact) return INF_LL;\n            total += sum + (ll)(N - vis) * INF_INT;\n        } else {\n            total += sum;\n        }\n    }\n    return total;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    cin >> N >> M >> D >> K;\n    edges.resize(M);\n    adj.assign(N, {});\n    vector<int> xs(N), ys(N);\n    for(int i=0;i<M;i++){\n        int u,v,w;\n        cin >> u >> v >> w;\n        u--; v--;\n        edges[i] = {u,v,w};\n        adj[u].push_back({v,w,i});\n        adj[v].push_back({u,w,i});\n    }\n    for(int i=0;i<N;i++) cin >> xs[i] >> ys[i];\n\n    rem_stamp.assign(M, 0);\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    // ----- approximate edge importance (shortest path tree usage) -----\n    vector<int> imp(M, 0);\n    vector<int> dist0(N);\n    vector<int> parent(N);\n    SimpleHeap pq0;\n    for(int it=0; it<100; it++){\n        int s = rng() % N;\n        fill(dist0.begin(), dist0.end(), INF_INT);\n        dist0[s] = 0;\n        fill(parent.begin(), parent.end(), -1);\n        pq0.clear();\n        pq0.push({0, s});\n        while(!pq0.empty()){\n            auto [d,u] = pq0.top(); pq0.pop();\n            if(d != dist0[u]) continue;\n            for(const auto& [v,w,eid] : adj[u]){\n                if(dist0[v] > d + w){\n                    dist0[v] = d + w;\n                    parent[v] = eid;\n                    pq0.push({dist0[v], v});\n                }\n            }\n        }\n        for(int v=0; v<N; v++){\n            if(v != s && parent[v] != -1) imp[parent[v]]++;\n        }\n    }\n\n    // ----- greedy initialization (balance importance) -----\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){\n        if(imp[a] != imp[b]) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    vector<int> edge_day(M);\n    vector<vector<int>> day_edges(D);\n    vector<ll> day_imp_sum(D, 0);\n    vector<int> day_load(D, 0);\n    for(int eid : order){\n        int best_d = -1;\n        ll best_val = INF_LL;\n        for(int d=0; d<D; d++){\n            if(day_load[d] >= K) continue;\n            if(day_imp_sum[d] < best_val){\n                best_val = day_imp_sum[d];\n                best_d = d;\n            }\n        }\n        if(best_d == -1){\n            for(int d=0; d<D; d++) if(day_load[d] < K){ best_d = d; break; }\n        }\n        edge_day[eid] = best_d;\n        day_edges[best_d].push_back(eid);\n        day_load[best_d]++;\n        day_imp_sum[best_d] += imp[eid];\n    }\n\n    // ----- ensure every day is connected -----\n    vector<int> dist(N);\n    SimpleHeap pq;\n    auto is_conn = [&](int d)->bool{\n        static vector<int> dummy = {0};\n        return eval_day(d, -1, -1, dummy, day_edges, dist, pq) < INF_LL;\n    };\n\n    for(int d=0; d<D; d++){\n        int attempts = 0;\n        while(!is_conn(d)){\n            int d2 = rng() % D;\n            if(d2 == d) continue;\n            if(day_edges[d].empty() || day_edges[d2].empty()) continue;\n            int i1 = rng() % (int)day_edges[d].size();\n            int i2 = rng() % (int)day_edges[d2].size();\n            int e1 = day_edges[d][i1];\n            int e2 = day_edges[d2][i2];\n            swap(day_edges[d][i1], day_edges[d2][i2]);\n            edge_day[e1] = d2;\n            edge_day[e2] = d;\n            if(is_conn(d) && is_conn(d2)){\n                // keep swap\n            } else {\n                swap(day_edges[d][i1], day_edges[d2][i2]);\n                edge_day[e1] = d;\n                edge_day[e2] = d2;\n            }\n            if(++attempts > 20000) break;\n        }\n    }\n\n    // ----- stratified sample sources -----\n    vector<pair<int,int>> nodes_by_x;\n    for(int i=0;i<N;i++) nodes_by_x.push_back({xs[i], i});\n    sort(nodes_by_x.begin(), nodes_by_x.end());\n    const int NS = 20;\n    vector<int> samples;\n    for(int i=0;i<NS;i++){\n        int L = i * N / NS;\n        int R = (i+1) * N / NS;\n        if(L >= R) continue;\n        int idx = L + (int)(rng() % (R - L));\n        samples.push_back(nodes_by_x[idx].second);\n    }\n    while((int)samples.size() < NS) samples.push_back(rng() % N);\n\n    // ----- compute initial proxy scores -----\n    vector<ll> day_score(D);\n    auto recompute_day = [&](int d){\n        day_score[d] = eval_day(d, -1, -1, samples, day_edges, dist, pq);\n    };\n    for(int d=0; d<D; d++) recompute_day(d);\n    ll cur_total = 0;\n    for(ll v : day_score) cur_total += v;\n\n    vector<int> best_edge_day = edge_day;\n    vector<vector<int>> best_day_edges = day_edges;\n    ll best_total = cur_total;\n\n    const double TIME_LIMIT = 5.4;\n    int stagnant = 0;\n\n    while(true){\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if(elapsed > TIME_LIMIT) break;\n\n        int d1 = rng() % D;\n        int d2 = rng() % D;\n        if(d1 == d2) continue;\n        if(day_edges[d1].empty() || day_edges[d2].empty()) continue;\n        int i1 = rng() % (int)day_edges[d1].size();\n        int i2 = rng() % (int)day_edges[d2].size();\n        int e1 = day_edges[d1][i1];\n        int e2 = day_edges[d2][i2];\n\n        ll s1 = eval_day(d1, e1, e2, samples, day_edges, dist, pq);\n        if(s1 >= INF_LL) continue;\n        ll s2 = eval_day(d2, e2, e1, samples, day_edges, dist, pq);\n        if(s2 >= INF_LL) continue;\n\n        ll new_total = cur_total - day_score[d1] - day_score[d2] + s1 + s2;\n        if(new_total < cur_total){\n            edge_day[e1] = d2;\n            edge_day[e2] = d1;\n            day_edges[d1][i1] = e2;\n            day_edges[d2][i2] = e1;\n            day_score[d1] = s1;\n            day_score[d2] = s2;\n            cur_total = new_total;\n            stagnant = 0;\n            if(cur_total < best_total){\n                best_total = cur_total;\n                best_edge_day = edge_day;\n                best_day_edges = day_edges;\n            }\n        } else {\n            stagnant++;\n            if(stagnant > 300){\n                // perturb from best and continue\n                bool ok = false;\n                for(int attempt=0; attempt<10; attempt++){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                    int num_swaps = 10 + (int)(rng() % 10);\n                    for(int k=0; k<num_swaps; k++){\n                        int a = rng() % D;\n                        int b = rng() % D;\n                        if(a == b) continue;\n                        if(day_edges[a].empty() || day_edges[b].empty()) continue;\n                        int ai = rng() % (int)day_edges[a].size();\n                        int bi = rng() % (int)day_edges[b].size();\n                        int ae = day_edges[a][ai];\n                        int be = day_edges[b][bi];\n                        swap(day_edges[a][ai], day_edges[b][bi]);\n                        edge_day[ae] = b;\n                        edge_day[be] = a;\n                    }\n                    bool all_conn = true;\n                    for(int d=0; d<D; d++){\n                        if(!is_conn(d)){\n                            all_conn = false;\n                            break;\n                        }\n                    }\n                    if(all_conn){\n                        ok = true;\n                        break;\n                    }\n                }\n                if(!ok){\n                    edge_day = best_edge_day;\n                    day_edges = best_day_edges;\n                }\n                for(int d=0; d<D; d++) recompute_day(d);\n                cur_total = 0;\n                for(ll v : day_score) cur_total += v;\n                stagnant = 0;\n                if(cur_total < best_total){\n                    best_total = cur_total;\n                    best_edge_day = edge_day;\n                    best_day_edges = day_edges;\n                }\n            }\n        }\n    }\n\n    for(int i=0;i<M;i++){\n        if(i) cout << ' ';\n        cout << best_edge_day[i] + 1;\n    }\n    cout << '\\n';\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nint D;\nvector<string> F[2], R[2];\n\nusing BS = bitset<196>;\nBS validMask[2][16];\nBS occ[2][16];\nbool needF[2][16][16] = {};\nbool needR[2][16][16] = {};\n\nint prefFree[2][17][17][17];\nint needPrefF[2][16][17];\nint needPrefR[2][16][17];\n\nstruct Block {\n    int id;\n    vector<array<int,3>> c[2];\n};\nvector<Block> blocks;\nint nextId = 1;\n\nmt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\nchrono::steady_clock::time_point startT;\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startT).count();\n}\n\n/* ---------- 3D prefix sums of free valid cells ---------- */\nvoid rebuildPrefFree(int idx) {\n    for (int x = 0; x < D; ++x)\n        for (int y = 0; y < D; ++y)\n            for (int z = 0; z < D; ++z) {\n                int v = (validMask[idx][z].test(x * D + y) && !occ[idx][z].test(x * D + y)) ? 1 : 0;\n                prefFree[idx][x + 1][y + 1][z + 1] =\n                    v\n                    + prefFree[idx][x][y + 1][z + 1]\n                    + prefFree[idx][x + 1][y][z + 1]\n                    + prefFree[idx][x + 1][y + 1][z]\n                    - prefFree[idx][x][y][z + 1]\n                    - prefFree[idx][x][y + 1][z]\n                    - prefFree[idx][x + 1][y][z]\n                    + prefFree[idx][x][y][z];\n            }\n}\n\ninline int boxFreeSum(int idx, int x, int y, int z, int dx, int dy, int dz) {\n    auto &p = prefFree[idx];\n    int x1 = x, y1 = y, z1 = z;\n    int x2 = x + dx, y2 = y + dy, z2 = z + dz;\n    return p[x2][y2][z2] - p[x1][y2][z2] - p[x2][y1][z2] - p[x2][y2][z1]\n         + p[x1][y1][z2] + p[x1][y2][z1] + p[x2][y1][z1] - p[x1][y1][z1];\n}\n\n/* ---------- need prefix sums per layer ---------- */\nvoid rebuildNeedPref(int idx) {\n    for (int z = 0; z < D; ++z) {\n        needPrefF[idx][z][0] = 0;\n        needPrefR[idx][z][0] = 0;\n        for (int i = 0; i < D; ++i) {\n            needPrefF[idx][z][i + 1] = needPrefF[idx][z][i] + (needF[idx][z][i] ? 1 : 0);\n            needPrefR[idx][z][i + 1] = needPrefR[idx][z][i] + (needR[idx][z][i] ? 1 : 0);\n        }\n    }\n}\n\ninline int boxBenefit(int idx, int x, int y, int z, int dx, int dy, int dz) {\n    int ben = 0;\n    for (int k = 0; k < dz; ++k) {\n        ben += needPrefF[idx][z + k][x + dx] - needPrefF[idx][z + k][x];\n        ben += needPrefR[idx][z + k][y + dy] - needPrefR[idx][z + k][y];\n    }\n    return ben;\n}\n\n/* ---------- place a shared block ---------- */\nvoid placeShared(const vector<array<int,3>> &c1, const vector<array<int,3>> &c2) {\n    int id = nextId++;\n    for (auto [x, y, z] : c1) {\n        occ[0][z].set(x * D + y);\n        needF[0][z][x] = false;\n        needR[0][z][y] = false;\n    }\n    for (auto [x, y, z] : c2) {\n        occ[1][z].set(x * D + y);\n        needF[1][z][x] = false;\n        needR[1][z][y] = false;\n    }\n    blocks.push_back({id, c1, c2});\n}\n\n/* ---------- 24 proper rotations ---------- */\nvector<array<array<int,3>,3>> genRotations() {\n    vector<array<array<int,3>,3>> res;\n    array<int,3> p = {0, 1, 2};\n    do {\n        int signPerm = ((p[0] == 0 && p[1] == 1 && p[2] == 2) ||\n                        (p[0] == 1 && p[1] == 2 && p[2] == 0) ||\n                        (p[0] == 2 && p[1] == 0 && p[2] == 1)) ? 1 : -1;\n        for (int sx : {1, -1}) {\n            for (int sy : {1, -1}) {\n                int sz = sx * sy * signPerm;\n                array<array<int,3>,3> m = {};\n                m[0][p[0]] = sx;\n                m[1][p[1]] = sy;\n                m[2][p[2]] = sz;\n                res.push_back(m);\n            }\n        }\n    } while (next_permutation(p.begin(), p.end()));\n    return res;\n}\n\n/* ================================================================ */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    startT = chrono::steady_clock::now();\n\n    /* ---- input ---- */\n    if (!(cin >> D)) return 0;\n    for (int i = 0; i < 2; ++i) {\n        F[i].resize(D); R[i].resize(D);\n        for (int z = 0; z < D; ++z) cin >> F[i][z];\n        for (int z = 0; z < D; ++z) cin >> R[i][z];\n    }\n\n    auto rots = genRotations();\n\n    /* ---- valid masks and needs ---- */\n    for (int i = 0; i < 2; ++i) {\n        for (int z = 0; z < D; ++z) {\n            for (int x = 0; x < D; ++x) {\n                needF[i][z][x] = (F[i][z][x] == '1');\n                for (int y = 0; y < D; ++y) {\n                    bool ok = (F[i][z][x] == '1' && R[i][z][y] == '1');\n                    if (ok) validMask[i][z].set(x * D + y);\n                    needR[i][z][y] = (R[i][z][y] == '1');\n                }\n            }\n        }\n    }\n\n    /* ---- ordered box shapes (volume >= 2) ---- */\n    struct Shape { int dx, dy, dz, vol; };\n    vector<Shape> shapes;\n    for (int dx = 1; dx <= D; ++dx)\n        for (int dy = 1; dy <= D; ++dy)\n            for (int dz = 1; dz <= D; ++dz)\n                if (dx * dy * dz >= 2)\n                    shapes.push_back({dx, dy, dz, dx * dy * dz});\n    sort(shapes.begin(), shapes.end(),\n         [](const Shape &a, const Shape &b) { return a.vol > b.vol; });\n\n    const double BOX_TIME = 3.5;\n    const double TIME_LIMIT = 5.8;\n    const int DIRS[6][3] = {{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};\n\n    /* ============================================================\n       PHASE 1 : Greedy shared boxes (ordered shapes, top-K + random)\n       ============================================================ */\n    while (elapsed() < BOX_TIME) {\n        rebuildPrefFree(0); rebuildPrefFree(1);\n        rebuildNeedPref(0); rebuildNeedPref(1);\n\n        long long bestScore = -1;\n        int best_x1 = 0, best_y1 = 0, best_z1 = 0;\n        int best_x2 = 0, best_y2 = 0, best_z2 = 0;\n        int best_dx = 0, best_dy = 0, best_dz = 0;\n        int best_px = 0, best_py = 0, best_pz = 0;\n\n        int limitShapes = min((int)shapes.size(), 300);\n        for (int si = 0; si < limitShapes; ++si) {\n            int dx = shapes[si].dx, dy = shapes[si].dy, dz = shapes[si].dz;\n            int vol = shapes[si].vol;\n\n            struct Cand { int x, y, z, ben; };\n            vector<Cand> pos1, zero1;\n            for (int x = 0; x + dx <= D; ++x)\n                for (int y = 0; y + dy <= D; ++y)\n                    for (int z = 0; z + dz <= D; ++z)\n                        if (boxFreeSum(0, x, y, z, dx, dy, dz) == vol) {\n                            int b = boxBenefit(0, x, y, z, dx, dy, dz);\n                            if (b > 0) pos1.push_back({x, y, z, b});\n                            else if ((int)zero1.size() < 15) zero1.push_back({x, y, z, 0});\n                        }\n\n            if (pos1.empty() && zero1.empty()) continue;\n            if ((int)pos1.size() > 50) {\n                shuffle(pos1.begin(), pos1.end(), rng);\n                pos1.resize(50);\n            }\n\n            array<int,3> dim = {dx, dy, dz};\n            sort(dim.begin(), dim.end());\n            do {\n                int px = dim[0], py = dim[1], pz = dim[2];\n                vector<Cand> pos2, zero2;\n                for (int x = 0; x + px <= D; ++x)\n                    for (int y = 0; y + py <= D; ++y)\n                        for (int z = 0; z + pz <= D; ++z)\n                            if (boxFreeSum(1, x, y, z, px, py, pz) == vol) {\n                                int b = boxBenefit(1, x, y, z, px, py, pz);\n                                if (b > 0) pos2.push_back({x, y, z, b});\n                                else if ((int)zero2.size() < 15) zero2.push_back({x, y, z, 0});\n                            }\n\n                if (pos2.empty() && zero2.empty()) continue;\n                if ((int)pos2.size() > 50) {\n                    shuffle(pos2.begin(), pos2.end(), rng);\n                    pos2.resize(50);\n                }\n\n                auto consider = [&](const Cand &a, const Cand &b, int b1, int b2) {\n                    if (b1 + b2 == 0) return;\n                    long long score = (long long)(b1 + b2) * 1000LL + vol;\n                    if (score > bestScore) {\n                        bestScore = score;\n                        best_x1 = a.x; best_y1 = a.y; best_z1 = a.z;\n                        best_x2 = b.x; best_y2 = b.y; best_z2 = b.z;\n                        best_dx = dx; best_dy = dy; best_dz = dz;\n                        best_px = px; best_py = py; best_pz = pz;\n                    }\n                };\n\n                for (auto &a : pos1)\n                    for (auto &b : pos2)\n                        consider(a, b, a.ben, b.ben);\n                for (auto &a : pos1)\n                    for (auto &b : zero2)\n                        consider(a, b, a.ben, 0);\n                for (auto &a : zero1)\n                    for (auto &b : pos2)\n                        consider(a, b, 0, b.ben);\n            } while (next_permutation(dim.begin(), dim.end()));\n        }\n\n        if (bestScore <= 0) break;\n\n        vector<array<int,3>> c1, c2;\n        c1.reserve(best_dx * best_dy * best_dz);\n        c2.reserve(best_px * best_py * best_pz);\n        for (int k = 0; k < best_dz; ++k)\n            for (int i = 0; i < best_dx; ++i)\n                for (int j = 0; j < best_dy; ++j)\n                    c1.push_back({best_x1 + i, best_y1 + j, best_z1 + k});\n        for (int k = 0; k < best_pz; ++k)\n            for (int i = 0; i < best_px; ++i)\n                for (int j = 0; j < best_py; ++j)\n                    c2.push_back({best_x2 + i, best_y2 + j, best_z2 + k});\n        placeShared(c1, c2);\n    }\n\n    /* ============================================================\n       PHASE 2 : Random BFS shared polycubes\n       ============================================================ */\n    while (elapsed() < TIME_LIMIT) {\n        long long bestScore = -1;\n        vector<array<int,3>> bestC1, bestC2;\n\n        for (int it = 0; it < 4000; ++it) {\n            array<int,3> s1 = {-1,-1,-1}, s2 = {-1,-1,-1};\n            for (int att = 0; att < 30; ++att) {\n                int x = (int)(rng() % D), y = (int)(rng() % D), z = (int)(rng() % D);\n                if (validMask[0][z].test(x * D + y) && !occ[0][z].test(x * D + y)) {\n                    s1 = {x, y, z}; break;\n                }\n            }\n            if (s1[0] < 0) continue;\n            for (int att = 0; att < 30; ++att) {\n                int x = (int)(rng() % D), y = (int)(rng() % D), z = (int)(rng() % D);\n                if (validMask[1][z].test(x * D + y) && !occ[1][z].test(x * D + y)) {\n                    s2 = {x, y, z}; break;\n                }\n            }\n            if (s2[0] < 0) continue;\n\n            for (int rc = 0; rc < 3; ++rc) {\n                const auto &rot = rots[rng() % rots.size()];\n\n                bool inObj1[14][14][14] = {};\n                vector<array<int,3>> shape, q;\n                shape.reserve(30);\n                q.reserve(30);\n\n                auto tryAdd = [&](int x, int y, int z) {\n                    if (x < 0 || x >= D || y < 0 || y >= D || z < 0 || z >= D) return;\n                    if (inObj1[x][y][z]) return;\n                    if (!validMask[0][z].test(x * D + y) || occ[0][z].test(x * D + y)) return;\n                    int rx = x - s1[0], ry = y - s1[1], rz = z - s1[2];\n                    int ax2 = s2[0] + rot[0][0] * rx + rot[0][1] * ry + rot[0][2] * rz;\n                    int ay2 = s2[1] + rot[1][0] * rx + rot[1][1] * ry + rot[1][2] * rz;\n                    int az2 = s2[2] + rot[2][0] * rx + rot[2][1] * ry + rot[2][2] * rz;\n                    if (ax2 < 0 || ax2 >= D || ay2 < 0 || ay2 >= D || az2 < 0 || az2 >= D) return;\n                    if (!validMask[1][az2].test(ax2 * D + ay2) || occ[1][az2].test(ax2 * D + ay2)) return;\n                    inObj1[x][y][z] = true;\n                    shape.push_back({x, y, z});\n                    q.push_back({x, y, z});\n                };\n\n                inObj1[s1[0]][s1[1]][s1[2]] = true;\n                shape.push_back(s1);\n                q.push_back(s1);\n\n                while (!q.empty() && (int)shape.size() < 30) {\n                    int qi = (int)(rng() % q.size());\n                    auto cur = q[qi];\n                    q[qi] = q.back();\n                    q.pop_back();\n\n                    array<int,6> ord = {0, 1, 2, 3, 4, 5};\n                    shuffle(ord.begin(), ord.end(), rng);\n                    for (int d : ord) {\n                        tryAdd(cur[0] + DIRS[d][0], cur[1] + DIRS[d][1], cur[2] + DIRS[d][2]);\n                        if ((int)shape.size() >= 30) break;\n                    }\n                }\n\n                if ((int)shape.size() < 2) continue;\n\n                bool seenF1[16][16] = {}, seenR1[16][16] = {};\n                int ben1 = 0;\n                for (auto &v : shape) {\n                    int x = v[0], y = v[1], z = v[2];\n                    if (!seenF1[z][x] && needF[0][z][x]) { seenF1[z][x] = true; ++ben1; }\n                    if (!seenR1[z][y] && needR[0][z][y]) { seenR1[z][y] = true; ++ben1; }\n                }\n\n                bool seenF2[16][16] = {}, seenR2[16][16] = {};\n                int ben2 = 0;\n                for (auto &v : shape) {\n                    int rx = v[0] - s1[0], ry = v[1] - s1[1], rz = v[2] - s1[2];\n                    int x = s2[0] + rot[0][0] * rx + rot[0][1] * ry + rot[0][2] * rz;\n                    int y = s2[1] + rot[1][0] * rx + rot[1][1] * ry + rot[1][2] * rz;\n                    int z = s2[2] + rot[2][0] * rx + rot[2][1] * ry + rot[2][2] * rz;\n                    if (!seenF2[z][x] && needF[1][z][x]) { seenF2[z][x] = true; ++ben2; }\n                    if (!seenR2[z][y] && needR[1][z][y]) { seenR2[z][y] = true; ++ben2; }\n                }\n\n                if (ben1 + ben2 == 0) continue;\n                long long score = (long long)(ben1 + ben2) * 1000LL + (int)shape.size();\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestC1.clear(); bestC2.clear();\n                    for (auto &v : shape) bestC1.push_back(v);\n                    for (auto &v : shape) {\n                        int rx = v[0] - s1[0], ry = v[1] - s1[1], rz = v[2] - s1[2];\n                        int x = s2[0] + rot[0][0] * rx + rot[0][1] * ry + rot[0][2] * rz;\n                        int y = s2[1] + rot[1][0] * rx + rot[1][1] * ry + rot[1][2] * rz;\n                        int z = s2[2] + rot[2][0] * rx + rot[2][1] * ry + rot[2][2] * rz;\n                        bestC2.push_back({x, y, z});\n                    }\n                }\n            }\n        }\n\n        if (bestScore > 0) placeShared(bestC1, bestC2);\n        else break;\n    }\n\n    /* ============================================================\n       PHASE 3 : Fatten every shared block (simultaneous BFS)\n       ============================================================ */\n    for (auto &bl : blocks) {\n        // recover the rotation that maps c[0] to c[1]\n        array<array<int,3>,3> R;\n        bool found = false;\n        for (const auto &rot : rots) {\n            bool ok = true;\n            for (size_t i = 0; i < bl.c[0].size(); ++i) {\n                int rx = bl.c[0][i][0] - bl.c[0][0][0];\n                int ry = bl.c[0][i][1] - bl.c[0][0][1];\n                int rz = bl.c[0][i][2] - bl.c[0][0][2];\n                int x2 = bl.c[1][0][0] + rot[0][0]*rx + rot[0][1]*ry + rot[0][2]*rz;\n                int y2 = bl.c[1][0][1] + rot[1][0]*rx + rot[1][1]*ry + rot[1][2]*rz;\n                int z2 = bl.c[1][0][2] + rot[2][0]*rx + rot[2][1]*ry + rot[2][2]*rz;\n                if (x2 != bl.c[1][i][0] || y2 != bl.c[1][i][1] || z2 != bl.c[1][i][2]) {\n                    ok = false; break;\n                }\n            }\n            if (ok) { R = rot; found = true; break; }\n        }\n        if (!found) continue;\n\n        bool inBlock1[14][14][14] = {};\n        queue<array<int,3>> q;\n        for (auto &c : bl.c[0]) {\n            inBlock1[c[0]][c[1]][c[2]] = true;\n            q.push(c);\n        }\n\n        while (!q.empty()) {\n            auto cur = q.front(); q.pop();\n            for (int d = 0; d < 6; ++d) {\n                int nx = cur[0] + DIRS[d][0];\n                int ny = cur[1] + DIRS[d][1];\n                int nz = cur[2] + DIRS[d][2];\n                if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) continue;\n                if (inBlock1[nx][ny][nz]) continue;\n                if (!validMask[0][nz].test(nx * D + ny) || occ[0][nz].test(nx * D + ny)) continue;\n\n                int rx = nx - bl.c[0][0][0];\n                int ry = ny - bl.c[0][0][1];\n                int rz = nz - bl.c[0][0][2];\n                int ax2 = bl.c[1][0][0] + R[0][0]*rx + R[0][1]*ry + R[0][2]*rz;\n                int ay2 = bl.c[1][0][1] + R[1][0]*rx + R[1][1]*ry + R[1][2]*rz;\n                int az2 = bl.c[1][0][2] + R[2][0]*rx + R[2][1]*ry + R[2][2]*rz;\n                if (ax2 < 0 || ax2 >= D || ay2 < 0 || ay2 >= D || az2 < 0 || az2 >= D) continue;\n                if (!validMask[1][az2].test(ax2 * D + ay2) || occ[1][az2].test(ax2 * D + ay2)) continue;\n\n                inBlock1[nx][ny][nz] = true;\n                occ[0][nz].set(nx * D + ny);\n                occ[1][az2].set(ax2 * D + ay2);\n                if (needF[0][nz][nx]) needF[0][nz][nx] = false;\n                if (needR[0][nz][ny]) needR[0][nz][ny] = false;\n                if (needF[1][az2][ax2]) needF[1][az2][ax2] = false;\n                if (needR[1][az2][ay2]) needR[1][az2][ay2] = false;\n                bl.c[0].push_back({nx, ny, nz});\n                bl.c[1].push_back({ax2, ay2, az2});\n                q.push({nx, ny, nz});\n            }\n        }\n    }\n\n    /* ============================================================\n       PHASE 4 : Minimum edge cover for remaining unique needs\n       ============================================================ */\n    vector<array<int,3>> uniq[2];\n\n    for (int idx = 0; idx < 2; ++idx) {\n        for (int z = 0; z < D; ++z) {\n            vector<int> xs, ys;\n            for (int x = 0; x < D; ++x) if (needF[idx][z][x]) xs.push_back(x);\n            for (int y = 0; y < D; ++y) if (needR[idx][z][y]) ys.push_back(y);\n            int nL = (int)xs.size(), nR = (int)ys.size();\n            if (nL == 0 && nR == 0) continue;\n\n            if (nL == 0) {\n                for (int y : ys) {\n                    for (int x = 0; x < D; ++x) {\n                        int c = x * D + y;\n                        if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                            occ[idx][z].set(c);\n                            uniq[idx].push_back({x, y, z});\n                            break;\n                        }\n                    }\n                }\n                continue;\n            }\n            if (nR == 0) {\n                for (int x : xs) {\n                    for (int y = 0; y < D; ++y) {\n                        int c = x * D + y;\n                        if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                            occ[idx][z].set(c);\n                            uniq[idx].push_back({x, y, z});\n                            break;\n                        }\n                    }\n                }\n                continue;\n            }\n\n            int yId[16];\n            fill(begin(yId), end(yId), -1);\n            for (int i = 0; i < nR; ++i) yId[ys[i]] = i;\n            vector<vector<int>> adj(nL);\n            for (int i = 0; i < nL; ++i) {\n                int x = xs[i];\n                for (int y : ys) {\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c))\n                        adj[i].push_back(yId[y]);\n                }\n            }\n\n            vector<int> matchR(nR, -1);\n            function<bool(int, vector<char>&)> dfs = [&](int v, vector<char> &seen) -> bool {\n                for (int to : adj[v]) {\n                    if (seen[to]) continue;\n                    seen[to] = 1;\n                    if (matchR[to] == -1 || dfs(matchR[to], seen)) {\n                        matchR[to] = v;\n                        return true;\n                    }\n                }\n                return false;\n            };\n            for (int v = 0; v < nL; ++v) {\n                vector<char> seen(nR, 0);\n                dfs(v, seen);\n            }\n\n            vector<char> matchedL(nL, 0), matchedR(nR, 0);\n            vector<pair<int,int>> cover;\n            for (int j = 0; j < nR; ++j) if (matchR[j] != -1) {\n                cover.push_back({matchR[j], j});\n                matchedL[matchR[j]] = 1;\n                matchedR[j] = 1;\n            }\n            for (int i = 0; i < nL; ++i) if (!matchedL[i]) {\n                for (int to : adj[i]) {\n                    cover.push_back({i, to});\n                    break;\n                }\n            }\n            for (int j = 0; j < nR; ++j) if (!matchedR[j]) {\n                int y = ys[j];\n                for (int i = 0; i < nL; ++i) {\n                    int x = xs[i];\n                    int c = x * D + y;\n                    if (validMask[idx][z].test(c) && !occ[idx][z].test(c)) {\n                        cover.push_back({i, j});\n                        break;\n                    }\n                }\n            }\n\n            sort(cover.begin(), cover.end());\n            cover.erase(unique(cover.begin(), cover.end()), cover.end());\n\n            for (auto &e : cover) {\n                int x = xs[e.first];\n                int y = ys[e.second];\n                int c = x * D + y;\n                if (!validMask[idx][z].test(c) || occ[idx][z].test(c)) continue;\n                occ[idx][z].set(c);\n                uniq[idx].push_back({x, y, z});\n            }\n        }\n    }\n\n    /* ============================================================\n       PHASE 5 : Pair leftover unit cubes between the two objects\n       ============================================================ */\n    int common = min((int)uniq[0].size(), (int)uniq[1].size());\n    vector<int> id0(uniq[0].size()), id1(uniq[1].size());\n    int curId = 1;\n    for (auto &bl : blocks) bl.id = curId++;\n    for (int i = 0; i < common; ++i) {\n        id0[i] = curId;\n        id1[i] = curId;\n        ++curId;\n    }\n    for (int i = common; i < (int)uniq[0].size(); ++i) id0[i] = curId++;\n    for (int i = common; i < (int)uniq[1].size(); ++i) id1[i] = curId++;\n\n    /* ============================================================\n       Output\n       ============================================================ */\n    vector<int> b0(D * D * D, 0), b1(D * D * D, 0);\n    for (auto &bl : blocks) {\n        for (auto [x, y, z] : bl.c[0]) b0[x * D * D + y * D + z] = bl.id;\n        for (auto [x, y, z] : bl.c[1]) b1[x * D * D + y * D + z] = bl.id;\n    }\n    for (int i = 0; i < (int)uniq[0].size(); ++i) {\n        auto [x, y, z] = uniq[0][i];\n        b0[x * D * D + y * D + z] = id0[i];\n    }\n    for (int i = 0; i < (int)uniq[1].size(); ++i) {\n        auto [x, y, z] = uniq[1][i];\n        b1[x * D * D + y * D + z] = id1[i];\n    }\n\n    cout << (curId - 1) << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b0[i];\n    }\n    cout << \"\\n\";\n    for (int i = 0; i < D * D * D; ++i) {\n        if (i) cout << ' ';\n        cout << b1[i];\n    }\n    cout << \"\\n\";\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst long long INF = (1LL << 60);\n\nint N, M, K;\nlong long xs[100], ys[100];\n\nstruct Edge { int u, v; long long w; };\nEdge edges[300];\nEdge esort[300];\nint edgeIdMat[100][100];\nvector<pair<int,int>> adj[100];\n\nstatic int need[5000][100];\nstatic unsigned char res_sorted_v[5000][100];\nstruct TeEdge { int u, v; };\n\n// ---------- DSU ----------\nstruct DSU {\n    int p[100];\n    int rnk[100];\n    void init(int n) {\n        for (int i = 0; i < n; ++i) { p[i] = i; rnk[i] = 0; }\n    }\n    int find(int x) { return p[x]==x ? x : p[x]=find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (rnk[a] < rnk[b]) swap(a,b);\n        p[b] = a;\n        if (rnk[a] == rnk[b]) ++rnk[a];\n        return true;\n    }\n};\n\n// ---------- MST ----------\nlong long mst(const char inV[100], TeEdge te[100], int& teCnt) {\n    teCnt = 0;\n    int nV = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) ++nV;\n    if (nV == 0) return INF;\n    if (nV == 1) return 0;\n    DSU dsu; dsu.init(N);\n    long long cost = 0;\n    int used = 0;\n    for (int j = 0; j < M; ++j) {\n        int u = esort[j].u, v = esort[j].v;\n        if (!inV[u] || !inV[v]) continue;\n        if (dsu.unite(u, v)) {\n            te[teCnt++] = {u, v};\n            cost += esort[j].w;\n            if (++used == nV - 1) break;\n        }\n    }\n    if (used != nV - 1) return INF;\n    return cost;\n}\n\n// ---------- Good power: greedy + two fast incremental passes ----------\nlong long power_good(const char inV[100], int outP[100], int assign[5000], mt19937& rng) {\n    int act[100], R = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) act[R++] = i;\n    if (R == 0) return INF;\n    shuffle(act, act + R, rng);\n\n    static int bucketHead[5001];\n    static int bucketNext[5000];\n    memset(bucketHead, -1, sizeof(bucketHead));\n\n    for (int k = 0; k < K; ++k) {\n        int mn = 100000;\n        for (int idx = 0; idx < N; ++idx) {\n            int v = res_sorted_v[k][idx];\n            if (inV[v]) { mn = need[k][v]; break; }\n        }\n        if (mn > 5000) return INF;\n        bucketNext[k] = bucketHead[mn];\n        bucketHead[mn] = k;\n    }\n\n    static int Plocal[100];\n    static int max1[100], max2[100], who1[100], who2[100];\n    for (int i = 0; i < R; ++i) {\n        Plocal[i] = 0;\n        max1[i] = max2[i] = -1;\n        who1[i] = who2[i] = -1;\n    }\n\n    static int pos[100];\n    for (int i = 0; i < R; ++i) pos[act[i]] = i;\n\n    for (int d = 5000; d >= 0; --d) {\n        for (int k = bucketHead[d]; k != -1; k = bucketNext[k]) {\n            int bestIdx = -1;\n            long long bestInc = LLONG_MAX;\n            for (int i = 0; i < R; ++i) {\n                int dist = need[k][act[i]];\n                if (dist > 5000) continue;\n                if (Plocal[i] >= dist) { bestIdx = i; bestInc = 0; break; }\n                long long inc = 1LL*dist*dist - 1LL*Plocal[i]*Plocal[i];\n                if (inc < bestInc) { bestInc = inc; bestIdx = i; }\n            }\n            if (bestIdx == -1) return INF;\n            int dist = need[k][act[bestIdx]];\n            if (dist > Plocal[bestIdx]) Plocal[bestIdx] = dist;\n            assign[k] = act[bestIdx];\n            if (dist > max1[bestIdx]) {\n                max2[bestIdx] = max1[bestIdx];\n                who2[bestIdx] = who1[bestIdx];\n                max1[bestIdx] = dist;\n                who1[bestIdx] = k;\n            } else if (dist > max2[bestIdx]) {\n                max2[bestIdx] = dist;\n                who2[bestIdx] = k;\n            }\n        }\n    }\n\n    // two fast incremental refinement passes\n    for (int pass = 0; pass < 2; ++pass) {\n        static int order[100];\n        for (int i = 0; i < R; ++i) order[i] = i;\n        shuffle(order, order + R, rng);\n        for (int ii = 0; ii < R; ++ii) {\n            int src = order[ii];\n            if (who1[src] == -1) continue;\n            int k = who1[src];\n            int dik = max1[src];\n            long long saving = 1LL*dik*dik - (max2[src] <= 0 ? 0LL : 1LL*max2[src]*max2[src]);\n            int bestTgt = -1;\n            long long bestNet = 0;\n            for (int tgt = 0; tgt < R; ++tgt) {\n                if (tgt == src) continue;\n                int djk = need[k][act[tgt]];\n                if (djk > 5000) continue;\n                int newP = max(Plocal[tgt], djk);\n                if (newP > 5000) continue;\n                long long costj = 1LL*newP*newP - 1LL*Plocal[tgt]*Plocal[tgt];\n                long long net = saving - costj;\n                if (net > bestNet) { bestNet = net; bestTgt = tgt; }\n            }\n            if (bestTgt != -1) {\n                int djk = need[k][act[bestTgt]];\n                assign[k] = act[bestTgt];\n                // update src incrementally (who2[src] is still at src)\n                Plocal[src] = max2[src] <= 0 ? 0 : max2[src];\n                max1[src] = max2[src]; who1[src] = who2[src]; max2[src] = -1; who2[src] = -1;\n                // update tgt incrementally\n                if (djk > max1[bestTgt]) {\n                    max2[bestTgt] = max1[bestTgt]; who2[bestTgt] = who1[bestTgt];\n                    max1[bestTgt] = djk; who1[bestTgt] = k;\n                } else if (djk > max2[bestTgt]) {\n                    max2[bestTgt] = djk; who2[bestTgt] = k;\n                }\n                Plocal[bestTgt] = max1[bestTgt];\n            }\n        }\n        if (pass == 0) {\n            // recompute stats accurately for second pass\n            for (int i = 0; i < R; ++i) {\n                max1[i] = max2[i] = -1;\n                who1[i] = who2[i] = -1;\n            }\n            for (int k = 0; k < K; ++k) {\n                int v = assign[k];\n                int idx = pos[v];\n                int d = need[k][v];\n                if (d > max1[idx]) {\n                    max2[idx] = max1[idx]; who2[idx] = who1[idx];\n                    max1[idx] = d; who1[idx] = k;\n                } else if (d > max2[idx]) {\n                    max2[idx] = d; who2[idx] = k;\n                }\n            }\n            for (int i = 0; i < R; ++i) Plocal[i] = max1[i] <= 0 ? 0 : max1[i];\n        }\n    }\n\n    for (int i = 0; i < N; ++i) outP[i] = 0;\n    long long cost = 0;\n    for (int i = 0; i < R; ++i) {\n        outP[act[i]] = Plocal[i];\n        cost += 1LL*Plocal[i]*Plocal[i];\n    }\n    return cost;\n}\n\n// ---------- Full refinement (multi-pass, used only at end) ----------\nlong long power_refined(const char inV[100], int outP[100], int assign[5000], mt19937& rng) {\n    int act[100], R = 0;\n    for (int i = 0; i < N; ++i) if (inV[i]) act[R++] = i;\n    if (R == 0) return INF;\n    shuffle(act, act + R, rng);\n\n    static int bucketHead[5001];\n    static int bucketNext[5000];\n    memset(bucketHead, -1, sizeof(bucketHead));\n\n    for (int k = 0; k < K; ++k) {\n        int mn = 100000;\n        for (int idx = 0; idx < N; ++idx) {\n            int v = res_sorted_v[k][idx];\n            if (inV[v]) { mn = need[k][v]; break; }\n        }\n        if (mn > 5000) return INF;\n        bucketNext[k] = bucketHead[mn];\n        bucketHead[mn] = k;\n    }\n\n    static int Plocal[100];\n    static int max1[100], max2[100], who1[100], who2[100];\n    for (int i = 0; i < R; ++i) {\n        Plocal[i] = 0;\n        max1[i] = max2[i] = -1;\n        who1[i] = who2[i] = -1;\n    }\n\n    static int pos[100];\n    for (int i = 0; i < R; ++i) pos[act[i]] = i;\n\n    for (int d = 5000; d >= 0; --d) {\n        for (int k = bucketHead[d]; k != -1; k = bucketNext[k]) {\n            int bestIdx = -1;\n            long long bestInc = LLONG_MAX;\n            for (int i = 0; i < R; ++i) {\n                int dist = need[k][act[i]];\n                if (dist > 5000) continue;\n                if (Plocal[i] >= dist) { bestIdx = i; bestInc = 0; break; }\n                long long inc = 1LL*dist*dist - 1LL*Plocal[i]*Plocal[i];\n                if (inc < bestInc) { bestInc = inc; bestIdx = i; }\n            }\n            if (bestIdx == -1) return INF;\n            int dist = need[k][act[bestIdx]];\n            if (dist > Plocal[bestIdx]) Plocal[bestIdx] = dist;\n            assign[k] = act[bestIdx];\n            if (dist > max1[bestIdx]) {\n                max2[bestIdx] = max1[bestIdx];\n                who2[bestIdx] = who1[bestIdx];\n                max1[bestIdx] = dist;\n                who1[bestIdx] = k;\n            } else if (dist > max2[bestIdx]) {\n                max2[bestIdx] = dist;\n                who2[bestIdx] = k;\n            }\n        }\n    }\n\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int src = 0; src < R; ++src) {\n            if (who1[src] == -1) continue;\n            int k = who1[src];\n            int dik = max1[src];\n            long long saving = 1LL*dik*dik - (max2[src] <= 0 ? 0LL : 1LL*max2[src]*max2[src]);\n            int bestTgt = -1;\n            long long bestNet = 0;\n            for (int tgt = 0; tgt < R; ++tgt) {\n                if (tgt == src) continue;\n                int djk = need[k][act[tgt]];\n                if (djk > 5000) continue;\n                int newP = max(Plocal[tgt], djk);\n                if (newP > 5000) continue;\n                long long costj = 1LL*newP*newP - 1LL*Plocal[tgt]*Plocal[tgt];\n                long long net = saving - costj;\n                if (net > bestNet) { bestNet = net; bestTgt = tgt; }\n            }\n            if (bestTgt != -1) {\n                int djk = need[k][act[bestTgt]];\n                assign[k] = act[bestTgt];\n                // recompute src from scratch\n                max1[src] = max2[src] = -1; who1[src] = who2[src] = -1;\n                for (int kk = 0; kk < K; ++kk) {\n                    if (assign[kk] != act[src]) continue;\n                    int dd = need[kk][act[src]];\n                    if (dd > max1[src]) { max2[src] = max1[src]; who2[src] = who1[src]; max1[src] = dd; who1[src] = kk; }\n                    else if (dd > max2[src]) { max2[src] = dd; who2[src] = kk; }\n                }\n                Plocal[src] = max1[src] <= 0 ? 0 : max1[src];\n                // update tgt\n                if (djk > max1[bestTgt]) {\n                    max2[bestTgt] = max1[bestTgt]; who2[bestTgt] = who1[bestTgt];\n                    max1[bestTgt] = djk; who1[bestTgt] = k;\n                } else if (djk > max2[bestTgt]) {\n                    max2[bestTgt] = djk; who2[bestTgt] = k;\n                }\n                Plocal[bestTgt] = max1[bestTgt];\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) outP[i] = 0;\n    long long cost = 0;\n    for (int i = 0; i < R; ++i) {\n        outP[act[i]] = Plocal[i];\n        cost += 1LL*Plocal[i]*Plocal[i];\n    }\n    return cost;\n}\n\n// ---------- Evaluate ----------\nlong long eval_good(const char inV[100], TeEdge te[100], int& teCnt,\n                    int P[100], int assign[5000], mt19937& rng,\n                    long long& out_ec, long long& out_pc) {\n    out_ec = mst(inV, te, teCnt);\n    if (out_ec >= INF) return INF;\n    out_pc = power_good(inV, P, assign, rng);\n    if (out_pc >= INF) return INF;\n    return out_ec + out_pc;\n}\n\nlong long eval_refined(const char inV[100], TeEdge te[100], int& teCnt,\n                       int P[100], int assign[5000], mt19937& rng,\n                       long long& out_ec, long long& out_pc) {\n    out_ec = mst(inV, te, teCnt);\n    if (out_ec >= INF) return INF;\n    out_pc = power_refined(inV, P, assign, rng);\n    if (out_pc >= INF) return INF;\n    return out_ec + out_pc;\n}\n\n// ---------- First-improvement descent ----------\nvoid descent_fast(char inV[100], long long& cost,\n                  TeEdge te[100], int& teCnt,\n                  int P[100], int assign[5000], mt19937& rng) {\n    while (true) {\n        int deg[100] = {0};\n        for (int i = 0; i < teCnt; ++i) { ++deg[te[i].u]; ++deg[te[i].v]; }\n        int leaves[100], leafCnt = 0;\n        for (int i = 1; i < N; ++i) if (inV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n\n        bool improved = false;\n        if (leafCnt > 0) {\n            shuffle(leaves, leaves + leafCnt, rng);\n            for (int i = 0; i < leafCnt; ++i) {\n                int u = leaves[i];\n                inV[u] = 0;\n                TeEdge nte[100]; int nteCnt;\n                int nP[100]; int nassign[5000];\n                long long ec, pc;\n                long long c = eval_good(inV, nte, nteCnt, nP, nassign, rng, ec, pc);\n                if (c < cost) {\n                    cost = c; teCnt = nteCnt;\n                    memcpy(te, nte, sizeof(TeEdge) * teCnt);\n                    memcpy(P, nP, sizeof(int) * N);\n                    memcpy(assign, nassign, sizeof(int) * K);\n                    improved = true;\n                    break;\n                }\n                inV[u] = 1;\n            }\n        }\n        if (improved) continue;\n\n        bool seen[100] = {false};\n        int cand[100], candCnt = 0;\n        for (int i = 0; i < N; ++i) if (inV[i]) {\n            for (auto& [to, id] : adj[i]) {\n                if (!inV[to] && !seen[to]) { seen[to] = true; cand[candCnt++] = to; }\n            }\n        }\n        if (candCnt > 0) {\n            shuffle(cand, cand + candCnt, rng);\n            for (int i = 0; i < candCnt; ++i) {\n                int v = cand[i];\n                inV[v] = 1;\n                TeEdge nte[100]; int nteCnt;\n                int nP[100]; int nassign[5000];\n                long long ec, pc;\n                long long c = eval_good(inV, nte, nteCnt, nP, nassign, rng, ec, pc);\n                if (c < cost) {\n                    cost = c; teCnt = nteCnt;\n                    memcpy(te, nte, sizeof(TeEdge) * teCnt);\n                    memcpy(P, nP, sizeof(int) * N);\n                    memcpy(assign, nassign, sizeof(int) * K);\n                    improved = true;\n                    break;\n                }\n                inV[v] = 0;\n            }\n        }\n        if (improved) continue;\n\n        // random swaps\n        if (leafCnt > 0 && candCnt > 0) {\n            for (int t = 0; t < 3; ++t) {\n                int u = leaves[rng() % leafCnt];\n                int v = cand[rng() % candCnt];\n                inV[u] = 0; inV[v] = 1;\n                TeEdge nte[100]; int nteCnt;\n                int nP[100]; int nassign[5000];\n                long long ec, pc;\n                long long c = eval_good(inV, nte, nteCnt, nP, nassign, rng, ec, pc);\n                if (c < cost) {\n                    cost = c; teCnt = nteCnt;\n                    memcpy(te, nte, sizeof(TeEdge) * teCnt);\n                    memcpy(P, nP, sizeof(int) * N);\n                    memcpy(assign, nassign, sizeof(int) * K);\n                    improved = true;\n                    break;\n                }\n                inV[v] = 0; inV[u] = 1;\n            }\n        }\n        if (improved) continue;\n\n        break;\n    }\n}\n\n// ---------- Random connected starting state ----------\nvoid random_state(char inV[100], mt19937& rng) {\n    for (int i = 0; i < N; ++i) inV[i] = 1;\n    uniform_int_distribution<int> dist(1, N/2);\n    int steps = dist(rng);\n    for (int s = 0; s < steps; ++s) {\n        TeEdge te[100]; int teCnt;\n        if (mst(inV, te, teCnt) >= INF) break;\n        int deg[100] = {0};\n        for (int i = 0; i < teCnt; ++i) { ++deg[te[i].u]; ++deg[te[i].v]; }\n        int leaves[100], leafCnt = 0;\n        for (int i = 1; i < N; ++i) if (inV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n        if (leafCnt == 0) break;\n        uniform_int_distribution<int> d(0, leafCnt - 1);\n        inV[leaves[d(rng)]] = 0;\n    }\n    TeEdge te[100]; int teCnt;\n    if (mst(inV, te, teCnt) >= INF) for (int i = 0; i < N; ++i) inV[i] = 1;\n}\n\n// ---------- SA neighbor ----------\nvoid random_neighbor(const char curV[100], const TeEdge curTe[100], int curTeCnt,\n                     char nxtV[100], mt19937& rng) {\n    memcpy(nxtV, curV, 100);\n    int deg[100] = {0};\n    for (int i = 0; i < curTeCnt; ++i) { ++deg[curTe[i].u]; ++deg[curTe[i].v]; }\n    int leaves[100], leafCnt = 0;\n    for (int i = 1; i < N; ++i) if (curV[i] && deg[i] == 1) leaves[leafCnt++] = i;\n\n    bool seen[100] = {false};\n    int cand[100], candCnt = 0;\n    for (int i = 0; i < N; ++i) if (curV[i]) {\n        for (auto& [to, id] : adj[i]) {\n            if (!curV[to] && !seen[to]) { seen[to] = true; cand[candCnt++] = to; }\n        }\n    }\n\n    int typ;\n    if (leafCnt == 0 && candCnt == 0) return;\n    if (leafCnt == 0) typ = 1;\n    else if (candCnt == 0) typ = 0;\n    else typ = (int)(rng() % 3);\n\n    if (typ == 0) {\n        uniform_int_distribution<int> d(0, leafCnt - 1);\n        nxtV[leaves[d(rng)]] = 0;\n    } else if (typ == 1) {\n        uniform_int_distribution<int> d(0, candCnt - 1);\n        nxtV[cand[d(rng)]] = 1;\n    } else {\n        uniform_int_distribution<int> d1(0, leafCnt - 1);\n        nxtV[leaves[d1(rng)]] = 0;\n        bool seen2[100] = {false};\n        int cand2[100], cand2Cnt = 0;\n        for (int i = 0; i < N; ++i) if (nxtV[i]) {\n            for (auto& [to, id] : adj[i]) {\n                if (!nxtV[to] && !seen2[to]) { seen2[to] = true; cand2[cand2Cnt++] = to; }\n            }\n        }\n        if (cand2Cnt > 0) {\n            uniform_int_distribution<int> d2(0, cand2Cnt - 1);\n            nxtV[cand2[d2(rng)]] = 1;\n        } else {\n            nxtV[leaves[d1(rng)]] = 1;\n        }\n    }\n}\n\n// ============================================================\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto time_start = chrono::steady_clock::now();\n    const double TL = 1.88;\n\n    cin >> N >> M >> K;\n    for (int i = 0; i < N; ++i) cin >> xs[i] >> ys[i];\n\n    memset(edgeIdMat, -1, sizeof(edgeIdMat));\n    for (int j = 0; j < M; ++j) {\n        int u, v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[j] = {u, v, w};\n        adj[u].push_back({v, j});\n        adj[v].push_back({u, j});\n        edgeIdMat[u][v] = edgeIdMat[v][u] = j;\n    }\n    for (int k = 0; k < K; ++k) {\n        long long a, b;\n        cin >> a >> b;\n        for (int i = 0; i < N; ++i) {\n            long long dx = xs[i] - a;\n            long long dy = ys[i] - b;\n            long long sq = dx*dx + dy*dy;\n            int d = (int)ceil(sqrt((double)sq));\n            while (1LL*d*d < sq) ++d;\n            while (d > 0 && 1LL*(d-1)*(d-1) >= sq) --d;\n            need[k][i] = d;\n        }\n    }\n\n    memcpy(esort, edges, sizeof(Edge) * M);\n    sort(esort, esort + M, [](const Edge& a, const Edge& b){ return a.w < b.w; });\n\n    for (int k = 0; k < K; ++k) {\n        unsigned char order[100];\n        for (int i = 0; i < N; ++i) order[i] = (unsigned char)i;\n        sort(order, order + N, [&](unsigned char a, unsigned char b){\n            return need[k][a] < need[k][b];\n        });\n        memcpy(res_sorted_v[k], order, 100);\n    }\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    char bestV[100];\n    TeEdge bestTe[100]; int bestTeCnt = 0;\n    int bestP[100]; int bestAssign[5000];\n    long long bestCost = INF;\n\n    auto update_best = [&](char V[100], TeEdge Te[100], int TeCnt,\n                           int P[100], int assign[5000], long long cost) {\n        if (cost < bestCost) {\n            bestCost = cost;\n            memcpy(bestV, V, 100);\n            bestTeCnt = TeCnt;\n            memcpy(bestTe, Te, sizeof(TeEdge) * TeCnt);\n            memcpy(bestP, P, sizeof(int) * N);\n            memcpy(bestAssign, assign, sizeof(int) * K);\n        }\n    };\n\n    // 1) All ones + descent\n    {\n        char V[100];\n        for (int i = 0; i < N; ++i) V[i] = 1;\n        TeEdge Te[100]; int TeCnt;\n        int P[100]; int assign[5000];\n        long long ec, pc;\n        long long c = eval_good(V, Te, TeCnt, P, assign, rng, ec, pc);\n        if (c < INF) {\n            descent_fast(V, c, Te, TeCnt, P, assign, rng);\n            update_best(V, Te, TeCnt, P, assign, c);\n        }\n    }\n\n    // 2) Random restarts + descent\n    for (int rep = 0; rep < 3; ++rep) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n        if (elapsed > TL * 0.25) break;\n        char V[100];\n        random_state(V, rng);\n        TeEdge Te[100]; int TeCnt;\n        int P[100]; int assign[5000];\n        long long ec, pc;\n        long long c = eval_good(V, Te, TeCnt, P, assign, rng, ec, pc);\n        if (c < INF) {\n            descent_fast(V, c, Te, TeCnt, P, assign, rng);\n            update_best(V, Te, TeCnt, P, assign, c);\n        }\n    }\n\n    // 3) SA from best\n    char curV[100];\n    TeEdge curTe[100]; int curTeCnt;\n    int curP[100]; int curAssign[5000];\n    long long curCost;\n\n    memcpy(curV, bestV, 100);\n    curTeCnt = bestTeCnt;\n    memcpy(curTe, bestTe, sizeof(TeEdge) * curTeCnt);\n    memcpy(curP, bestP, sizeof(int) * N);\n    memcpy(curAssign, bestAssign, sizeof(int) * K);\n    curCost = bestCost;\n\n    double T = max(1.0, (double)bestCost * 0.03);\n    const double alpha = 0.9996;\n    int iter = 0, lastImprove = 0;\n\n    while (true) {\n        if (++iter % 256 == 0) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - time_start).count();\n            if (elapsed > TL) break;\n        }\n\n        char nxtV[100];\n        random_neighbor(curV, curTe, curTeCnt, nxtV, rng);\n\n        TeEdge nxtTe[100]; int nxtTeCnt;\n        int nxtP[100]; int nxtAssign[5000];\n        long long ec, pc;\n        long long nxtCost = eval_good(nxtV, nxtTe, nxtTeCnt, nxtP, nxtAssign, rng, ec, pc);\n\n        if (nxtCost < INF) {\n            long long delta = nxtCost - curCost;\n            if (delta < 0 || uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) {\n                memcpy(curV, nxtV, 100);\n                curTeCnt = nxtTeCnt;\n                memcpy(curTe, nxtTe, sizeof(TeEdge) * curTeCnt);\n                memcpy(curP, nxtP, sizeof(int) * N);\n                memcpy(curAssign, nxtAssign, sizeof(int) * K);\n                curCost = nxtCost;\n                if (curCost < bestCost) {\n                    update_best(curV, curTe, curTeCnt, curP, curAssign, curCost);\n                    lastImprove = iter;\n                }\n            }\n        }\n\n        T *= alpha;\n        if (iter - lastImprove > 2500) {\n            memcpy(curV, bestV, 100);\n            curTeCnt = bestTeCnt;\n            memcpy(curTe, bestTe, sizeof(TeEdge) * curTeCnt);\n            memcpy(curP, bestP, sizeof(int) * N);\n            memcpy(curAssign, bestAssign, sizeof(int) * K);\n            curCost = bestCost;\n            T = max(1.0, (double)bestCost * 0.03);\n            lastImprove = iter;\n        }\n    }\n\n    // 4) Final refine on best\n    {\n        long long ec, pc;\n        long long rc = eval_refined(bestV, bestTe, bestTeCnt, bestP, bestAssign, rng, ec, pc);\n        if (rc < bestCost) bestCost = rc;\n    }\n\n    // ---------- output ----------\n    int Pout[100] = {0};\n    for (int i = 0; i < N; ++i)\n        if (bestV[i]) Pout[i] = bestP[i];\n\n    int Bout[300] = {0};\n    for (int i = 0; i < bestTeCnt; ++i) {\n        int u = bestTe[i].u;\n        int v = bestTe[i].v;\n        Bout[edgeIdMat[u][v]] = 1;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << Pout[i];\n    }\n    cout << '\\n';\n    for (int j = 0; j < M; ++j) {\n        if (j) cout << ' ';\n        cout << Bout[j];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static constexpr int N = 30;\n    static constexpr int TOTAL = N * (N + 1) / 2;\n    using State = array<short, TOTAL>;\n\n    int ch1[TOTAL], ch2[TOTAL];\n    int cx[TOTAL], cy[TOTAL];\n    State init_state;\n    mt19937 rng;\n\n    Solver() : rng(chrono::steady_clock::now().time_since_epoch().count()) {\n        for (int x = 0; x < N; ++x) {\n            int base = x * (x + 1) / 2;\n            for (int y = 0; y <= x; ++y) {\n                int id = base + y;\n                cx[id] = x;\n                cy[id] = y;\n                if (x + 1 < N) {\n                    int b2 = (x + 1) * (x + 2) / 2;\n                    ch1[id] = b2 + y;\n                    ch2[id] = b2 + y + 1;\n                } else {\n                    ch1[id] = -1;\n                    ch2[id] = -1;\n                }\n            }\n        }\n    }\n\n    inline int process_layer(int x, const vector<int>& ord, State& st, int limit) const {\n        int swaps = 0;\n        int base = x * (x + 1) / 2;\n        for (int y : ord) {\n            int cur = base + y;\n            while (true) {\n                int c1 = ch1[cur];\n                if (c1 == -1) break;\n                int c2 = ch2[cur];\n                int vc = st[cur];\n                int v1 = st[c1];\n                int v2 = st[c2];\n                if (vc <= v1 && vc <= v2) break;\n                int nxt = (v1 < v2) ? c1 : c2;\n                short tmp = st[cur];\n                st[cur] = st[nxt];\n                st[nxt] = tmp;\n                cur = nxt;\n                if (++swaps > limit) return limit + 1;\n            }\n        }\n        return swaps;\n    }\n\n    inline int eval_from(int x, const vector<int>& cand,\n                         const vector<vector<int>>& order,\n                         const array<State, N>& pref,\n                         int limit) const {\n        State st = pref[x + 1];\n        int swaps = process_layer(x, cand, st, limit);\n        if (swaps > limit) return limit + 1;\n        for (int xx = x - 1; xx >= 0; --xx) {\n            swaps += process_layer(xx, order[xx], st, limit - swaps);\n            if (swaps > limit) return limit + 1;\n        }\n        return swaps;\n    }\n\n    void apply_change(int x, const vector<vector<int>>& order, array<State, N>& pref) const {\n        for (int xx = x; xx >= 0; --xx) {\n            pref[xx] = pref[xx + 1];\n            process_layer(xx, order[xx], pref[xx], INT_MAX);\n        }\n    }\n\n    void recompute_pref(const vector<vector<int>>& order, array<State, N>& pref) const {\n        pref[N - 1] = init_state;\n        for (int x = N - 2; x >= 0; --x) {\n            pref[x] = pref[x + 1];\n            process_layer(x, order[x], pref[x], INT_MAX);\n        }\n    }\n\n    int eval_full(const vector<vector<int>>& order) const {\n        State st = init_state;\n        int swaps = 0;\n        for (int x = N - 2; x >= 0; --x)\n            swaps += process_layer(x, order[x], st, INT_MAX);\n        return swaps;\n    }\n\n    inline int sift_down_id(int id, short* val) const {\n        int cur = id;\n        int swaps = 0;\n        while (true) {\n            int c1 = ch1[cur];\n            if (c1 == -1) break;\n            int c2 = ch2[cur];\n            int vc = val[cur];\n            int v1 = val[c1];\n            int v2 = val[c2];\n            if (vc <= v1 && vc <= v2) break;\n            int nxt = (v1 < v2) ? c1 : c2;\n            short tmp = val[cur];\n            val[cur] = val[nxt];\n            val[nxt] = tmp;\n            cur = nxt;\n            ++swaps;\n        }\n        return swaps;\n    }\n\n    vector<vector<int>> solve_beam(uint32_t seed, int width) {\n        mt19937 rs(seed);\n        State cur = init_state;\n        vector<vector<int>> orders(N - 1);\n\n        for (int x = N - 2; x >= 0; --x) {\n            int m = x + 1;\n            int base = x * (x + 1) / 2;\n\n            if (m <= 8) {\n                vector<int> perm(m);\n                iota(perm.begin(), perm.end(), 0);\n                int best_cost = INT_MAX;\n                vector<int> best_ord;\n                State best_st;\n                do {\n                    State s = cur;\n                    int cost = 0;\n                    for (int y : perm) cost += sift_down_id(base + y, s.data());\n                    if (cost < best_cost) {\n                        best_cost = cost;\n                        best_ord = perm;\n                        best_st = s;\n                    }\n                } while (next_permutation(perm.begin(), perm.end()));\n                orders[x] = best_ord;\n                cur = best_st;\n                continue;\n            }\n\n            struct Node {\n                State st;\n                int cost;\n                uint32_t used;\n                uint8_t ord[30];\n                uint8_t len;\n            };\n            vector<Node> beam;\n            beam.reserve(width);\n            Node start;\n            start.st = cur;\n            start.cost = 0;\n            start.used = 0;\n            start.len = 0;\n            beam.push_back(start);\n\n            for (int step = 0; step < m; ++step) {\n                vector<Node> nxt;\n                nxt.reserve(beam.size() * (m - step));\n                for (const Node& e : beam) {\n                    for (int y = 0; y < m; ++y) {\n                        if (e.used & (1u << y)) continue;\n                        Node nd = e;\n                        nd.cost += sift_down_id(base + y, nd.st.data());\n                        nd.ord[nd.len++] = (uint8_t)y;\n                        nd.used |= (1u << y);\n                        nxt.push_back(nd);\n                    }\n                }\n                sort(nxt.begin(), nxt.end(),\n                     [](const Node& a, const Node& b) {\n                         if (a.cost != b.cost) return a.cost < b.cost;\n                         return a.used < b.used;\n                     });\n                if ((int)nxt.size() > width) nxt.resize(width);\n                beam.swap(nxt);\n            }\n            orders[x].resize(m);\n            for (int i = 0; i < m; ++i) orders[x][i] = beam[0].ord[i];\n            cur = beam[0].st;\n        }\n        return orders;\n    }\n\n    vector<tuple<int,int,int,int>> record(const vector<vector<int>>& order) const {\n        State st = init_state;\n        vector<tuple<int,int,int,int>> ops;\n        ops.reserve(5000);\n        for (int x = N - 2; x >= 0; --x) {\n            int base = x * (x + 1) / 2;\n            for (int y : order[x]) {\n                int cur = base + y;\n                while (true) {\n                    int c1 = ch1[cur];\n                    if (c1 == -1) break;\n                    int c2 = ch2[cur];\n                    int vc = st[cur];\n                    int v1 = st[c1];\n                    int v2 = st[c2];\n                    if (vc <= v1 && vc <= v2) break;\n                    int nxt = (v1 < v2) ? c1 : c2;\n                    ops.emplace_back(cx[cur], cy[cur], cx[nxt], cy[nxt]);\n                    short tmp = st[cur];\n                    st[cur] = st[nxt];\n                    st[nxt] = tmp;\n                    cur = nxt;\n                }\n            }\n        }\n        return ops;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    for (int x = 0; x < Solver::N; ++x) {\n        for (int y = 0; y <= x; ++y) {\n            int v;\n            cin >> v;\n            solver.init_state[x * (x + 1) / 2 + y] = (short)v;\n        }\n    }\n\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    // -----------------------------------------------------------------\n    // Phase 1: initial candidates\n    // -----------------------------------------------------------------\n    vector<vector<int>> best_order;\n    int best_cost = INT_MAX;\n\n    auto consider = [&](const vector<vector<int>>& ord) {\n        int c = solver.eval_full(ord);\n        if (c < best_cost) {\n            best_cost = c;\n            best_order = ord;\n        }\n    };\n\n    {\n        vector<vector<int>> ord(Solver::N - 1);\n        for (int x = 0; x < Solver::N - 1; ++x) {\n            ord[x].resize(x + 1);\n            iota(ord[x].begin(), ord[x].end(), 0);\n        }\n        consider(ord);\n    }\n    {\n        vector<vector<int>> ord(Solver::N - 1);\n        for (int x = 0; x < Solver::N - 1; ++x) {\n            ord[x].resize(x + 1);\n            iota(ord[x].begin(), ord[x].end(), 0);\n            reverse(ord[x].begin(), ord[x].end());\n        }\n        consider(ord);\n    }\n    {\n        vector<vector<int>> ord(Solver::N - 1);\n        for (int x = 0; x < Solver::N - 1; ++x) {\n            ord[x].resize(x + 1);\n            iota(ord[x].begin(), ord[x].end(), 0);\n            sort(ord[x].begin(), ord[x].end(),\n                 [&](int a, int b) {\n                     return solver.init_state[x * (x + 1) / 2 + a] >\n                            solver.init_state[x * (x + 1) / 2 + b];\n                 });\n        }\n        consider(ord);\n    }\n    {\n        vector<vector<int>> ord(Solver::N - 1);\n        for (int x = 0; x < Solver::N - 1; ++x) {\n            ord[x].resize(x + 1);\n            iota(ord[x].begin(), ord[x].end(), 0);\n            sort(ord[x].begin(), ord[x].end(),\n                 [&](int a, int b) {\n                     return solver.init_state[x * (x + 1) / 2 + a] <\n                            solver.init_state[x * (x + 1) / 2 + b];\n                 });\n        }\n        consider(ord);\n    }\n    {\n        vector<vector<int>> ord(Solver::N - 1);\n        for (int x = 0; x < Solver::N - 1; ++x) {\n            ord[x].resize(x + 1);\n            iota(ord[x].begin(), ord[x].end(), 0);\n            sort(ord[x].begin(), ord[x].end(),\n                 [&](int a, int b) {\n                     int ida = x * (x + 1) / 2 + a;\n                     int idb = x * (x + 1) / 2 + b;\n                     int mina = min(solver.init_state[solver.ch1[ida]], solver.init_state[solver.ch2[ida]]);\n                     int minb = min(solver.init_state[solver.ch1[idb]], solver.init_state[solver.ch2[idb]]);\n                     int exa = solver.init_state[ida] - mina;\n                     int exb = solver.init_state[idb] - minb;\n                     if (exa != exb) return exa > exb;\n                     return solver.init_state[ida] > solver.init_state[idb];\n                 });\n        }\n        consider(ord);\n    }\n    {\n        vector<vector<int>> ord(Solver::N - 1);\n        for (int x = 0; x < Solver::N - 1; ++x) {\n            ord[x].resize(x + 1);\n            iota(ord[x].begin(), ord[x].end(), 0);\n            sort(ord[x].begin(), ord[x].end(),\n                 [&](int a, int b) {\n                     int ida = x * (x + 1) / 2 + a;\n                     int idb = x * (x + 1) / 2 + b;\n                     int mina = min(solver.init_state[solver.ch1[ida]], solver.init_state[solver.ch2[ida]]);\n                     int minb = min(solver.init_state[solver.ch1[idb]], solver.init_state[solver.ch2[idb]]);\n                     bool va = solver.init_state[ida] > mina;\n                     bool vb = solver.init_state[idb] > minb;\n                     if (va != vb) return va > vb;\n                     int exa = solver.init_state[ida] - mina;\n                     int exb = solver.init_state[idb] - minb;\n                     if (exa != exb) return exa > exb;\n                     return solver.init_state[ida] > solver.init_state[idb];\n                 });\n        }\n        consider(ord);\n    }\n\n    consider(solver.solve_beam(0, 200));\n    consider(solver.solve_beam(12345, 200));\n    consider(solver.solve_beam(99999, 200));\n\n    for (int t = 0; t < 10; ++t) {\n        vector<vector<int>> ord(Solver::N - 1);\n        for (int x = 0; x < Solver::N - 1; ++x) {\n            ord[x].resize(x + 1);\n            iota(ord[x].begin(), ord[x].end(), 0);\n            shuffle(ord[x].begin(), ord[x].end(), solver.rng);\n        }\n        consider(ord);\n    }\n\n    // -----------------------------------------------------------------\n    // Phase 2: intensive hill climbing (pairwise, reverse, insertion)\n    // -----------------------------------------------------------------\n    vector<vector<int>> order = best_order;\n    int cur_cost = best_cost;\n    array<Solver::State, Solver::N> pref;\n    solver.recompute_pref(order, pref);\n\n    for (int rep = 0; rep < 10; ++rep) {\n        if (elapsed() > 0.8) break;\n        bool any = false;\n        for (int x = Solver::N - 2; x >= 0; --x) {\n            int best_s = cur_cost;\n            vector<int> best_o = order[x];\n            bool found = false;\n\n            // pairwise\n            for (int i = 0; i <= x; ++i) {\n                for (int j = i + 1; j <= x; ++j) {\n                    swap(order[x][i], order[x][j]);\n                    int s = solver.eval_from(x, order[x], order, pref, best_s - 1);\n                    if (s < best_s) {\n                        best_s = s;\n                        best_o = order[x];\n                        found = true;\n                    }\n                    swap(order[x][i], order[x][j]);\n                }\n            }\n\n            // reverse segment\n            for (int i = 0; i <= x; ++i) {\n                for (int j = i + 1; j <= x; ++j) {\n                    reverse(order[x].begin() + i, order[x].begin() + j + 1);\n                    int s = solver.eval_from(x, order[x], order, pref, best_s - 1);\n                    if (s < best_s) {\n                        best_s = s;\n                        best_o = order[x];\n                        found = true;\n                    }\n                    reverse(order[x].begin() + i, order[x].begin() + j + 1);\n                }\n            }\n\n            // insertion\n            for (int i = 0; i <= x; ++i) {\n                for (int j = 0; j <= x; ++j) {\n                    if (i == j) continue;\n                    auto tmp = order[x];\n                    int v = tmp[i];\n                    if (i < j) {\n                        for (int k = i; k < j; ++k) tmp[k] = tmp[k + 1];\n                    } else {\n                        for (int k = i; k > j; --k) tmp[k] = tmp[k - 1];\n                    }\n                    tmp[j] = v;\n                    int s = solver.eval_from(x, tmp, order, pref, best_s - 1);\n                    if (s < best_s) {\n                        best_s = s;\n                        best_o = tmp;\n                        found = true;\n                    }\n                }\n            }\n\n            if (found) {\n                cur_cost = best_s;\n                order[x] = best_o;\n                solver.apply_change(x, order, pref);\n                any = true;\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_order = order;\n                }\n            }\n        }\n        if (!any) break;\n    }\n\n    // -----------------------------------------------------------------\n    // Phase 3: simulated annealing\n    // -----------------------------------------------------------------\n    const double TIME_LIMIT = 1.88;\n    uniform_int_distribution<int> layer_dist(0, Solver::N - 2);\n    int last_improve = 0;\n    int iter = 0;\n\n    while (elapsed() < TIME_LIMIT) {\n        double progress = elapsed() / TIME_LIMIT;\n        double T = 20.0 * exp(-4.0 * progress);\n\n        int x = layer_dist(solver.rng);\n        int sz = x + 1;\n        auto cand = order[x];\n        int tp = solver.rng() % 4;\n        if (tp == 0) {\n            int i = solver.rng() % sz;\n            int j = solver.rng() % sz;\n            if (i != j) swap(cand[i], cand[j]);\n        } else if (tp == 1) {\n            int i = solver.rng() % sz;\n            int j = solver.rng() % sz;\n            if (i > j) swap(i, j);\n            if (i < j) reverse(cand.begin() + i, cand.begin() + j + 1);\n        } else if (tp == 2) {\n            int i = solver.rng() % sz;\n            int j = solver.rng() % sz;\n            if (i > j) swap(i, j);\n            if (i < j) {\n                int k = i + 1 + (solver.rng() % (j - i));\n                rotate(cand.begin() + i, cand.begin() + k, cand.begin() + j + 1);\n            }\n        } else {\n            int i = solver.rng() % sz;\n            int j = solver.rng() % sz;\n            if (i != j) {\n                int tmp = cand[i];\n                if (i < j) {\n                    for (int k = i; k < j; ++k) cand[k] = cand[k + 1];\n                } else {\n                    for (int k = i; k > j; --k) cand[k] = cand[k - 1];\n                }\n                cand[j] = tmp;\n            }\n        }\n\n        int max_delta = max(1, (int)(T * 15.0));\n        int limit = cur_cost + max_delta;\n        int new_cost = solver.eval_from(x, cand, order, pref, limit);\n\n        if (new_cost <= limit) {\n            int delta = new_cost - cur_cost;\n            bool accept = false;\n            if (delta <= 0) {\n                accept = true;\n            } else if (T > 0.005) {\n                double p = exp(-delta / T);\n                if (solver.rng() < p * numeric_limits<uint32_t>::max()) accept = true;\n            }\n\n            if (accept) {\n                order[x].swap(cand);\n                cur_cost = new_cost;\n                solver.apply_change(x, order, pref);\n                if (cur_cost < best_cost) {\n                    best_cost = cur_cost;\n                    best_order = order;\n                    last_improve = iter;\n                }\n            }\n        }\n\n        if (++iter - last_improve > 120000) {\n            if (cur_cost > best_cost) {\n                order = best_order;\n                cur_cost = best_cost;\n                solver.recompute_pref(order, pref);\n            }\n            last_improve = iter;\n        }\n    }\n\n    // -----------------------------------------------------------------\n    // Phase 4: final hill climbing (pairwise only, quick)\n    // -----------------------------------------------------------------\n    order = best_order;\n    cur_cost = best_cost;\n    solver.recompute_pref(order, pref);\n\n    for (int rep = 0; rep < 2; ++rep) {\n        bool improved = false;\n        for (int x = Solver::N - 2; x >= 0; --x) {\n            auto best_o = order[x];\n            int best_s = cur_cost;\n            for (int i = 0; i <= x; ++i) {\n                for (int j = i + 1; j <= x; ++j) {\n                    swap(order[x][i], order[x][j]);\n                    int s = solver.eval_from(x, order[x], order, pref, best_s - 1);\n                    if (s < best_s) {\n                        best_s = s;\n                        best_o = order[x];\n                    }\n                    swap(order[x][i], order[x][j]);\n                }\n            }\n            if (best_s < cur_cost) {\n                cur_cost = best_s;\n                order[x] = best_o;\n                solver.apply_change(x, order, pref);\n                improved = true;\n            }\n        }\n        if (!improved) break;\n    }\n    if (cur_cost < best_cost) {\n        best_cost = cur_cost;\n        best_order = order;\n    }\n\n    auto ops = solver.record(best_order);\n    cout << ops.size() << '\\n';\n    for (auto& [x1, y1, x2, y2] : ops) {\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\n/* ---------- globals ---------- */\nint D, N, M;\nint si, sj;\nchar obs[9][9];\nchar dist_arr[9][9];\npair<int,int> cells[81];\nint cid[9][9];\nconst int di[4] = {-1, 1, 0, 0};\nconst int dj[4] = {0, 0, -1, 1};\n\n/* AP DFS globals */\nint disc_g[9][9];\nint low_g[9][9];\nchar vis_g[9][9];\nchar ap_g[9][9];\nint timer_g;\n\n/* ---------- geometry ---------- */\ninline bool is_free(int i, int j, const char f[9][9]) {\n    if (i == si && j == sj) return true;\n    if (i < 0 || i >= D || j < 0 || j >= D) return false;\n    if (obs[i][j]) return false;\n    return !f[i][j];\n}\n\nvoid dfs_ap(int i, int j, int pi, int pj, const char f[9][9]) {\n    vis_g[i][j] = 1;\n    disc_g[i][j] = low_g[i][j] = ++timer_g;\n    int child_cnt = 0;\n    for (int dir = 0; dir < 4; ++dir) {\n        int ni = i + di[dir], nj = j + dj[dir];\n        if (!is_free(ni, nj, f)) continue;\n        if (ni == pi && nj == pj) continue;\n        if (!vis_g[ni][nj]) {\n            ++child_cnt;\n            dfs_ap(ni, nj, i, j, f);\n            low_g[i][j] = min(low_g[i][j], low_g[ni][nj]);\n            if (pi != -1 && low_g[ni][nj] >= disc_g[i][j]) ap_g[i][j] = 1;\n        } else {\n            low_g[i][j] = min(low_g[i][j], disc_g[ni][nj]);\n        }\n    }\n    if (pi == -1 && child_cnt > 1) ap_g[i][j] = 1;\n}\n\n/* returns count of safe cells, writes ids into safe_ids */\nint find_safe(const char f[9][9], int safe_ids[]) {\n    memset(vis_g, 0, sizeof(vis_g));\n    memset(ap_g,  0, sizeof(ap_g));\n    timer_g = 0;\n    dfs_ap(si, sj, -1, -1, f);\n    int cnt = 0;\n    for (int k = 0; k < M; ++k) {\n        int i = cells[k].first, j = cells[k].second;\n        if (f[i][j]) continue;\n        if (vis_g[i][j] && !ap_g[i][j]) safe_ids[cnt++] = k;\n    }\n    if (cnt == 0) {\n        for (int k = 0; k < M; ++k) {\n            int i = cells[k].first, j = cells[k].second;\n            if (!f[i][j] && vis_g[i][j]) safe_ids[cnt++] = k;\n        }\n    }\n    return cnt;\n}\n\ninline int degree_of(int id, const char f[9][9]) {\n    int i = cells[id].first, j = cells[id].second;\n    int deg = 0;\n    for (int dir = 0; dir < 4; ++dir) {\n        int ni = i + di[dir], nj = j + dj[dir];\n        if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n        if (obs[ni][nj]) continue;\n        if (ni == si && nj == sj) ++deg;\n        else if (!f[ni][nj]) ++deg;\n    }\n    return deg;\n}\n\n/* ---------- candidate generation (fast) ---------- */\nvoid generate_order(int policy, mt19937& rng, int out_ideal[]) {\n    char f[9][9] = {};\n    int elim[81];\n    int elim_cnt = 0;\n    int safe_ids[81];\n\n    for (int step = 0; step < M; ++step) {\n        int sc = find_safe(f, safe_ids);\n        int best_id = -1;\n\n        if (policy < 10) {          /* deterministic */\n            int best_score = INT_MIN;\n            for (int idx = 0; idx < sc; ++idx) {\n                int id = safe_ids[idx];\n                int i = cells[id].first, j = cells[id].second;\n                int d = dist_arr[i][j];\n                int deg = degree_of(id, f);\n                int score;\n                if (policy == 0) score = d * 1000 - deg;\n                else if (policy == 1) score = -deg * 1000 + d;\n                else if (policy == 2) score = d * 1000 + deg;\n                else if (policy == 3) score = -deg * 1000 - d;\n                else if (policy == 4) score = (deg == 1 ? 1000000 : 0) + d * 1000 - deg;\n                else if (policy == 5) score = (deg == 1 ? 1000000 : 0) - d * 1000 - deg;\n                else if (policy == 6) score = d * 100 - deg * 1000;\n                else if (policy == 7) score = -d * 1000 - deg;\n                else if (policy == 8) score = deg * 1000 + d;\n                else score = d * 1000 - deg * 10;\n                if (score > best_score) {\n                    best_score = score;\n                    best_id = id;\n                }\n            }\n        } else {                    /* fast random */\n            int r = (int)(rng() % (unsigned)sc);\n            best_id = safe_ids[r];\n        }\n\n        int bi = cells[best_id].first, bj = cells[best_id].second;\n        f[bi][bj] = 1;\n        elim[elim_cnt++] = best_id;\n    }\n    for (int i = 0; i < M; ++i) out_ideal[elim[i]] = M - 1 - i;\n}\n\n/* ---------- L1 future matching ---------- */\ninline int future_cost(const int rem_labs[], int L, const int rem_ideals[], int I, int skip_ide) {\n    int i = 0, j = 0, cost = 0;\n    while (i < L && j < I) {\n        if (rem_ideals[j] == skip_ide) { ++j; continue; }\n        cost += abs(rem_labs[i] - rem_ideals[j]);\n        ++i; ++j;\n    }\n    return cost;\n}\n\n/* ---------- evaluation of one candidate on one sequence ---------- */\nlong long evaluate(const int ideal[], const int seq[]) {\n    char f[9][9] = {};\n    int lab[9][9];\n    memset(lab, -1, sizeof(lab));\n    char seen[81] = {};\n    int safe_ids[81];\n    int rem_labs[81];\n    int rem_ideals[81];\n\n    for (int step = 0; step < M; ++step) {\n        int t = seq[step];\n        seen[t] = 1;\n        int sc = find_safe(f, safe_ids);\n\n        int lc = 0;\n        for (int l = 0; l < M; ++l) if (!seen[l]) rem_labs[lc++] = l;\n\n        int ic = 0;\n        for (int id = 0; id < M; ++id) {\n            int i = cells[id].first, j = cells[id].second;\n            if (!f[i][j]) rem_ideals[ic++] = ideal[id];\n        }\n        sort(rem_ideals, rem_ideals + ic);\n\n        int best_id = -1, best_cat = -1, best_cost = INT_MAX, best_deg = 100;\n        for (int idx = 0; idx < sc; ++idx) {\n            int id = safe_ids[idx];\n            int ide = ideal[id];\n            int cat;\n            if (ide == t) cat = 3;\n            else if (ide > t) cat = 2;\n            else if (seen[ide]) cat = 1;\n            else cat = 0;\n\n            int cost = abs(t - ide) + future_cost(rem_labs, lc, rem_ideals, ic, ide);\n            int deg = degree_of(id, f);\n            if (cat > best_cat ||\n                (cat == best_cat && cost < best_cost) ||\n                (cat == best_cat && cost == best_cost && deg < best_deg)) {\n                best_cat = cat; best_cost = cost; best_deg = deg; best_id = id;\n            }\n        }\n        int bi = cells[best_id].first, bj = cells[best_id].second;\n        f[bi][bj] = 1;\n        lab[bi][bj] = t;\n    }\n\n    /* greedy removal \u2013 entrance never queued */\n    char emp[9][9] = {};\n    emp[si][sj] = 1;\n    using T = tuple<int,int,int>;\n    priority_queue<T, vector<T>, greater<T>> pq;\n    char in_pq[9][9] = {};\n\n    for (int dir = 0; dir < 4; ++dir) {\n        int ni = si + di[dir], nj = sj + dj[dir];\n        if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n        if (obs[ni][nj]) continue;\n        pq.emplace(lab[ni][nj], ni, nj);\n        in_pq[ni][nj] = 1;\n    }\n\n    int rem_seq[81], rcnt = 0;\n    while (!pq.empty()) {\n        auto [v, i, j] = pq.top(); pq.pop();\n        rem_seq[rcnt++] = v;\n        emp[i][j] = 1;\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni == si && nj == sj) continue;\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obs[ni][nj]) continue;\n            if (emp[ni][nj]) continue;\n            if (in_pq[ni][nj]) continue;\n            pq.emplace(lab[ni][nj], ni, nj);\n            in_pq[ni][nj] = 1;\n        }\n    }\n\n    long long inv = 0;\n    for (int i = 0; i < rcnt; ++i)\n        for (int j = i + 1; j < rcnt; ++j)\n            if (rem_seq[i] > rem_seq[j]) ++inv;\n    return inv;\n}\n\n/*============================================================*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> D >> N;\n    si = 0; sj = (D - 1) / 2;\n    memset(obs, 0, sizeof(obs));\n    for (int k = 0; k < N; ++k) {\n        int r, c; cin >> r >> c;\n        obs[r][c] = 1;\n    }\n\n    /* BFS distances */\n    memset(dist_arr, -1, sizeof(dist_arr));\n    queue<pair<int,int>> q;\n    dist_arr[si][sj] = 0;\n    q.push({si, sj});\n    while (!q.empty()) {\n        auto [i, j] = q.front(); q.pop();\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obs[ni][nj]) continue;\n            if (dist_arr[ni][nj] != -1) continue;\n            dist_arr[ni][nj] = dist_arr[i][j] + 1;\n            q.push({ni, nj});\n        }\n    }\n\n    /* collect storage cells */\n    memset(cid, -1, sizeof(cid));\n    M = 0;\n    for (int i = 0; i < D; ++i)\n        for (int j = 0; j < D; ++j)\n            if (!(i == si && j == sj) && !obs[i][j]) {\n                cid[i][j] = M;\n                cells[M++] = {i, j};\n            }\n\n    /* ----- fast offline two-phase search ----- */\n    mt19937 rng(123456789);\n    const int NUM_CAND = 40;\n    const int PHASE1_SEQ = 5;\n    const int PHASE2_KEEP = 8;\n    const int PHASE2_SEQ = 10;\n\n    static int candidates[40][81];\n    long long score[40];\n    int seq[81];\n    iota(seq, seq + M, 0);\n\n    for (int pol = 0; pol < 10; ++pol) generate_order(pol, rng, candidates[pol]);\n    for (int rep = 10; rep < NUM_CAND; ++rep) generate_order(10, rng, candidates[rep]); /* pure random */\n\n    for (int idx = 0; idx < NUM_CAND; ++idx) score[idx] = 0;\n\n    for (int idx = 0; idx < NUM_CAND; ++idx) {\n        for (int s = 0; s < PHASE1_SEQ; ++s) {\n            shuffle(seq, seq + M, rng);\n            score[idx] += evaluate(candidates[idx], seq);\n        }\n    }\n\n    /* select top PHASE2_KEEP */\n    vector<int> ord(NUM_CAND);\n    iota(ord.begin(), ord.end(), 0);\n    nth_element(ord.begin(), ord.begin() + PHASE2_KEEP, ord.end(),\n                [&](int a, int b){ return score[a] < score[b]; });\n    ord.resize(PHASE2_KEEP);\n    sort(ord.begin(), ord.end(), [&](int a, int b){ return score[a] < score[b]; });\n\n    long long best_score = LLONG_MAX;\n    int best_idx = ord[0];\n    for (int idx : ord) {\n        long long tot = score[idx];\n        for (int s = 0; s < PHASE2_SEQ; ++s) {\n            shuffle(seq, seq + M, rng);\n            tot += evaluate(candidates[idx], seq);\n        }\n        if (tot < best_score) {\n            best_score = tot;\n            best_idx = idx;\n        }\n    }\n\n    static int ideal[81];\n    for (int i = 0; i < M; ++i) ideal[i] = candidates[best_idx][i];\n    /* ---------------------------------------- */\n\n    /* ----- online placement ----- */\n    char filled[9][9] = {};\n    int label_at[9][9];\n    memset(label_at, -1, sizeof(label_at));\n    char seen[81] = {};\n    int safe_ids[81];\n    int rem_labs[81];\n    int rem_ideals[81];\n\n    for (int step = 0; step < M; ++step) {\n        int t; cin >> t;\n        seen[t] = 1;\n        int sc = find_safe(filled, safe_ids);\n\n        int lc = 0;\n        for (int l = 0; l < M; ++l) if (!seen[l]) rem_labs[lc++] = l;\n\n        int ic = 0;\n        for (int id = 0; id < M; ++id) {\n            int i = cells[id].first, j = cells[id].second;\n            if (!filled[i][j]) rem_ideals[ic++] = ideal[id];\n        }\n        sort(rem_ideals, rem_ideals + ic);\n\n        int best_id = -1, best_cat = -1, best_cost = INT_MAX, best_deg = 100;\n        for (int idx = 0; idx < sc; ++idx) {\n            int id = safe_ids[idx];\n            int ide = ideal[id];\n            int cat;\n            if (ide == t) cat = 3;\n            else if (ide > t) cat = 2;\n            else if (seen[ide]) cat = 1;\n            else cat = 0;\n\n            int cost = abs(t - ide) + future_cost(rem_labs, lc, rem_ideals, ic, ide);\n            int deg = degree_of(id, filled);\n            if (cat > best_cat ||\n                (cat == best_cat && cost < best_cost) ||\n                (cat == best_cat && cost == best_cost && deg < best_deg)) {\n                best_cat = cat; best_cost = cost; best_deg = deg; best_id = id;\n            }\n        }\n        int bi = cells[best_id].first, bj = cells[best_id].second;\n        filled[bi][bj] = 1;\n        label_at[bi][bj] = t;\n        cout << bi << ' ' << bj << '\\n' << flush;\n    }\n\n    /* ----- output greedy removal order ----- */\n    char emp[9][9] = {};\n    emp[si][sj] = 1;\n    using T = tuple<int,int,int>;\n    priority_queue<T, vector<T>, greater<T>> pq;\n    char in_pq[9][9] = {};\n\n    for (int dir = 0; dir < 4; ++dir) {\n        int ni = si + di[dir], nj = sj + dj[dir];\n        if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n        if (obs[ni][nj]) continue;\n        pq.emplace(label_at[ni][nj], ni, nj);\n        in_pq[ni][nj] = 1;\n    }\n\n    while (!pq.empty()) {\n        auto [v, i, j] = pq.top(); pq.pop();\n        cout << i << ' ' << j << '\\n';\n        emp[i][j] = 1;\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ni == si && nj == sj) continue;\n            if (ni < 0 || ni >= D || nj < 0 || nj >= D) continue;\n            if (obs[ni][nj]) continue;\n            if (emp[ni][nj]) continue;\n            if (in_pq[ni][nj]) continue;\n            pq.emplace(label_at[ni][nj], ni, nj);\n            in_pq[ni][nj] = 1;\n        }\n    }\n    cout << flush;\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nint n, m;\nint orig_g[50][50];\nint need[101][101];\nbool isB[101];\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\n\ninline bool ins(int i, int j) { return 0 <= i && i < n && 0 <= j && j < n; }\n\nchrono::steady_clock::time_point T0;\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - T0).count();\n}\n\nstruct State {\n    int g[50][50];\n    int sz[101];\n    int adjCnt[101][101];\n    int vis[50][50];\n    int visToken;\n    mt19937 rng;\n    pair<short, short> qu[2500];\n\n    State(unsigned seed) : visToken(1), rng(seed) {\n        memset(vis, 0, sizeof(vis));\n    }\n\n    void recompute() {\n        memset(sz, 0, sizeof(sz));\n        memset(adjCnt, 0, sizeof(adjCnt));\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j) {\n                int c = g[i][j];\n                ++sz[c];\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    if (ins(ni, nj)) {\n                        int d = g[ni][nj];\n                        if (c != d) ++adjCnt[c][d];\n                    } else {\n                        ++adjCnt[c][0];\n                    }\n                }\n            }\n    }\n\n    void init() {\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                g[i][j] = orig_g[i][j];\n        recompute();\n    }\n\n    vector<vector<int>> get_grid() const {\n        vector<vector<int>> res(n, vector<int>(n));\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                res[i][j] = g[i][j];\n        return res;\n    }\n\n    bool connectedWithout(int i, int j, int c, int szc, int same_c) {\n        if (szc <= 1) return false;\n        if (szc == 2) return true;\n        if (same_c == 0) return false;\n        if (same_c == 1) return true;\n\n        int si = -1, sj = -1;\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            if (ins(ni, nj) && g[ni][nj] == c) {\n                si = ni; sj = nj; break;\n            }\n        }\n        if (si == -1) return false;\n\n        int qb = 0, qe = 0;\n        qu[qe++] = {(short)si, (short)sj};\n        vis[si][sj] = visToken;\n        int cnt = 1;\n        while (qb < qe) {\n            int x = qu[qb].first;\n            int y = qu[qb].second;\n            ++qb;\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + di[dir], ny = y + dj[dir];\n                if (!ins(nx, ny)) continue;\n                if (g[nx][ny] != c) continue;\n                if (nx == i && ny == j) continue;\n                if (vis[nx][ny] == visToken) continue;\n                vis[nx][ny] = visToken;\n                if (++cnt == szc - 1) {\n                    ++visToken;\n                    return true;\n                }\n                qu[qe++] = {(short)nx, (short)ny};\n            }\n        }\n        ++visToken;\n        return false;\n    }\n\n    inline void applyRecolor(int i, int j, int d) {\n        int c = g[i][j];\n        for (int dir = 0; dir < 4; ++dir) {\n            int ni = i + di[dir], nj = j + dj[dir];\n            int e = ins(ni, nj) ? g[ni][nj] : 0;\n            if (e != c) {\n                --adjCnt[c][e];\n                --adjCnt[e][c];\n            }\n            if (e != d) {\n                ++adjCnt[d][e];\n                ++adjCnt[e][d];\n            }\n        }\n        g[i][j] = d;\n        --sz[c];\n        ++sz[d];\n    }\n\n    int solve(int heuristic, double deadline) {\n        for (int iter = 0; iter < 300; ++iter) {\n            if ((iter & 15) == 0 && elapsed() > deadline) break;\n            bool changed = false;\n\n            vector<pair<short, short>> order;\n            order.reserve(2500);\n            for (int i = 0; i < n; ++i)\n                for (int j = 0; j < n; ++j)\n                    if (g[i][j] > 0 && sz[g[i][j]] > 1)\n                        order.emplace_back(i, j);\n\n            shuffle(order.begin(), order.end(), rng);\n\n            for (auto [i, j] : order) {\n                int c = g[i][j];\n                if (c == 0 || sz[c] <= 1) continue;\n\n                int neigh[4];\n                int same_c = 0;\n                int contrib_c[101] = {};\n                bool hasZero = false;\n                bool isBorder = (i == 0 || i == n - 1 || j == 0 || j == n - 1);\n                for (int dir = 0; dir < 4; ++dir) {\n                    int ni = i + di[dir], nj = j + dj[dir];\n                    int e = ins(ni, nj) ? g[ni][nj] : 0;\n                    neigh[dir] = e;\n                    if (e == c) ++same_c;\n                    else {\n                        ++contrib_c[e];\n                        if (e == 0) hasZero = true;\n                    }\n                }\n\n                // try delete\n                if (isB[c] && (isBorder || hasZero)) {\n                    bool ok = true;\n                    for (int e = 1; e <= m; ++e)\n                        if (contrib_c[e] && !isB[e]) { ok = false; break; }\n                    if (ok) {\n                        for (int e = 0; e <= m; ++e) {\n                            if (contrib_c[e] == 0) continue;\n                            if (!need[c][e]) continue;\n                            int rem = adjCnt[c][e] - contrib_c[e];\n                            if (e == 0) rem += same_c;\n                            if (rem <= 0) { ok = false; break; }\n                        }\n                    }\n                    if (ok) {\n                        if (same_c == 1 || connectedWithout(i, j, c, sz[c], same_c)) {\n                            applyRecolor(i, j, 0);\n                            changed = true;\n                            continue;\n                        }\n                    }\n                }\n\n                // try recolor (connectivity test reused for all candidates)\n                bool conn = (same_c == 1) || connectedWithout(i, j, c, sz[c], same_c);\n                if (!conn) continue;\n\n                int bestD = -1;\n                int bestScore = INT_MIN;\n\n                for (int dir = 0; dir < 4; ++dir) {\n                    int d = neigh[dir];\n                    if (d == 0 || d == c) continue;\n                    if (contrib_c[0] > 0 && !need[d][0]) continue;\n\n                    bool ok = true;\n                    for (int k = 0; k < 4; ++k) {\n                        int e = neigh[k];\n                        if (e == d) continue;\n                        if (!need[d][e]) { ok = false; break; }\n                    }\n                    if (!ok) continue;\n\n                    for (int e = 0; e <= m; ++e) {\n                        if (contrib_c[e] == 0) continue;\n                        if (!need[c][e]) continue;\n                        int rem = adjCnt[c][e] - contrib_c[e];\n                        if (e == d) rem += same_c;\n                        if (rem <= 0) { ok = false; break; }\n                    }\n                    if (!ok) continue;\n\n                    int score;\n                    switch (heuristic % 4) {\n                        case 0: score = -sz[d]; break;\n                        case 1: score = sz[d]; break;\n                        case 2: score = int(rng() & 0x7FFF); break;\n                        case 3: score = -sz[d] + (isB[d] ? 200 : 0); break;\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestD = d;\n                    }\n                }\n\n                if (bestD != -1) {\n                    applyRecolor(i, j, bestD);\n                    changed = true;\n                }\n            }\n\n            if (!changed) break;\n        }\n        return sz[0];\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> n >> m;\n    for (int i = 0; i < n; ++i)\n        for (int j = 0; j < n; ++j)\n            cin >> orig_g[i][j];\n\n    memset(need, 0, sizeof(need));\n    memset(isB, 0, sizeof(isB));\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            int c = orig_g[i][j];\n            for (int dir = 0; dir < 4; ++dir) {\n                int ni = i + di[dir], nj = j + dj[dir];\n                if (ins(ni, nj)) {\n                    int d = orig_g[ni][nj];\n                    if (c != d) need[c][d] = 1;\n                } else {\n                    need[c][0] = 1;\n                }\n            }\n        }\n    }\n    for (int c = 1; c <= m; ++c) isB[c] = need[c][0];\n    for (int c = 1; c <= m; ++c) need[0][c] = isB[c];\n\n    T0 = chrono::steady_clock::now();\n    const double DEADLINE = 1.98;\n\n    int best_zero = -1;\n    vector<vector<int>> best_grid;\n\n    {\n        State s(1234567u);\n        s.init();\n        int z = s.solve(0, DEADLINE);\n        if (z > best_zero) {\n            best_zero = z;\n            best_grid = s.get_grid();\n        }\n    }\n\n    for (int trial = 0; elapsed() < 1.96; ++trial) {\n        State s((unsigned)(trial + 1000));\n        s.init();\n        int z = s.solve(trial % 4, DEADLINE);\n        if (z > best_zero) {\n            best_zero = z;\n            best_grid = s.get_grid();\n        }\n    }\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (j) cout << ' ';\n            cout << best_grid[i][j];\n        }\n        cout << '\\n';\n    }\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) { p.resize(n); sz.assign(n, 1); iota(p.begin(), p.end(), 0); }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    void unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a != b) { if (sz[a] < sz[b]) swap(a, b); p[b] = a; sz[a] += sz[b]; }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, D, Q;\n    cin >> N >> D >> Q;\n    \n    vector<bitset<128>> gt(N);\n    vector<vector<char>> direct_done(N, vector<char>(N, 0));\n    for (int i = 0; i < N; ++i) direct_done[i][i] = 1;\n    DSU dsu(N);\n    \n    const double LAMBDA = 1e-5;\n    double M_cap = 100000.0 * N / D;\n    vector<double> H(N + 1, 0.0);\n    for (int i = 1; i <= N; ++i) H[i] = H[i - 1] + 1.0 / i;\n    vector<long long> est(N, 100000);\n    \n    auto recompute_est = [&]() {\n        vector<int> low(N), high(N);\n        for (int i = 0; i < N; ++i) low[i] = (int)gt[i].count();\n        for (int i = 0; i < N; ++i) {\n            high[i] = 0;\n            for (int k = 0; k < N; ++k) if (gt[k].test(i)) ++high[i];\n        }\n        \n        vector<pair<double, int>> ord;\n        for (int i = 0; i < N; ++i) {\n            if (dsu.find(i) != i) continue;\n            double rank = (high[i] + (N - 1 - low[i])) / 2.0;\n            ord.emplace_back(rank, i);\n        }\n        sort(ord.begin(), ord.end(), greater<pair<double,int>>());\n        \n        int idx = 0;\n        for (auto& [rank, rep] : ord) {\n            int s = dsu.sz[rep];\n            double avg_idx = idx + (s - 1) / 2.0;\n            double val = (H[N] - H[N - 1 - (int)llround(avg_idx)]) / LAMBDA;\n            if (val > M_cap) val = M_cap;\n            long long w = max(1LL, (long long)llround(val));\n            for (int j = 0; j < N; ++j) {\n                if (dsu.find(j) == rep) est[j] = w;\n            }\n            idx += s;\n        }\n    };\n    \n    auto calc_obj = [&](const vector<long long>& gsum) -> long long {\n        long long s = 0;\n        for (long long x : gsum) s += x * x;\n        return s;\n    };\n    \n    auto improve_partition = [&](vector<int>& as) {\n        vector<long long> gsum(D, 0);\n        for (int i = 0; i < N; ++i) gsum[as[i]] += est[i];\n        vector<vector<int>> groups(D);\n        for (int i = 0; i < N; ++i) groups[as[i]].push_back(i);\n        \n        for (int iter = 0; iter < 15; ++iter) {\n            long long bestDelta = 0;\n            int best_type = 0;\n            int best_i = -1, best_j = -1, best_to = -1;\n            \n            for (int i = 0; i < N; ++i) {\n                int a = as[i];\n                for (int b = 0; b < D; ++b) {\n                    if (a == b) continue;\n                    long long sa = gsum[a], sb = gsum[b], wi = est[i];\n                    long long nsa = sa - wi, nsb = sb + wi;\n                    long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        best_type = 2;\n                        best_i = i; best_to = b;\n                    }\n                }\n            }\n            \n            for (int i = 0; i < N; ++i) {\n                int a = as[i];\n                for (int j = i + 1; j < N; ++j) {\n                    int b = as[j];\n                    if (a == b) continue;\n                    long long sa = gsum[a], sb = gsum[b];\n                    long long wi = est[i], wj = est[j];\n                    long long nsa = sa - wi + wj;\n                    long long nsb = sb - wj + wi;\n                    long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        best_type = 1;\n                        best_i = i; best_j = j;\n                    }\n                }\n            }\n            \n            if (bestDelta >= 0) break;\n            \n            if (best_type == 2) {\n                int i = best_i, a = as[i], b = best_to;\n                as[i] = b;\n                gsum[a] -= est[i];\n                gsum[b] += est[i];\n                for (size_t k = 0; k < groups[a].size(); ++k) {\n                    if (groups[a][k] == i) {\n                        groups[a][k] = groups[a].back();\n                        groups[a].pop_back();\n                        break;\n                    }\n                }\n                groups[b].push_back(i);\n            } else {\n                int i = best_i, j = best_j;\n                int a = as[i], b = as[j];\n                as[i] = b; as[j] = a;\n                gsum[a] = gsum[a] - est[i] + est[j];\n                gsum[b] = gsum[b] - est[j] + est[i];\n                for (auto& x : groups[a]) if (x == i) { x = j; break; }\n                for (auto& x : groups[b]) if (x == j) { x = i; break; }\n            }\n        }\n    };\n    \n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    \n    vector<int> query_assign(N);\n    for (int i = 0; i < N; ++i) query_assign[i] = i % D;\n    \n    for (int q = 0; q < Q; ++q) {\n        if (q % 50 == 0 || q >= Q - 100) {\n            recompute_est();\n            improve_partition(query_assign);\n        }\n        \n        vector<int> direct_deg(N, 0);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (direct_done[i][j]) ++direct_deg[i];\n        \n        vector<int> low(N), high(N);\n        for (int i = 0; i < N; ++i) low[i] = (int)gt[i].count();\n        for (int i = 0; i < N; ++i) {\n            high[i] = 0;\n            for (int k = 0; k < N; ++k) if (gt[k].test(i)) ++high[i];\n        }\n        \n        int best_i = -1, best_j = -1;\n        double best_score = 1e300;\n        \n        for (int i = 0; i < N; ++i) {\n            for (int j = i + 1; j < N; ++j) {\n                if (direct_done[i][j]) continue;\n                if (dsu.find(i) == dsu.find(j)) continue;\n                if (gt[i].test(j) || gt[j].test(i)) continue;\n                \n                double rank_i = (high[i] + (N - 1 - low[i])) / 2.0;\n                double rank_j = (high[j] + (N - 1 - low[j])) / 2.0;\n                double diff = abs(rank_i - rank_j);\n                int deg = direct_deg[i] + direct_deg[j];\n                double cross = (query_assign[i] != query_assign[j]) ? 0.0 : 1000.0;\n                double score = diff * 5.0 + deg * 0.5 + cross;\n                \n                if (score < best_score) {\n                    best_score = score;\n                    best_i = i; best_j = j;\n                }\n            }\n        }\n        \n        if (best_i == -1) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (direct_done[i][j]) continue;\n                    if (dsu.find(i) == dsu.find(j)) continue;\n                    if (gt[i].test(j) || gt[j].test(i)) continue;\n                    if (query_assign[i] != query_assign[j]) {\n                        best_i = i; best_j = j;\n                        break;\n                    }\n                }\n                if (best_i != -1) break;\n            }\n        }\n        \n        if (best_i == -1) {\n            for (int i = 0; i < N; ++i) {\n                for (int j = i + 1; j < N; ++j) {\n                    if (direct_done[i][j]) continue;\n                    if (dsu.find(i) == dsu.find(j)) continue;\n                    if (gt[i].test(j) || gt[j].test(i)) continue;\n                    best_i = i; best_j = j;\n                    break;\n                }\n                if (best_i != -1) break;\n            }\n        }\n        \n        if (best_i == -1) {\n            best_i = 0; best_j = 1;\n        }\n        \n        cout << \"1 1 \" << best_i << \" \" << best_j << '\\n' << flush;\n        string res;\n        cin >> res;\n        \n        direct_done[best_i][best_j] = direct_done[best_j][best_i] = 1;\n        if (res == \">\") {\n            gt[best_i].set(best_j);\n        } else if (res == \"<\") {\n            gt[best_j].set(best_i);\n        } else {\n            dsu.unite(best_i, best_j);\n            for (int k = 0; k < N; ++k) {\n                if (k == best_i || k == best_j) continue;\n                bool ik = gt[best_i].test(k);\n                bool jk = gt[best_j].test(k);\n                bool ki = gt[k].test(best_i);\n                bool kj = gt[k].test(best_j);\n                if (ik || jk) {\n                    gt[best_i].set(k);\n                    gt[best_j].set(k);\n                }\n                if (ki || kj) {\n                    gt[k].set(best_i);\n                    gt[k].set(best_j);\n                }\n            }\n        }\n        \n        for (int rep = 0; rep < 3; ++rep) {\n            bool changed = false;\n            for (int k = 0; k < N; ++k) {\n                for (int i = 0; i < N; ++i) {\n                    if (gt[i].test(k)) {\n                        auto old = gt[i];\n                        gt[i] |= gt[k];\n                        if (gt[i] != old) changed = true;\n                    }\n                }\n            }\n            if (!changed) break;\n        }\n    }\n    \n    recompute_est();\n    \n    vector<vector<int>> candidates;\n    \n    {\n        vector<int> as(N);\n        vector<pair<long long, int>> ord;\n        for (int i = 0; i < N; ++i) ord.emplace_back(est[i], i);\n        sort(ord.begin(), ord.end(), greater<pair<long long,int>>());\n        vector<long long> gsum(D, 0);\n        for (auto& [w, i] : ord) {\n            int best = 0;\n            for (int g = 1; g < D; ++g) if (gsum[g] < gsum[best]) best = g;\n            as[i] = best;\n            gsum[best] += w;\n        }\n        improve_partition(as);\n        candidates.push_back(as);\n    }\n    \n    {\n        vector<int> as(N);\n        vector<int> low(N), high(N);\n        for (int i = 0; i < N; ++i) low[i] = (int)gt[i].count();\n        for (int i = 0; i < N; ++i) {\n            high[i] = 0;\n            for (int k = 0; k < N; ++k) if (gt[k].test(i)) ++high[i];\n        }\n        vector<pair<double, int>> ord;\n        for (int i = 0; i < N; ++i) {\n            double rank = (high[i] + (N - 1 - low[i])) / 2.0;\n            ord.emplace_back(rank, i);\n        }\n        sort(ord.begin(), ord.end(), greater<pair<double,int>>());\n        for (int idx = 0; idx < N; ++idx) as[ord[idx].second] = idx % D;\n        improve_partition(as);\n        candidates.push_back(as);\n    }\n    \n    improve_partition(query_assign);\n    candidates.push_back(query_assign);\n    \n    for (int rep = 0; rep < 3; ++rep) {\n        vector<int> as(N);\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), rng);\n        vector<long long> gsum(D, 0);\n        for (int i : ord) {\n            int best = 0;\n            for (int g = 1; g < D; ++g) if (gsum[g] < gsum[best]) best = g;\n            as[i] = best;\n            gsum[best] += est[i];\n        }\n        improve_partition(as);\n        candidates.push_back(as);\n    }\n    \n    long long bestObj = LLONG_MAX;\n    vector<int> bestAssign;\n    for (auto& as : candidates) {\n        vector<long long> gsum(D, 0);\n        for (int i = 0; i < N; ++i) gsum[as[i]] += est[i];\n        long long obj = calc_obj(gsum);\n        if (obj < bestObj) {\n            bestObj = obj;\n            bestAssign = as;\n        }\n    }\n    \n    auto start_time = chrono::steady_clock::now();\n    auto elapsed_ms = [&]() {\n        return chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_time).count();\n    };\n    \n    auto run_sa = [&](vector<int> as, vector<long long> gs, int max_iters, double initT, double cool) {\n        vector<vector<int>> groups(D);\n        vector<int> pos(N);\n        for (int i = 0; i < N; ++i) {\n            pos[i] = groups[as[i]].size();\n            groups[as[i]].push_back(i);\n        }\n        \n        double T = initT;\n        for (int iter = 0; iter < max_iters; ++iter) {\n            if (elapsed_ms() > 1800) break;\n            T *= cool;\n            int type = uniform_int_distribution<int>(0, 1)(rng);\n            int a = uniform_int_distribution<int>(0, D - 1)(rng);\n            int b = uniform_int_distribution<int>(0, D - 2)(rng);\n            if (b >= a) ++b;\n            \n            if (groups[a].empty() || groups[b].empty()) continue;\n            \n            if (type == 0) {\n                int idx = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n                int i = groups[a][idx];\n                long long sa = gs[a], sb = gs[b];\n                long long wi = est[i];\n                long long nsa = sa - wi, nsb = sb + wi;\n                long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                bool accept = delta < 0;\n                if (!accept) {\n                    if (uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) accept = true;\n                }\n                if (accept) {\n                    groups[a][idx] = groups[a].back();\n                    pos[groups[a].back()] = idx;\n                    groups[a].pop_back();\n                    pos[i] = groups[b].size();\n                    groups[b].push_back(i);\n                    as[i] = b;\n                    gs[a] = nsa; gs[b] = nsb;\n                    long long obj = calc_obj(gs);\n                    if (obj < bestObj) {\n                        bestObj = obj;\n                        bestAssign = as;\n                    }\n                }\n            } else {\n                int idx1 = uniform_int_distribution<int>(0, (int)groups[a].size() - 1)(rng);\n                int idx2 = uniform_int_distribution<int>(0, (int)groups[b].size() - 1)(rng);\n                int i = groups[a][idx1], j = groups[b][idx2];\n                long long sa = gs[a], sb = gs[b];\n                long long wi = est[i], wj = est[j];\n                long long nsa = sa - wi + wj, nsb = sb - wj + wi;\n                long long delta = (nsa * nsa + nsb * nsb) - (sa * sa + sb * sb);\n                bool accept = delta < 0;\n                if (!accept) {\n                    if (uniform_real_distribution<double>(0.0, 1.0)(rng) < exp(-(double)delta / T)) accept = true;\n                }\n                if (accept) {\n                    swap(groups[a][idx1], groups[b][idx2]);\n                    swap(pos[i], pos[j]);\n                    as[i] = b; as[j] = a;\n                    gs[a] = nsa; gs[b] = nsb;\n                    long long obj = calc_obj(gs);\n                    if (obj < bestObj) {\n                        bestObj = obj;\n                        bestAssign = as;\n                    }\n                }\n            }\n        }\n    };\n    \n    vector<long long> gsum(D, 0);\n    for (int i = 0; i < N; ++i) gsum[bestAssign[i]] += est[i];\n    run_sa(bestAssign, gsum, 500000, 1e12, 0.99997);\n    \n    for (int rep = 0; rep < 5; ++rep) {\n        if (elapsed_ms() > 1800) break;\n        auto as = bestAssign;\n        auto gs = vector<long long>(D, 0);\n        for (int i = 0; i < N; ++i) gs[as[i]] += est[i];\n        for (int k = 0; k < N / 15; ++k) {\n            int i = uniform_int_distribution<int>(0, N - 1)(rng);\n            int b = uniform_int_distribution<int>(0, D - 1)(rng);\n            int a = as[i];\n            if (a != b) {\n                gs[a] -= est[i];\n                gs[b] += est[i];\n                as[i] = b;\n            }\n        }\n        run_sa(as, gs, 150000, 5e11, 0.999965);\n    }\n    \n    improve_partition(bestAssign);\n    \n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << bestAssign[i];\n    }\n    cout << endl;\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int MAXN = 200;\nconst int MAXM = 10;\n\nint n, m;\n\nstruct Result {\n    int energy = INT_MAX;\n    vector<pair<int,int>> ops;\n};\n\ninline void recomp(int mn[MAXM], int a[MAXM][MAXN], int sz[MAXM], int s) {\n    if (sz[s] == 0) mn[s] = INT_MAX;\n    else {\n        mn[s] = INT_MAX;\n        for (int i = 0; i < sz[s]; ++i) mn[s] = min(mn[s], a[s][i]);\n    }\n}\n\n/* ---------- classic greedy (10\u00d710 grid) ---------- */\nvoid simulate_greedy(const int init_a[MAXM][MAXN], const int init_sz[MAXM],\n                     int bulkVar, int peelMode, Result &out) {\n    int a[MAXM][MAXN];\n    int sz[MAXM];\n    int pos[MAXN + 1];\n    int mn[MAXM];\n    memcpy(a, init_a, sizeof(int) * MAXM * MAXN);\n    memcpy(sz, init_sz, sizeof(int) * MAXM);\n\n    for (int i = 0; i < m; ++i) {\n        mn[i] = INT_MAX;\n        for (int j = 0; j < sz[i]; ++j) {\n            int v = a[i][j];\n            pos[v] = i;\n            mn[i] = min(mn[i], v);\n        }\n    }\n\n    Result res;\n    res.ops.reserve(5000);\n\n    for (int v = 1; v <= n; ++v) {\n        if ((int)res.ops.size() >= 5000) { res.energy = INT_MAX; return; }\n\n        int s = pos[v];\n        int vp = 0;\n        while (vp < sz[s] && a[s][vp] != v) ++vp;\n\n        /* ---- peeling ---- */\n        if (peelMode != 0) {\n            while ((int)res.ops.size() < 5000) {\n                if (sz[s] == 0 || vp == sz[s] - 1) break;\n                int tailSz = sz[s] - vp - 1;\n                if (tailSz <= 0) break;\n\n                int x = a[s][sz[s] - 1];\n                int mnTail = INT_MAX, mxTail = 0;\n                for (int i = vp + 1; i < sz[s]; ++i) {\n                    mnTail = min(mnTail, a[s][i]);\n                    mxTail = max(mxTail, a[s][i]);\n                }\n                if (x == mnTail) break;\n\n                bool hasSafeBulk = false;\n                for (int d = 0; d < m; ++d) if (d != s) {\n                    if (sz[d] == 0 || mn[d] >= mxTail) { hasSafeBulk = true; break; }\n                }\n\n                bool should = false;\n                if (peelMode == 1) { if (!hasSafeBulk) should = true; }\n                else if (peelMode == 2) { if (!hasSafeBulk && tailSz >= 3) should = true; }\n                else if (peelMode == 3) { if (tailSz >= 2) should = true; }\n                else if (peelMode == 4) { if (tailSz >= 3) should = true; }\n                else if (peelMode == 5) { if (!hasSafeBulk) should = true; }\n                else if (peelMode == 6) { if (tailSz >= 2) should = true; }\n                else if (peelMode == 7) { should = true; }\n                else if (peelMode == 8) { if (tailSz >= 2 && x <= v + 5) should = true; }\n                else if (peelMode == 9) { if (!hasSafeBulk) should = true; else if (tailSz >= 2 && x <= v + 3) should = true; }\n\n                if (!should) break;\n\n                int best_d = -1, best_mn = INT_MAX, empty_d = -1;\n                for (int d = 0; d < m; ++d) if (d != s) {\n                    if (sz[d] == 0) { if (empty_d == -1) empty_d = d; }\n                    else if (mn[d] > x) {\n                        if (mn[d] < best_mn) { best_mn = mn[d]; best_d = d; }\n                    }\n                }\n\n                int d = -1;\n                if (peelMode == 5 || peelMode == 6 || peelMode == 8) {\n                    if (empty_d != -1) d = empty_d; else break;\n                } else {\n                    if (empty_d != -1) d = empty_d;\n                    else if (best_d != -1) d = best_d;\n                    else break;\n                }\n\n                res.ops.emplace_back(x, d + 1);\n                res.energy += 2;\n                a[d][sz[d]++] = x;\n                pos[x] = d;\n                --sz[s];\n                recomp(mn, a, sz, d);\n                vp = 0; while (vp < sz[s] && a[s][vp] != v) ++vp;\n            }\n        }\n\n        if ((int)res.ops.size() >= 5000) { res.energy = INT_MAX; return; }\n\n        vp = 0; while (vp < sz[s] && a[s][vp] != v) ++vp;\n        if (vp == sz[s] - 1) {\n            res.ops.emplace_back(v, 0);\n            --sz[s]; pos[v] = -1;\n            recomp(mn, a, sz, s);\n            continue;\n        }\n\n        int w = a[s][vp + 1];\n        int k = sz[s] - vp - 1;\n        int mxT = 0;\n        for (int i = vp + 1; i < sz[s]; ++i) mxT = max(mxT, a[s][i]);\n\n        tuple<int,int,int,int> bestSc = {INT_MAX, INT_MAX, INT_MAX, INT_MAX};\n        int best_d = -1;\n        for (int d = 0; d < m; ++d) if (d != s) {\n            tuple<int,int,int,int> sc;\n            if (sz[d] == 0) {\n                if (bulkVar == 2 || bulkVar == 7 || bulkVar == 9) sc = make_tuple(0, 0, 0, 0);\n                else                                         sc = make_tuple(1, 0, 0, 0);\n            } else if (mn[d] >= mxT) {\n                if (bulkVar == 0)       sc = make_tuple(0, a[d][sz[d]-1], 0, 0);\n                else if (bulkVar == 1 || bulkVar == 3 || bulkVar == 4 || bulkVar == 8)\n                                        sc = make_tuple(0, mn[d], 0, 0);\n                else if (bulkVar == 5)  sc = make_tuple(0, sz[d], mn[d], 0);\n                else if (bulkVar == 6 || bulkVar == 7)\n                                        sc = make_tuple(0, -mn[d], 0, 0);\n                else if (bulkVar == 9)  sc = make_tuple(0, -mn[d], 0, 0);\n                else                    sc = make_tuple(0, mn[d], 0, 0);\n            } else {\n                int invc = 0, blockers = 0;\n                for (int i = vp + 1; i < sz[s]; ++i) {\n                    int t = a[s][i];\n                    if (t > mn[d]) ++blockers;\n                    for (int j = 0; j < sz[d]; ++j) if (a[d][j] < t) ++invc;\n                }\n                if (bulkVar == 3)       sc = make_tuple(2, blockers, -mn[d], 0);\n                else if (bulkVar == 4)  sc = make_tuple(2, blockers, invc, -mn[d]);\n                else if (bulkVar == 8)  sc = make_tuple(2, invc + blockers, -mn[d], 0);\n                else                    sc = make_tuple(2, invc, -mn[d], 0);\n            }\n            if (sc < bestSc) { bestSc = sc; best_d = d; }\n        }\n\n        res.ops.emplace_back(w, best_d + 1);\n        res.energy += k + 1;\n        for (int i = vp + 1; i < sz[s]; ++i) {\n            int t = a[s][i];\n            a[best_d][sz[best_d]++] = t;\n            pos[t] = best_d;\n        }\n        sz[s] = vp;\n        pos[v] = -1;\n        recomp(mn, a, sz, s);\n        recomp(mn, a, sz, best_d);\n        res.ops.emplace_back(v, 0);\n    }\n\n    if (res.energy < out.energy && (int)res.ops.size() <= 5000) {\n        out = std::move(res);\n    }\n}\n\n/* ---------- greedy rollout ---------- */\nint rollout(int a[MAXM][MAXN], int sz[MAXM], int pos[MAXN+1], int mn[MAXM], int start_v, int mode) {\n    int energy = 0;\n    for (int v = start_v; v <= n; ++v) {\n        int s = pos[v];\n        int vp = 0;\n        while (vp < sz[s] && a[s][vp] != v) ++vp;\n\n        if (vp == sz[s] - 1) {\n            sz[s] = vp;\n            pos[v] = -1;\n            recomp(mn, a, sz, s);\n            continue;\n        }\n\n        int k = sz[s] - vp - 1;\n        int mxT = 0;\n        for (int i = vp + 1; i < sz[s]; ++i) mxT = max(mxT, a[s][i]);\n\n        int best_d = -1;\n        tuple<int,int,int> best_sc = {INT_MAX, INT_MAX, INT_MAX};\n        for (int d = 0; d < m; ++d) if (d != s) {\n            tuple<int,int,int> sc;\n            if (sz[d] == 0) {\n                sc = make_tuple(1, 0, 0);\n            } else if (mn[d] >= mxT) {\n                sc = make_tuple(0, mn[d], 0);\n            } else {\n                if (mode == 0) { // exact cross inversions\n                    int cross = 0;\n                    for (int i = vp + 1; i < sz[s]; ++i)\n                        for (int j = 0; j < sz[d]; ++j)\n                            if (a[d][j] < a[s][i]) ++cross;\n                    sc = make_tuple(2, cross, -mn[d]);\n                } else if (mode == 1) { // blockers * 1\n                    int blockers = 0;\n                    for (int i = vp + 1; i < sz[s]; ++i)\n                        if (a[s][i] > mn[d]) ++blockers;\n                    sc = make_tuple(2, blockers, -mn[d]);\n                } else { // blockers * 2\n                    int blockers = 0;\n                    for (int i = vp + 1; i < sz[s]; ++i)\n                        if (a[s][i] > mn[d]) ++blockers;\n                    sc = make_tuple(2, blockers * 2, -mn[d]);\n                }\n            }\n            if (sc < best_sc) { best_sc = sc; best_d = d; }\n        }\n\n        energy += k + 1;\n        for (int i = vp + 1; i < sz[s]; ++i) {\n            int t = a[s][i];\n            a[best_d][sz[best_d]++] = t;\n            pos[t] = best_d;\n        }\n        sz[s] = vp;\n        pos[v] = -1;\n        recomp(mn, a, sz, s);\n        recomp(mn, a, sz, best_d);\n    }\n    return energy;\n}\n\n/* ---------- 1.5-ply solver ---------- */\nResult solve_1ply(const int init_a[MAXM][MAXN], const int init_sz[MAXM], int mode) {\n    int a[MAXM][MAXN];\n    int sz[MAXM];\n    int pos[MAXN+1];\n    int mn[MAXM];\n    memcpy(a, init_a, sizeof(int) * MAXM * MAXN);\n    memcpy(sz, init_sz, sizeof(int) * MAXM);\n\n    for (int i = 0; i < m; ++i) {\n        mn[i] = INT_MAX;\n        for (int j = 0; j < sz[i]; ++j) {\n            int v = a[i][j];\n            pos[v] = i;\n            mn[i] = min(mn[i], v);\n        }\n    }\n\n    Result res;\n    res.ops.reserve(5000);\n\n    for (int v = 1; v <= n; ++v) {\n        if ((int)res.ops.size() >= 5000) { res.energy = INT_MAX; return res; }\n\n        int s = pos[v];\n        int vp = 0;\n        while (vp < sz[s] && a[s][vp] != v) ++vp;\n\n        if (vp == sz[s] - 1) {\n            res.ops.emplace_back(v, 0);\n            --sz[s];\n            pos[v] = -1;\n            recomp(mn, a, sz, s);\n            continue;\n        }\n\n        int tailSz = sz[s] - vp - 1;\n        int x = a[s][sz[s]-1];\n        int mnTail = INT_MAX;\n        for (int i = vp+1; i < sz[s]; ++i) mnTail = min(mnTail, a[s][i]);\n\n        struct Opt { int dp; int cost; };\n        vector<Opt> opts;\n        opts.push_back({-1, 0});\n\n        if (tailSz >= 2 && x != mnTail) {\n            vector<pair<int,int>> cand;\n            int empty_d = -1;\n            for (int d = 0; d < m; ++d) if (d != s) {\n                if (sz[d] == 0) { if (empty_d == -1) empty_d = d; }\n                else if (mn[d] > x) cand.emplace_back(mn[d], d);\n            }\n            sort(cand.begin(), cand.end());\n            if (empty_d != -1) opts.push_back({empty_d, 2});\n            for (int i = 0; i < min(3, (int)cand.size()); ++i)\n                opts.push_back({cand[i].second, 2});\n        }\n\n        int best_total = INT_MAX;\n        int best_opt = -1;\n        int best_d = -1;\n\n        for (int oi = 0; oi < (int)opts.size(); ++oi) {\n            const Opt &op = opts[oi];\n\n            int ca[MAXM][MAXN];\n            int csz[MAXM];\n            int cpos[MAXN+1];\n            int cmn[MAXM];\n            memcpy(ca, a, sizeof(int) * MAXM * MAXN);\n            memcpy(csz, sz, sizeof(int) * MAXM);\n            memcpy(cpos, pos, sizeof(int) * (MAXN+1));\n            memcpy(cmn, mn, sizeof(int) * MAXM);\n\n            int cs = s;\n            if (op.dp != -1) {\n                int px = ca[cs][csz[cs]-1];\n                ca[op.dp][csz[op.dp]++] = px;\n                cpos[px] = op.dp;\n                --csz[cs];\n                recomp(cmn, ca, csz, op.dp);\n            }\n\n            int cvp = 0;\n            while (cvp < csz[cs] && ca[cs][cvp] != v) ++cvp;\n\n            // if v became on top after peel, just carry it out\n            if (cvp == csz[cs] - 1) {\n                csz[cs] = cvp;\n                cpos[v] = -1;\n                recomp(cmn, ca, csz, cs);\n                int future = rollout(ca, csz, cpos, cmn, v+1, mode);\n                int total = res.energy + op.cost + future;\n                if (total < best_total) {\n                    best_total = total;\n                    best_opt = oi;\n                    best_d = -1;\n                }\n                continue;\n            }\n\n            int ck = csz[cs] - cvp - 1;\n            for (int d = 0; d < m; ++d) if (d != cs) {\n                int ba[MAXM][MAXN];\n                int bsz[MAXM];\n                int bpos[MAXN+1];\n                int bmn[MAXM];\n                memcpy(ba, ca, sizeof(int) * MAXM * MAXN);\n                memcpy(bsz, csz, sizeof(int) * MAXM);\n                memcpy(bpos, cpos, sizeof(int) * (MAXN+1));\n                memcpy(bmn, cmn, sizeof(int) * MAXM);\n\n                for (int i = cvp+1; i < bsz[cs]; ++i) {\n                    int t = ba[cs][i];\n                    ba[d][bsz[d]++] = t;\n                    bpos[t] = d;\n                }\n                bsz[cs] = cvp;\n                bpos[v] = -1;\n                recomp(bmn, ba, bsz, cs);\n                recomp(bmn, ba, bsz, d);\n\n                int future = rollout(ba, bsz, bpos, bmn, v+1, mode);\n                int total = res.energy + op.cost + (ck + 1) + future;\n                if (total < best_total) {\n                    best_total = total;\n                    best_opt = oi;\n                    best_d = d;\n                }\n            }\n        }\n\n        // apply best peel to real state\n        if (opts[best_opt].dp != -1) {\n            int dp = opts[best_opt].dp;\n            int px = a[s][sz[s]-1];\n            res.ops.emplace_back(px, dp+1);\n            res.energy += 2;\n            a[dp][sz[dp]++] = px;\n            pos[px] = dp;\n            --sz[s];\n            recomp(mn, a, sz, dp);\n        }\n\n        // recompute position of v\n        s = pos[v];\n        vp = 0; while (vp < sz[s] && a[s][vp] != v) ++vp;\n\n        // if v is now on top, carry out directly\n        if (vp == sz[s] - 1) {\n            res.ops.emplace_back(v, 0);\n            --sz[s];\n            pos[v] = -1;\n            recomp(mn, a, sz, s);\n            continue;\n        }\n\n        // apply best bulk\n        int w = a[s][vp+1];\n        int k = sz[s] - vp - 1;\n        res.ops.emplace_back(w, best_d+1);\n        res.energy += k + 1;\n        for (int i = vp+1; i < sz[s]; ++i) {\n            int t = a[s][i];\n            a[best_d][sz[best_d]++] = t;\n            pos[t] = best_d;\n        }\n        sz[s] = vp;\n        pos[v] = -1;\n        recomp(mn, a, sz, s);\n        recomp(mn, a, sz, best_d);\n        res.ops.emplace_back(v, 0);\n    }\n    return res;\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> n >> m)) return 0;\n\n    int init_a[MAXM][MAXN] = {};\n    int init_sz[MAXM] = {};\n    for (int i = 0; i < m; ++i) {\n        init_sz[i] = n / m;\n        for (int j = 0; j < init_sz[i]; ++j) cin >> init_a[i][j];\n    }\n\n    Result best;\n\n    // fast greedy grid\n    for (int bulk = 0; bulk < 10; ++bulk)\n        for (int peel = 0; peel < 10; ++peel)\n            simulate_greedy(init_a, init_sz, bulk, peel, best);\n\n    // 1.5-ply with three rollout modes\n    for (int mode = 0; mode <= 2; ++mode) {\n        Result cur = solve_1ply(init_a, init_sz, mode);\n        if ((int)cur.ops.size() <= 5000 && cur.energy < best.energy)\n            best = std::move(cur);\n    }\n\n    for (auto &p : best.ops)\n        cout << p.first << ' ' << p.second << '\\n';\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    auto prog_start = chrono::steady_clock::now();\n    \n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> h(N - 1);\n    vector<string> vwall(N);\n    for (int i = 0; i < N - 1; ++i) cin >> h[i];\n    for (int i = 0; i < N; ++i) cin >> vwall[i];\n    vector<vector<int>> dmat(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> dmat[i][j];\n\n    const int V = N * N;\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto geti = [&](int v) { return v / N; };\n    auto getj = [&](int v) { return v % N; };\n\n    vector<int> dval(V);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dval[id(i, j)] = dmat[i][j];\n\n    vector<pair<int,int>> edges;\n    vector<vector<pair<int,int>>> adj(V);\n    auto add_edge = [&](int u, int v) {\n        int eid = edges.size();\n        edges.emplace_back(u, v);\n        adj[u].push_back({v, eid});\n        adj[v].push_back({u, eid});\n    };\n    for (int i = 0; i < N - 1; ++i)\n        for (int j = 0; j < N; ++j)\n            if (h[i][j] == '0') add_edge(id(i, j), id(i + 1, j));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N - 1; ++j)\n            if (vwall[i][j] == '0') add_edge(id(i, j), id(i, j + 1));\n    const int E = edges.size();\n\n    const long long L = 100000;\n\n    auto move_char = [&](int u, int v) -> char {\n        int i1 = geti(u), j1 = getj(u);\n        int i2 = geti(v), j2 = getj(v);\n        if (i2 == i1 - 1) return 'U';\n        if (i2 == i1 + 1) return 'D';\n        if (j2 == j1 - 1) return 'L';\n        return 'R';\n    };\n\n    struct UF {\n        vector<int> p, r;\n        UF(int n): p(n), r(n,0) { iota(p.begin(), p.end(), 0); }\n        int find(int x){ return p[x]==x?x:p[x]=find(p[x]); }\n        bool unite(int x, int y){\n            x=find(x); y=find(y);\n            if(x==y) return false;\n            if(r[x]<r[y]) swap(x,y);\n            p[y]=x;\n            if(r[x]==r[y]) r[x]++;\n            return true;\n        }\n    };\n\n    // Build various spanning trees\n    vector<vector<int>> trees;\n    \n    // 1. BFS\n    {\n        vector<int> tree;\n        vector<char> vis(V, 0);\n        queue<int> q;\n        vis[0] = 1; q.push(0);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (auto [v, eid] : adj[u]) {\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    tree.push_back(eid);\n                    q.push(v);\n                }\n            }\n        }\n        trees.push_back(tree);\n    }\n    \n    // 2. DFS\n    {\n        vector<int> tree;\n        vector<char> vis(V, 0);\n        vector<int> stk = {0};\n        vis[0] = 1;\n        while (!stk.empty()) {\n            int u = stk.back();\n            bool found = false;\n            for (auto [v, eid] : adj[u]) {\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    tree.push_back(eid);\n                    stk.push_back(v);\n                    found = true;\n                    break;\n                }\n            }\n            if (!found) stk.pop_back();\n        }\n        trees.push_back(tree);\n    }\n    \n    // 3. Prim (max dval)\n    {\n        vector<int> tree;\n        vector<char> vis(V, 0);\n        priority_queue<pair<int,int>> pq;\n        vector<int> peid(V, -1);\n        pq.push({dval[0], 0});\n        while (!pq.empty()) {\n            auto [dv, u] = pq.top(); pq.pop();\n            if (vis[u]) continue;\n            vis[u] = 1;\n            if (peid[u] != -1) tree.push_back(peid[u]);\n            for (auto [v, eid] : adj[u]) {\n                if (!vis[v]) {\n                    peid[v] = eid;\n                    pq.push({dval[v], v});\n                }\n            }\n        }\n        trees.push_back(tree);\n    }\n    \n    // 4. Kruskal (max weight = d_u + d_v)\n    {\n        vector<int> tree;\n        vector<pair<int,int>> w;\n        for (int eid = 0; eid < E; ++eid) {\n            int u = edges[eid].first, v = edges[eid].second;\n            w.push_back({dval[u] + dval[v], eid});\n        }\n        sort(w.rbegin(), w.rend());\n        UF uf(V);\n        for (auto [weight, eid] : w) {\n            int u = edges[eid].first, v = edges[eid].second;\n            if (uf.unite(u, v)) tree.push_back(eid);\n        }\n        trees.push_back(tree);\n    }\n    \n    // 5. Random BFS\n    {\n        vector<int> tree;\n        vector<char> vis(V, 0);\n        queue<int> q;\n        vis[0] = 1; q.push(0);\n        mt19937 rng(42);\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            auto nb = adj[u];\n            shuffle(nb.begin(), nb.end(), rng);\n            for (auto [v, eid] : nb) {\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    tree.push_back(eid);\n                    q.push(v);\n                }\n            }\n        }\n        trees.push_back(tree);\n    }\n    \n    // 6. Random DFS\n    {\n        vector<int> tree;\n        vector<char> vis(V, 0);\n        vector<int> stk = {0};\n        vis[0] = 1;\n        mt19937 rng(99);\n        while (!stk.empty()) {\n            int u = stk.back();\n            vector<pair<int,int>> unvis;\n            for (auto [v, eid] : adj[u]) if (!vis[v]) unvis.push_back({v, eid});\n            if (unvis.empty()) {\n                stk.pop_back();\n            } else {\n                int idx = (int)(rng() % unvis.size());\n                int v = unvis[idx].first, eid = unvis[idx].second;\n                vis[v] = 1;\n                tree.push_back(eid);\n                stk.push_back(v);\n            }\n        }\n        trees.push_back(tree);\n    }\n\n    // Greedy doubling on a tree\n    auto build_mult = [&](const vector<int>& tree) -> vector<long long> {\n        vector<long long> mult(E, 0);\n        for (int eid : tree) mult[eid] = 2;\n        \n        vector<long long> k(V, 0);\n        for (int eid = 0; eid < E; ++eid) if (mult[eid]) {\n            k[edges[eid].first] += mult[eid];\n            k[edges[eid].second] += mult[eid];\n        }\n        for (int v = 0; v < V; ++v) k[v] /= 2;\n        long long Lcur = 0;\n        for (int v = 0; v < V; ++v) Lcur += k[v];\n        \n        vector<double> escore(E);\n        vector<int> ver(E, 0);\n        int gver = 1;\n        auto recompute = [&](int eid) {\n            int u = edges[eid].first, v = edges[eid].second;\n            escore[eid] = (double)dval[u] / ((double)k[u] * (k[u] + 1.0))\n                        + (double)dval[v] / ((double)k[v] * (k[v] + 1.0));\n            ver[eid] = gver++;\n        };\n        for (int eid = 0; eid < E; ++eid) recompute(eid);\n        \n        using T = tuple<double, int, int>;\n        priority_queue<T> pq;\n        for (int eid = 0; eid < E; ++eid) pq.push({escore[eid], eid, ver[eid]});\n        \n        while (Lcur + 2 <= L) {\n            while (!pq.empty()) {\n                auto [sc, eid, ve] = pq.top(); pq.pop();\n                if (ve != ver[eid]) continue;\n                mult[eid] += 2;\n                int u = edges[eid].first, v = edges[eid].second;\n                k[u]++; k[v]++;\n                Lcur += 2;\n                for (auto [w, eid2] : adj[u]) {\n                    recompute(eid2);\n                    pq.push({escore[eid2], eid2, ver[eid2]});\n                }\n                for (auto [w, eid2] : adj[v]) {\n                    recompute(eid2);\n                    pq.push({escore[eid2], eid2, ver[eid2]});\n                }\n                break;\n            }\n            if (pq.empty()) break;\n        }\n        return mult;\n    };\n\n    // Build multigraphs and score them approximately\n    vector<pair<double, vector<long long>>> mults;\n    for (const auto& tree : trees) {\n        auto mult = build_mult(tree);\n        vector<long long> k(V, 0);\n        for (int eid = 0; eid < E; ++eid) if (mult[eid]) {\n            k[edges[eid].first] += mult[eid];\n            k[edges[eid].second] += mult[eid];\n        }\n        double approx = 0;\n        for (int v = 0; v < V; ++v) {\n            k[v] /= 2;\n            approx += dval[v] * 1.0 * L * L / max(1LL, k[v]);\n        }\n        mults.push_back({approx, move(mult)});\n    }\n    sort(mults.begin(), mults.end());\n\n    // Try best multigraphs with many random tour seeds\n    long long bestCost = LLONG_MAX;\n    string bestRoute;\n    bestRoute.reserve((size_t)L);\n\n    vector<uint32_t> seeds;\n    for (int s = 0; s < 200; ++s) seeds.push_back((uint32_t)s + 12345);\n    seeds.push_back((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    // Pre-allocated buffers\n    vector<long long> rem(E);\n    vector<int> lastVisit(V);\n    vector<int> path;\n    path.reserve((size_t)L + 1);\n    vector<int> stk;\n    stk.reserve((size_t)L + 1);\n\n    for (int mi = 0; mi < (int)mults.size(); ++mi) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - prog_start).count() > 1.75) break;\n        \n        const auto& mult = mults[mi].second;\n        long long multSum = 0;\n        for (auto x : mult) multSum += x;\n        if (multSum != L) continue;\n\n        int seedsToTry = (mi < 3) ? 50 : ((mi < 6) ? 20 : 5);\n        for (int si = 0; si < seedsToTry && si < (int)seeds.size(); ++si) {\n            now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - prog_start).count() > 1.85) break;\n            \n            uint32_t seed = seeds[si];\n            mt19937 rng(seed);\n            vector<vector<pair<int,int>>> adj2 = adj;\n            for (auto& lst : adj2) shuffle(lst.begin(), lst.end(), rng);\n\n            for (int i = 0; i < E; ++i) rem[i] = mult[i];\n            fill(lastVisit.begin(), lastVisit.end(), -1000000);\n            lastVisit[0] = 0;\n            path.clear();\n            stk.clear();\n            stk.push_back(0);\n            int curTime = 0;\n\n            while (!stk.empty()) {\n                int u = stk.back();\n                int bestEid = -1, bestV = -1;\n                long long bestScore = LLONG_MIN;\n                for (auto [v, eid] : adj2[u]) {\n                    if (rem[eid] == 0) continue;\n                    long long score = (curTime + 1 - lastVisit[v]) * 1LL * dval[v];\n                    score += (long long)(rng() & 2047);\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestV = v;\n                        bestEid = eid;\n                    }\n                }\n                if (bestEid == -1) {\n                    path.push_back(u);\n                    stk.pop_back();\n                } else {\n                    rem[bestEid]--;\n                    curTime++;\n                    lastVisit[bestV] = curTime;\n                    stk.push_back(bestV);\n                }\n            }\n\n            reverse(path.begin(), path.end());\n            if ((long long)path.size() != L + 1) continue;\n\n            long long cost = 0;\n            vector<long long> acc(V, 0);\n            vector<int> ftime(V, -1);\n            vector<int> ltime(V, -1);\n            for (int t = 1; t <= L; ++t) {\n                int v = path[t];\n                if (ftime[v] == -1) {\n                    ftime[v] = t;\n                } else {\n                    long long gap = t - ltime[v];\n                    acc[v] += gap * gap;\n                }\n                ltime[v] = t;\n            }\n            for (int v = 0; v < V; ++v) {\n                if (ftime[v] != -1) {\n                    long long gap = L - ltime[v] + ftime[v];\n                    cost += 1LL * dval[v] * (acc[v] + gap * gap);\n                }\n            }\n\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestRoute.clear();\n                for (int i = 0; i < L; ++i)\n                    bestRoute.push_back(move_char(path[i], path[i+1]));\n            }\n        }\n    }\n\n    cout << bestRoute << \"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M;\nint start_cell;\nstring targets[200];\nvector<int> pos[26];\nint dist_arr[225][225];\n\nint last_cells[200][225];\nint last_sz[200];\n// cost_tbl[t][k][c * last_sz[t] + e]\nvector<int16_t> cost_tbl[200][5];\nint16_t best_cost_full[200][225];\n\ninline int manhattan(int a, int b) { return dist_arr[a][b]; }\n\n/*--------------- suffix state (last up to 5 chars) ---------------*/\nstruct State {\n    char s[5];\n    uint8_t len;\n    State() : len(0) {}\n    int overlap(const string& t) const {\n        int mk = min<int>(len, (int)t.size());\n        for (int k = mk; k >= 1; --k) {\n            bool ok = true;\n            for (int i = 0; i < k; ++i)\n                if (s[len - k + i] != t[i]) { ok = false; break; }\n            if (ok) return k;\n        }\n        return 0;\n    }\n    void append(const string& t, int k) {\n        for (int i = k; i < (int)t.size(); ++i) {\n            if (len < 5) {\n                s[len++] = t[i];\n            } else {\n                s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; s[3] = s[4]; s[4] = t[i];\n            }\n        }\n    }\n};\n\n/*--------------- exact evaluation of a permutation ---------------*/\nint evaluate(const vector<int>& ord) {\n    int ks[200];\n    State suf;\n    for (int i = 0; i < M; ++i) {\n        ks[i] = suf.overlap(targets[ord[i]]);\n        suf.append(targets[ord[i]], ks[i]);\n    }\n\n    int dp_prev[225];\n    int prev_t = -1;\n    int sza = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int t = ord[i];\n        int k = ks[i];\n        if (k == 5) continue;\n        int sz = last_sz[t];\n        if (prev_t == -1) {\n            for (int e = 0; e < sz; ++e)\n                dp_prev[e] = (int)cost_tbl[t][k][start_cell * sz + e];\n            sza = sz;\n            prev_t = t;\n        } else {\n            int dp_cur[225];\n            for (int e2 = 0; e2 < sz; ++e2) {\n                int best = INT_MAX;\n                for (int e1 = 0; e1 < sza; ++e1) {\n                    int c = last_cells[prev_t][e1];\n                    int cand = dp_prev[e1] + (int)cost_tbl[t][k][c * sz + e2];\n                    if (cand < best) best = cand;\n                }\n                dp_cur[e2] = best;\n            }\n            for (int e2 = 0; e2 < sz; ++e2) dp_prev[e2] = dp_cur[e2];\n            sza = sz;\n            prev_t = t;\n        }\n    }\n    if (prev_t == -1) return 0;\n    int ans = INT_MAX;\n    for (int e = 0; e < sza; ++e) ans = min(ans, dp_prev[e]);\n    return ans;\n}\n\n/*--------------- GRASP construction ---------------*/\nvector<int> grasp_construct(mt19937& rng, bool randomized, int rcl_size) {\n    vector<int> ord;\n    ord.reserve(M);\n    vector<char> used(M, 0);\n    State suf;\n    int cur = start_cell;\n\n    for (int step = 0; step < M; ++step) {\n        int16_t best1[225];\n        int16_t best2[225];\n        int best1t[225];\n        for (int d = 0; d < 225; ++d) {\n            best1[d] = INT16_MAX;\n            best2[d] = INT16_MAX;\n            best1t[d] = -1;\n        }\n\n        for (int t = 0; t < M; ++t) if (!used[t]) {\n            for (int d = 0; d < 225; ++d) {\n                int16_t v = best_cost_full[t][d];\n                if (v < best1[d]) {\n                    best2[d] = best1[d];\n                    best1[d] = v;\n                    best1t[d] = t;\n                } else if (v < best2[d]) {\n                    best2[d] = v;\n                }\n            }\n        }\n\n        struct Cand { int t, e, val; };\n        Cand top[20];\n        int tcnt = 0;\n\n        for (int t = 0; t < M; ++t) if (!used[t]) {\n            int k = suf.overlap(targets[t]);\n            int sz = last_sz[t];\n            for (int e = 0; e < sz; ++e) {\n                int d = last_cells[t][e];\n                int here = (int)cost_tbl[t][k][cur * sz + e];\n                int future = (step == M - 1) ? 0\n                             : (best1t[d] == t ? best2[d] : best1[d]);\n                int val = here + future;\n                if (tcnt < rcl_size) {\n                    top[tcnt++] = {t, e, val};\n                    for (int x = tcnt - 1; x > 0; --x)\n                        if (top[x].val < top[x - 1].val) swap(top[x], top[x - 1]);\n                } else if (val < top[tcnt - 1].val) {\n                    top[tcnt - 1] = {t, e, val};\n                    for (int x = tcnt - 1; x > 0; --x)\n                        if (top[x].val < top[x - 1].val) swap(top[x], top[x - 1]);\n                }\n            }\n        }\n\n        Cand distinct[20];\n        int dcnt = 0;\n        for (int i = 0; i < tcnt; ++i) {\n            bool ok = true;\n            for (int j = 0; j < dcnt; ++j)\n                if (distinct[j].t == top[i].t) { ok = false; break; }\n            if (ok) distinct[dcnt++] = top[i];\n        }\n        if (dcnt == 0) { // should never happen\n            for (int t = 0; t < M; ++t) if (!used[t]) {\n                distinct[0] = {t, 0, 0};\n                dcnt = 1;\n                break;\n            }\n        }\n\n        int pick = randomized ? (rng() % dcnt) : 0;\n        int chosen_t = distinct[pick].t;\n        int chosen_e = distinct[pick].e;\n\n        ord.push_back(chosen_t);\n        used[chosen_t] = 1;\n        int kk = suf.overlap(targets[chosen_t]);\n        suf.append(targets[chosen_t], kk);\n        cur = last_cells[chosen_t][chosen_e];\n    }\n    return ord;\n}\n\n/*--------------- reconstruct best order ---------------*/\nvector<pair<int,int>> reconstruct(const vector<int>& ord) {\n    vector<pair<int,int>> answer;\n    int ks[200];\n    State suf;\n    for (int i = 0; i < M; ++i) {\n        ks[i] = suf.overlap(targets[ord[i]]);\n        suf.append(targets[ord[i]], ks[i]);\n    }\n\n    vector<vector<uint8_t>> back_ptrs;\n    vector<int> chunk_t;\n    vector<int> chunk_k;\n    int dp_prev[225];\n    int prev_t = -1;\n    int sza = 0;\n\n    for (int i = 0; i < M; ++i) {\n        int t = ord[i];\n        int k = ks[i];\n        if (k == 5) continue;\n        int sz = last_sz[t];\n        if (prev_t == -1) {\n            for (int e = 0; e < sz; ++e)\n                dp_prev[e] = (int)cost_tbl[t][k][start_cell * sz + e];\n            sza = sz;\n            prev_t = t;\n            chunk_t.push_back(t);\n            chunk_k.push_back(k);\n        } else {\n            vector<uint8_t> bp(sz);\n            int dp_cur[225];\n            for (int e2 = 0; e2 < sz; ++e2) {\n                int best = INT_MAX;\n                uint8_t best_e1 = 0;\n                for (int e1 = 0; e1 < sza; ++e1) {\n                    int c = last_cells[prev_t][e1];\n                    int cand = dp_prev[e1] + (int)cost_tbl[t][k][c * sz + e2];\n                    if (cand < best) {\n                        best = cand;\n                        best_e1 = (uint8_t)e1;\n                    }\n                }\n                dp_cur[e2] = best;\n                bp[e2] = best_e1;\n            }\n            for (int e2 = 0; e2 < sz; ++e2) dp_prev[e2] = dp_cur[e2];\n            back_ptrs.push_back(std::move(bp));\n            sza = sz;\n            prev_t = t;\n            chunk_t.push_back(t);\n            chunk_k.push_back(k);\n        }\n    }\n\n    int Cn = (int)chunk_t.size();\n    if (Cn == 0) return answer;\n\n    int best_e = 0;\n    for (int e = 1; e < sza; ++e)\n        if (dp_prev[e] < dp_prev[best_e]) best_e = e;\n\n    vector<int> end_idx(Cn);\n    end_idx[Cn - 1] = best_e;\n    for (int i = Cn - 1; i >= 1; --i)\n        end_idx[i - 1] = back_ptrs[i - 1][end_idx[i]];\n\n    int cur_cell = start_cell;\n    for (int idx = 0; idx < Cn; ++idx) {\n        int t = chunk_t[idx];\n        int k = chunk_k[idx];\n        int ej = end_idx[idx];\n        int L = 5 - k;\n        vector<int> layers[5];\n        for (int l = 0; l < L; ++l)\n            layers[l] = pos[targets[t][k + l] - 'A'];\n\n        int dp_p[225], dp_c[225];\n        uint8_t par[5][225];\n\n        int sz0 = (int)layers[0].size();\n        for (int i = 0; i < sz0; ++i)\n            dp_p[i] = manhattan(cur_cell, layers[0][i]);\n\n        for (int l = 1; l < L; ++l) {\n            int szp = (int)layers[l - 1].size();\n            int szc = (int)layers[l].size();\n            for (int j = 0; j < szc; ++j) {\n                int best = INT_MAX;\n                uint8_t best_i = 0;\n                for (int i = 0; i < szp; ++i) {\n                    int val = dp_p[i] + manhattan(layers[l - 1][i], layers[l][j]);\n                    if (val < best) {\n                        best = val;\n                        best_i = (uint8_t)i;\n                    }\n                }\n                dp_c[j] = best;\n                par[l][j] = best_i;\n            }\n            for (int j = 0; j < szc; ++j) dp_p[j] = dp_c[j];\n        }\n\n        int cells[5];\n        int cur_j = ej;\n        cells[L - 1] = layers[L - 1][cur_j];\n        for (int l = L - 1; l >= 1; --l) {\n            cur_j = par[l][cur_j];\n            cells[l - 1] = layers[l - 1][cur_j];\n        }\n\n        for (int l = 0; l < L; ++l) {\n            int id = cells[l];\n            answer.emplace_back(id / N, id % N);\n        }\n        cur_cell = cells[L - 1];\n    }\n    return answer;\n}\n\n/*--------------- strong perturbation (ILS kick) ---------------*/\nvector<int> kick(const vector<int>& ord, mt19937& rng) {\n    vector<int> res = ord;\n    int type = rng() % 3;\n    if (type == 0) {\n        // reverse segment\n        int i = rng() % max(1, M - 1);\n        int len = 10 + (int)(rng() % 21); // 10..30\n        int j = min(M - 1, i + len);\n        reverse(res.begin() + i, res.begin() + j + 1);\n    } else if (type == 1) {\n        // move block\n        int len = 5 + (int)(rng() % 11); // 5..15\n        if (len > M) len = M;\n        int i = rng() % max(1, M - len + 1);\n        int j = i + len;\n        vector<int> block(res.begin() + i, res.begin() + j);\n        res.erase(res.begin() + i, res.begin() + j);\n        int pos = rng() % ((int)res.size() + 1);\n        res.insert(res.begin() + pos, block.begin(), block.end());\n    } else {\n        // scramble segment\n        int len = 8 + (int)(rng() % 13); // 8..20\n        if (len > M) len = M;\n        int i = rng() % max(1, M - len + 1);\n        shuffle(res.begin() + i, res.begin() + i + len, rng);\n    }\n    return res;\n}\n\n/*--------------- main ---------------*/\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    start_cell = si * N + sj;\n    const int C = N * N;\n\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            pos[s[j] - 'A'].push_back(id);\n        }\n    }\n    for (int k = 0; k < M; ++k) cin >> targets[k];\n\n    for (int i = 0; i < C; ++i) {\n        int i1 = i / N, j1 = i % N;\n        for (int j = 0; j < C; ++j) {\n            int i2 = j / N, j2 = j % N;\n            dist_arr[i][j] = abs(i1 - i2) + abs(j1 - j2);\n        }\n    }\n\n    /* precompute suffix costs */\n    for (int t = 0; t < M; ++t) {\n        char last_ch = targets[t][4];\n        last_sz[t] = (int)pos[last_ch - 'A'].size();\n        for (int i = 0; i < last_sz[t]; ++i)\n            last_cells[t][i] = pos[last_ch - 'A'][i];\n\n        for (int k = 0; k < 5; ++k) {\n            int L = 5 - k;\n            vector<int> cells[5];\n            for (int l = 0; l < L; ++l)\n                cells[l] = pos[targets[t][k + l] - 'A'];\n\n            int sz_last = (int)cells[L - 1].size();\n            cost_tbl[t][k].assign(C * sz_last, 0);\n            vector<int> dp_prev(225), dp_cur(225);\n            for (int c = 0; c < C; ++c) {\n                int sz0 = (int)cells[0].size();\n                for (int i = 0; i < sz0; ++i)\n                    dp_prev[i] = manhattan(c, cells[0][i]) + 1;\n                for (int l = 1; l < L; ++l) {\n                    int szp = (int)cells[l - 1].size();\n                    int szc = (int)cells[l].size();\n                    for (int j = 0; j < szc; ++j) {\n                        int best = INT_MAX;\n                        for (int i = 0; i < szp; ++i) {\n                            int val = dp_prev[i] + manhattan(cells[l - 1][i], cells[l][j]);\n                            if (val < best) best = val;\n                        }\n                        dp_cur[j] = best + 1;\n                    }\n                    for (int j = 0; j < szc; ++j) dp_prev[j] = dp_cur[j];\n                }\n                for (int e = 0; e < sz_last; ++e)\n                    cost_tbl[t][k][c * sz_last + e] = (int16_t)dp_prev[e];\n            }\n        }\n\n        int sz = last_sz[t];\n        for (int c = 0; c < C; ++c) {\n            int best = INT_MAX;\n            for (int e = 0; e < sz; ++e)\n                best = min(best, (int)cost_tbl[t][0][c * sz + e]);\n            best_cost_full[t][c] = (int16_t)best;\n        }\n    }\n\n    /* generate initial solutions with GRASP */\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    auto start_time = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    vector<int> best_order;\n    int best_val = INT_MAX;\n\n    // deterministic greedy\n    {\n        vector<int> ord = grasp_construct(rng, false, 1);\n        int v = evaluate(ord);\n        if (v < best_val) { best_val = v; best_order = ord; }\n    }\n\n    // randomized GRASP runs with varying RCL sizes\n    for (int run = 0; run < 25; ++run) {\n        int rcl = (run < 8) ? 3 : (run < 16) ? 5 : 7;\n        vector<int> ord = grasp_construct(rng, true, rcl);\n        if ((int)ord.size() != M) continue;\n        int v = evaluate(ord);\n        if (v < best_val) { best_val = v; best_order = ord; }\n    }\n\n    /* iterated local search around the best known solution */\n    vector<int> cur_order = best_order;\n    int cur_val = best_val;\n\n    const double TL = 1.97;\n    const int PATIENCE = 6000;\n    int iter = 0, last_improve = 0;\n\n    while (elapsed() < TL) {\n        ++iter;\n        int type = rng() % 4;\n        int i = rng() % M;\n        int j = rng() % M;\n        if (i == j) continue;\n        if (i > j) swap(i, j);\n\n        vector<int> nxt = cur_order;\n        if (type == 0) {\n            swap(nxt[i], nxt[j]);\n        } else if (type == 1) {\n            int v = nxt[i];\n            nxt.erase(nxt.begin() + i);\n            nxt.insert(nxt.begin() + j, v);\n        } else if (type == 2) {\n            reverse(nxt.begin() + i, nxt.begin() + j + 1);\n        } else {\n            int len = 2 + (int)(rng() % 3);\n            if (i + len > M) len = M - i;\n            vector<int> block(nxt.begin() + i, nxt.begin() + i + len);\n            nxt.erase(nxt.begin() + i, nxt.begin() + i + len);\n            int pos = rng() % ((int)nxt.size() + 1);\n            nxt.insert(nxt.begin() + pos, block.begin(), block.end());\n        }\n\n        int nxt_val = evaluate(nxt);\n        if (nxt_val <= cur_val) {\n            cur_order = std::move(nxt);\n            cur_val = nxt_val;\n            last_improve = iter;\n            if (cur_val < best_val) {\n                best_val = cur_val;\n                best_order = cur_order;\n            }\n        } else if (iter - last_improve > PATIENCE) {\n            cur_order = kick(best_order, rng);\n            cur_val = evaluate(cur_order);\n            last_improve = iter;\n        }\n    }\n\n    vector<pair<int,int>> ans = reconstruct(best_order);\n    for (auto &p : ans) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, MAX_OPS;\ndouble eps;\nconst int MAXC = 400;\nconst int MAXT = 400;\n\nvector<vector<bitset<MAXC>>> masks;\nvector<vector<bitset<MAXT>>> trans_cover_cell;\nvector<vector<bitset<MAXT>>> not_cover_cell;\nvector<bitset<MAXT>> all_valid;\n\nvector<int> drilled_val;\nvector<int> drilled_cells;\nmt19937 rng;\n\nvoid global_propagate(vector<bitset<MAXT>>& cand) {\n    bool changed = true;\n    int it = 0;\n    while (changed && it++ < 15) {\n        changed = false;\n        for (int k = 0; k < M; k++) if (!cand[k].any()) return;\n\n        vector<vector<char>> any(M, vector<char>(N * N, 0));\n        vector<vector<char>> all(M, vector<char>(N * N, 0));\n        vector<int> tot_any(N * N, 0), tot_all(N * N, 0);\n\n        for (int k = 0; k < M; k++) {\n            for (int p : drilled_cells) {\n                bool a = (cand[k] & trans_cover_cell[k][p]).any();\n                bool b = false;\n                if (cand[k].any()) b = (cand[k] & not_cover_cell[k][p]).none();\n                any[k][p] = a;  all[k][p] = b;\n                if (a) ++tot_any[p];\n                if (b) ++tot_all[p];\n            }\n        }\n\n        for (int k = 0; k < M; k++) {\n            for (int t = 0; t < (int)masks[k].size(); t++) if (cand[k].test(t)) {\n                bool ok = true;\n                for (int p : drilled_cells) {\n                    int need = drilled_val[p] - (masks[k][t].test(p) ? 1 : 0);\n                    int minRem = tot_all[p] - (all[k][p] ? 1 : 0);\n                    int maxRem = tot_any[p] - (any[k][p] ? 1 : 0);\n                    if (need < minRem || need > maxRem) { ok = false; break; }\n                }\n                if (!ok) {\n                    cand[k].reset(t);\n                    changed = true;\n                }\n            }\n        }\n    }\n}\n\nvoid deduce(vector<bitset<MAXT>>& cand) {\n    for (int k = 0; k < M; k++) if (!cand[k].any()) return;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) {\n            int any_cnt = 0, all_cnt = 0;\n            for (int k = 0; k < M; k++) {\n                bool a = (cand[k] & trans_cover_cell[k][p]).any();\n                bool b = false;\n                if (cand[k].any()) b = (cand[k] & not_cover_cell[k][p]).none();\n                if (a) ++any_cnt;\n                if (b) ++all_cnt;\n            }\n            if (any_cnt == 0) {\n                drilled_val[p] = 0;\n                drilled_cells.push_back(p);\n                for (int k = 0; k < M; k++) cand[k] &= not_cover_cell[k][p];\n                changed = true;\n            } else if (all_cnt == M) {\n                drilled_val[p] = M;\n                drilled_cells.push_back(p);\n                for (int k = 0; k < M; k++) cand[k] &= trans_cover_cell[k][p];\n                changed = true;\n            }\n        }\n        if (changed) global_propagate(cand);\n    }\n}\n\nvoid compute_forced(const vector<bitset<MAXT>>& cand,\n                    bitset<MAXC>& forced_pos,\n                    bitset<MAXC>& forced_zero,\n                    int& ambiguous_cnt) {\n    forced_pos.reset();\n    forced_zero.reset();\n    ambiguous_cnt = 0;\n    for (int p = 0; p < N * N; p++) if (drilled_val[p] == -1) {\n        int mn = 0, mx = 0;\n        for (int k = 0; k < M; k++) {\n            if (!cand[k].any()) continue;\n            if ((cand[k] & not_cover_cell[k][p]).none()) ++mn;\n            if ((cand[k] & trans_cover_cell[k][p]).any()) ++mx;\n        }\n        if (mn > 0) forced_pos.set(p);\n        else if (mx == 0) forced_zero.set(p);\n        else ++ambiguous_cnt;\n    }\n}\n\nvector<bitset<MAXC>> greedy_sample(const vector<bitset<MAXT>>& cand,\n                                   int max_unique, int max_attempts,\n                                   double tl_sec,\n                                   int& out_success) {\n    vector<bitset<MAXC>> res;\n    out_success = 0;\n    auto deadline = chrono::steady_clock::now() + chrono::milliseconds((long long)(tl_sec * 1000));\n    vector<int> order(M);\n    for (int att = 0; att < max_attempts && (int)res.size() < max_unique; ++att) {\n        if (att % 32 == 0 && chrono::steady_clock::now() > deadline) break;\n        iota(order.begin(), order.end(), 0);\n        shuffle(order.begin(), order.end(), rng);\n        array<short, MAXC> cur{};\n        cur.fill(0);\n        vector<int> assign(M, -1);\n        bool ok = true;\n        for (int idx = 0; idx < M && ok; ++idx) {\n            int k = order[idx];\n            vector<int> ok_ts;\n            int rem = M - idx - 1;\n            for (int t = 0; t < (int)masks[k].size(); ++t) if (cand[k].test(t)) {\n                bool can = true;\n                for (int p : drilled_cells) {\n                    int after = cur[p] + (masks[k][t].test(p) ? 1 : 0);\n                    if (after > drilled_val[p]) { can = false; break; }\n                }\n                if (!can) continue;\n                for (int p : drilled_cells) {\n                    int after = cur[p] + (masks[k][t].test(p) ? 1 : 0);\n                    if (after + rem < drilled_val[p]) { can = false; break; }\n                }\n                if (!can) continue;\n                ok_ts.push_back(t);\n            }\n            if (ok_ts.empty()) { ok = false; break; }\n            int t = ok_ts[rng() % ok_ts.size()];\n            assign[k] = t;\n            for (int p : drilled_cells) if (masks[k][t].test(p)) ++cur[p];\n        }\n        if (!ok) continue;\n        ++out_success;\n        bitset<MAXC> uni;\n        for (int k = 0; k < M; ++k) if (assign[k] >= 0) uni |= masks[k][assign[k]];\n        bool dup = false;\n        for (auto &u : res) if (u == uni) { dup = true; break; }\n        if (!dup) res.push_back(uni);\n    }\n    return res;\n}\n\nint pick_splitter(const vector<bitset<MAXC>>& unions, const bitset<MAXC>& skip) {\n    if ((int)unions.size() < 2) return -1;\n    bitset<MAXC> diff = unions[0] ^ unions[1];\n    for (size_t i = 2; i < unions.size(); ++i) diff |= (unions[0] ^ unions[i]);\n    int best = -1;\n    double best_score = -1.0;\n    for (int p = 0; p < N * N; p++) if (diff.test(p) && !skip.test(p) && drilled_val[p] == -1) {\n        int cnt = 0;\n        for (auto &u : unions) if (u.test(p)) ++cnt;\n        double f = cnt / (double)unions.size();\n        double score = f * (1.0 - f);\n        if (score > best_score + 1e-9) {\n            best_score = score;\n            best = p;\n        }\n    }\n    return best;\n}\n\nint pick_entropy(const vector<bitset<MAXT>>& cand, const bitset<MAXC>& skip) {\n    int best = -1;\n    double best_score = -1.0;\n    for (int p = 0; p < N * N; p++) if (!skip.test(p) && drilled_val[p] == -1) {\n        double score = 0.0;\n        for (int k = 0; k < M; ++k) {\n            int total = (int)cand[k].count();\n            if (total <= 1) continue;\n            int cov = (int)(cand[k] & trans_cover_cell[k][p]).count();\n            if (cov == 0 || cov == total) continue;\n            double pk = cov / (double)total;\n            score += pk * log2(1.0 / pk) + (1.0 - pk) * log2(1.0 / (1.0 - pk));\n        }\n        if (score > best_score + 1e-9) {\n            best_score = score;\n            best = p;\n        }\n    }\n    return best;\n}\n\nstruct DFSHelper {\n    const vector<bitset<MAXT>>& cand;\n    int limit_sol;\n    chrono::steady_clock::time_point deadline;\n    int nodes = 0;\n    bool aborted = false;\n    vector<bitset<MAXC>> unions;\n\n    DFSHelper(const vector<bitset<MAXT>>& c, int ls, double tl_sec)\n        : cand(c), limit_sol(ls) {\n        auto ms = chrono::milliseconds((long long)(tl_sec * 1000.0));\n        deadline = chrono::steady_clock::now() + ms;\n    }\n\n    void rec(vector<int>& assigned, array<short, MAXC>& cur, int depth) {\n        if (aborted) return;\n        if ((int)unions.size() >= limit_sol) return;\n        if (++nodes % 256 == 0) {\n            if (chrono::steady_clock::now() > deadline) { aborted = true; return; }\n        }\n        if (depth == M) {\n            bitset<MAXC> uni;\n            for (int k = 0; k < M; k++) uni |= masks[k][assigned[k]];\n            bool dup = false;\n            for (auto &u : unions) if (u == uni) { dup = true; break; }\n            if (!dup) unions.push_back(uni);\n            return;\n        }\n\n        vector<int> fields;\n        for (int i = 0; i < M; i++) if (assigned[i] == -1) fields.push_back(i);\n        sort(fields.begin(), fields.end(),\n             [&](int a, int b) { return cand[a].count() < cand[b].count(); });\n\n        int k = fields[rng() % min((int)fields.size(), max(1, (int)fields.size() / 2 + 1))];\n\n        vector<int> ts;\n        for (int t = 0; t < (int)masks[k].size(); t++)\n            if (cand[k].test(t)) ts.push_back(t);\n        shuffle(ts.begin(), ts.end(), rng);\n\n        for (int t : ts) {\n            bool ok = true;\n            for (int p : drilled_cells) {\n                int after = cur[p] + (masks[k][t].test(p) ? 1 : 0);\n                if (after > drilled_val[p]) { ok = false; break; }\n            }\n            if (!ok) continue;\n            int rem = M - depth - 1;\n            for (int p : drilled_cells) {\n                int after = cur[p] + (masks[k][t].test(p) ? 1 : 0);\n                if (after + rem < drilled_val[p]) { ok = false; break; }\n            }\n            if (!ok) continue;\n\n            int old = assigned[k];\n            assigned[k] = t;\n            for (int p : drilled_cells) if (masks[k][t].test(p)) ++cur[p];\n            rec(assigned, cur, depth + 1);\n            for (int p : drilled_cells) if (masks[k][t].test(p)) --cur[p];\n            assigned[k] = old;\n        }\n    }\n\n    void run() {\n        vector<int> assigned(M, -1);\n        array<short, MAXC> cur{};\n        cur.fill(0);\n        rec(assigned, cur, 0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n\n    if (!(cin >> N >> M >> eps)) return 0;\n    vector<vector<pair<int,int>>> shapes(M);\n    for (int k = 0; k < M; k++) {\n        int d; cin >> d;\n        shapes[k].resize(d);\n        for (int i = 0; i < d; i++) cin >> shapes[k][i].first >> shapes[k][i].second;\n    }\n    MAX_OPS = 2 * N * N;\n\n    masks.assign(M, {});\n    all_valid.assign(M, {});\n    for (int k = 0; k < M; k++) {\n        int hi = 0, hj = 0;\n        for (auto &c : shapes[k]) {\n            hi = max(hi, c.first);\n            hj = max(hj, c.second);\n        }\n        int h = hi + 1, w = hj + 1;\n        for (int di = 0; di + h <= N; di++) {\n            for (int dj = 0; dj + w <= N; dj++) {\n                bitset<MAXC> bs;\n                for (auto &c : shapes[k]) {\n                    int i = di + c.first;\n                    int j = dj + c.second;\n                    bs.set(i * N + j);\n                }\n                masks[k].push_back(bs);\n            }\n        }\n        for (int t = 0; t < (int)masks[k].size(); t++) all_valid[k].set(t);\n    }\n\n    trans_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    not_cover_cell.assign(M, vector<bitset<MAXT>>(N * N));\n    for (int k = 0; k < M; k++) {\n        for (int p = 0; p < N * N; p++) {\n            for (int t = 0; t < (int)masks[k].size(); t++)\n                if (masks[k][t].test(p)) trans_cover_cell[k][p].set(t);\n            not_cover_cell[k][p] = all_valid[k] & ~trans_cover_cell[k][p];\n        }\n    }\n\n    drilled_val.assign(N * N, -1);\n    rng = mt19937((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<bitset<MAXT>> cand(M);\n    for (int k = 0; k < M; k++) cand[k] = all_valid[k];\n\n    int ops = 0;\n\n    auto do_drill = [&](int p) -> bool {\n        int i = p / N, j = p % N;\n        cout << \"q 1 \" << i << ' ' << j << endl;\n        int v;\n        if (!(cin >> v)) return false;\n        ++ops;\n        drilled_val[p] = v;\n        drilled_cells.push_back(p);\n        if (v == 0) {\n            for (int k = 0; k < M; k++) cand[k] &= not_cover_cell[k][p];\n        } else if (v == M) {\n            for (int k = 0; k < M; k++) cand[k] &= trans_cover_cell[k][p];\n        }\n        global_propagate(cand);\n        deduce(cand);\n        return true;\n    };\n\n    auto do_guess = [&](const bitset<MAXC>& uni,\n                        const bitset<MAXC>& forced_pos) -> bool {\n        bitset<MAXC> guess = uni | forced_pos;\n        for (int p = 0; p < N * N; p++) {\n            if (drilled_val[p] > 0) guess.set(p);\n            else if (drilled_val[p] == 0) guess.reset(p);\n        }\n        vector<pair<int,int>> ans;\n        for (int p = 0; p < N * N; p++) if (guess.test(p)) ans.emplace_back(p / N, p % N);\n        cout << \"a \" << ans.size();\n        for (auto &pr : ans) cout << ' ' << pr.first << ' ' << pr.second;\n        cout << endl;\n        int resp;\n        if (!(cin >> resp)) return false;\n        ++ops;\n        return resp == 1;\n    };\n\n    auto pick_random_ambiguous = [&](const bitset<MAXC>& skip) -> int {\n        int p = uniform_int_distribution<int>(0, N * N - 1)(rng);\n        for (int i = 0; i < N * N; ++i) {\n            int q = (p + i) % (N * N);\n            if (drilled_val[q] == -1 && !skip.test(q)) return q;\n        }\n        return -1;\n    };\n\n    /* initial strategic drilling */\n    {\n        vector<int> cov(N * N, 0);\n        for (int k = 0; k < M; k++)\n            for (int t = 0; t < (int)masks[k].size(); t++)\n                for (int p = 0; p < N * N; p++)\n                    if (masks[k][t].test(p)) ++cov[p];\n        vector<pair<int,int>> order;\n        for (int p = 0; p < N * N; p++) order.emplace_back(cov[p], p);\n        sort(order.rbegin(), order.rend());\n        int init_cnt = min(N * N, max(3, min(N, 5)));\n        for (int i = 0; i < init_cnt && ops < MAX_OPS - 20; i++) {\n            if (!do_drill(order[i].second)) return 0;\n        }\n    }\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration_cast<chrono::milliseconds>(now - start).count() / 1000.0;\n\n        if (elapsed > 2.40) {\n            for (int p = 0; p < N * N && ops < MAX_OPS - 1; p++)\n                if (drilled_val[p] == -1)\n                    if (!do_drill(p)) return 0;\n            bitset<MAXC> exact, dummy;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            do_guess(exact, dummy);\n            return 0;\n        }\n\n        deduce(cand);\n\n        bitset<MAXC> forced_pos, forced_zero;\n        int ambiguous_cnt;\n        compute_forced(cand, forced_pos, forced_zero, ambiguous_cnt);\n\n        if (ambiguous_cnt == 0) {\n            bitset<MAXC> dummy;\n            if (do_guess(dummy, forced_pos)) return 0;\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) if (!do_drill(p)) return 0;\n            bitset<MAXC> exact;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            do_guess(exact, dummy);\n            return 0;\n        }\n\n        int undrilled = N * N - (int)drilled_cells.size();\n        if (undrilled + 1 > MAX_OPS - ops) {\n            bitset<MAXC> guess, dummy;\n            for (int k = 0; k < M; k++)\n                for (int t = 0; t < (int)masks[k].size(); t++)\n                    if (cand[k].test(t)) guess |= masks[k][t];\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) guess.set(p);\n            do_guess(guess, forced_pos);\n            return 0;\n        }\n\n        if (undrilled <= 8) {\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) {\n                    if (!do_drill(p)) return 0;\n                }\n            bitset<MAXC> exact, dummy;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            do_guess(exact, dummy);\n            return 0;\n        }\n\n        bool feasible = true;\n        for (int k = 0; k < M; k++) if (!cand[k].any()) { feasible = false; break; }\n        if (!feasible) {\n            for (int p = 0; p < N * N; p++)\n                if (drilled_val[p] == -1) if (!do_drill(p)) return 0;\n            bitset<MAXC> exact, dummy;\n            for (int p = 0; p < N * N; p++) if (drilled_val[p] > 0) exact.set(p);\n            do_guess(exact, dummy);\n            return 0;\n        }\n\n        bool all_one = true;\n        for (int k = 0; k < M; k++) if (cand[k].count() != 1) { all_one = false; break; }\n        if (all_one) {\n            bitset<MAXC> uni, dummy;\n            for (int k = 0; k < M; k++) {\n                for (int t = 0; t < (int)masks[k].size(); t++) if (cand[k].test(t)) {\n                    uni |= masks[k][t];\n                    break;\n                }\n            }\n            if (do_guess(uni, forced_pos)) return 0;\n        }\n\n        bitset<MAXC> skip = forced_pos | forced_zero;\n        int total_cand = 0, max_cand = 0;\n        for (int k = 0; k < M; k++) {\n            int c = (int)cand[k].count();\n            total_cand += c;\n            max_cand = max(max_cand, c);\n        }\n\n        /* tiny space DFS */\n        if (total_cand <= 200 && max_cand <= 25) {\n            DFSHelper dfs(cand, 200, 0.08);\n            dfs.run();\n            bool exhaustive = !dfs.aborted && (int)dfs.unions.size() < 200;\n            if (exhaustive && !dfs.unions.empty()) {\n                bool agree = true;\n                for (size_t i = 1; i < dfs.unions.size(); i++)\n                    if (dfs.unions[i] != dfs.unions[0]) { agree = false; break; }\n                if (agree) {\n                    if (do_guess(dfs.unions[0], forced_pos)) return 0;\n                } else {\n                    int best = pick_splitter(dfs.unions, skip);\n                    if (best != -1) {\n                        if (!do_drill(best)) return 0;\n                        continue;\n                    }\n                }\n            }\n        }\n\n        /* greedy sampling */\n        int successes;\n        auto unions = greedy_sample(cand, 4, 200, 0.06, successes);\n\n        if ((int)unions.size() >= 2) {\n            int best = pick_splitter(unions, skip);\n            if (best != -1) {\n                if (!do_drill(best)) return 0;\n                continue;\n            }\n            if (do_guess(unions[0], forced_pos)) return 0;\n        }\n\n        if ((int)unions.size() == 1 && successes >= 30) {\n            if (do_guess(unions[0], forced_pos)) return 0;\n        }\n\n        int best = pick_entropy(cand, skip);\n        if (best == -1) best = pick_random_ambiguous(skip);\n        if (best != -1) {\n            if (!do_drill(best)) return 0;\n        } else {\n            bitset<MAXC> exact, dummy;\n            for (int c = 0; c < N * N; c++) if (drilled_val[c] > 0) exact.set(c);\n            do_guess(exact, dummy);\n            return 0;\n        }\n    }\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nusing ull = unsigned long long;\n\nstruct Rect { int x, y, w, h; };\n\nstruct Cand {\n    vector<Rect> r;\n    vector<ull> mask;\n    ll acost;\n};\n\nstatic int W, D, N;\nstatic int G_WORDS;\nstatic vector<vector<ll>> a;\n\n/* ---------- mask utilities ---------- */\nstatic void build_mask(const vector<Rect>& rects, vector<ull>& mask) {\n    fill(mask.begin(), mask.end(), 0ULL);\n    auto sb = [&](int p) { mask[p >> 6] |= 1ULL << (p & 63); };\n    for (const auto& rc : rects) {\n        int x = rc.x, y = rc.y, w = rc.w, h = rc.h;\n        if (y > 0 && y < W) for (int j = x; j < x + w; ++j) sb((y - 1) * W + j);\n        if (y + h > 0 && y + h < W) for (int j = x; j < x + w; ++j) sb((y + h - 1) * W + j);\n        if (x > 0 && x < W) for (int i = y; i < y + h; ++i) sb((W - 1) * W + i * (W - 1) + (x - 1));\n        if (x + w > 0 && x + w < W) for (int i = y; i < y + h; ++i) sb((W - 1) * W + i * (W - 1) + (x + w - 1));\n    }\n}\n\nstatic ll trans_cost(const vector<ull>& A, const vector<ull>& B) {\n    ll s = 0;\n    for (int i = 0; i < G_WORDS; ++i) s += __builtin_popcountll(A[i] ^ B[i]);\n    return s;\n}\n\nstatic ll area_cost(const vector<Rect>& r, const vector<ll>& area) {\n    ll c = 0;\n    for (int k = 0; k < N; ++k) {\n        ll A = 1LL * r[k].w * r[k].h;\n        if (area[k] > A) c += 100LL * (area[k] - A);\n    }\n    return c;\n}\n\n/* ---------- dimension helper ---------- */\nstatic pair<int,int> choose_dim(ll A, mt19937& rng, int dim_mode) {\n    int w, h;\n    if (dim_mode == 0) { w = max(1, (int)sqrt((double)A)); h = (int)((A + w - 1) / w); }\n    else if (dim_mode == 1) { h = max(1, (int)sqrt((double)A)); w = (int)((A + h - 1) / h); }\n    else if (dim_mode == 2) { w = (int)max(1LL, (A + W - 1) / W); h = (int)((A + w - 1) / w); }\n    else if (dim_mode == 3) { h = (int)max(1LL, (A + W - 1) / W); w = (int)((A + h - 1) / h); }\n    else {\n        ll lo = max(1LL, (A + W - 1) / W), hi = min((ll)W, A);\n        if (lo >= hi) w = (int)lo; else w = uniform_int_distribution<int>((int)lo, (int)hi)(rng);\n        h = (int)((A + w - 1) / w);\n    }\n    if (h > W) { h = W; w = (int)((A + h - 1) / h); }\n    if (w > W) { w = W; h = (int)((A + w - 1) / w); }\n    if (w < 1) w = 1; if (h < 1) h = 1;\n    return {w, h};\n}\n\n/* ---------- guillotine packer ---------- */\nstatic vector<Rect> pack_guillotine(const vector<ll>& area, mt19937& rng, int order_type, int dim_mode) {\n    int n = (int)area.size();\n    vector<int> ord(n); iota(ord.begin(), ord.end(), 0);\n    if (order_type == 0) sort(ord.begin(), ord.end(), [&](int i, int j){ return area[i] > area[j]; });\n    else if (order_type == 1) sort(ord.begin(), ord.end(), [&](int i, int j){ return area[i] < area[j]; });\n    else shuffle(ord.begin(), ord.end(), rng);\n\n    vector<pair<int,int>> dim(n);\n    for (int idx : ord) dim[idx] = choose_dim(area[idx], rng, dim_mode);\n\n    vector<Rect> cur(n);\n    struct F { int x, y, w, h; };\n    vector<F> freeList;\n    freeList.reserve(2 * n + 2);\n    freeList.push_back({0, 0, W, W});\n\n    for (int idx : ord) {\n        int w = dim[idx].first, h = dim[idx].second;\n        int bestPos = -1; ll bestScore = (1LL<<60); int bw = w, bh = h;\n        for (int i = 0; i < (int)freeList.size(); ++i) {\n            const F& f = freeList[i];\n            if (f.w >= w && f.h >= h) { ll sc = 1LL * (f.w - w) * (f.h - h); if (sc < bestScore) { bestScore = sc; bestPos = i; bw = w; bh = h; } }\n            if (f.w >= h && f.h >= w) { ll sc = 1LL * (f.w - h) * (f.h - w); if (sc < bestScore) { bestScore = sc; bestPos = i; bw = h; bh = w; } }\n        }\n        if (bestPos == -1) return {};\n        F f = freeList[bestPos];\n        cur[idx] = {f.x, f.y, bw, bh};\n        freeList[bestPos] = freeList.back(); freeList.pop_back();\n        if (f.w > bw && f.h > bh) {\n            if (f.w - bw >= f.h - bh) { freeList.push_back({f.x + bw, f.y, f.w - bw, f.h}); freeList.push_back({f.x, f.y + bh, bw, f.h - bh}); }\n            else { freeList.push_back({f.x + bw, f.y, f.w - bw, bh}); freeList.push_back({f.x, f.y + bh, f.w, f.h - bh}); }\n        } else if (f.w > bw) { freeList.push_back({f.x + bw, f.y, f.w - bw, f.h}); }\n        else if (f.h > bh) { freeList.push_back({f.x, f.y + bh, f.w, f.h - bh}); }\n    }\n    return cur;\n}\n\n/* ---------- skyline packer ---------- */\nstatic vector<Rect> pack_skyline(const vector<ll>& area, mt19937& rng, int order_type, int dim_mode) {\n    int n = (int)area.size();\n    vector<int> ord(n); iota(ord.begin(), ord.end(), 0);\n    if (order_type == 0) sort(ord.begin(), ord.end(), [&](int i, int j){ return area[i] > area[j]; });\n    else if (order_type == 1) sort(ord.begin(), ord.end(), [&](int i, int j){ return area[i] < area[j]; });\n    else shuffle(ord.begin(), ord.end(), rng);\n\n    vector<pair<int,int>> dim(n);\n    for (int idx : ord) dim[idx] = choose_dim(area[idx], rng, dim_mode);\n\n    vector<Rect> res(n);\n    vector<int> sky(W, 0);\n    for (int idx : ord) {\n        int w = dim[idx].first, h = dim[idx].second;\n        if (w > W) return {};\n        deque<int> dq;\n        int best_x = -1, best_y = W + 1;\n        for (int i = 0; i < W; ++i) {\n            while (!dq.empty() && sky[dq.back()] <= sky[i]) dq.pop_back();\n            dq.push_back(i);\n            if (dq.front() <= i - w) dq.pop_front();\n            if (i >= w - 1) { int x = i - w + 1, y = sky[dq.front()]; if (y < best_y) { best_y = y; best_x = x; } }\n        }\n        if (best_x == -1 || best_y + h > W) return {};\n        res[idx] = {best_x, best_y, w, h};\n        for (int j = 0; j < w; ++j) sky[best_x + j] = best_y + h;\n    }\n    return res;\n}\n\n/* ---------- strip utilities ---------- */\nstatic vector<Rect> make_strips(const vector<int>& w, const vector<ll>& area) {\n    vector<Rect> r(N);\n    int x = 0;\n    for (int k = 0; k < N; ++k) {\n        int h = (int)min((ll)W, (area[k] + w[k] - 1) / w[k]);\n        if (h < 1) h = 1;\n        r[k] = {x, 0, w[k], h};\n        x += w[k];\n    }\n    return r;\n}\n\nstatic vector<Rect> local_optimal_strips(const vector<ll>& area) {\n    vector<int> need(N);\n    ll sum_need = 0;\n    for (int k = 0; k < N; ++k) { need[k] = (int)max(1LL, (area[k] + W - 1) / W); sum_need += need[k]; }\n    vector<int> w = need;\n    if (sum_need <= W) {\n        int rem = W - (int)sum_need;\n        vector<int> ord(N); iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int i, int j){ return area[i] > area[j]; });\n        for (int k : ord) { if (rem <= 0) break; int give = min(rem, W - w[k]); w[k] += give; rem -= give; }\n    } else {\n        ll excess = sum_need - W;\n        vector<pair<ll,int>> reducible;\n        for (int k = 0; k < N; ++k) if (need[k] > 1) reducible.push_back({area[k] - 1LL * (need[k] - 1) * W, k});\n        sort(reducible.begin(), reducible.end());\n        ll first_reduce = min((ll)reducible.size(), excess);\n        for (ll i = 0; i < first_reduce; ++i) w[reducible[i].second]--;\n        ll remaining = excess - first_reduce;\n        while (remaining > 0) {\n            int best_k = -1;\n            for (int k = 0; k < N; ++k) if (w[k] > 1 && (best_k == -1 || w[k] > w[best_k])) best_k = k;\n            if (best_k == -1) break;\n            w[best_k]--; remaining--;\n        }\n    }\n    return make_strips(w, area);\n}\n\n/* ---------- daily candidate generation ---------- */\nstatic vector<Cand> gen_day_rects(int day, int want, const vector<int>& global_w, mt19937& rng) {\n    const vector<ll>& area = a[day];\n    vector<pair<vector<Rect>, ll>> raw;\n    raw.reserve(250);\n\n    auto add = [&](vector<Rect>&& r) {\n        if (!r.empty()) raw.push_back({r, area_cost(r, area)});\n    };\n\n    add(local_optimal_strips(area));\n    if (!global_w.empty()) add(make_strips(global_w, area));\n\n    {\n        ll sum_min = 0;\n        for (int k = 0; k < N; ++k) sum_min += max(1LL, (area[k] + W - 1) / W);\n        if (sum_min <= W) {\n            vector<int> w(N);\n            for (int k = 0; k < N; ++k) w[k] = (int)max(1LL, (area[k] + W - 1) / W);\n            int rem = W - (int)sum_min;\n            ll S = accumulate(area.begin(), area.end(), 0LL);\n            for (int k = 0; k < N && rem > 0; ++k) { int addw = (int)(rem * area[k] / S); w[k] += addw; rem -= addw; }\n            for (int k = N - 1; k >= 0 && rem > 0; --k) { w[k]++; rem--; }\n            add(make_strips(w, area));\n        }\n    }\n\n    for (int rep = 0; rep < 6; ++rep) {\n        vector<int> w(N, 1);\n        int rem = W - N;\n        for (int k = 0; k < N - 1 && rem > 0; ++k) { int give = (int)(rng() % (rem + 1)); w[k] += give; rem -= give; }\n        w[N - 1] += rem;\n        add(make_strips(w, area));\n    }\n\n    for (int trial = 0; trial < 80; ++trial) {\n        int order = (trial < 2) ? trial : 2;\n        add(pack_guillotine(area, rng, order, trial % 5));\n    }\n\n    for (int trial = 0; trial < 20; ++trial) {\n        int order = (trial < 2) ? trial : 2;\n        add(pack_skyline(area, rng, order, trial % 5));\n    }\n\n    if (raw.empty()) add(local_optimal_strips(area));\n\n    sort(raw.begin(), raw.end(), [](const auto& p, const auto& q){ return p.second < q.second; });\n    vector<char> used(raw.size(), 0);\n    vector<Cand> res; res.reserve(want);\n    for (int i = 0; i < (int)raw.size() && (int)res.size() < want / 2; ++i) {\n        used[i] = 1;\n        Cand c; c.r = std::move(raw[i].first); c.acost = raw[i].second; c.mask.resize(G_WORDS); build_mask(c.r, c.mask); res.push_back(std::move(c));\n    }\n    int step = max(1, (int)raw.size() / (want - (int)res.size() + 1));\n    for (int i = 0; i < (int)raw.size() && (int)res.size() < want; i += step) {\n        if (used[i]) continue;\n        used[i] = 1;\n        Cand c; c.r = std::move(raw[i].first); c.acost = raw[i].second; c.mask.resize(G_WORDS); build_mask(c.r, c.mask); res.push_back(std::move(c));\n    }\n    return res;\n}\n\n/* ---------- local search ---------- */\nstatic void local_search(vector<int>& seq, const vector<vector<Cand>>& cands, vector<vector<vector<ll>>>& memo) {\n    auto get_trans = [&](int d, int i, int j)->ll {\n        ll& v = memo[d][i][j];\n        if (v < 0) v = trans_cost(cands[d][i].mask, cands[d+1][j].mask);\n        return v;\n    };\n    mt19937 rng(1234567);\n    for (int rep = 0; rep < 4; ++rep) {\n        bool improved = false;\n        for (int d = 0; d < D; ++d) {\n            ll best = cands[d][seq[d]].acost;\n            if (d > 0) best += get_trans(d - 1, seq[d - 1], seq[d]);\n            if (d + 1 < D) best += get_trans(d, seq[d], seq[d + 1]);\n            int best_j = seq[d];\n            for (int j = 0; j < (int)cands[d].size(); ++j) {\n                if (j == seq[d]) continue;\n                ll c = cands[d][j].acost;\n                if (d > 0) c += get_trans(d - 1, seq[d - 1], j);\n                if (d + 1 < D) c += get_trans(d, j, seq[d + 1]);\n                if (c < best) { best = c; best_j = j; }\n            }\n            if (best_j != seq[d]) { seq[d] = best_j; improved = true; }\n        }\n        if (!improved) break;\n    }\n    for (int iter = 0; iter < 400; ++iter) {\n        int d = uniform_int_distribution<int>(0, D - 1)(rng);\n        if (cands[d].size() <= 1) continue;\n        int j = uniform_int_distribution<int>(0, (int)cands[d].size() - 1)(rng);\n        if (j == seq[d]) continue;\n        ll old_part = cands[d][seq[d]].acost;\n        if (d > 0) old_part += get_trans(d - 1, seq[d - 1], seq[d]);\n        if (d + 1 < D) old_part += get_trans(d, seq[d], seq[d + 1]);\n        ll new_part = cands[d][j].acost;\n        if (d > 0) new_part += get_trans(d - 1, seq[d - 1], j);\n        if (d + 1 < D) new_part += get_trans(d, j, seq[d + 1]);\n        if (new_part < old_part) seq[d] = j;\n    }\n}\n\n/* ---------- main ---------- */\nint main() {\n    ios::sync_with_stdio(false); cin.tie(nullptr);\n    if (!(cin >> W >> D >> N)) return 0;\n    a.assign(D, vector<ll>(N));\n    for (int d = 0; d < D; ++d) for (int k = 0; k < N; ++k) cin >> a[d][k];\n    G_WORDS = (2 * W * (W - 1) + 63) >> 6;\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    vector<ll> b(N, 0);\n    for (int k = 0; k < N; ++k) for (int d = 0; d < D; ++d) b[k] = max(b[k], a[d][k]);\n\n    /* strict fixed packing (cost 0) */\n    if (accumulate(b.begin(), b.end(), 0LL) <= 1LL * W * W) {\n        vector<Rect> fixed;\n        for (int t = 0; t < 5000 && fixed.empty(); ++t) fixed = pack_guillotine(b, rng, t % 3, t % 5);\n        for (int t = 0; t < 500 && fixed.empty(); ++t) fixed = pack_skyline(b, rng, t % 3, t % 5);\n        if (!fixed.empty()) {\n            for (int d = 0; d < D; ++d) for (int k = 0; k < N; ++k) {\n                const Rect& r = fixed[k];\n                cout << r.y << ' ' << r.x << ' ' << r.y + r.h << ' ' << r.x + r.w << '\\n';\n            }\n            return 0;\n        }\n    }\n\n    /* fast global strip widths (shared across days) */\n    vector<int> global_w;\n    {\n        ll S = accumulate(b.begin(), b.end(), 0LL);\n        global_w.resize(N, 1);\n        ll rem = W - N;\n        for (int k = 0; k < N; ++k) {\n            ll add = rem * b[k] / S;\n            global_w[k] += (int)add;\n            rem -= add;\n        }\n        for (int k = N - 1; k >= 0 && rem > 0; --k) { global_w[k]++; rem--; }\n    }\n\n    const int WANT = 25;\n    const int BEAM = 20;\n\n    /* generate candidates for every day */\n    vector<vector<Cand>> cands(D);\n    for (int d = 0; d < D; ++d) cands[d] = gen_day_rects(d, WANT, global_w, rng);\n\n    /* beam search over days */\n    vector<vector<ll>> beam_cost(D, vector<ll>(BEAM, (1LL<<60)));\n    vector<vector<int>> beam_cidx(D, vector<int>(BEAM, -1));\n    vector<vector<int>> beam_parent(D, vector<int>(BEAM, -1));\n\n    int prev_size = min(BEAM, (int)cands[0].size());\n    for (int i = 0; i < prev_size; ++i) {\n        beam_cost[0][i] = cands[0][i].acost;\n        beam_cidx[0][i] = i;\n        beam_parent[0][i] = -1;\n    }\n\n    for (int d = 1; d < D; ++d) {\n        int C = cands[d].size();\n        vector<tuple<ll,int,int>> all;\n        all.reserve(C * prev_size);\n        for (int ci = 0; ci < C; ++ci) {\n            for (int pi = 0; pi < prev_size; ++pi) {\n                ll c = beam_cost[d-1][pi] + cands[d][ci].acost\n                     + trans_cost(cands[d-1][beam_cidx[d-1][pi]].mask, cands[d][ci].mask);\n                all.emplace_back(c, ci, pi);\n            }\n        }\n        sort(all.begin(), all.end(), [](const auto& p, const auto& q){ return get<0>(p) < get<0>(q); });\n        vector<char> used_cand(C, 0);\n        int taken = 0;\n        for (auto& tup : all) {\n            if (taken >= BEAM) break;\n            int ci = get<1>(tup);\n            if (used_cand[ci]) continue;\n            used_cand[ci] = 1;\n            beam_cost[d][taken] = get<0>(tup);\n            beam_cidx[d][taken] = ci;\n            beam_parent[d][taken] = get<2>(tup);\n            ++taken;\n        }\n        prev_size = taken;\n    }\n\n    /* traceback */\n    vector<int> seq(D, -1);\n    int bidx = 0;\n    for (int d = D - 1; d >= 0; --d) {\n        seq[d] = beam_cidx[d][bidx];\n        bidx = beam_parent[d][bidx];\n    }\n\n    /* safety: if beam failed, fall back to cheapest candidate per day */\n    bool ok = true;\n    for (int d = 0; d < D; ++d) if (seq[d] < 0 || seq[d] >= (int)cands[d].size()) { ok = false; break; }\n    if (!ok) {\n        for (int d = 0; d < D; ++d) {\n            seq[d] = 0;\n            for (int i = 1; i < (int)cands[d].size(); ++i)\n                if (cands[d][i].acost < cands[d][seq[d]].acost) seq[d] = i;\n        }\n    }\n\n    /* local search */\n    vector<vector<vector<ll>>> memo(D - 1);\n    for (int d = 0; d < D - 1; ++d)\n        memo[d].assign(cands[d].size(), vector<ll>(cands[d + 1].size(), -1));\n    local_search(seq, cands, memo);\n\n    /* output */\n    for (int d = 0; d < D; ++d) {\n        for (int k = 0; k < N; ++k) {\n            const Rect& r = cands[d][seq[d]].r[k];\n            cout << r.y << ' ' << r.x << ' ' << r.y + r.h << ' ' << r.x + r.w << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nconstexpr int N = 9;\nconstexpr int M = 20;\nconstexpr int K = 81;\nconstexpr int POS = (N - 2) * (N - 2);          // 49\nconstexpr int TOTAL_OPS = M * POS;               // 980\nconstexpr int CELLS = N * N;                     // 81\nconstexpr int MOD = 998244353;\nconstexpr int NOP = TOTAL_OPS;                   // sentinel\n\nstruct Operation {\n    uint8_t cell[9];\n    uint32_t val[9];\n};\nOperation ops[TOTAL_OPS];\n\nusing Board = array<uint32_t, CELLS>;\nusing Slots = array<int, K>;\n\n// ------------------------------------------------------------------\ninline ll delta_add(const uint32_t *board, int op) {\n    ll d = 0;\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[o.cell[i]];\n        uint32_t s = o.val[i];\n        d += (v >= MOD - s) ? (ll)s - MOD : s;\n    }\n    return d;\n}\n\ninline ll delta_remove(const uint32_t *board, int op) {\n    ll d = 0;\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        uint32_t v = board[o.cell[i]];\n        uint32_t s = o.val[i];\n        d += (v < s) ? (ll)MOD - s : -(ll)s;\n    }\n    return d;\n}\n\ninline void apply_add(uint32_t *board, int op) {\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        int c = o.cell[i];\n        uint32_t v = board[c] + o.val[i];\n        if (v >= MOD) v -= MOD;\n        board[c] = v;\n    }\n}\n\ninline void apply_remove(uint32_t *board, int op) {\n    const auto &o = ops[op];\n    for (int i = 0; i < 9; ++i) {\n        int c = o.cell[i];\n        uint32_t v = board[c];\n        uint32_t s = o.val[i];\n        board[c] = (v >= s) ? v - s : v + MOD - s;\n    }\n}\n\n// ------------------------------------------------------------------\n// exact steepest-ascent 1-opt hill climbing\nvoid hill_climb(Slots &sl, Board &board, ll &score) {\n    while (true) {\n        ll best_d = 0;\n        int best_i = -1, best_a = -1;\n        for (int i = 0; i < K; ++i) {\n            int old = sl[i];\n            ll d;\n            int a;\n            if (old == NOP) {\n                ll bd = 0;\n                int ba = NOP;\n                for (int op = 0; op < TOTAL_OPS; ++op) {\n                    ll dd = delta_add(board.data(), op);\n                    if (dd > bd) {\n                        bd = dd;\n                        ba = op;\n                    }\n                }\n                d = bd; a = ba;\n            } else {\n                ll drem = delta_remove(board.data(), old);\n                apply_remove(board.data(), old);\n                ll bd = 0;\n                int ba = NOP;\n                for (int op = 0; op < TOTAL_OPS; ++op) {\n                    if (op == old) continue;\n                    ll dd = delta_add(board.data(), op);\n                    if (dd > bd) {\n                        bd = dd;\n                        ba = op;\n                    }\n                }\n                d = drem + bd;\n                a = ba;\n                apply_add(board.data(), old);\n            }\n            if (d > best_d) {\n                best_d = d;\n                best_i = i;\n                best_a = a;\n            }\n        }\n        if (best_d <= 0) break;\n        if (sl[best_i] != NOP) apply_remove(board.data(), sl[best_i]);\n        if (best_a != NOP) apply_add(board.data(), best_a);\n        sl[best_i] = best_a;\n        score += best_d;\n    }\n}\n\n// ------------------------------------------------------------------\n// keep best 4 in descending order\ninline void ins4(pair<ll,int> *buf, int &n, ll d, int a) {\n    if (n < 4) {\n        int k = n++;\n        while (k > 0 && buf[k-1].first < d) {\n            buf[k] = buf[k-1];\n            --k;\n        }\n        buf[k] = {d, a};\n    } else if (d > buf[3].first) {\n        int k = 3;\n        while (k > 0 && buf[k-1].first < d) {\n            buf[k] = buf[k-1];\n            --k;\n        }\n        buf[k] = {d, a};\n    }\n}\n\n// randomized 2-opt probe: sample random pairs + random candidates, evaluate exactly\nbool probe2(Slots &sl, Board &board, ll &score, mt19937_64 &rng) {\n    ll best_d = 0;\n    int best_i = -1, best_j = -1, best_a = -1, best_b = -1;\n\n    for (int t = 0; t < 200; ++t) {\n        int i = (int)(rng() % K);\n        int j = (int)(rng() % (K - 1));\n        if (j >= i) ++j;\n        int old_i = sl[i], old_j = sl[j];\n\n        // candidates for slot i\n        ll base_i = 0;\n        if (old_i != NOP) {\n            base_i = delta_remove(board.data(), old_i);\n            apply_remove(board.data(), old_i);\n        }\n        pair<ll,int> ci[4];\n        int ni = 0;\n        if (old_i != NOP) ins4(ci, ni, base_i, NOP);\n        for (int s = 0; s < 20; ++s) {\n            int a = (int)(rng() % (TOTAL_OPS + 1));\n            if (a == old_i) continue;\n            ll d = (a == NOP) ? 0 : delta_add(board.data(), a);\n            if (old_i != NOP) d += base_i;\n            ins4(ci, ni, d, a);\n        }\n\n        // candidates for slot j (on board with old_i removed)\n        ll base_j = 0;\n        if (old_j != NOP) {\n            base_j = delta_remove(board.data(), old_j);\n            apply_remove(board.data(), old_j);\n        }\n        pair<ll,int> cj[4];\n        int nj = 0;\n        if (old_j != NOP) ins4(cj, nj, base_j, NOP);\n        for (int s = 0; s < 20; ++s) {\n            int b = (int)(rng() % (TOTAL_OPS + 1));\n            if (b == old_j) continue;\n            ll d = (b == NOP) ? 0 : delta_add(board.data(), b);\n            if (old_j != NOP) d += base_j;\n            ins4(cj, nj, d, b);\n        }\n\n        // restore board\n        if (old_j != NOP) apply_add(board.data(), old_j);\n        if (old_i != NOP) apply_add(board.data(), old_i);\n\n        if (ni == 0 || nj == 0) continue;\n\n        // exact evaluation of promising combinations\n        for (int x = 0; x < ni; ++x) {\n            int a = ci[x].second;\n            for (int y = 0; y < nj; ++y) {\n                int b = cj[y].second;\n                if (a == old_i && b == old_j) continue;\n\n                ll d = 0;\n                if (old_i != NOP) {\n                    d += delta_remove(board.data(), old_i);\n                    apply_remove(board.data(), old_i);\n                }\n                if (old_j != NOP) {\n                    d += delta_remove(board.data(), old_j);\n                    apply_remove(board.data(), old_j);\n                }\n                if (a != NOP) {\n                    d += delta_add(board.data(), a);\n                    apply_add(board.data(), a);\n                }\n                if (b != NOP) {\n                    d += delta_add(board.data(), b);\n                    apply_add(board.data(), b);\n                }\n\n                if (d > best_d) {\n                    best_d = d;\n                    best_i = i; best_j = j; best_a = a; best_b = b;\n                }\n\n                if (b != NOP) apply_remove(board.data(), b);\n                if (a != NOP) apply_remove(board.data(), a);\n                if (old_j != NOP) apply_add(board.data(), old_j);\n                if (old_i != NOP) apply_add(board.data(), old_i);\n            }\n        }\n    }\n\n    if (best_d > 0) {\n        if (sl[best_i] != NOP) apply_remove(board.data(), sl[best_i]);\n        if (sl[best_j] != NOP) apply_remove(board.data(), sl[best_j]);\n        if (best_a != NOP) apply_add(board.data(), best_a);\n        if (best_b != NOP) apply_add(board.data(), best_b);\n        sl[best_i] = best_a;\n        sl[best_j] = best_b;\n        score += best_d;\n        return true;\n    }\n    return false;\n}\n\n// ------------------------------------------------------------------\nvoid reconstruct(Slots &sl, Board &board, ll &score, bool randomized, mt19937_64 &rng) {\n    int filled = 0;\n    for (int i = 0; i < K; ++i) if (sl[i] != NOP) ++filled;\n    while (filled < K) {\n        int best_a = -1;\n        ll best_d = 0;\n        if (!randomized) {\n            for (int op = 0; op < TOTAL_OPS; ++op) {\n                ll d = delta_add(board.data(), op);\n                if (d > best_d) {\n                    best_d = d;\n                    best_a = op;\n                }\n            }\n            if (best_d <= 0) break;\n        } else {\n            pair<ll, int> top[10];\n            int tn = 0;\n            for (int op = 0; op < TOTAL_OPS; ++op) {\n                ll d = delta_add(board.data(), op);\n                if (d <= 0) continue;\n                if (tn < 10) {\n                    top[tn++] = {d, op};\n                    if (tn == 10) {\n                        nth_element(top, top + 5, top + 10,\n                                    [](const auto &x, const auto &y) { return x.first > y.first; });\n                        sort(top, top + 5,\n                             [](const auto &x, const auto &y) { return x.first > y.first; });\n                        tn = 5;\n                    }\n                } else if (d > top[4].first) {\n                    top[4] = {d, op};\n                    for (int k = 4; k > 0 && top[k].first > top[k - 1].first; --k)\n                        swap(top[k], top[k - 1]);\n                }\n            }\n            if (tn == 0) break;\n            sort(top, top + tn,\n                 [](const auto &x, const auto &y) { return x.first > y.first; });\n            int t = min(5, tn);\n            int idx = (int)(rng() % (uint64_t)t);\n            best_a = top[idx].second;\n            best_d = top[idx].first;\n        }\n        int slot = -1;\n        for (int i = 0; i < K; ++i)\n            if (sl[i] == NOP) {\n                slot = i;\n                break;\n            }\n        if (slot == -1) break;\n        apply_add(board.data(), best_a);\n        sl[slot] = best_a;\n        score += best_d;\n        ++filled;\n    }\n}\n\n// ------------------------------------------------------------------\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m, k_input;\n    if (!(cin >> n >> m >> k_input)) return 0;\n\n    Board init_board{};\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            uint32_t x;\n            cin >> x;\n            init_board[i * N + j] = x;\n        }\n\n    vector<vector<vector<uint32_t>>> stamp(M,\n        vector<vector<uint32_t>>(3, vector<uint32_t>(3)));\n    for (int s = 0; s < M; ++s)\n        for (int i = 0; i < 3; ++i)\n            for (int j = 0; j < 3; ++j)\n                cin >> stamp[s][i][j];\n\n    int id = 0;\n    for (int s = 0; s < M; ++s)\n        for (int p = 0; p <= N - 3; ++p)\n            for (int q = 0; q <= N - 3; ++q) {\n                int t = 0;\n                for (int di = 0; di < 3; ++di)\n                    for (int dj = 0; dj < 3; ++dj) {\n                        ops[id].cell[t] = (p + di) * N + (q + dj);\n                        ops[id].val[t] = stamp[s][di][dj];\n                        ++t;\n                    }\n                ++id;\n            }\n\n    ll initial_score = 0;\n    for (int i = 0; i < CELLS; ++i) initial_score += init_board[i];\n\n    mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto start = chrono::high_resolution_clock::now();\n    const double TIME_LIMIT = 1.92;\n\n    Slots best;\n    best.fill(NOP);\n    Board best_board = init_board;\n    ll best_score = initial_score;\n\n    // ----- diverse initial solutions -----\n    for (int attempt = 0; attempt < 10; ++attempt) {\n        Slots sl;\n        Board bd;\n        ll sc;\n        if (attempt == 0) {\n            sl.fill(NOP);\n            bd = init_board;\n            sc = initial_score;\n            reconstruct(sl, bd, sc, false, rng);\n        } else if (attempt < 6) {\n            sl.fill(NOP);\n            bd = init_board;\n            sc = initial_score;\n            reconstruct(sl, bd, sc, true, rng);\n        } else {\n            sl.fill(NOP);\n            bd = init_board;\n            sc = initial_score;\n            for (int i = 0; i < K; ++i) {\n                int a = (int)(rng() % TOTAL_OPS);\n                ll d = delta_add(bd.data(), a);\n                apply_add(bd.data(), a);\n                sl[i] = a;\n                sc += d;\n            }\n        }\n        hill_climb(sl, bd, sc);\n        while (probe2(sl, bd, sc, rng))\n            hill_climb(sl, bd, sc);\n        if (sc > best_score) {\n            best_score = sc;\n            best = sl;\n            best_board = bd;\n        }\n    }\n\n    // ----- Ruin-and-Recreate ILS -----\n    Slots cur = best;\n    Board cur_board = best_board;\n    ll cur_score = best_score;\n\n    while (true) {\n        auto now = chrono::high_resolution_clock::now();\n        if (chrono::duration<double>(now - start).count() > TIME_LIMIT) break;\n\n        int used = 0;\n        for (int i = 0; i < K; ++i)\n            if (cur[i] != NOP) ++used;\n        if (used == 0) {\n            cur = best;\n            cur_board = best_board;\n            cur_score = best_score;\n            continue;\n        }\n\n        int r;\n        int mode = (int)(rng() % 10);\n        if (mode < 5)\n            r = 1 + (int)(rng() % 3);\n        else if (mode < 8)\n            r = 2 + (int)(rng() % 5);\n        else\n            r = 6 + (int)(rng() % 10);\n        if (r > used) r = used;\n\n        for (int t = 0; t < r; ++t) {\n            int idx;\n            do {\n                idx = (int)(rng() % K);\n            } while (cur[idx] == NOP);\n            int op = cur[idx];\n            cur_score += delta_remove(cur_board.data(), op);\n            apply_remove(cur_board.data(), op);\n            cur[idx] = NOP;\n        }\n\n        // try two reconstructions and keep the best\n        Slots best_rec_sl = cur;\n        Board best_rec_bd = cur_board;\n        ll best_rec_sc = cur_score;\n\n        for (int att = 0; att < 2; ++att) {\n            Slots tmp_sl = cur;\n            Board tmp_bd = cur_board;\n            ll tmp_sc = cur_score;\n            reconstruct(tmp_sl, tmp_bd, tmp_sc, att > 0, rng);\n            hill_climb(tmp_sl, tmp_bd, tmp_sc);\n            while (probe2(tmp_sl, tmp_bd, tmp_sc, rng))\n                hill_climb(tmp_sl, tmp_bd, tmp_sc);\n            if (tmp_sc > best_rec_sc) {\n                best_rec_sc = tmp_sc;\n                best_rec_sl = tmp_sl;\n                best_rec_bd = tmp_bd;\n            }\n        }\n\n        cur = best_rec_sl;\n        cur_board = best_rec_bd;\n        cur_score = best_rec_sc;\n\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best = cur;\n            best_board = cur_board;\n        } else {\n            cur = best;\n            cur_board = best_board;\n            cur_score = best_score;\n        }\n    }\n\n    // final polish on absolute best\n    hill_climb(best, best_board, best_score);\n    while (probe2(best, best_board, best_score, rng))\n        hill_climb(best, best_board, best_score);\n\n    int L = 0;\n    for (int i = 0; i < K; ++i)\n        if (best[i] != NOP) ++L;\n    cout << L << '\\n';\n    for (int i = 0; i < K; ++i) {\n        if (best[i] == NOP) continue;\n        int op = best[i];\n        int mm = op / POS;\n        int rest = op % POS;\n        int p = rest / 7;\n        int q = rest % 7;\n        cout << mm << ' ' << p << ' ' << q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nint A[5][5];\n\nstruct Result {\n    vector<char> ops;\n    int turns;\n};\n\nResult simulate(unsigned seed, bool deterministic) {\n    mt19937 rng(seed);\n    int grid[5][5];\n    memset(grid, -1, sizeof(grid));\n    int cr = 0, cc = 0, hold = -1, hold_src = -1;\n    int dispatched[5] = {0}, next_in[5] = {0};\n    vector<char> ops;\n    ops.reserve(500);\n\n    auto need = [&](int r) -> int { return 5 * r + dispatched[r]; };\n\n    auto toward = [&](int r, int c, int tr, int tc) -> char {\n        if (r == tr && c == tc) return '.';\n        if (r < tr) return 'D';\n        if (r > tr) return 'U';\n        if (c < tc) return 'R';\n        return 'L';\n    };\n\n    auto buffer_for = [&](int src, int dst) -> pair<int,int> {\n        for (int c : {3, 2, 1})\n            if (grid[src][c] == -1) return {src, c};\n        for (int c : {3, 2, 1})\n            if (grid[dst][c] == -1) return {dst, c};\n        for (int r = 0; r < 5; ++r)\n            if (next_in[r] >= 5 && grid[r][0] == -1) return {r, 0};\n        for (int c : {3, 2, 1})\n            for (int r = 0; r < 5; ++r)\n                if (r != src && r != dst && grid[r][c] == -1) return {r, c};\n        return {-1, -1};\n    };\n\n    for (int turn = 0; turn < 10000; ++turn) {\n        for (int i = 0; i < 5; ++i) {\n            if (next_in[i] < 5 && grid[i][0] == -1 && !(cr == i && cc == 0 && hold != -1))\n                grid[i][0] = A[i][next_in[i]++];\n        }\n\n        char act = '.';\n\n        if (hold != -1) {\n            int row = hold / 5;\n            if (hold == need(row)) {\n                if (cr == row && cc == 4) act = (grid[row][4] == -1) ? 'Q' : '.';\n                else act = toward(cr, cc, row, 4);\n            } else {\n                auto [tr, tc] = buffer_for(hold_src, row);\n                if (tr == -1) act = '.';\n                else if (cr == tr && cc == tc) act = 'Q';\n                else act = toward(cr, cc, tr, tc);\n            }\n        } else {\n            struct Item { int dist, r, c; };\n            vector<Item> items;\n            for (int row = 0; row < 5; ++row) {\n                if (dispatched[row] >= 5) continue;\n                int nid = need(row);\n                for (int r = 0; r < 5; ++r)\n                    for (int c = 0; c <= 3; ++c)\n                        if (grid[r][c] == nid)\n                            items.push_back({abs(cr - r) + abs(cc - c), r, c});\n            }\n            if (!items.empty()) {\n                int best = 1e9;\n                for (auto &it : items) best = min(best, it.dist);\n                vector<Item> cand;\n                for (auto &it : items)\n                    if (it.dist <= best + 1) cand.push_back(it);\n                const Item &pick = cand[deterministic ? 0 : (rng() % cand.size())];\n                act = (cr == pick.r && cc == pick.c) ? 'P' : toward(cr, cc, pick.r, pick.c);\n            } else {\n                struct Gate { int i, score; };\n                vector<Gate> gates;\n                for (int i = 0; i < 5; ++i) {\n                    int dist = abs(cr - i) + abs(cc - 0);\n                    if (grid[i][0] == -1) {\n                        if (next_in[i] < 5) {\n                            int nxt = A[i][next_in[i]];\n                            int r = nxt / 5;\n                            if (nxt == need(r)) gates.push_back({i, 2000000 - dist * 100});\n                            else gates.push_back({i, -dist});\n                        }\n                        continue;\n                    }\n                    int cont = grid[i][0];\n                    int row = cont / 5;\n                    if (cont == need(row)) {\n                        gates.push_back({i, 1000000 - dist * 100});\n                        continue;\n                    }\n                    int cur = next_in[i] - 1;\n                    int depth = 100, penalty = 0;\n                    for (int d = 0; cur + d < 5; ++d) {\n                        int cid = A[i][cur + d];\n                        int r = cid / 5;\n                        if (cid == need(r)) { depth = d; break; }\n                        penalty += abs(r - i);\n                    }\n                    int score = 100000 - depth * 5000 - dist * 100 - penalty * 10;\n                    if (!deterministic) score += uniform_int_distribution<int>(-150, 150)(rng);\n                    gates.push_back({i, score});\n                }\n\n                if (!gates.empty()) {\n                    sort(gates.begin(), gates.end(),\n                         [](const Gate &a, const Gate &b) { return a.score > b.score; });\n                    int top = gates[0].score;\n                    vector<int> cand;\n                    for (auto &g : gates)\n                        if (g.score >= top - 300) cand.push_back(g.i);\n                    int pick = cand[deterministic ? 0 : (rng() % cand.size())];\n\n                    if (cr == pick && cc == 0) {\n                        int cont = grid[pick][0];\n                        bool needed_now = false;\n                        for (int row = 0; row < 5; ++row)\n                            if (dispatched[row] < 5 && cont == need(row)) needed_now = true;\n                        if (!needed_now) {\n                            auto buf = buffer_for(pick, cont / 5);\n                            act = (buf.first == -1) ? '.' : 'P';\n                        } else act = 'P';\n                    } else {\n                        act = toward(cr, cc, pick, 0);\n                    }\n                } else {\n                    act = '.';\n                }\n            }\n        }\n\n        if (act == 'P') {\n            hold = grid[cr][cc];\n            grid[cr][cc] = -1;\n            hold_src = cr;\n        } else if (act == 'Q') {\n            grid[cr][cc] = hold;\n            hold = -1;\n            hold_src = -1;\n        } else if (act == 'U') {\n            --cr;\n        } else if (act == 'D') {\n            ++cr;\n        } else if (act == 'L') {\n            --cc;\n        } else if (act == 'R') {\n            ++cc;\n        }\n        ops.push_back(act);\n\n        for (int i = 0; i < 5; ++i)\n            if (grid[i][4] != -1) {\n                ++dispatched[i];\n                grid[i][4] = -1;\n            }\n\n        bool done = true;\n        for (int i = 0; i < 5; ++i)\n            if (dispatched[i] < 5) done = false;\n        if (done) break;\n    }\n    return {ops, (int)ops.size()};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    cin >> N;\n    for (int i = 0; i < 5; ++i)\n        for (int j = 0; j < 5; ++j)\n            cin >> A[i][j];\n\n    Result best = simulate(0, true);\n    for (int iter = 1; iter < 20000; ++iter) {\n        Result cur = simulate(iter, false);\n        if (cur.turns < best.turns) best = cur;\n    }\n\n    size_t T = best.ops.size();\n    string s0(best.ops.begin(), best.ops.end());\n    cout << s0 << '\\n';\n    for (int k = 1; k < 5; ++k) {\n        cout << 'B';\n        for (size_t i = 1; i < T; ++i) cout << '.';\n        cout << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Result {\n    long long cost = 0;\n    vector<string> ops;\n    bool valid = false;\n};\n\nstruct SeedParams {\n    uint64_t seed;\n    bool smart;\n    double w_amt, w_pot;\n    int tb_mode;          // 0=rand, 1=large first, 2=small first  (pure NN only)\n    long long cost;\n};\n\n/* =============================================================\n   Deterministic route from a visitation order\n   ============================================================= */\nResult solve_given_order(const vector<vector<int>>& h,\n                         const vector<pair<int,int>>& order)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n    for (auto [tr, tc] : order) {\n        if (r == tr && c == tc) continue;\n        move_to(tr, tc);\n    }\n    while (load > 0) {\n        int tr = -1, tc = -1, best = 1e9;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] < 0) {\n                    int d = abs(r - i) + abs(c - j);\n                    if (d < best) { best = d; tr = i; tc = j; }\n                }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* =============================================================\n   Deterministic greedy variants\n   ============================================================= */\nResult solve_greedy(const vector<vector<int>>& h) {\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n        int tr = -1, tc = -1, best = 1e9;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        int d = abs(r - i) + abs(c - j);\n                        if (d < best) { best = d; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\nResult solve_lookahead(const vector<vector<int>>& h,\n                       const vector<vector<int>>& nearest_snk,\n                       const vector<vector<int>>& nearest_src,\n                       double w_empty, double w_loaded)\n{\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n        int tr = -1, tc = -1;\n        double best = 1e100;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        double sc = abs(r - i) + abs(c - j) + w_empty * nearest_snk[i][j];\n                        if (sc < best) { best = sc; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        double sc = abs(r - i) + abs(c - j) + w_loaded * nearest_src[i][j];\n                        if (sc < best) { best = sc; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\nResult solve_weighted(const vector<vector<int>>& h) {\n    int N = (int)h.size();\n    auto need = h;\n    int load = 0, r = 0, c = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n\n    auto process = [&](int cr, int cc) {\n        if (need[cr][cc] > 0) {\n            int d = need[cr][cc];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d; load += d; need[cr][cc] = 0;\n        } else if (need[cr][cc] < 0 && load > 0) {\n            int d = min(load, -need[cr][cc]);\n            if (d > 0) {\n                ops.push_back(\"-\" + to_string(d));\n                cost += d; load -= d; need[cr][cc] += d;\n            }\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            if (r < tr)       { ops.push_back(\"D\"); ++r; }\n            else if (r > tr)  { ops.push_back(\"U\"); --r; }\n            else if (c < tc)  { ops.push_back(\"R\"); ++c; }\n            else              { ops.push_back(\"L\"); --c; }\n            cost += 100 + load;\n            process(r, c);\n        }\n    };\n    process(r, c);\n\n    while (true) {\n        bool has_pos = false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (need[i][j] > 0) has_pos = true;\n        if (!has_pos && load == 0) break;\n        int tr = -1, tc = -1;\n        double best = -1.0;\n        if (load == 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] > 0) {\n                        double sc = need[i][j] / double(abs(r - i) + abs(c - j) + 1);\n                        if (sc > best) { best = sc; tr = i; tc = j; }\n                    }\n        } else {\n            for (int i = 0; i < N; ++i)\n                for (int j = 0; j < N; ++j)\n                    if (need[i][j] < 0) {\n                        double sc = (-need[i][j]) / double(abs(r - i) + abs(c - j) + 1);\n                        if (sc > best) { best = sc; tr = i; tc = j; }\n                    }\n        }\n        if (tr == -1) break;\n        move_to(tr, tc);\n    }\n    bool ok = (load == 0);\n    for (int i = 0; i < N && ok; ++i)\n        for (int j = 0; j < N && ok; ++j)\n            if (need[i][j] != 0) ok = false;\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* =============================================================\n   Path generators\n   ============================================================= */\nvector<pair<int,int>> spiral_snake(int N, bool row_first) {\n    vector<vector<bool>> vis(N, vector<bool>(N, false));\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    int r = 0, c = 0, dr = row_first ? 0 : 1, dc = row_first ? 1 : 0;\n    for (int step = 0; step < N * N; ++step) {\n        res.emplace_back(r, c);\n        vis[r][c] = true;\n        int nr = r + dr, nc = c + dc;\n        if (nr < 0 || nr >= N || nc < 0 || nc >= N || vis[nr][nc]) {\n            int ndr = row_first ? dc : -dc;\n            int ndc = row_first ? -dr : dr;\n            dr = ndr; dc = ndc;\n            nr = r + dr; nc = c + dc;\n        }\n        r = nr; c = nc;\n    }\n    return res;\n}\n\nvector<pair<int,int>> diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int s = 0; s <= 2 * (N - 1); ++s) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = s - i;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        bool revflag = (s % 2 == (rev ? 0 : 1));\n        if (revflag) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nvector<pair<int,int>> anti_diagonal_snake(int N, bool rev) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    for (int d = -(N - 1); d <= N - 1; ++d) {\n        vector<pair<int,int>> cells;\n        for (int i = 0; i < N; ++i) {\n            int j = i - d;\n            if (0 <= j && j < N) cells.emplace_back(i, j);\n        }\n        if (cells.empty()) continue;\n        int parity = d & 1;\n        bool revflag = (parity == (rev ? 1 : 0));\n        if (revflag) std::reverse(cells.begin(), cells.end());\n        for (auto &p : cells) res.push_back(p);\n    }\n    return res;\n}\n\nstatic uint32_t spread(uint32_t x) {\n    x = (x | (x << 8)) & 0x00FF00FFu;\n    x = (x | (x << 4)) & 0x0F0F0F0Fu;\n    x = (x | (x << 2)) & 0x33333333u;\n    x = (x | (x << 1)) & 0x55555555u;\n    return x;\n}\nstatic uint32_t morton2(uint32_t x, uint32_t y) {\n    return spread(x) | (spread(y) << 1);\n}\nvector<pair<int,int>> zorder_snake(int N) {\n    vector<pair<int,int>> cells;\n    cells.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cells.emplace_back(i, j);\n    sort(cells.begin(), cells.end(),\n         [](const pair<int,int>& a, const pair<int,int>& b){\n             return morton2((uint32_t)a.first, (uint32_t)a.second)\n                  < morton2((uint32_t)b.first, (uint32_t)b.second);\n         });\n    return cells;\n}\n\nvector<pair<int,int>> strip_snake(int N, int sh, bool rev_blocks) {\n    vector<pair<int,int>> res;\n    res.reserve(N * N);\n    int num_blocks = (N + sh - 1) / sh;\n    for (int b = 0; b < num_blocks; ++b) {\n        int bi = rev_blocks ? (num_blocks - 1 - b) : b;\n        int r0 = bi * sh;\n        int r1 = min(N, r0 + sh);\n        for (int c = 0; c < N; ++c) {\n            if (c % 2 == 0) {\n                for (int r = r0; r < r1; ++r) res.emplace_back(r, c);\n            } else {\n                for (int r = r1 - 1; r >= r0; --r) res.emplace_back(r, c);\n            }\n        }\n    }\n    return res;\n}\n\nvector<pair<int,int>> height_snake(const vector<vector<int>>& h, bool desc, bool absval) {\n    int N = (int)h.size();\n    vector<pair<int,int>> cells;\n    cells.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cells.emplace_back(i, j);\n    sort(cells.begin(), cells.end(),\n        [&](const pair<int,int>& a, const pair<int,int>& b){\n            int va = h[a.first][a.second];\n            int vb = h[b.first][b.second];\n            if (absval) {\n                if (abs(va) != abs(vb)) return abs(va) > abs(vb);\n            } else {\n                if (va != vb) return desc ? (va > vb) : (va < vb);\n            }\n            if (a.first != b.first) return a.first < b.first;\n            return a.second < b.second;\n        });\n    return cells;\n}\n\nvector<pair<int,int>> angle_snake(const vector<vector<int>>& h, double cx, double cy, bool rev) {\n    int N = (int)h.size();\n    vector<pair<int,int>> cells;\n    cells.reserve(N * N);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cells.emplace_back(i, j);\n    sort(cells.begin(), cells.end(),\n        [&](const pair<int,int>& a, const pair<int,int>& b){\n            double angA = atan2(a.first - cy, a.second - cx);\n            double angB = atan2(b.first - cy, b.second - cx);\n            if (angA != angB) return rev ? (angA > angB) : (angA < angB);\n            double da = hypot(a.first - cy, a.second - cx);\n            double db = hypot(b.first - cy, b.second - cx);\n            return da < db;\n        });\n    return cells;\n}\n\n/* =============================================================\n   Fast random evaluator\n   ============================================================= */\nstruct FastEval {\n    int N, n2;\n    const vector<vector<int>> &dist;\n    vector<int> need;\n    vector<int> pos, neg;\n    vector<int> pos_of, neg_of;\n    int load = 0, r = 0, c = 0, steps = 0;\n    long long cost = 0;\n    mt19937_64 rng;\n    bool smart;\n    double w_amt, w_pot;\n    int tb_mode; // 0=rand, 1=large, 2=small\n    const vector<int> *pot_src;\n    const vector<int> *pot_snk;\n\n    FastEval(const vector<vector<int>>& h,\n             const vector<vector<int>>& d,\n             uint64_t seed,\n             bool sm,\n             double wa, double wp,\n             int tm,\n             const vector<int>* ps,\n             const vector<int>* pn)\n        : dist(d), rng(seed), smart(sm), w_amt(wa), w_pot(wp), tb_mode(tm),\n          pot_src(ps), pot_snk(pn)\n    {\n        N = (int)h.size(); n2 = N * N;\n        need.resize(n2);\n        pos_of.assign(n2, -1); neg_of.assign(n2, -1);\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j) {\n                int id = i * N + j;\n                need[id] = h[i][j];\n                if (need[id] > 0) {\n                    pos_of[id] = (int)pos.size();\n                    pos.push_back(id);\n                } else if (need[id] < 0) {\n                    neg_of[id] = (int)neg.size();\n                    neg.push_back(id);\n                }\n            }\n        process(0);\n    }\n\n    inline void remove_pos(int id) {\n        int p = pos_of[id], back = pos.back();\n        pos[p] = back; pos_of[back] = p;\n        pos.pop_back(); pos_of[id] = -1;\n    }\n    inline void remove_neg(int id) {\n        int p = neg_of[id], back = neg.back();\n        neg[p] = back; neg_of[back] = p;\n        neg.pop_back(); neg_of[id] = -1;\n    }\n    inline void process(int id) {\n        int v = need[id];\n        if (v > 0) {\n            cost += v; load += v; need[id] = 0;\n            remove_pos(id); ++steps;\n        } else if (v < 0 && load > 0) {\n            int d = min(load, -v);\n            cost += d; load -= d; need[id] += d; ++steps;\n            if (need[id] == 0) remove_neg(id);\n        }\n    }\n\n    inline int choose_target(bool want_pos) {\n        const auto& vec = want_pos ? pos : neg;\n        if (vec.empty()) return -1;\n        int cur = r * N + c;\n        if (!smart) {\n            int best_d = INT_MAX, ch = -1, cnt = 0;\n            int best_amt = (tb_mode == 2) ? INT_MAX : -1;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                int amt = want_pos ? need[id] : -need[id];\n                if (d < best_d) {\n                    best_d = d; ch = id; cnt = 1;\n                    best_amt = amt;\n                } else if (d == best_d) {\n                    if (tb_mode == 0) {\n                        ++cnt;\n                        if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                    } else if (tb_mode == 1) {\n                        if (amt > best_amt) {\n                            best_amt = amt; ch = id; cnt = 1;\n                        } else if (amt == best_amt) {\n                            ++cnt;\n                            if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                        }\n                    } else { // tb_mode == 2\n                        if (amt < best_amt) {\n                            best_amt = amt; ch = id; cnt = 1;\n                        } else if (amt == best_amt) {\n                            ++cnt;\n                            if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                        }\n                    }\n                }\n            }\n            return ch;\n        } else {\n            double best = 1e100;\n            int ch = -1, cnt = 0;\n            const vector<int> *pot = want_pos ? pot_snk : pot_src;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                double actual = want_pos ? (double)need[id]\n                                         : min((double)load, -(double)need[id]);\n                double score = d - w_amt * actual + w_pot * (*pot)[id];\n                if (score < best) {\n                    best = score; ch = id; cnt = 1;\n                } else if (score == best) {\n                    ++cnt;\n                    if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                }\n            }\n            return ch;\n        }\n    }\n\n    inline void move_to(int tr, int tc, long long limit) {\n        while (r != tr || c != tc) {\n            bool mv_r = (r != tr), mv_c = (c != tc);\n            if (mv_r && mv_c) {\n                if (rng() & 1ULL) {\n                    if (r < tr) ++r; else --r;\n                } else {\n                    if (c < tc) ++c; else --c;\n                }\n            } else if (mv_r) {\n                if (r < tr) ++r; else --r;\n            } else {\n                if (c < tc) ++c; else --c;\n            }\n            cost += 100 + load;\n            ++steps;\n            process(r * N + c);\n            if (steps > 100000 || cost >= limit) {\n                steps = 100001;\n                return;\n            }\n        }\n    }\n\n    long long evaluate(long long limit) {\n        while (!pos.empty() || load > 0) {\n            int tid = (load == 0) ? choose_target(true) : choose_target(false);\n            if (tid == -1) break;\n            move_to(tid / N, tid % N, limit);\n            if (steps > 100000) return LLONG_MAX;\n        }\n        if (load != 0 || !pos.empty() || steps > 100000) return LLONG_MAX;\n        return cost;\n    }\n};\n\n/* =============================================================\n   Build full operation list from a FastEval seed\n   ============================================================= */\nResult build_fast(const vector<vector<int>>& h,\n                  const vector<vector<int>>& dist,\n                  uint64_t seed,\n                  bool smart,\n                  double w_amt, double w_pot,\n                  int tb_mode,\n                  const vector<int>& pot_src,\n                  const vector<int>& pot_snk)\n{\n    int N = (int)h.size(), n2 = N * N;\n    vector<int> need(n2);\n    vector<int> pos, neg;\n    vector<int> pos_of(n2, -1), neg_of(n2, -1);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            int id = i * N + j;\n            need[id] = h[i][j];\n            if (need[id] > 0) {\n                pos_of[id] = (int)pos.size();\n                pos.push_back(id);\n            } else if (need[id] < 0) {\n                neg_of[id] = (int)neg.size();\n                neg.push_back(id);\n            }\n        }\n    int load = 0, r = 0, c = 0, steps = 0;\n    long long cost = 0;\n    vector<string> ops;\n    ops.reserve(80000);\n    mt19937_64 rng(seed);\n\n    auto remove_pos = [&](int id) {\n        int p = pos_of[id], back = pos.back();\n        pos[p] = back; pos_of[back] = p;\n        pos.pop_back(); pos_of[id] = -1;\n    };\n    auto remove_neg = [&](int id) {\n        int p = neg_of[id], back = neg.back();\n        neg[p] = back; neg_of[back] = p;\n        neg.pop_back(); neg_of[id] = -1;\n    };\n    auto process = [&](int id) {\n        int v = need[id];\n        if (v > 0) {\n            ops.push_back(\"+\" + to_string(v));\n            cost += v; load += v; need[id] = 0;\n            remove_pos(id); ++steps;\n        } else if (v < 0 && load > 0) {\n            int d = min(load, -v);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d; load -= d; need[id] += d; ++steps;\n            if (need[id] == 0) remove_neg(id);\n        }\n    };\n    auto choose_target = [&](bool want_pos) -> int {\n        const auto& vec = want_pos ? pos : neg;\n        if (vec.empty()) return -1;\n        int cur = r * N + c;\n        if (!smart) {\n            int best_d = INT_MAX, ch = -1, cnt = 0;\n            int best_amt = (tb_mode == 2) ? INT_MAX : -1;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                int amt = want_pos ? need[id] : -need[id];\n                if (d < best_d) {\n                    best_d = d; ch = id; cnt = 1;\n                    best_amt = amt;\n                } else if (d == best_d) {\n                    if (tb_mode == 0) {\n                        ++cnt;\n                        if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                    } else if (tb_mode == 1) {\n                        if (amt > best_amt) {\n                            best_amt = amt; ch = id; cnt = 1;\n                        } else if (amt == best_amt) {\n                            ++cnt;\n                            if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                        }\n                    } else {\n                        if (amt < best_amt) {\n                            best_amt = amt; ch = id; cnt = 1;\n                        } else if (amt == best_amt) {\n                            ++cnt;\n                            if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                        }\n                    }\n                }\n            }\n            return ch;\n        } else {\n            double best = 1e100;\n            int ch = -1, cnt = 0;\n            const vector<int> *pot = want_pos ? &pot_snk : &pot_src;\n            for (int id : vec) {\n                int d = dist[cur][id];\n                double actual = want_pos ? (double)need[id]\n                                         : min((double)load, -(double)need[id]);\n                double score = d - w_amt * actual + w_pot * (*pot)[id];\n                if (score < best) {\n                    best = score; ch = id; cnt = 1;\n                } else if (score == best) {\n                    ++cnt;\n                    if ((int)(rng() % (uint64_t)cnt) == 0) ch = id;\n                }\n            }\n            return ch;\n        }\n    };\n    auto move_to = [&](int tr, int tc) {\n        while (r != tr || c != tc) {\n            bool mv_r = (r != tr), mv_c = (c != tc);\n            if (mv_r && mv_c) {\n                if (rng() & 1ULL) {\n                    if (r < tr) { ops.push_back(\"D\"); ++r; }\n                    else        { ops.push_back(\"U\"); --r; }\n                } else {\n                    if (c < tc) { ops.push_back(\"R\"); ++c; }\n                    else        { ops.push_back(\"L\"); --c; }\n                }\n            } else if (mv_r) {\n                if (r < tr) { ops.push_back(\"D\"); ++r; }\n                else        { ops.push_back(\"U\"); --r; }\n            } else {\n                if (c < tc) { ops.push_back(\"R\"); ++c; }\n                else        { ops.push_back(\"L\"); --c; }\n            }\n            cost += 100 + load;\n            ++steps;\n            process(r * N + c);\n            if (steps > 100000) return;\n        }\n    };\n\n    process(0);\n    while (!pos.empty() || load > 0) {\n        int tid = (load == 0) ? choose_target(true) : choose_target(false);\n        if (tid == -1) break;\n        move_to(tid / N, tid % N);\n        if (steps > 100000) return Result{0, {}, false};\n    }\n    bool ok = (load == 0 && pos.empty());\n    if ((int)ops.size() > 100000) ok = false;\n    return {cost, ops, ok};\n}\n\n/* =============================================================\n   Main\n   ============================================================= */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    auto start = chrono::steady_clock::now();\n    auto elapsed = [&](){\n        return chrono::duration<double>(chrono::steady_clock::now() - start).count();\n    };\n\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    int N2 = N * N;\n    vector<vector<int>> dist(N2, vector<int>(N2));\n    for (int i = 0; i < N2; ++i) {\n        int r = i / N, c = i % N;\n        for (int j = 0; j < N2; ++j) {\n            int rr = j / N, cc = j % N;\n            dist[i][j] = abs(r - rr) + abs(c - cc);\n        }\n    }\n\n    vector<vector<int>> nearest_src(N, vector<int>(N, INT_MAX));\n    vector<vector<int>> nearest_snk(N, vector<int>(N, INT_MAX));\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) {\n        if (h[i][j] > 0) {\n            for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y)\n                nearest_snk[x][y] = min(nearest_snk[x][y], abs(x - i) + abs(y - j));\n        } else if (h[i][j] < 0) {\n            for (int x = 0; x < N; ++x) for (int y = 0; y < N; ++y)\n                nearest_src[x][y] = min(nearest_src[x][y], abs(x - i) + abs(y - j));\n        }\n    }\n\n    vector<int> pot_src(N2, INT_MAX), pot_snk(N2, INT_MAX);\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            pot_src[i * N + j] = nearest_src[i][j];\n            pot_snk[i * N + j] = nearest_snk[i][j];\n        }\n\n    Result best; best.valid = false; best.cost = LLONG_MAX;\n    auto upd = [&](const Result& res){\n        if (res.valid && res.cost < best.cost) best = res;\n    };\n\n    /* --- row / column snakes --- */\n    vector<pair<int,int>> ord;\n    for (int i = 0; i < N; ++i) {\n        if (i % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else            for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    ord.clear();\n    for (int i = N - 1; i >= 0; --i) {\n        if ((N - 1 - i) % 2 == 0) for (int j = 0; j < N; ++j) ord.emplace_back(i, j);\n        else                      for (int j = N - 1; j >= 0; --j) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    ord.clear();\n    for (int j = 0; j < N; ++j) {\n        if (j % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else            for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    ord.clear();\n    for (int j = N - 1; j >= 0; --j) {\n        if ((N - 1 - j) % 2 == 0) for (int i = 0; i < N; ++i) ord.emplace_back(i, j);\n        else                      for (int i = N - 1; i >= 0; --i) ord.emplace_back(i, j);\n    }\n    upd(solve_given_order(h, ord));\n\n    /* --- spirals / diagonals / z-order / strips --- */\n    upd(solve_given_order(h, spiral_snake(N, true)));\n    upd(solve_given_order(h, spiral_snake(N, false)));\n    upd(solve_given_order(h, diagonal_snake(N, false)));\n    upd(solve_given_order(h, diagonal_snake(N, true)));\n    upd(solve_given_order(h, anti_diagonal_snake(N, false)));\n    upd(solve_given_order(h, anti_diagonal_snake(N, true)));\n    auto z = zorder_snake(N);\n    upd(solve_given_order(h, z));\n    auto zr = z; reverse(zr.begin(), zr.end());\n    upd(solve_given_order(h, zr));\n\n    upd(solve_given_order(h, strip_snake(N, 2, false)));\n    upd(solve_given_order(h, strip_snake(N, 2, true)));\n    upd(solve_given_order(h, strip_snake(N, 4, false)));\n    upd(solve_given_order(h, strip_snake(N, 4, true)));\n    upd(solve_given_order(h, strip_snake(N, 5, false)));\n    upd(solve_given_order(h, strip_snake(N, 5, true)));\n    upd(solve_given_order(h, strip_snake(N, 10, false)));\n    upd(solve_given_order(h, strip_snake(N, 10, true)));\n\n    /* --- height-ordered snakes --- */\n    upd(solve_given_order(h, height_snake(h, true,  false)));\n    upd(solve_given_order(h, height_snake(h, false, false)));\n    upd(solve_given_order(h, height_snake(h, true,  true )));\n\n    /* --- angle sweep from centre --- */\n    upd(solve_given_order(h, angle_snake(h, (N-1)/2.0, (N-1)/2.0, false)));\n    upd(solve_given_order(h, angle_snake(h, (N-1)/2.0, (N-1)/2.0, true)));\n\n    /* --- deterministic greedy --- */\n    upd(solve_greedy(h));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.0, 0.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.5, 0.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.0, 0.5));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 1.0, 1.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 2.0, 2.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 3.0, 0.0));\n    upd(solve_lookahead(h, nearest_snk, nearest_src, 0.0, 3.0));\n    upd(solve_weighted(h));\n\n    /* --- random greedy (time-guarded) --- */\n    long long prune = best.valid ? best.cost : LLONG_MAX;\n    vector<SeedParams> top;\n    top.reserve(3);\n\n    mt19937_64 param_rng(20240518u);\n    const vector<double> wa_vals = {-1.0, -0.5, -0.1, 0.0, 0.1, 0.3, 0.5, 1.0, 2.0};\n    const vector<double> wp_vals = {0.0, 0.5, 1.0, 2.0, 5.0};\n\n    for (int s = 0; elapsed() < 1.98; ++s) {\n        uint64_t seed = 1234567ULL + (uint64_t)s;\n        SeedParams sp{seed, false, 0, 0, 0, LLONG_MAX};\n\n        if (s % 5 < 3) { // 60% pure NN with varying tiebreak\n            sp.smart = false;\n            sp.tb_mode = (int)(param_rng() % 3ULL);\n            sp.w_amt = 0; sp.w_pot = 0;\n            FastEval eval(h, dist, seed, false, 0, 0, sp.tb_mode, &pot_src, &pot_snk);\n            sp.cost = eval.evaluate(prune);\n        } else { // 40% linear smart\n            sp.smart = true;\n            sp.tb_mode = 0;\n            sp.w_amt = wa_vals[(size_t)(param_rng() % wa_vals.size())];\n            sp.w_pot = wp_vals[(size_t)(param_rng() % wp_vals.size())];\n            FastEval eval(h, dist, seed, true, sp.w_amt, sp.w_pot, 0, &pot_src, &pot_snk);\n            sp.cost = eval.evaluate(prune);\n        }\n\n        if (sp.cost < prune) prune = sp.cost;\n\n        if (sp.cost != LLONG_MAX) {\n            top.push_back(sp);\n            sort(top.begin(), top.end(),\n                 [](const SeedParams& a, const SeedParams& b){ return a.cost < b.cost; });\n            if ((int)top.size() > 3) top.resize(3);\n        }\n    }\n\n    // rebuild top-3 and pick the true best\n    for (const auto& sp : top) {\n        upd(build_fast(h, dist, sp.seed, sp.smart, sp.w_amt, sp.w_pot,\n                       sp.tb_mode, pot_src, pot_snk));\n    }\n\n    if (!best.valid) best = solve_greedy(h);\n    for (auto &s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nconstexpr int N = 6;\nconstexpr int M = 15;\nconstexpr int S = 2 * N * (N - 1); // 60 seeds\nconstexpr int P = N * N;            // 36 cells\n\nint X[S][M];\n\nint nbr[P][4];\nint nbr_cnt[P];\nint deg[P];\nbool is_corner_cell[P];\nint cells_by_deg[P];\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    // ----- pre-compute grid topology -----\n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int id = r * N + c;\n            int k = 0;\n            if (r > 0)     nbr[id][k++] = (r - 1) * N + c;\n            if (r < N - 1) nbr[id][k++] = (r + 1) * N + c;\n            if (c > 0)     nbr[id][k++] = r * N + (c - 1);\n            if (c < N - 1) nbr[id][k++] = r * N + (c + 1);\n            nbr_cnt[id] = k;\n            deg[id] = k;\n            is_corner_cell[id] = (k == 2);\n        }\n    }\n    iota(cells_by_deg, cells_by_deg + P, 0);\n    sort(cells_by_deg, cells_by_deg + P,\n         [&](int a, int b) { return deg[a] > deg[b]; });\n\n    int N_in, M_in, T;\n    while (cin >> N_in >> M_in >> T) {\n        for (int i = 0; i < S; ++i)\n            for (int l = 0; l < M_in; ++l)\n                cin >> X[i][l];\n\n        for (int turn = 0; turn < T; ++turn) {\n            // ---- 1. pool statistics ----\n            int mx[M];\n            fill(mx, mx + M_in, 0);\n            for (int i = 0; i < S; ++i)\n                for (int l = 0; l < M_in; ++l)\n                    if (X[i][l] > mx[l]) mx[l] = X[i][l];\n\n            int V[S];\n            int mask[S];\n            int pool_cnt[M] = {0};\n            for (int i = 0; i < S; ++i) {\n                int s = 0, m = 0;\n                for (int l = 0; l < M_in; ++l) {\n                    s += X[i][l];\n                    if (X[i][l] == mx[l]) {\n                        m |= (1 << l);\n                        ++pool_cnt[l];\n                    }\n                }\n                V[i] = s;\n                mask[i] = m;\n            }\n\n            int need[M];\n            for (int l = 0; l < M_in; ++l)\n                need[l] = min(2, pool_cnt[l]);\n\n            // ---- 2. greedy selection ----\n            bool in_sel[S] = {false};\n            int selected[P];\n            int sel_cnt[M] = {0};\n            int nsel = 0;\n\n            // force pool-unique carriers first\n            for (int l = 0; l < M_in; ++l) {\n                if (pool_cnt[l] == 1) {\n                    for (int i = 0; i < S; ++i)\n                        if (((mask[i] >> l) & 1) && !in_sel[i]) {\n                            in_sel[i] = true;\n                            selected[nsel++] = i;\n                            for (int ll = 0; ll < M_in; ++ll)\n                                if ((mask[i] >> ll) & 1) ++sel_cnt[ll];\n                            break;\n                        }\n                }\n            }\n\n            while (nsel < P) {\n                long long best_sc = -1;\n                int best_i = -1;\n                for (int i = 0; i < S; ++i) if (!in_sel[i]) {\n                    long long urg = 0;\n                    int pc = __builtin_popcount(mask[i]);\n                    for (int l = 0; l < M_in; ++l) if ((mask[i] >> l) & 1) {\n                        if (sel_cnt[l] < need[l]) {\n                            int w = (pool_cnt[l] == 1) ? 50000 :\n                                    (pool_cnt[l] == 2) ? 10000 : 3000;\n                            urg += 1LL * mx[l] * w;\n                        }\n                        if (pool_cnt[l] <= 2) urg += 4000LL;\n                    }\n                    long long sc = 1LL * V[i] * 10 + 100LL * pc + urg;\n                    if (sc > best_sc) {\n                        best_sc = sc;\n                        best_i = i;\n                    }\n                }\n                in_sel[best_i] = true;\n                selected[nsel++] = best_i;\n                for (int l = 0; l < M_in; ++l)\n                    if ((mask[best_i] >> l) & 1) ++sel_cnt[l];\n            }\n\n            // ---- 3. repair: every coordinate must appear at least once ----\n            auto rebuild_sel_cnt = [&]() {\n                fill(sel_cnt, sel_cnt + M_in, 0);\n                for (int s = 0; s < P; ++s)\n                    for (int l = 0; l < M_in; ++l)\n                        if ((mask[selected[s]] >> l) & 1) ++sel_cnt[l];\n            };\n\n            for (int l = 0; l < M_in; ++l) if (sel_cnt[l] == 0) {\n                int best_i = -1, best_v = -1;\n                for (int i = 0; i < S; ++i)\n                    if (!in_sel[i] && ((mask[i] >> l) & 1) && V[i] > best_v) {\n                        best_v = V[i]; best_i = i;\n                    }\n                if (best_i == -1) continue;\n                int worst_pos = -1, worst_v = INT_MAX;\n                for (int s = 0; s < P; ++s) {\n                    int old = selected[s];\n                    bool sole_pool_unique = false;\n                    for (int ll = 0; ll < M_in; ++ll)\n                        if (((mask[old] >> ll) & 1) && pool_cnt[ll] == 1) {\n                            sole_pool_unique = true; break;\n                        }\n                    if (!sole_pool_unique && V[old] < worst_v) {\n                        worst_v = V[old];\n                        worst_pos = s;\n                    }\n                }\n                if (worst_pos != -1) {\n                    in_sel[selected[worst_pos]] = false;\n                    selected[worst_pos] = best_i;\n                    in_sel[best_i] = true;\n                    rebuild_sel_cnt();\n                }\n            }\n\n            // ---- 4. classify selected seeds ----\n            bool is_unique_sel[P] = {false};\n            bool is_rare_sel[P] = {false};\n            for (int s = 0; s < P; ++s) {\n                int i = selected[s];\n                for (int l = 0; l < M_in; ++l) if ((mask[i] >> l) & 1) {\n                    if (pool_cnt[l] == 1) is_unique_sel[s] = true;\n                    if (pool_cnt[l] == 2) is_rare_sel[s] = true;\n                }\n            }\n\n            int sel_V[P];\n            int sel_mval[P];\n            for (int s = 0; s < P; ++s) {\n                int i = selected[s];\n                sel_V[s] = V[i];\n                int mv = 0;\n                for (int l = 0; l < M_in; ++l)\n                    if (X[i][l] == mx[l]) mv += mx[l];\n                sel_mval[s] = mv;\n            }\n\n            // ---- 5. potential matrix (pure sum of max) ----\n            static int pot[P][P];\n            for (int i = 0; i < P; ++i) {\n                int a = selected[i];\n                for (int j = i + 1; j < P; ++j) {\n                    int b = selected[j];\n                    int s = 0;\n                    for (int l = 0; l < M_in; ++l)\n                        s += max(X[a][l], X[b][l]);\n                    pot[i][j] = pot[j][i] = s;\n                }\n            }\n\n            // ---- 6. greedy placement with interior reservation for rare seeds ----\n            int pos2idx[P];\n            for (int i = 0; i < P; ++i) pos2idx[i] = -1;\n            bool used_seed[P] = {false};\n\n            int n_rare_sel_total = 0;\n            for (int s = 0; s < P; ++s)\n                if (is_unique_sel[s] || is_rare_sel[s]) ++n_rare_sel_total;\n            int rare_placed = 0;\n\n            for (int ci = 0; ci < P; ++ci) {\n                int cell = cells_by_deg[ci];\n                bool corner = is_corner_cell[cell];\n                bool interior = (deg[cell] == 4);\n                int best_s = -1;\n                int best_gain = -1;\n                int best_pri = -1;\n\n                if (interior && rare_placed < n_rare_sel_total) {\n                    // first try unique carriers\n                    for (int s = 0; s < P; ++s) {\n                        if (used_seed[s] || !is_unique_sel[s]) continue;\n                        int gain = 0;\n                        for (int k = 0; k < nbr_cnt[cell]; ++k) {\n                            int nb = nbr[cell][k];\n                            if (pos2idx[nb] != -1) gain += pot[s][pos2idx[nb]];\n                        }\n                        int pri = sel_mval[s] * 10 + sel_V[s];\n                        if (gain > best_gain || (gain == best_gain && pri > best_pri)) {\n                            best_gain = gain; best_s = s; best_pri = pri;\n                        }\n                    }\n                    // then try pool_cnt==2 carriers\n                    if (best_s == -1) {\n                        for (int s = 0; s < P; ++s) {\n                            if (used_seed[s] || !is_rare_sel[s] || is_unique_sel[s]) continue;\n                            int gain = 0;\n                            for (int k = 0; k < nbr_cnt[cell]; ++k) {\n                                int nb = nbr[cell][k];\n                                if (pos2idx[nb] != -1) gain += pot[s][pos2idx[nb]];\n                            }\n                            int pri = sel_mval[s] * 10 + sel_V[s];\n                            if (gain > best_gain || (gain == best_gain && pri > best_pri)) {\n                                best_gain = gain; best_s = s; best_pri = pri;\n                            }\n                        }\n                    }\n                    if (best_s != -1) ++rare_placed;\n                }\n\n                if (best_s == -1) {\n                    for (int s = 0; s < P; ++s) {\n                        if (used_seed[s]) continue;\n                        if (corner && (is_unique_sel[s] || is_rare_sel[s])) continue;\n                        int gain = 0;\n                        for (int k = 0; k < nbr_cnt[cell]; ++k) {\n                            int nb = nbr[cell][k];\n                            if (pos2idx[nb] != -1) gain += pot[s][pos2idx[nb]];\n                        }\n                        int pri = sel_mval[s] * 10 + sel_V[s];\n                        if (gain > best_gain || (gain == best_gain && pri > best_pri)) {\n                            best_gain = gain; best_s = s; best_pri = pri;\n                        }\n                    }\n                }\n\n                if (best_s == -1) { // safety fallback\n                    for (int s = 0; s < P; ++s)\n                        if (!used_seed[s]) { best_s = s; break; }\n                }\n\n                used_seed[best_s] = true;\n                pos2idx[cell] = best_s;\n            }\n\n            // ---- 7. hill climbing (best improvement) ----\n            auto do_hill_climb = [&](int max_iter) {\n                for (int it = 0; it < max_iter; ++it) {\n                    int best_delta = 0;\n                    int best_a = -1, best_b = -1;\n                    for (int a = 0; a < P; ++a) {\n                        int ia = pos2idx[a];\n                        for (int b = a + 1; b < P; ++b) {\n                            int ib = pos2idx[b];\n\n                            if (is_unique_sel[ia] && deg[b] != 4) continue;\n                            if (is_unique_sel[ib] && deg[a] != 4) continue;\n                            if (is_rare_sel[ia] && is_corner_cell[b]) continue;\n                            if (is_rare_sel[ib] && is_corner_cell[a]) continue;\n\n                            int delta = 0;\n                            for (int k = 0; k < nbr_cnt[a]; ++k) {\n                                int w = nbr[a][k];\n                                if (w == b) continue;\n                                delta += pot[ib][pos2idx[w]] - pot[ia][pos2idx[w]];\n                            }\n                            for (int k = 0; k < nbr_cnt[b]; ++k) {\n                                int w = nbr[b][k];\n                                if (w == a) continue;\n                                delta += pot[ia][pos2idx[w]] - pot[ib][pos2idx[w]];\n                            }\n                            if (delta > best_delta) {\n                                best_delta = delta;\n                                best_a = a;\n                                best_b = b;\n                            }\n                        }\n                    }\n                    if (best_delta > 0)\n                        swap(pos2idx[best_a], pos2idx[best_b]);\n                    else\n                        break;\n                }\n            };\n\n            do_hill_climb(300);\n\n            // ---- 8. post-processing: try to make pool_cnt==2 carriers adjacent ----\n            for (int pp = 0; pp < 5; ++pp) {\n                bool improved = false;\n                for (int l = 0; l < M_in; ++l) if (pool_cnt[l] == 2) {\n                    int ca = -1, cb = -1;\n                    for (int cell = 0; cell < P; ++cell) {\n                        int s = pos2idx[cell];\n                        if ((mask[selected[s]] >> l) & 1) {\n                            if (ca == -1) ca = cell;\n                            else cb = cell;\n                        }\n                    }\n                    if (ca == -1 || cb == -1) continue;\n\n                    // already adjacent?\n                    bool adj = false;\n                    for (int k = 0; k < nbr_cnt[ca]; ++k)\n                        if (nbr[ca][k] == cb) { adj = true; break; }\n                    if (adj) continue;\n\n                    auto try_move = [&](int from_cell, int target_cell, int moved_seed) -> pair<int,int> {\n                        int best_delta = -1000000;\n                        int best_cn = -1;\n                        for (int k = 0; k < nbr_cnt[target_cell]; ++k) {\n                            int cn = nbr[target_cell][k];\n                            int sn = pos2idx[cn];\n                            if (cn == from_cell) continue;\n\n                            // constraints after swap: moved_seed->cn, sn->from_cell\n                            if (is_unique_sel[moved_seed] && deg[cn] != 4) continue;\n                            if (is_unique_sel[sn] && deg[from_cell] != 4) continue;\n                            if (is_rare_sel[moved_seed] && is_corner_cell[cn]) continue;\n                            if (is_rare_sel[sn] && is_corner_cell[from_cell]) continue;\n\n                            int delta = 0;\n                            for (int kk = 0; kk < nbr_cnt[from_cell]; ++kk) {\n                                int w = nbr[from_cell][kk];\n                                if (w == cn) continue;\n                                delta -= pot[moved_seed][pos2idx[w]];\n                            }\n                            for (int kk = 0; kk < nbr_cnt[cn]; ++kk) {\n                                int w = nbr[cn][kk];\n                                if (w == from_cell) continue;\n                                delta -= pot[sn][pos2idx[w]];\n                            }\n                            for (int kk = 0; kk < nbr_cnt[cn]; ++kk) {\n                                int w = nbr[cn][kk];\n                                if (w == from_cell) continue;\n                                delta += pot[moved_seed][pos2idx[w]];\n                            }\n                            for (int kk = 0; kk < nbr_cnt[from_cell]; ++kk) {\n                                int w = nbr[from_cell][kk];\n                                if (w == cn) continue;\n                                delta += pot[sn][pos2idx[w]];\n                            }\n                            if (delta > best_delta) {\n                                best_delta = delta;\n                                best_cn = cn;\n                            }\n                        }\n                        return {best_delta, best_cn};\n                    };\n\n                    int sa = pos2idx[ca];\n                    int sb = pos2idx[cb];\n                    auto ra = try_move(ca, cb, sa);\n                    auto rb = try_move(cb, ca, sb);\n\n                    int best_delta = -1000000;\n                    int swap_from = -1, swap_to = -1;\n                    if (ra.second != -1 && ra.first > best_delta) {\n                        best_delta = ra.first; swap_from = ca; swap_to = ra.second;\n                    }\n                    if (rb.second != -1 && rb.first > best_delta) {\n                        best_delta = rb.first; swap_from = cb; swap_to = rb.second;\n                    }\n\n                    if (swap_to != -1 && best_delta > -1500) {\n                        swap(pos2idx[swap_from], pos2idx[swap_to]);\n                        improved = true;\n                    }\n                }\n                if (!improved) break;\n            }\n\n            // cleanup hill climbing after post-processing\n            do_hill_climb(100);\n\n            // ---- 9. output ----\n            for (int r = 0; r < N; ++r) {\n                for (int c = 0; c < N; ++c) {\n                    if (c) cout << ' ';\n                    int cell = r * N + c;\n                    cout << selected[pos2idx[cell]];\n                }\n                cout << '\\n';\n            }\n            cout.flush();\n\n            // ---- 10. read next generation ----\n            for (int i = 0; i < S; ++i)\n                for (int l = 0; l < M_in; ++l)\n                    cin >> X[i][l];\n        }\n    }\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, M, V;\nvector<char> has_src;   // size N*N\nvector<char> need_tgt;  // size N*N\ninline int ID(int r, int c) { return r * N + c; }\n\nvector<int> len;\nint reach_id[15][30][30][4]; // -1 if out of bounds\nvector<int> cur_dir;\nvector<char> holding;\nint cur_r, cur_c;\n\nvector<string> ans;\nint hold_cnt = 0;\nint rem_src = 0;\nint rem_tgt = 0;\n\nconst int dr[4] = {0, 1, 0, -1};\nconst int dc[4] = {1, 0, -1, 0};\n\ninline int rotcost(int a, int b) {\n    int d = abs(a - b);\n    return min(d, 4 - d);\n}\ninline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstruct Batch {\n    int size = 0;\n    int turns = 0;\n    int dist = 0;\n    int r = -1, c = -1;\n    int ndir[15];\n    int tr[15], tc[15];\n    Batch() {\n        memset(ndir, -1, sizeof(ndir));\n        memset(tr, -1, sizeof(tr));\n        memset(tc, -1, sizeof(tc));\n    }\n};\n\nbool isBetter(int sz, int turn, int dst, const Batch& b) {\n    if (b.size == 0) return true;\n    long long lhs = 1LL * sz * b.turns;\n    long long rhs = 1LL * b.size * turn;\n    if (lhs != rhs) return lhs > rhs;\n    if (sz != b.size) return sz > b.size;\n    if (turn != b.turns) return turn < b.turns;\n    return dst < b.dist;\n}\n\nBatch find_batch() {\n    Batch best;\n    int ndir[15];\n    int ncost[15];\n    int ntr[15], ntc[15];\n    \n    for (int r = 0; r < N; ++r) {\n        for (int c = 0; c < N; ++c) {\n            int dist = manhattan(cur_r, cur_c, r, c);\n            int cnt_le1 = 0; // cost 0 or 1\n            int cnt_eq2 = 0; // cost 2\n            \n            for (int i = 1; i < V; ++i) {\n                ndir[i] = -1;\n                if (holding[i]) {\n                    if (rem_tgt == 0) continue;\n                } else {\n                    if (rem_src == 0) continue;\n                }\n                for (int d = 0; d < 4; ++d) {\n                    int nid = reach_id[i][r][c][d];\n                    if (nid == -1) continue;\n                    if (holding[i] ? !need_tgt[nid] : !has_src[nid]) continue;\n                    int cost = rotcost(cur_dir[i], d);\n                    if (ndir[i] == -1 || cost < ncost[i]) {\n                        ndir[i] = d;\n                        ncost[i] = cost;\n                        ntr[i] = nid / N;\n                        ntc[i] = nid % N;\n                    }\n                }\n                if (ndir[i] != -1) {\n                    if (ncost[i] <= 1) ++cnt_le1;\n                    else ++cnt_eq2;\n                }\n            }\n            \n            auto upd = [&](int L, int sz, int turns) {\n                if (sz == 0) return;\n                if (isBetter(sz, turns, dist, best)) {\n                    best.size = sz;\n                    best.turns = turns;\n                    best.dist = dist;\n                    best.r = r;\n                    best.c = c;\n                    for (int i = 1; i < V; ++i) {\n                        if (ndir[i] != -1 && ncost[i] <= L) {\n                            best.ndir[i] = ndir[i];\n                            best.tr[i] = ntr[i];\n                            best.tc[i] = ntc[i];\n                        } else {\n                            best.ndir[i] = -1;\n                        }\n                    }\n                }\n            };\n            \n            if (dist >= 2) {\n                upd(2, cnt_le1 + cnt_eq2, dist);\n            } else {\n                // dist 0 or 1\n                upd(1, cnt_le1, 1);\n                upd(2, cnt_le1 + cnt_eq2, 2);\n            }\n        }\n    }\n    return best;\n}\n\nvoid execute_batch(const Batch& b) {\n    int travel = b.turns;\n    for (int step = 0; step < travel; ++step) {\n        char move = '.';\n        if (cur_r < b.r)       { move = 'D'; ++cur_r; }\n        else if (cur_r > b.r)  { move = 'U'; --cur_r; }\n        else if (cur_c < b.c)  { move = 'R'; ++cur_c; }\n        else if (cur_c > b.c)  { move = 'L'; --cur_c; }\n\n        string S(2 * V, '.');\n        S[0] = move;\n\n        for (int i = 1; i < V; ++i) {\n            if (b.ndir[i] == -1) continue;\n            if (cur_dir[i] == b.ndir[i]) continue;\n            int diff = (b.ndir[i] - cur_dir[i] + 4) % 4;\n            if (diff == 1) {\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            } else if (diff == 3) {\n                S[i] = 'L';\n                cur_dir[i] = (cur_dir[i] + 3) & 3;\n            } else { // diff == 2\n                S[i] = 'R';\n                cur_dir[i] = (cur_dir[i] + 1) & 3;\n            }\n        }\n\n        if (step == travel - 1) {\n            for (int i = 1; i < V; ++i) {\n                if (b.ndir[i] == -1) continue;\n                S[V + i] = 'P';\n                if (holding[i]) {\n                    need_tgt[ID(b.tr[i], b.tc[i])] = 0;\n                    holding[i] = 0;\n                    --hold_cnt;\n                    --rem_tgt;\n                } else {\n                    has_src[ID(b.tr[i], b.tc[i])] = 0;\n                    holding[i] = 1;\n                    ++hold_cnt;\n                    --rem_src;\n                }\n            }\n        }\n        ans.push_back(S);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> M >> V;\n\n    vector<string> s(N), t(N);\n    for (int i = 0; i < N; ++i) cin >> s[i];\n    for (int i = 0; i < N; ++i) cin >> t[i];\n\n    has_src.assign(N * N, 0);\n    need_tgt.assign(N * N, 0);\n    long long sumr = 0, sumc = 0, work = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (s[i][j] == '1' && t[i][j] == '1') {\n                // already satisfied\n            } else if (s[i][j] == '1') {\n                has_src[ID(i, j)] = 1;\n                ++rem_src;\n                sumr += i; sumc += j; ++work;\n            } else if (t[i][j] == '1') {\n                need_tgt[ID(i, j)] = 1;\n                ++rem_tgt;\n                sumr += i; sumc += j; ++work;\n            }\n        }\n    }\n\n    /*--- design the arm (star with distinct lengths 1..V-1) ---*/\n    cout << V << '\\n';\n    len.assign(V, 0);\n    for (int u = 1; u < V; ++u) {\n        int L = u;\n        if (L > N - 1) L = N - 1;\n        len[u] = L;\n        cout << 0 << ' ' << L << '\\n';\n    }\n\n    if (work > 0) {\n        cur_r = int(sumr / work);\n        cur_c = int(sumc / work);\n    } else {\n        cur_r = N / 2;\n        cur_c = N / 2;\n    }\n    cur_r = max(0, min(N - 1, cur_r));\n    cur_c = max(0, min(N - 1, cur_c));\n    cout << cur_r << ' ' << cur_c << '\\n';\n\n    cur_dir.assign(V, 0);\n    holding.assign(V, 0);\n    ans.reserve(200000);\n\n    /*--- precompute reach_id ---*/\n    memset(reach_id, -1, sizeof(reach_id));\n    for (int i = 1; i < V; ++i) {\n        for (int r = 0; r < N; ++r) {\n            for (int c = 0; c < N; ++c) {\n                for (int d = 0; d < 4; ++d) {\n                    int nr = r + dr[d] * len[i];\n                    int nc = c + dc[d] * len[i];\n                    if (0 <= nr && nr < N && 0 <= nc && nc < N) {\n                        reach_id[i][r][c][d] = ID(nr, nc);\n                    }\n                }\n            }\n        }\n    }\n\n    /*--- main greedy loop ---*/\n    while (rem_src > 0 || hold_cnt > 0) {\n        Batch b = find_batch();\n        if (b.size > 0) {\n            execute_batch(b);\n        } else {\n            // Fallback: move toward nearest remaining work\n            int tr = -1, tc = -1, bestd = 1e9;\n            for (int i = 0; i < N; ++i) {\n                for (int j = 0; j < N; ++j) {\n                    if (has_src[ID(i, j)] || need_tgt[ID(i, j)]) {\n                        int d = manhattan(cur_r, cur_c, i, j);\n                        if (d < bestd) {\n                            bestd = d;\n                            tr = i; tc = j;\n                        }\n                    }\n                }\n            }\n            if (tr == -1) break;\n            char move = '.';\n            if (cur_r < tr) { move = 'D'; ++cur_r; }\n            else if (cur_r > tr) { move = 'U'; --cur_r; }\n            else if (cur_c < tc) { move = 'R'; ++cur_c; }\n            else if (cur_c > tc) { move = 'L'; --cur_c; }\n            string S(2 * V, '.');\n            S[0] = move;\n            ans.push_back(S);\n        }\n    }\n\n    for (const string& str : ans) cout << str << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n    int w;          // +1 = mackerel, -1 = sardine\n};\n\nstruct Rect {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    const int MAXC = 100000;\n    int N;\n    if (!(cin >> N)) return 0;\n    const int M = 2 * N;\n\n    vector<Point> pts(M);\n    unordered_set<unsigned long long> occ;\n    occ.reserve(M * 2);\n    for (int i = 0; i < N; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n        pts[i].w = +1;\n        occ.insert(((unsigned long long)pts[i].x << 32) | (unsigned long long)pts[i].y);\n    }\n    for (int i = N; i < M; ++i) {\n        cin >> pts[i].x >> pts[i].y;\n        pts[i].w = -1;\n        occ.insert(((unsigned long long)pts[i].x << 32) | (unsigned long long)pts[i].y);\n    }\n\n    /* coordinate compression */\n    vector<int> ux, uy;\n    ux.reserve(M);\n    uy.reserve(M);\n    for (auto &p : pts) {\n        ux.push_back(p.x);\n        uy.push_back(p.y);\n    }\n    sort(ux.begin(), ux.end());\n    ux.erase(unique(ux.begin(), ux.end()), ux.end());\n    sort(uy.begin(), uy.end());\n    uy.erase(unique(uy.begin(), uy.end()), uy.end());\n    const int X = (int)ux.size();\n    const int Y = (int)uy.size();\n\n    unordered_map<int,int> yid;\n    yid.reserve(Y * 2);\n    for (int i = 0; i < Y; ++i) yid[uy[i]] = i;\n\n    vector<int> py_id(M);\n    for (int i = 0; i < M; ++i) py_id[i] = yid[pts[i].y];\n\n    /* sort points by x */\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(),\n         [&](int a, int b){ return pts[a].x < pts[b].x; });\n    vector<int> spx(M), spy(M), spw(M);\n    for (int i = 0; i < M; ++i) {\n        spx[i] = pts[ord[i]].x;\n        spy[i] = py_id[ord[i]];\n        spw[i] = pts[ord[i]].w;\n    }\n\n    /* reusable buffer */\n    vector<int> ysum(Y);\n\n    auto eval_interval = [&](int x1, int x2, int &out_y1, int &out_y2) -> int {\n        memset(ysum.data(), 0, Y * sizeof(int));\n        int l = lower_bound(spx.begin(), spx.end(), x1) - spx.begin();\n        int r = upper_bound(spx.begin(), spx.end(), x2) - spx.begin();\n        for (int i = l; i < r; ++i) ysum[spy[i]] += spw[i];\n\n        int best = 0, cur = 0;\n        int best_l = 0, best_r = -1;\n        int cur_l = 0;\n        for (int i = 0; i < Y; ++i) {\n            if (cur + ysum[i] < ysum[i]) {\n                cur = ysum[i];\n                cur_l = i;\n            } else {\n                cur += ysum[i];\n            }\n            if (cur > best) {\n                best = cur;\n                best_l = cur_l;\n                best_r = i;\n            }\n        }\n        if (best <= 0) {\n            out_y1 = 0; out_y2 = 0;\n            return 0;\n        }\n        out_y1 = uy[best_l];\n        out_y2 = uy[best_r];\n        return best;\n    };\n\n    auto eval_rect = [&](const Rect &r) -> int {\n        int a = 0, b = 0;\n        for (auto &p : pts) {\n            if (r.x1 <= p.x && p.x <= r.x2 && r.y1 <= p.y && p.y <= r.y2) {\n                if (p.w == 1) ++a; else ++b;\n            }\n        }\n        return a - b;\n    };\n\n    /* fallback empty 1x1 */\n    Rect best_rect{0, 0, 1, 1};\n    int best_score = 0;\n    {\n        mt19937 rng(123456789);\n        uniform_int_distribution<int> dx(0, MAXC - 1);\n        uniform_int_distribution<int> dy(0, MAXC - 1);\n        for (int t = 0; t < 20000; ++t) {\n            int x = dx(rng), y = dy(rng);\n            unsigned long long c1 = ((unsigned long long)x << 32) | (unsigned long long)y;\n            unsigned long long c2 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)y;\n            unsigned long long c3 = ((unsigned long long)x << 32) | (unsigned long long)(y + 1);\n            unsigned long long c4 = ((unsigned long long)(x + 1) << 32) | (unsigned long long)(y + 1);\n            if (!occ.count(c1) && !occ.count(c2) && !occ.count(c3) && !occ.count(c4)) {\n                best_rect = {x, y, x + 1, y + 1};\n                best_score = 0;\n                break;\n            }\n        }\n    }\n\n    /* ---------- coarse grid seeds ---------- */\n    auto grid_search = [&](int S, int K) {\n        int G = (MAXC + S) / S;\n        vector<vector<int>> grid(G, vector<int>(G, 0));\n        for (auto &p : pts) {\n            int cx = min(p.x / S, G - 1);\n            int cy = min(p.y / S, G - 1);\n            grid[cy][cx] += p.w;\n        }\n        using T = tuple<int,int,int,int,int>;          // val, y1, y2, x1, x2\n        priority_queue<T, vector<T>, greater<T>> pq;\n        for (int y1 = 0; y1 < G; ++y1) {\n            vector<int> col(G, 0);\n            for (int y2 = y1; y2 < G; ++y2) {\n                for (int x = 0; x < G; ++x) col[x] += grid[y2][x];\n                int cur = col[0], cur_l = 0;\n                int best = col[0], best_l = 0, best_r = 0;\n                for (int x = 1; x < G; ++x) {\n                    if (cur + col[x] < col[x]) {\n                        cur = col[x];\n                        cur_l = x;\n                    } else {\n                        cur += col[x];\n                    }\n                    if (cur > best) {\n                        best = cur;\n                        best_l = cur_l;\n                        best_r = x;\n                    }\n                }\n                if ((int)pq.size() < K) {\n                    pq.emplace(best, y1, y2, best_l, best_r);\n                } else if (best > get<0>(pq.top())) {\n                    pq.pop();\n                    pq.emplace(best, y1, y2, best_l, best_r);\n                }\n            }\n        }\n        vector<tuple<int,int,int,int,int>> res;\n        while (!pq.empty()) {\n            auto v = pq.top(); pq.pop();\n            res.emplace_back(S, get<1>(v), get<2>(v), get<3>(v), get<4>(v));\n        }\n        return res;\n    };\n\n    vector<tuple<int,int,int,int,int>> seeds;\n    for (int S : {500, 1000, 2000}) {\n        auto v = grid_search(S, 5);\n        seeds.insert(seeds.end(), v.begin(), v.end());\n    }\n\n    for (auto &sd : seeds) {\n        int S, gy1, gy2, gx1, gx2;\n        tie(S, gy1, gy2, gx1, gx2) = sd;\n        int x1 = gx1 * S;\n        int x2 = min(MAXC, (gx2 + 1) * S);\n        if (x1 > x2) swap(x1, x2);\n        int yy1, yy2;\n        int sc = eval_interval(x1, x2, yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {x1, yy1, x2, yy2};\n        }\n    }\n\n    /* snap best rectangle to actual point coordinates to obtain start indices */\n    int ix1 = 0, ix2 = X - 1;\n    if (best_score > 0) {\n        int minx = MAXC, maxx = 0, miny = MAXC, maxy = 0;\n        for (auto &p : pts) {\n            if (best_rect.x1 <= p.x && p.x <= best_rect.x2 &&\n                best_rect.y1 <= p.y && p.y <= best_rect.y2) {\n                minx = min(minx, p.x);\n                maxx = max(maxx, p.x);\n                miny = min(miny, p.y);\n                maxy = max(maxy, p.y);\n            }\n        }\n        if (minx <= maxx) {\n            best_rect = {minx, miny, maxx, maxy};\n            best_score = eval_rect(best_rect);\n            ix1 = lower_bound(ux.begin(), ux.end(), minx) - ux.begin();\n            ix2 = lower_bound(ux.begin(), ux.end(), maxx) - ux.begin();\n        }\n    }\n\n    {\n        int yy1, yy2;\n        int sc = eval_interval(ux[ix1], ux[ix2], yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {ux[ix1], yy1, ux[ix2], yy2};\n        }\n    }\n\n    /* ---------- helper to try an interval ---------- */\n    auto try_interval = [&](int i1, int i2) -> bool {\n        if (i1 < 0 || i2 >= X || i1 > i2) return false;\n        int yy1, yy2;\n        int sc = eval_interval(ux[i1], ux[i2], yy1, yy2);\n        if (sc > best_score) {\n            best_score = sc;\n            best_rect = {ux[i1], yy1, ux[i2], yy2};\n            ix1 = i1; ix2 = i2;\n            return true;\n        }\n        return false;\n    };\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    uniform_int_distribution<int> dist_local(-30, 30);\n    uniform_int_distribution<int> dist_global(0, X - 1);\n\n    auto hill_climb = [&]() {\n        while (true) {\n            int local_best = best_score;\n            int li1 = -1, li2 = -1;\n            int ly1 = 0, ly2 = 0;\n            for (int d1 = -1; d1 <= 1; ++d1) {\n                for (int d2 = -1; d2 <= 1; ++d2) {\n                    if (d1 == 0 && d2 == 0) continue;\n                    int ti1 = ix1 + d1;\n                    int ti2 = ix2 + d2;\n                    if (ti1 < 0 || ti2 >= X || ti1 > ti2) continue;\n                    int ty1, ty2;\n                    int tsc = eval_interval(ux[ti1], ux[ti2], ty1, ty2);\n                    if (tsc > local_best) {\n                        local_best = tsc;\n                        li1 = ti1; li2 = ti2;\n                        ly1 = ty1; ly2 = ty2;\n                    }\n                }\n            }\n            if (local_best <= best_score) break;\n            best_score = local_best;\n            best_rect = {ux[li1], ly1, ux[li2], ly2};\n            ix1 = li1; ix2 = li2;\n        }\n    };\n\n    /* Phase 1: pure random exploration */\n    for (int it = 0; it < 4000; ++it) {\n        int ni1, ni2;\n        if ((rng() & 1) && X > 1) {\n            ni1 = ix1 + dist_local(rng);\n            ni2 = ix2 + dist_local(rng);\n        } else {\n            ni1 = dist_global(rng);\n            ni2 = dist_global(rng);\n        }\n        if (ni1 < 0) ni1 = 0;\n        if (ni2 < 0) ni2 = 0;\n        if (ni1 >= X) ni1 = X - 1;\n        if (ni2 >= X) ni2 = X - 1;\n        if (ni1 > ni2) swap(ni1, ni2);\n        try_interval(ni1, ni2);\n    }\n\n    /* Phase 2: hill climb from the best found so far */\n    hill_climb();\n\n    /* Phase 3: more random jumps, hill climbing only on real improvement */\n    for (int it = 0; it < 2000; ++it) {\n        int ni1, ni2;\n        if ((rng() & 1) && X > 1) {\n            ni1 = ix1 + dist_local(rng);\n            ni2 = ix2 + dist_local(rng);\n        } else {\n            ni1 = dist_global(rng);\n            ni2 = dist_global(rng);\n        }\n        if (ni1 < 0) ni1 = 0;\n        if (ni2 < 0) ni2 = 0;\n        if (ni1 >= X) ni1 = X - 1;\n        if (ni2 >= X) ni2 = X - 1;\n        if (ni1 > ni2) swap(ni1, ni2);\n        if (try_interval(ni1, ni2))\n            hill_climb();\n    }\n\n    /* final safety: non\u2011zero area */\n    if (best_score <= 0) {\n        best_rect = {0, 0, 1, 1};   // empty fallback\n    } else {\n        if (best_rect.x1 == best_rect.x2) {\n            if (best_rect.x2 < MAXC) ++best_rect.x2;\n            else --best_rect.x1;\n        }\n        if (best_rect.y1 == best_rect.y2) {\n            if (best_rect.y2 < MAXC) ++best_rect.y2;\n            else --best_rect.y1;\n        }\n    }\n\n    cout << 4 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y1 << \"\\n\";\n    cout << best_rect.x2 << \" \" << best_rect.y2 << \"\\n\";\n    cout << best_rect.x1 << \" \" << best_rect.y2 << \"\\n\";\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N, T;\nlong long SIGMA;\nlong long Wobs[100], Hobs[100];\n\nstruct Packing {\n    int r[100];\n    char d[100];\n    int b[100];\n    long long x[100], y[100], w[100], h[100];\n    long long score;\n};\n\ninline long long simulate(Packing& p, int start) {\n    long long W = 0, H = 0;\n    for (int j = 0; j < start; ++j) {\n        if (p.x[j] + p.w[j] > W) W = p.x[j] + p.w[j];\n        if (p.y[j] + p.h[j] > H) H = p.y[j] + p.h[j];\n    }\n    for (int i = start; i < N; ++i) {\n        long long wi = p.r[i] ? Hobs[i] : Wobs[i];\n        long long hi = p.r[i] ? Wobs[i] : Hobs[i];\n        long long xx, yy;\n        if (p.d[i] == 'U') {\n            xx = (p.b[i] == -1) ? 0LL : p.x[p.b[i]] + p.w[p.b[i]];\n            yy = 0;\n            for (int j = 0; j < i; ++j) {\n                if (xx < p.x[j] + p.w[j] && p.x[j] < xx + wi)\n                    yy = max(yy, p.y[j] + p.h[j]);\n            }\n        } else {\n            yy = (p.b[i] == -1) ? 0LL : p.y[p.b[i]] + p.h[p.b[i]];\n            xx = 0;\n            for (int j = 0; j < i; ++j) {\n                if (yy < p.y[j] + p.h[j] && p.y[j] < yy + hi)\n                    xx = max(xx, p.x[j] + p.w[j]);\n            }\n        }\n        p.x[i] = xx; p.y[i] = yy; p.w[i] = wi; p.h[i] = hi;\n        if (xx + wi > W) W = xx + wi;\n        if (yy + hi > H) H = yy + hi;\n    }\n    p.score = W + H;\n    return p.score;\n}\n\nlong long greedy_build(Packing& p, int start, int objective, bool stochastic, mt19937& rng) {\n    long long W = 0, H = 0;\n    for (int j = 0; j < start; ++j) {\n        W = max(W, p.x[j] + p.w[j]);\n        H = max(H, p.y[j] + p.h[j]);\n    }\n    struct Cand {\n        int r, b;\n        char d;\n        long long x, y, w, h, sc;\n    } cands[404];\n    int cand_cnt;\n    for (int i = start; i < N; ++i) {\n        cand_cnt = 0;\n        for (int rot = 0; rot < 2; ++rot) {\n            long long wi = rot ? Hobs[i] : Wobs[i];\n            long long hi = rot ? Wobs[i] : Hobs[i];\n            for (int di = 0; di < 2; ++di) {\n                char dd = di ? 'L' : 'U';\n                for (int bv = -1; bv < i; ++bv) {\n                    long long xx, yy;\n                    if (dd == 'U') {\n                        xx = (bv == -1) ? 0LL : p.x[bv] + p.w[bv];\n                        yy = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (xx < p.x[j] + p.w[j] && p.x[j] < xx + wi)\n                                yy = max(yy, p.y[j] + p.h[j]);\n                    } else {\n                        yy = (bv == -1) ? 0LL : p.y[bv] + p.h[bv];\n                        xx = 0;\n                        for (int j = 0; j < i; ++j)\n                            if (yy < p.y[j] + p.h[j] && p.y[j] < yy + hi)\n                                xx = max(xx, p.x[j] + p.w[j]);\n                    }\n                    long long nW = max(W, xx + wi);\n                    long long nH = max(H, yy + hi);\n                    long long sc;\n                    if (objective == 0) sc = nW + nH;\n                    else if (objective == 1) sc = max(nW, nH);\n                    else if (objective == 2) sc = nW * nH;\n                    else sc = nW + nH + llabs(nW - nH) / 10;\n                    cands[cand_cnt++] = {rot, bv, dd, xx, yy, wi, hi, sc};\n                }\n            }\n        }\n        long long best_sc = cands[0].sc;\n        for (int k = 1; k < cand_cnt; ++k)\n            if (cands[k].sc < best_sc) best_sc = cands[k].sc;\n        int idx = 0;\n        if (stochastic) {\n            long long thr = best_sc + max(1LL, best_sc / 50);\n            int good[404], gcnt = 0;\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc <= thr) good[gcnt++] = k;\n            idx = good[rng() % gcnt];\n        } else {\n            for (int k = 0; k < cand_cnt; ++k)\n                if (cands[k].sc == best_sc) { idx = k; break; }\n        }\n        const Cand& c = cands[idx];\n        p.r[i] = c.r; p.d[i] = c.d; p.b[i] = c.b;\n        p.x[i] = c.x; p.y[i] = c.y; p.w[i] = c.w; p.h[i] = c.h;\n        W = max(W, c.x + c.w);\n        H = max(H, c.y + c.h);\n    }\n    p.score = W + H;\n    return p.score;\n}\n\ninline void exhaustive_move(Packing& p, int i) {\n    long long bak_x[100], bak_y[100], bak_w[100], bak_h[100];\n    memcpy(bak_x, p.x + i, (N - i) * sizeof(long long));\n    memcpy(bak_y, p.y + i, (N - i) * sizeof(long long));\n    memcpy(bak_w, p.w + i, (N - i) * sizeof(long long));\n    memcpy(bak_h, p.h + i, (N - i) * sizeof(long long));\n    int orig_r = p.r[i], orig_b = p.b[i];\n    char orig_d = p.d[i];\n    long long orig_sc = p.score;\n\n    long long best_sc = orig_sc;\n    int best_r = orig_r, best_b = orig_b;\n    char best_d = orig_d;\n\n    for (int rot = 0; rot < 2; ++rot) {\n        for (int di = 0; di < 2; ++di) {\n            char dd = di ? 'L' : 'U';\n            for (int bv = -1; bv < i; ++bv) {\n                p.r[i] = rot; p.d[i] = dd; p.b[i] = bv;\n                long long sc = simulate(p, i);\n                if (sc < best_sc) {\n                    best_sc = sc;\n                    best_r = rot; best_d = dd; best_b = bv;\n                }\n            }\n        }\n    }\n    if (best_sc < orig_sc) {\n        p.r[i] = best_r; p.d[i] = best_d; p.b[i] = best_b;\n        p.score = best_sc;\n        simulate(p, i);\n    } else {\n        p.r[i] = orig_r; p.d[i] = orig_d; p.b[i] = orig_b;\n        memcpy(p.x + i, bak_x, (N - i) * sizeof(long long));\n        memcpy(p.y + i, bak_y, (N - i) * sizeof(long long));\n        memcpy(p.w + i, bak_w, (N - i) * sizeof(long long));\n        memcpy(p.h + i, bak_h, (N - i) * sizeof(long long));\n        p.score = orig_sc;\n    }\n}\n\ninline bool random_move(Packing& p, int i, mt19937& rng) {\n    long long bak_x[100], bak_y[100], bak_w[100], bak_h[100];\n    memcpy(bak_x, p.x + i, (N - i) * sizeof(long long));\n    memcpy(bak_y, p.y + i, (N - i) * sizeof(long long));\n    memcpy(bak_w, p.w + i, (N - i) * sizeof(long long));\n    memcpy(bak_h, p.h + i, (N - i) * sizeof(long long));\n    int orig_r = p.r[i], orig_b = p.b[i];\n    char orig_d = p.d[i];\n    long long orig_sc = p.score;\n\n    p.r[i] = (int)(rng() & 1);\n    p.d[i] = (rng() & 1) ? 'L' : 'U';\n    p.b[i] = (int)(rng() % (i + 1)) - 1;\n    long long sc = simulate(p, i);\n    if (sc < orig_sc) {\n        p.score = sc;\n        return true;\n    }\n    p.r[i] = orig_r; p.d[i] = orig_d; p.b[i] = orig_b;\n    memcpy(p.x + i, bak_x, (N - i) * sizeof(long long));\n    memcpy(p.y + i, bak_y, (N - i) * sizeof(long long));\n    memcpy(p.w + i, bak_w, (N - i) * sizeof(long long));\n    memcpy(p.h + i, bak_h, (N - i) * sizeof(long long));\n    p.score = orig_sc;\n    return false;\n}\n\ninline Packing crossover(const Packing& A, const Packing& B, int k) {\n    Packing C = A;\n    for (int i = k; i < N; ++i) {\n        C.r[i] = B.r[i];\n        C.d[i] = B.d[i];\n        C.b[i] = B.b[i];\n    }\n    simulate(C, k);\n    return C;\n}\n\nPacking beam_search(int B, int objective) {\n    struct Mini {\n        long long W, H;\n        long long x[100], y[100], w[100], h[100];\n        int r[100], b[100];\n        char d[100];\n    };\n    struct Cand {\n        long long sc;\n        int pid, r, b;\n        char d;\n        long long x, y, w, h, W, H;\n    };\n\n    vector<Mini> cur;\n    cur.reserve(B);\n    Mini empty;\n    memset(&empty, 0, sizeof(empty));\n    empty.W = empty.H = 0;\n    cur.push_back(empty);\n    vector<Cand> cands;\n    cands.reserve(B * 404);\n\n    for (int i = 0; i < N; ++i) {\n        cands.clear();\n        int psz = (int)cur.size();\n        for (int pid = 0; pid < psz; ++pid) {\n            const Mini& par = cur[pid];\n            for (int rot = 0; rot < 2; ++rot) {\n                long long wi = rot ? Hobs[i] : Wobs[i];\n                long long hi = rot ? Wobs[i] : Hobs[i];\n                for (int di = 0; di < 2; ++di) {\n                    char dd = di ? 'L' : 'U';\n                    for (int bv = -1; bv < i; ++bv) {\n                        long long xx, yy;\n                        if (dd == 'U') {\n                            xx = (bv == -1) ? 0LL : par.x[bv] + par.w[bv];\n                            yy = 0;\n                            for (int j = 0; j < i; ++j)\n                                if (xx < par.x[j] + par.w[j] && par.x[j] < xx + wi)\n                                    yy = max(yy, par.y[j] + par.h[j]);\n                        } else {\n                            yy = (bv == -1) ? 0LL : par.y[bv] + par.h[bv];\n                            xx = 0;\n                            for (int j = 0; j < i; ++j)\n                                if (yy < par.y[j] + par.h[j] && par.y[j] < yy + hi)\n                                    xx = max(xx, par.x[j] + par.w[j]);\n                        }\n                        long long nW = max(par.W, xx + wi);\n                        long long nH = max(par.H, yy + hi);\n                        long long sc = (objective == 0) ? nW + nH\n                                       : nW + nH + llabs(nW - nH) / 10;\n                        cands.push_back({sc, pid, rot, bv, dd,\n                                         xx, yy, wi, hi, nW, nH});\n                    }\n                }\n            }\n        }\n        int keep = min(B, (int)cands.size());\n        nth_element(cands.begin(), cands.begin() + keep, cands.end(),\n                    [](const Cand& a, const Cand& b) { return a.sc < b.sc; });\n        vector<Mini> nxt;\n        nxt.reserve(keep);\n        for (int k = 0; k < keep; ++k) {\n            const Cand& c = cands[k];\n            const Mini& par = cur[c.pid];\n            Mini ns;\n            memcpy(ns.x, par.x, sizeof(long long) * i);\n            memcpy(ns.y, par.y, sizeof(long long) * i);\n            memcpy(ns.w, par.w, sizeof(long long) * i);\n            memcpy(ns.h, par.h, sizeof(long long) * i);\n            memcpy(ns.r, par.r, sizeof(int) * i);\n            memcpy(ns.b, par.b, sizeof(int) * i);\n            memcpy(ns.d, par.d, sizeof(char) * i);\n            ns.x[i] = c.x; ns.y[i] = c.y; ns.w[i] = c.w; ns.h[i] = c.h;\n            ns.r[i] = c.r; ns.b[i] = c.b; ns.d[i] = c.d;\n            ns.W = c.W; ns.H = c.H;\n            nxt.push_back(ns);\n        }\n        cur.swap(nxt);\n    }\n    Packing res;\n    memset(&res, 0, sizeof(res));\n    const Mini& s = cur[0];\n    for (int i = 0; i < N; ++i) {\n        res.r[i] = s.r[i]; res.d[i] = s.d[i]; res.b[i] = s.b[i];\n        res.x[i] = s.x[i]; res.y[i] = s.y[i]; res.w[i] = s.w[i]; res.h[i] = s.h[i];\n    }\n    simulate(res, 0);\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    cin >> N >> T >> SIGMA;\n    for (int i = 0; i < N; ++i) cin >> Wobs[i] >> Hobs[i];\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n\n    const double TIME_LIMIT = 2.88;\n    auto start_clock = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - start_clock).count();\n    };\n\n    /* ---- initialization ---- */\n    Packing pred_best;\n    memset(&pred_best, 0, sizeof(pred_best));\n    pred_best.score = (1LL << 60);\n\n    for (int t = 0; t < 40 && elapsed() < 0.25; ++t) {\n        Packing p;\n        memset(&p, 0, sizeof(p));\n        long long sc = greedy_build(p, 0, (int)(rng() % 4), true, rng);\n        if (sc < pred_best.score) pred_best = p;\n    }\n    for (int obj = 0; obj < 4 && elapsed() < 0.40; ++obj) {\n        Packing p;\n        memset(&p, 0, sizeof(p));\n        long long sc = greedy_build(p, 0, obj, false, rng);\n        if (sc < pred_best.score) pred_best = p;\n    }\n    if (elapsed() < 0.55) {\n        Packing b = beam_search(80, 1);\n        if (b.score < pred_best.score) pred_best = b;\n    }\n    if (elapsed() < 0.70) {\n        Packing b = beam_search(80, 0);\n        if (b.score < pred_best.score) pred_best = b;\n    }\n\n    {\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n        for (int pass = 0; pass < 5 && elapsed() < 0.90; ++pass) {\n            shuffle(order.begin(), order.end(), rng);\n            bool improved = false;\n            for (int idx = 0; idx < N && elapsed() < 0.90; ++idx) {\n                long long old_sc = pred_best.score;\n                exhaustive_move(pred_best, order[idx]);\n                if (pred_best.score < old_sc) improved = true;\n            }\n            if (!improved) break;\n        }\n    }\n\n    // observed-score population (initially seeded with pred_best variants)\n    vector<pair<long long, Packing>> obs_pop;\n    auto add_obs = [&](long long obs, const Packing& p) {\n        obs_pop.push_back({obs, p});\n        sort(obs_pop.begin(), obs_pop.end(),\n             [](const auto& a, const auto& b) { return a.first < b.first; });\n        if ((int)obs_pop.size() > 8) obs_pop.pop_back();\n    };\n\n    // seed with a few diverse predicted-good packings\n    {\n        Packing p; memset(&p,0,sizeof(p));\n        greedy_build(p, 0, 0, false, rng);\n        add_obs(p.score, p);\n    }\n    {\n        Packing p; memset(&p,0,sizeof(p));\n        greedy_build(p, 0, 1, false, rng);\n        add_obs(p.score, p);\n    }\n    add_obs(pred_best.score, pred_best);\n\n    Packing obs_best = pred_best;\n    long long best_observed = (1LL << 60);\n\n    /* ---- turn loop ---- */\n    for (int turn = 0; turn < T; ++turn) {\n        if (elapsed() >= TIME_LIMIT - 0.05) {\n            cout << N << '\\n';\n            for (int i = 0; i < N; ++i)\n                cout << i << ' ' << obs_best.r[i] << ' ' << obs_best.d[i] << ' ' << obs_best.b[i] << '\\n';\n            cout.flush();\n            long long Wp, Hp;\n            cin >> Wp >> Hp;\n            continue;\n        }\n\n        double remain = TIME_LIMIT - elapsed();\n        double turn_budget = remain / max(1, T - turn) * 0.85;\n        auto deadline = chrono::steady_clock::now() + chrono::duration<double>(turn_budget);\n\n        // choose starting parent\n        Packing cur;\n        int rc = (int)(rng() % 100);\n        if (rc < 35) cur = pred_best;\n        else if (rc < 65) cur = obs_best;\n        else if (!obs_pop.empty() && rc < 85) cur = obs_pop[rng() % min((int)obs_pop.size(), 4)].second;\n        else {\n            memset(&cur, 0, sizeof(cur));\n            greedy_build(cur, 0, (int)(rng() % 4), true, rng);\n        }\n\n        // iterative local search\n        int no_improve = 0;\n        while (true) {\n            if ((no_improve & 7) == 0) {\n                if (chrono::steady_clock::now() >= deadline) break;\n            }\n\n            Packing nxt = cur;\n            int op = (int)(rng() % 100);\n            if (op < 15) {\n                exhaustive_move(nxt, (int)(rng() % N));\n            } else if (op < 55) {\n                random_move(nxt, (int)(rng() % N), rng);\n            } else if (op < 75 && !obs_pop.empty()) {\n                int other = rng() % obs_pop.size();\n                int k = rng() % (N - 1) + 1;\n                nxt = crossover(cur, obs_pop[other].second, k);\n            } else if (op < 90) {\n                int k = rng() % N;\n                greedy_build(nxt, k, (int)(rng() % 4), true, rng);\n            } else {\n                int k = 2 + (int)(rng() % 5);\n                int min_i = N;\n                for (int t = 0; t < k; ++t) {\n                    int i = rng() % N;\n                    if (i < min_i) min_i = i;\n                    nxt.r[i] = (int)(rng() & 1);\n                    nxt.d[i] = (rng() & 1) ? 'L' : 'U';\n                    nxt.b[i] = (int)(rng() % (i + 1)) - 1;\n                }\n                simulate(nxt, min_i);\n            }\n\n            if (nxt.score < cur.score) {\n                cur = nxt;\n                no_improve = 0;\n            } else {\n                ++no_improve;\n                if (no_improve > 80 && (rng() & 255) < 40) {\n                    cur = nxt;\n                    no_improve = 0;\n                }\n            }\n        }\n\n        // epsilon exploration\n        Packing cand = cur;\n        if ((rng() % 16) == 0) {\n            Packing tmp = cur;\n            int i = rng() % N;\n            tmp.r[i] = (int)(rng() & 1);\n            tmp.d[i] = (rng() & 1) ? 'L' : 'U';\n            tmp.b[i] = (int)(rng() % (i + 1)) - 1;\n            simulate(tmp, i);\n            if (tmp.score < cand.score) cand = tmp;\n        }\n\n        if (cand.score < pred_best.score) pred_best = cand;\n\n        cout << N << '\\n';\n        for (int i = 0; i < N; ++i) {\n            cout << i << ' ' << cand.r[i] << ' ' << cand.d[i] << ' ' << cand.b[i] << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        long long obs = Wp + Hp;\n\n        add_obs(obs, cand);\n        if (obs < best_observed) {\n            best_observed = obs;\n            obs_best = cand;\n        }\n    }\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    \n    int N, M, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; ++i) cin >> A[i];\n    vector<vector<int>> adj(N);\n    for (int i = 0; i < M; ++i) {\n        int u, v; cin >> u >> v;\n        adj[u].push_back(v);\n        adj[v].push_back(u);\n    }\n    for (int i = 0; i < N; ++i) {\n        int x, y; cin >> x >> y;\n    }\n\n    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());\n    auto rand01 = [&]() -> double {\n        return (rng() & 0x7FFFFFFF) / 2147483648.0;\n    };\n\n    // sup[v][k] = #neighbours of v with depth k-1  (1..H)\n    vector<array<short, 13>> sup(N);\n    vector<int> d(N);\n    vector<int> best_d(N, 0);\n    long long best_score = 0;\n\n    auto recompute_sup = [&]() {\n        for (int i = 0; i < N; ++i) sup[i].fill(0);\n        for (int v = 0; v < N; ++v) {\n            for (int w : adj[v]) {\n                int k = d[w] + 1;\n                if (k <= H) ++sup[v][k];\n            }\n        }\n    };\n\n    auto calc_score = [&]() -> long long {\n        long long s = 0;\n        for (int i = 0; i < N; ++i) s += 1LL * (d[i] + 1) * A[i];\n        return s;\n    };\n\n    auto apply_move = [&](int v, int k) {\n        int old = d[v];\n        if (old == k) return;\n        for (int w : adj[v]) {\n            if (old + 1 <= H) --sup[w][old + 1];\n            if (k + 1 <= H) ++sup[w][k + 1];\n        }\n        d[v] = k;\n    };\n\n    auto greedy_ascent = [&](const vector<int>& order) -> long long {\n        fill(d.begin(), d.end(), 0);\n        for (int i = 0; i < N; ++i) sup[i].fill(0);\n        for (int v = 0; v < N; ++v) for (int w : adj[v]) ++sup[v][1];\n        vector<int> ord = order;\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int v : ord) {\n                int dv = d[v];\n                if (dv == H) continue;\n                bool locked = false;\n                if (dv + 1 <= H) {\n                    for (int w : adj[v]) {\n                        if (d[w] == dv + 1 && sup[w][dv + 1] == 1) {\n                            locked = true; break;\n                        }\n                    }\n                }\n                if (locked) continue;\n                for (int k = H; k > dv; --k) {\n                    if (sup[v][k] > 0) {\n                        for (int w : adj[v]) {\n                            --sup[w][dv + 1];\n                            if (k + 1 <= H) ++sup[w][k + 1];\n                        }\n                        d[v] = k;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n        return calc_score();\n    };\n\n    auto polish = [&]() {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int v : ord) {\n                int dv = d[v];\n                if (dv == H) continue;\n                bool locked = false;\n                if (dv + 1 <= H) {\n                    for (int w : adj[v]) {\n                        if (d[w] == dv + 1 && sup[w][dv + 1] == 1) {\n                            locked = true; break;\n                        }\n                    }\n                }\n                if (locked) continue;\n                for (int k = H; k > dv; --k) {\n                    if (sup[v][k] > 0) {\n                        for (int w : adj[v]) {\n                            --sup[w][dv + 1];\n                            if (k + 1 <= H) ++sup[w][k + 1];\n                        }\n                        d[v] = k;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n    };\n\n    auto is_unlocked = [&](int v) -> bool {\n        if (d[v] + 1 <= H) {\n            for (int w : adj[v]) {\n                if (d[w] == d[v] + 1 && sup[w][d[v] + 1] == 1) return false;\n            }\n        }\n        return true;\n    };\n\n    const double TL = 1.96;\n    double start_t = (double)clock() / CLOCKS_PER_SEC;\n    auto elapsed = [&]() { return (double)clock() / CLOCKS_PER_SEC - start_t; };\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n\n    // ---- Phase 1: Construction ----\n    // Ascending A (strong baseline)\n    sort(ord.begin(), ord.end(), [&](int a, int b){ return A[a] < A[b]; });\n    best_score = greedy_ascent(ord);\n    best_d = d;\n\n    // Descending A\n    sort(ord.begin(), ord.end(), [&](int a, int b){ return A[a] > A[b]; });\n    long long sc = greedy_ascent(ord);\n    if (sc > best_score) { best_score = sc; best_d = d; }\n\n    // Many noisy greedy ascents for diversification\n    while (elapsed() < 0.50) {\n        iota(ord.begin(), ord.end(), 0);\n        int mode = rng() % 4;\n        if (mode == 0) {\n            shuffle(ord.begin(), ord.end(), rng);\n        } else {\n            int noise = (mode == 1) ? 15 : (mode == 2) ? 40 : 80;\n            vector<int> nvals(N);\n            for (int i = 0; i < N; ++i) nvals[i] = (int)(rng() % noise);\n            sort(ord.begin(), ord.end(), [&](int a, int b){\n                int va = A[a] + nvals[a];\n                int vb = A[b] + nvals[b];\n                if (va != vb) return va < vb;\n                return a < b;\n            });\n        }\n        sc = greedy_ascent(ord);\n        if (sc > best_score) {\n            best_score = sc;\n            best_d = d;\n        }\n    }\n\n    // ---- Phase 2: Single long SA from the best start ----\n    d = best_d;\n    recompute_sup();\n    long long cur_score = best_score;\n\n    const int K = 15;\n    const double T0 = 1000.0;\n    const double alpha = 0.99997;\n    double T = T0;\n    int last_improve = 0;\n    int iter = 0;\n\n    while (elapsed() < TL) {\n        if ((iter & 4095) == 0 && elapsed() >= TL) break;\n\n        // Best-of-K steepest ascent among unlocked vertices\n        int best_v = -1, best_k = -1;\n        long long best_gain = LLONG_MIN;\n\n        for (int s = 0; s < K; ) {\n            int v = (int)(rng() % N);\n            if (!is_unlocked(v)) continue;\n            ++s;\n            int old = d[v];\n            if (old > 0) {\n                long long gain = -1LL * old * A[v];\n                if (gain > best_gain) {\n                    best_gain = gain; best_v = v; best_k = 0;\n                }\n            }\n            for (int k2 = 1; k2 <= H; ++k2) {\n                if (k2 == old || sup[v][k2] == 0) continue;\n                long long gain = 1LL * (k2 - old) * A[v];\n                if (gain > best_gain) {\n                    best_gain = gain; best_v = v; best_k = k2;\n                }\n            }\n        }\n\n        bool moved = false;\n        if (best_gain > 0) {\n            apply_move(best_v, best_k);\n            cur_score += best_gain;\n            moved = true;\n        } else {\n            // No improving move found: try up to 3 random SA moves\n            for (int attempt = 0; attempt < 3 && !moved; ++attempt) {\n                int v = (int)(rng() % N);\n                if (!is_unlocked(v)) continue;\n                int old = d[v];\n                int cands[12];\n                int cn = 0;\n                cands[cn++] = 0;\n                for (int k2 = 1; k2 <= H; ++k2) {\n                    if (k2 != old && sup[v][k2] > 0) cands[cn++] = k2;\n                }\n                if (cn <= 1) continue;\n                int k = cands[(int)(rng() % cn)];\n                long long gain = 1LL * (k - old) * A[v];\n                bool accept = (gain > 0);\n                if (!accept) {\n                    double prob = exp((double)gain / T);\n                    accept = prob > rand01();\n                }\n                if (accept) {\n                    apply_move(v, k);\n                    cur_score += gain;\n                    moved = true;\n                }\n            }\n        }\n\n        if (moved && cur_score > best_score) {\n            best_score = cur_score;\n            best_d = d;\n            last_improve = iter;\n        }\n\n        T *= alpha;\n        if (T < 0.005) T = 0.005;\n\n        // Periodic monotonic polish\n        if (iter % 20000 == 0) {\n            polish();\n            cur_score = calc_score();\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_d = d;\n                last_improve = iter;\n            }\n        }\n\n        // Ruin-and-recreate when stuck\n        if (iter - last_improve > 70000) {\n            if (cur_score < best_score) {\n                d = best_d;\n                cur_score = best_score;\n                recompute_sup();\n            }\n            // Lower a few random unlocked vertices to open structure\n            for (int p = 0; p < 5; ++p) {\n                int v = (int)(rng() % N);\n                if (d[v] > 0 && is_unlocked(v)) {\n                    int cands[12];\n                    int cn = 0;\n                    for (int k2 = 0; k2 < d[v]; ++k2) {\n                        if (k2 == 0 || sup[v][k2] > 0) cands[cn++] = k2;\n                    }\n                    if (cn > 0) apply_move(v, cands[(int)(rng() % cn)]);\n                }\n            }\n            polish();\n            cur_score = calc_score();\n            if (cur_score > best_score) {\n                best_score = cur_score;\n                best_d = d;\n            }\n            T = T0;\n            last_improve = iter;\n        }\n        ++iter;\n    }\n\n    // Final polish on the best known solution\n    d = best_d;\n    recompute_sup();\n    polish();\n    long long final_score = calc_score();\n    if (final_score > best_score) {\n        best_score = final_score;\n        best_d = d;\n    }\n\n    // Reconstruct parents from the best depth labeling\n    vector<int> parent(N, -1);\n    for (int v = 0; v < N; ++v) {\n        if (best_d[v] > 0) {\n            for (int u : adj[v]) {\n                if (best_d[u] == best_d[v] - 1) {\n                    parent[v] = u;\n                    break;\n                }\n            }\n        }\n    }\n    for (int i = 0; i < N; ++i) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 1e9;\n\n/* -------------------------------------------------------------\n   Board state (N <= 20, row bitmasks)\n   ------------------------------------------------------------- */\nstruct State {\n    array<unsigned int, 20> oni{}, fuku{};\n    int oni_cnt = 0;\n};\n\n/* -------------------------------------------------------------\n   Non\u2011restoring sweeps (return false if a Fukunokami would fall)\n   ------------------------------------------------------------- */\nbool sweep_L(State &s, int i, int k, int N) {\n    unsigned int dm = (1u << k) - 1;\n    if (s.fuku[i] & dm) return false;\n    s.oni_cnt -= __builtin_popcount(s.oni[i] & dm);\n    s.oni[i] >>= k;\n    s.fuku[i] >>= k;\n    return true;\n}\nbool sweep_R(State &s, int i, int k, int N) {\n    unsigned int keep = (1u << (N - k)) - 1;\n    unsigned int dm   = (~keep) & ((1u << N) - 1);\n    if (s.fuku[i] & dm) return false;\n    s.oni_cnt -= __builtin_popcount(s.oni[i] & dm);\n    s.oni[i] = (s.oni[i] & keep) << k;\n    s.fuku[i] = (s.fuku[i] & keep) << k;\n    return true;\n}\nbool sweep_U(State &s, int j, int k, int N) {\n    unsigned int fcol = 0, ocol = 0;\n    for (int i = 0; i < N; ++i) {\n        if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n        if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n    }\n    unsigned int dm = (1u << k) - 1;\n    if (fcol & dm) return false;\n    s.oni_cnt -= __builtin_popcount(ocol & dm);\n    for (int i = 0; i < N - k; ++i) {\n        unsigned int vo = (s.oni[i + k] >> j) & 1u;\n        unsigned int vf = (s.fuku[i + k] >> j) & 1u;\n        s.oni[i]  = (s.oni[i]  & ~(1u << j)) | (vo << j);\n        s.fuku[i] = (s.fuku[i] & ~(1u << j)) | (vf << j);\n    }\n    for (int i = N - k; i < N; ++i) {\n        s.oni[i]  &= ~(1u << j);\n        s.fuku[i] &= ~(1u << j);\n    }\n    return true;\n}\nbool sweep_D(State &s, int j, int k, int N) {\n    unsigned int fcol = 0, ocol = 0;\n    for (int i = 0; i < N; ++i) {\n        if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n        if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n    }\n    unsigned int keep = (1u << (N - k)) - 1;\n    unsigned int dm   = (~keep) & ((1u << N) - 1);\n    if (fcol & dm) return false;\n    s.oni_cnt -= __builtin_popcount(ocol & dm);\n    for (int i = N - 1; i >= k; --i) {\n        unsigned int vo = (s.oni[i - k] >> j) & 1u;\n        unsigned int vf = (s.fuku[i - k] >> j) & 1u;\n        s.oni[i]  = (s.oni[i]  & ~(1u << j)) | (vo << j);\n        s.fuku[i] = (s.fuku[i] & ~(1u << j)) | (vf << j);\n    }\n    for (int i = 0; i < k; ++i) {\n        s.oni[i]  &= ~(1u << j);\n        s.fuku[i] &= ~(1u << j);\n    }\n    return true;\n}\n\n/* -------------------------------------------------------------\n   Fast check: every remaining Oni has at least one safe restoring dir?\n   Used only as a cheap pre\u2011filter before calling exact_cost.\n   ------------------------------------------------------------- */\nbool feasible_for_exact(const State &s, int N) {\n    unsigned int all = (1u << N) - 1;\n    for (int i = 0; i < N; ++i) {\n        unsigned int m = s.oni[i];\n        while (m) {\n            int j = __builtin_ctz(m);\n            bool ok = false;\n            if ((s.fuku[i] & ((1u << (j + 1)) - 1)) == 0) ok = true;\n            unsigned int rmask = (~((1u << j) - 1)) & all;\n            if ((s.fuku[i] & rmask) == 0) ok = true;\n            bool up = true;\n            for (int r = 0; r <= i; ++r)\n                if (s.fuku[r] >> j & 1u) { up = false; break; }\n            if (up) ok = true;\n            bool down = true;\n            for (int r = i; r < N; ++r)\n                if (s.fuku[r] >> j & 1u) { down = false; break; }\n            if (down) ok = true;\n            if (!ok) return false;\n            m &= m - 1;\n        }\n    }\n    return true;\n}\n\n/* -------------------------------------------------------------\n   Exact restoring\u2011block solver (weighted set cover, optimal)\n   ------------------------------------------------------------- */\nstruct Block {\n    uint64_t mask;\n    int cost;\n    char dir;\n    int idx;\n    int k;\n};\n\nstatic vector<Block> g_blocks;\nstatic vector<int> g_sol;\n\nuint64_t state_hash(const State& s, int N) {\n    uint64_t h = 14695981039346656037ull;\n    for (int i = 0; i < N; ++i) {\n        h ^= s.oni[i] + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n        h ^= s.fuku[i] + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n    }\n    return h;\n}\n\nstatic unordered_map<uint64_t, int> exact_cache;\n\nint exact_cost_raw(const State &s, int N) {\n    g_blocks.clear();\n    g_sol.clear();\n\n    int id_of[20][20];\n    memset(id_of, -1, sizeof(id_of));\n    vector<pair<int,int>> onis;\n    for (int i = 0; i < N; ++i) {\n        unsigned int m = s.oni[i];\n        while (m) {\n            int j = __builtin_ctz(m);\n            id_of[i][j] = (int)onis.size();\n            onis.emplace_back(i, j);\n            m &= m - 1;\n        }\n    }\n    int M = (int)onis.size();\n    if (M == 0) return 0;\n    const uint64_t FULL = (M == 64) ? ~0ULL : ((1ULL << M) - 1ULL);\n\n    vector<Block> ops;\n    auto add = [&](uint64_t mask, int cost, char d, int idx, int k) {\n        if (mask) ops.push_back({mask, cost, d, idx, k});\n    };\n\n    // rows\n    for (int i = 0; i < N; ++i) {\n        int L = N, R = -1;\n        unsigned int fm = s.fuku[i];\n        if (fm) {\n            L = __builtin_ctz(fm);\n            R = 31 - __builtin_clz(fm);\n        }\n        uint64_t m = 0;\n        for (int j = 0; j < L; ++j)\n            if (s.oni[i] >> j & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (j + 1), 'L', i, j + 1);\n            }\n        m = 0;\n        for (int j = N - 1; j > R; --j)\n            if (s.oni[i] >> j & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (N - j), 'R', i, N - j);\n            }\n    }\n    // columns\n    for (int j = 0; j < N; ++j) {\n        unsigned int fcol = 0, ocol = 0;\n        for (int i = 0; i < N; ++i) {\n            if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n            if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n        }\n        int T = N, Bot = -1;\n        if (fcol) {\n            T  = __builtin_ctz(fcol);\n            Bot = 31 - __builtin_clz(fcol);\n        }\n        uint64_t m = 0;\n        for (int i = 0; i < T; ++i)\n            if (ocol >> i & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (i + 1), 'U', j, i + 1);\n            }\n        m = 0;\n        for (int i = N - 1; i > Bot; --i)\n            if (ocol >> i & 1u) {\n                m |= 1ULL << id_of[i][j];\n                add(m, 2 * (N - i), 'D', j, N - i);\n            }\n    }\n\n    // dominance pruning\n    vector<Block> pruned;\n    for (auto &op : ops) {\n        bool dominated = false;\n        for (auto &p : pruned)\n            if ((p.mask | op.mask) == p.mask && p.cost <= op.cost) {\n                dominated = true; break;\n            }\n        if (dominated) continue;\n        vector<Block> nxt;\n        for (auto &p : pruned)\n            if (!((op.mask | p.mask) == op.mask && op.cost <= p.cost))\n                nxt.push_back(p);\n        nxt.push_back(op);\n        pruned.swap(nxt);\n    }\n    ops.swap(pruned);\n    int S = (int)ops.size();\n\n    vector<vector<int>> cover(M);\n    for (int i = 0; i < S; ++i) {\n        uint64_t m = ops[i].mask;\n        while (m) {\n            int b = __builtin_ctzll(m);\n            cover[b].push_back(i);\n            m &= m - 1;\n        }\n    }\n\n    for (int o = 0; o < M; ++o)\n        if (cover[o].empty()) return INF;\n\n    // greedy upper bound\n    int greedy_cost = 0;\n    uint64_t uncovered = FULL;\n    vector<int> greedy_sol;\n    while (uncovered) {\n        int best = -1;\n        double best_r = 1e300;\n        for (int i = 0; i < S; ++i) {\n            uint64_t nw = ops[i].mask & uncovered;\n            int cnt = __builtin_popcountll(nw);\n            if (cnt == 0) continue;\n            double r = (double)ops[i].cost / cnt;\n            if (r < best_r) { best_r = r; best = i; }\n        }\n        if (best == -1) return INF;\n        greedy_cost += ops[best].cost;\n        uncovered &= ~ops[best].mask;\n        greedy_sol.push_back(best);\n    }\n\n    int best_cost = greedy_cost;\n    vector<int> best_sol = greedy_sol;\n\n    static unordered_map<uint64_t, int> memo;\n    memo.clear();\n    if (memo.bucket_count() < 100000) memo.reserve(100000);\n\n    function<void(uint64_t,int,vector<int>&)> dfs = [&](uint64_t unc, int cur, vector<int> &vec) {\n        if (unc == 0) {\n            if (cur < best_cost) {\n                best_cost = cur;\n                best_sol = vec;\n            }\n            return;\n        }\n        if (cur >= best_cost) return;\n        auto it = memo.find(unc);\n        if (it != memo.end() && it->second <= cur) return;\n        memo[unc] = cur;\n\n        int lb = cur;\n        uint64_t tmp = unc;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int mn = INF;\n            for (int id : cover[o])\n                if (ops[id].mask & unc) mn = min(mn, ops[id].cost);\n            if (mn == INF) return;\n            lb += mn;\n            if (lb >= best_cost) return;\n            tmp &= tmp - 1;\n        }\n\n        int target = -1, mindeg = INT_MAX;\n        tmp = unc;\n        while (tmp) {\n            int o = __builtin_ctzll(tmp);\n            int deg = 0;\n            for (int id : cover[o]) if (ops[id].mask & unc) ++deg;\n            if (deg < mindeg) { mindeg = deg; target = o; }\n            tmp &= tmp - 1;\n        }\n\n        vector<pair<int,int>> cands;\n        for (int id : cover[target])\n            if (ops[id].mask & unc) cands.emplace_back(ops[id].cost, id);\n        sort(cands.begin(), cands.end());\n        for (auto &[c, id] : cands) {\n            if (cur + c >= best_cost) continue;\n            vec.push_back(id);\n            dfs(unc & ~ops[id].mask, cur + c, vec);\n            vec.pop_back();\n        }\n    };\n\n    vector<int> vec;\n    dfs(FULL, 0, vec);\n\n    // remove redundant blocks\n    vector<int> sol = best_sol;\n    bool changed = true;\n    while (changed) {\n        changed = false;\n        for (size_t i = 0; i < sol.size(); ++i) {\n            uint64_t u = 0;\n            for (size_t j = 0; j < sol.size(); ++j)\n                if (j != i) u |= ops[sol[j]].mask;\n            if ((u & FULL) == FULL) {\n                sol.erase(sol.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    g_blocks = ops;\n    g_sol = sol;\n    int total = 0;\n    for (int id : sol) total += ops[id].cost;\n    return total;\n}\n\nint exact_cost_memo(const State &s, int N) {\n    uint64_t h = state_hash(s, N);\n    auto it = exact_cache.find(h);\n    if (it != exact_cache.end()) return it->second;\n    int res = exact_cost_raw(s, N);\n    exact_cache[h] = res;\n    return res;\n}\n\n/* emit restoring moves for the last exact_cost_raw() call */\nvoid exact_seq(vector<pair<char,int>> &out) {\n    for (int id : g_sol) {\n        const Block &op = g_blocks[id];\n        for (int t = 0; t < op.k; ++t) out.emplace_back(op.dir, op.idx);\n        char rev = 0;\n        if (op.dir == 'L') rev = 'R';\n        else if (op.dir == 'R') rev = 'L';\n        else if (op.dir == 'U') rev = 'D';\n        else rev = 'U';\n        for (int t = 0; t < op.k; ++t) out.emplace_back(rev, op.idx);\n    }\n}\n\n/* -------------------------------------------------------------\n   Generate all safe non\u2011restoring sweeps\n   ------------------------------------------------------------- */\nstruct Cand { char d; int idx, k, cnt; };\n\nvector<Cand> gen_cands(const State &s, int N) {\n    vector<Cand> c;\n    unsigned int all = (1u << N) - 1;\n    for (int i = 0; i < N; ++i) {\n        unsigned int orow = s.oni[i], frow = s.fuku[i];\n        int L = N, R = -1;\n        if (frow) {\n            L = __builtin_ctz(frow);\n            R = 31 - __builtin_clz(frow);\n        }\n        for (int j = 0; j < L; ++j)\n            if (orow >> j & 1u) {\n                int k = j + 1;\n                int cnt = __builtin_popcount(orow & ((1u << k) - 1));\n                if (cnt) c.push_back({'L', i, k, cnt});\n            }\n        for (int j = N - 1; j > R; --j)\n            if (orow >> j & 1u) {\n                int k = N - j;\n                int cnt = __builtin_popcount(orow >> j);\n                if (cnt) c.push_back({'R', i, k, cnt});\n            }\n    }\n    for (int j = 0; j < N; ++j) {\n        unsigned int fcol = 0, ocol = 0;\n        for (int i = 0; i < N; ++i) {\n            if (s.fuku[i] >> j & 1u) fcol |= 1u << i;\n            if (s.oni[i] >> j & 1u)  ocol |= 1u << i;\n        }\n        int T = N, Bot = -1;\n        if (fcol) {\n            T  = __builtin_ctz(fcol);\n            Bot = 31 - __builtin_clz(fcol);\n        }\n        for (int i = 0; i < T; ++i)\n            if (ocol >> i & 1u) {\n                int k = i + 1;\n                int cnt = __builtin_popcount(ocol & ((1u << k) - 1));\n                if (cnt) c.push_back({'U', j, k, cnt});\n            }\n        for (int i = N - 1; i > Bot; --i)\n            if (ocol >> i & 1u) {\n                int k = N - i;\n                int cnt = __builtin_popcount(ocol >> i);\n                if (cnt) c.push_back({'D', j, k, cnt});\n            }\n    }\n    return c;\n}\n\n/* -------------------------------------------------------------\n   Pure safe solution (restoring blocks only)\n   ------------------------------------------------------------- */\nvector<pair<char,int>> pure_safe(const vector<string> &B, int N) {\n    State init;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { init.oni[i] |= 1u << j; ++init.oni_cnt; }\n            else if (B[i][j] == 'o') init.fuku[i] |= 1u << j;\n        }\n    exact_cost_raw(init, N);\n    vector<pair<char,int>> moves;\n    exact_seq(moves);\n    return moves;\n}\n\n/* -------------------------------------------------------------\n   Full simulation validator\n   ------------------------------------------------------------- */\nbool validate(const vector<string> &B, const vector<pair<char,int>> &moves, int N) {\n    State s;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { s.oni[i] |= 1u << j; ++s.oni_cnt; }\n            else if (B[i][j] == 'o') s.fuku[i] |= 1u << j;\n        }\n    for (auto &p : moves) {\n        bool ok = false;\n        if (p.first == 'L') ok = sweep_L(s, p.second, 1, N);\n        else if (p.first == 'R') ok = sweep_R(s, p.second, 1, N);\n        else if (p.first == 'U') ok = sweep_U(s, p.second, 1, N);\n        else if (p.first == 'D') ok = sweep_D(s, p.second, 1, N);\n        if (!ok) return false;\n    }\n    return s.oni_cnt == 0;\n}\n\n/* -------------------------------------------------------------\n   2\u2011ply exact lookahead solver with occasional 3\u2011ply rescue\n   ------------------------------------------------------------- */\nvector<pair<char,int>> solve_2ply(const State &init, int N, int best_cost,\n                                  const chrono::steady_clock::time_point &deadline) {\n    vector<pair<char,int>> moves;\n    State s = init;\n    const int W1 = 35;\n    const int W2 = 12;\n\n    while (s.oni_cnt > 0) {\n        if (chrono::steady_clock::now() > deadline) { moves.clear(); return moves; }\n\n        int base = exact_cost_memo(s, N);\n        if (base >= INF) { moves.clear(); return moves; }\n\n        auto cands1 = gen_cands(s, N);\n        struct I1 { Cand c; int total1; };\n        vector<I1> v1;\n        for (const auto &c1 : cands1) {\n            if ((int)moves.size() + c1.k >= best_cost) continue;\n            State s1 = s;\n            bool ok = false;\n            if (c1.d == 'L') ok = sweep_L(s1, c1.idx, c1.k, N);\n            else if (c1.d == 'R') ok = sweep_R(s1, c1.idx, c1.k, N);\n            else if (c1.d == 'U') ok = sweep_U(s1, c1.idx, c1.k, N);\n            else ok = sweep_D(s1, c1.idx, c1.k, N);\n            if (!ok) continue;\n            int tail1 = exact_cost_memo(s1, N);\n            int total1 = (tail1 >= INF) ? INF : c1.k + tail1;\n            if ((int)moves.size() + total1 >= best_cost) continue;\n            v1.push_back({c1, total1});\n        }\n        if (v1.empty()) break;\n        sort(v1.begin(), v1.end(),\n             [](const I1 &a, const I1 &b){\n                 if (a.total1 != b.total1) return a.total1 < b.total1;\n                 return a.c.k < b.c.k;\n             });\n\n        int global_best = base;\n        Cand best_c{0,0,0,0};\n        bool found = false;\n\n        int limit1 = min((int)v1.size(), W1);\n        for (int i = 0; i < limit1; ++i) {\n            if (chrono::steady_clock::now() > deadline) break;\n\n            const Cand &c1 = v1[i].c;\n            if (v1[i].total1 < global_best) {\n                global_best = v1[i].total1;\n                best_c = c1;\n                found = true;\n            }\n\n            State s1 = s;\n            if (c1.d == 'L') sweep_L(s1, c1.idx, c1.k, N);\n            else if (c1.d == 'R') sweep_R(s1, c1.idx, c1.k, N);\n            else if (c1.d == 'U') sweep_U(s1, c1.idx, c1.k, N);\n            else sweep_D(s1, c1.idx, c1.k, N);\n\n            auto cands2 = gen_cands(s1, N);\n            for (const auto &c2 : cands2) {\n                if ((int)moves.size() + c1.k + c2.k >= best_cost) continue;\n                if (c1.k + c2.k >= global_best) continue;\n                State s2 = s1;\n                bool ok = false;\n                if (c2.d == 'L') ok = sweep_L(s2, c2.idx, c2.k, N);\n                else if (c2.d == 'R') ok = sweep_R(s2, c2.idx, c2.k, N);\n                else if (c2.d == 'U') ok = sweep_U(s2, c2.idx, c2.k, N);\n                else ok = sweep_D(s2, c2.idx, c2.k, N);\n                if (!ok) continue;\n                int tail2 = exact_cost_memo(s2, N);\n                if (tail2 >= INF) continue;\n                int total2 = c1.k + c2.k + tail2;\n                if ((int)moves.size() + total2 >= best_cost) continue;\n                if (total2 < global_best) {\n                    global_best = total2;\n                    best_c = c1;\n                    found = true;\n                }\n            }\n        }\n\n        // 3\u2011ply rescue when 2\u2011ply stalls\n        if (!found && chrono::steady_clock::now() < deadline) {\n            const int R1 = 12, R2 = 6;\n            int lim1 = min((int)v1.size(), R1);\n            for (int i = 0; i < lim1; ++i) {\n                if (v1[i].total1 > base + 10) break; // FIXED: stop when too bad\n                if (chrono::steady_clock::now() > deadline) break;\n\n                const Cand &c1 = v1[i].c;\n                State s1 = s;\n                if (c1.d == 'L') sweep_L(s1, c1.idx, c1.k, N);\n                else if (c1.d == 'R') sweep_R(s1, c1.idx, c1.k, N);\n                else if (c1.d == 'U') sweep_U(s1, c1.idx, c1.k, N);\n                else sweep_D(s1, c1.idx, c1.k, N);\n\n                auto cands2 = gen_cands(s1, N);\n                struct I2 { Cand c; int total2; };\n                vector<I2> v2;\n                for (const auto &c2 : cands2) {\n                    if (c1.k + c2.k >= global_best) continue;\n                    State s2 = s1;\n                    bool ok = false;\n                    if (c2.d == 'L') ok = sweep_L(s2, c2.idx, c2.k, N);\n                    else if (c2.d == 'R') ok = sweep_R(s2, c2.idx, c2.k, N);\n                    else if (c2.d == 'U') ok = sweep_U(s2, c2.idx, c2.k, N);\n                    else ok = sweep_D(s2, c2.idx, c2.k, N);\n                    if (!ok) continue;\n                    int tail2 = exact_cost_memo(s2, N);\n                    int total2 = (tail2 >= INF) ? INF : c1.k + c2.k + tail2;\n                    v2.push_back({c2, total2});\n                }\n                sort(v2.begin(), v2.end(),\n                     [](const I2 &a, const I2 &b){\n                         if (a.total2 != b.total2) return a.total2 < b.total2;\n                         return a.c.k < b.c.k;\n                     });\n\n                int lim2 = min((int)v2.size(), R2);\n                for (int j = 0; j < lim2; ++j) {\n                    if (chrono::steady_clock::now() > deadline) break;\n                    const Cand &c2 = v2[j].c;\n                    if (c1.k + c2.k >= global_best) continue;\n                    State s2 = s1;\n                    if (c2.d == 'L') sweep_L(s2, c2.idx, c2.k, N);\n                    else if (c2.d == 'R') sweep_R(s2, c2.idx, c2.k, N);\n                    else if (c2.d == 'U') sweep_U(s2, c2.idx, c2.k, N);\n                    else sweep_D(s2, c2.idx, c2.k, N);\n\n                    auto cands3 = gen_cands(s2, N);\n                    for (const auto &c3 : cands3) {\n                        if (c1.k + c2.k + c3.k >= global_best) continue;\n                        State s3 = s2;\n                        bool ok = false;\n                        if (c3.d == 'L') ok = sweep_L(s3, c3.idx, c3.k, N);\n                        else if (c3.d == 'R') ok = sweep_R(s3, c3.idx, c3.k, N);\n                        else if (c3.d == 'U') ok = sweep_U(s3, c3.idx, c3.k, N);\n                        else ok = sweep_D(s3, c3.idx, c3.k, N);\n                        if (!ok) continue;\n                        int tail3 = exact_cost_memo(s3, N);\n                        if (tail3 >= INF) continue;\n                        int total3 = c1.k + c2.k + c3.k + tail3;\n                        if ((int)moves.size() + total3 >= best_cost) continue;\n                        if (total3 < global_best) {\n                            global_best = total3;\n                            best_c = c1;\n                            found = true;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!found) break;\n\n        bool ok = false;\n        if (best_c.d == 'L') ok = sweep_L(s, best_c.idx, best_c.k, N);\n        else if (best_c.d == 'R') ok = sweep_R(s, best_c.idx, best_c.k, N);\n        else if (best_c.d == 'U') ok = sweep_U(s, best_c.idx, best_c.k, N);\n        else ok = sweep_D(s, best_c.idx, best_c.k, N);\n        if (!ok) { moves.clear(); return moves; }\n\n        for (int t = 0; t < best_c.k; ++t)\n            moves.emplace_back(best_c.d, best_c.idx);\n    }\n\n    if (s.oni_cnt > 0) {\n        int tail = exact_cost_memo(s, N);\n        if (tail >= INF) { moves.clear(); return moves; }\n        if ((int)moves.size() + tail >= best_cost) { moves.clear(); return moves; }\n        exact_cost_raw(s, N);\n        exact_seq(moves);\n    }\n    return moves;\n}\n\n/* -------------------------------------------------------------\n   Stochastic 1\u2011ply greedy with slack\n   ------------------------------------------------------------- */\nvector<pair<char,int>> greedy_stoch(const State &init, int N, int trial_id,\n                                    int best_cost,\n                                    const chrono::steady_clock::time_point &deadline) {\n    vector<pair<char,int>> moves;\n    State s = init;\n    mt19937 rng(123456789 + trial_id * 1000003);\n    const int SLACK = 4;\n\n    while (s.oni_cnt > 0) {\n        if (chrono::steady_clock::now() > deadline) { moves.clear(); return moves; }\n\n        int base = exact_cost_memo(s, N);\n        if (base >= INF) { moves.clear(); return moves; }\n\n        auto cands = gen_cands(s, N);\n        struct Item { Cand c; int total; };\n        vector<Item> items;\n\n        for (auto &c : cands) {\n            if ((int)moves.size() + c.k >= best_cost) continue;\n            State nxt = s;\n            bool ok = false;\n            if (c.d == 'L') ok = sweep_L(nxt, c.idx, c.k, N);\n            else if (c.d == 'R') ok = sweep_R(nxt, c.idx, c.k, N);\n            else if (c.d == 'U') ok = sweep_U(nxt, c.idx, c.k, N);\n            else ok = sweep_D(nxt, c.idx, c.k, N);\n            if (!ok) continue;\n            int rem = exact_cost_memo(nxt, N);\n            int total = (rem >= INF) ? INF : c.k + rem;\n            if ((int)moves.size() + total >= best_cost) continue;\n            if (total < base + SLACK) items.push_back({c, total});\n        }\n\n        if (items.empty()) break;\n\n        sort(items.begin(), items.end(),\n             [](const Item &a, const Item &b){ return a.total < b.total; });\n\n        int top = min(3, (int)items.size());\n        uniform_int_distribution<int> dist(0, top - 1);\n        Cand chosen = items[dist(rng)].c;\n\n        bool ok = false;\n        if (chosen.d == 'L') ok = sweep_L(s, chosen.idx, chosen.k, N);\n        else if (chosen.d == 'R') ok = sweep_R(s, chosen.idx, chosen.k, N);\n        else if (chosen.d == 'U') ok = sweep_U(s, chosen.idx, chosen.k, N);\n        else ok = sweep_D(s, chosen.idx, chosen.k, N);\n        if (!ok) { moves.clear(); return moves; }\n\n        for (int t = 0; t < chosen.k; ++t)\n            moves.emplace_back(chosen.d, chosen.idx);\n    }\n\n    if (s.oni_cnt > 0) {\n        int tail = exact_cost_memo(s, N);\n        if (tail >= INF) { moves.clear(); return moves; }\n        if ((int)moves.size() + tail >= best_cost) { moves.clear(); return moves; }\n        exact_cost_raw(s, N);\n        exact_seq(moves);\n    }\n    return moves;\n}\n\n/* -------------------------------------------------------------\n   Main\n   ------------------------------------------------------------- */\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N;\n    if (!(cin >> N)) return 0;\n    vector<string> B(N);\n    for (int i = 0; i < N; ++i) cin >> B[i];\n\n    const int LIMIT = 4 * N * N;\n\n    // fallback\n    vector<pair<char,int>> best = pure_safe(B, N);\n    int best_cost = (int)best.size();\n\n    auto consider = [&](const vector<pair<char,int>> &moves) {\n        if ((int)moves.size() > LIMIT) return;\n        if (!validate(B, moves, N)) return;\n        if ((int)moves.size() < best_cost) {\n            best_cost = (int)moves.size();\n            best = moves;\n        }\n    };\n\n    State init;\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            if (B[i][j] == 'x') { init.oni[i] |= 1u << j; ++init.oni_cnt; }\n            else if (B[i][j] == 'o') init.fuku[i] |= 1u << j;\n        }\n\n    auto start = chrono::steady_clock::now();\n    auto deadline = start + chrono::milliseconds(1980);\n\n    // primary: 2\u2011ply + occasional 3\u2011ply rescue\n    auto ans = solve_2ply(init, N, best_cost, deadline);\n    consider(ans);\n\n    // remaining time: stochastic greedy trials\n    for (int trial = 1; trial <= 10000; ++trial) {\n        if (chrono::steady_clock::now() > deadline) break;\n        ans = greedy_stoch(init, N, trial, best_cost, deadline);\n        consider(ans);\n    }\n\n    // final safety\n    if (!validate(B, best, N)) {\n        best = pure_safe(B, N);\n    }\n\n    for (auto &p : best)\n        cout << p.first << ' ' << p.second << '\\n';\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    int N, L;\n    if (!(cin >> N >> L)) return 0;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n    vector<int> target2(N);\n    for (int i = 0; i < N; ++i) target2[i] = 2 * T[i];\n\n    mt19937 rng((unsigned)chrono::steady_clock::now().time_since_epoch().count());\n    auto curTime = [&]() { return (double)clock() / (double)CLOCKS_PER_SEC; };\n\n    /*------------------------------------------------------------\n        Phase 1 : pair-greedy init + fast proxy hill climbing\n      ------------------------------------------------------------*/\n    vector<int> a(N), b(N), M(N, 0);\n    vector<int> order(N);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int x, int y){ return T[x] > T[y]; });\n\n    for (int idx : order) {\n        int bestD = INT_MAX;\n        int bestU = -1, bestV = -1;\n        for (int u = 0; u < N; ++u) {\n            int du = abs(M[u] + T[idx] - target2[u]) - abs(M[u] - target2[u]);\n            for (int v = 0; v < N; ++v) {\n                int d;\n                if (u == v) {\n                    d = abs(M[u] + 2 * T[idx] - target2[u]) - abs(M[u] - target2[u]);\n                } else {\n                    d = du + abs(M[v] + T[idx] - target2[v]) - abs(M[v] - target2[v]);\n                }\n                if (d < bestD) {\n                    bestD = d;\n                    bestU = u;\n                    bestV = v;\n                }\n            }\n        }\n        a[idx] = bestU;\n        b[idx] = bestV;\n        M[bestU] += T[idx];\n        M[bestV] += T[idx];\n    }\n\n    for (int it = 0; it < 500000; ++it) {\n        int i = (int)(rng() % N);\n        int typ = (int)(rng() % 2);\n        int oldv = typ ? b[i] : a[i];\n        int newv = (int)(rng() % N);\n        if (newv == oldv) continue;\n        int d = abs(M[oldv] - T[i] - target2[oldv]) - abs(M[oldv] - target2[oldv])\n              + abs(M[newv] + T[i] - target2[newv]) - abs(M[newv] - target2[newv]);\n        if (d < 0) {\n            M[oldv] -= T[i];\n            M[newv] += T[i];\n            if (typ) b[i] = newv; else a[i] = newv;\n        }\n    }\n\n    /*------------------------------------------------------------\n        Phase 2 : exact simulation + SA with proxy filtering\n      ------------------------------------------------------------*/\n    uint8_t nxt[100][2];\n    auto rebuild_nxt = [&]() {\n        for (int i = 0; i < N; ++i) {\n            nxt[i][0] = (uint8_t)b[i];\n            nxt[i][1] = (uint8_t)a[i];\n        }\n    };\n    rebuild_nxt();\n\n    int cnt_arr[100];\n    auto simulate = [&]() -> int {\n        memset(cnt_arr, 0, sizeof(cnt_arr));\n        uint8_t cur = 0;\n        cnt_arr[0] = 1;\n        for (int step = 1; step < L; ++step) {\n            cur = nxt[cur][cnt_arr[cur] & 1];\n            ++cnt_arr[cur];\n        }\n        int err = 0;\n        for (int i = 0; i < N; ++i) err += abs(cnt_arr[i] - T[i]);\n        return err;\n    };\n\n    int curE = simulate();\n    int bestE = curE;\n    vector<int> bestA = a, bestB = b;\n\n    int diff[100];\n    for (int i = 0; i < N; ++i) diff[i] = cnt_arr[i] - T[i];\n\n    double temp = max(100.0, (double)curE * 0.2);\n    uniform_real_distribution<double> prob01(0.0, 1.0);\n    int iter = 0, lastImprove = 0;\n\n    while (true) {\n        if (curTime() > 1.75) break;\n        ++iter;\n\n        if (iter - lastImprove > 150) {\n            a = bestA; b = bestB;\n            fill(M.begin(), M.end(), 0);\n            for (int i = 0; i < N; ++i) {\n                M[a[i]] += T[i];\n                M[b[i]] += T[i];\n            }\n            for (int k = 0; k < 3; ++k) {\n                int i = (int)(rng() % N);\n                int typ = (int)(rng() % 2);\n                int nv = (int)(rng() % N);\n                int ov = typ ? b[i] : a[i];\n                if (ov == nv) continue;\n                M[ov] -= T[i];\n                M[nv] += T[i];\n                if (typ) b[i] = nv; else a[i] = nv;\n            }\n            rebuild_nxt();\n            if (curTime() > 1.75) break;\n            curE = simulate();\n            for (int i = 0; i < N; ++i) diff[i] = cnt_arr[i] - T[i];\n            if (curE < bestE) {\n                bestE = curE;\n                bestA = a; bestB = b;\n                lastImprove = iter;\n            }\n            temp = max(100.0, (double)curE * 0.2);\n            continue;\n        }\n\n        int si = -1, styp = -1, sold = -1, snew = -1;\n        bool swapped = false;\n\n        int mode = (int)(rng() % 5);\n        if (mode < 2) {\n            // random edge change\n            si = (int)(rng() % N);\n            styp = (int)(rng() % 2);\n            sold = styp ? b[si] : a[si];\n            snew = (int)(rng() % N);\n            if (snew == sold) continue;\n            int pd = abs(M[sold] - T[si] - target2[sold]) - abs(M[sold] - target2[sold])\n                   + abs(M[snew] + T[si] - target2[snew]) - abs(M[snew] - target2[snew]);\n            if (pd > 0) continue;\n            M[sold] -= T[si];\n            M[snew] += T[si];\n            if (styp == 0) a[si] = snew; else b[si] = snew;\n            nxt[si][0] = (uint8_t)b[si];\n            nxt[si][1] = (uint8_t)a[si];\n        } else if (mode < 4) {\n            // targeted move\n            int over[100], under[100], nover = 0, nunder = 0;\n            for (int i = 0; i < N; ++i) {\n                if (diff[i] > 200) over[nover++] = i;\n                else if (diff[i] < -200) under[nunder++] = i;\n            }\n            if (nover == 0 || nunder == 0) {\n                si = (int)(rng() % N);\n                styp = (int)(rng() % 2);\n                sold = styp ? b[si] : a[si];\n                snew = (int)(rng() % N);\n                if (snew == sold) continue;\n                int pd = abs(M[sold] - T[si] - target2[sold]) - abs(M[sold] - target2[sold])\n                       + abs(M[snew] + T[si] - target2[snew]) - abs(M[snew] - target2[snew]);\n                if (pd > 0) continue;\n                M[sold] -= T[si];\n                M[snew] += T[si];\n                if (styp == 0) a[si] = snew; else b[si] = snew;\n                nxt[si][0] = (uint8_t)b[si];\n                nxt[si][1] = (uint8_t)a[si];\n            } else {\n                int src = over[(int)(rng() % nover)];\n                int cand_i[100], cand_typ[100], ncand = 0;\n                for (int x = 0; x < N; ++x) {\n                    if (a[x] == src) { cand_i[ncand] = x; cand_typ[ncand] = 0; ++ncand; }\n                    if (b[x] == src) { cand_i[ncand] = x; cand_typ[ncand] = 1; ++ncand; }\n                }\n                if (ncand == 0) {\n                    si = (int)(rng() % N);\n                    styp = (int)(rng() % 2);\n                    sold = styp ? b[si] : a[si];\n                    snew = (int)(rng() % N);\n                    if (snew == sold) continue;\n                    int pd = abs(M[sold] - T[si] - target2[sold]) - abs(M[sold] - target2[sold])\n                           + abs(M[snew] + T[si] - target2[snew]) - abs(M[snew] - target2[snew]);\n                    if (pd > 0) continue;\n                    M[sold] -= T[si];\n                    M[snew] += T[si];\n                    if (styp == 0) a[si] = snew; else b[si] = snew;\n                    nxt[si][0] = (uint8_t)b[si];\n                    nxt[si][1] = (uint8_t)a[si];\n                } else {\n                    int c = (int)(rng() % ncand);\n                    si = cand_i[c]; styp = cand_typ[c];\n                    sold = styp ? b[si] : a[si];\n                    snew = under[(int)(rng() % nunder)];\n                    if (snew == sold) continue;\n                    int pd = abs(M[sold] - T[si] - target2[sold]) - abs(M[sold] - target2[sold])\n                           + abs(M[snew] + T[si] - target2[snew]) - abs(M[snew] - target2[snew]);\n                    if (pd > 0) continue;\n                    M[sold] -= T[si];\n                    M[snew] += T[si];\n                    if (styp == 0) a[si] = snew; else b[si] = snew;\n                    nxt[si][0] = (uint8_t)b[si];\n                    nxt[si][1] = (uint8_t)a[si];\n                }\n            }\n        } else {\n            // swap a_i <-> b_i\n            si = (int)(rng() % N);\n            if (a[si] == b[si]) continue;\n            swapped = true;\n            swap(a[si], b[si]);\n            nxt[si][0] = (uint8_t)b[si];\n            nxt[si][1] = (uint8_t)a[si];\n        }\n\n        if (curTime() > 1.75) break;\n        int newE = simulate();\n        bool accept = false;\n        if (newE < curE) accept = true;\n        else if (prob01(rng) < exp(((double)curE - (double)newE) / temp)) accept = true;\n\n        if (newE < bestE) {\n            bestE = newE;\n            bestA = a;\n            bestB = b;\n            lastImprove = iter;\n        }\n\n        if (accept) {\n            curE = newE;\n            for (int i = 0; i < N; ++i) diff[i] = cnt_arr[i] - T[i];\n            temp *= 0.9995;\n        } else {\n            if (!swapped) {\n                M[sold] += T[si];\n                M[snew] -= T[si];\n                if (styp == 0) a[si] = sold; else b[si] = sold;\n                nxt[si][0] = (uint8_t)b[si];\n                nxt[si][1] = (uint8_t)a[si];\n            } else {\n                swap(a[si], b[si]);\n                nxt[si][0] = (uint8_t)b[si];\n                nxt[si][1] = (uint8_t)a[si];\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << bestA[i] << ' ' << bestB[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, r;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        r.assign(n, 0);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (r[a] < r[b]) swap(a, b);\n        p[b] = a;\n        if (r[a] == r[b]) ++r[a];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    if (!(cin >> N >> M >> Q >> L >> W)) return 0;\n    vector<int> G(M);\n    for (int i = 0; i < M; ++i) cin >> G[i];\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    for (int i = 0; i < N; ++i) cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n    vector<double> cx(N), cy(N);\n    for (int i = 0; i < N; ++i) {\n        cx[i] = (lx[i] + rx[i]) * 0.5;\n        cy[i] = (ly[i] + ry[i]) * 0.5;\n    }\n\n    vector<vector<double>> est(N, vector<double>(N));\n    for (int i = 0; i < N; ++i) {\n        est[i][i] = 0.0;\n        for (int j = i + 1; j < N; ++j) {\n            double dx = cx[i] - cx[j];\n            double dy = cy[i] - cy[j];\n            est[i][j] = est[j][i] = sqrt(dx * dx + dy * dy);\n        }\n    }\n\n    auto expand_bits = [&](uint32_t x) -> uint64_t {\n        uint64_t z = 0;\n        for (int i = 0; i < 15; ++i)\n            z |= ((uint64_t)((x >> i) & 1U)) << (2 * i);\n        return z;\n    };\n    auto morton_key = [&](int v) -> uint64_t {\n        uint32_t x = (uint32_t)(lx[v] + rx[v]);\n        uint32_t y = (uint32_t)(ly[v] + ry[v]);\n        return expand_bits(x) | (expand_bits(y) << 1);\n    };\n\n    auto group_mst_cost = [&](const vector<int> &nodes,\n                              const vector<vector<double>> &d) -> double {\n        int g = (int)nodes.size();\n        if (g <= 1) return 0.0;\n        if (g == 2) return d[nodes[0]][nodes[1]];\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        double total = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            total += mincost[v];\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double dd = d[nodes[v]][nodes[i]];\n                if (dd < mincost[i]) mincost[i] = dd;\n            }\n        }\n        return total;\n    };\n\n    auto group_mst_edges = [&](const vector<int> &nodes,\n                               const vector<vector<double>> &d) -> vector<pair<int,int>> {\n        int g = (int)nodes.size();\n        vector<pair<int,int>> edges;\n        if (g <= 1) return edges;\n        if (g == 2) {\n            edges.emplace_back(nodes[0], nodes[1]);\n            return edges;\n        }\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<int> parent(g, -1);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            if (parent[v] != -1) edges.emplace_back(nodes[parent[v]], nodes[v]);\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double dd = d[nodes[v]][nodes[i]];\n                if (dd < mincost[i]) {\n                    mincost[i] = dd;\n                    parent[i] = v;\n                }\n            }\n        }\n        return edges;\n    };\n\n    auto mst_order = [&](const vector<int> &nodes,\n                         const vector<vector<double>> &d) -> vector<int> {\n        int g = (int)nodes.size();\n        if (g <= 1) return nodes;\n        const double INF = 1e100;\n        vector<double> mincost(g, INF);\n        vector<int> parent(g, -1);\n        vector<char> used(g, 0);\n        mincost[0] = 0.0;\n        for (int it = 0; it < g; ++it) {\n            int v = -1;\n            for (int i = 0; i < g; ++i)\n                if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int i = 0; i < g; ++i) if (!used[i]) {\n                double dd = d[nodes[v]][nodes[i]];\n                if (dd < mincost[i]) {\n                    mincost[i] = dd;\n                    parent[i] = v;\n                }\n            }\n        }\n        vector<vector<int>> adj(g);\n        for (int i = 1; i < g; ++i) {\n            adj[i].push_back(parent[i]);\n            adj[parent[i]].push_back(i);\n        }\n        vector<int> ord;\n        ord.reserve(g);\n        stack<int> st;\n        st.push(0);\n        vector<char> vis(g, 0);\n        vis[0] = 1;\n        while (!st.empty()) {\n            int u = st.top(); st.pop();\n            ord.push_back(nodes[u]);\n            for (int v : adj[u]) if (!vis[v]) {\n                vis[v] = 1;\n                st.push(v);\n            }\n        }\n        return ord;\n    };\n\n    /* ---------- Descending size order ---------- */\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(),\n         [&](int a, int b) {\n             if (G[a] != G[b]) return G[a] > G[b];\n             return a < b;\n         });\n\n    /* ---------- Multi-start greedy (exact seed evaluation) ---------- */\n    mt19937 rng(123456789);\n    uniform_real_distribution<double> uni(0.0, 1.0);\n\n    double best_cost = 1e100;\n    vector<vector<int>> best_groups;\n\n    const int RESTARTS = 15;\n    const double PERTURB = 0.02; // multipliers in [0.99, 1.01]\n\n    for (int rep = 0; rep < RESTARTS; ++rep) {\n        vector<vector<double>> d = est;\n        if (rep > 0) {\n            for (int i = 0; i < N; ++i)\n                for (int j = i + 1; j < N; ++j) {\n                    double noise = 1.0 + PERTURB * (uni(rng) - 0.5);\n                    d[i][j] = d[j][i] = est[i][j] * noise;\n                }\n        }\n\n        vector<vector<int>> groups(M);\n        vector<char> assigned(N, 0);\n        vector<int> unassigned;\n        unassigned.reserve(N);\n        for (int i = 0; i < N; ++i) unassigned.push_back(i);\n        sort(unassigned.begin(), unassigned.end(),\n             [&](int a, int b) { return morton_key(a) < morton_key(b); });\n\n        for (int idx : order) {\n            int g = G[idx];\n            if (g < 3) continue;\n            int U = (int)unassigned.size();\n            int K = min(30, U);\n            vector<int> best_cluster;\n            double best_local = 1e100;\n            for (int s = 0; s < K; ++s) {\n                int seed = unassigned[s * U / K];\n                vector<int> cluster;\n                cluster.reserve(g);\n                cluster.push_back(seed);\n                vector<char> in_cl(N, 0);\n                in_cl[seed] = 1;\n                vector<double> dist(N, 1e100);\n                for (int v : unassigned) if (v != seed) dist[v] = d[seed][v];\n                while ((int)cluster.size() < g) {\n                    int best_u = -1;\n                    double best_du = 1e100;\n                    for (int v : unassigned) {\n                        if (in_cl[v]) continue;\n                        if (dist[v] < best_du) {\n                            best_du = dist[v];\n                            best_u = v;\n                        }\n                    }\n                    cluster.push_back(best_u);\n                    in_cl[best_u] = 1;\n                    for (int v : unassigned) if (!in_cl[v]) {\n                        double nd = d[best_u][v];\n                        if (nd < dist[v]) dist[v] = nd;\n                    }\n                }\n                double cost = group_mst_cost(cluster, d);\n                if (cost < best_local) {\n                    best_local = cost;\n                    best_cluster = move(cluster);\n                }\n            }\n            groups[idx] = best_cluster;\n            for (int v : best_cluster) assigned[v] = 1;\n            vector<int> nxt;\n            nxt.reserve(unassigned.size() - g);\n            for (int v : unassigned) if (!assigned[v]) nxt.push_back(v);\n            unassigned.swap(nxt);\n        }\n\n        for (int idx : order) {\n            if (G[idx] != 2) continue;\n            int U = (int)unassigned.size();\n            double best_d = 1e100;\n            int best_a = -1, best_b = -1;\n            for (int i = 0; i < U; ++i)\n                for (int j = i + 1; j < U; ++j) {\n                    double dd = d[unassigned[i]][unassigned[j]];\n                    if (dd < best_d) {\n                        best_d = dd;\n                        best_a = i;\n                        best_b = j;\n                    }\n                }\n            int a = unassigned[best_a];\n            int b = unassigned[best_b];\n            groups[idx] = {a, b};\n            assigned[a] = assigned[b] = 1;\n            vector<int> nxt;\n            nxt.reserve(U - 2);\n            for (int i = 0; i < U; ++i)\n                if (i != best_a && i != best_b) nxt.push_back(unassigned[i]);\n            unassigned.swap(nxt);\n        }\n\n        for (int idx : order) {\n            if (G[idx] != 1) continue;\n            int v = unassigned.back(); unassigned.pop_back();\n            groups[idx] = {v};\n            assigned[v] = 1;\n        }\n\n        double total = 0.0;\n        for (int k = 0; k < M; ++k) total += group_mst_cost(groups[k], est);\n        if (total < best_cost) {\n            best_cost = total;\n            best_groups = move(groups);\n        }\n    }\n\n    vector<vector<int>> group_nodes = move(best_groups);\n\n    /* ---------- Query allocation ---------- */\n    vector<int> alloc(M, 0);\n    int sum_alloc = 0;\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (g > L) alloc[k] = (g - 1 + L - 2) / (L - 1);\n        else if (g >= 3) alloc[k] = 1;\n        else alloc[k] = 0;\n        sum_alloc += alloc[k];\n    }\n    int surplus = Q - sum_alloc;\n    if (surplus > 0) {\n        vector<int> large;\n        for (int k = 0; k < M; ++k) if (G[k] > L) large.push_back(k);\n        sort(large.begin(), large.end(),\n             [&](int a, int b) { return G[a] > G[b]; });\n        while (surplus > 0) {\n            bool changed = false;\n            for (int k : large) {\n                int max_q = G[k] - L + 1;\n                if (alloc[k] < max_q) {\n                    ++alloc[k];\n                    --surplus;\n                    changed = true;\n                    if (surplus == 0) break;\n                }\n            }\n            if (!changed) break;\n        }\n    }\n\n    /* ---------- Perform queries ---------- */\n    vector<vector<pair<int,int>>> raw_edges(M);\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        if (alloc[k] == 0) continue;\n        const auto &nodes = group_nodes[k];\n        if (g > L) {\n            auto ordered = mst_order(nodes, est);\n            int q = alloc[k];\n            for (int i = 0; i < q; ++i) {\n                int start = (int)((long long)i * (g - L) / (q - 1));\n                cout << \"? \" << L;\n                for (int j = 0; j < L; ++j) cout << ' ' << ordered[start + j];\n                cout << '\\n' << flush;\n                for (int j = 0; j < L - 1; ++j) {\n                    int a, b; cin >> a >> b;\n                    raw_edges[k].push_back({a, b});\n                }\n            }\n        } else {\n            cout << \"? \" << g;\n            for (int v : nodes) cout << ' ' << v;\n            cout << '\\n' << flush;\n            for (int i = 0; i < g - 1; ++i) {\n                int a, b; cin >> a >> b;\n                raw_edges[k].push_back({a, b});\n            }\n        }\n    }\n\n    /* ---------- Output answer ---------- */\n    cout << \"!\\n\";\n    for (int k = 0; k < M; ++k) {\n        int g = G[k];\n        const auto &nodes = group_nodes[k];\n        for (int i = 0; i < g; ++i) {\n            if (i) cout << ' ';\n            cout << nodes[i];\n        }\n        cout << '\\n';\n\n        if (g <= 1) {\n            continue;\n        } else if (g == 2) {\n            cout << nodes[0] << ' ' << nodes[1] << '\\n';\n        } else if (g <= L) {\n            for (auto &e : raw_edges[k])\n                cout << e.first << ' ' << e.second << '\\n';\n        } else {\n            vector<int> pos(N, -1);\n            for (int i = 0; i < g; ++i) pos[nodes[i]] = i;\n            set<pair<int,int>> seen;\n            vector<tuple<double,int,int>> cand;\n            for (auto &e : raw_edges[k]) {\n                int u = e.first, v = e.second;\n                if (u > v) swap(u, v);\n                if (!seen.insert({u, v}).second) continue;\n                int iu = pos[u], iv = pos[v];\n                if (iu == -1 || iv == -1) continue;\n                cand.emplace_back(est[u][v], u, v);\n            }\n            sort(cand.begin(), cand.end());\n            DSU dsu(g);\n            vector<pair<int,int>> tree_edges;\n            for (auto &t : cand) {\n                int u = get<1>(t), v = get<2>(t);\n                if (dsu.unite(pos[u], pos[v])) {\n                    tree_edges.emplace_back(u, v);\n                    if ((int)tree_edges.size() == g - 1) break;\n                }\n            }\n            if ((int)tree_edges.size() < g - 1) {\n                auto est_edges = group_mst_edges(nodes, est);\n                for (auto &e : est_edges) {\n                    int u = e.first, v = e.second;\n                    if (dsu.unite(pos[u], pos[v])) {\n                        tree_edges.push_back(e);\n                        if ((int)tree_edges.size() == g - 1) break;\n                    }\n                }\n            }\n            for (auto &e : tree_edges)\n                cout << e.first << ' ' << e.second << '\\n';\n        }\n    }\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nconst int INF = 0x3F3F3F3F;\nconst int MAXN = 20;\nconst int MAX_ACTIONS = 1600;   // 2 * N * M\nconst int TOP_K = 60;\n\nconst int dr[4] = {-1, 1, 0, 0};\nconst int dc[4] = {0, 0, -1, 1};\n\nint N, M;\nvector<pair<int,int>> pts;\nusing Grid = array<array<char, MAXN>, MAXN>;\nGrid blocks;\narray<array<int, MAXN>, MAXN> target_id;\nvector<pair<char,char>> ans;\n\n/*---------- fast distance-only BFS ----------*/\nint dist_one(int sr, int sc, int tr, int tc, const Grid& blk) {\n    if (sr == tr && sc == tc) return 0;\n    int dist[MAXN][MAXN];\n    pair<int,int> q[MAXN * MAXN];\n    memset(dist, 0x3F, sizeof(dist));\n    int qs = 0, qe = 0;\n    q[qe++] = {sr, sc};\n    dist[sr][sc] = 0;\n    while (qs < qe) {\n        auto [r, c] = q[qs++];\n        int nd = dist[r][c] + 1;\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (blk[nr][nc]) continue;\n            if (dist[nr][nc] > nd) {\n                if (nr == tr && nc == tc) return nd;\n                dist[nr][nc] = nd;\n                q[qe++] = {nr, nc};\n            }\n        }\n        for (int d = 0; d < 4; ++d) {\n            int nr = r + dr[d];\n            int nc = c + dc[d];\n            while (nr >= 0 && nr < N && nc >= 0 && nc < N && !blk[nr][nc]) {\n                nr += dr[d];\n                nc += dc[d];\n            }\n            int rr = nr - dr[d];\n            int cc = nc - dc[d];\n            if (rr == r && cc == c) continue;\n            if (dist[rr][cc] > nd) {\n                if (rr == tr && cc == tc) return nd;\n                dist[rr][cc] = nd;\n                q[qe++] = {rr, cc};\n            }\n        }\n    }\n    return INF;\n}\n\n/*---------- exact suffix cost with budget cutoff ----------*/\nint suffix_cost(int sr, int sc, int idx, const Grid& blk, int budget) {\n    if (idx >= M) return 0;\n    int sum = 0;\n    int r = sr, c = sc;\n    for (int k = idx; k < M; ++k) {\n        int d = dist_one(r, c, pts[k].first, pts[k].second, blk);\n        if (d >= INF) return INF;\n        sum += d;\n        if (sum > budget) return INF;\n        r = pts[k].first;\n        c = pts[k].second;\n    }\n    return sum;\n}\n\n/*---------- full BFS with parent storage ----------*/\nvoid bfs_full(int sr, int sc, const Grid& blk,\n              array<array<int,MAXN>,MAXN>& dist,\n              array<array<pair<int,int>,MAXN>,MAXN>& par,\n              array<array<char,MAXN>,MAXN>& act,\n              array<array<char,MAXN>,MAXN>& dirc)\n{\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            dist[i][j] = INF;\n    queue<pair<int,int>> q;\n    dist[sr][sc] = 0;\n    par[sr][sc] = {-1, -1};\n    act[sr][sc] = 0;\n    dirc[sr][sc] = 0;\n    q.emplace(sr, sc);\n    while (!q.empty()) {\n        auto [r, c] = q.front(); q.pop();\n        int d = dist[r][c];\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n            if (blk[nr][nc]) continue;\n            if (dist[nr][nc] > d + 1) {\n                dist[nr][nc] = d + 1;\n                par[nr][nc] = {r, c};\n                act[nr][nc] = 'M';\n                dirc[nr][nc] = \"UDLR\"[dir];\n                q.emplace(nr, nc);\n            }\n        }\n        for (int dir = 0; dir < 4; ++dir) {\n            int nr = r + dr[dir];\n            int nc = c + dc[dir];\n            while (nr >= 0 && nr < N && nc >= 0 && nc < N && !blk[nr][nc]) {\n                nr += dr[dir];\n                nc += dc[dir];\n            }\n            int rr = nr - dr[dir];\n            int cc = nc - dc[dir];\n            if (rr == r && cc == c) continue;\n            if (dist[rr][cc] > d + 1) {\n                dist[rr][cc] = d + 1;\n                par[rr][cc] = {r, c};\n                act[rr][cc] = 'S';\n                dirc[rr][cc] = \"UDLR\"[dir];\n                q.emplace(rr, cc);\n            }\n        }\n    }\n}\n\n/*---------- reconstruct action sequence ----------*/\nvector<pair<char,char>> reconstruct(int sr, int sc, int gr, int gc,\n                                    const array<array<pair<int,int>,MAXN>,MAXN>& par,\n                                    const array<array<char,MAXN>,MAXN>& act,\n                                    const array<array<char,MAXN>,MAXN>& dirc)\n{\n    vector<pair<char,char>> res;\n    int r = gr, c = gc;\n    while (r != sr || c != sc) {\n        res.push_back({act[r][c], dirc[r][c]});\n        auto [pr, pc] = par[r][c];\n        r = pr; c = pc;\n        if (r == -1 && c == -1) break;\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\n/*============================================================*/\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    if (!(cin >> N >> M)) return 0;\n    pts.resize(M);\n    for (int i = 0; i < M; ++i) cin >> pts[i].first >> pts[i].second;\n\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j) {\n            blocks[i][j] = 0;\n            target_id[i][j] = -1;\n        }\n    for (int i = 0; i < M; ++i)\n        target_id[pts[i].first][pts[i].second] = i;\n\n    ans.clear();\n    int cur_r = pts[0].first;\n    int cur_c = pts[0].second;\n\n    for (int t = 1; t < M; ++t) {\n        int tr = pts[t].first;\n        int tc = pts[t].second;\n\n        /*--- baseline BFS from current position in ORIGINAL grid ---*/\n        array<array<int,MAXN>,MAXN> dist0;\n        array<array<pair<int,int>,MAXN>,MAXN> par0;\n        array<array<char,MAXN>,MAXN> act0, dirc0;\n        bfs_full(cur_r, cur_c, blocks, dist0, par0, act0, dirc0);\n\n        int base_seg = dist0[tr][tc];\n        int base_total = INF;\n        if (base_seg < INF && (int)ans.size() + base_seg <= MAX_ACTIONS) {\n            int base_rem = suffix_cost(tr, tc, t + 1, blocks,\n                                       MAX_ACTIONS - (int)ans.size() - base_seg);\n            if (base_rem < INF) base_total = base_seg + base_rem;\n        }\n\n        struct Cand {\n            int sr, sc, pr, pc;\n            int d_pt;\n            int lb;\n            int next_seg;\n            char dir;\n            bool remove;\n        };\n        vector<Cand> cands;\n        cands.reserve(1000);\n\n        auto generate = [&](int sr, int sc, bool remove) {\n            if (sr == tr && sc == tc) return;          // never touch current target\n            int id = target_id[sr][sc];\n            if (!remove && id > t) return;             // don't block future targets\n            if (remove && id > t) return;              // don't remove future targets\n\n            Grid mod = blocks;\n            mod[sr][sc] ^= 1;\n\n            for (int pd = 0; pd < 4; ++pd) {\n                int pr = sr + dr[pd];\n                int pc = sc + dc[pd];\n                if (pr < 0 || pr >= N || pc < 0 || pc >= N) continue;\n                if (mod[pr][pc]) continue;             // must be empty after alter\n\n                // CRITICAL: pivot must be reachable in the ORIGINAL grid\n                int d0 = dist0[pr][pc];\n                if (d0 >= INF) continue;\n\n                int d_pt = dist_one(pr, pc, tr, tc, mod);\n                if (d_pt >= INF) continue;\n\n                int lb = d0 + 1 + d_pt;\n                if (base_total < INF && lb >= base_total) continue;\n\n                int next_seg = 0;\n                if (t + 1 < M) {\n                    next_seg = dist_one(tr, tc, pts[t+1].first, pts[t+1].second, mod);\n                    if (next_seg >= INF) continue;\n                }\n\n                // direction FROM pivot TO the block cell\n                char alter_dir = '?';\n                if (pr == sr - 1 && pc == sc) alter_dir = 'D';\n                else if (pr == sr + 1 && pc == sc) alter_dir = 'U';\n                else if (pr == sr && pc == sc - 1) alter_dir = 'R';\n                else if (pr == sr && pc == sc + 1) alter_dir = 'L';\n                else continue;\n\n                cands.push_back({sr, sc, pr, pc, d_pt, lb, next_seg, alter_dir, remove});\n            }\n        };\n\n        /*--- placement candidates: cells adjacent to current/future targets ---*/\n        bool in_cand[MAXN][MAXN] = {};\n        for (int k = max(0, t - 1); k < M; ++k) {\n            for (int d = 0; d < 4; ++d) {\n                int nr = pts[k].first + dr[d];\n                int nc = pts[k].second + dc[d];\n                if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                if (blocks[nr][nc]) continue;\n                if (in_cand[nr][nc]) continue;\n                in_cand[nr][nc] = true;\n                generate(nr, nc, false);\n            }\n        }\n\n        /*--- removal candidates ---*/\n        for (int sr = 0; sr < N; ++sr)\n            for (int sc = 0; sc < N; ++sc)\n                if (blocks[sr][sc])\n                    generate(sr, sc, true);\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            return a.lb + a.next_seg < b.lb + b.next_seg;\n        });\n\n        /*--- exact evaluation for top-K finalists ---*/\n        int best_total = base_total;\n        int best_idx = -1;\n\n        int limit = min((int)cands.size(), TOP_K);\n        for (int i = 0; i < limit; ++i) {\n            const auto& c = cands[i];\n            int exact_seg = c.lb; // dist0[pr][pc] + 1 + d_pt\n            if ((int)ans.size() + exact_seg > MAX_ACTIONS) continue;\n            if (exact_seg >= best_total) continue; // rem >= 0, cannot improve\n\n            Grid mod = blocks;\n            mod[c.sr][c.sc] ^= 1;\n            int rem = suffix_cost(tr, tc, t + 1, mod, best_total - exact_seg - 1);\n            if (rem >= INF) continue;\n            if ((int)ans.size() + exact_seg + rem > MAX_ACTIONS) continue;\n\n            int total = exact_seg + rem;\n            if (total < best_total) {\n                best_total = total;\n                best_idx = i;\n            }\n        }\n\n        /*--- execute best plan ---*/\n        if (best_idx != -1 && (best_total < base_total || base_total >= INF)) {\n            const auto& c = cands[best_idx];\n\n            // Path1: cur -> P  (ORIGINAL grid, guaranteed legal)\n            auto path1 = reconstruct(cur_r, cur_c, c.pr, c.pc, par0, act0, dirc0);\n            for (auto &ac : path1) ans.push_back(ac);\n\n            // Alter action\n            ans.push_back({'A', c.dir});\n\n            // Update internal block state\n            blocks[c.sr][c.sc] ^= 1;\n\n            // Path2: P -> target  (MODIFIED grid, if needed)\n            if (c.pr != tr || c.pc != tc) {\n                array<array<int,MAXN>,MAXN> distP;\n                array<array<pair<int,int>,MAXN>,MAXN> parP;\n                array<array<char,MAXN>,MAXN> actP, dircP;\n                bfs_full(c.pr, c.pc, blocks, distP, parP, actP, dircP);\n                auto path2 = reconstruct(c.pr, c.pc, tr, tc, parP, actP, dircP);\n                for (auto &ac : path2) ans.push_back(ac);\n            }\n        } else {\n            // Baseline without altering\n            auto path = reconstruct(cur_r, cur_c, tr, tc, par0, act0, dirc0);\n            for (auto &ac : path) ans.push_back(ac);\n        }\n\n        cur_r = tr;\n        cur_c = tc;\n    }\n\n    for (auto &ac : ans) {\n        cout << ac.first << ' ' << ac.second << '\\n';\n    }\n    return 0;\n}"}}}