{"model_name":"gpt-5.5-none","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Input {\n    int n;\n    vector<int> x, y;\n    vector<long long> r;\n};\n\nstatic constexpr int W = 10000;\nstatic constexpr double TIME_LIMIT = 4.85;\n\nchrono::steady_clock::time_point start_time;\n\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nlong long area(const Rect& e) {\n    return 1LL * (e.c - e.a) * (e.d - e.b);\n}\n\nbool overlap_interval(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\ndouble rect_score(long long s, long long r) {\n    double mn = (double)min(s, r);\n    double mx = (double)max(s, r);\n    double q = mn / mx;\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble total_score(const vector<Rect>& rects, const Input& in) {\n    double res = 0;\n    for (int i = 0; i < in.n; i++) {\n        res += rect_score(area(rects[i]), in.r[i]);\n    }\n    return res;\n}\n\nint max_expand_dir(const vector<Rect>& rects, int idx, int dir) {\n    const Rect& cur = rects[idx];\n    int n = rects.size();\n\n    if (dir == 0) {\n        // left\n        int lim = cur.a;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.c <= cur.a) {\n                lim = min(lim, cur.a - o.c);\n            }\n        }\n        return lim;\n    } else if (dir == 1) {\n        // right\n        int lim = W - cur.c;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.a >= cur.c) {\n                lim = min(lim, o.a - cur.c);\n            }\n        }\n        return lim;\n    } else if (dir == 2) {\n        // down\n        int lim = cur.b;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.d <= cur.b) {\n                lim = min(lim, cur.b - o.d);\n            }\n        }\n        return lim;\n    } else {\n        // up\n        int lim = W - cur.d;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.b >= cur.d) {\n                lim = min(lim, o.b - cur.d);\n            }\n        }\n        return lim;\n    }\n}\n\nRect expanded(Rect r, int dir, int delta) {\n    if (dir == 0) r.a -= delta;\n    else if (dir == 1) r.c += delta;\n    else if (dir == 2) r.b -= delta;\n    else r.d += delta;\n    return r;\n}\n\nvector<Rect> solve_once(const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<Rect> rects(n);\n\n    for (int i = 0; i < n; i++) {\n        rects[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n    }\n\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int stagnate = 0;\n\n    while (elapsed() < TIME_LIMIT && stagnate < 40) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-15;\n\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len;\n                if (dir <= 1) len = rects[id].d - rects[id].b;\n                else len = rects[id].c - rects[id].a;\n\n                long long need = in.r[id] - cur_area;\n\n                vector<int> cand;\n                cand.push_back(1);\n                cand.push_back(mx);\n\n                if (need > 0) {\n                    long long f = need / len;\n                    long long c = (need + len - 1) / len;\n                    for (long long v : {f - 1, f, f + 1, c - 1, c, c + 1}) {\n                        if (1 <= v && v <= mx) cand.push_back((int)v);\n                    }\n                } else {\n                    cand.push_back(1);\n                }\n\n                sort(cand.begin(), cand.end());\n                cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    // Prefer larger useful expansions if gain is almost equal.\n                    gain += 1e-13 * delta;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_dir != -1) {\n                rects[id] = expanded(rects[id], best_dir, best_delta);\n                changed = true;\n            }\n        }\n\n        if (changed) stagnate = 0;\n        else stagnate++;\n    }\n\n    return rects;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    Input in;\n    cin >> in.n;\n    in.x.resize(in.n);\n    in.y.resize(in.n);\n    in.r.resize(in.n);\n\n    for (int i = 0; i < in.n; i++) {\n        cin >> in.x[i] >> in.y[i] >> in.r[i];\n    }\n\n    mt19937 rng(1234567);\n\n    vector<Rect> best;\n    double best_score = -1;\n\n    int trials = 0;\n\n    while (elapsed() < TIME_LIMIT) {\n        auto rects = solve_once(in, rng);\n        double sc = total_score(rects, in);\n\n        if (sc > best_score) {\n            best_score = sc;\n            best = rects;\n        }\n\n        trials++;\n        if (trials >= 200 && elapsed() > TIME_LIMIT * 0.8) break;\n    }\n\n    if (best.empty()) {\n        best.resize(in.n);\n        for (int i = 0; i < in.n; i++) {\n            best[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n        }\n    }\n\n    for (int i = 0; i < in.n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' '\n             << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr double TIME_LIMIT = 1.90;\n\nint si, sj;\nint tile_id[N][N];\nint pval[N][N];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) {\n        return (int)(next() % n);\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nbool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tile = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> tile_id[i][j];\n            max_tile = max(max_tile, tile_id[i][j]);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> pval[i][j];\n        }\n    }\n\n    int M = max_tile + 1;\n\n    Timer timer;\n    XorShift rng;\n\n    string best_path;\n    int best_score = pval[si][sj];\n\n    vector<int> visited(M, 0);\n    vector<pair<int,int>> cells;\n    vector<char> path;\n\n    int iter = 0;\n\n    while (timer.elapsed() < TIME_LIMIT) {\n        iter++;\n\n        fill(visited.begin(), visited.end(), 0);\n        cells.clear();\n        path.clear();\n\n        int ci = si;\n        int cj = sj;\n        int score = pval[ci][cj];\n\n        visited[tile_id[ci][cj]] = 1;\n        cells.emplace_back(ci, cj);\n\n        // Randomized parameters for this rollout\n        int mode = rng.next_int(5);\n\n        int w_deg;\n        int w_near;\n        int noise;\n\n        if (mode == 0) {\n            // score-oriented\n            w_deg = 12;\n            w_near = 2;\n            noise = 180;\n        } else if (mode == 1) {\n            // avoid dead ends\n            w_deg = 35;\n            w_near = 2;\n            noise = 120;\n        } else if (mode == 2) {\n            // Warnsdorff-like: sometimes go into narrow areas first\n            w_deg = -25;\n            w_near = 1;\n            noise = 120;\n        } else if (mode == 3) {\n            // balanced\n            w_deg = 20;\n            w_near = 4;\n            noise = 160;\n        } else {\n            // more random exploration\n            w_deg = 8;\n            w_near = 1;\n            noise = 350;\n        }\n\n        while (true) {\n            struct Cand {\n                int dir;\n                int ni, nj;\n                int eval;\n            };\n\n            vector<Cand> cand;\n\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n\n                if (!inside(ni, nj)) continue;\n\n                int tid = tile_id[ni][nj];\n                if (visited[tid]) continue;\n\n                visited[tid] = 1;\n\n                int deg = 0;\n                int near_score = 0;\n\n                for (int e = 0; e < 4; e++) {\n                    int xi = ni + di[e];\n                    int xj = nj + dj[e];\n\n                    if (!inside(xi, xj)) continue;\n\n                    int nt = tile_id[xi][xj];\n                    if (!visited[nt]) {\n                        deg++;\n                        near_score += pval[xi][xj];\n                    }\n                }\n\n                visited[tid] = 0;\n\n                int eval = pval[ni][nj] * 100\n                         + w_deg * deg\n                         + w_near * near_score\n                         + rng.next_int(noise + 1);\n\n                // Strong penalty for immediate dead end unless it is very valuable\n                if (deg == 0) eval -= 2500;\n\n                cand.push_back({d, ni, nj, eval});\n            }\n\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n                return a.eval > b.eval;\n            });\n\n            int choose = 0;\n\n            // Occasionally choose second/third best to diversify\n            int r = rng.next_int(100);\n            if ((int)cand.size() >= 2 && r < 18) choose = 1;\n            if ((int)cand.size() >= 3 && r < 6) choose = 2;\n            if ((int)cand.size() >= 4 && r < 2) choose = 3;\n\n            auto c = cand[choose];\n\n            path.push_back(dc[c.dir]);\n            ci = c.ni;\n            cj = c.nj;\n            visited[tile_id[ci][cj]] = 1;\n            score += pval[ci][cj];\n            cells.emplace_back(ci, cj);\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_path.assign(path.begin(), path.end());\n        }\n    }\n\n    cout << best_path << '\\n';\n\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int Q = 1000;\n\nstruct UsedEdge {\n    int type; // 0 horizontal, 1 vertical\n    int a, b;\n};\n\ndouble h_est[N][N - 1];\ndouble v_est[N - 1][N];\n\nint h_cnt[N][N - 1];\nint v_cnt[N - 1][N];\n\ndouble row_sum[N], row_cnt[N];\ndouble col_sum[N], col_cnt[N];\n\nstring prev_path;\nint prev_si, prev_sj, prev_ti, prev_tj;\nvector<UsedEdge> prev_edges;\n\nmt19937 rng(1234567);\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos(int x) {\n    return {x / N, x % N};\n}\n\ndouble get_h_cost(int i, int j, int turn) {\n    double local = h_est[i][j];\n    double global = row_cnt[i] > 0 ? row_sum[i] / row_cnt[i] : 5000.0;\n    double alpha = min(0.75, h_cnt[i][j] / 4.0);\n    double beta = min(0.55, turn / 700.0);\n    return alpha * local + (1.0 - alpha) * ((1.0 - beta) * 5000.0 + beta * global);\n}\n\ndouble get_v_cost(int i, int j, int turn) {\n    double local = v_est[i][j];\n    double global = col_cnt[j] > 0 ? col_sum[j] / col_cnt[j] : 5000.0;\n    double alpha = min(0.75, v_cnt[i][j] / 4.0);\n    double beta = min(0.55, turn / 700.0);\n    return alpha * local + (1.0 - alpha) * ((1.0 - beta) * 5000.0 + beta * global);\n}\n\nvector<UsedEdge> path_edges(int si, int sj, const string& path) {\n    vector<UsedEdge> edges;\n    int i = si, j = sj;\n    for (char c : path) {\n        if (c == 'U') {\n            edges.push_back({1, i - 1, j});\n            --i;\n        } else if (c == 'D') {\n            edges.push_back({1, i, j});\n            ++i;\n        } else if (c == 'L') {\n            edges.push_back({0, i, j - 1});\n            --j;\n        } else if (c == 'R') {\n            edges.push_back({0, i, j});\n            ++j;\n        }\n    }\n    return edges;\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool vertical_first) {\n    string s;\n    if (vertical_first) {\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n    } else {\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n    }\n    return s;\n}\n\nstring randomized_manhattan(int si, int sj, int ti, int tj) {\n    string s;\n    int i = si, j = sj;\n    while (i != ti || j != tj) {\n        vector<char> cand;\n        if (i < ti) cand.push_back('D');\n        if (i > ti) cand.push_back('U');\n        if (j < tj) cand.push_back('R');\n        if (j > tj) cand.push_back('L');\n        char c = cand[rng() % cand.size()];\n        s.push_back(c);\n        if (c == 'D') ++i;\n        else if (c == 'U') --i;\n        else if (c == 'R') ++j;\n        else --j;\n    }\n    return s;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    vector<double> dist(V, 1e100);\n    vector<int> par(V, -1);\n    vector<char> pch(V, '?');\n\n    priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n\n    int S = id(si, sj), T = id(ti, tj);\n    dist[S] = 0;\n    pq.push({0, S});\n\n    while (!pq.empty()) {\n        auto [d, x] = pq.top();\n        pq.pop();\n        if (d != dist[x]) continue;\n        if (x == T) break;\n\n        auto [i, j] = pos(x);\n\n        auto relax = [&](int ni, int nj, double w, char c) {\n            int y = id(ni, nj);\n            if (dist[y] > d + w) {\n                dist[y] = d + w;\n                par[y] = x;\n                pch[y] = c;\n                pq.push({dist[y], y});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, get_v_cost(i - 1, j, turn), 'U');\n        if (i + 1 < N) relax(i + 1, j, get_v_cost(i, j, turn), 'D');\n        if (j > 0) relax(i, j - 1, get_h_cost(i, j - 1, turn), 'L');\n        if (j + 1 < N) relax(i, j + 1, get_h_cost(i, j, turn), 'R');\n    }\n\n    string res;\n    int cur = T;\n    while (cur != S) {\n        res.push_back(pch[cur]);\n        cur = par[cur];\n        if (cur < 0) {\n            // Should never happen.\n            return manhattan_path(si, sj, ti, tj, true);\n        }\n    }\n    reverse(res.begin(), res.end());\n\n    // Dijkstra can generate paths with cycles only if negative edges exist, impossible here.\n    return res;\n}\n\nvoid update_from_result(int measured, int turn) {\n    if (prev_edges.empty()) return;\n\n    double predicted = 0.0;\n    for (auto &e : prev_edges) {\n        if (e.type == 0) predicted += h_est[e.a][e.b];\n        else predicted += v_est[e.a][e.b];\n    }\n\n    if (predicted <= 1.0) return;\n\n    double ratio = measured / predicted;\n\n    // Clamp to reduce influence of 10% multiplicative noise and bad current estimates.\n    ratio = max(0.70, min(1.30, ratio));\n\n    int len = (int)prev_edges.size();\n\n    // Learning rate decreases over time and with path length.\n    double lr = 0.35;\n    if (turn > 100) lr = 0.25;\n    if (turn > 400) lr = 0.18;\n    if (turn > 700) lr = 0.12;\n    lr *= min(1.0, 30.0 / max(10, len));\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            int i = e.a, j = e.b;\n            double old = h_est[i][j];\n            double neu = old * (1.0 + lr * (ratio - 1.0));\n            neu = max(100.0, min(10000.0, neu));\n            h_est[i][j] = neu;\n            h_cnt[i][j]++;\n\n            // Row aggregate receives an implied per-edge average.\n            double implied = measured / (double)len;\n            row_sum[i] += implied;\n            row_cnt[i] += 1.0;\n        } else {\n            int i = e.a, j = e.b;\n            double old = v_est[i][j];\n            double neu = old * (1.0 + lr * (ratio - 1.0));\n            neu = max(100.0, min(10000.0, neu));\n            v_est[i][j] = neu;\n            v_cnt[i][j]++;\n\n            double implied = measured / (double)len;\n            col_sum[j] += implied;\n            col_cnt[j] += 1.0;\n        }\n    }\n}\n\nbool valid_simple_path(int si, int sj, int ti, int tj, const string& s) {\n    bool seen[N][N] = {};\n    int i = si, j = sj;\n    seen[i][j] = true;\n    for (char c : s) {\n        if (c == 'U') --i;\n        else if (c == 'D') ++i;\n        else if (c == 'L') --j;\n        else if (c == 'R') ++j;\n        else return false;\n\n        if (i < 0 || i >= N || j < 0 || j >= N) return false;\n        if (seen[i][j]) return false;\n        seen[i][j] = true;\n    }\n    return i == ti && j == tj;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; i++) {\n        row_sum[i] = row_cnt[i] = 0;\n        for (int j = 0; j < N - 1; j++) {\n            h_est[i][j] = 5000.0;\n            h_cnt[i][j] = 0;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        col_sum[j] = col_cnt[j] = 0;\n    }\n\n    for (int i = 0; i < N - 1; i++) {\n        for (int j = 0; j < N; j++) {\n            v_est[i][j] = 5000.0;\n            v_cnt[i][j] = 0;\n        }\n    }\n\n    int measured = -1;\n\n    for (int turn = 0; turn < Q; turn++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        if (turn > 0) {\n            // In the real interactive judge, result of previous query is read after output.\n            // Here, because of loop structure, measured has already been read at the end\n            // of previous iteration.\n            update_from_result(measured, turn);\n        }\n\n        string ans;\n\n        if (turn < 40) {\n            // Early exploration: diverse monotone paths.\n            if (turn % 3 == 0) ans = manhattan_path(si, sj, ti, tj, true);\n            else if (turn % 3 == 1) ans = manhattan_path(si, sj, ti, tj, false);\n            else ans = randomized_manhattan(si, sj, ti, tj);\n        } else {\n            ans = dijkstra_path(si, sj, ti, tj, turn);\n\n            // Occasionally still use monotone exploration early/mid-game.\n            if (turn < 250 && turn % 13 == 0) {\n                string alt = randomized_manhattan(si, sj, ti, tj);\n                if ((int)alt.size() <= (int)ans.size() + 8) ans = alt;\n            }\n        }\n\n        if (!valid_simple_path(si, sj, ti, tj, ans)) {\n            ans = manhattan_path(si, sj, ti, tj, true);\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        prev_path = ans;\n        prev_si = si;\n        prev_sj = sj;\n        prev_ti = ti;\n        prev_tj = tj;\n        prev_edges = path_edges(si, sj, ans);\n\n        cin >> measured;\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const string ALPHA = \"ABCDEFGH\";\n\nint M;\nvector<string> S;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        auto now = chrono::steady_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nint overlap_len(const string& a, const string& b) {\n    int ma = (int)a.size(), mb = (int)b.size();\n    int lim = min(ma, mb);\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[ma - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nbool contains_str(const string& a, const string& b) {\n    return a.find(b) != string::npos;\n}\n\nvector<string> greedy_merge_lines(vector<string> v, int maxLines, int maxLen) {\n    vector<int> alive(v.size(), 1);\n\n    while (true) {\n        int n = v.size();\n        int bestI = -1, bestJ = -1, bestOv = -1;\n        string bestMerge;\n\n        for (int i = 0; i < n; ++i) if (alive[i]) {\n            for (int j = 0; j < n; ++j) if (i != j && alive[j]) {\n                if (contains_str(v[i], v[j])) {\n                    bestI = i;\n                    bestJ = j;\n                    bestOv = 1000;\n                    bestMerge = v[i];\n                    goto FOUND;\n                }\n                int ov = overlap_len(v[i], v[j]);\n                int nl = (int)v[i].size() + (int)v[j].size() - ov;\n                if (nl <= maxLen) {\n                    if (ov > bestOv) {\n                        bestOv = ov;\n                        bestI = i;\n                        bestJ = j;\n                        bestMerge = v[i] + v[j].substr(ov);\n                    }\n                }\n            }\n        }\n\nFOUND:\n        int cnt = 0;\n        for (int x : alive) cnt += x;\n\n        if (bestI == -1) break;\n        if (cnt <= maxLines && bestOv < 2) break;\n\n        v[bestI] = bestMerge;\n        alive[bestJ] = 0;\n    }\n\n    vector<string> res;\n    for (int i = 0; i < (int)v.size(); ++i) if (alive[i]) res.push_back(v[i]);\n\n    sort(res.begin(), res.end(), [](const string& a, const string& b) {\n        if (a.size() != b.size()) return a.size() > b.size();\n        return a < b;\n    });\n\n    if ((int)res.size() > maxLines) res.resize(maxLines);\n    return res;\n}\n\nstring cyclic_extend(const string& s, mt19937& rng) {\n    string t = s;\n    while ((int)t.size() < N) {\n        t += ALPHA[rng() % 8];\n    }\n    if ((int)t.size() > N) t.resize(N);\n    return t;\n}\n\nbool match_in_cyclic(const string& line, const string& pat) {\n    int L = line.size(), K = pat.size();\n    for (int st = 0; st < L; ++st) {\n        bool ok = true;\n        for (int p = 0; p < K; ++p) {\n            if (line[(st + p) % L] != pat[p]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n    return false;\n}\n\nint evaluate(const vector<string>& grid) {\n    vector<string> rows = grid;\n    vector<string> cols(N, string(N, 'A'));\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) cols[j][i] = grid[i][j];\n    }\n\n    int c = 0;\n    for (const string& s : S) {\n        bool ok = false;\n        for (int i = 0; i < N && !ok; ++i) {\n            if (match_in_cyclic(rows[i], s)) ok = true;\n        }\n        for (int j = 0; j < N && !ok; ++j) {\n            if (match_in_cyclic(cols[j], s)) ok = true;\n        }\n        if (ok) ++c;\n    }\n    return c;\n}\n\nvector<string> build_candidate(const vector<string>& lines, mt19937& rng) {\n    vector<string> grid(N, string(N, '.'));\n\n    vector<int> ids(lines.size());\n    iota(ids.begin(), ids.end(), 0);\n\n    shuffle(ids.begin(), ids.end(), rng);\n\n    sort(ids.begin(), ids.end(), [&](int a, int b) {\n        int wa = lines[a].size();\n        int wb = lines[b].size();\n        if ((rng() & 7) == 0) return rng() & 1;\n        return wa > wb;\n    });\n\n    int ptr = 0;\n\n    for (int r = 0; r < N && ptr < (int)ids.size(); ++r, ++ptr) {\n        string t = cyclic_extend(lines[ids[ptr]], rng);\n        int shift = rng() % N;\n        for (int j = 0; j < N; ++j) {\n            grid[r][(j + shift) % N] = t[j];\n        }\n    }\n\n    vector<int> colOrder(N);\n    iota(colOrder.begin(), colOrder.end(), 0);\n    shuffle(colOrder.begin(), colOrder.end(), rng);\n\n    for (int idx = 0; idx < N && ptr < (int)ids.size(); ++idx, ++ptr) {\n        int col = colOrder[idx];\n        string t = cyclic_extend(lines[ids[ptr]], rng);\n        int shift = rng() % N;\n\n        int bestShift = shift;\n        int bestConf = 1e9;\n\n        for (int sh = 0; sh < N; ++sh) {\n            int conf = 0;\n            for (int i = 0; i < N; ++i) {\n                char ch = t[(i - sh + N) % N];\n                if (grid[i][col] != '.' && grid[i][col] != ch) conf++;\n            }\n            if (conf < bestConf) {\n                bestConf = conf;\n                bestShift = sh;\n            }\n        }\n\n        for (int i = 0; i < N; ++i) {\n            char ch = t[(i - bestShift + N) % N];\n            if (grid[i][col] == '.') grid[i][col] = ch;\n            else {\n                if ((rng() & 3) == 0) grid[i][col] = ch;\n            }\n        }\n    }\n\n    vector<int> freq(8, 0);\n    for (auto& s : S) for (char c : s) freq[c - 'A']++;\n    int bestChar = max_element(freq.begin(), freq.end()) - freq.begin();\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == '.') {\n                if ((rng() & 3) == 0) grid[i][j] = ALPHA[rng() % 8];\n                else grid[i][j] = ALPHA[bestChar];\n            }\n        }\n    }\n\n    return grid;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n >> M;\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    Timer timer;\n    mt19937 rng(1234567);\n\n    vector<string> base = S;\n\n    sort(base.begin(), base.end(), [](const string& a, const string& b) {\n        if (a.size() != b.size()) return a.size() > b.size();\n        return a < b;\n    });\n\n    base.erase(unique(base.begin(), base.end()), base.end());\n\n    vector<string> lines = greedy_merge_lines(base, 70, N);\n\n    while ((int)lines.size() < 40) {\n        lines.push_back(S[rng() % M]);\n    }\n\n    vector<string> bestGrid(N, string(N, 'A'));\n    int bestScore = -1;\n\n    int iter = 0;\n    while (timer.elapsed() < 2.85) {\n        vector<string> cand = build_candidate(lines, rng);\n        int sc = evaluate(cand);\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestGrid = cand;\n        }\n\n        iter++;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << bestGrid[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Node {\n    int d, v;\n    bool operator<(const Node& other) const {\n        return d > other.d;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    auto pos = [&](int v) {\n        return pair<int,int>{v / N, v % N};\n    };\n\n    int V = N * N;\n\n    vector<int> road_ids;\n    vector<int> weight(V, 0);\n    vector<int> isroad(V, 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                int v = id(i, j);\n                isroad[v] = 1;\n                weight[v] = grid[i][j] - '0';\n                road_ids.push_back(v);\n            }\n        }\n    }\n\n    int R = (int)road_ids.size();\n\n    vector<vector<int>> visible(V);\n\n    // Horizontal visibility\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            vector<int> seg;\n            int k = j;\n            while (k < N && grid[i][k] != '#') {\n                seg.push_back(id(i, k));\n                k++;\n            }\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n            j = k;\n        }\n    }\n\n    // Vertical visibility\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            vector<int> seg;\n            int k = i;\n            while (k < N && grid[k][j] != '#') {\n                seg.push_back(id(k, j));\n                k++;\n            }\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n            i = k;\n        }\n    }\n\n    for (int v : road_ids) {\n        auto &a = visible[v];\n        sort(a.begin(), a.end());\n        a.erase(unique(a.begin(), a.end()), a.end());\n    }\n\n    const int INF = 1e9;\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    auto dijkstra = [&](int s) {\n        vector<int> dist(V, INF), par(V, -1), parDir(V, -1);\n        priority_queue<Node> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n            if (d != dist[v]) continue;\n\n            auto [i, j] = pos(v);\n            for (int z = 0; z < 4; z++) {\n                int ni = i + di[z];\n                int nj = j + dj[z];\n                if (!inside(ni, nj)) continue;\n                if (grid[ni][nj] == '#') continue;\n\n                int nv = id(ni, nj);\n                int nd = d + weight[nv];\n                if (nd < dist[nv]) {\n                    dist[nv] = nd;\n                    par[nv] = v;\n                    parDir[nv] = z;\n                    pq.push({nd, nv});\n                }\n            }\n        }\n        return tuple<vector<int>, vector<int>, vector<int>>(dist, par, parDir);\n    };\n\n    auto restore_path = [&](int s, int t, const vector<int>& par,\n                            const vector<int>& parDir) {\n        string path;\n        int cur = t;\n        while (cur != s) {\n            int z = parDir[cur];\n            path.push_back(dc[z]);\n            cur = par[cur];\n        }\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    vector<char> covered(V, 0);\n    int covered_count = 0;\n\n    auto apply_visible = [&](int v) {\n        for (int u : visible[v]) {\n            if (!covered[u]) {\n                covered[u] = 1;\n                covered_count++;\n            }\n        }\n    };\n\n    int start = id(si, sj);\n    int cur = start;\n    string answer;\n\n    apply_visible(cur);\n\n    // Initial candidate set: all road cells.\n    vector<int> candidates = road_ids;\n\n    while (covered_count < R) {\n        auto [dist, par, parDir] = dijkstra(cur);\n\n        int best = -1;\n        double bestScore = -1.0;\n        int bestGain = -1;\n        int bestDist = INF;\n\n        for (int v : candidates) {\n            if (dist[v] >= INF) continue;\n\n            int gain = 0;\n            for (int u : visible[v]) {\n                if (!covered[u]) gain++;\n            }\n            if (gain == 0) continue;\n\n            double score = (double)gain / (double)(dist[v] + 1);\n\n            // Slight bias toward large gain.\n            score *= (1.0 + 0.03 * sqrt((double)gain));\n\n            if (score > bestScore ||\n                (abs(score - bestScore) < 1e-12 && dist[v] < bestDist)) {\n                bestScore = score;\n                best = v;\n                bestGain = gain;\n                bestDist = dist[v];\n            }\n        }\n\n        if (best == -1) {\n            // Fallback: should not happen on connected road component.\n            for (int v : road_ids) {\n                if (!covered[v]) {\n                    best = v;\n                    break;\n                }\n            }\n        }\n\n        string path = restore_path(cur, best, par, parDir);\n        answer += path;\n        cur = best;\n        apply_visible(cur);\n    }\n\n    // Return to start.\n    {\n        auto [dist, par, parDir] = dijkstra(cur);\n        string path = restore_path(cur, start, par, parDir);\n        answer += path;\n    }\n\n    cout << answer << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    vector<int> d;\n    vector<int> pre;\n    vector<int> nxt;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<Task> tasks(N);\n    for (int i = 0; i < N; i++) {\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; k++) cin >> tasks[i].d[k];\n    }\n\n    vector<int> indeg(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        tasks[u].nxt.push_back(v);\n        tasks[v].pre.push_back(u);\n        indeg[v]++;\n    }\n\n    // Reverse topological DP: critical path priority.\n    vector<double> crit(N, 1.0);\n    vector<int> descScore(N, 0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double best = 0;\n        int ds = 0;\n        for (int v : tasks[i].nxt) {\n            best = max(best, crit[v]);\n            ds += 1 + descScore[v] / 4;\n        }\n        double diffSum = 0;\n        for (int x : tasks[i].d) diffSum += x;\n        crit[i] = 1.0 + best + 0.015 * diffSum;\n        descScore[i] = min(1000000, ds);\n    }\n\n    vector<double> basePriority(N);\n    for (int i = 0; i < N; i++) {\n        double diffSum = 0;\n        double diffMax = 0;\n        for (int x : tasks[i].d) {\n            diffSum += x;\n            diffMax = max(diffMax, (double)x);\n        }\n\n        basePriority[i] =\n            20.0 * crit[i]\n            + 2.0 * (double)tasks[i].nxt.size()\n            + 0.03 * descScore[i]\n            + 0.05 * diffSum\n            + 0.03 * diffMax\n            - 0.002 * i;\n    }\n\n    // status:\n    // -1 = not started\n    //  0 = running\n    //  1 = completed\n    vector<int> status(N, -1);\n\n    // memberTask[j] = running task index, or -1\n    vector<int> memberTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // Estimated skill vectors.\n    // Generated true skills have norm 20..60, so a neutral initial value around 8~10 is reasonable.\n    vector<vector<double>> skill(M, vector<double>(K, 8.0));\n\n    // completed observations per member\n    vector<int> obsCount(M, 0);\n\n    auto estimate_duration = [&](int task, int member) {\n        double w = 0.0;\n        for (int k = 0; k < K; k++) {\n            w += max(0.0, (double)tasks[task].d[k] - skill[member][k]);\n        }\n        // r_i has mean 0.  If w == 0, duration is 1.\n        return max(1.0, w);\n    };\n\n    auto ready = [&](int task) {\n        if (status[task] != -1) return false;\n        for (int p : tasks[task].pre) {\n            if (status[p] != 1) return false;\n        }\n        return true;\n    };\n\n    int completed = 0;\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        vector<int> availableTasks;\n        availableTasks.reserve(N);\n        for (int i = 0; i < N; i++) {\n            if (ready(i)) availableTasks.push_back(i);\n        }\n\n        vector<int> freeMembers;\n        for (int j = 0; j < M; j++) {\n            if (memberTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        vector<pair<int,int>> assignments;\n\n        // Greedy assignment. Repeatedly choose the best member-task pair.\n        vector<char> taskUsed(N, 0);\n        vector<char> memberUsed(M, 0);\n\n        while (true) {\n            double bestScore = -1e100;\n            int bestMember = -1;\n            int bestTask = -1;\n\n            for (int j : freeMembers) {\n                if (memberUsed[j]) continue;\n\n                for (int t : availableTasks) {\n                    if (taskUsed[t]) continue;\n\n                    double est = estimate_duration(t, j);\n\n                    // Exploration bonus:\n                    // in early phase, give each member varied tasks.\n                    double exploration = 0.0;\n                    if (obsCount[j] < 8) {\n                        double dsum = 0;\n                        for (int x : tasks[t].d) dsum += x;\n                        exploration = 0.04 * dsum;\n                    }\n\n                    // Avoid assigning extremely hard tasks to uncertain members too often.\n                    double uncertaintyPenalty = 0.0;\n                    if (obsCount[j] < 3) uncertaintyPenalty = 0.15 * est;\n\n                    double score =\n                        (basePriority[t] + exploration) / pow(est + 1.0, 0.85)\n                        - uncertaintyPenalty;\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestMember = j;\n                        bestTask = t;\n                    }\n                }\n            }\n\n            if (bestMember == -1) break;\n\n            assignments.push_back({bestMember, bestTask});\n            memberUsed[bestMember] = 1;\n            taskUsed[bestTask] = 1;\n        }\n\n        for (auto [j, t] : assignments) {\n            status[t] = 0;\n            memberTask[j] = t;\n            startDay[j] = day;\n        }\n\n        cout << assignments.size();\n        for (auto [j, t] : assignments) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        string line;\n        if (!getline(cin >> ws, line)) return 0;\n\n        stringstream ss(line);\n        int nfin;\n        ss >> nfin;\n\n        if (nfin == -1) {\n            return 0;\n        }\n\n        for (int z = 0; z < nfin; z++) {\n            int memberInput;\n            ss >> memberInput;\n            int j = memberInput - 1;\n\n            int t = memberTask[j];\n            if (t < 0) continue;\n\n            int duration = day - startDay[j] + 1;\n\n            status[t] = 1;\n            completed++;\n            memberTask[j] = -1;\n            startDay[j] = -1;\n\n            // Online skill update.\n            //\n            // Observed duration is approximately:\n            //   max(1, sum(max(0, d_k - s_k)) + noise)\n            //\n            // We update skills so predicted shortage approaches observed duration.\n            double predW = 0.0;\n            vector<int> active;\n            for (int k = 0; k < K; k++) {\n                double gap = (double)tasks[t].d[k] - skill[j][k];\n                if (gap > 0) {\n                    predW += gap;\n                    active.push_back(k);\n                }\n            }\n\n            double targetW;\n            if (duration <= 1) {\n                targetW = 0.0;\n            } else {\n                targetW = (double)duration;\n            }\n\n            double err = predW - targetW;\n            obsCount[j]++;\n\n            if (!active.empty()) {\n                double lr = 0.35 / sqrt((double)obsCount[j]);\n                double delta = lr * err / (double)active.size();\n\n                // If predW > targetW, member is better than estimated -> increase skills.\n                // If predW < targetW, member is worse than estimated -> decrease skills.\n                for (int k : active) {\n                    skill[j][k] += delta;\n                    if (skill[j][k] < 0.0) skill[j][k] = 0.0;\n                    if (skill[j][k] > 80.0) skill[j][k] = 80.0;\n                }\n            } else {\n                // Completed a task predicted as easy. Raise small lower bounds a little.\n                if (duration <= 1) {\n                    for (int k = 0; k < K; k++) {\n                        if (skill[j][k] < tasks[t].d[k]) {\n                            skill[j][k] += 0.08;\n                            skill[j][k] = min(skill[j][k], 80.0);\n                        }\n                    }\n                }\n            }\n\n            // Extra correction using one-day completion:\n            // if duration is 1, likely s_k >= d_k for many dimensions.\n            if (duration == 1) {\n                double lr = 0.20 / sqrt((double)obsCount[j]);\n                for (int k = 0; k < K; k++) {\n                    if (skill[j][k] < tasks[t].d[k]) {\n                        skill[j][k] += lr * ((double)tasks[t].d[k] - skill[j][k]);\n                        skill[j][k] = min(skill[j][k], 80.0);\n                    }\n                }\n            }\n\n            // Optional visualizer comments. Legal in judge.\n            /*\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << ' ' << (int)round(skill[j][k]);\n            }\n            cout << '\\n';\n            cout.flush();\n            */\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n};\n\nstatic inline int mdist(const Point& p, const Point& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstatic inline int mdist_xy(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nconst Point OFFICE{400, 400};\n\nvector<Order> ords(1000);\n\nPoint pickup_point(int id) {\n    return {ords[id].a, ords[id].b};\n}\n\nPoint delivery_point(int id) {\n    return {ords[id].c, ords[id].d};\n}\n\nvector<int> nearest_order_path(const vector<int>& ids, bool pickup, Point start) {\n    int n = ids.size();\n    vector<int> res;\n    res.reserve(n);\n    vector<char> used(n, false);\n\n    Point cur = start;\n    for (int step = 0; step < n; step++) {\n        int best = -1;\n        int bestd = INT_MAX;\n        for (int i = 0; i < n; i++) {\n            if (used[i]) continue;\n            Point p = pickup ? pickup_point(ids[i]) : delivery_point(ids[i]);\n            int d = mdist(cur, p);\n            if (d < bestd) {\n                bestd = d;\n                best = i;\n            }\n        }\n        used[best] = true;\n        res.push_back(ids[best]);\n        cur = pickup ? pickup_point(ids[best]) : delivery_point(ids[best]);\n    }\n    return res;\n}\n\nint segment_path_length(const vector<Point>& pts) {\n    int s = 0;\n    for (int i = 0; i + 1 < (int)pts.size(); i++) {\n        s += mdist(pts[i], pts[i + 1]);\n    }\n    return s;\n}\n\nvoid two_opt_points(vector<int>& path, bool pickup, Point start, Point goal, int iter_limit = 4000) {\n    int n = path.size();\n    if (n <= 2) return;\n\n    auto getp = [&](int idx) -> Point {\n        if (idx == -1) return start;\n        if (idx == n) return goal;\n        return pickup ? pickup_point(path[idx]) : delivery_point(path[idx]);\n    };\n\n    bool improved = true;\n    int iter = 0;\n    while (improved && iter < iter_limit) {\n        improved = false;\n        iter++;\n        for (int i = 0; i < n - 1; i++) {\n            Point A = getp(i - 1);\n            Point B = getp(i);\n            for (int k = i + 1; k < n; k++) {\n                Point C = getp(k);\n                Point D = getp(k + 1);\n\n                int before = mdist(A, B) + mdist(C, D);\n                int after = mdist(A, C) + mdist(B, D);\n\n                if (after < before) {\n                    reverse(path.begin() + i, path.begin() + k + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    vector<int> ids;\n    vector<int> pickups;\n    vector<int> deliveries;\n    vector<Point> route;\n    int cost;\n};\n\nSolution build_solution(vector<int> ids) {\n    Solution sol;\n    sol.ids = ids;\n\n    sol.pickups = nearest_order_path(ids, true, OFFICE);\n\n    Point last_pick = OFFICE;\n    if (!sol.pickups.empty()) {\n        last_pick = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_order_path(ids, false, last_pick);\n\n    Point first_delivery_start = OFFICE;\n    if (!sol.pickups.empty()) first_delivery_start = pickup_point(sol.pickups.back());\n\n    Point delivery_goal = OFFICE;\n\n    two_opt_points(sol.pickups, true, OFFICE,\n                   sol.deliveries.empty() ? OFFICE : delivery_point(sol.deliveries.front()));\n\n    Point after_pick = OFFICE;\n    if (!sol.pickups.empty()) after_pick = pickup_point(sol.pickups.back());\n\n    sol.deliveries = nearest_order_path(ids, false, after_pick);\n    two_opt_points(sol.deliveries, false, after_pick, OFFICE);\n\n    sol.route.clear();\n    sol.route.push_back(OFFICE);\n\n    for (int id : sol.pickups) {\n        sol.route.push_back(pickup_point(id));\n    }\n    for (int id : sol.deliveries) {\n        sol.route.push_back(delivery_point(id));\n    }\n    sol.route.push_back(OFFICE);\n\n    sol.cost = segment_path_length(sol.route);\n    return sol;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 1000; i++) {\n        cin >> ords[i].a >> ords[i].b >> ords[i].c >> ords[i].d;\n    }\n\n    vector<pair<int,int>> score_id;\n    score_id.reserve(1000);\n\n    for (int i = 0; i < 1000; i++) {\n        int s =\n            mdist_xy(400, 400, ords[i].a, ords[i].b) +\n            mdist_xy(ords[i].a, ords[i].b, ords[i].c, ords[i].d) +\n            mdist_xy(ords[i].c, ords[i].d, 400, 400);\n        score_id.push_back({s, i});\n    }\n\n    sort(score_id.begin(), score_id.end());\n\n    vector<int> initial;\n    for (int i = 0; i < 50; i++) initial.push_back(score_id[i].second);\n\n    Solution best = build_solution(initial);\n\n    vector<int> pool;\n    int pool_size = 180;\n    for (int i = 0; i < pool_size; i++) pool.push_back(score_id[i].second);\n\n    mt19937 rng(1234567);\n\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> cur_ids = best.ids;\n    Solution cur = best;\n\n    while (true) {\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        vector<int> next_ids = cur_ids;\n\n        unordered_set<int> selected(next_ids.begin(), next_ids.end());\n\n        int remove_pos = uniform_int_distribution<int>(0, 49)(rng);\n\n        vector<int> candidates;\n        for (int id : pool) {\n            if (!selected.count(id)) candidates.push_back(id);\n        }\n        if (candidates.empty()) continue;\n\n        int add_id = candidates[uniform_int_distribution<int>(0, (int)candidates.size() - 1)(rng)];\n        next_ids[remove_pos] = add_id;\n\n        sort(next_ids.begin(), next_ids.end());\n        next_ids.erase(unique(next_ids.begin(), next_ids.end()), next_ids.end());\n        if ((int)next_ids.size() != 50) continue;\n\n        Solution nxt = build_solution(next_ids);\n\n        if (nxt.cost < cur.cost || uniform_real_distribution<double>(0.0, 1.0)(rng) < 0.002) {\n            cur = nxt;\n            cur_ids = next_ids;\n        }\n\n        if (nxt.cost < best.cost) {\n            best = nxt;\n        }\n    }\n\n    cout << 50;\n    for (int id : best.ids) {\n        cout << ' ' << id + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (auto& p : best.route) {\n        cout << ' ' << p.x << ' ' << p.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#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) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[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 (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct KEdge {\n    int w;\n    int id;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return id < other.id;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = x[edges[i].u] - x[edges[i].v];\n        long long dy = y[edges[i].u] - y[edges[i].v];\n        edges[i].d = (int)llround(sqrt((double)(dx * dx + dy * dy)));\n    }\n\n    DSU accepted(N);\n    vector<int> actual(M, -1);\n    vector<char> used(M, 0);\n\n    double coef = 1.92;\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        actual[i] = l;\n\n        bool take = false;\n\n        int ru = accepted.find(edges[i].u);\n        int rv = accepted.find(edges[i].v);\n\n        if (ru != rv) {\n            // Safety check:\n            // If the current edge is a bridge among accepted-components\n            // using only edges i..M-1, then it must be taken.\n            {\n                unordered_map<int, int> mp;\n                mp.reserve(N * 2);\n                vector<int> roots;\n                roots.reserve(N);\n                for (int v = 0; v < N; v++) {\n                    int r = accepted.find(v);\n                    if (!mp.count(r)) {\n                        int id = (int)mp.size();\n                        mp[r] = id;\n                        roots.push_back(r);\n                    }\n                }\n\n                int C = (int)mp.size();\n                vector<vector<pair<int,int>>> g(C);\n                g.reserve(C);\n\n                for (int j = i; j < M; j++) {\n                    int a = mp[accepted.find(edges[j].u)];\n                    int b = mp[accepted.find(edges[j].v)];\n                    if (a == b) continue;\n                    g[a].push_back({b, j});\n                    g[b].push_back({a, j});\n                }\n\n                int cu = mp[ru], cv = mp[rv];\n                vector<int> tin(C, -1), low(C, -1);\n                int timer = 0;\n                bool is_bridge = false;\n\n                function<void(int,int)> dfs = [&](int v, int pe) {\n                    tin[v] = low[v] = timer++;\n                    for (auto [to, eid] : g[v]) {\n                        if (eid == pe) continue;\n                        if (tin[to] != -1) {\n                            low[v] = min(low[v], tin[to]);\n                        } else {\n                            dfs(to, eid);\n                            low[v] = min(low[v], low[to]);\n                            if (low[to] > tin[v] && eid == i) {\n                                is_bridge = true;\n                            }\n                        }\n                    }\n                };\n\n                for (int v = 0; v < C; v++) {\n                    if (tin[v] == -1) dfs(v, -1);\n                }\n\n                if (is_bridge) take = true;\n            }\n\n            // Predicted MST membership test.\n            if (!take) {\n                vector<KEdge> order;\n                order.reserve(M);\n\n                for (int j = 0; j < M; j++) {\n                    int w;\n                    if (j <= i) {\n                        w = actual[j];\n                    } else {\n                        w = max(1, (int)round(coef * edges[j].d));\n                    }\n                    order.push_back({w, j});\n                }\n\n                sort(order.begin(), order.end());\n\n                DSU tmp(N);\n                bool in_predicted_mst = false;\n\n                for (auto [w, id] : order) {\n                    if (tmp.unite(edges[id].u, edges[id].v)) {\n                        if (id == i) {\n                            in_predicted_mst = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (in_predicted_mst) {\n                    // Avoid very bad edges unless needed.\n                    double ratio = (double)l / max(1, edges[i].d);\n\n                    int comps = 0;\n                    for (int v = 0; v < N; v++) {\n                        if (accepted.find(v) == v) comps++;\n                    }\n\n                    double progress = (double)i / M;\n                    double limit = 2.18 - 0.28 * progress;\n                    if (comps > 80) limit += 0.10;\n                    if (comps < 30) limit -= 0.10;\n\n                    if (ratio <= limit || i > M - 420) {\n                        take = true;\n                    }\n                }\n            }\n\n            // Endgame: be less selective.\n            if (!take) {\n                int comps = 0;\n                for (int v = 0; v < N; v++) {\n                    if (accepted.find(v) == v) comps++;\n                }\n\n                int remaining = M - i;\n                if (remaining <= comps * 2) {\n                    take = true;\n                }\n            }\n        }\n\n        if (take) {\n            accepted.unite(edges[i].u, edges[i].v);\n            used[i] = 1;\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n        cout.flush();\n\n        // Slight adaptation from observed average ratio.\n        if (i > 0 && i % 100 == 0) {\n            double sum = 0;\n            int cnt = 0;\n            for (int j = 0; j <= i; j++) {\n                sum += (double)actual[j] / max(1, edges[j].d);\n                cnt++;\n            }\n            double avg = sum / cnt;\n            coef = 0.75 * coef + 0.25 * avg;\n            coef = min(2.08, max(1.78, coef));\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nconst int H = 30, W = 30;\nconst int TURNS = 300;\nint N, M;\nvector<Pos> pet, human_pos;\nvector<int> pet_type;\nbool wall[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar mvC[4] = {'U', 'D', 'L', 'R'};\nchar buildC[4] = {'u', 'd', 'l', 'r'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\nint dirIndex(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    if (c == 'R') return 3;\n    return -1;\n}\n\nbool hasPet(int x, int y) {\n    for (auto &p : pet) if (p.x == x && p.y == y) return true;\n    return false;\n}\n\nbool hasHuman(int x, int y) {\n    for (auto &h : human_pos) if (h.x == x && h.y == y) return true;\n    return false;\n}\n\nbool nearPetOrPet(int x, int y) {\n    if (hasPet(x, y)) return true;\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && hasPet(nx, ny)) return true;\n    }\n    return false;\n}\n\nbool canBuildCell(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (wall[x][y]) return true; // allowed, but useless\n    if (hasPet(x, y) || hasHuman(x, y)) return false;\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && hasPet(nx, ny)) return false;\n    }\n    return true;\n}\n\nbool canMoveCell(int x, int y) {\n    return inside(x, y) && !wall[x][y];\n}\n\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nchar stepToward(Pos cur, Pos goal) {\n    int bestd = 1e9;\n    char best = '.';\n    for (int d = 0; d < 4; d++) {\n        int nx = cur.x + dx[d], ny = cur.y + dy[d];\n        if (!canMoveCell(nx, ny)) continue;\n        int md = abs(nx - goal.x) + abs(ny - goal.y);\n        if (md < bestd) {\n            bestd = md;\n            best = mvC[d];\n        }\n    }\n    return best;\n}\n\nvoid applyHumanActions(const string &ans) {\n    vector<Pos> newh = human_pos;\n    vector<pair<int,int>> builds;\n    for (int i = 0; i < M; i++) {\n        char c = ans[i];\n        if (c >= 'a' && c <= 'z') {\n            int d = -1;\n            if (c == 'u') d = 0;\n            if (c == 'd') d = 1;\n            if (c == 'l') d = 2;\n            if (c == 'r') d = 3;\n            if (d >= 0) {\n                int nx = human_pos[i].x + dx[d], ny = human_pos[i].y + dy[d];\n                if (inside(nx, ny) && canBuildCell(nx, ny)) builds.push_back({nx, ny});\n            }\n        }\n    }\n    for (auto &b : builds) wall[b.first][b.second] = true;\n    for (int i = 0; i < M; i++) {\n        char c = ans[i];\n        int d = dirIndex(c);\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d], ny = human_pos[i].y + dy[d];\n            if (canMoveCell(nx, ny)) newh[i] = {nx, ny};\n        }\n    }\n    human_pos = newh;\n}\n\nvoid applyPetMoves(const vector<string>& moves) {\n    for (int i = 0; i < N; i++) {\n        for (char c : moves[i]) {\n            int d = dirIndex(c);\n            if (d >= 0) {\n                int nx = pet[i].x + dx[d], ny = pet[i].y + dy[d];\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pet[i] = {nx, ny};\n                }\n            }\n        }\n    }\n}\n\nint nearestPetDist(Pos p) {\n    int ret = 1000;\n    for (auto &q : pet) ret = min(ret, manhattan(p, q));\n    return ret;\n}\n\n// Very robust baseline strategy:\n// - Move all humans to the central vertical \"construction line\" y=15.\n// - Build as much of a vertical wall at y=15 as possible from adjacent cells y=14 or y=16.\n// - Keep humans spread over different rows.\n// This frequently splits the board into large components; if most pets are on one side,\n// humans on the other side get good score.  The strategy is intentionally conservative\n// to avoid illegal outputs in the interactive judge.\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pet.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; i++) cin >> pet[i].x >> pet[i].y >> pet_type[i];\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; i++) cin >> human_pos[i].x >> human_pos[i].y;\n\n    memset(wall, 0, sizeof(wall));\n\n    vector<int> targetRow(M);\n    for (int i = 0; i < M; i++) {\n        // spread roughly evenly, avoiding exact borders a little\n        targetRow[i] = 2 + (26 * i) / max(1, M - 1);\n        if (M == 1) targetRow[i] = 15;\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        string ans(M, '.');\n\n        // Phase 1: go to construction positions.\n        // Prefer y=14; if starting on right side, y=16 can be used too.\n        for (int i = 0; i < M; i++) {\n            Pos cur = human_pos[i];\n            Pos goal;\n            goal.x = targetRow[i];\n            goal.y = (cur.y <= 15 ? 14 : 16);\n\n            // Once near line, align row first.\n            if (cur.y == 14 || cur.y == 16) goal.y = cur.y;\n\n            // If not at target row/side, move.\n            if (cur.x != goal.x || cur.y != goal.y) {\n                char c = stepToward(cur, goal);\n                if (c != '.') ans[i] = c;\n            }\n        }\n\n        // Phase 2: if positioned beside column 15, build it.\n        // Humans construct adjacent wall cells when safe.\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n            Pos cur = human_pos[i];\n\n            if (cur.y == 14) {\n                int bx = cur.x, by = 15;\n                if (!wall[bx][by] && canBuildCell(bx, by)) ans[i] = 'r';\n            } else if (cur.y == 16) {\n                int bx = cur.x, by = 15;\n                if (!wall[bx][by] && canBuildCell(bx, by)) ans[i] = 'l';\n            }\n        }\n\n        // Phase 3: patrol along the line to fill missing wall cells.\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n            Pos cur = human_pos[i];\n            if (cur.y != 14 && cur.y != 16) continue;\n\n            // Find nearest unbuilt cell in column 15 that seems safe.\n            int bestx = -1, best = 1000;\n            for (int x = 1; x <= 30; x++) {\n                if (wall[x][15]) continue;\n                if (!canBuildCell(x, 15)) continue;\n                int dist = abs(cur.x - x);\n                if (dist < best) {\n                    best = dist;\n                    bestx = x;\n                }\n            }\n            if (bestx != -1) {\n                if (cur.x < bestx && canMoveCell(cur.x + 1, cur.y)) ans[i] = 'D';\n                else if (cur.x > bestx && canMoveCell(cur.x - 1, cur.y)) ans[i] = 'U';\n                else {\n                    if (cur.y == 14 && canBuildCell(cur.x, 15)) ans[i] = 'r';\n                    if (cur.y == 16 && canBuildCell(cur.x, 15)) ans[i] = 'l';\n                }\n            }\n        }\n\n        // Collision with newly built cells is already avoided by self-simulation;\n        // the official judge also validates based on current state.\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n\n        vector<string> pm(N);\n        for (int i = 0; i < N; i++) cin >> pm[i];\n        applyPetMoves(pm);\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int V = 400;\nstatic constexpr int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble pforget;\nstring hwall[N];\nstring vwall[N - 1];\n\nint id(int i, int j) { return i * N + j; }\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\nint nxt[V][4];\nint distT[V];\n\nbool canMove(int i, int j, int d) {\n    if (d == 0) {\n        if (i == 0) return false;\n        return vwall[i - 1][j] == '0';\n    }\n    if (d == 1) {\n        if (i == N - 1) return false;\n        return vwall[i][j] == '0';\n    }\n    if (d == 2) {\n        if (j == 0) return false;\n        return hwall[i][j - 1] == '0';\n    }\n    if (d == 3) {\n        if (j == N - 1) return false;\n        return hwall[i][j] == '0';\n    }\n    return false;\n}\n\nvoid buildGraph() {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int v = id(i, j);\n            for (int d = 0; d < 4; d++) {\n                if (canMove(i, j, d)) nxt[v][d] = id(i + di[d], j + dj[d]);\n                else nxt[v][d] = v;\n            }\n        }\n    }\n}\n\nvoid bfsTarget() {\n    fill(distT, distT + V, 1e9);\n    int t = id(ti_, tj_);\n    queue<int> q;\n    distT[t] = 0;\n    q.push(t);\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (distT[u] > distT[v] + 1) {\n                distT[u] = distT[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n}\n\nstring shortestPath(int s, int t) {\n    vector<int> pre(V, -1), pred(V, -1);\n    queue<int> q;\n    pre[s] = s;\n    q.push(s);\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == t) break;\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (pre[u] == -1) {\n                pre[u] = v;\n                pred[u] = d;\n                q.push(u);\n            }\n        }\n    }\n    if (pre[t] == -1) return \"\";\n    string res;\n    int cur = t;\n    while (cur != s) {\n        int d = pred[cur];\n        res.push_back(dc[d]);\n        cur = pre[cur];\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\ndouble evaluate(const string& route) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n    vector<double> prob(V, 0.0), np(V, 0.0);\n    prob[s] = 1.0;\n\n    double expected = 0.0;\n    for (int step = 0; step < (int)route.size(); step++) {\n        int d = 0;\n        for (int k = 0; k < 4; k++) if (dc[k] == route[step]) d = k;\n\n        fill(np.begin(), np.end(), 0.0);\n\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n\n            np[v] += pr * pforget;\n            int u = nxt[v][d];\n            np[u] += pr * (1.0 - pforget);\n        }\n\n        double reach = np[t];\n        if (reach > 0.0) {\n            expected += reach * (401.0 - (step + 1));\n            np[t] = 0.0;\n        }\n\n        prob.swap(np);\n    }\n\n    return expected;\n}\n\nstring repeatChars(const string& base, int r) {\n    string res;\n    for (char c : base) {\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) res.push_back(c);\n    }\n    return res;\n}\n\nstring repeatPath(const string& base, int r) {\n    string res;\n    while ((int)res.size() + (int)base.size() <= MAXL) {\n        for (int k = 0; k < r; k++) {\n            for (char c : base) {\n                if ((int)res.size() >= MAXL) return res;\n                res.push_back(c);\n            }\n        }\n    }\n    while ((int)res.size() < MAXL) {\n        res.push_back(base[res.size() % base.size()]);\n    }\n    return res;\n}\n\nstring greedyRoute(double temperature, double penaltyStay, int seed, int lenLimit = MAXL) {\n    mt19937 rng(seed);\n\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<double> prob(V, 0.0), np(V);\n    prob[s] = 1.0;\n\n    string route;\n\n    for (int step = 0; step < lenLimit; step++) {\n        double bestScore = 1e100;\n        vector<int> bestDirs;\n\n        for (int d = 0; d < 4; d++) {\n            fill(np.begin(), np.end(), 0.0);\n            for (int v = 0; v < V; v++) {\n                double pr = prob[v];\n                if (pr == 0.0) continue;\n                np[v] += pr * pforget;\n                np[nxt[v][d]] += pr * (1.0 - pforget);\n            }\n\n            double score = 0.0;\n            double alive = 0.0;\n            for (int v = 0; v < V; v++) {\n                if (v == t) continue;\n                double pr = np[v];\n                if (pr == 0.0) continue;\n                alive += pr;\n                score += pr * distT[v];\n                if (nxt[v][d] == v) score += penaltyStay * pr;\n            }\n\n            // Prefer earlier arrival a little.\n            score -= np[t] * (30.0 + 0.1 * (MAXL - step));\n\n            // Random perturbation.\n            if (temperature > 0) {\n                uniform_real_distribution<double> ud(-temperature, temperature);\n                score += ud(rng);\n            }\n\n            if (score + 1e-12 < bestScore) {\n                bestScore = score;\n                bestDirs.clear();\n                bestDirs.push_back(d);\n            } else if (abs(score - bestScore) < 1e-12) {\n                bestDirs.push_back(d);\n            }\n        }\n\n        int d = bestDirs[rng() % bestDirs.size()];\n        route.push_back(dc[d]);\n\n        fill(np.begin(), np.end(), 0.0);\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * (1.0 - pforget);\n        }\n        np[t] = 0.0;\n        prob.swap(np);\n\n        double alive = accumulate(prob.begin(), prob.end(), 0.0);\n        if (alive < 1e-10) break;\n    }\n\n    return route;\n}\n\nstring deterministicDistRoute(int repeatBias, int lenLimit = MAXL) {\n    int cur = id(si_, sj_);\n    int t = id(ti_, tj_);\n    string route;\n\n    while ((int)route.size() < lenLimit && cur != t) {\n        int bd = -1;\n        int best = 1e9;\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[cur][d];\n            if (u != cur && distT[u] < best) {\n                best = distT[u];\n                bd = d;\n            }\n        }\n        if (bd == -1) break;\n        int rep = repeatBias;\n        for (int k = 0; k < rep && (int)route.size() < lenLimit; k++) {\n            route.push_back(dc[bd]);\n        }\n        cur = nxt[cur][bd];\n    }\n\n    return route;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si_ >> sj_ >> ti_ >> tj_ >> pforget;\n    for (int i = 0; i < N; i++) cin >> hwall[i];\n    for (int i = 0; i < N - 1; i++) cin >> vwall[i];\n\n    buildGraph();\n    bfsTarget();\n\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<string> candidates;\n\n    string sp = shortestPath(s, t);\n    if (!sp.empty()) {\n        candidates.push_back(sp);\n\n        for (int r = 2; r <= 8; r++) {\n            candidates.push_back(repeatChars(sp, r));\n        }\n\n        for (int r = 1; r <= 4; r++) {\n            candidates.push_back(repeatPath(sp, r));\n        }\n\n        // Prefix shortest path repeated then normal path.\n        for (int cut = 1; cut <= (int)sp.size(); cut += max(1, (int)sp.size() / 8)) {\n            string res;\n            for (int i = 0; i < cut; i++) {\n                int rep = 2 + (i % 3);\n                for (int k = 0; k < rep && (int)res.size() < MAXL; k++) res.push_back(sp[i]);\n            }\n            for (char c : sp) if ((int)res.size() < MAXL) res.push_back(c);\n            candidates.push_back(res);\n        }\n    }\n\n    for (int r = 1; r <= 7; r++) {\n        candidates.push_back(deterministicDistRoute(r));\n    }\n\n    // Greedy candidates.\n    int seedBase = 1234567;\n    vector<double> temps = {0.0, 0.05, 0.1, 0.2, 0.4, 0.8, 1.5, 3.0};\n    vector<double> penalties = {0.0, 0.1, 0.3, 0.7, 1.5, 3.0};\n\n    for (double temp : temps) {\n        for (double pen : penalties) {\n            for (int k = 0; k < 3; k++) {\n                candidates.push_back(greedyRoute(temp, pen, seedBase++));\n            }\n        }\n    }\n\n    // Intermediate waypoint candidates.\n    vector<int> cells(V);\n    iota(cells.begin(), cells.end(), 0);\n    sort(cells.begin(), cells.end(), [&](int a, int b) {\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n        int ascore = abs(ai - 10) + abs(aj - 10) + distT[a];\n        int bscore = abs(bi - 10) + abs(bj - 10) + distT[b];\n        return ascore < bscore;\n    });\n\n    for (int idx = 0; idx < min(V, 60); idx++) {\n        int mid = cells[idx];\n        string a = shortestPath(s, mid);\n        string b = shortestPath(mid, t);\n        if (a.empty() || b.empty()) continue;\n        string path = a + b;\n        if ((int)path.size() > MAXL) path.resize(MAXL);\n        candidates.push_back(path);\n        for (int r = 2; r <= 4; r++) candidates.push_back(repeatChars(path, r));\n    }\n\n    // Add simple monotone-like random shortest descent routes.\n    mt19937 rng(998244353);\n    for (int trial = 0; trial < 200; trial++) {\n        string route;\n        int cur = s;\n        while (cur != t && (int)route.size() < MAXL) {\n            vector<int> ds;\n            int best = distT[cur];\n            for (int d = 0; d < 4; d++) {\n                int u = nxt[cur][d];\n                if (u != cur && distT[u] < best) ds.push_back(d);\n            }\n            if (ds.empty()) break;\n            int d = ds[rng() % ds.size()];\n            int rep = 1 + (rng() % (1 + (int)(pforget * 8)));\n            for (int k = 0; k < rep && (int)route.size() < MAXL; k++) route.push_back(dc[d]);\n            cur = nxt[cur][d];\n        }\n        if (!route.empty()) candidates.push_back(route);\n    }\n\n    string best = sp.empty() ? string(\"D\") : sp;\n    double bestVal = -1.0;\n\n    for (string cand : candidates) {\n        if (cand.empty()) continue;\n        if ((int)cand.size() > MAXL) cand.resize(MAXL);\n        double val = evaluate(cand);\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n    }\n\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n    cout << best << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N * 4;\n\nint to_dir[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\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) {\n        return (int)(next_u64() % n);\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint rotate_state(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (0 <= t && t <= 3) t = (t + 1) & 3;\n        else if (t == 4) t = 5;\n        else if (t == 5) t = 4;\n        else if (t == 6) t = 7;\n        else if (t == 7) t = 6;\n    }\n    return t;\n}\n\nstruct Solver {\n    vector<string> input;\n    array<int, N * N> base{};\n    array<int, N * N> rot{};\n    array<int, N * N> tile{};\n    array<int, N * N> best_rot{};\n\n    XorShift rng;\n\n    int id(int i, int j, int d) const {\n        return ((i * N + j) << 2) | d;\n    }\n\n    tuple<int,int,int> decode(int x) const {\n        int d = x & 3;\n        x >>= 2;\n        int i = x / N;\n        int j = x % N;\n        return {i, j, d};\n    }\n\n    int nxt(int x) const {\n        auto [i, j, d] = decode(x);\n        int t = tile[i * N + j];\n        int d2 = to_dir[t][d];\n        if (d2 == -1) return -1;\n        int ni = i + di[d2];\n        int nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n        int nd = (d2 + 2) & 3;\n        return id(ni, nj, nd);\n    }\n\n    long long evaluate() const {\n        static int state[V];\n        static int seen_iter[V];\n        static int depth[V];\n\n        for (int i = 0; i < V; i++) {\n            state[i] = 0;\n            seen_iter[i] = -1;\n            depth[i] = 0;\n        }\n\n        vector<int> loops;\n\n        for (int s = 0; s < V; s++) {\n            if (state[s]) continue;\n\n            int cur = s;\n            vector<int> path;\n\n            while (true) {\n                if (cur == -1) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n\n                if (state[cur] == 2) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n\n                if (state[cur] == 1) {\n                    if (seen_iter[cur] == s) {\n                        int len = (int)path.size() - depth[cur];\n                        if (len > 0) loops.push_back(len);\n                    }\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n\n                state[cur] = 1;\n                seen_iter[cur] = s;\n                depth[cur] = (int)path.size();\n                path.push_back(cur);\n                cur = nxt(cur);\n            }\n        }\n\n        if ((int)loops.size() <= 1) return 0;\n        sort(loops.rbegin(), loops.rend());\n        return 1LL * loops[0] * loops[1];\n    }\n\n    void rebuild_tile() {\n        for (int i = 0; i < N * N; i++) {\n            tile[i] = rotate_state(base[i], rot[i]);\n        }\n    }\n\n    void random_initial() {\n        for (int i = 0; i < N * N; i++) {\n            int t = base[i];\n            if (t <= 3) rot[i] = rng.next_int(4);\n            else rot[i] = rng.next_int(2);\n        }\n        rebuild_tile();\n    }\n\n    void greedy_init_patterns() {\n        // Try a few deterministic global patterns and keep the best among them.\n        array<int, N * N> save_rot{};\n        long long best = -1;\n\n        for (int pat = 0; pat < 8; pat++) {\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 = base[idx];\n                    int r = 0;\n\n                    if (pat == 0) r = 0;\n                    if (pat == 1) r = (i + j) & 3;\n                    if (pat == 2) r = (i - j + 100) & 3;\n                    if (pat == 3) r = i & 3;\n                    if (pat == 4) r = j & 3;\n                    if (pat == 5) r = ((i / 2) + (j / 2)) & 3;\n                    if (pat == 6) r = rng.next_int(4);\n                    if (pat == 7) r = rng.next_int(4);\n\n                    if (t >= 4) r &= 1;\n                    rot[idx] = r;\n                }\n            }\n            rebuild_tile();\n            long long sc = evaluate();\n            if (sc > best) {\n                best = sc;\n                save_rot = rot;\n            }\n        }\n\n        rot = save_rot;\n        rebuild_tile();\n    }\n\n    void solve() {\n        input.resize(N);\n        for (int i = 0; i < N; i++) cin >> input[i];\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                base[i * N + j] = input[i][j] - '0';\n            }\n        }\n\n        Timer timer;\n\n        greedy_init_patterns();\n\n        long long cur_score = evaluate();\n        long long best_score = cur_score;\n        best_rot = rot;\n\n        const double TL = 1.90;\n        int iter = 0;\n\n        while (timer.elapsed() < TL) {\n            iter++;\n\n            int p = rng.next_int(N * N);\n            int old_r = rot[p];\n            int old_t = tile[p];\n\n            int type = base[p];\n            int maxr = (type <= 3 ? 4 : 2);\n\n            int nr = rng.next_int(maxr);\n            if (nr == old_r) nr = (nr + 1) % maxr;\n\n            rot[p] = nr;\n            tile[p] = rotate_state(base[p], nr);\n\n            long long ns = evaluate();\n            long long diff = ns - cur_score;\n\n            double progress = timer.elapsed() / TL;\n            double temp = 5000.0 * (1.0 - progress) + 10.0 * progress;\n\n            bool accept = false;\n            if (diff >= 0) accept = true;\n            else {\n                double prob = exp((double)diff / temp);\n                if (rng.next_double() < prob) accept = true;\n            }\n\n            if (accept) {\n                cur_score = ns;\n                if (cur_score > best_score) {\n                    best_score = cur_score;\n                    best_rot = rot;\n                }\n            } else {\n                rot[p] = old_r;\n                tile[p] = old_t;\n            }\n\n            // Occasionally restart from a random state if current state is poor.\n            if ((iter & 4095) == 0 && timer.elapsed() < TL * 0.75) {\n                if (rng.next_int(100) < 3) {\n                    random_initial();\n                    cur_score = evaluate();\n                    if (cur_score > best_score) {\n                        best_score = cur_score;\n                        best_rot = rot;\n                    }\n                }\n            }\n        }\n\n        string ans;\n        ans.reserve(N * N);\n        for (int i = 0; i < N * N; i++) {\n            ans.push_back(char('0' + best_rot[i]));\n        }\n        cout << ans << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        sz.assign(n,1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[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(sz[a]<sz[b]) swap(a,b);\n        p[b]=a; sz[a]+=sz[b];\n        return true;\n    }\n};\n\nint N,Tlim;\nvector<int> init_board;\nint total_cells;\n\nint hexval(char c){\n    if('0'<=c && c<='9') return c-'0';\n    return c-'a'+10;\n}\n\nstruct EvalResult {\n    int largest_tree;\n    int edges;\n    int cycle_edges;\n    int comps;\n};\n\nEvalResult evaluate_board(const vector<unsigned char>& b){\n    int M = N*N;\n    DSU dsu(M);\n    vector<int> active(M,0);\n    int active_cnt=0;\n    for(int i=0;i<M;i++){\n        if(b[i]!=0){\n            active[i]=1;\n            active_cnt++;\n        }\n    }\n\n    int edges=0, cyc=0;\n\n    for(int r=0;r<N;r++){\n        for(int c=0;c<N;c++){\n            int id=r*N+c;\n            if(!active[id]) continue;\n            int v=b[id];\n\n            if(c+1<N){\n                int nid=id+1;\n                if(active[nid] && (v&4) && (b[nid]&1)){\n                    edges++;\n                    if(!dsu.unite(id,nid)) cyc++;\n                }\n            }\n            if(r+1<N){\n                int nid=id+N;\n                if(active[nid] && (v&8) && (b[nid]&2)){\n                    edges++;\n                    if(!dsu.unite(id,nid)) cyc++;\n                }\n            }\n        }\n    }\n\n    unordered_map<int,int> vc, ec;\n    vc.reserve(M*2);\n    ec.reserve(M*2);\n\n    for(int i=0;i<M;i++){\n        if(active[i]) vc[dsu.find(i)]++;\n    }\n\n    for(int r=0;r<N;r++){\n        for(int c=0;c<N;c++){\n            int id=r*N+c;\n            if(!active[id]) continue;\n            int v=b[id];\n\n            if(c+1<N){\n                int nid=id+1;\n                if(active[nid] && (v&4) && (b[nid]&1)){\n                    ec[dsu.find(id)]++;\n                }\n            }\n            if(r+1<N){\n                int nid=id+N;\n                if(active[nid] && (v&8) && (b[nid]&2)){\n                    ec[dsu.find(id)]++;\n                }\n            }\n        }\n    }\n\n    int best=1;\n    int comps=0;\n    for(auto &kv: vc){\n        int root=kv.first;\n        int vcnt=kv.second;\n        int e=(ec.count(root)?ec[root]:0);\n        comps++;\n        if(e==vcnt-1){\n            best=max(best,vcnt);\n        }\n    }\n\n    return {best, edges, cyc, comps};\n}\n\nstruct State {\n    vector<unsigned char> b;\n    int emp;\n    string path;\n    char last;\n    int score;\n    int tree;\n};\n\nint heuristic_score(const vector<unsigned char>& b, int depth){\n    auto e = evaluate_board(b);\n    int full = N*N-1;\n\n    int score = 0;\n    score += e.largest_tree * 1000000;\n    score += e.edges * 2500;\n    score -= e.cycle_edges * 10000;\n    score -= e.comps * 300;\n    if(e.largest_tree == full){\n        score += 100000000;\n        score -= depth * 1000;\n    }\n    return score;\n}\n\nchar opposite(char c){\n    if(c=='U') return 'D';\n    if(c=='D') return 'U';\n    if(c=='L') return 'R';\n    if(c=='R') return 'L';\n    return '?';\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    total_cells = N*N;\n    init_board.resize(total_cells);\n\n    int emp=0;\n    for(int i=0;i<N;i++){\n        string s; cin >> s;\n        for(int j=0;j<N;j++){\n            int v=hexval(s[j]);\n            init_board[i*N+j]=v;\n            if(v==0) emp=i*N+j;\n        }\n    }\n\n    Timer timer;\n\n    vector<unsigned char> startb(total_cells);\n    for(int i=0;i<total_cells;i++) startb[i]=init_board[i];\n\n    State start;\n    start.b=startb;\n    start.emp=emp;\n    start.path=\"\";\n    start.last='?';\n    start.score=heuristic_score(start.b,0);\n    start.tree=evaluate_board(start.b).largest_tree;\n\n    State best=start;\n\n    int beamWidth;\n    if(N<=6) beamWidth=900;\n    else if(N==7) beamWidth=650;\n    else if(N==8) beamWidth=430;\n    else if(N==9) beamWidth=280;\n    else beamWidth=190;\n\n    vector<State> beam;\n    beam.push_back(start);\n\n    const int dr[4]={-1,1,0,0};\n    const int dc[4]={0,0,-1,1};\n    const char mv[4]={'U','D','L','R'};\n\n    int maxDepth=Tlim;\n\n    for(int depth=0; depth<maxDepth; depth++){\n        if(timer.elapsed() > 2.85) break;\n\n        vector<State> cand;\n        cand.reserve(beam.size()*3);\n\n        for(const State& st: beam){\n            int er=st.emp/N, ec=st.emp%N;\n\n            for(int k=0;k<4;k++){\n                char m=mv[k];\n                if(st.last!='?' && opposite(st.last)==m) continue;\n\n                int nr=er+dr[k], nc=ec+dc[k];\n                if(nr<0 || nr>=N || nc<0 || nc>=N) continue;\n\n                int np=nr*N+nc;\n\n                State ns;\n                ns.b=st.b;\n                swap(ns.b[st.emp], ns.b[np]);\n                ns.emp=np;\n                ns.path=st.path;\n                ns.path.push_back(m);\n                ns.last=m;\n\n                auto ev = evaluate_board(ns.b);\n                ns.tree=ev.largest_tree;\n\n                int score=0;\n                score += ev.largest_tree * 1000000;\n                score += ev.edges * 2500;\n                score -= ev.cycle_edges * 10000;\n                score -= ev.comps * 300;\n\n                if(ev.largest_tree == N*N-1){\n                    score += 100000000;\n                    score -= (int)ns.path.size()*5000;\n                } else {\n                    score -= (int)ns.path.size()*10;\n                }\n\n                // Mild preference for keeping the blank near the boundary,\n                // because the generated original blank was bottom-right.\n                int rr=ns.emp/N, cc=ns.emp%N;\n                int distBR=abs(rr-(N-1))+abs(cc-(N-1));\n                score -= distBR*80;\n\n                ns.score=score;\n\n                if(ns.tree > best.tree ||\n                   (ns.tree==best.tree && ns.score>best.score)){\n                    best=ns;\n                    if(best.tree==N*N-1){\n                        // Full tree found. Still could improve length, but good enough.\n                    }\n                }\n\n                cand.push_back(move(ns));\n            }\n        }\n\n        if(cand.empty()) break;\n\n        int keep = min<int>(beamWidth, cand.size());\n\n        nth_element(cand.begin(), cand.begin()+keep, cand.end(),\n            [](const State& a, const State& b){\n                return a.score > b.score;\n            });\n        cand.resize(keep);\n\n        sort(cand.begin(), cand.end(),\n            [](const State& a, const State& b){\n                return a.score > b.score;\n            });\n\n        // Remove exact duplicate boards among top states.\n        vector<State> nb;\n        nb.reserve(keep);\n        unordered_set<string> seen;\n        seen.reserve(keep*2);\n\n        for(auto &s: cand){\n            string key;\n            key.resize(total_cells);\n            for(int i=0;i<total_cells;i++) key[i]=char(s.b[i]);\n            key.push_back(char(s.emp));\n            if(seen.insert(key).second){\n                nb.push_back(move(s));\n                if((int)nb.size()>=keep) break;\n            }\n        }\n\n        beam.swap(nb);\n\n        // If full tree is found fairly early, spend a little more time trying\n        // but stop before timeout.\n        if(best.tree==N*N-1 && timer.elapsed()>1.5) break;\n    }\n\n    if((int)best.path.size() > Tlim) best.path.resize(Tlim);\n    cout << best.path << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n\n    vector<int> a(11);\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // ----------------------------------------------------------------------\n    // Heuristic:\n    // Use 100 parallel-ish grid cuts: vertical and horizontal quantile cuts.\n    //\n    // Since strawberries are uniformly random, a rectangular grid tends to\n    // create many small cells.  We choose the number of vertical / horizontal\n    // strips so that the average strawberries per cell is around the weighted\n    // average target piece size.  Then cut at quantiles so each strip contains\n    // a roughly equal number of strawberries.\n    //\n    // This is a simple, robust baseline for AHC012.\n    // ----------------------------------------------------------------------\n\n    int totalAttendees = 0;\n    for (int d = 1; d <= 10; d++) totalAttendees += a[d];\n\n    double avgTarget = (double)N / max(1, totalAttendees); // about 1..10\n    int desiredCells = max(1, (int)round((double)N / avgTarget)); // roughly attendees count\n    desiredCells = min(desiredCells, K * K / 4);\n\n    // Need (vx+1)*(hy+1) cells, vx+hy<=100.\n    // Select vx,hy minimizing difference from desiredCells and balanced aspect.\n    int bestV = 50, bestH = 50;\n    double bestCost = 1e100;\n    for (int vx = 0; vx <= K; vx++) {\n        for (int hy = 0; hy + vx <= K; hy++) {\n            int cells = (vx + 1) * (hy + 1);\n            double cost = abs(cells - desiredCells);\n            cost += 0.05 * abs(vx - hy);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestV = vx;\n                bestH = hy;\n            }\n        }\n    }\n\n    vector<int> xs, ys;\n    xs.reserve(N);\n    ys.reserve(N);\n    for (auto &pt : p) {\n        xs.push_back(pt.x);\n        ys.push_back(pt.y);\n    }\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    vector<array<int,4>> lines;\n\n    auto add_vertical = [&](int x) {\n        // line x = const\n        lines.push_back({x, -1000000000, x, 1000000000});\n    };\n    auto add_horizontal = [&](int y) {\n        // line y = const\n        lines.push_back({-1000000000, y, 1000000000, y});\n    };\n\n    // Quantile cuts between consecutive coordinates.\n    for (int i = 1; i <= bestV; i++) {\n        int idx = (long long)N * i / (bestV + 1);\n        if (idx <= 0 || idx >= N) continue;\n        int x1 = xs[idx - 1], x2 = xs[idx];\n        int cut;\n        if (x1 == x2) cut = x1 + 1;\n        else cut = (x1 + x2) / 2;\n        add_vertical(cut);\n    }\n\n    for (int i = 1; i <= bestH; i++) {\n        int idx = (long long)N * i / (bestH + 1);\n        if (idx <= 0 || idx >= N) continue;\n        int y1 = ys[idx - 1], y2 = ys[idx];\n        int cut;\n        if (y1 == y2) cut = y1 + 1;\n        else cut = (y1 + y2) / 2;\n        add_horizontal(cut);\n    }\n\n    // Fallback / improvement: if duplicate quantile cuts reduced the count,\n    // add several diagonal cuts through the origin with different slopes.\n    // This increases fragmentation without much risk.\n    int diagId = 0;\n    while ((int)lines.size() < K && diagId < 200) {\n        double theta = M_PI * diagId / 200.0;\n        int dx = (int)round(cos(theta) * 1000000000.0);\n        int dy = (int)round(sin(theta) * 1000000000.0);\n        if (dx == 0 && dy == 0) {\n            diagId++;\n            continue;\n        }\n        lines.push_back({-dx, -dy, dx, dy});\n        diagId++;\n    }\n\n    if ((int)lines.size() > K) lines.resize(K);\n\n    cout << lines.size() << '\\n';\n    for (auto &ln : lines) {\n        cout << ln[0] << ' ' << ln[1] << ' ' << ln[2] << ' ' << ln[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    int score;\n    int lenSum;\n};\n\nint N, M;\nvector<vector<int>> dotGrid;\nset<tuple<int,int,int,int>> usedSeg;\nvector<Move> answerMoves;\n\nint weightPoint(int x, int y) {\n    int c = (N - 1) / 2;\n    int dx = x - c;\n    int dy = y - c;\n    return dx * dx + dy * dy + 1;\n}\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ntuple<int,int,int,int> segKey(int x1, int y1, int x2, int y2) {\n    if (x1 > x2 || (x1 == x2 && y1 > y2)) {\n        swap(x1, x2);\n        swap(y1, y2);\n    }\n    return {x1, y1, x2, y2};\n}\n\nint gcdAbs(int a, int b) {\n    return std::gcd(abs(a), abs(b));\n}\n\nbool checkSideNoDotAndNoSeg(int ax, int ay, int bx, int by,\n                            int ex1, int ey1,\n                            int ex2, int ey2,\n                            int ex3, int ey3) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n\n        if (usedSeg.count(segKey(x, y, nx, ny))) return false;\n    }\n\n    for (int i = 1; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n\n        if ((x == ex1 && y == ey1) ||\n            (x == ex2 && y == ey2) ||\n            (x == ex3 && y == ey3)) {\n            continue;\n        }\n\n        if (dotGrid[x][y]) return false;\n    }\n\n    return true;\n}\n\nvoid addSideSegments(int ax, int ay, int bx, int by) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n        usedSeg.insert(segKey(x, y, nx, ny));\n    }\n}\n\nbool legalMove(const Move& mv) {\n    int x1 = mv.x1, y1 = mv.y1;\n    int x2 = mv.x2, y2 = mv.y2;\n    int x3 = mv.x3, y3 = mv.y3;\n    int x4 = mv.x4, y4 = mv.y4;\n\n    if (!inside(x1, y1) || !inside(x2, y2) || !inside(x3, y3) || !inside(x4, y4)) return false;\n    if (dotGrid[x1][y1]) return false;\n    if (!dotGrid[x2][y2] || !dotGrid[x3][y3] || !dotGrid[x4][y4]) return false;\n\n    if (!checkSideNoDotAndNoSeg(x1, y1, x2, y2, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x2, y2, x3, y3, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x3, y3, x4, y4, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x4, y4, x1, y1, x2, y2, x3, y3, x4, y4)) return false;\n\n    return true;\n}\n\nvoid applyMove(const Move& mv) {\n    dotGrid[mv.x1][mv.y1] = 1;\n\n    addSideSegments(mv.x1, mv.y1, mv.x2, mv.y2);\n    addSideSegments(mv.x2, mv.y2, mv.x3, mv.y3);\n    addSideSegments(mv.x3, mv.y3, mv.x4, mv.y4);\n    addSideSegments(mv.x4, mv.y4, mv.x1, mv.y1);\n\n    answerMoves.push_back(mv);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    dotGrid.assign(N, vector<int>(N, 0));\n\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        dotGrid[x][y] = 1;\n    }\n\n    auto startTime = chrono::steady_clock::now();\n\n    vector<pair<int,int>> dirs = {\n        {1, 0}, {0, 1}, {-1, 0}, {0, -1},\n        {1, 1}, {-1, 1}, {-1, -1}, {1, -1}\n    };\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (elapsed > 4.75) break;\n\n        Move best;\n        bool found = false;\n\n        vector<pair<int,int>> dots;\n        dots.reserve(N * N);\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                if (dotGrid[x][y]) dots.push_back({x, y});\n            }\n        }\n\n        for (auto [x3, y3] : dots) {\n            for (auto [dx, dy] : dirs) {\n                int rdx = -dy;\n                int rdy = dx;\n\n                for (int sign : {-1, 1}) {\n                    int bx = rdx * sign;\n                    int by = rdy * sign;\n\n                    for (int l1 = 1; l1 < N; l1++) {\n                        int x2 = x3 + dx * l1;\n                        int y2 = y3 + dy * l1;\n                        if (!inside(x2, y2)) break;\n                        if (!dotGrid[x2][y2]) continue;\n\n                        for (int l2 = 1; l2 < N; l2++) {\n                            int x4 = x3 + bx * l2;\n                            int y4 = y3 + by * l2;\n                            if (!inside(x4, y4)) break;\n                            if (!dotGrid[x4][y4]) continue;\n\n                            int x1 = x2 + bx * l2;\n                            int y1 = y2 + by * l2;\n                            if (!inside(x1, y1)) break;\n                            if (dotGrid[x1][y1]) continue;\n\n                            Move mv;\n                            mv.x1 = x1; mv.y1 = y1;\n                            mv.x2 = x2; mv.y2 = y2;\n                            mv.x3 = x3; mv.y3 = y3;\n                            mv.x4 = x4; mv.y4 = y4;\n                            mv.score = weightPoint(x1, y1);\n                            mv.lenSum = l1 + l2;\n\n                            if (!legalMove(mv)) continue;\n\n                            if (!found ||\n                                mv.score > best.score ||\n                                (mv.score == best.score && mv.lenSum < best.lenSum)) {\n                                best = mv;\n                                found = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!found) break;\n        applyMove(best);\n    }\n\n    cout << answerMoves.size() << '\\n';\n    for (auto &mv : answerMoves) {\n        cout << mv.x1 << ' ' << mv.y1 << ' '\n             << mv.x2 << ' ' << mv.y2 << ' '\n             << mv.x3 << ' ' << mv.y3 << ' '\n             << mv.x4 << ' ' << mv.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\n\nint f[100];\nint board_[N][N];\n\nstruct Pos {\n    int r, c;\n};\n\nconst char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n\nint dr4[4] = {-1, 1, 0, 0};\nint dc4[4] = {0, 0, -1, 1};\n\narray<Pos, 4> corner = {\n    Pos{0, 0},\n    Pos{9, 9},\n    Pos{0, 9},\n    Pos{9, 0}\n};\n\nPos targetPos[4];\n\nvoid tilt_board(const int src[N][N], int dst[N][N], int dir) {\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) dst[r][c] = 0;\n    }\n\n    if (dir == 0) { // F: up\n        for (int c = 0; c < N; c++) {\n            int write = 0;\n            for (int r = 0; r < N; r++) {\n                if (src[r][c]) {\n                    dst[write++][c] = src[r][c];\n                }\n            }\n        }\n    } else if (dir == 1) { // B: down\n        for (int c = 0; c < N; c++) {\n            int write = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                if (src[r][c]) {\n                    dst[write--][c] = src[r][c];\n                }\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < N; r++) {\n            int write = 0;\n            for (int c = 0; c < N; c++) {\n                if (src[r][c]) {\n                    dst[r][write++] = src[r][c];\n                }\n            }\n        }\n    } else { // R\n        for (int r = 0; r < N; r++) {\n            int write = N - 1;\n            for (int c = N - 1; c >= 0; c--) {\n                if (src[r][c]) {\n                    dst[r][write--] = src[r][c];\n                }\n            }\n        }\n    }\n}\n\ndouble evaluate(const int b[N][N], int turn) {\n    bool vis[N][N] = {};\n    double compScore = 0.0;\n    double edgeScore = 0.0;\n    double distScore = 0.0;\n    double compactScore = 0.0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int x = b[r][c];\n            if (!x) continue;\n\n            Pos t = targetPos[x];\n            int man = abs(r - t.r) + abs(c - t.c);\n            distScore += (18 - man);\n\n            for (int k = 1; k <= 2; k++) {\n                // mild pull toward target row/col\n            }\n\n            if (r + 1 < N && b[r + 1][c] == x) edgeScore += 1.0;\n            if (c + 1 < N && b[r][c + 1] == x) edgeScore += 1.0;\n        }\n    }\n\n    for (int sr = 0; sr < N; sr++) {\n        for (int sc = 0; sc < N; sc++) {\n            if (!b[sr][sc] || vis[sr][sc]) continue;\n\n            int color = b[sr][sc];\n            queue<pair<int,int>> q;\n            q.push({sr, sc});\n            vis[sr][sc] = true;\n\n            int sz = 0;\n            int minr = sr, maxr = sr, minc = sc, maxc = sc;\n\n            while (!q.empty()) {\n                auto [r, c] = q.front();\n                q.pop();\n                sz++;\n\n                minr = min(minr, r);\n                maxr = max(maxr, r);\n                minc = min(minc, c);\n                maxc = max(maxc, c);\n\n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr4[d];\n                    int nc = c + dc4[d];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (vis[nr][nc]) continue;\n                    if (b[nr][nc] != color) continue;\n                    vis[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n\n            compScore += sz * sz;\n\n            int boxArea = (maxr - minr + 1) * (maxc - minc + 1);\n            compactScore += 0.2 * sz * sz / max(1, boxArea);\n        }\n    }\n\n    // Dynamic weighting:\n    // Earlier: encourage geometric separation.\n    // Later: prioritize actual connected components.\n    double progress = turn / 100.0;\n\n    double wComp = 8.0 + 20.0 * progress;\n    double wEdge = 12.0;\n    double wDist = 1.5 * (1.0 - progress) + 0.3;\n    double wCompact = 10.0;\n\n    return wComp * compScore + wEdge * edgeScore + wDist * distScore + wCompact * compactScore;\n}\n\nvoid place_candy(int p, int flavor) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (board_[r][c] == 0) {\n                cnt++;\n                if (cnt == p) {\n                    board_[r][c] = flavor;\n                    return;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; i++) cin >> f[i];\n\n    int cnt[4] = {};\n    for (int i = 0; i < 100; i++) cnt[f[i]]++;\n\n    vector<int> flavors = {1, 2, 3};\n    sort(flavors.begin(), flavors.end(), [&](int a, int b) {\n        return cnt[a] > cnt[b];\n    });\n\n    // Assign three flavors to separated target corners.\n    // Largest: upper-left, second: lower-right, third: upper-right.\n    targetPos[flavors[0]] = {0, 0};\n    targetPos[flavors[1]] = {9, 9};\n    targetPos[flavors[2]] = {0, 9};\n\n    memset(board_, 0, sizeof(board_));\n\n    for (int turn = 1; turn <= 100; turn++) {\n        int p;\n        if (!(cin >> p)) break;\n\n        place_candy(p, f[turn - 1]);\n\n        int bestDir = 0;\n        double bestVal = -1e100;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int nb[N][N];\n            tilt_board(board_, nb, dir);\n            double val = evaluate(nb, turn);\n\n            // Tiny deterministic tie-breaker to avoid excessive oscillation.\n            if (dir == 0 || dir == 2) val += 0.001;\n\n            if (val > bestVal) {\n                bestVal = val;\n                bestDir = dir;\n            }\n        }\n\n        int nb[N][N];\n        tilt_board(board_, nb, bestDir);\n        memcpy(board_, nb, sizeof(board_));\n\n        cout << DIR_CH[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint M, N;\ndouble epsv;\n\nstring graph_to_string(const vector<vector<int>>& adj) {\n    string s;\n    s.reserve(N * (N - 1) / 2);\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            s.push_back(adj[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nvector<int> degrees_from_string(const string& s, int n) {\n    vector<int> deg(n, 0);\n    int p = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            if (s[p] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n            p++;\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\n// Greedy realization of approximate degree sequence.\n// If exact realization fails, still returns a graph close to desired.\nvector<vector<int>> realize_degree_sequence(vector<int> target) {\n    int n = (int)target.size();\n    vector<vector<int>> adj(n, vector<int>(n, 0));\n    vector<int> cur(n, 0);\n\n    // Clamp.\n    for (int &x : target) x = max(0, min(n - 1, x));\n\n    // Parity fix.\n    int sum = accumulate(target.begin(), target.end(), 0);\n    if (sum & 1) {\n        int id = max_element(target.begin(), target.end()) - target.begin();\n        if (target[id] > 0) target[id]--;\n        else target[id]++;\n    }\n\n    // Priority greedy: repeatedly connect vertices with largest deficits.\n    for (int iter = 0; iter < n * n; iter++) {\n        vector<int> rem(n);\n        int total = 0;\n        for (int i = 0; i < n; i++) {\n            rem[i] = target[i] - cur[i];\n            if (rem[i] > 0) total += rem[i];\n        }\n        if (total <= 0) break;\n\n        int u = -1;\n        for (int i = 0; i < n; i++) {\n            if (rem[i] > 0 && (u == -1 || rem[i] > rem[u])) u = i;\n        }\n        if (u == -1) break;\n\n        vector<int> cand;\n        for (int v = 0; v < n; v++) {\n            if (v != u && !adj[u][v] && rem[v] > 0) cand.push_back(v);\n        }\n        if (cand.empty()) {\n            // Cannot satisfy u further.\n            target[u] = cur[u];\n            continue;\n        }\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            if (rem[a] != rem[b]) return rem[a] > rem[b];\n            return a < b;\n        });\n\n        int need = min(rem[u], (int)cand.size());\n        for (int t = 0; t < need; t++) {\n            int v = cand[t];\n            adj[u][v] = adj[v][u] = 1;\n            cur[u]++;\n            cur[v]++;\n        }\n    }\n\n    return adj;\n}\n\nint choose_N(int M, double e) {\n    if (e < 1e-9) {\n        int n = 4;\n        while (n * (n - 1) / 2 < M) n++;\n        return max(4, n);\n    }\n\n    int n;\n    if (e <= 0.03) n = 18;\n    else if (e <= 0.06) n = 24;\n    else if (e <= 0.10) n = 32;\n    else if (e <= 0.15) n = 44;\n    else if (e <= 0.20) n = 56;\n    else if (e <= 0.25) n = 68;\n    else if (e <= 0.30) n = 80;\n    else if (e <= 0.35) n = 90;\n    else n = 100;\n\n    if (M > 70) n += 6;\n    if (M > 90) n += 4;\n    return min(100, max(4, n));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> M >> epsv;\n    N = choose_N(M, epsv);\n\n    vector<string> graphs(M);\n    vector<vector<int>> code_deg(M), expected_deg_int(M);\n    vector<vector<double>> expected_deg(M);\n\n    int maxD = N - 1;\n\n    if (epsv < 1e-9) {\n        // Exact no-noise mode: distinguish by edge count.\n        int Emax = N * (N - 1) / 2;\n        for (int k = 0; k < M; k++) {\n            string s(Emax, '0');\n            for (int i = 0; i < k; i++) s[i] = '1';\n            graphs[k] = s;\n            code_deg[k] = degrees_from_string(s, N);\n        }\n    } else {\n        // Degree-profile codes.\n        // Density levels avoid extremes because noise pulls toward 1/2.\n        double lo = 0.10, hi = 0.90;\n        if (epsv >= 0.25) {\n            lo = 0.04;\n            hi = 0.96;\n        }\n        if (epsv >= 0.35) {\n            lo = 0.01;\n            hi = 0.99;\n        }\n\n        for (int k = 0; k < M; k++) {\n            double x = (M == 1 ? 0.5 : (double)k / (M - 1));\n            double center = lo + (hi - lo) * x;\n\n            vector<int> target(N);\n\n            // Small deterministic wave/slope helps distinguish close centers\n            // and reduces accidental automorphism.\n            double amp = max(1.0, 0.10 * maxD);\n            for (int i = 0; i < N; i++) {\n                double y = ((double)i - (N - 1) / 2.0) / max(1.0, (N - 1) / 2.0);\n                double wave = 0.35 * sin((i + 1) * (k + 3) * 0.37);\n                double d = center * maxD + amp * (0.65 * y + wave);\n                int di = (int)llround(d);\n                target[i] = max(0, min(maxD, di));\n            }\n\n            sort(target.begin(), target.end());\n            auto adj = realize_degree_sequence(target);\n            graphs[k] = graph_to_string(adj);\n            code_deg[k] = degrees_from_string(graphs[k], N);\n        }\n    }\n\n    // Precompute expected noisy sorted degrees.\n    expected_deg.assign(M, vector<double>(N));\n    for (int k = 0; k < M; k++) {\n        for (int i = 0; i < N; i++) {\n            double d = code_deg[k][i];\n            expected_deg[k][i] = epsv * (N - 1) + (1.0 - 2.0 * epsv) * d;\n        }\n        sort(expected_deg[k].begin(), expected_deg[k].end());\n    }\n\n    cout << N << '\\n';\n    for (int k = 0; k < M; k++) cout << graphs[k] << '\\n';\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n        vector<int> d = degrees_from_string(H, N);\n\n        if (epsv < 1e-9) {\n            int edges = accumulate(d.begin(), d.end(), 0) / 2;\n            int ans = min(M - 1, max(0, edges));\n            cout << ans << '\\n';\n            cout.flush();\n            continue;\n        }\n\n        int best = 0;\n        double bestScore = 1e100;\n\n        for (int k = 0; k < M; k++) {\n            double score = 0.0;\n\n            // Main metric: sorted degree L2.\n            for (int i = 0; i < N; i++) {\n                double diff = d[i] - expected_deg[k][i];\n                score += diff * diff;\n            }\n\n            // Edge count term, useful when degree profiles are close.\n            double sumObs = accumulate(d.begin(), d.end(), 0);\n            double sumExp = 0.0;\n            for (double v : expected_deg[k]) sumExp += v;\n            double ediff = (sumObs - sumExp) / max(1.0, (double)N);\n            score += 0.35 * ediff * ediff * N;\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = k;\n            }\n        }\n\n        cout << best << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    double mx, my;\n};\n\nstatic uint64_t rng_state = 88172645463325252ull;\nuint64_t xorshift64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\nint rnd_int(int l, int r) {\n    return l + (int)(xorshift64() % (uint64_t)(r - l + 1));\n}\ndouble rnd01() {\n    return (xorshift64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> adj(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 = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n\n    vector<double> X(N), Y(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    for (int i = 0; i < M; i++) {\n        edges[i].mx = (X[edges[i].u] + X[edges[i].v]) * 0.5;\n        edges[i].my = (Y[edges[i].u] + Y[edges[i].v]) * 0.5;\n    }\n\n    // ---------- Approximate edge importance by sampled shortest path trees ----------\n    vector<double> imp(M, 1.0);\n\n    vector<int> landmarks;\n    {\n        // Include random vertices and geometrically extreme vertices.\n        vector<pair<double,int>> vals;\n        for (int i = 0; i < N; i++) vals.push_back({X[i] + Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i] - Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        int samples = min(N, 28);\n        while ((int)landmarks.size() < samples) {\n            landmarks.push_back(rnd_int(0, N - 1));\n        }\n        sort(landmarks.begin(), landmarks.end());\n        landmarks.erase(unique(landmarks.begin(), landmarks.end()), landmarks.end());\n    }\n\n    const long long INF = (1LL << 60);\n    vector<long long> dist(N);\n    vector<int> parEdge(N);\n\n    for (int s : landmarks) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(parEdge.begin(), parEdge.end(), -1);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != dist[u]) continue;\n            for (auto [v, ei] : adj[u]) {\n                long long nd = du + edges[ei].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parEdge[v] = ei;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        for (int v = 0; v < N; v++) {\n            if (parEdge[v] >= 0) imp[parEdge[v]] += 1.0;\n        }\n    }\n\n    double maxImp = *max_element(imp.begin(), imp.end());\n    for (int i = 0; i < M; i++) {\n        imp[i] = sqrt(imp[i] / maxImp);\n        // Longer edges are also often costly to remove.\n        imp[i] += 0.15 * sqrt((double)edges[i].w / 1000000.0);\n    }\n\n    // ---------- Surrogate objective state ----------\n    vector<int> ans(M, -1), load(D, 0);\n    vector<double> dayImp(D, 0.0);\n    vector<vector<int>> dayEdges(D);\n    vector<vector<int>> dayVertCnt(D, vector<int>(N, 0));\n\n    auto pairCost = [&](int a, int b) -> double {\n        double dx = edges[a].mx - edges[b].mx;\n        double dy = edges[a].my - edges[b].my;\n        double d2 = dx * dx + dy * dy;\n        // Strong penalty if close. Small residual penalty for global spread.\n        double c = 18000.0 / (d2 + 900.0);\n        if (edges[a].u == edges[b].u || edges[a].u == edges[b].v ||\n            edges[a].v == edges[b].u || edges[a].v == edges[b].v) c += 2.0;\n        return c * (0.7 + 0.8 * (imp[a] + imp[b]));\n    };\n\n    auto addCostToDay = [&](int e, int d) -> double {\n        double c = 0.0;\n        for (int f : dayEdges[d]) c += pairCost(e, f);\n        c += 2.0 * imp[e] * dayImp[d];\n\n        int u = edges[e].u, v = edges[e].v;\n        c += 6.0 * dayVertCnt[d][u];\n        c += 6.0 * dayVertCnt[d][v];\n\n        double target = (double)M / D;\n        c += 0.2 * max(0.0, load[d] + 1 - target);\n        return c;\n    };\n\n    auto assignEdge = [&](int e, int d) {\n        ans[e] = d;\n        load[d]++;\n        dayImp[d] += imp[e];\n        dayEdges[d].push_back(e);\n        dayVertCnt[d][edges[e].u]++;\n        dayVertCnt[d][edges[e].v]++;\n    };\n\n    // ---------- Initial construction ----------\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return imp[a] > imp[b];\n    });\n\n    for (int e : ord) {\n        int bestD = -1;\n        double best = 1e100;\n        for (int d = 0; d < D; d++) {\n            if (load[d] >= K) continue;\n            double c = addCostToDay(e, d);\n            if (c < best) {\n                best = c;\n                bestD = d;\n            }\n        }\n        if (bestD < 0) {\n            for (int d = 0; d < D; d++) if (load[d] < K) { bestD = d; break; }\n        }\n        assignEdge(e, bestD);\n    }\n\n    auto removeFromDayVec = [&](int e, int d) {\n        auto &vec = dayEdges[d];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i] == e) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n\n    auto removeEdge = [&](int e, int d) {\n        load[d]--;\n        dayImp[d] -= imp[e];\n        dayVertCnt[d][edges[e].u]--;\n        dayVertCnt[d][edges[e].v]--;\n        removeFromDayVec(e, d);\n        ans[e] = -1;\n    };\n\n    auto edgeContribution = [&](int e, int d) -> double {\n        double c = 0.0;\n        for (int f : dayEdges[d]) if (f != e) c += pairCost(e, f);\n        c += 2.0 * imp[e] * (dayImp[d] - imp[e]);\n        int u = edges[e].u, v = edges[e].v;\n        c += 6.0 * (dayVertCnt[d][u] - 1);\n        c += 6.0 * (dayVertCnt[d][v] - 1);\n        return c;\n    };\n\n    // ---------- Local search ----------\n    double timeLimit = 5.75;\n    int iter = 0;\n    while (timer.elapsed() < timeLimit) {\n        iter++;\n        if ((xorshift64() & 3) != 0) {\n            // Move one edge.\n            int e = rnd_int(0, M - 1);\n            int a = ans[e];\n            int b = rnd_int(0, D - 1);\n            if (a == b || load[b] >= K) continue;\n\n            double oldc = edgeContribution(e, a);\n\n            removeEdge(e, a);\n            double newc = addCostToDay(e, b);\n\n            double t = max(0.001, 0.08 * (1.0 - timer.elapsed() / timeLimit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) {\n                assignEdge(e, b);\n            } else {\n                assignEdge(e, a);\n            }\n        } else {\n            // Swap two edges from different days.\n            int e1 = rnd_int(0, M - 1);\n            int e2 = rnd_int(0, M - 1);\n            if (e1 == e2) continue;\n            int d1 = ans[e1], d2 = ans[e2];\n            if (d1 == d2) continue;\n\n            double oldc = edgeContribution(e1, d1) + edgeContribution(e2, d2);\n\n            removeEdge(e1, d1);\n            removeEdge(e2, d2);\n\n            double newc = addCostToDay(e1, d2) + addCostToDay(e2, d1);\n\n            double t = max(0.001, 0.08 * (1.0 - timer.elapsed() / timeLimit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) {\n                assignEdge(e1, d2);\n                assignEdge(e2, d1);\n            } else {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << ans[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y, z;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for (int i = 0; i < 2; i++) {\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    int N3 = D * D * D;\n\n    auto id = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    vector<vector<int>> feasible(2, vector<int>(N3, 0));\n    vector<vector<int>> ans(2, vector<int>(N3, 0));\n\n    for (int t = 0; t < 2; t++) {\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 (f[t][z][x] == '1' && r[t][z][y] == '1') {\n                        feasible[t][id(x, y, z)] = 1;\n                    }\n                }\n            }\n        }\n    }\n\n    int block_id = 0;\n\n    const int dx[3] = {1, 0, 0};\n    const int dy[3] = {0, 1, 0};\n    const int dz[3] = {0, 0, 1};\n\n    auto can_segment = [&](int t, int x, int y, int z, int dir, int len) {\n        for (int k = 0; k < len; k++) {\n            int nx = x + dx[dir] * k;\n            int ny = y + dy[dir] * k;\n            int nz = z + dz[dir] * k;\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) return false;\n            int p = id(nx, ny, nz);\n            if (!feasible[t][p] || ans[t][p] != 0) return false;\n        }\n        return true;\n    };\n\n    auto place_segment = [&](int t, int x, int y, int z, int dir, int len, int bid) {\n        for (int k = 0; k < len; k++) {\n            int nx = x + dx[dir] * k;\n            int ny = y + dy[dir] * k;\n            int nz = z + dz[dir] * k;\n            ans[t][id(nx, ny, nz)] = bid;\n        }\n    };\n\n    struct Seg {\n        int x, y, z, dir;\n    };\n\n    mt19937 rng(1234567);\n\n    /*\n      Greedily pair long straight segments.\n\n      Max length is D. For each length, collect all currently available\n      segments in both objects, shuffle them, and pair greedily.\n    */\n    for (int len = D; len >= 2; len--) {\n        bool updated = true;\n\n        while (updated) {\n            updated = false;\n\n            vector<Seg> segs[2];\n\n            for (int t = 0; t < 2; t++) {\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                            for (int dir = 0; dir < 3; dir++) {\n                                if (can_segment(t, x, y, z, dir, len)) {\n                                    segs[t].push_back({x, y, z, dir});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (segs[0].empty() || segs[1].empty()) continue;\n\n            shuffle(segs[0].begin(), segs[0].end(), rng);\n            shuffle(segs[1].begin(), segs[1].end(), rng);\n\n            size_t p0 = 0, p1 = 0;\n\n            while (p0 < segs[0].size() && p1 < segs[1].size()) {\n                while (p0 < segs[0].size() &&\n                       !can_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z, segs[0][p0].dir, len)) {\n                    p0++;\n                }\n                while (p1 < segs[1].size() &&\n                       !can_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z, segs[1][p1].dir, len)) {\n                    p1++;\n                }\n\n                if (p0 >= segs[0].size() || p1 >= segs[1].size()) break;\n\n                block_id++;\n                place_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z, segs[0][p0].dir, len, block_id);\n                place_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z, segs[1][p1].dir, len, block_id);\n\n                updated = true;\n                p0++;\n                p1++;\n            }\n        }\n    }\n\n    /*\n      Pair remaining single cells where possible.\n      A unit cube has the same shape in both objects.\n    */\n    vector<int> rem[2];\n    for (int t = 0; t < 2; t++) {\n        for (int p = 0; p < N3; p++) {\n            if (feasible[t][p] && ans[t][p] == 0) {\n                rem[t].push_back(p);\n            }\n        }\n    }\n\n    int common_units = min(rem[0].size(), rem[1].size());\n    for (int i = 0; i < common_units; i++) {\n        block_id++;\n        ans[0][rem[0][i]] = block_id;\n        ans[1][rem[1][i]] = block_id;\n    }\n\n    for (int i = common_units; i < (int)rem[0].size(); i++) {\n        block_id++;\n        ans[0][rem[0][i]] = block_id;\n    }\n\n    for (int i = common_units; i < (int)rem[1].size(); i++) {\n        block_id++;\n        ans[1][rem[1][i]] = block_id;\n    }\n\n    cout << block_id << '\\n';\n\n    for (int t = 0; t < 2; t++) {\n        for (int p = 0; p < N3; p++) {\n            if (p) cout << ' ';\n            cout << ans[t][p];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        sz.assign(n,1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[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(sz[a]<sz[b]) swap(a,b);\n        p[b]=a; sz[a]+=sz[b];\n        return true;\n    }\n};\n\nstatic inline long long sqdist(long long x1,long long y1,long long x2,long long y2){\n    long long dx=x1-x2, dy=y1-y2;\n    return dx*dx+dy*dy;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K;\n    cin >> N >> M >> K;\n\n    vector<int> x(N), y(N);\n    for(int i=0;i<N;i++) cin >> x[i] >> y[i];\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> g(N);\n    for(int i=0;i<M;i++){\n        cin >> edges[i].u >> edges[i].v >> edges[i].w;\n        --edges[i].u; --edges[i].v;\n        g[edges[i].u].push_back({edges[i].v, i});\n        g[edges[i].v].push_back({edges[i].u, i});\n    }\n\n    vector<int> a(K), b(K);\n    for(int i=0;i<K;i++) cin >> a[i] >> b[i];\n\n    // Distance squared from station to resident.\n    vector<vector<int>> d2(N, vector<int>(K));\n    for(int i=0;i<N;i++){\n        for(int k=0;k<K;k++){\n            long long d = sqdist(x[i], y[i], a[k], b[k]);\n            d2[i][k] = (int)d;\n        }\n    }\n\n    // For each resident, sorted nearby stations.\n    vector<vector<pair<int,int>>> cand(K);\n    for(int k=0;k<K;k++){\n        cand[k].reserve(N);\n        for(int i=0;i<N;i++){\n            if(d2[i][k] <= 5000LL * 5000LL) cand[k].push_back({d2[i][k], i});\n        }\n        if(cand[k].empty()){\n            for(int i=0;i<N;i++) cand[k].push_back({d2[i][k], i});\n        }\n        sort(cand[k].begin(), cand[k].end());\n    }\n\n    // All-pairs shortest paths from each vertex.\n    const long long INF = (1LL<<60);\n    vector<vector<long long>> dist(N, vector<long long>(N, INF));\n    vector<vector<int>> prevEdge(N, vector<int>(N, -1));\n    vector<vector<int>> prevNode(N, vector<int>(N, -1));\n\n    for(int s=0;s<N;s++){\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        dist[s][s]=0;\n        pq.push({0,s});\n        while(!pq.empty()){\n            auto [cd,v]=pq.top(); pq.pop();\n            if(cd != dist[s][v]) continue;\n            for(auto [to, ei]: g[v]){\n                long long nd = cd + edges[ei].w;\n                if(nd < dist[s][to]){\n                    dist[s][to]=nd;\n                    prevEdge[s][to]=ei;\n                    prevNode[s][to]=v;\n                    pq.push({nd,to});\n                }\n            }\n        }\n    }\n\n    auto build_edges = [&](const vector<int>& P)->vector<int>{\n        vector<int> B(M,0);\n        vector<int> terminals;\n        terminals.push_back(0);\n        for(int i=0;i<N;i++) if(P[i]>0) terminals.push_back(i);\n\n        // Use shortest path from root to each active station.\n        for(int t: terminals){\n            int cur=t;\n            while(cur!=0){\n                int ei = prevEdge[0][cur];\n                if(ei<0) break;\n                B[ei]=1;\n                cur = prevNode[0][cur];\n            }\n        }\n\n        // Prune zero-radius leaves not needed to connect positive-radius stations.\n        bool changed=true;\n        while(changed){\n            changed=false;\n            vector<int> deg(N,0);\n            vector<vector<pair<int,int>>> tg(N);\n            for(int i=0;i<M;i++) if(B[i]){\n                int u=edges[i].u, v=edges[i].v;\n                deg[u]++; deg[v]++;\n                tg[u].push_back({v,i});\n                tg[v].push_back({u,i});\n            }\n            queue<int> q;\n            for(int i=1;i<N;i++){\n                if(deg[i]==1 && P[i]==0) q.push(i);\n            }\n            while(!q.empty()){\n                int v=q.front(); q.pop();\n                if(deg[v]!=1 || P[v]!=0) continue;\n                int rem=-1, to=-1;\n                for(auto [nv,ei]: tg[v]){\n                    if(B[ei]){\n                        rem=ei; to=nv; break;\n                    }\n                }\n                if(rem==-1) continue;\n                B[rem]=0;\n                deg[v]--;\n                deg[to]--;\n                changed=true;\n                if(to!=0 && deg[to]==1 && P[to]==0) q.push(to);\n            }\n        }\n        return B;\n    };\n\n    auto calc_cost = [&](const vector<int>& P, const vector<int>& B)->long long{\n        long long s=0;\n        for(int p:P) s += 1LL*p*p;\n        for(int i=0;i<M;i++) if(B[i]) s += edges[i].w;\n        return s;\n    };\n\n    auto ceil_sqrt = [&](int val)->int{\n        int r = (int)ceil(sqrt((double)val));\n        while(1LL*r*r < val) r++;\n        while(r>0 && 1LL*(r-1)*(r-1) >= val) r--;\n        return r;\n    };\n\n    vector<int> bestP(N,0), bestB(M,0);\n    long long bestCost = INF;\n\n    auto solve_with_limit = [&](int candidateLimit){\n        vector<int> assign(K,-1);\n        vector<vector<int>> assigned(N);\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int p, int q){\n            return cand[p][0].first < cand[q][0].first;\n        });\n\n        vector<int> maxd2(N,0);\n        vector<int> active(N,0);\n\n        for(int k: order){\n            long long bestInc = INF;\n            int bestI = cand[k][0].second;\n            int lim = min(candidateLimit, (int)cand[k].size());\n            for(int z=0; z<lim; z++){\n                int i = cand[k][z].second;\n                int nd = d2[i][k];\n                int oldr = ceil_sqrt(maxd2[i]);\n                int newr = ceil_sqrt(max(maxd2[i], nd));\n                long long inc = 1LL*newr*newr - 1LL*oldr*oldr;\n                // crude connection penalty for activating a new station\n                if(!active[i]) inc += dist[0][i] / 4;\n                if(inc < bestInc){\n                    bestInc = inc;\n                    bestI = i;\n                }\n            }\n            assign[k]=bestI;\n            assigned[bestI].push_back(k);\n            maxd2[bestI]=max(maxd2[bestI], d2[bestI][k]);\n            active[bestI]=1;\n        }\n\n        auto recomputeP = [&](){\n            vector<int> P(N,0);\n            for(int i=0;i<N;i++){\n                int md=0;\n                for(int k: assigned[i]) md=max(md, d2[i][k]);\n                P[i]=ceil_sqrt(md);\n                if(P[i]>5000) P[i]=5000;\n            }\n            return P;\n        };\n\n        // Local reassignment iterations.\n        for(int it=0; it<8; it++){\n            vector<int> P = recomputeP();\n            bool any=false;\n            vector<int> curMax(N,0), secondMax(N,0), cntMax(N,0);\n            for(int i=0;i<N;i++){\n                for(int k: assigned[i]){\n                    int dd=d2[i][k];\n                    if(dd>curMax[i]){\n                        secondMax[i]=curMax[i];\n                        curMax[i]=dd;\n                        cntMax[i]=1;\n                    }else if(dd==curMax[i]){\n                        cntMax[i]++;\n                    }else if(dd>secondMax[i]){\n                        secondMax[i]=dd;\n                    }\n                }\n            }\n\n            for(int k=0;k<K;k++){\n                int old=assign[k];\n                long long bestDelta=0;\n                int bestI=old;\n\n                int oldAfterD2 = curMax[old];\n                if(d2[old][k]==curMax[old] && cntMax[old]==1) oldAfterD2=secondMax[old];\n                int oldR = ceil_sqrt(curMax[old]);\n                int oldAfterR = ceil_sqrt(oldAfterD2);\n                long long gainOld = 1LL*oldAfterR*oldAfterR - 1LL*oldR*oldR;\n\n                int lim = min(candidateLimit, (int)cand[k].size());\n                for(int z=0; z<lim; z++){\n                    int ni=cand[k][z].second;\n                    if(ni==old) continue;\n                    int nr0 = ceil_sqrt(curMax[ni]);\n                    int nr1 = ceil_sqrt(max(curMax[ni], d2[ni][k]));\n                    long long delta = gainOld + (1LL*nr1*nr1 - 1LL*nr0*nr0);\n                    if(assigned[ni].empty()) delta += dist[0][ni] / 5;\n                    if(assigned[old].size()==1) delta -= dist[0][old] / 5;\n                    if(delta < bestDelta){\n                        bestDelta=delta;\n                        bestI=ni;\n                    }\n                }\n\n                if(bestI!=old){\n                    auto &vec = assigned[old];\n                    vec.erase(find(vec.begin(), vec.end(), k));\n                    assigned[bestI].push_back(k);\n                    assign[k]=bestI;\n                    any=true;\n                }\n            }\n            if(!any) break;\n        }\n\n        // Try removing active stations.\n        bool changed=true;\n        while(changed){\n            changed=false;\n            vector<int> P = recomputeP();\n            vector<int> stations;\n            for(int i=0;i<N;i++) if(!assigned[i].empty()) stations.push_back(i);\n            sort(stations.begin(), stations.end(), [&](int i,int j){\n                return assigned[i].size() < assigned[j].size();\n            });\n\n            for(int rem: stations){\n                if(assigned[rem].empty()) continue;\n                if((int)assigned[rem].size() > 200) continue;\n\n                vector<int> backup = assigned[rem];\n                vector<pair<int,int>> moves;\n                bool ok=true;\n\n                for(int k: backup){\n                    long long bestInc=INF;\n                    int bestI=-1;\n                    int lim = min(candidateLimit, (int)cand[k].size());\n                    for(int z=0; z<lim; z++){\n                        int ni=cand[k][z].second;\n                        if(ni==rem) continue;\n                        int md=0;\n                        for(int kk: assigned[ni]) md=max(md, d2[ni][kk]);\n                        int r0=ceil_sqrt(md);\n                        int r1=ceil_sqrt(max(md, d2[ni][k]));\n                        long long inc=1LL*r1*r1-1LL*r0*r0;\n                        if(assigned[ni].empty()) inc += dist[0][ni]/5;\n                        if(inc<bestInc){\n                            bestInc=inc;\n                            bestI=ni;\n                        }\n                    }\n                    if(bestI<0){ ok=false; break; }\n                    moves.push_back({k,bestI});\n                    assigned[bestI].push_back(k);\n                    assign[k]=bestI;\n                }\n\n                assigned[rem].clear();\n\n                vector<int> nP = recomputeP();\n                vector<int> nB = build_edges(nP);\n                long long nc = calc_cost(nP,nB);\n\n                // compare with rollback version\n                assigned[rem]=backup;\n                for(auto [k,ni]: moves){\n                    auto &vec=assigned[ni];\n                    auto it=find(vec.begin(), vec.end(), k);\n                    if(it!=vec.end()) vec.erase(it);\n                    assign[k]=rem;\n                }\n                vector<int> oP = recomputeP();\n                vector<int> oB = build_edges(oP);\n                long long oc = calc_cost(oP,oB);\n\n                if(ok && nc < oc){\n                    assigned[rem].clear();\n                    for(auto [k,ni]: moves){\n                        assigned[ni].push_back(k);\n                        assign[k]=ni;\n                    }\n                    changed=true;\n                }\n            }\n        }\n\n        vector<int> P = recomputeP();\n        vector<int> B = build_edges(P);\n        long long cost = calc_cost(P,B);\n        if(cost < bestCost){\n            bestCost=cost;\n            bestP=P;\n            bestB=B;\n        }\n    };\n\n    solve_with_limit(8);\n    solve_with_limit(15);\n    solve_with_limit(30);\n    solve_with_limit(100);\n\n    // Safety: verify coverage. If somehow uncovered, assign to nearest station.\n    for(int k=0;k<K;k++){\n        bool cov=false;\n        for(int i=0;i<N;i++){\n            if(1LL*bestP[i]*bestP[i] >= d2[i][k]){\n                cov=true;\n                break;\n            }\n        }\n        if(!cov){\n            int bi=cand[k][0].second;\n            bestP[bi]=max(bestP[bi], (int)ceil(sqrt((double)d2[bi][k])));\n            if(bestP[bi]>5000) bestP[bi]=5000;\n        }\n    }\n    bestB = build_edges(bestP);\n\n    for(int i=0;i<N;i++){\n        if(i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n\n    for(int i=0;i<M;i++){\n        if(i) cout << ' ';\n        cout << bestB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int M = N * (N + 1) / 2;\n\nstruct Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> a(N);\n    vector<Pos> pos(M);\n\n    for (int x = 0; x < N; x++) {\n        a[x].resize(x + 1);\n        for (int y = 0; y <= x; y++) {\n            cin >> a[x][y];\n            pos[a[x][y]] = {x, y};\n        }\n    }\n\n    vector<array<int, 4>> ops;\n\n    auto id_order_less = [](const Pos& p, const Pos& q) {\n        if (p.x != q.x) return p.x < q.x;\n        return p.y < q.y;\n    };\n\n    auto swap_cells = [&](int x1, int y1, int x2, int y2) {\n        if ((int)ops.size() >= 10000) return false;\n        ops.push_back({x1, y1, x2, y2});\n        int v1 = a[x1][y1], v2 = a[x2][y2];\n        swap(a[x1][y1], a[x2][y2]);\n        pos[v1] = {x2, y2};\n        pos[v2] = {x1, y1};\n        return true;\n    };\n\n    vector<vector<bool>> fixed(N);\n    for (int x = 0; x < N; x++) fixed[x].assign(x + 1, false);\n\n    // target cells in row-major order\n    for (int tx = 0; tx < N; tx++) {\n        for (int ty = 0; ty <= tx; ty++) {\n            // Find smallest value among unfixed cells.\n            int best = -1;\n            for (int v = 0; v < M; v++) {\n                Pos p = pos[v];\n                if (!fixed[p.x][p.y]) {\n                    best = v;\n                    break;\n                }\n            }\n\n            int cx = pos[best].x;\n            int cy = pos[best].y;\n\n            // Move upward until reaching row tx.\n            // From (cx,cy), upward neighbors are:\n            // (cx-1,cy-1) if cy>0 and (cx-1,cy) if cy<cx.\n            // Choose moves that keep column >= ty when possible.\n            while (cx > tx) {\n                int nx, ny;\n\n                if (cy > ty) {\n                    // go up-left: (cx,cy) -> (cx-1,cy-1)\n                    nx = cx - 1;\n                    ny = cy - 1;\n                } else {\n                    // go up-right-ish: (cx,cy) -> (cx-1,cy)\n                    // valid if cy <= cx-1, which holds unless cy==cx.\n                    if (cy <= cx - 1) {\n                        nx = cx - 1;\n                        ny = cy;\n                    } else {\n                        nx = cx - 1;\n                        ny = cy - 1;\n                    }\n                }\n\n                // This should not enter fixed cells due to processing order.\n                if (fixed[nx][ny]) {\n                    // Fallback: try the other upward direction.\n                    bool moved = false;\n                    if (cy > 0) {\n                        int ax = cx - 1, ay = cy - 1;\n                        if (!fixed[ax][ay]) {\n                            nx = ax; ny = ay; moved = true;\n                        }\n                    }\n                    if (!moved && cy < cx) {\n                        int ax = cx - 1, ay = cy;\n                        if (!fixed[ax][ay]) {\n                            nx = ax; ny = ay; moved = true;\n                        }\n                    }\n                    if (!moved) {\n                        // Should not happen.\n                        fixed[tx][ty] = true;\n                        goto next_cell;\n                    }\n                }\n\n                if (!swap_cells(cx, cy, nx, ny)) goto output;\n                cx = nx;\n                cy = ny;\n            }\n\n            // Move horizontally left/right on target row.\n            while (cy > ty) {\n                int nx = cx, ny = cy - 1;\n                if (fixed[nx][ny]) break; // should not happen for cy-1 >= ty\n                if (!swap_cells(cx, cy, nx, ny)) goto output;\n                cy = ny;\n            }\n            while (cy < ty) {\n                int nx = cx, ny = cy + 1;\n                if (fixed[nx][ny]) break;\n                if (!swap_cells(cx, cy, nx, ny)) goto output;\n                cy = ny;\n            }\n\n            fixed[tx][ty] = true;\n\n        next_cell:;\n        }\n    }\n\noutput:\n    cout << ops.size() << '\\n';\n    for (auto &op : ops) {\n        cout << op[0] << ' ' << op[1] << ' ' << op[2] << ' ' << op[3] << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c;\n};\n\nint D, N;\nstatic const int SZ = 9;\nint entR = 0, entC = 4;\nbool obstacle[9][9];\nbool occupied[9][9];\nint valAt[9][9];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nvector<vector<int>> calcReachableEmpty() {\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    queue<pair<int,int>> q;\n    if (!obstacle[entR][entC] && !occupied[entR][entC]) {\n        vis[entR][entC] = 1;\n        q.push({entR, entC});\n    }\n    while (!q.empty()) {\n        auto [r,c] = q.front(); q.pop();\n        for (int k=0;k<4;k++) {\n            int nr=r+dr[k], nc=c+dc[k];\n            if (!inside(nr,nc)) continue;\n            if (vis[nr][nc]) continue;\n            if (obstacle[nr][nc] || occupied[nr][nc]) continue;\n            vis[nr][nc] = 1;\n            q.push({nr,nc});\n        }\n    }\n    return vis;\n}\n\nvector<vector<int>> calcReachableForRemoval() {\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    queue<pair<int,int>> q;\n    vis[entR][entC] = 1;\n    q.push({entR, entC});\n    while (!q.empty()) {\n        auto [r,c] = q.front(); q.pop();\n        for (int k=0;k<4;k++) {\n            int nr=r+dr[k], nc=c+dc[k];\n            if (!inside(nr,nc)) continue;\n            if (vis[nr][nc]) continue;\n            if (obstacle[nr][nc]) continue;\n            if (occupied[nr][nc]) continue;\n            vis[nr][nc] = 1;\n            q.push({nr,nc});\n        }\n    }\n    return vis;\n}\n\nbool isReachableContainer(int r, int c, const vector<vector<int>>& emptyReach) {\n    for (int k=0;k<4;k++) {\n        int nr=r+dr[k], nc=c+dc[k];\n        if (!inside(nr,nc)) continue;\n        if (emptyReach[nr][nc]) return true;\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n    memset(obstacle, 0, sizeof(obstacle));\n    memset(occupied, 0, sizeof(occupied));\n    for (int i=0;i<D;i++) for (int j=0;j<D;j++) valAt[i][j] = -1;\n\n    for (int i=0;i<N;i++) {\n        int r,c; cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    int M = D*D - 1 - N;\n\n    // BFS distance from entrance ignoring containers.\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n    dist[entR][entC] = 0;\n    q.push({entR, entC});\n    while (!q.empty()) {\n        auto [r,c] = q.front(); q.pop();\n        for (int k=0;k<4;k++) {\n            int nr=r+dr[k], nc=c+dc[k];\n            if (!inside(nr,nc)) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr,nc});\n        }\n    }\n\n    vector<Cell> cells;\n    for (int r=0;r<D;r++) {\n        for (int c=0;c<D;c++) {\n            if (r == entR && c == entC) continue;\n            if (obstacle[r][c]) continue;\n            cells.push_back({r,c});\n        }\n    }\n\n    // Rank cells by accessibility/removal priority.\n    // Lower rank = easier to remove, higher rank = deeper.\n    sort(cells.begin(), cells.end(), [&](const Cell& a, const Cell& b) {\n        int da = dist[a.r][a.c], db = dist[b.r][b.c];\n        if (da != db) return da < db;\n        int ca = abs(a.c - entC), cb = abs(b.c - entC);\n        if (ca != cb) return ca < cb;\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    map<pair<int,int>, int> rankOf;\n    for (int i=0;i<(int)cells.size();i++) {\n        rankOf[{cells[i].r, cells[i].c}] = i;\n    }\n\n    // Online placement.\n    for (int d=0; d<M; d++) {\n        int t;\n        cin >> t;\n\n        auto reach = calcReachableEmpty();\n\n        int targetRank;\n        if (M == 1) targetRank = 0;\n        else targetRank = (long long)t * (M-1) / (M-1);\n\n        Cell best{-1,-1};\n        long long bestScore = (1LL<<60);\n\n        for (auto cell : cells) {\n            int r = cell.r, c = cell.c;\n            if (occupied[r][c]) continue;\n            if (!reach[r][c]) continue;\n\n            int rk = rankOf[{r,c}];\n\n            // Prefer large labels deeper, small labels near entrance.\n            long long score = 0;\n            score += 1000LL * abs(rk - targetRank);\n\n            // Slightly prefer filling deeper cells first to preserve front.\n            score -= 5LL * dist[r][c];\n\n            // Avoid blocking central corridor too early.\n            if (c == entC) score += 15;\n\n            // Prefer side cells for large labels.\n            score -= 2LL * abs(c - entC);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = cell;\n            }\n        }\n\n        // Fallback, should rarely/never be needed.\n        if (best.r == -1) {\n            for (int r=0;r<D;r++) for (int c=0;c<D;c++) {\n                if (r == entR && c == entC) continue;\n                if (obstacle[r][c] || occupied[r][c]) continue;\n                if (reach[r][c]) {\n                    best = {r,c};\n                    break;\n                }\n            }\n        }\n\n        occupied[best.r][best.c] = true;\n        valAt[best.r][best.c] = t;\n\n        cout << best.r << \" \" << best.c << \"\\n\";\n        cout.flush();\n    }\n\n    // Removal phase: repeatedly remove reachable container with minimum label.\n    vector<Cell> removal;\n    for (int step=0; step<M; step++) {\n        auto emptyReach = calcReachableForRemoval();\n\n        int bestVal = INT_MAX;\n        Cell best{-1,-1};\n\n        for (int r=0;r<D;r++) {\n            for (int c=0;c<D;c++) {\n                if (!occupied[r][c]) continue;\n                if (!isReachableContainer(r,c,emptyReach)) continue;\n\n                if (valAt[r][c] < bestVal) {\n                    bestVal = valAt[r][c];\n                    best = {r,c};\n                }\n            }\n        }\n\n        // Fallback: should not happen if state is valid.\n        if (best.r == -1) {\n            for (int r=0;r<D;r++) for (int c=0;c<D;c++) {\n                if (occupied[r][c]) {\n                    best = {r,c};\n                    break;\n                }\n            }\n        }\n\n        removal.push_back(best);\n        occupied[best.r][best.c] = false;\n        valAt[best.r][best.c] = -1;\n    }\n\n    for (auto cell : removal) {\n        cout << cell.r << \" \" << cell.c << \"\\n\";\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 50;\nstatic const int M = 100;\n\nint n, m;\narray<array<int, N>, N> g;\nbool targetAdj[M + 1][M + 1];\nint colorCnt[M + 1];\n\nchrono::steady_clock::time_point startTime;\ndouble timeLimit = 1.90;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\nvoid addAdj(bool adj[M + 1][M + 1], int a, int b) {\n    if (a == b) return;\n    if (a > b) swap(a, b);\n    adj[a][b] = adj[b][a] = true;\n}\n\nvoid computeAdj(const array<array<int, N>, N>& grid, bool adj[M + 1][M + 1]) {\n    for (int i = 0; i <= M; i++) {\n        for (int j = 0; j <= M; j++) adj[i][j] = false;\n    }\n\n    for (int i = 0; i < n; i++) {\n        addAdj(adj, 0, grid[i][0]);\n        addAdj(adj, 0, grid[i][n - 1]);\n    }\n    for (int j = 0; j < n; j++) {\n        addAdj(adj, 0, grid[0][j]);\n        addAdj(adj, 0, grid[n - 1][j]);\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i + 1 < n) addAdj(adj, grid[i][j], grid[i + 1][j]);\n            if (j + 1 < n) addAdj(adj, grid[i][j], grid[i][j + 1]);\n        }\n    }\n}\n\nbool checkAdjacency() {\n    bool curAdj[M + 1][M + 1];\n    computeAdj(g, curAdj);\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            if (curAdj[i][j] != targetAdj[i][j]) return false;\n        }\n    }\n    return true;\n}\n\nbool checkZeroConnected() {\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n\n    for (int i = 0; i < n; i++) {\n        if (g[i][0] == 0 && !vis[i][0]) {\n            vis[i][0] = true;\n            q.push({i, 0});\n        }\n        if (g[i][n - 1] == 0 && !vis[i][n - 1]) {\n            vis[i][n - 1] = true;\n            q.push({i, n - 1});\n        }\n    }\n    for (int j = 0; j < n; j++) {\n        if (g[0][j] == 0 && !vis[0][j]) {\n            vis[0][j] = true;\n            q.push({0, j});\n        }\n        if (g[n - 1][j] == 0 && !vis[n - 1][j]) {\n            vis[n - 1][j] = true;\n            q.push({n - 1, j});\n        }\n    }\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        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 (vis[ni][nj] || g[ni][nj] != 0) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == 0 && !vis[i][j]) return false;\n        }\n    }\n    return true;\n}\n\nbool checkColorConnected(int c) {\n    if (colorCnt[c] <= 0) return false;\n\n    bool found = false;\n    int si = -1, sj = -1;\n    for (int i = 0; i < n && !found; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == c) {\n                si = i;\n                sj = j;\n                found = true;\n                break;\n            }\n        }\n    }\n\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n    vis[si][sj] = true;\n    q.push({si, sj});\n    int cnt = 0;\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        cnt++;\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 (!vis[ni][nj] && g[ni][nj] == c) {\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n    }\n\n    return cnt == colorCnt[c];\n}\n\nbool fullCheck() {\n    if (!checkZeroConnected()) return false;\n\n    for (int c = 1; c <= m; c++) {\n        if (!checkColorConnected(c)) return false;\n    }\n\n    if (!checkAdjacency()) return false;\n    return true;\n}\n\nbool tryEraseCell(int i, int j) {\n    int c = g[i][j];\n    if (c == 0) return false;\n    if (colorCnt[c] <= 1) return false;\n\n    g[i][j] = 0;\n    colorCnt[c]--;\n    colorCnt[0]++;\n\n    bool ok = fullCheck();\n\n    if (!ok) {\n        g[i][j] = c;\n        colorCnt[c]++;\n        colorCnt[0]--;\n    }\n    return ok;\n}\n\nint zeroCount() {\n    int z = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == 0) z++;\n        }\n    }\n    return z;\n}\n\nvoid printGrid() {\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}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    startTime = chrono::steady_clock::now();\n\n    cin >> n >> m;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> g[i][j];\n            colorCnt[g[i][j]]++;\n        }\n    }\n\n    computeAdj(g, targetAdj);\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++) cells.push_back({i, j});\n    }\n\n    mt19937 rng(1234567);\n\n    int pass = 0;\n    while (elapsed() < timeLimit) {\n        pass++;\n\n        // Mix several orders. Boundary-first is often useful because zeros must touch outside.\n        if (pass % 4 == 1) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, N - 1 - a.first, N - 1 - a.second});\n                int db = min({b.first, b.second, N - 1 - b.first, N - 1 - b.second});\n                return da < db;\n            });\n        } else if (pass % 4 == 2) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, N - 1 - a.first, N - 1 - a.second});\n                int db = min({b.first, b.second, N - 1 - b.first, N - 1 - b.second});\n                return da > db;\n            });\n        } else {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n\n        bool changed = false;\n        for (auto [i, j] : cells) {\n            if (elapsed() > timeLimit) break;\n            if (tryEraseCell(i, j)) changed = true;\n        }\n\n        if (!changed && pass > 6) {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n    }\n\n    printGrid();\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    vector<int> ord;              // light -> heavy estimated\n    vector<vector<int>> groups;\n    vector<int> ans;\n\n    char query_vec(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        char c;\n        cin >> c;\n        used++;\n        return c;\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query_vec(L, R);\n    }\n\n    // returns true if item a is lighter than item b\n    bool less_item(int a, int b) {\n        char c = query_single(a, b);\n        return c == '<';\n    }\n\n    // compare current groups\n    // returns -1 if A lighter, 0 if equal/unknown, 1 if A heavier\n    int compare_group(int a, int b) {\n        if (groups[a].empty() && groups[b].empty()) return 0;\n        if (groups[a].empty()) return -1;\n        if (groups[b].empty()) return 1;\n        char c = query_vec(groups[a], groups[b]);\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    void bounded_insertion_sort() {\n        ord.clear();\n        ord.push_back(0);\n\n        for (int i = 1; i < N; i++) {\n            if (used >= Q) {\n                ord.push_back(i);\n                continue;\n            }\n\n            // Binary insertion if enough budget, otherwise linear fallback.\n            int lo = 0, hi = (int)ord.size();\n            while (lo < hi && used < Q) {\n                int mid = (lo + hi) / 2;\n                // if i < ord[mid], go left\n                bool lt = less_item(i, ord[mid]);\n                if (lt) hi = mid;\n                else lo = mid + 1;\n            }\n            ord.insert(ord.begin() + lo, i);\n        }\n\n        // If sorting was interrupted, ord still contains all items.\n        vector<int> seen(N, 0);\n        for (int x : ord) seen[x] = 1;\n        for (int i = 0; i < N; i++) {\n            if (!seen[i]) ord.push_back(i);\n        }\n    }\n\n    int find_lightest_group() {\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (used >= Q) break;\n            int cmp = compare_group(g, best);\n            if (cmp == -1) best = g;\n        }\n        return best;\n    }\n\n    void make_partition() {\n        groups.assign(D, {});\n        ans.assign(N, 0);\n\n        // Put heaviest estimated items first.\n        vector<int> heavy_to_light = ord;\n        reverse(heavy_to_light.begin(), heavy_to_light.end());\n\n        for (int item : heavy_to_light) {\n            int g;\n            if (used + D - 1 <= Q) {\n                g = find_lightest_group();\n            } else {\n                // query budget is tight: deterministic fallback\n                int mn = 0;\n                for (int i = 1; i < D; i++) {\n                    if (groups[i].size() < groups[mn].size()) mn = i;\n                }\n                g = mn;\n            }\n            groups[g].push_back(item);\n            ans[item] = g;\n        }\n    }\n\n    void spend_remaining_queries() {\n        // Use remaining queries in harmless but somewhat informative ways.\n        int ptr = 0;\n        while (used < Q) {\n            bool done = false;\n\n            // Prefer comparing non-empty groups.\n            for (int k = 0; k < D && used < Q; k++) {\n                int a = (ptr + k) % D;\n                int b = (ptr + k + 1) % D;\n                if (a == b) continue;\n                if (!groups[a].empty() && !groups[b].empty()) {\n                    query_vec(groups[a], groups[b]);\n                    done = true;\n                    break;\n                }\n            }\n            ptr++;\n\n            if (!done && used < Q) {\n                int a = used % N;\n                int b = (a + 1) % N;\n                query_single(a, b);\n            }\n        }\n    }\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        bounded_insertion_sort();\n\n        if (used < Q) {\n            make_partition();\n        } else {\n            // No budget left: simple sorted round-robin.\n            groups.assign(D, {});\n            ans.assign(N, 0);\n            vector<int> heavy_to_light = ord;\n            reverse(heavy_to_light.begin(), heavy_to_light.end());\n            for (int i = 0; i < (int)heavy_to_light.size(); i++) {\n                int g = i % D;\n                ans[heavy_to_light[i]] = g;\n                groups[g].push_back(heavy_to_light[i]);\n            }\n        }\n\n        spend_remaining_queries();\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << ans[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\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    cin >> n >> m;\n\n    vector<vector<int>> st(m);\n    int h0 = n / m;\n    vector<int> pos(n + 1);\n\n    for (int i = 0; i < m; i++) {\n        st[i].resize(h0);\n        for (int j = 0; j < h0; j++) {\n            cin >> st[i][j];\n            pos[st[i][j]] = i;\n        }\n    }\n\n    vector<pair<int,int>> ans;\n    vector<char> removed(n + 1, false);\n\n    auto rebuild_pos = [&]() {\n        fill(pos.begin(), pos.end(), -1);\n        for (int i = 0; i < m; i++) {\n            for (int x : st[i]) pos[x] = i;\n        }\n    };\n\n    auto remove_greedy = [&](int &cur) {\n        bool changed = true;\n        while (cur <= n && changed) {\n            changed = false;\n            for (int i = 0; i < m; i++) {\n                if (!st[i].empty() && st[i].back() == cur) {\n                    st[i].pop_back();\n                    removed[cur] = true;\n                    pos[cur] = -1;\n                    ans.push_back({cur, 0});\n                    cur++;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    };\n\n    int cur = 1;\n    remove_greedy(cur);\n\n    while (cur <= n) {\n        rebuild_pos();\n\n        int s = pos[cur];\n        if (s < 0) {\n            remove_greedy(cur);\n            continue;\n        }\n\n        int idx = -1;\n        for (int j = 0; j < (int)st[s].size(); j++) {\n            if (st[s][j] == cur) {\n                idx = j;\n                break;\n            }\n        }\n\n        if (idx == (int)st[s].size() - 1) {\n            remove_greedy(cur);\n            continue;\n        }\n\n        vector<int> seg;\n        for (int j = idx + 1; j < (int)st[s].size(); j++) seg.push_back(st[s][j]);\n\n        int k = (int)seg.size();\n        int segMin = *min_element(seg.begin(), seg.end());\n        int segMax = *max_element(seg.begin(), seg.end());\n        int segBottom = seg.front();\n        int segTop = seg.back();\n\n        int bestDst = -1;\n        long long bestScore = (1LL << 60);\n\n        for (int d = 0; d < m; d++) {\n            if (d == s) continue;\n\n            long long score = 0;\n\n            if (st[d].empty()) {\n                // Empty stack is very flexible, especially good for troublesome small boxes.\n                score -= 2500;\n                score += k * 8;\n                score += segMin;\n            } else {\n                int top = st[d].back();\n\n                // Boundary after move: destination top lies directly below segBottom.\n                // If top > segBottom, then smaller box is above larger box: good.\n                if (top > segBottom) {\n                    score -= 1800;\n                    score += (top - segBottom) * 3;\n                } else {\n                    score += 2500;\n                    score += (segBottom - top) * 20;\n                }\n\n                // The actual top after move becomes segTop.\n                // Small segTop will be needed soon, so avoid burying it on very tall stacks.\n                if (segTop < cur + 30) score += (long long)st[d].size() * 25;\n\n                // If destination contains very small top, avoid covering it.\n                if (top < cur + 25) score += 3000 + (cur + 25 - top) * 30;\n\n                // Prefer destination top just above segment bottom.\n                score += abs(top - segBottom) * 2;\n            }\n\n            // Avoid making very tall stacks.\n            score += (long long)st[d].size() * 15;\n\n            // Segments with small minimum should stay accessible.\n            if (segMin < cur + 20) score += (long long)st[d].size() * 20;\n\n            // Prefer stacks where all elements are larger than segMin near the top.\n            int badNearTop = 0;\n            for (int t = (int)st[d].size() - 1; t >= 0 && t >= (int)st[d].size() - 5; t--) {\n                if (st[d][t] < segMin) badNearTop++;\n            }\n            score += badNearTop * 700;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestDst = d;\n            }\n        }\n\n        if (bestDst == -1) {\n            // Should never happen for m >= 2.\n            bestDst = (s + 1) % m;\n        }\n\n        int v = st[s][idx + 1]; // bottom of moved suffix\n        ans.push_back({v, bestDst + 1});\n\n        for (int j = idx + 1; j < (int)st[s].size(); j++) {\n            st[bestDst].push_back(st[s][j]);\n        }\n        st[s].resize(idx + 1);\n\n        remove_greedy(cur);\n\n        if ((int)ans.size() > 4900) {\n            // Safety fallback: continue still likely okay, but avoid exceeding 5000.\n            // Since n=200, this should not trigger.\n            break;\n        }\n    }\n\n    // If somehow not all removed, use a very conservative fallback.\n    while (cur <= n && (int)ans.size() < 5000) {\n        remove_greedy(cur);\n        if (cur > n) break;\n\n        rebuild_pos();\n        int s = pos[cur];\n        int idx = -1;\n        for (int j = 0; j < (int)st[s].size(); j++) {\n            if (st[s][j] == cur) {\n                idx = j;\n                break;\n            }\n        }\n\n        if (idx == (int)st[s].size() - 1) continue;\n\n        int dst = -1;\n        for (int i = 0; i < m; i++) {\n            if (i != s && st[i].empty()) {\n                dst = i;\n                break;\n            }\n        }\n        if (dst == -1) {\n            int bestH = INT_MAX;\n            for (int i = 0; i < m; i++) {\n                if (i == s) continue;\n                if ((int)st[i].size() < bestH) {\n                    bestH = st[i].size();\n                    dst = i;\n                }\n            }\n        }\n\n        int v = st[s][idx + 1];\n        ans.push_back({v, dst + 1});\n        for (int j = idx + 1; j < (int)st[s].size(); j++) {\n            st[dst].push_back(st[s][j]);\n        }\n        st[s].resize(idx + 1);\n    }\n\n    if ((int)ans.size() > 5000) ans.resize(5000);\n\n    for (auto [v, i] : ans) {\n        cout << v << ' ' << i << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Child {\n    int to;\n    char dir;\n    char back;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> d[i][j];\n    }\n\n    int V = N * N;\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto pos = [&](int x) { return pair<int,int>(x / N, x % N); };\n\n    vector<vector<pair<int,char>>> g(V);\n\n    auto add_edge = [&](int a, int b, char c) {\n        g[a].push_back({b, c});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int cur = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(cur, id(i + 1, j), 'D');\n                add_edge(id(i + 1, j), cur, 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(cur, id(i, j + 1), 'R');\n                add_edge(id(i, j + 1), cur, 'L');\n            }\n        }\n    }\n\n    vector<int> parent(V, -1), parent_dir(V, -1);\n    vector<vector<int>> tree(V);\n\n    // Build a spanning tree. Prefer high-d neighboring cells while constructing.\n    vector<int> visited(V, 0);\n    priority_queue<pair<int,int>> pq;\n    visited[0] = 1;\n    pq.push({d[0][0], 0});\n\n    while (!pq.empty()) {\n        auto [_, u] = pq.top();\n        pq.pop();\n\n        vector<pair<int,char>> ng = g[u];\n        sort(ng.begin(), ng.end(), [&](auto &a, auto &b) {\n            auto [ai, aj] = pos(a.first);\n            auto [bi, bj] = pos(b.first);\n            return d[ai][aj] > d[bi][bj];\n        });\n\n        for (auto [to, c] : ng) {\n            if (!visited[to]) {\n                visited[to] = 1;\n                parent[to] = u;\n                parent_dir[to] = c;\n                tree[u].push_back(to);\n                pq.push({d[pos(to).first][pos(to).second], to});\n            }\n        }\n    }\n\n    // In rare case priority construction somehow misses none due connected guarantee,\n    // but keep a fallback DFS spanning tree for safety.\n    bool ok = true;\n    for (int i = 0; i < V; i++) if (!visited[i]) ok = false;\n\n    if (!ok) {\n        parent.assign(V, -1);\n        parent_dir.assign(V, -1);\n        tree.assign(V, {});\n        visited.assign(V, 0);\n\n        stack<int> st;\n        st.push(0);\n        visited[0] = 1;\n\n        while (!st.empty()) {\n            int u = st.top();\n            st.pop();\n            for (auto [to, c] : g[u]) {\n                if (!visited[to]) {\n                    visited[to] = 1;\n                    parent[to] = u;\n                    parent_dir[to] = c;\n                    tree[u].push_back(to);\n                    st.push(to);\n                }\n            }\n        }\n    }\n\n    vector<long long> sub(V, 0);\n\n    function<void(int)> calc = [&](int u) {\n        auto [i, j] = pos(u);\n        sub[u] = d[i][j];\n        for (int to : tree[u]) {\n            calc(to);\n            sub[u] += sub[to];\n        }\n    };\n    calc(0);\n\n    auto opposite = [&](char c) {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        return 'L';\n    };\n\n    for (int u = 0; u < V; u++) {\n        sort(tree[u].begin(), tree[u].end(), [&](int a, int b) {\n            return sub[a] > sub[b];\n        });\n    }\n\n    string ans;\n    ans.reserve(2 * V + 10);\n\n    function<void(int)> dfs = [&](int u) {\n        for (int to : tree[u]) {\n            char c = (char)parent_dir[to];\n            ans.push_back(c);\n            dfs(to);\n            ans.push_back(opposite(c));\n        }\n    };\n\n    dfs(0);\n\n    if ((int)ans.size() > 100000) {\n        // This will never happen for N<=40 with the tree tour,\n        // but keep output legal if modified.\n        ans.resize(100000);\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int r, c;\n};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint overlap_len(const string& a, const string& b) {\n    int best = 0;\n    for (int k = 1; k <= 4; k++) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[5 - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) best = k;\n    }\n    return best;\n}\n\nstring build_superstring_from_order(const vector<string>& t, const vector<int>& ord,\n                                    const vector<vector<int>>& ov) {\n    string s = t[ord[0]];\n    for (int i = 1; i < (int)ord.size(); i++) {\n        int a = ord[i - 1];\n        int b = ord[i];\n        int k = ov[a][b];\n        s += t[b].substr(k);\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    Pos start;\n    cin >> start.r >> start.c;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) ov[i][j] = overlap_len(t[i], t[j]);\n        }\n    }\n\n    mt19937 rng(71236721);\n\n    vector<int> best_order;\n    string best_super;\n    int best_len = INT_MAX;\n\n    auto eval_order = [&](const vector<int>& ord) {\n        int len = 5;\n        for (int i = 1; i < M; i++) {\n            len += 5 - ov[ord[i - 1]][ord[i]];\n        }\n        return len;\n    };\n\n    auto make_greedy_order = [&](int st, double noise) {\n        vector<int> ord;\n        vector<char> used(M, false);\n        ord.reserve(M);\n\n        int cur = st;\n        ord.push_back(cur);\n        used[cur] = true;\n\n        for (int step = 1; step < M; step++) {\n            int best = -1;\n            double best_score = -1e100;\n\n            for (int nxt = 0; nxt < M; nxt++) {\n                if (used[nxt]) continue;\n\n                double score = ov[cur][nxt] * 1000.0;\n\n                // Tie-breaking: prefer words that also have many possible outgoing overlaps.\n                int mxout = 0;\n                for (int z = 0; z < M; z++) {\n                    if (!used[z] && z != nxt) mxout = max(mxout, ov[nxt][z]);\n                }\n                score += mxout * 10.0;\n\n                if (noise > 0) {\n                    score += uniform_real_distribution<double>(0.0, noise)(rng);\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best = nxt;\n                }\n            }\n\n            cur = best;\n            used[cur] = true;\n            ord.push_back(cur);\n        }\n\n        return ord;\n    };\n\n    // Deterministic starts.\n    for (int st = 0; st < M; st++) {\n        vector<int> ord = make_greedy_order(st, 0.0);\n        int len = eval_order(ord);\n        if (len < best_len) {\n            best_len = len;\n            best_order = ord;\n        }\n    }\n\n    // Randomized greedy attempts.\n    auto time_start = chrono::steady_clock::now();\n    int attempts = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - time_start).count();\n        if (elapsed > 0.45) break;\n\n        int st = uniform_int_distribution<int>(0, M - 1)(rng);\n        double noise = 800.0;\n        vector<int> ord = make_greedy_order(st, noise);\n        int len = eval_order(ord);\n        if (len < best_len) {\n            best_len = len;\n            best_order = ord;\n        }\n        attempts++;\n    }\n\n    // Local improvement by trying swaps/reversals with quick full reevaluation.\n    // M is only 200, so this is cheap.\n    bool improved = true;\n    int loop = 0;\n    while (improved && loop < 30) {\n        improved = false;\n        loop++;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 1; j < M; j++) {\n                vector<int> cand = best_order;\n                swap(cand[i], cand[j]);\n                int len = eval_order(cand);\n                if (len < best_len) {\n                    best_len = len;\n                    best_order.swap(cand);\n                    improved = true;\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 2; j < M; j++) {\n                vector<int> cand = best_order;\n                reverse(cand.begin() + i, cand.begin() + j + 1);\n                int len = eval_order(cand);\n                if (len < best_len) {\n                    best_len = len;\n                    best_order.swap(cand);\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    best_super = build_superstring_from_order(t, best_order, ov);\n\n    // Safety: if somehow too long, simple concatenation is still <=1000.\n    if ((int)best_super.size() > 5000) {\n        best_super.clear();\n        for (auto& x : t) best_super += x;\n    }\n\n    vector<vector<Pos>> occ(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            occ[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    int L = best_super.size();\n    const int INF = 1e9;\n\n    vector<vector<int>> dp(L);\n    vector<vector<int>> pre(L);\n\n    for (int idx = 0; idx < L; idx++) {\n        int ch = best_super[idx] - 'A';\n        int sz = occ[ch].size();\n        dp[idx].assign(sz, INF);\n        pre[idx].assign(sz, -1);\n\n        if (idx == 0) {\n            for (int k = 0; k < sz; k++) {\n                dp[idx][k] = manhattan(start, occ[ch][k]) + 1;\n            }\n        } else {\n            int pch = best_super[idx - 1] - 'A';\n            int psz = occ[pch].size();\n\n            for (int k = 0; k < sz; k++) {\n                for (int pk = 0; pk < psz; pk++) {\n                    int val = dp[idx - 1][pk] + manhattan(occ[pch][pk], occ[ch][k]) + 1;\n                    if (val < dp[idx][k]) {\n                        dp[idx][k] = val;\n                        pre[idx][k] = pk;\n                    }\n                }\n            }\n        }\n    }\n\n    int last_ch = best_super[L - 1] - 'A';\n    int best_last = 0;\n    for (int k = 1; k < (int)occ[last_ch].size(); k++) {\n        if (dp[L - 1][k] < dp[L - 1][best_last]) best_last = k;\n    }\n\n    vector<Pos> answer(L);\n    int cur_idx = best_last;\n    for (int idx = L - 1; idx >= 0; idx--) {\n        int ch = best_super[idx] - 'A';\n        answer[idx] = occ[ch][cur_idx];\n        cur_idx = pre[idx][cur_idx];\n    }\n\n    for (auto& p : answer) {\n        cout << p.r << ' ' << p.c << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#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    double eps;\n    cin >> N >> M >> eps;\n\n    vector<vector<pair<int,int>>> fields(M);\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        fields[k].resize(d);\n        for (int t = 0; t < d; t++) {\n            cin >> fields[k][t].first >> fields[k][t].second;\n        }\n    }\n\n    vector<pair<int,int>> oil_cells;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cout << \"q 1 \" << i << ' ' << j << endl;\n            cout.flush();\n\n            int v;\n            cin >> v;\n\n            if (v > 0) {\n                oil_cells.emplace_back(i, j);\n            }\n        }\n    }\n\n    cout << \"a \" << oil_cells.size();\n    for (auto [i, j] : oil_cells) {\n        cout << ' ' << i << ' ' << j;\n    }\n    cout << endl;\n    cout.flush();\n\n    int res;\n    cin >> res;\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W, D, N;\n    cin >> W >> D >> N;\n\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> a[d][k];\n    }\n\n    const long long INF = (1LL << 60);\n\n    // cost[k][w] = total shortage area for reservation index k if width is w.\n    // Actual score multiplies shortage area by 100, but multiplier is irrelevant for DP.\n    vector<vector<long long>> cost(N, vector<long long>(W + 1, 0));\n    for (int k = 0; k < N; k++) {\n        for (int w = 1; w <= W; w++) { // width must be at least 1 for valid rectangle\n            long long c = 0;\n            long long area = 1LL * W * w;\n            for (int d = 0; d < D; d++) {\n                if (a[d][k] > area) c += a[d][k] - area;\n            }\n            cost[k][w] = c;\n        }\n    }\n\n    // DP over total used width. Each reservation must receive width >= 1.\n    vector<vector<long long>> dp(N + 1, vector<long long>(W + 1, INF));\n    vector<vector<int>> pre(N + 1, vector<int>(W + 1, -1));\n    dp[0][0] = 0;\n\n    for (int k = 0; k < N; k++) {\n        for (int used = 0; used <= W; used++) {\n            if (dp[k][used] >= INF) continue;\n            int remainAfter = N - (k + 1); // need at least 1 each\n            for (int w = 1; used + w + remainAfter <= W; w++) {\n                int nu = used + w;\n                long long nv = dp[k][used] + cost[k][w];\n                if (nv < dp[k + 1][nu]) {\n                    dp[k + 1][nu] = nv;\n                    pre[k + 1][nu] = w;\n                }\n            }\n        }\n    }\n\n    // Choose best used width <= W.\n    int bestUsed = 0;\n    long long best = INF;\n    for (int used = N; used <= W; used++) {\n        if (dp[N][used] < best) {\n            best = dp[N][used];\n            bestUsed = used;\n        }\n    }\n\n    vector<int> width(N);\n    int cur = bestUsed;\n    for (int k = N; k >= 1; k--) {\n        int w = pre[k][cur];\n        if (w < 1) w = 1;\n        width[k - 1] = w;\n        cur -= w;\n    }\n\n    // In rare tie cases, unused width remains. Add it greedily where it helps most.\n    int used = accumulate(width.begin(), width.end(), 0);\n    while (used < W) {\n        int bestK = -1;\n        long long bestGain = 0;\n        for (int k = 0; k < N; k++) {\n            long long now = cost[k][width[k]];\n            long long nxt = (width[k] + 1 <= W ? cost[k][width[k] + 1] : now);\n            long long gain = now - nxt;\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestK = k;\n            }\n        }\n        if (bestK == -1 || bestGain <= 0) break;\n        width[bestK]++;\n        used++;\n    }\n\n    // Construct stable vertical strips. Coordinates are (row, col).\n    vector<Rect> rects(N);\n    int x = 0;\n    for (int k = 0; k < N; k++) {\n        int x2 = x + width[k];\n        if (k == N - 1) x2 = min(x2, W); // safety\n        rects[k] = {0, x, W, x2};\n        x = x2;\n    }\n\n    // If due to safety the last rectangle somehow got invalid, repair by simple unit strips.\n    bool ok = true;\n    for (int k = 0; k < N; k++) {\n        if (!(0 <= rects[k].i0 && rects[k].i0 < rects[k].i1 && rects[k].i1 <= W &&\n              0 <= rects[k].j0 && rects[k].j0 < rects[k].j1 && rects[k].j1 <= W)) {\n            ok = false;\n        }\n    }\n    if (!ok) {\n        for (int k = 0; k < N; k++) {\n            rects[k] = {k, 0, k + 1, W};\n        }\n    }\n\n    // Same layout every day: transition cost is zero because L0 is ignored and no changes occur.\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            cout << rects[k].i0 << ' ' << rects[k].j0 << ' '\n                 << rects[k].i1 << ' ' << rects[k].j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr long long MOD = 998244353LL;\nstatic constexpr int N = 9;\nstatic constexpr int M = 20;\nstatic constexpr int K = 81;\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct Cand {\n    long long gain;\n    int m, p, q;\n    bool operator<(const Cand& other) const {\n        return gain > other.gain;\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    XorShift() {}\n    XorShift(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n    double uniform() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nlong long calc_score(const array<array<long long, N>, N>& b) {\n    long long score = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            score += b[i][j];\n        }\n    }\n    return score;\n}\n\nlong long calc_gain(\n    const array<array<long long, N>, N>& b,\n    const long long s[M][3][3],\n    int m,\n    int p,\n    int q\n) {\n    long long gain = 0;\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            long long oldv = b[p + i][q + j];\n            long long nv = oldv + s[m][i][j];\n            if (nv >= MOD) nv -= MOD;\n            gain += nv - oldv;\n        }\n    }\n    return gain;\n}\n\nvoid apply_op(\n    array<array<long long, N>, N>& b,\n    const long long s[M][3][3],\n    int m,\n    int p,\n    int q\n) {\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            b[p + i][q + j] += s[m][i][j];\n            if (b[p + i][q + j] >= MOD) b[p + i][q + j] -= MOD;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m_input, k_input;\n    cin >> n >> m_input >> k_input;\n\n    array<array<long long, N>, N> initial{};\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    static long long stamp[M][3][3];\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamp[m][i][j];\n            }\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    vector<Op> best_ops;\n    long long best_score = calc_score(initial);\n\n    XorShift rng(\n        chrono::steady_clock::now().time_since_epoch().count()\n    );\n\n    int trial = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        array<array<long long, N>, N> b = initial;\n        vector<Op> ops;\n        long long score = calc_score(b);\n\n        for (int step = 0; step < K; step++) {\n            vector<Cand> cands;\n            cands.reserve(M * 49);\n\n            for (int sm = 0; sm < M; sm++) {\n                for (int p = 0; p <= N - 3; p++) {\n                    for (int q = 0; q <= N - 3; q++) {\n                        long long g = calc_gain(b, stamp, sm, p, q);\n                        if (g > 0) {\n                            cands.push_back({g, sm, p, q});\n                        }\n                    }\n                }\n            }\n\n            if (cands.empty()) break;\n\n            sort(cands.begin(), cands.end());\n\n            Cand chosen = cands[0];\n\n            if (trial > 0) {\n                int top = min<int>((int)cands.size(), 12);\n\n                // Earlier steps are randomized more, later steps become greedier.\n                double temp = 1.0 - double(step) / K;\n                double r = rng.uniform();\n\n                if (r < 0.70 + 0.25 * (1.0 - temp)) {\n                    chosen = cands[0];\n                } else {\n                    int idx = rng.randint(0, top - 1);\n                    chosen = cands[idx];\n                }\n            }\n\n            apply_op(b, stamp, chosen.m, chosen.p, chosen.q);\n            score += chosen.gain;\n            ops.push_back({chosen.m, chosen.p, chosen.q});\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n\n        trial++;\n    }\n\n    cout << best_ops.size() << '\\n';\n    for (auto &op : best_ops) {\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\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\n    int N;\n    cin >> N;\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> A[i][j];\n        }\n    }\n\n    vector<string> ans(N);\n\n    // Crane 0 is the large crane.\n    // Small cranes are bombed immediately.\n    for (int i = 1; i < N; i++) {\n        ans[i].push_back('B');\n    }\n\n    int cr = 0, cc = 0; // current position of the large crane\n\n    auto add_move = [&](char c) {\n        ans[0].push_back(c);\n        if (c == 'U') cr--;\n        if (c == 'D') cr++;\n        if (c == 'L') cc--;\n        if (c == 'R') cc++;\n    };\n\n    auto move_to = [&](int tr, int tc) {\n        while (cr < tr) add_move('D');\n        while (cr > tr) add_move('U');\n        while (cc < tc) add_move('R');\n        while (cc > tc) add_move('L');\n    };\n\n    // First turn:\n    // - Receiving gates receive their first containers.\n    // - Large crane picks up the container at (0,0).\n    // - Small cranes are bombed.\n    //\n    // To keep the implementation simple, we process all containers uniformly.\n    // If the first operation is not at (0,0), we still output valid moves.\n    // Since all receiving gates are initially filled at the start of turn 0,\n    // picking from any receiving gate after moving there is valid.\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x = A[i][j];\n            int dest_row = x / N;\n\n            // Go to receiving gate (i,0)\n            move_to(i, 0);\n\n            // Pick the container\n            ans[0].push_back('P');\n\n            // Move to its correct dispatch gate\n            move_to(dest_row, N - 1);\n\n            // Release it. It is dispatched at the end of this turn.\n            ans[0].push_back('Q');\n        }\n    }\n\n    int L = ans[0].size();\n    for (int i = 1; i < N; i++) {\n        while ((int)ans[i].size() < L) ans[i].push_back('.');\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Result {\n    long long cost;\n    vector<string> ops;\n};\n\nint N;\nvector<vector<int>> H;\n\nvoid add_move(vector<string>& ops, long long& cost, long long load, int& r, int& c, int nr, int nc) {\n    while (r < nr) {\n        ops.push_back(\"D\");\n        cost += 100 + load;\n        r++;\n    }\n    while (r > nr) {\n        ops.push_back(\"U\");\n        cost += 100 + load;\n        r--;\n    }\n    while (c < nc) {\n        ops.push_back(\"R\");\n        cost += 100 + load;\n        c++;\n    }\n    while (c > nc) {\n        ops.push_back(\"L\");\n        cost += 100 + load;\n        c--;\n    }\n}\n\nResult simulate_path(const vector<pair<int,int>>& path) {\n    vector<vector<int>> h = H;\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n\n    auto process_cell = [&](int i, int j) {\n        if (h[i][j] > 0) {\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        } else if (h[i][j] < 0 && load > 0) {\n            int d = min<long long>(-h[i][j], load);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] += d;\n        }\n    };\n\n    // First pass.\n    for (auto [i,j] : path) {\n        add_move(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    // Second pass in reverse.\n    for (int idx = (int)path.size() - 1; idx >= 0; --idx) {\n        auto [i,j] = path[idx];\n        add_move(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    // In rare pathological case, repeat until complete.\n    // With total sum zero and positive loading allowed before unloading, this should finish.\n    for (int rep = 0; rep < 3; rep++) {\n        bool done = true;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (h[i][j] != 0) done = false;\n        if (done) break;\n\n        for (auto [i,j] : path) {\n            add_move(ops, cost, load, r, c, i, j);\n            process_cell(i, j);\n        }\n        for (int idx = (int)path.size() - 1; idx >= 0; --idx) {\n            auto [i,j] = path[idx];\n            add_move(ops, cost, load, r, c, i, j);\n            process_cell(i, j);\n        }\n    }\n\n    // Final safety: gather all remaining positives, then fill all remaining negatives.\n    for (auto [i,j] : path) {\n        if (h[i][j] > 0) {\n            add_move(ops, cost, load, r, c, i, j);\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        }\n    }\n    for (auto [i,j] : path) {\n        if (h[i][j] < 0) {\n            add_move(ops, cost, load, r, c, i, j);\n            int d = -h[i][j];\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] = 0;\n        }\n    }\n\n    return {cost, ops};\n}\n\nvector<pair<int,int>> row_snake() {\n    vector<pair<int,int>> p;\n    for (int i = 0; i < N; i++) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; j++) p.push_back({i,j});\n        } else {\n            for (int j = N-1; j >= 0; j--) p.push_back({i,j});\n        }\n    }\n    return p;\n}\n\nvector<pair<int,int>> col_snake() {\n    vector<pair<int,int>> p;\n    for (int j = 0; j < N; j++) {\n        if (j % 2 == 0) {\n            for (int i = 0; i < N; i++) p.push_back({i,j});\n        } else {\n            for (int i = N-1; i >= 0; i--) p.push_back({i,j});\n        }\n    }\n    return p;\n}\n\nvector<pair<int,int>> row_raster() {\n    vector<pair<int,int>> p;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> col_raster() {\n    vector<pair<int,int>> p;\n    for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) p.push_back({i,j});\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    H.assign(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> H[i][j];\n    }\n\n    vector<vector<pair<int,int>>> candidates;\n    candidates.push_back(row_snake());\n    candidates.push_back(col_snake());\n    candidates.push_back(row_raster());\n    candidates.push_back(col_raster());\n\n    int base_cnt = candidates.size();\n    for (int k = 0; k < base_cnt; k++) {\n        auto q = candidates[k];\n        reverse(q.begin(), q.end());\n        candidates.push_back(q);\n    }\n\n    Result best;\n    best.cost = (1LL << 60);\n\n    for (auto& p : candidates) {\n        Result res = simulate_path(p);\n        if ((int)res.ops.size() <= 100000 && res.cost < best.cost) {\n            best = move(res);\n        }\n    }\n\n    for (const string& s : best.ops) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    XorShift() {}\n    XorShift(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n    double rand01() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int S = 2 * N * (N - 1); // 60\n    const int C = N * N;           // 36\n\n    vector<vector<int>> X(S, vector<int>(M));\n    for (int i = 0; i < S; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    vector<pair<int,int>> edges;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (j + 1 < N) edges.push_back({id, id + 1});\n            if (i + 1 < N) edges.push_back({id, id + N});\n        }\n    }\n\n    vector<int> deg(C, 0);\n    for (auto [a,b] : edges) {\n        deg[a]++;\n        deg[b]++;\n    }\n\n    vector<int> cells(C);\n    iota(cells.begin(), cells.end(), 0);\n    sort(cells.begin(), cells.end(), [&](int a, int b) {\n        return deg[a] > deg[b];\n    });\n\n    auto start_time = chrono::steady_clock::now();\n    XorShift rng(1234567);\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> mx(M, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) mx[l] = max(mx[l], X[i][l]);\n        }\n\n        vector<int> sumv(S, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) sumv[i] += X[i][l];\n        }\n\n        vector<double> baseScore(S, 0);\n        for (int i = 0; i < S; i++) {\n            double sc = sumv[i];\n            double norm = 0;\n            double elite = 0;\n            for (int l = 0; l < M; l++) {\n                norm += 100.0 * X[i][l] / max(1, mx[l]);\n                if (X[i][l] >= mx[l] * 0.90) elite += 25.0;\n                if (X[i][l] == mx[l]) elite += 35.0;\n            }\n            baseScore[i] = sc + 0.75 * norm + elite;\n        }\n\n        vector<int> selected;\n        vector<int> used(S, 0);\n        vector<int> cover(M, 0);\n\n        // First choose several very high raw seeds.\n        vector<int> order(S);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return baseScore[a] > baseScore[b];\n        });\n\n        int initial_take = 8;\n        for (int z = 0; z < initial_take; z++) {\n            int id = order[z];\n            selected.push_back(id);\n            used[id] = 1;\n            for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[id][l]);\n        }\n\n        // Greedy diversity / coverage selection.\n        while ((int)selected.size() < C) {\n            int best = -1;\n            double bestScore = -1e100;\n            for (int i = 0; i < S; i++) if (!used[i]) {\n                double gain = 0;\n                for (int l = 0; l < M; l++) {\n                    int d = max(0, X[i][l] - cover[l]);\n                    gain += d * 8.0;\n                    gain += 1.5 * X[i][l] / max(1, mx[l]) * 100.0;\n                }\n                double sc = gain + 0.75 * baseScore[i];\n\n                // mild randomness to avoid repeated deterministic bad patterns\n                sc *= 0.98 + 0.04 * rng.rand01();\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    best = i;\n                }\n            }\n            used[best] = 1;\n            selected.push_back(best);\n            for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[best][l]);\n        }\n\n        // Sort selected by strength, assign stronger seeds to higher-degree cells.\n        sort(selected.begin(), selected.end(), [&](int a, int b) {\n            return baseScore[a] > baseScore[b];\n        });\n\n        vector<int> posSeed(C, -1);\n        for (int i = 0; i < C; i++) {\n            posSeed[cells[i]] = selected[i];\n        }\n\n        auto pairScore = [&](int a, int b) -> double {\n            double s = 0;\n            int va = sumv[a], vb = sumv[b];\n            s += 0.55 * (va + vb);\n\n            int maxsum = 0;\n            int absdiff = 0;\n            for (int l = 0; l < M; l++) {\n                maxsum += max(X[a][l], X[b][l]);\n                absdiff += abs(X[a][l] - X[b][l]);\n            }\n            s += 1.10 * maxsum;\n            s += 0.18 * absdiff;\n\n            // Encourage pair having at least one near-max in many dimensions.\n            int nearCnt = 0;\n            for (int l = 0; l < M; l++) {\n                if (max(X[a][l], X[b][l]) >= mx[l] * 0.88) nearCnt++;\n            }\n            s += 18.0 * nearCnt;\n\n            return s;\n        };\n\n        auto totalScore = [&]() -> double {\n            double s = 0;\n            for (auto [u,v] : edges) {\n                s += pairScore(posSeed[u], posSeed[v]);\n            }\n            return s;\n        };\n\n        double curScore = totalScore();\n\n        // Local search by swapping two cells.\n        int iterations = 35000;\n        for (int it = 0; it < iterations; it++) {\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            int a = rng.randint(C);\n            int b = rng.randint(C);\n            if (a == b) continue;\n\n            double before = 0, after = 0;\n            for (auto [u,v] : edges) {\n                if (u == a || u == b || v == a || v == b) {\n                    before += pairScore(posSeed[u], posSeed[v]);\n                }\n            }\n\n            swap(posSeed[a], posSeed[b]);\n\n            for (auto [u,v] : edges) {\n                if (u == a || u == b || v == a || v == b) {\n                    after += pairScore(posSeed[u], posSeed[v]);\n                }\n            }\n\n            double delta = after - before;\n            double temp = 30.0 * (1.0 - (double)it / iterations);\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else if (temp > 1e-9 && exp(delta / temp) > rng.rand01()) accept = true;\n\n            if (accept) {\n                curScore += delta;\n            } else {\n                swap(posSeed[a], posSeed[b]);\n            }\n        }\n\n        vector<vector<int>> A(N, vector<int>(N));\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                A[i][j] = posSeed[i * N + 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 << A[i][j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < S; i++) {\n            for (int j = 0; j < M; j++) cin >> X[i][j];\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\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    vector<Pos> src, dst;\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] == '0') src.push_back({i, j});\n            if (s[i][j] == '0' && t[i][j] == '1') dst.push_back({i, j});\n        }\n    }\n\n    int K = (int)src.size();\n\n    /*\n        Arm:\n          0 --1-- 1\n\n        vertex 0: root\n        vertex 1: fingertip\n    */\n    int Vp = 2;\n    int root_x = 0, root_y = 0;\n\n    // Direction of edge 0->1.\n    // 0:R, 1:D, 2:L, 3:U\n    int dir = 0;\n\n    const int dx[4] = {0, 1, 0, -1};\n    const int dy[4] = {1, 0, -1, 0};\n\n    auto inside = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    vector<string> ops;\n\n    auto add_op = [&](char mv, char rot, char act) {\n        string op(2 * Vp, '.');\n        op[0] = mv;\n        op[1] = rot;\n        op[2] = '.';\n        op[3] = act;\n\n        if (mv == 'U') root_x--;\n        if (mv == 'D') root_x++;\n        if (mv == 'L') root_y--;\n        if (mv == 'R') root_y++;\n\n        if (rot == 'L') dir = (dir + 3) % 4;\n        if (rot == 'R') dir = (dir + 1) % 4;\n\n        ops.push_back(op);\n    };\n\n    auto rotate_to = [&](int ndir) {\n        while (dir != ndir) {\n            int diff = (ndir - dir + 4) % 4;\n            if (diff == 1) {\n                add_op('.', 'R', '.');\n            } else if (diff == 3) {\n                add_op('.', 'L', '.');\n            } else {\n                add_op('.', 'R', '.');\n            }\n        }\n    };\n\n    /*\n        Move the root and rotate the arm so that the fingertip reaches target cell p.\n\n        Since the fingertip is at root + direction vector, we choose an adjacent\n        root position inside the board.\n    */\n    auto move_tip_to = [&](Pos p) {\n        int best_d = -1;\n        Pos best_root{-1, -1};\n        int best_cost = 1e9;\n\n        for (int d = 0; d < 4; d++) {\n            int rx = p.x - dx[d];\n            int ry = p.y - dy[d];\n            if (!inside(rx, ry)) continue;\n\n            int move_cost = abs(root_x - rx) + abs(root_y - ry);\n            int rot_diff = abs(d - dir);\n            int rot_cost = min(rot_diff, 4 - rot_diff);\n            int cost = move_cost + rot_cost;\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_d = d;\n                best_root = {rx, ry};\n            }\n        }\n\n        // Move root by Manhattan path.\n        while (root_x < best_root.x) add_op('D', '.', '.');\n        while (root_x > best_root.x) add_op('U', '.', '.');\n        while (root_y < best_root.y) add_op('R', '.', '.');\n        while (root_y > best_root.y) add_op('L', '.', '.');\n\n        rotate_to(best_d);\n    };\n\n    /*\n        Slight improvement:\n        greedily pair each source with a nearby destination.\n    */\n    vector<int> used_dst(K, 0);\n    vector<pair<Pos, Pos>> pairs;\n\n    for (int i = 0; i < K; i++) {\n        int best = -1;\n        int best_dist = 1e9;\n        for (int j = 0; j < K; j++) {\n            if (used_dst[j]) continue;\n            int dist = abs(src[i].x - dst[j].x) + abs(src[i].y - dst[j].y);\n            if (dist < best_dist) {\n                best_dist = dist;\n                best = j;\n            }\n        }\n        used_dst[best] = 1;\n        pairs.push_back({src[i], dst[best]});\n    }\n\n    /*\n        Further simple ordering:\n        process pairs in nearest-neighbor order based on current root/tip travel.\n    */\n    vector<int> used_pair(K, 0);\n    vector<pair<Pos, Pos>> ordered;\n\n    Pos cur_root{root_x, root_y};\n\n    for (int step = 0; step < K; step++) {\n        int best = -1;\n        int best_cost = 1e9;\n\n        for (int i = 0; i < K; i++) {\n            if (used_pair[i]) continue;\n\n            Pos a = pairs[i].first;\n            Pos b = pairs[i].second;\n\n            int cost = abs(cur_root.x - a.x) + abs(cur_root.y - a.y)\n                     + abs(a.x - b.x) + abs(a.y - b.y);\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best = i;\n            }\n        }\n\n        used_pair[best] = 1;\n        ordered.push_back(pairs[best]);\n        cur_root = pairs[best].second;\n    }\n\n    for (auto [a, b] : ordered) {\n        move_tip_to(a);\n        add_op('.', '.', 'P'); // pick\n\n        move_tip_to(b);\n        add_op('.', '.', 'P'); // place\n    }\n\n    /*\n        In rare pathological cases this simple strategy should still be far below\n        100000 turns for given constraints. But keep a safety truncation guard.\n        It is better not to truncate if possible, because unfinished solution gets\n        a large penalty. For N<=30, M<=450 this remains safe.\n    */\n\n    cout << Vp << '\\n';\n    cout << 0 << ' ' << 1 << '\\n';\n    cout << root_x * 0 << ' ' << root_y * 0 << '\\n';\n\n    for (const string &op : ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n    bool operator==(const Pt& o) const { return x == o.x && y == o.y; }\n};\n\nstruct Fish {\n    int x, y, t; // +1 mackerel, -1 sardine\n};\n\nstatic const int LIM = 100000;\nstatic const int N = 5000;\n\nlong long perimeter_poly(const vector<Pt>& p) {\n    int m = (int)p.size();\n    long long per = 0;\n    for (int i = 0; i < m; i++) {\n        Pt a = p[i], b = p[(i + 1) % m];\n        per += abs(a.x - b.x) + abs(a.y - b.y);\n    }\n    return per;\n}\n\nvector<Pt> simplify_poly(vector<Pt> p) {\n    if (p.empty()) return p;\n    vector<Pt> q;\n    for (auto v : p) {\n        if (!q.empty() && q.back() == v) continue;\n        q.push_back(v);\n    }\n    if (q.size() > 1 && q.front() == q.back()) q.pop_back();\n\n    bool changed = true;\n    while (changed && q.size() >= 4) {\n        changed = false;\n        vector<Pt> r;\n        int m = q.size();\n        for (int i = 0; i < m; i++) {\n            Pt a = q[(i - 1 + m) % m], b = q[i], c = q[(i + 1) % m];\n            long long dx1 = b.x - a.x, dy1 = b.y - a.y;\n            long long dx2 = c.x - b.x, dy2 = c.y - b.y;\n            if (dx1 * dy2 - dy1 * dx2 == 0) {\n                changed = true;\n            } else {\n                r.push_back(b);\n            }\n        }\n        q.swap(r);\n    }\n    return q;\n}\n\nbool inside_poly(const vector<Pt>& poly, int x, int y) {\n    int m = poly.size();\n    bool in = false;\n    for (int i = 0, j = m - 1; i < m; j = i++) {\n        Pt a = poly[j], b = poly[i];\n\n        // boundary check\n        if (a.x == b.x && x == a.x && min(a.y,b.y) <= y && y <= max(a.y,b.y)) return true;\n        if (a.y == b.y && y == a.y && min(a.x,b.x) <= x && x <= max(a.x,b.x)) return true;\n\n        bool cond = ((a.y > y) != (b.y > y));\n        if (cond) {\n            long double xin = (long double)(b.x - a.x) * (y - a.y) / (long double)(b.y - a.y) + a.x;\n            if (xin >= x) in = !in;\n        }\n    }\n    return in;\n}\n\nint eval_score_raw(const vector<Pt>& poly, const vector<Fish>& fishes) {\n    int s = 0;\n    for (auto &f : fishes) {\n        if (inside_poly(poly, f.x, f.y)) s += f.t;\n    }\n    return s;\n}\n\nbool legal_basic(const vector<Pt>& p) {\n    if ((int)p.size() < 4 || (int)p.size() > 1000) return false;\n    set<pair<int,int>> st;\n    for (auto &v : p) {\n        if (v.x < 0 || v.x > LIM || v.y < 0 || v.y > LIM) return false;\n        if (!st.insert({v.x,v.y}).second) return false;\n    }\n    for (int i = 0; i < (int)p.size(); i++) {\n        Pt a = p[i], b = p[(i+1)%p.size()];\n        if (!(a.x == b.x || a.y == b.y)) return false;\n    }\n    if (perimeter_poly(p) > 400000) return false;\n    return true;\n}\n\nstruct EdgeKey {\n    int x1,y1,x2,y2;\n};\n\nvector<Pt> boundary_from_component(const vector<pair<int,int>>& cells, int G, int W, int H) {\n    set<array<int,4>> edges;\n    auto add_edge = [&](int x1,int y1,int x2,int y2){\n        array<int,4> rev = {x2,y2,x1,y1};\n        auto it = edges.find(rev);\n        if (it != edges.end()) edges.erase(it);\n        else edges.insert({x1,y1,x2,y2});\n    };\n\n    for (auto [i,j] : cells) {\n        int x0 = i * G, x1 = min(LIM, (i+1)*G);\n        int y0 = j * G, y1 = min(LIM, (j+1)*G);\n        add_edge(x0,y0,x1,y0);\n        add_edge(x1,y0,x1,y1);\n        add_edge(x1,y1,x0,y1);\n        add_edge(x0,y1,x0,y0);\n    }\n\n    map<pair<int,int>, vector<pair<int,int>>> adj;\n    for (auto e : edges) {\n        adj[{e[0],e[1]}].push_back({e[2],e[3]});\n    }\n\n    vector<Pt> best;\n    set<array<int,4>> unused = edges;\n\n    while (!unused.empty()) {\n        auto e = *unused.begin();\n        int sx=e[0], sy=e[1], cx=e[2], cy=e[3];\n        unused.erase(e);\n        vector<Pt> cyc;\n        cyc.push_back({sx,sy});\n        cyc.push_back({cx,cy});\n\n        int px=sx, py=sy;\n        while (!(cx==sx && cy==sy)) {\n            auto &v = adj[{cx,cy}];\n            pair<int,int> nxt = {-1,-1};\n            for (auto to : v) {\n                array<int,4> ee = {cx,cy,to.first,to.second};\n                if (unused.count(ee)) {\n                    nxt = to;\n                    break;\n                }\n            }\n            if (nxt.first == -1) break;\n            array<int,4> ee = {cx,cy,nxt.first,nxt.second};\n            unused.erase(ee);\n            px = cx; py = cy;\n            cx = nxt.first; cy = nxt.second;\n            if (!(cx==sx && cy==sy)) cyc.push_back({cx,cy});\n            if (cyc.size() > 5000) break;\n        }\n\n        cyc = simplify_poly(cyc);\n        if (perimeter_poly(cyc) > perimeter_poly(best)) best = cyc;\n    }\n\n    return simplify_poly(best);\n}\n\nvector<vector<pair<int,int>>> get_components(const vector<vector<char>>& sel) {\n    int W = sel.size(), H = sel[0].size();\n    vector<vector<char>> vis(W, vector<char>(H, 0));\n    vector<vector<pair<int,int>>> comps;\n    int dx[4]={1,-1,0,0}, dy[4]={0,0,1,-1};\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if(sel[i][j]&&!vis[i][j]) {\n        vector<pair<int,int>> comp;\n        queue<pair<int,int>> q;\n        q.push({i,j}); vis[i][j]=1;\n        while(!q.empty()) {\n            auto [x,y]=q.front(); q.pop();\n            comp.push_back({x,y});\n            for(int d=0;d<4;d++) {\n                int nx=x+dx[d], ny=y+dy[d];\n                if(nx>=0&&nx<W&&ny>=0&&ny<H&&sel[nx][ny]&&!vis[nx][ny]) {\n                    vis[nx][ny]=1; q.push({nx,ny});\n                }\n            }\n        }\n        comps.push_back(comp);\n    }\n    return comps;\n}\n\nvector<Pt> rect_poly(int x1,int y1,int x2,int y2) {\n    x1=max(0,min(LIM,x1)); x2=max(0,min(LIM,x2));\n    y1=max(0,min(LIM,y1)); y2=max(0,min(LIM,y2));\n    if (x1>x2) swap(x1,x2);\n    if (y1>y2) swap(y1,y2);\n    if (x1==x2) x2=min(LIM,x1+1);\n    if (y1==y2) y2=min(LIM,y1+1);\n    return {{x1,y1},{x2,y1},{x2,y2},{x1,y2}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Fish> fishes;\n    fishes.reserve(2*n);\n    for (int i=0;i<2*n;i++) {\n        int x,y; cin >> x >> y;\n        fishes.push_back({x,y, i<n ? 1 : -1});\n    }\n\n    vector<Pt> best = rect_poly(0,0,1,1);\n    int bestVal = eval_score_raw(best, fishes);\n\n    vector<int> gridSizes = {800,1000,1250,1600,2000,2500};\n    vector<double> thresholds = {-0.4,-0.2,0.0,0.2,0.5,1.0,1.5,2.0};\n\n    for (int G : gridSizes) {\n        int W = (LIM + G) / G;\n        int H = (LIM + G) / G;\n        vector<vector<int>> diff(W, vector<int>(H,0));\n        for (auto &f : fishes) {\n            int ix = min(W-1, f.x / G);\n            int iy = min(H-1, f.y / G);\n            diff[ix][iy] += f.t;\n        }\n\n        vector<vector<double>> sm(W, vector<double>(H,0));\n        int wx[3][3]={{1,2,1},{2,4,2},{1,2,1}};\n        for(int i=0;i<W;i++) for(int j=0;j<H;j++) {\n            double s=0, ww=0;\n            for(int dx=-1;dx<=1;dx++) for(int dy=-1;dy<=1;dy++) {\n                int ni=i+dx,nj=j+dy;\n                if(ni>=0&&ni<W&&nj>=0&&nj<H) {\n                    int w=wx[dx+1][dy+1];\n                    s += w*diff[ni][nj];\n                    ww += w;\n                }\n            }\n            sm[i][j]=s/ww;\n        }\n\n        for (double th : thresholds) {\n            vector<vector<char>> sel(W, vector<char>(H,0));\n            for(int i=0;i<W;i++) for(int j=0;j<H;j++) {\n                if (sm[i][j] > th) sel[i][j]=1;\n            }\n\n            auto comps = get_components(sel);\n            sort(comps.begin(), comps.end(), [&](auto &a, auto &b){\n                int sa=0,sb=0;\n                for(auto [i,j]:a) sa+=diff[i][j];\n                for(auto [i,j]:b) sb+=diff[i][j];\n                return sa>sb;\n            });\n\n            int limitComps = min<int>(30, comps.size());\n            for(int ci=0; ci<limitComps; ci++) {\n                auto poly = boundary_from_component(comps[ci], G, W, H);\n                poly = simplify_poly(poly);\n                if (!legal_basic(poly)) continue;\n                int val = eval_score_raw(poly, fishes);\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = poly;\n                }\n            }\n        }\n    }\n\n    // Rectangle fallback / improvement around coordinate quantiles.\n    vector<int> xs={0,LIM}, ys={0,LIM};\n    for (auto &f:fishes) {\n        xs.push_back(max(0,f.x-1000));\n        xs.push_back(min(LIM,f.x+1000));\n        ys.push_back(max(0,f.y-1000));\n        ys.push_back(min(LIM,f.y+1000));\n    }\n    auto reduce_coords = [](vector<int> v) {\n        sort(v.begin(), v.end());\n        v.erase(unique(v.begin(), v.end()), v.end());\n        if ((int)v.size() <= 80) return v;\n        vector<int> r;\n        for (int k=0;k<80;k++) {\n            int idx = (long long)k*(v.size()-1)/79;\n            r.push_back(v[idx]);\n        }\n        sort(r.begin(), r.end());\n        r.erase(unique(r.begin(), r.end()), r.end());\n        return r;\n    };\n    xs = reduce_coords(xs);\n    ys = reduce_coords(ys);\n\n    for (int xi1=0; xi1<(int)xs.size(); xi1++) for (int xi2=xi1+1; xi2<(int)xs.size(); xi2++) {\n        int x1=xs[xi1], x2=xs[xi2];\n        if (2LL*(x2-x1) > 400000) continue;\n        vector<pair<int,int>> ev;\n        for (auto &f:fishes) if (x1<=f.x && f.x<=x2) ev.push_back({f.y,f.t});\n        sort(ev.begin(), ev.end());\n        for (int yi1=0; yi1<(int)ys.size(); yi1++) {\n            int cur=0;\n            for (int yi2=yi1+1; yi2<(int)ys.size(); yi2++) {\n                int y1=ys[yi1], y2=ys[yi2];\n                if (2LL*((x2-x1)+(y2-y1)) > 400000) continue;\n                int val=0;\n                for(auto &e:ev) if(y1<=e.first && e.first<=y2) val+=e.second;\n                if (val > bestVal) {\n                    auto p=rect_poly(x1,y1,x2,y2);\n                    if (legal_basic(p)) {\n                        bestVal=val;\n                        best=p;\n                    }\n                }\n            }\n        }\n    }\n\n    best = simplify_poly(best);\n    if (!legal_basic(best)) best = rect_poly(0,0,1,1);\n\n    cout << best.size() << \"\\n\";\n    for (auto &p : best) cout << p.x << \" \" << p.y << \"\\n\";\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    long long w, h;\n};\n\nstruct Op {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n\n    vector<Rect> a(N);\n    for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n    long double area = 0;\n    long long sumW = 0, sumH = 0;\n    for (auto &e : a) {\n        area += (long double)e.w * (long double)e.h;\n        sumW += e.w;\n        sumH += e.h;\n    }\n\n    auto make_layout = [&](int mode, int turn) {\n        vector<Op> ops;\n        ops.reserve(N);\n\n        vector<long long> ww(N), hh(N);\n        for (int i = 0; i < N; i++) {\n            long long w = a[i].w;\n            long long h = a[i].h;\n            int r = 0;\n\n            if (mode == 0) {\n                // Keep original.\n                r = 0;\n            } else if (mode == 1) {\n                // Taller-than-wide orientation for vertical shelves.\n                if (w > h) {\n                    swap(w, h);\n                    r = 1;\n                }\n            } else if (mode == 2) {\n                // Wider-than-tall orientation.\n                if (w < h) {\n                    swap(w, h);\n                    r = 1;\n                }\n            } else if (mode == 3) {\n                // Alternate.\n                if ((i + turn) & 1) {\n                    swap(w, h);\n                    r = 1;\n                }\n            } else {\n                // Balance local aspect with a deterministic pseudo-random choice.\n                uint32_t x = (uint32_t)(i * 1103515245u + turn * 12345u + mode * 998244353u);\n                if ((x >> 16) & 1) {\n                    swap(w, h);\n                    r = 1;\n                }\n            }\n\n            ww[i] = w;\n            hh[i] = h;\n        }\n\n        long double A = 0;\n        for (int i = 0; i < N; i++) A += (long double)ww[i] * hh[i];\n\n        int variant = turn % 17;\n        long double factor = 0.70L + 0.045L * variant;\n        long double targetH = sqrt(A) * factor;\n\n        if (turn % 5 == 0) targetH *= 0.85L;\n        if (turn % 7 == 0) targetH *= 1.18L;\n\n        int last_col_first = -1;\n        int prev = -1;\n        long double curH = 0;\n\n        for (int i = 0; i < N; i++) {\n            bool newCol = false;\n            if (i == 0) {\n                newCol = true;\n            } else {\n                long double projected = curH + hh[i];\n                if (curH > 0 && projected > targetH) {\n                    // Avoid making tiny columns unless very overflowing.\n                    long double over1 = fabsl(targetH - curH);\n                    long double over2 = fabsl(projected - targetH);\n                    if (over2 > over1 * 0.75L) newCol = true;\n                }\n            }\n\n            int r = 0;\n            if (mode == 0) r = 0;\n            else if (mode == 1) r = (a[i].w > a[i].h);\n            else if (mode == 2) r = (a[i].w < a[i].h);\n            else if (mode == 3) r = ((i + turn) & 1);\n            else {\n                uint32_t x = (uint32_t)(i * 1103515245u + turn * 12345u + mode * 998244353u);\n                r = ((x >> 16) & 1);\n            }\n\n            if (newCol) {\n                if (last_col_first == -1) {\n                    ops.push_back({i, r, 'U', -1});\n                } else {\n                    // Place new column to the right of previous column.\n                    ops.push_back({i, r, 'U', last_col_first});\n                }\n                last_col_first = i;\n                curH = hh[i];\n            } else {\n                // Stack below previous rectangle in same column.\n                ops.push_back({i, r, 'L', prev});\n                curH += hh[i];\n            }\n            prev = i;\n        }\n\n        return ops;\n    };\n\n    auto make_row_layout = [&](int mode, int turn) {\n        vector<Op> ops;\n        ops.reserve(N);\n\n        vector<long long> ww(N), hh(N);\n        vector<int> rr(N);\n\n        for (int i = 0; i < N; i++) {\n            long long w = a[i].w;\n            long long h = a[i].h;\n            int r = 0;\n\n            if (mode == 0) {\n                r = 0;\n            } else if (mode == 1) {\n                if (w < h) {\n                    swap(w, h);\n                    r = 1;\n                }\n            } else if (mode == 2) {\n                if (w > h) {\n                    swap(w, h);\n                    r = 1;\n                }\n            } else {\n                if ((i + turn) & 1) {\n                    swap(w, h);\n                    r = 1;\n                }\n            }\n\n            ww[i] = w;\n            hh[i] = h;\n            rr[i] = r;\n        }\n\n        long double A = 0;\n        for (int i = 0; i < N; i++) A += (long double)ww[i] * hh[i];\n\n        int variant = turn % 19;\n        long double factor = 0.70L + 0.04L * variant;\n        long double targetW = sqrt(A) * factor;\n\n        int first_in_row = -1;\n        int prev = -1;\n        long double curW = 0;\n\n        for (int i = 0; i < N; i++) {\n            bool newRow = false;\n            if (i == 0) {\n                newRow = true;\n            } else {\n                long double projected = curW + ww[i];\n                if (curW > 0 && projected > targetW) {\n                    long double over1 = fabsl(targetW - curW);\n                    long double over2 = fabsl(projected - targetW);\n                    if (over2 > over1 * 0.75L) newRow = true;\n                }\n            }\n\n            if (newRow) {\n                if (first_in_row == -1) {\n                    ops.push_back({i, rr[i], 'L', -1});\n                } else {\n                    // Place new row below previous row.\n                    ops.push_back({i, rr[i], 'L', first_in_row});\n                }\n                first_in_row = i;\n                curW = ww[i];\n            } else {\n                // Place to the right of previous rectangle in same row.\n                ops.push_back({i, rr[i], 'U', prev});\n                curW += ww[i];\n            }\n            prev = i;\n        }\n\n        return ops;\n    };\n\n    for (int t = 0; t < T; t++) {\n        vector<Op> ops;\n\n        if (t % 3 == 0) {\n            int mode = (t / 3) % 5;\n            ops = make_layout(mode, t);\n        } else if (t % 3 == 1) {\n            int mode = (t / 3) % 4;\n            ops = make_row_layout(mode, t);\n        } else {\n            int mode = (t / 3 + 1) % 5;\n            ops = make_layout(mode, t + 11);\n        }\n\n        cout << ops.size() << '\\n';\n        for (auto &op : ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        long long W, H;\n        cin >> W >> H;\n        if (!cin) return 0;\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 1000;\nstatic constexpr int H = 10;\n\nstruct Solver {\n    int n, m, h;\n    vector<int> A;\n    vector<vector<int>> g;\n    vector<pair<int,int>> xy;\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n    double TL = 1.90;\n\n    Solver() : rng(71236721) {}\n\n    double elapsed() {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    long long calcScore(const vector<int>& par) {\n        vector<vector<int>> ch(n);\n        vector<int> roots;\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -1) roots.push_back(v);\n            else ch[par[v]].push_back(v);\n        }\n        long long score = 1;\n        vector<int> dep(n, -1);\n        queue<int> q;\n        for (int r : roots) {\n            dep[r] = 0;\n            q.push(r);\n        }\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            score += 1LL * (dep[v] + 1) * A[v];\n            for (int to : ch[v]) {\n                dep[to] = dep[v] + 1;\n                q.push(to);\n            }\n        }\n        return score;\n    }\n\n    vector<int> allDistancesFrom(int s) {\n        vector<int> d(n, 1e9);\n        queue<int> q;\n        d[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (d[v] == H) continue;\n            for (int to : g[v]) {\n                if (d[to] > d[v] + 1) {\n                    d[to] = d[v] + 1;\n                    q.push(to);\n                }\n            }\n        }\n        return d;\n    }\n\n    vector<int> construct(double lowBias, double noise, bool randomOrder) {\n        vector<char> covered(n, 0), isRoot(n, 0);\n        vector<int> roots;\n        int coveredCnt = 0;\n\n        vector<vector<int>> reach(n);\n        for (int s = 0; s < n; s++) {\n            vector<int> d(n, -1);\n            queue<int> q;\n            d[s] = 0;\n            q.push(s);\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                reach[s].push_back(v);\n                if (d[v] == H) continue;\n                for (int to : g[v]) {\n                    if (d[to] == -1) {\n                        d[to] = d[v] + 1;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        while (coveredCnt < n) {\n            int best = -1;\n            double bestVal = -1e100;\n            vector<int> cand(n);\n            iota(cand.begin(), cand.end(), 0);\n            if (randomOrder) shuffle(cand.begin(), cand.end(), rng);\n\n            for (int v : cand) {\n                if (isRoot[v]) continue;\n                int gain = 0;\n                int gainW = 0;\n                for (int u : reach[v]) {\n                    if (!covered[u]) {\n                        gain++;\n                        gainW += A[u];\n                    }\n                }\n                if (gain == 0) continue;\n                double rnoise = noise * uniform_real_distribution<double>(-1.0, 1.0)(rng);\n                double val = gain * 1000.0 - lowBias * A[v] + 0.05 * gainW + rnoise;\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = v;\n                }\n            }\n\n            if (best == -1) {\n                for (int v = 0; v < n; v++) if (!covered[v]) {\n                    best = v;\n                    break;\n                }\n            }\n\n            roots.push_back(best);\n            isRoot[best] = 1;\n            for (int u : reach[best]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        vector<int> dist(n, 1e9), par(n, -2), owner(n, -1);\n        struct Node {\n            double key;\n            int v;\n            bool operator<(const Node& o) const { return key > o.key; }\n        };\n        priority_queue<Node> pq;\n\n        for (int r : roots) {\n            dist[r] = 0;\n            par[r] = -1;\n            owner[r] = r;\n            double key = 0.0 + 0.002 * A[r];\n            pq.push({key, r});\n        }\n\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int v = cur.v;\n            if (cur.key > dist[v] + 1000) {}\n            if (dist[v] == H) continue;\n\n            vector<int> ns = g[v];\n            shuffle(ns.begin(), ns.end(), rng);\n            for (int to : ns) {\n                if (dist[to] == 1e9) {\n                    dist[to] = dist[v] + 1;\n                    par[to] = v;\n                    owner[to] = owner[v];\n                    double key = dist[to] + 0.012 * (100 - A[to])\n                               + uniform_real_distribution<double>(0.0, 0.02)(rng);\n                    pq.push({key, to});\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) {\n                par[v] = -1;\n            }\n        }\n        return par;\n    }\n\n    vector<int> rerootTrees(const vector<int>& par0) {\n        vector<int> par = par0;\n        vector<vector<int>> treeAdj(n);\n        for (int v = 0; v < n; v++) {\n            if (par[v] != -1) {\n                treeAdj[v].push_back(par[v]);\n                treeAdj[par[v]].push_back(v);\n            }\n        }\n\n        vector<int> compId(n, -1);\n        vector<vector<int>> comps;\n        for (int s = 0; s < n; s++) if (compId[s] == -1) {\n            int id = comps.size();\n            comps.push_back({});\n            queue<int> q;\n            q.push(s);\n            compId[s] = id;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                comps.back().push_back(v);\n                for (int to : treeAdj[v]) {\n                    if (compId[to] == -1) {\n                        compId[to] = id;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        vector<int> newPar(n, -2);\n\n        for (auto &comp : comps) {\n            int bestRoot = comp[0];\n            long long bestVal = LLONG_MIN;\n            vector<int> bestDist;\n\n            for (int r : comp) {\n                unordered_map<int,int> dummy;\n                vector<int> d(n, -1);\n                queue<int> q;\n                d[r] = 0;\n                q.push(r);\n                int mx = 0;\n                long long val = 0;\n                while (!q.empty()) {\n                    int v = q.front(); q.pop();\n                    mx = max(mx, d[v]);\n                    val += 1LL * (d[v] + 1) * A[v];\n                    for (int to : treeAdj[v]) {\n                        if (d[to] == -1) {\n                            d[to] = d[v] + 1;\n                            q.push(to);\n                        }\n                    }\n                }\n                if (mx <= H && val > bestVal) {\n                    bestVal = val;\n                    bestRoot = r;\n                    bestDist.swap(d);\n                }\n            }\n\n            queue<int> q;\n            vector<int> seen(n, 0);\n            newPar[bestRoot] = -1;\n            seen[bestRoot] = 1;\n            q.push(bestRoot);\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                for (int to : treeAdj[v]) {\n                    if (!seen[to]) {\n                        seen[to] = 1;\n                        newPar[to] = v;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (newPar[v] == -2) newPar[v] = -1;\n        }\n        return newPar;\n    }\n\n    void solve() {\n        cin >> n >> m >> h;\n        A.resize(n);\n        for (int i = 0; i < n; i++) cin >> A[i];\n        g.assign(n, {});\n        for (int i = 0; i < m; i++) {\n            int u, v;\n            cin >> u >> v;\n            g[u].push_back(v);\n            g[v].push_back(u);\n        }\n        xy.resize(n);\n        for (int i = 0; i < n; i++) cin >> xy[i].first >> xy[i].second;\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestPar(n, -1);\n        long long bestScore = -1;\n\n        int iter = 0;\n        while (elapsed() < TL) {\n            double lowBias = 5.0 + (iter % 10) * 8.0;\n            double noise = 100.0 + (iter % 7) * 300.0;\n            bool ro = (iter % 2);\n\n            vector<int> par = construct(lowBias, noise, ro);\n            par = rerootTrees(par);\n            long long sc = calcScore(par);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPar = par;\n            }\n            iter++;\n        }\n\n        for (int i = 0; i < n; i++) {\n            if (i) cout << ' ';\n            cout << bestPar[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc042":"#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    cin >> N;\n    vector<string> board(N);\n    for (int i = 0; i < N; i++) cin >> board[i];\n\n    vector<pair<char,int>> ans;\n\n    auto oni_count = [&]() {\n        int c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (board[i][j] == 'x') c++;\n            }\n        }\n        return c;\n    };\n\n    while (oni_count() > 0) {\n        struct Cand {\n            int cost;\n            int removed;\n            char dir;\n            int p;\n            int k;\n            vector<pair<int,int>> cells;\n        };\n\n        Cand best;\n        best.cost = 1e9;\n        best.removed = -1;\n\n        auto update = [&](Cand c) {\n            if (c.removed <= 0) return;\n\n            // Prefer better efficiency, then fewer moves.\n            long long lhs = 1LL * c.removed * best.cost;\n            long long rhs = 1LL * best.removed * c.cost;\n\n            if (best.removed == -1 || lhs > rhs ||\n                (lhs == rhs && c.cost < best.cost) ||\n                (lhs == rhs && c.cost == best.cost && c.removed > best.removed)) {\n                best = c;\n            }\n        };\n\n        // Upward cycles.\n        for (int j = 0; j < N; j++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int i = 0; i < N; i++) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (i + 1);\n                    c.removed = removed;\n                    c.dir = 'U';\n                    c.p = j;\n                    c.k = i + 1;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // Downward cycles.\n        for (int j = 0; j < N; j++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int i = N - 1; i >= 0; i--) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (N - i);\n                    c.removed = removed;\n                    c.dir = 'D';\n                    c.p = j;\n                    c.k = N - i;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // Left cycles.\n        for (int i = 0; i < N; i++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int j = 0; j < N; j++) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (j + 1);\n                    c.removed = removed;\n                    c.dir = 'L';\n                    c.p = i;\n                    c.k = j + 1;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // Right cycles.\n        for (int i = 0; i < N; i++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int j = N - 1; j >= 0; j--) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (N - j);\n                    c.removed = removed;\n                    c.dir = 'R';\n                    c.p = i;\n                    c.k = N - j;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // The input guarantee ensures this should never fail.\n        if (best.removed <= 0) break;\n\n        for (auto [i, j] : best.cells) {\n            if (board[i][j] == 'x') board[i][j] = '.';\n        }\n\n        char rev;\n        if (best.dir == 'U') rev = 'D';\n        else if (best.dir == 'D') rev = 'U';\n        else if (best.dir == 'L') rev = 'R';\n        else rev = 'L';\n\n        for (int t = 0; t < best.k; t++) ans.push_back({best.dir, best.p});\n        for (int t = 0; t < best.k; t++) ans.push_back({rev, best.p});\n    }\n\n    // Guaranteed by the simple construction: at most 40 Oni * 40 moves = 1600.\n    // Still, avoid illegal output just in case.\n    if ((int)ans.size() > 4 * N * N) {\n        ans.resize(4 * N * N);\n    }\n\n    for (auto [d, p] : ans) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 100;\nstatic const int L = 500000;\n\nstruct Plan {\n    int a[N], b[N];\n};\n\nint eval_plan(const Plan& p, const vector<int>& T) {\n    static int cnt[N];\n\n    for (int i = 0; i < N; i++) cnt[i] = 0;\n\n    int x = 0;\n    for (int week = 0; week < L; week++) {\n        cnt[x]++;\n        if (cnt[x] & 1) x = p.a[x];\n        else x = p.b[x];\n    }\n\n    int err = 0;\n    for (int i = 0; i < N; i++) {\n        err += abs(cnt[i] - T[i]);\n    }\n    return err;\n}\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 88172645463325252ull) : x(seed) {}\n\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint sample_weighted(const vector<int>& pref, RNG& rng) {\n    int v = rng.next_int(1, L);\n    int id = lower_bound(pref.begin(), pref.end(), v) - pref.begin();\n    if (id >= N) id = N - 1;\n    return id;\n}\n\nPlan random_plan(const vector<int>& pref, RNG& rng) {\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        p.a[i] = sample_weighted(pref, rng);\n        p.b[i] = sample_weighted(pref, rng);\n    }\n    return p;\n}\n\nPlan quota_plan(const vector<int>& T, RNG& rng) {\n    vector<double> rem(N);\n    vector<int> q(N, 0);\n\n    int sumq = 0;\n    for (int i = 0; i < N; i++) {\n        double exact = 200.0 * T[i] / L;\n        q[i] = (int)floor(exact);\n        rem[i] = exact - q[i];\n        sumq += q[i];\n    }\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        return rem[x] > rem[y];\n    });\n\n    for (int k = 0; sumq < 200; k++, sumq++) {\n        q[ord[k % N]]++;\n    }\n\n    vector<int> edges;\n    edges.reserve(200);\n    for (int i = 0; i < N; i++) {\n        for (int c = 0; c < q[i]; c++) edges.push_back(i);\n    }\n\n    while ((int)edges.size() < 200) {\n        edges.push_back(rng.next_int(0, N - 1));\n    }\n\n    shuffle(edges.begin(), edges.end(), std::mt19937((uint32_t)rng.next_u64()));\n\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        p.a[i] = edges[2 * i];\n        p.b[i] = edges[2 * i + 1];\n    }\n    return p;\n}\n\nPlan mutate_plan(const Plan& base, const vector<int>& pref, RNG& rng, int changes) {\n    Plan p = base;\n    for (int k = 0; k < changes; k++) {\n        int i = rng.next_int(0, N - 1);\n        int side = rng.next_int(0, 1);\n        int to = sample_weighted(pref, rng);\n        if (side == 0) p.a[i] = to;\n        else p.b[i] = to;\n    }\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n\n    vector<int> T(N);\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    vector<int> pref(N);\n    for (int i = 0; i < N; i++) {\n        pref[i] = T[i] + (i ? pref[i - 1] : 0);\n    }\n\n    RNG rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    Plan best;\n    for (int i = 0; i < N; i++) {\n        best.a[i] = best.b[i] = 0;\n    }\n\n    int best_err = eval_plan(best, T);\n\n    auto start = chrono::steady_clock::now();\n\n    int iter = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 1.88) break;\n\n        Plan cand;\n\n        if (iter % 5 == 0) {\n            cand = quota_plan(T, rng);\n        } else if (iter % 5 == 1 && best_err < L) {\n            int changes = 1 + (iter % 7);\n            cand = mutate_plan(best, pref, rng, changes);\n        } else {\n            cand = random_plan(pref, rng);\n        }\n\n        int err = eval_plan(cand, T);\n\n        if (err < best_err) {\n            best_err = err;\n            best = cand;\n        }\n\n        iter++;\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#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) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while ( p[x] != x ) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    bool operator<(const Edge& other) const {\n        if (w != other.w) return w < other.w;\n        if (u != other.u) return u < other.u;\n        return v < other.v;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<double> x(N), y(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        x[i] = (lx[i] + rx[i]) * 0.5;\n        y[i] = (ly[i] + ry[i]) * 0.5;\n    }\n\n    auto dist2 = [&](int a, int b) -> long long {\n        long long dx = llround(x[a] - x[b]);\n        long long dy = llround(y[a] - y[b]);\n        return dx * dx + dy * dy;\n    };\n\n    auto distApprox = [&](int a, int b) -> long long {\n        double dx = x[a] - x[b];\n        double dy = y[a] - y[b];\n        return (long long)(sqrt(dx * dx + dy * dy));\n    };\n\n    // Sort groups by descending size for assignment.\n    vector<int> ordG(M);\n    iota(ordG.begin(), ordG.end(), 0);\n    sort(ordG.begin(), ordG.end(), [&](int a, int b) {\n        return G[a] > G[b];\n    });\n\n    // City order by space-filling-ish key.\n    vector<int> cities(N);\n    iota(cities.begin(), cities.end(), 0);\n\n    // Use Morton-like coarse ordering, with fallback to x/y.\n    auto morton_key = [&](int i) -> long long {\n        int xi = max(0, min(10000, (int)x[i]));\n        int yi = max(0, min(10000, (int)y[i]));\n        long long key = 0;\n        for (int b = 0; b < 14; b++) {\n            key |= ((long long)((xi >> b) & 1)) << (2 * b);\n            key |= ((long long)((yi >> b) & 1)) << (2 * b + 1);\n        }\n        return key;\n    };\n\n    sort(cities.begin(), cities.end(), [&](int a, int b) {\n        long long ka = morton_key(a), kb = morton_key(b);\n        if (ka != kb) return ka < kb;\n        if (x[a] != x[b]) return x[a] < x[b];\n        return y[a] < y[b];\n    });\n\n    vector<vector<int>> groups(M);\n    vector<int> used(N, 0);\n\n    // Initial partition along Morton order according to original G order.\n    int ptr = 0;\n    for (int k = 0; k < M; k++) {\n        for (int t = 0; t < G[k]; t++) groups[k].push_back(cities[ptr++]);\n    }\n\n    // Light local improvement: try swapping boundary cities between adjacent groups\n    // in Morton order if it improves approximate compactness.\n    auto groupCost = [&](const vector<int>& v) -> double {\n        if (v.size() <= 1) return 0.0;\n        double cx = 0, cy = 0;\n        for (int id : v) {\n            cx += x[id];\n            cy += y[id];\n        }\n        cx /= v.size();\n        cy /= v.size();\n        double s = 0;\n        for (int id : v) {\n            double dx = x[id] - cx;\n            double dy = y[id] - cy;\n            s += sqrt(dx * dx + dy * dy);\n        }\n        return s;\n    };\n\n    for (int it = 0; it < 2; it++) {\n        for (int k = 0; k + 1 < M; k++) {\n            if (groups[k].empty() || groups[k + 1].empty()) continue;\n\n            double base = groupCost(groups[k]) + groupCost(groups[k + 1]);\n            int bestA = -1, bestB = -1;\n            double bestDelta = 0;\n\n            int ak0 = max(0, (int)groups[k].size() - 5);\n            int bk1 = min(5, (int)groups[k + 1].size());\n\n            for (int ia = ak0; ia < (int)groups[k].size(); ia++) {\n                for (int ib = 0; ib < bk1; ib++) {\n                    swap(groups[k][ia], groups[k + 1][ib]);\n                    double nc = groupCost(groups[k]) + groupCost(groups[k + 1]);\n                    double delta = nc - base;\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestA = ia;\n                        bestB = ib;\n                    }\n                    swap(groups[k][ia], groups[k + 1][ib]);\n                }\n            }\n\n            if (bestA != -1) {\n                swap(groups[k][bestA], groups[k + 1][bestB]);\n            }\n        }\n    }\n\n    // Sort inside each group spatially.\n    for (int k = 0; k < M; k++) {\n        sort(groups[k].begin(), groups[k].end(), [&](int a, int b) {\n            if (x[a] != x[b]) return x[a] < x[b];\n            return y[a] < y[b];\n        });\n    }\n\n    vector<vector<pair<int,int>>> queriedEdges(M);\n    int qcnt = 0;\n\n    auto query = [&](const vector<int>& c) -> vector<pair<int,int>> {\n        cout << \"? \" << c.size();\n        for (int v : c) cout << ' ' << v;\n        cout << endl;\n        cout.flush();\n\n        vector<pair<int,int>> ret;\n        for (int i = 0; i < (int)c.size() - 1; i++) {\n            int a, b;\n            cin >> a >> b;\n            if (a > b) swap(a, b);\n            ret.push_back({a, b});\n        }\n        return ret;\n    };\n\n    // Query strategy.\n    // 1. Whole small groups first.\n    vector<int> groupQueryOrder(M);\n    iota(groupQueryOrder.begin(), groupQueryOrder.end(), 0);\n    sort(groupQueryOrder.begin(), groupQueryOrder.end(), [&](int a, int b) {\n        if (G[a] <= L && G[b] > L) return true;\n        if (G[a] > L && G[b] <= L) return false;\n        return G[a] < G[b];\n    });\n\n    vector<int> wholeQueried(M, 0);\n    for (int k : groupQueryOrder) {\n        if (qcnt >= Q) break;\n        if (G[k] >= 2 && G[k] <= L) {\n            auto ret = query(groups[k]);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            wholeQueried[k] = 1;\n        }\n    }\n\n    // 2. For larger groups, query local chunks of size L.\n    for (int k = 0; k < M && qcnt < Q; k++) {\n        if (wholeQueried[k]) continue;\n        int s = groups[k].size();\n        if (s < 2) continue;\n\n        if (s <= L) {\n            auto ret = query(groups[k]);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            continue;\n        }\n\n        int step = max(2, L - 1);\n        for (int st = 0; st < s && qcnt < Q; st += step) {\n            int en = min(s, st + L);\n            if (en - st < 2) break;\n            vector<int> c;\n            for (int i = st; i < en; i++) c.push_back(groups[k][i]);\n            auto ret = query(c);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            if (en == s) break;\n        }\n    }\n\n    // If queries remain, query sliding neighborhoods in large groups.\n    for (int k = 0; k < M && qcnt < Q; k++) {\n        int s = groups[k].size();\n        if (s <= L || s < 2) continue;\n        int stride = max(1, L / 2);\n        for (int st = stride; st + 1 < s && qcnt < Q; st += stride) {\n            int from = max(0, st - L / 2);\n            int to = min(s, from + L);\n            from = max(0, to - L);\n            if (to - from < 2) continue;\n            vector<int> c;\n            for (int i = from; i < to; i++) c.push_back(groups[k][i]);\n            auto ret = query(c);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n        }\n    }\n\n    // Final answer construction.\n    vector<vector<pair<int,int>>> answerEdges(M);\n\n    for (int k = 0; k < M; k++) {\n        int s = groups[k].size();\n        if (s <= 1) {\n            continue;\n        }\n\n        unordered_map<int,int> pos;\n        pos.reserve(s * 2);\n        for (int i = 0; i < s; i++) pos[groups[k][i]] = i;\n\n        vector<Edge> cand;\n\n        // Queried edges get strong preference, because they are true MST edges\n        // in some local subset.\n        set<pair<int,int>> seen;\n        for (auto [a, b] : queriedEdges[k]) {\n            if (!pos.count(a) || !pos.count(b)) continue;\n            if (a > b) swap(a, b);\n            if (seen.insert({a, b}).second) {\n                cand.push_back({a, b, distApprox(a, b) - 1000000000LL});\n            }\n        }\n\n        // Add k-nearest approximate candidates inside group.\n        int K = min(s - 1, 12);\n        for (int ii = 0; ii < s; ii++) {\n            int a = groups[k][ii];\n            vector<pair<long long,int>> nb;\n            nb.reserve(s - 1);\n            for (int jj = 0; jj < s; jj++) if (ii != jj) {\n                int b = groups[k][jj];\n                nb.push_back({dist2(a, b), b});\n            }\n            nth_element(nb.begin(), nb.begin() + K, nb.end());\n            nb.resize(K);\n            for (auto [d2, b] : nb) {\n                int u = min(a, b), v = max(a, b);\n                if (seen.insert({u, v}).second) {\n                    cand.push_back({u, v, distApprox(u, v)});\n                }\n            }\n        }\n\n        // Add chain edges as guaranteed connectivity fallback.\n        for (int i = 0; i + 1 < s; i++) {\n            int a = groups[k][i], b = groups[k][i + 1];\n            int u = min(a, b), v = max(a, b);\n            if (seen.insert({u, v}).second) {\n                cand.push_back({u, v, distApprox(u, v) + 1000000LL});\n            }\n        }\n\n        sort(cand.begin(), cand.end());\n\n        DSU dsu(N);\n        for (auto &e : cand) {\n            if ((int)answerEdges[k].size() == s - 1) break;\n            if (dsu.unite(e.u, e.v)) {\n                answerEdges[k].push_back({e.u, e.v});\n            }\n        }\n\n        // Absolute fallback if somehow disconnected.\n        for (int i = 0; i + 1 < s && (int)answerEdges[k].size() < s - 1; i++) {\n            int a = groups[k][i], b = groups[k][i + 1];\n            if (dsu.unite(a, b)) answerEdges[k].push_back({a, b});\n        }\n    }\n\n    cout << \"!\" << '\\n';\n    for (int k = 0; k < M; k++) {\n        for (int i = 0; i < (int)groups[k].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[k][i];\n        }\n        cout << '\\n';\n\n        for (auto [a, b] : answerEdges[k]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Action {\n    char a, d;\n};\n\nstruct Prev {\n    int pi, pj;\n    Action act;\n    bool used = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    vector<pair<int,int>> p(M);\n    for (int i = 0; i < M; i++) {\n        cin >> p[i].first >> p[i].second;\n    }\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    vector<Action> answer;\n\n    for (int t = 0; t + 1 < M; t++) {\n        auto [si, sj] = p[t];\n        auto [gi, gj] = p[t + 1];\n\n        vector<vector<int>> dist(N, vector<int>(N, -1));\n        vector<vector<Prev>> prv(N, vector<Prev>(N));\n\n        queue<pair<int,int>> q;\n        dist[si][sj] = 0;\n        q.push({si, sj});\n\n        while (!q.empty()) {\n            auto [i, j] = q.front();\n            q.pop();\n\n            if (i == gi && j == gj) break;\n\n            for (int dir = 0; dir < 4; dir++) {\n                // Move\n                {\n                    int ni = i + di[dir];\n                    int nj = j + dj[dir];\n                    if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                        if (dist[ni][nj] == -1) {\n                            dist[ni][nj] = dist[i][j] + 1;\n                            prv[ni][nj] = {i, j, {'M', dc[dir]}, true};\n                            q.push({ni, nj});\n                        }\n                    }\n                }\n\n                // Slide: since there are no internal blocks, this goes to the border.\n                {\n                    int ni = i;\n                    int nj = j;\n                    while (true) {\n                        int ti = ni + di[dir];\n                        int tj = nj + dj[dir];\n                        if (ti < 0 || ti >= N || tj < 0 || tj >= N) break;\n                        ni = ti;\n                        nj = tj;\n                    }\n\n                    if (ni != i || nj != j) {\n                        if (dist[ni][nj] == -1) {\n                            dist[ni][nj] = dist[i][j] + 1;\n                            prv[ni][nj] = {i, j, {'S', dc[dir]}, true};\n                            q.push({ni, nj});\n                        }\n                    }\n                }\n            }\n        }\n\n        vector<Action> path;\n        int ci = gi, cj = gj;\n\n        while (!(ci == si && cj == sj)) {\n            Prev pr = prv[ci][cj];\n            path.push_back(pr.act);\n            ci = pr.pi;\n            cj = pr.pj;\n        }\n\n        reverse(path.begin(), path.end());\n        for (auto a : path) answer.push_back(a);\n    }\n\n    // The limit is 2*N*M = 1600. This strategy should be far below it.\n    int limit = 2 * N * M;\n    if ((int)answer.size() > limit) {\n        answer.resize(limit);\n    }\n\n    for (auto [a, d] : answer) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Input {\n    int n;\n    vector<int> x, y;\n    vector<long long> r;\n};\n\nstatic constexpr int W = 10000;\nstatic constexpr double TIME_LIMIT = 4.85;\n\nchrono::steady_clock::time_point start_time;\n\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nlong long area(const Rect& e) {\n    return 1LL * (e.c - e.a) * (e.d - e.b);\n}\n\nbool overlap_interval(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\ndouble rect_score(long long s, long long r) {\n    double mn = (double)min(s, r);\n    double mx = (double)max(s, r);\n    double q = mn / mx;\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble total_score(const vector<Rect>& rects, const Input& in) {\n    double res = 0;\n    for (int i = 0; i < in.n; i++) {\n        res += rect_score(area(rects[i]), in.r[i]);\n    }\n    return res;\n}\n\nbool contains_point_after_shrink(const Rect& r, int x, int y) {\n    return r.a <= x && x < r.c && r.b <= y && y < r.d;\n}\n\nint max_expand_dir(const vector<Rect>& rects, int idx, int dir) {\n    const Rect& cur = rects[idx];\n    int n = rects.size();\n\n    if (dir == 0) {\n        int lim = cur.a;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.c <= cur.a) {\n                lim = min(lim, cur.a - o.c);\n            }\n        }\n        return lim;\n    } else if (dir == 1) {\n        int lim = W - cur.c;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.a >= cur.c) {\n                lim = min(lim, o.a - cur.c);\n            }\n        }\n        return lim;\n    } else if (dir == 2) {\n        int lim = cur.b;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.d <= cur.b) {\n                lim = min(lim, cur.b - o.d);\n            }\n        }\n        return lim;\n    } else {\n        int lim = W - cur.d;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.b >= cur.d) {\n                lim = min(lim, o.b - cur.d);\n            }\n        }\n        return lim;\n    }\n}\n\nRect expanded(Rect r, int dir, int delta) {\n    if (dir == 0) r.a -= delta;\n    else if (dir == 1) r.c += delta;\n    else if (dir == 2) r.b -= delta;\n    else r.d += delta;\n    return r;\n}\n\nRect shrunk(Rect r, int dir, int delta) {\n    if (dir == 0) r.a += delta;\n    else if (dir == 1) r.c -= delta;\n    else if (dir == 2) r.b += delta;\n    else r.d -= delta;\n    return r;\n}\n\nbool valid_rect_for_point(const Rect& r, int x, int y) {\n    return r.a <= x && x < r.c && r.b <= y && y < r.d && r.a < r.c && r.b < r.d;\n}\n\nvector<int> candidate_deltas(int mx, long long cur_area, long long target, int len) {\n    vector<int> cand;\n    if (mx <= 0) return cand;\n\n    cand.push_back(1);\n    cand.push_back(mx);\n\n    long long need = target - cur_area;\n\n    if (need != 0) {\n        long long ab = llabs(need);\n        long long f = ab / len;\n        long long c = (ab + len - 1) / len;\n\n        for (long long v : {f - 2, f - 1, f, f + 1, f + 2,\n                            c - 2, c - 1, c, c + 1, c + 2}) {\n            if (1 <= v && v <= mx) cand.push_back((int)v);\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    return cand;\n}\n\nvoid greedy_expand(vector<Rect>& rects, const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int stagnate = 0;\n\n    while (elapsed() < TIME_LIMIT && stagnate < 35) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-15;\n\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1)\n                    ? rects[id].d - rects[id].b\n                    : rects[id].c - rects[id].a;\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    gain += 1e-13 * delta;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_dir != -1) {\n                rects[id] = expanded(rects[id], best_dir, best_delta);\n                changed = true;\n            }\n        }\n\n        if (changed) stagnate = 0;\n        else stagnate++;\n    }\n}\n\nvoid local_refine(vector<Rect>& rects, const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int loop = 0;\n\n    while (elapsed() < TIME_LIMIT && loop < 300) {\n        loop++;\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_type = -1; // 0 expand, 1 shrink\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-14;\n\n            // Expansion moves\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1)\n                    ? rects[id].d - rects[id].b\n                    : rects[id].c - rects[id].a;\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 0;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            // Shrink moves\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = 0;\n\n                if (dir == 0) {\n                    mx = in.x[id] - rects[id].a;\n                } else if (dir == 1) {\n                    mx = rects[id].c - (in.x[id] + 1);\n                } else if (dir == 2) {\n                    mx = in.y[id] - rects[id].b;\n                } else {\n                    mx = rects[id].d - (in.y[id] + 1);\n                }\n\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1)\n                    ? rects[id].d - rects[id].b\n                    : rects[id].c - rects[id].a;\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = shrunk(rects[id], dir, delta);\n                    if (!valid_rect_for_point(nr, in.x[id], in.y[id])) continue;\n\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 1;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_type != -1) {\n                if (best_type == 0) {\n                    rects[id] = expanded(rects[id], best_dir, best_delta);\n                } else {\n                    rects[id] = shrunk(rects[id], best_dir, best_delta);\n                }\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n}\n\nvector<Rect> solve_once(const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<Rect> rects(n);\n\n    for (int i = 0; i < n; i++) {\n        rects[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n    }\n\n    greedy_expand(rects, in, rng);\n    local_refine(rects, in, rng);\n\n    return rects;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    Input in;\n    cin >> in.n;\n    in.x.resize(in.n);\n    in.y.resize(in.n);\n    in.r.resize(in.n);\n\n    for (int i = 0; i < in.n; i++) {\n        cin >> in.x[i] >> in.y[i] >> in.r[i];\n    }\n\n    mt19937 rng(1234567);\n\n    vector<Rect> best;\n    double best_score = -1.0;\n\n    int trials = 0;\n\n    while (elapsed() < TIME_LIMIT) {\n        auto rects = solve_once(in, rng);\n        double sc = total_score(rects, in);\n\n        if (sc > best_score) {\n            best_score = sc;\n            best = rects;\n        }\n\n        trials++;\n    }\n\n    if (best.empty()) {\n        best.resize(in.n);\n        for (int i = 0; i < in.n; i++) {\n            best[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n        }\n    }\n\n    for (int i = 0; i < in.n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' '\n             << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr double TIME_LIMIT = 1.90;\n\nint si, sj;\nint tile_id[N][N];\nint pval[N][N];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) {\n        return (int)(next() % n);\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nbool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tile = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> tile_id[i][j];\n            max_tile = max(max_tile, tile_id[i][j]);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> pval[i][j];\n        }\n    }\n\n    int M = max_tile + 1;\n\n    Timer timer;\n    XorShift rng;\n\n    string best_path;\n    int best_score = pval[si][sj];\n\n    vector<int> visited(M, 0);\n    vector<pair<int,int>> cells;\n    vector<char> path;\n\n    int iter = 0;\n\n    while (timer.elapsed() < TIME_LIMIT) {\n        iter++;\n\n        fill(visited.begin(), visited.end(), 0);\n        cells.clear();\n        path.clear();\n\n        int ci = si;\n        int cj = sj;\n        int score = pval[ci][cj];\n\n        visited[tile_id[ci][cj]] = 1;\n        cells.emplace_back(ci, cj);\n\n        // Randomized parameters for this rollout\n        int mode = rng.next_int(5);\n\n        int w_deg;\n        int w_near;\n        int noise;\n\n        if (mode == 0) {\n            // score-oriented\n            w_deg = 12;\n            w_near = 2;\n            noise = 180;\n        } else if (mode == 1) {\n            // avoid dead ends\n            w_deg = 35;\n            w_near = 2;\n            noise = 120;\n        } else if (mode == 2) {\n            // Warnsdorff-like: sometimes go into narrow areas first\n            w_deg = -25;\n            w_near = 1;\n            noise = 120;\n        } else if (mode == 3) {\n            // balanced\n            w_deg = 20;\n            w_near = 4;\n            noise = 160;\n        } else {\n            // more random exploration\n            w_deg = 8;\n            w_near = 1;\n            noise = 350;\n        }\n\n        while (true) {\n            struct Cand {\n                int dir;\n                int ni, nj;\n                int eval;\n            };\n\n            vector<Cand> cand;\n\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n\n                if (!inside(ni, nj)) continue;\n\n                int tid = tile_id[ni][nj];\n                if (visited[tid]) continue;\n\n                visited[tid] = 1;\n\n                int deg = 0;\n                int near_score = 0;\n\n                for (int e = 0; e < 4; e++) {\n                    int xi = ni + di[e];\n                    int xj = nj + dj[e];\n\n                    if (!inside(xi, xj)) continue;\n\n                    int nt = tile_id[xi][xj];\n                    if (!visited[nt]) {\n                        deg++;\n                        near_score += pval[xi][xj];\n                    }\n                }\n\n                visited[tid] = 0;\n\n                int eval = pval[ni][nj] * 100\n                         + w_deg * deg\n                         + w_near * near_score\n                         + rng.next_int(noise + 1);\n\n                // Strong penalty for immediate dead end unless it is very valuable\n                if (deg == 0) eval -= 2500;\n\n                cand.push_back({d, ni, nj, eval});\n            }\n\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n                return a.eval > b.eval;\n            });\n\n            int choose = 0;\n\n            // Occasionally choose second/third best to diversify\n            int r = rng.next_int(100);\n            if ((int)cand.size() >= 2 && r < 18) choose = 1;\n            if ((int)cand.size() >= 3 && r < 6) choose = 2;\n            if ((int)cand.size() >= 4 && r < 2) choose = 3;\n\n            auto c = cand[choose];\n\n            path.push_back(dc[c.dir]);\n            ci = c.ni;\n            cj = c.nj;\n            visited[tile_id[ci][cj]] = 1;\n            score += pval[ci][cj];\n            cells.emplace_back(ci, cj);\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_path.assign(path.begin(), path.end());\n        }\n    }\n\n    cout << best_path << '\\n';\n\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int Q = 1000;\n\nstruct UsedEdge {\n    int type; // 0: horizontal, 1: vertical\n    int a, b;\n};\n\ndouble h_edge[N][N - 1];\ndouble v_edge[N - 1][N];\nint h_cnt[N][N - 1];\nint v_cnt[N - 1][N];\n\ndouble row_cost[N]; // horizontal cost by row\ndouble col_cost[N]; // vertical cost by column\n\nvector<UsedEdge> prev_edges;\nint prev_si, prev_sj, prev_ti, prev_tj;\n\nmt19937 rng(1234567);\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos(int x) {\n    return {x / N, x % N};\n}\n\ndouble clamp_cost(double x) {\n    return max(100.0, min(10000.0, x));\n}\n\ndouble get_h_cost(int i, int j, int turn) {\n    double coarse = row_cost[i];\n    double local = h_edge[i][j];\n\n    // Early: trust row model. Later: allow local deviations.\n    double local_w = min(0.45, h_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\ndouble get_v_cost(int i, int j, int turn) {\n    double coarse = col_cost[j];\n    double local = v_edge[i][j];\n\n    double local_w = min(0.45, v_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\nvector<UsedEdge> path_edges(int si, int sj, const string& path) {\n    vector<UsedEdge> edges;\n    int i = si, j = sj;\n    for (char c : path) {\n        if (c == 'U') {\n            edges.push_back({1, i - 1, j});\n            --i;\n        } else if (c == 'D') {\n            edges.push_back({1, i, j});\n            ++i;\n        } else if (c == 'L') {\n            edges.push_back({0, i, j - 1});\n            --j;\n        } else if (c == 'R') {\n            edges.push_back({0, i, j});\n            ++j;\n        }\n    }\n    return edges;\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool vertical_first) {\n    string s;\n    if (vertical_first) {\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n    } else {\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n    }\n    return s;\n}\n\nstring randomized_manhattan(int si, int sj, int ti, int tj) {\n    string s;\n    int i = si, j = sj;\n\n    while (i != ti || j != tj) {\n        vector<char> cand;\n        if (i < ti) cand.push_back('D');\n        if (i > ti) cand.push_back('U');\n        if (j < tj) cand.push_back('R');\n        if (j > tj) cand.push_back('L');\n\n        char c = cand[rng() % cand.size()];\n        s.push_back(c);\n\n        if (c == 'D') ++i;\n        else if (c == 'U') --i;\n        else if (c == 'R') ++j;\n        else --j;\n    }\n\n    return s;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    vector<double> dist(V, 1e100);\n    vector<int> par(V, -1);\n    vector<char> pch(V, '?');\n\n    priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n\n    int S = id(si, sj);\n    int T = id(ti, tj);\n\n    dist[S] = 0.0;\n    pq.push({0.0, S});\n\n    while (!pq.empty()) {\n        auto [d, x] = pq.top();\n        pq.pop();\n\n        if (d != dist[x]) continue;\n        if (x == T) break;\n\n        auto [i, j] = pos(x);\n\n        auto relax = [&](int ni, int nj, double w, char c) {\n            int y = id(ni, nj);\n            if (dist[y] > d + w) {\n                dist[y] = d + w;\n                par[y] = x;\n                pch[y] = c;\n                pq.push({dist[y], y});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, get_v_cost(i - 1, j, turn), 'U');\n        if (i + 1 < N) relax(i + 1, j, get_v_cost(i, j, turn), 'D');\n        if (j > 0) relax(i, j - 1, get_h_cost(i, j - 1, turn), 'L');\n        if (j + 1 < N) relax(i, j + 1, get_h_cost(i, j, turn), 'R');\n    }\n\n    string res;\n    int cur = T;\n    while (cur != S) {\n        if (cur < 0 || pch[cur] == '?') {\n            return manhattan_path(si, sj, ti, tj, true);\n        }\n        res.push_back(pch[cur]);\n        cur = par[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nbool valid_simple_path(int si, int sj, int ti, int tj, const string& s) {\n    bool seen[N][N] = {};\n    int i = si, j = sj;\n    seen[i][j] = true;\n\n    for (char c : s) {\n        if (c == 'U') --i;\n        else if (c == 'D') ++i;\n        else if (c == 'L') --j;\n        else if (c == 'R') ++j;\n        else return false;\n\n        if (i < 0 || i >= N || j < 0 || j >= N) return false;\n        if (seen[i][j]) return false;\n        seen[i][j] = true;\n    }\n\n    return i == ti && j == tj;\n}\n\nvoid update_from_result(int measured, int turn) {\n    if (prev_edges.empty()) return;\n\n    int row_use[N] = {};\n    int col_use[N] = {};\n\n    double pred_coarse = 0.0;\n    double pred_edge = 0.0;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            row_use[e.a]++;\n            pred_coarse += row_cost[e.a];\n            pred_edge += h_edge[e.a][e.b];\n        } else {\n            col_use[e.b]++;\n            pred_coarse += col_cost[e.b];\n            pred_edge += v_edge[e.a][e.b];\n        }\n    }\n\n    double pred = 0.75 * pred_coarse + 0.25 * pred_edge;\n    if (pred <= 1.0) return;\n\n    // Observation noise is multiplicative 0.9-1.1.\n    // Clamp residual to avoid overreacting.\n    double ratio = measured / pred;\n    ratio = max(0.75, min(1.25, ratio));\n    double target = pred * ratio;\n    double err = target - pred;\n\n    double norm = 1e-9;\n    for (int i = 0; i < N; i++) norm += row_use[i] * row_use[i];\n    for (int j = 0; j < N; j++) norm += col_use[j] * col_use[j];\n\n    // Coarse 60-parameter online regression.\n    double lr = 0.55;\n    if (turn > 100) lr = 0.42;\n    if (turn > 300) lr = 0.32;\n    if (turn > 600) lr = 0.24;\n\n    for (int i = 0; i < N; i++) {\n        if (row_use[i]) {\n            row_cost[i] += lr * err * row_use[i] / norm;\n            row_cost[i] = clamp_cost(row_cost[i]);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        if (col_use[j]) {\n            col_cost[j] += lr * err * col_use[j] / norm;\n            col_cost[j] = clamp_cost(col_cost[j]);\n        }\n    }\n\n    // Local edge correction.\n    // This captures random delta and some M=2 breakpoint behavior.\n    double edge_norm = max(1, (int)prev_edges.size());\n    double edge_lr = 0.20;\n    if (turn > 200) edge_lr = 0.16;\n    if (turn > 600) edge_lr = 0.11;\n\n    double per_edge_delta = edge_lr * err / edge_norm;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            int i = e.a, j = e.b;\n            h_edge[i][j] += per_edge_delta;\n            h_edge[i][j] = clamp_cost(h_edge[i][j]);\n            h_cnt[i][j]++;\n        } else {\n            int i = e.a, j = e.b;\n            v_edge[i][j] += per_edge_delta;\n            v_edge[i][j] = clamp_cost(v_edge[i][j]);\n            v_cnt[i][j]++;\n        }\n    }\n\n    // Keep edge estimates weakly tied to their coarse row/column model.\n    // Prevents bad noisy single observations from dominating.\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            int i = e.a, j = e.b;\n            h_edge[i][j] = 0.985 * h_edge[i][j] + 0.015 * row_cost[i];\n        } else {\n            int i = e.a, j = e.b;\n            v_edge[i][j] = 0.985 * v_edge[i][j] + 0.015 * col_cost[j];\n        }\n    }\n}\n\nstring choose_path(int si, int sj, int ti, int tj, int turn) {\n    // Exploration phase. Use monotone paths, which are always simple and shortest\n    // in number of steps, while still giving useful learning signals.\n    if (turn < 20) {\n        if (turn % 3 == 0) return manhattan_path(si, sj, ti, tj, true);\n        if (turn % 3 == 1) return manhattan_path(si, sj, ti, tj, false);\n        return randomized_manhattan(si, sj, ti, tj);\n    }\n\n    string best = dijkstra_path(si, sj, ti, tj, turn);\n\n    // Sparse continuing exploration in first half.\n    // Only use monotone paths, so path length is not excessive.\n    if (turn < 220 && turn % 17 == 0) {\n        string alt = randomized_manhattan(si, sj, ti, tj);\n\n        // Avoid very long detours. Randomized Manhattan has exact Manhattan length,\n        // so it is safe in step count.\n        if ((int)alt.size() <= (int)best.size() + 4) {\n            best = alt;\n        }\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; i++) {\n        row_cost[i] = 5000.0;\n        for (int j = 0; j < N - 1; j++) {\n            h_edge[i][j] = 5000.0;\n            h_cnt[i][j] = 0;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        col_cost[j] = 5000.0;\n    }\n\n    for (int i = 0; i < N - 1; i++) {\n        for (int j = 0; j < N; j++) {\n            v_edge[i][j] = 5000.0;\n            v_cnt[i][j] = 0;\n        }\n    }\n\n    int measured = -1;\n\n    for (int turn = 0; turn < Q; turn++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        if (turn > 0) {\n            update_from_result(measured, turn);\n        }\n\n        string ans = choose_path(si, sj, ti, tj, turn);\n\n        if (!valid_simple_path(si, sj, ti, tj, ans)) {\n            ans = manhattan_path(si, sj, ti, tj, true);\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        prev_si = si;\n        prev_sj = sj;\n        prev_ti = ti;\n        prev_tj = tj;\n        prev_edges = path_edges(si, sj, ans);\n\n        cin >> measured;\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const string ALPHA = \"ABCDEFGH\";\n\nint M;\nvector<string> S;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nint overlap_len(const string& a, const string& b) {\n    int la = (int)a.size();\n    int lb = (int)b.size();\n    int lim = min(la, lb);\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[la - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nbool contains_linear(const string& a, const string& b) {\n    return a.find(b) != string::npos;\n}\n\nbool match_cyclic_line(const string& line, const string& pat) {\n    int L = (int)line.size();\n    int K = (int)pat.size();\n    for (int st = 0; st < L; ++st) {\n        bool ok = true;\n        for (int p = 0; p < K; ++p) {\n            if (line[(st + p) % L] != pat[p]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n    return false;\n}\n\nvector<string> greedy_merge(vector<string> v, int maxLines, int maxLen) {\n    vector<int> alive(v.size(), 1);\n\n    while (true) {\n        int n = (int)v.size();\n        int aliveCnt = 0;\n        for (int x : alive) aliveCnt += x;\n\n        int bestI = -1;\n        int bestJ = -1;\n        int bestOv = -1;\n        string bestMerged;\n\n        for (int i = 0; i < n; ++i) if (alive[i]) {\n            for (int j = 0; j < n; ++j) if (i != j && alive[j]) {\n                if (contains_linear(v[i], v[j])) {\n                    bestI = i;\n                    bestJ = j;\n                    bestOv = 1000;\n                    bestMerged = v[i];\n                    goto FOUND;\n                }\n\n                int ov = overlap_len(v[i], v[j]);\n                int nl = (int)v[i].size() + (int)v[j].size() - ov;\n\n                if (nl <= maxLen && ov > bestOv) {\n                    bestOv = ov;\n                    bestI = i;\n                    bestJ = j;\n                    bestMerged = v[i] + v[j].substr(ov);\n                }\n            }\n        }\n\nFOUND:\n        if (bestI == -1) break;\n        if (aliveCnt <= maxLines && bestOv < 2) break;\n\n        v[bestI] = bestMerged;\n        alive[bestJ] = 0;\n    }\n\n    vector<string> res;\n    for (int i = 0; i < (int)v.size(); ++i) {\n        if (alive[i]) res.push_back(v[i]);\n    }\n\n    return res;\n}\n\nint line_cover_count(const string& line) {\n    int cnt = 0;\n    for (const string& s : S) {\n        if (match_cyclic_line(line, s)) cnt++;\n    }\n    return cnt;\n}\n\nvector<string> normalize_lines(vector<string> lines, mt19937& rng) {\n    vector<pair<int, string>> scored;\n\n    for (string t : lines) {\n        if ((int)t.size() > N) t.resize(N);\n        while ((int)t.size() < N) {\n            t += ALPHA[rng() % 8];\n        }\n        int sc = line_cover_count(t);\n        scored.push_back({sc, t});\n    }\n\n    sort(scored.begin(), scored.end(), [](const auto& a, const auto& b) {\n        if (a.first != b.first) return a.first > b.first;\n        return a.second < b.second;\n    });\n\n    vector<string> res;\n    set<string> used;\n    for (auto& [sc, t] : scored) {\n        if (!used.count(t)) {\n            used.insert(t);\n            res.push_back(t);\n        }\n    }\n\n    return res;\n}\n\nint evaluate_grid(const vector<string>& grid) {\n    vector<string> cols(N, string(N, 'A'));\n\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            cols[j][i] = grid[i][j];\n        }\n    }\n\n    int c = 0;\n    for (const string& s : S) {\n        bool ok = false;\n\n        for (int i = 0; i < N && !ok; ++i) {\n            if (match_cyclic_line(grid[i], s)) ok = true;\n        }\n\n        for (int j = 0; j < N && !ok; ++j) {\n            if (match_cyclic_line(cols[j], s)) ok = true;\n        }\n\n        if (ok) c++;\n    }\n\n    return c;\n}\n\nvector<string> build_candidate(const vector<string>& lines, mt19937& rng) {\n    vector<string> grid(N, string(N, '.'));\n\n    int L = (int)lines.size();\n    vector<int> ids(L);\n    iota(ids.begin(), ids.end(), 0);\n\n    shuffle(ids.begin(), ids.end(), rng);\n\n    stable_sort(ids.begin(), ids.end(), [&](int a, int b) {\n        return lines[a].size() > lines[b].size();\n    });\n\n    if ((rng() & 1) && L > 30) {\n        shuffle(ids.begin(), ids.begin() + min(L, 30), rng);\n    }\n\n    int ptr = 0;\n\n    vector<int> rowOrder(N);\n    iota(rowOrder.begin(), rowOrder.end(), 0);\n    shuffle(rowOrder.begin(), rowOrder.end(), rng);\n\n    for (int rpos = 0; rpos < N && ptr < L; ++rpos, ++ptr) {\n        int r = rowOrder[rpos];\n        const string& t = lines[ids[ptr]];\n        int shift = rng() % N;\n\n        for (int j = 0; j < N; ++j) {\n            grid[r][(j + shift) % N] = t[j];\n        }\n    }\n\n    vector<int> colOrder(N);\n    iota(colOrder.begin(), colOrder.end(), 0);\n    shuffle(colOrder.begin(), colOrder.end(), rng);\n\n    for (int cpos = 0; cpos < N && ptr < L; ++cpos, ++ptr) {\n        int col = colOrder[cpos];\n        const string& t = lines[ids[ptr]];\n\n        int bestShift = 0;\n        int bestConflict = INT_MAX;\n\n        for (int sh = 0; sh < N; ++sh) {\n            int conflict = 0;\n            for (int i = 0; i < N; ++i) {\n                char ch = t[(i - sh + N) % N];\n                if (grid[i][col] != '.' && grid[i][col] != ch) conflict++;\n            }\n\n            if (conflict < bestConflict) {\n                bestConflict = conflict;\n                bestShift = sh;\n            }\n        }\n\n        for (int i = 0; i < N; ++i) {\n            char ch = t[(i - bestShift + N) % N];\n\n            if (grid[i][col] == '.') {\n                grid[i][col] = ch;\n            } else if (grid[i][col] != ch) {\n                if ((rng() % 100) < 20) grid[i][col] = ch;\n            }\n        }\n    }\n\n    vector<int> freq(8, 0);\n    for (const string& s : S) {\n        for (char c : s) freq[c - 'A']++;\n    }\n\n    int bestChar = max_element(freq.begin(), freq.end()) - freq.begin();\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (grid[i][j] == '.') {\n                if ((rng() % 100) < 80) grid[i][j] = ALPHA[bestChar];\n                else grid[i][j] = ALPHA[rng() % 8];\n            }\n        }\n    }\n\n    return grid;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputN;\n    cin >> inputN >> M;\n\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    Timer timer;\n    mt19937 rng(123456789);\n\n    vector<string> base = S;\n\n    sort(base.begin(), base.end(), [](const string& a, const string& b) {\n        if (a.size() != b.size()) return a.size() > b.size();\n        return a < b;\n    });\n\n    base.erase(unique(base.begin(), base.end()), base.end());\n\n    vector<string> lines = greedy_merge(base, 90, N);\n    lines = normalize_lines(lines, rng);\n\n    while ((int)lines.size() < 50) {\n        string t = S[rng() % M];\n        while ((int)t.size() < N) t += ALPHA[rng() % 8];\n        if ((int)t.size() > N) t.resize(N);\n        lines.push_back(t);\n    }\n\n    if ((int)lines.size() > 100) lines.resize(100);\n\n    vector<string> bestGrid(N, string(N, 'A'));\n    int bestScore = -1;\n\n    int iter = 0;\n\n    while (timer.elapsed() < 2.85) {\n        vector<string> cand = build_candidate(lines, rng);\n        int sc = evaluate_grid(cand);\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestGrid = cand;\n        }\n\n        iter++;\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << bestGrid[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct PQNode {\n    int d, v;\n    bool operator<(const PQNode& other) const {\n        return d > other.d;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    const int V = N * N;\n    const int INF = 1e9;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    auto pos = [&](int v) {\n        return pair<int,int>{v / N, v % N};\n    };\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n\n    vector<int> isroad(V, 0), weight(V, 0), road_ids;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                int v = id(i, j);\n                isroad[v] = 1;\n                weight[v] = grid[i][j] - '0';\n                road_ids.push_back(v);\n            }\n        }\n    }\n\n    int R = (int)road_ids.size();\n\n    vector<vector<int>> visible(V);\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            vector<int> seg;\n            int k = j;\n            while (k < N && grid[i][k] != '#') {\n                seg.push_back(id(i, k));\n                k++;\n            }\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n            j = k;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            vector<int> seg;\n            int k = i;\n            while (k < N && grid[k][j] != '#') {\n                seg.push_back(id(k, j));\n                k++;\n            }\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n            i = k;\n        }\n    }\n\n    for (int v : road_ids) {\n        auto &a = visible[v];\n        sort(a.begin(), a.end());\n        a.erase(unique(a.begin(), a.end()), a.end());\n    }\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    auto dijkstra = [&](int s) {\n        vector<int> dist(V, INF), par(V, -1), parDir(V, -1);\n        priority_queue<PQNode> pq;\n\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n\n            if (d != dist[v]) continue;\n\n            auto [i, j] = pos(v);\n\n            for (int z = 0; z < 4; z++) {\n                int ni = i + di[z];\n                int nj = j + dj[z];\n\n                if (!inside(ni, nj)) continue;\n                if (grid[ni][nj] == '#') continue;\n\n                int nv = id(ni, nj);\n                int nd = d + weight[nv];\n\n                if (nd < dist[nv]) {\n                    dist[nv] = nd;\n                    par[nv] = v;\n                    parDir[nv] = z;\n                    pq.push({nd, nv});\n                }\n            }\n        }\n\n        return tuple<vector<int>, vector<int>, vector<int>>(dist, par, parDir);\n    };\n\n    auto restore_path = [&](int s, int t, const vector<int>& par,\n                            const vector<int>& parDir) {\n        string path;\n        int cur = t;\n\n        while (cur != s) {\n            int z = parDir[cur];\n            path.push_back(dc[z]);\n            cur = par[cur];\n        }\n\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    int start = id(si, sj);\n\n    // ------------------------------------------------------------\n    // Step 1: select useful observation target cells.\n    // ------------------------------------------------------------\n\n    vector<char> covered(V, 0);\n    int covered_count = 0;\n\n    auto apply_cover = [&](int v) {\n        for (int u : visible[v]) {\n            if (!covered[u]) {\n                covered[u] = 1;\n                covered_count++;\n            }\n        }\n    };\n\n    vector<int> targets;\n    apply_cover(start);\n\n    // Greedy set-cover with a small distance bias to the start.\n    auto [distStart, parStartDummy, parDirStartDummy] = dijkstra(start);\n\n    while (covered_count < R) {\n        int best = -1;\n        double bestScore = -1.0;\n\n        for (int v : road_ids) {\n            int gain = 0;\n            for (int u : visible[v]) {\n                if (!covered[u]) gain++;\n            }\n            if (gain == 0) continue;\n\n            double score = gain;\n\n            // Prefer larger coverage, but mildly prefer cells closer to start.\n            score /= pow((double)distStart[v] + 20.0, 0.18);\n\n            // Prefer intersections because they often cover two long lines.\n            auto [i, j] = pos(v);\n            int deg = 0;\n            for (int z = 0; z < 4; z++) {\n                int ni = i + di[z];\n                int nj = j + dj[z];\n                if (inside(ni, nj) && grid[ni][nj] != '#') deg++;\n            }\n            if (deg >= 3) score *= 1.08;\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = v;\n            }\n        }\n\n        if (best == -1) break;\n\n        targets.push_back(best);\n        apply_cover(best);\n    }\n\n    // Remove accidental duplicate targets.\n    sort(targets.begin(), targets.end());\n    targets.erase(unique(targets.begin(), targets.end()), targets.end());\n\n    // ------------------------------------------------------------\n    // Step 2: build node list.\n    // node 0 is start, nodes 1..M are selected targets.\n    // ------------------------------------------------------------\n\n    vector<int> nodes;\n    nodes.push_back(start);\n    for (int v : targets) {\n        if (v != start) nodes.push_back(v);\n    }\n\n    int M = (int)nodes.size();\n\n    // If no target is needed, just output empty route.\n    if (M == 1) {\n        cout << \"\\n\";\n        return 0;\n    }\n\n    vector<vector<int>> distMat(M, vector<int>(M, INF));\n    vector<vector<int>> allPar(M), allParDir(M);\n\n    for (int a = 0; a < M; a++) {\n        auto [dist, par, parDir] = dijkstra(nodes[a]);\n        allPar[a] = move(par);\n        allParDir[a] = move(parDir);\n\n        for (int b = 0; b < M; b++) {\n            distMat[a][b] = dist[nodes[b]];\n        }\n    }\n\n    // ------------------------------------------------------------\n    // Step 3: construct TSP cycle by nearest insertion.\n    // route contains target node indices only, excluding start.\n    // Final cycle is: 0 -> route[0] -> ... -> route.back() -> 0\n    // ------------------------------------------------------------\n\n    vector<int> remaining;\n    for (int i = 1; i < M; i++) remaining.push_back(i);\n\n    vector<int> route;\n\n    {\n        int first = remaining[0];\n        for (int x : remaining) {\n            if (distMat[0][x] + distMat[x][0] <\n                distMat[0][first] + distMat[first][0]) {\n                first = x;\n            }\n        }\n\n        route.push_back(first);\n        remaining.erase(find(remaining.begin(), remaining.end(), first));\n    }\n\n    while (!remaining.empty()) {\n        int bestNode = -1;\n        int bestPos = -1;\n        int bestInc = INF;\n\n        for (int x : remaining) {\n            int L = (int)route.size();\n\n            for (int p = 0; p <= L; p++) {\n                int a = (p == 0 ? 0 : route[p - 1]);\n                int b = (p == L ? 0 : route[p]);\n\n                int inc = distMat[a][x] + distMat[x][b] - distMat[a][b];\n\n                if (inc < bestInc) {\n                    bestInc = inc;\n                    bestNode = x;\n                    bestPos = p;\n                }\n            }\n        }\n\n        route.insert(route.begin() + bestPos, bestNode);\n        remaining.erase(find(remaining.begin(), remaining.end(), bestNode));\n    }\n\n    auto route_cost = [&]() {\n        long long cost = 0;\n        int prev = 0;\n        for (int x : route) {\n            cost += distMat[prev][x];\n            prev = x;\n        }\n        cost += distMat[prev][0];\n        return cost;\n    };\n\n    // ------------------------------------------------------------\n    // Step 4: 2-opt improvement.\n    // ------------------------------------------------------------\n\n    int L = (int)route.size();\n\n    bool improved = true;\n    int iter = 0;\n\n    while (improved && iter < 200) {\n        improved = false;\n        iter++;\n\n        for (int l = 0; l < L && !improved; l++) {\n            for (int r = l + 1; r < L && !improved; r++) {\n                int a = (l == 0 ? 0 : route[l - 1]);\n                int b = route[l];\n                int c = route[r];\n                int d = (r + 1 == L ? 0 : route[r + 1]);\n\n                int before = distMat[a][b] + distMat[c][d];\n                int after  = distMat[a][c] + distMat[b][d];\n\n                if (after < before) {\n                    reverse(route.begin() + l, route.begin() + r + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    // ------------------------------------------------------------\n    // Step 5: Output actual shortest paths.\n    // ------------------------------------------------------------\n\n    string answer;\n    int prev = 0;\n\n    for (int x : route) {\n        answer += restore_path(nodes[prev], nodes[x], allPar[prev], allParDir[prev]);\n        prev = x;\n    }\n\n    answer += restore_path(nodes[prev], nodes[0], allPar[prev], allParDir[prev]);\n\n    cout << answer << '\\n';\n\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    vector<int> d;\n    vector<int> pre;\n    vector<int> nxt;\n};\n\nstruct Obs {\n    int task;\n    int dur;\n};\n\nstatic uint64_t rng_state = 88172645463325252ull;\nuint64_t xorshift64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\ndouble rnd01() {\n    return (xorshift64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<Task> tasks(N);\n    vector<double> dsum(N, 0), dmaxv(N, 0);\n    vector<double> avgD(K, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; k++) {\n            cin >> tasks[i].d[k];\n            dsum[i] += tasks[i].d[k];\n            dmaxv[i] = max(dmaxv[i], (double)tasks[i].d[k]);\n            avgD[k] += tasks[i].d[k];\n        }\n    }\n    for (int k = 0; k < K; k++) avgD[k] /= N;\n\n    vector<int> indeg0(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        tasks[u].nxt.push_back(v);\n        tasks[v].pre.push_back(u);\n        indeg0[v]++;\n    }\n\n    // Downstream criticality.\n    vector<double> crit(N, 1.0);\n    vector<double> unlock(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double best = 0.0;\n        double sumChild = 0.0;\n        for (int v : tasks[i].nxt) {\n            best = max(best, crit[v]);\n            sumChild += 1.0 + 0.20 * unlock[v];\n        }\n\n        // Approximate own processing size under average unknown member.\n        double ownHard = dsum[i] / max(1, K);\n\n        crit[i] = 1.0 + best + 0.020 * ownHard;\n        unlock[i] = min(2000.0, sumChild);\n    }\n\n    vector<double> basePriority(N);\n    for (int i = 0; i < N; i++) {\n        basePriority[i] =\n            32.0 * crit[i]\n            + 5.0 * (double)tasks[i].nxt.size()\n            + 0.18 * unlock[i]\n            + 0.035 * dsum[i]\n            + 0.040 * dmaxv[i]\n            - 0.0015 * i;\n    }\n\n    vector<int> status(N, -1);      // -1 unstarted, 0 running, 1 completed\n    vector<int> memberTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    // Initial skill estimates.\n    // Randomized around average requirements to promote specialization.\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    for (int j = 0; j < M; j++) {\n        double scale = 0.90 + 0.35 * rnd01();\n        for (int k = 0; k < K; k++) {\n            double noise = (rnd01() - 0.5) * 4.0;\n            skill[j][k] = max(0.0, avgD[k] * scale + noise);\n        }\n    }\n\n    vector<vector<Obs>> observations(M);\n\n    auto shortage = [&](int task, int member) {\n        double w = 0.0;\n        for (int k = 0; k < K; k++) {\n            w += max(0.0, (double)tasks[task].d[k] - skill[member][k]);\n        }\n        return w;\n    };\n\n    auto estimate_duration = [&](int task, int member) {\n        double w = shortage(task, member);\n        return max(1.0, w);\n    };\n\n    auto ready = [&](int task) {\n        if (status[task] != -1) return false;\n        for (int p : tasks[task].pre) {\n            if (status[p] != 1) return false;\n        }\n        return true;\n    };\n\n    auto refit_member = [&](int j) {\n        int nobs = (int)observations[j].size();\n        if (nobs == 0) return;\n\n        // Number of small SGD passes. Cheap because each member has few observations.\n        int passes = 12;\n        if (nobs > 20) passes = 8;\n        if (nobs > 50) passes = 5;\n\n        double lambda = 0.002; // prevents exploding skills\n        for (int pass = 0; pass < passes; pass++) {\n            for (const Obs &ob : observations[j]) {\n                int t = ob.task;\n                double target = (ob.dur <= 1 ? 0.0 : (double)ob.dur);\n\n                double pred = 0.0;\n                vector<int> active;\n                active.reserve(K);\n\n                for (int k = 0; k < K; k++) {\n                    double gap = (double)tasks[t].d[k] - skill[j][k];\n                    if (gap > 0) {\n                        pred += gap;\n                        active.push_back(k);\n                    }\n                }\n\n                double err = pred - target;\n\n                if (!active.empty()) {\n                    double lr = 0.055 / sqrt(1.0 + 0.03 * nobs);\n                    double delta = lr * err / sqrt((double)active.size());\n\n                    // pred too large -> skill too low -> increase active skills.\n                    for (int k : active) {\n                        skill[j][k] += delta;\n                    }\n                } else {\n                    // If predicted zero shortage but observed long duration,\n                    // decrease dimensions related to this task.\n                    if (target > 1.5) {\n                        double lr = 0.030 / sqrt(1.0 + 0.03 * nobs);\n                        double dec = lr * target / K;\n                        for (int k = 0; k < K; k++) {\n                            if (tasks[t].d[k] > 0) skill[j][k] -= dec * (0.5 + tasks[t].d[k] / max(1.0, dmaxv[t]));\n                        }\n                    }\n                }\n\n                // Strong lower-bound learning for one-day jobs.\n                if (ob.dur == 1) {\n                    double lr = 0.040 / sqrt(1.0 + 0.03 * nobs);\n                    for (int k = 0; k < K; k++) {\n                        if (skill[j][k] < tasks[t].d[k]) {\n                            skill[j][k] += lr * ((double)tasks[t].d[k] - skill[j][k]);\n                        }\n                    }\n                }\n\n                // Mild regularization toward plausible range.\n                for (int k = 0; k < K; k++) {\n                    skill[j][k] *= (1.0 - lambda);\n                    if (skill[j][k] < 0.0) skill[j][k] = 0.0;\n                    if (skill[j][k] > 80.0) skill[j][k] = 80.0;\n                }\n            }\n        }\n    };\n\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        vector<int> readyTasks;\n        readyTasks.reserve(N);\n        for (int i = 0; i < N; i++) {\n            if (ready(i)) readyTasks.push_back(i);\n        }\n\n        sort(readyTasks.begin(), readyTasks.end(), [&](int a, int b) {\n            if (basePriority[a] != basePriority[b]) return basePriority[a] > basePriority[b];\n            return a < b;\n        });\n\n        vector<int> freeMembers;\n        for (int j = 0; j < M; j++) {\n            if (memberTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        vector<pair<int,int>> assignments;\n        vector<char> usedMember(M, 0);\n\n        // Important-task-first assignment:\n        // Consider top ready tasks and choose best member for each.\n        int taskLimit = min((int)readyTasks.size(), max(30, (int)freeMembers.size() * 8));\n\n        for (int idx = 0; idx < taskLimit; idx++) {\n            int t = readyTasks[idx];\n\n            int bestJ = -1;\n            double bestScore = -1e100;\n\n            for (int j : freeMembers) {\n                if (usedMember[j]) continue;\n\n                double est = estimate_duration(t, j);\n\n                // More uncertainty means we should avoid putting a brand-new member\n                // on an extremely critical long task unless necessary.\n                int cnt = observations[j].size();\n                double uncertaintyPenalty = 0.0;\n                if (cnt < 3) uncertaintyPenalty = 0.10 * est + 3.0;\n                else if (cnt < 8) uncertaintyPenalty = 0.04 * est;\n\n                // Small preference to use low-observation members on moderately short tasks.\n                double exploreBonus = 0.0;\n                if (cnt < 6 && est <= 8.0) exploreBonus = 2.0;\n\n                double score =\n                    basePriority[t] / pow(est + 1.0, 0.92)\n                    - uncertaintyPenalty\n                    + exploreBonus;\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestJ = j;\n                }\n            }\n\n            if (bestJ != -1) {\n                usedMember[bestJ] = 1;\n                assignments.push_back({bestJ, t});\n                if ((int)assignments.size() == (int)freeMembers.size()) break;\n            }\n        }\n\n        // If not all free members got a task, fill with remaining ready tasks using pair-greedy.\n        if ((int)assignments.size() < (int)freeMembers.size()) {\n            vector<char> usedTask(N, 0);\n            for (auto [j, t] : assignments) usedTask[t] = 1;\n\n            while ((int)assignments.size() < (int)freeMembers.size()) {\n                int bestJ = -1, bestT = -1;\n                double bestScore = -1e100;\n\n                for (int j : freeMembers) {\n                    if (usedMember[j]) continue;\n                    for (int t : readyTasks) {\n                        if (usedTask[t]) continue;\n\n                        double est = estimate_duration(t, j);\n                        double score = basePriority[t] / pow(est + 1.0, 0.90);\n\n                        if (score > bestScore) {\n                            bestScore = score;\n                            bestJ = j;\n                            bestT = t;\n                        }\n                    }\n                }\n\n                if (bestJ == -1) break;\n                usedMember[bestJ] = 1;\n                usedTask[bestT] = 1;\n                assignments.push_back({bestJ, bestT});\n            }\n        }\n\n        for (auto [j, t] : assignments) {\n            status[t] = 0;\n            memberTask[j] = t;\n            startDay[j] = day;\n        }\n\n        cout << assignments.size();\n        for (auto [j, t] : assignments) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        string line;\n        if (!getline(cin >> ws, line)) return 0;\n\n        stringstream ss(line);\n        int nfin;\n        ss >> nfin;\n\n        if (nfin == -1) {\n            return 0;\n        }\n\n        for (int z = 0; z < nfin; z++) {\n            int memberInput;\n            ss >> memberInput;\n            int j = memberInput - 1;\n\n            int t = memberTask[j];\n            if (t < 0) continue;\n\n            int duration = day - startDay[j] + 1;\n\n            status[t] = 1;\n            memberTask[j] = -1;\n            startDay[j] = -1;\n\n            observations[j].push_back({t, duration});\n            refit_member(j);\n\n            // Optional visualizer output. Disabled to avoid needless I/O.\n            /*\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << ' ' << (int)round(skill[j][k]);\n            }\n            cout << '\\n';\n            cout.flush();\n            */\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n};\n\nstatic inline int mdist(const Point& p, const Point& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstatic inline int mdist_xy(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nconst Point OFFICE{400, 400};\n\nvector<Order> ords(1000);\n\nPoint pickup_point(int id) {\n    return {ords[id].a, ords[id].b};\n}\n\nPoint delivery_point(int id) {\n    return {ords[id].c, ords[id].d};\n}\n\nvector<int> nearest_order_path(const vector<int>& ids, bool pickup, Point start) {\n    int n = ids.size();\n    vector<int> res;\n    res.reserve(n);\n    vector<char> used(n, false);\n\n    Point cur = start;\n    for (int step = 0; step < n; step++) {\n        int best = -1;\n        int bestd = INT_MAX;\n        for (int i = 0; i < n; i++) {\n            if (used[i]) continue;\n            Point p = pickup ? pickup_point(ids[i]) : delivery_point(ids[i]);\n            int d = mdist(cur, p);\n            if (d < bestd) {\n                bestd = d;\n                best = i;\n            }\n        }\n        used[best] = true;\n        res.push_back(ids[best]);\n        cur = pickup ? pickup_point(ids[best]) : delivery_point(ids[best]);\n    }\n    return res;\n}\n\nint segment_path_length(const vector<Point>& pts) {\n    int s = 0;\n    for (int i = 0; i + 1 < (int)pts.size(); i++) {\n        s += mdist(pts[i], pts[i + 1]);\n    }\n    return s;\n}\n\nvoid two_opt_points(vector<int>& path, bool pickup, Point start, Point goal, int iter_limit = 4000) {\n    int n = path.size();\n    if (n <= 2) return;\n\n    auto getp = [&](int idx) -> Point {\n        if (idx == -1) return start;\n        if (idx == n) return goal;\n        return pickup ? pickup_point(path[idx]) : delivery_point(path[idx]);\n    };\n\n    bool improved = true;\n    int iter = 0;\n    while (improved && iter < iter_limit) {\n        improved = false;\n        iter++;\n        for (int i = 0; i < n - 1; i++) {\n            Point A = getp(i - 1);\n            Point B = getp(i);\n            for (int k = i + 1; k < n; k++) {\n                Point C = getp(k);\n                Point D = getp(k + 1);\n\n                int before = mdist(A, B) + mdist(C, D);\n                int after = mdist(A, C) + mdist(B, D);\n\n                if (after < before) {\n                    reverse(path.begin() + i, path.begin() + k + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    vector<int> ids;\n    vector<int> pickups;\n    vector<int> deliveries;\n    vector<Point> route;\n    int cost;\n};\n\nSolution build_solution(vector<int> ids) {\n    Solution sol;\n    sol.ids = ids;\n\n    sol.pickups = nearest_order_path(ids, true, OFFICE);\n\n    Point last_pick = OFFICE;\n    if (!sol.pickups.empty()) {\n        last_pick = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_order_path(ids, false, last_pick);\n\n    Point first_delivery_start = OFFICE;\n    if (!sol.pickups.empty()) first_delivery_start = pickup_point(sol.pickups.back());\n\n    Point delivery_goal = OFFICE;\n\n    two_opt_points(sol.pickups, true, OFFICE,\n                   sol.deliveries.empty() ? OFFICE : delivery_point(sol.deliveries.front()));\n\n    Point after_pick = OFFICE;\n    if (!sol.pickups.empty()) after_pick = pickup_point(sol.pickups.back());\n\n    sol.deliveries = nearest_order_path(ids, false, after_pick);\n    two_opt_points(sol.deliveries, false, after_pick, OFFICE);\n\n    sol.route.clear();\n    sol.route.push_back(OFFICE);\n\n    for (int id : sol.pickups) {\n        sol.route.push_back(pickup_point(id));\n    }\n    for (int id : sol.deliveries) {\n        sol.route.push_back(delivery_point(id));\n    }\n    sol.route.push_back(OFFICE);\n\n    sol.cost = segment_path_length(sol.route);\n    return sol;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 1000; i++) {\n        cin >> ords[i].a >> ords[i].b >> ords[i].c >> ords[i].d;\n    }\n\n    vector<pair<int,int>> score_id;\n    score_id.reserve(1000);\n\n    for (int i = 0; i < 1000; i++) {\n        int s =\n            mdist_xy(400, 400, ords[i].a, ords[i].b) +\n            mdist_xy(ords[i].a, ords[i].b, ords[i].c, ords[i].d) +\n            mdist_xy(ords[i].c, ords[i].d, 400, 400);\n        score_id.push_back({s, i});\n    }\n\n    sort(score_id.begin(), score_id.end());\n\n    vector<int> initial;\n    for (int i = 0; i < 50; i++) initial.push_back(score_id[i].second);\n\n    Solution best = build_solution(initial);\n\n    vector<int> pool;\n    int pool_size = 180;\n    for (int i = 0; i < pool_size; i++) pool.push_back(score_id[i].second);\n\n    mt19937 rng(1234567);\n\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> cur_ids = best.ids;\n    Solution cur = best;\n\n    while (true) {\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        vector<int> next_ids = cur_ids;\n\n        unordered_set<int> selected(next_ids.begin(), next_ids.end());\n\n        int remove_pos = uniform_int_distribution<int>(0, 49)(rng);\n\n        vector<int> candidates;\n        for (int id : pool) {\n            if (!selected.count(id)) candidates.push_back(id);\n        }\n        if (candidates.empty()) continue;\n\n        int add_id = candidates[uniform_int_distribution<int>(0, (int)candidates.size() - 1)(rng)];\n        next_ids[remove_pos] = add_id;\n\n        sort(next_ids.begin(), next_ids.end());\n        next_ids.erase(unique(next_ids.begin(), next_ids.end()), next_ids.end());\n        if ((int)next_ids.size() != 50) continue;\n\n        Solution nxt = build_solution(next_ids);\n\n        if (nxt.cost < cur.cost || uniform_real_distribution<double>(0.0, 1.0)(rng) < 0.002) {\n            cur = nxt;\n            cur_ids = next_ids;\n        }\n\n        if (nxt.cost < best.cost) {\n            best = nxt;\n        }\n    }\n\n    cout << 50;\n    for (int id : best.ids) {\n        cout << ' ' << id + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (auto& p : best.route) {\n        cout << ' ' << p.x << ' ' << p.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#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) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[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 (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct KEdge {\n    int w;\n    int id;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return id < other.id;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = x[edges[i].u] - x[edges[i].v];\n        long long dy = y[edges[i].u] - y[edges[i].v];\n        edges[i].d = (int)llround(sqrt((double)(dx * dx + dy * dy)));\n    }\n\n    DSU accepted(N);\n    vector<int> actual(M, -1);\n    vector<char> used(M, 0);\n\n    double coef = 1.92;\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        actual[i] = l;\n\n        bool take = false;\n\n        int ru = accepted.find(edges[i].u);\n        int rv = accepted.find(edges[i].v);\n\n        if (ru != rv) {\n            // Safety check:\n            // If the current edge is a bridge among accepted-components\n            // using only edges i..M-1, then it must be taken.\n            {\n                unordered_map<int, int> mp;\n                mp.reserve(N * 2);\n                vector<int> roots;\n                roots.reserve(N);\n                for (int v = 0; v < N; v++) {\n                    int r = accepted.find(v);\n                    if (!mp.count(r)) {\n                        int id = (int)mp.size();\n                        mp[r] = id;\n                        roots.push_back(r);\n                    }\n                }\n\n                int C = (int)mp.size();\n                vector<vector<pair<int,int>>> g(C);\n                g.reserve(C);\n\n                for (int j = i; j < M; j++) {\n                    int a = mp[accepted.find(edges[j].u)];\n                    int b = mp[accepted.find(edges[j].v)];\n                    if (a == b) continue;\n                    g[a].push_back({b, j});\n                    g[b].push_back({a, j});\n                }\n\n                int cu = mp[ru], cv = mp[rv];\n                vector<int> tin(C, -1), low(C, -1);\n                int timer = 0;\n                bool is_bridge = false;\n\n                function<void(int,int)> dfs = [&](int v, int pe) {\n                    tin[v] = low[v] = timer++;\n                    for (auto [to, eid] : g[v]) {\n                        if (eid == pe) continue;\n                        if (tin[to] != -1) {\n                            low[v] = min(low[v], tin[to]);\n                        } else {\n                            dfs(to, eid);\n                            low[v] = min(low[v], low[to]);\n                            if (low[to] > tin[v] && eid == i) {\n                                is_bridge = true;\n                            }\n                        }\n                    }\n                };\n\n                for (int v = 0; v < C; v++) {\n                    if (tin[v] == -1) dfs(v, -1);\n                }\n\n                if (is_bridge) take = true;\n            }\n\n            // Predicted MST membership test.\n            if (!take) {\n                vector<KEdge> order;\n                order.reserve(M);\n\n                for (int j = 0; j < M; j++) {\n                    int w;\n                    if (j <= i) {\n                        w = actual[j];\n                    } else {\n                        w = max(1, (int)round(coef * edges[j].d));\n                    }\n                    order.push_back({w, j});\n                }\n\n                sort(order.begin(), order.end());\n\n                DSU tmp(N);\n                bool in_predicted_mst = false;\n\n                for (auto [w, id] : order) {\n                    if (tmp.unite(edges[id].u, edges[id].v)) {\n                        if (id == i) {\n                            in_predicted_mst = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (in_predicted_mst) {\n                    // Avoid very bad edges unless needed.\n                    double ratio = (double)l / max(1, edges[i].d);\n\n                    int comps = 0;\n                    for (int v = 0; v < N; v++) {\n                        if (accepted.find(v) == v) comps++;\n                    }\n\n                    double progress = (double)i / M;\n                    double limit = 2.18 - 0.28 * progress;\n                    if (comps > 80) limit += 0.10;\n                    if (comps < 30) limit -= 0.10;\n\n                    if (ratio <= limit || i > M - 420) {\n                        take = true;\n                    }\n                }\n            }\n\n            // Endgame: be less selective.\n            if (!take) {\n                int comps = 0;\n                for (int v = 0; v < N; v++) {\n                    if (accepted.find(v) == v) comps++;\n                }\n\n                int remaining = M - i;\n                if (remaining <= comps * 2) {\n                    take = true;\n                }\n            }\n        }\n\n        if (take) {\n            accepted.unite(edges[i].u, edges[i].v);\n            used[i] = 1;\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n        cout.flush();\n\n        // Slight adaptation from observed average ratio.\n        if (i > 0 && i % 100 == 0) {\n            double sum = 0;\n            int cnt = 0;\n            for (int j = 0; j <= i; j++) {\n                sum += (double)actual[j] / max(1, edges[j].d);\n                cnt++;\n            }\n            double avg = sum / cnt;\n            coef = 0.75 * coef + 0.25 * avg;\n            coef = min(2.08, max(1.78, coef));\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nconst int H = 30, W = 30;\nconst int TURNS = 300;\nint N, M;\nvector<Pos> pet, human_pos;\nvector<int> pet_type;\nbool wall[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar mvC[4] = {'U', 'D', 'L', 'R'};\nchar buildC[4] = {'u', 'd', 'l', 'r'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\nint dirIndex(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    if (c == 'R') return 3;\n    return -1;\n}\n\nbool hasPet(int x, int y) {\n    for (auto &p : pet) if (p.x == x && p.y == y) return true;\n    return false;\n}\n\nbool hasHuman(int x, int y) {\n    for (auto &h : human_pos) if (h.x == x && h.y == y) return true;\n    return false;\n}\n\nbool nearPetOrPet(int x, int y) {\n    if (hasPet(x, y)) return true;\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && hasPet(nx, ny)) return true;\n    }\n    return false;\n}\n\nbool canBuildCell(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (wall[x][y]) return true; // allowed, but useless\n    if (hasPet(x, y) || hasHuman(x, y)) return false;\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && hasPet(nx, ny)) return false;\n    }\n    return true;\n}\n\nbool canMoveCell(int x, int y) {\n    return inside(x, y) && !wall[x][y];\n}\n\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nchar stepToward(Pos cur, Pos goal) {\n    int bestd = 1e9;\n    char best = '.';\n    for (int d = 0; d < 4; d++) {\n        int nx = cur.x + dx[d], ny = cur.y + dy[d];\n        if (!canMoveCell(nx, ny)) continue;\n        int md = abs(nx - goal.x) + abs(ny - goal.y);\n        if (md < bestd) {\n            bestd = md;\n            best = mvC[d];\n        }\n    }\n    return best;\n}\n\nvoid applyHumanActions(const string &ans) {\n    vector<Pos> newh = human_pos;\n    vector<pair<int,int>> builds;\n    for (int i = 0; i < M; i++) {\n        char c = ans[i];\n        if (c >= 'a' && c <= 'z') {\n            int d = -1;\n            if (c == 'u') d = 0;\n            if (c == 'd') d = 1;\n            if (c == 'l') d = 2;\n            if (c == 'r') d = 3;\n            if (d >= 0) {\n                int nx = human_pos[i].x + dx[d], ny = human_pos[i].y + dy[d];\n                if (inside(nx, ny) && canBuildCell(nx, ny)) builds.push_back({nx, ny});\n            }\n        }\n    }\n    for (auto &b : builds) wall[b.first][b.second] = true;\n    for (int i = 0; i < M; i++) {\n        char c = ans[i];\n        int d = dirIndex(c);\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d], ny = human_pos[i].y + dy[d];\n            if (canMoveCell(nx, ny)) newh[i] = {nx, ny};\n        }\n    }\n    human_pos = newh;\n}\n\nvoid applyPetMoves(const vector<string>& moves) {\n    for (int i = 0; i < N; i++) {\n        for (char c : moves[i]) {\n            int d = dirIndex(c);\n            if (d >= 0) {\n                int nx = pet[i].x + dx[d], ny = pet[i].y + dy[d];\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pet[i] = {nx, ny};\n                }\n            }\n        }\n    }\n}\n\nint nearestPetDist(Pos p) {\n    int ret = 1000;\n    for (auto &q : pet) ret = min(ret, manhattan(p, q));\n    return ret;\n}\n\n// Very robust baseline strategy:\n// - Move all humans to the central vertical \"construction line\" y=15.\n// - Build as much of a vertical wall at y=15 as possible from adjacent cells y=14 or y=16.\n// - Keep humans spread over different rows.\n// This frequently splits the board into large components; if most pets are on one side,\n// humans on the other side get good score.  The strategy is intentionally conservative\n// to avoid illegal outputs in the interactive judge.\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pet.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; i++) cin >> pet[i].x >> pet[i].y >> pet_type[i];\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; i++) cin >> human_pos[i].x >> human_pos[i].y;\n\n    memset(wall, 0, sizeof(wall));\n\n    vector<int> targetRow(M);\n    for (int i = 0; i < M; i++) {\n        // spread roughly evenly, avoiding exact borders a little\n        targetRow[i] = 2 + (26 * i) / max(1, M - 1);\n        if (M == 1) targetRow[i] = 15;\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        string ans(M, '.');\n\n        // Phase 1: go to construction positions.\n        // Prefer y=14; if starting on right side, y=16 can be used too.\n        for (int i = 0; i < M; i++) {\n            Pos cur = human_pos[i];\n            Pos goal;\n            goal.x = targetRow[i];\n            goal.y = (cur.y <= 15 ? 14 : 16);\n\n            // Once near line, align row first.\n            if (cur.y == 14 || cur.y == 16) goal.y = cur.y;\n\n            // If not at target row/side, move.\n            if (cur.x != goal.x || cur.y != goal.y) {\n                char c = stepToward(cur, goal);\n                if (c != '.') ans[i] = c;\n            }\n        }\n\n        // Phase 2: if positioned beside column 15, build it.\n        // Humans construct adjacent wall cells when safe.\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n            Pos cur = human_pos[i];\n\n            if (cur.y == 14) {\n                int bx = cur.x, by = 15;\n                if (!wall[bx][by] && canBuildCell(bx, by)) ans[i] = 'r';\n            } else if (cur.y == 16) {\n                int bx = cur.x, by = 15;\n                if (!wall[bx][by] && canBuildCell(bx, by)) ans[i] = 'l';\n            }\n        }\n\n        // Phase 3: patrol along the line to fill missing wall cells.\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n            Pos cur = human_pos[i];\n            if (cur.y != 14 && cur.y != 16) continue;\n\n            // Find nearest unbuilt cell in column 15 that seems safe.\n            int bestx = -1, best = 1000;\n            for (int x = 1; x <= 30; x++) {\n                if (wall[x][15]) continue;\n                if (!canBuildCell(x, 15)) continue;\n                int dist = abs(cur.x - x);\n                if (dist < best) {\n                    best = dist;\n                    bestx = x;\n                }\n            }\n            if (bestx != -1) {\n                if (cur.x < bestx && canMoveCell(cur.x + 1, cur.y)) ans[i] = 'D';\n                else if (cur.x > bestx && canMoveCell(cur.x - 1, cur.y)) ans[i] = 'U';\n                else {\n                    if (cur.y == 14 && canBuildCell(cur.x, 15)) ans[i] = 'r';\n                    if (cur.y == 16 && canBuildCell(cur.x, 15)) ans[i] = 'l';\n                }\n            }\n        }\n\n        // Collision with newly built cells is already avoided by self-simulation;\n        // the official judge also validates based on current state.\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n\n        vector<string> pm(N);\n        for (int i = 0; i < N; i++) cin >> pm[i];\n        applyPetMoves(pm);\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int V = 400;\nstatic constexpr int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble pforget;\nstring hwall[N];\nstring vwall[N - 1];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\nint nxt[V][4];\nint distT[V];\nint distS[V];\n\nmt19937 rng(123456789);\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\nbool canMove(int i, int j, int d) {\n    if (d == 0) {\n        if (i == 0) return false;\n        return vwall[i - 1][j] == '0';\n    }\n    if (d == 1) {\n        if (i == N - 1) return false;\n        return vwall[i][j] == '0';\n    }\n    if (d == 2) {\n        if (j == 0) return false;\n        return hwall[i][j - 1] == '0';\n    }\n    if (d == 3) {\n        if (j == N - 1) return false;\n        return hwall[i][j] == '0';\n    }\n    return false;\n}\n\nvoid buildGraph() {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int v = id(i, j);\n            for (int d = 0; d < 4; d++) {\n                if (canMove(i, j, d)) nxt[v][d] = id(i + di[d], j + dj[d]);\n                else nxt[v][d] = v;\n            }\n        }\n    }\n}\n\nvoid bfsFrom(int src, int dist[V]) {\n    fill(dist, dist + V, 1e9);\n    queue<int> q;\n    dist[src] = 0;\n    q.push(src);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (dist[u] > dist[v] + 1) {\n                dist[u] = dist[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n}\n\nstring shortestPath(int s, int t, bool randomTie = false) {\n    vector<int> pre(V, -1), pred(V, -1);\n    queue<int> q;\n    pre[s] = s;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == t) break;\n\n        array<int, 4> ord = {0, 1, 2, 3};\n        if (randomTie) shuffle(ord.begin(), ord.end(), rng);\n\n        for (int d : ord) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (pre[u] == -1) {\n                pre[u] = v;\n                pred[u] = d;\n                q.push(u);\n            }\n        }\n    }\n\n    if (pre[t] == -1) return \"\";\n\n    string res;\n    int cur = t;\n    while (cur != s) {\n        int d = pred[cur];\n        res.push_back(dc[d]);\n        cur = pre[cur];\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\ndouble evaluate(const string& route) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    static double prob[V], np[V];\n    fill(prob, prob + V, 0.0);\n    prob[s] = 1.0;\n\n    double expected = 0.0;\n\n    for (int step = 0; step < (int)route.size(); step++) {\n        int d;\n        if (route[step] == 'U') d = 0;\n        else if (route[step] == 'D') d = 1;\n        else if (route[step] == 'L') d = 2;\n        else d = 3;\n\n        fill(np, np + V, 0.0);\n\n        double moveProb = 1.0 - pforget;\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * moveProb;\n        }\n\n        double reach = np[t];\n        if (reach > 0.0) {\n            expected += reach * (401.0 - (step + 1));\n            np[t] = 0.0;\n        }\n\n        memcpy(prob, np, sizeof(prob));\n    }\n\n    return expected;\n}\n\nstring repeatChars(const string& base, int r) {\n    string res;\n    for (char c : base) {\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n    return res;\n}\n\nstring repeatWhole(const string& base) {\n    string res;\n    while ((int)res.size() < MAXL) {\n        for (char c : base) {\n            if ((int)res.size() >= MAXL) break;\n            res.push_back(c);\n        }\n    }\n    return res;\n}\n\nstring distDescentPath(int repeatBias, bool randomTie) {\n    int cur = id(si_, sj_);\n    int t = id(ti_, tj_);\n    string route;\n\n    while (cur != t && (int)route.size() < MAXL) {\n        vector<int> cand;\n        int best = distT[cur];\n\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[cur][d];\n            if (u != cur && distT[u] < best) {\n                cand.push_back(d);\n            }\n        }\n\n        if (cand.empty()) break;\n\n        int d;\n        if (randomTie) d = cand[rng() % cand.size()];\n        else {\n            d = cand[0];\n            for (int x : cand) {\n                if (distT[nxt[cur][x]] < distT[nxt[cur][d]]) d = x;\n            }\n        }\n\n        int rep = repeatBias;\n        for (int k = 0; k < rep && (int)route.size() < MAXL; k++) {\n            route.push_back(dc[d]);\n        }\n\n        cur = nxt[cur][d];\n    }\n\n    return route;\n}\n\nstring greedyDistribution(double temperature, double stayPenalty, double reachBonus, int lenLimit = MAXL) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<double> prob(V, 0.0), np(V, 0.0);\n    prob[s] = 1.0;\n\n    string route;\n\n    for (int step = 0; step < lenLimit; step++) {\n        double bestScore = 1e100;\n        vector<int> bestDirs;\n\n        for (int d = 0; d < 4; d++) {\n            fill(np.begin(), np.end(), 0.0);\n\n            for (int v = 0; v < V; v++) {\n                double pr = prob[v];\n                if (pr == 0.0) continue;\n                np[v] += pr * pforget;\n                np[nxt[v][d]] += pr * (1.0 - pforget);\n            }\n\n            double score = 0.0;\n\n            for (int v = 0; v < V; v++) {\n                double pr = np[v];\n                if (pr == 0.0) continue;\n\n                if (v == t) {\n                    score -= reachBonus * pr * (MAXL - step);\n                    continue;\n                }\n\n                score += pr * distT[v];\n\n                if (nxt[v][d] == v) {\n                    score += stayPenalty * pr;\n                }\n            }\n\n            if (temperature > 0.0) {\n                uniform_real_distribution<double> ud(-temperature, temperature);\n                score += ud(rng);\n            }\n\n            if (score + 1e-12 < bestScore) {\n                bestScore = score;\n                bestDirs.clear();\n                bestDirs.push_back(d);\n            } else if (abs(score - bestScore) < 1e-12) {\n                bestDirs.push_back(d);\n            }\n        }\n\n        int d = bestDirs[rng() % bestDirs.size()];\n        route.push_back(dc[d]);\n\n        fill(np.begin(), np.end(), 0.0);\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * (1.0 - pforget);\n        }\n\n        np[t] = 0.0;\n        prob.swap(np);\n\n        double alive = accumulate(prob.begin(), prob.end(), 0.0);\n        if (alive < 1e-12) break;\n    }\n\n    return route;\n}\n\nstruct BeamNode {\n    string route;\n    array<double, V> prob;\n    double heuristic;\n};\n\nstring beamSearchRoute(int beamWidth, int lenLimit, double reachWeight, double distWeight) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<BeamNode> beam;\n    BeamNode init;\n    init.route.clear();\n    init.prob.fill(0.0);\n    init.prob[s] = 1.0;\n    init.heuristic = 0.0;\n    beam.push_back(init);\n\n    for (int step = 0; step < lenLimit; step++) {\n        vector<BeamNode> nb;\n        nb.reserve(beam.size() * 4);\n\n        for (const auto& node : beam) {\n            for (int d = 0; d < 4; d++) {\n                BeamNode x;\n                x.route = node.route;\n                x.route.push_back(dc[d]);\n                x.prob.fill(0.0);\n\n                double reached = 0.0;\n                for (int v = 0; v < V; v++) {\n                    double pr = node.prob[v];\n                    if (pr == 0.0) continue;\n                    x.prob[v] += pr * pforget;\n                    x.prob[nxt[v][d]] += pr * (1.0 - pforget);\n                }\n\n                reached = x.prob[t];\n                x.prob[t] = 0.0;\n\n                double alive = 0.0;\n                double dsum = 0.0;\n                for (int v = 0; v < V; v++) {\n                    alive += x.prob[v];\n                    dsum += x.prob[v] * distT[v];\n                }\n\n                x.heuristic = node.heuristic\n                            + reached * reachWeight * (401.0 - (step + 1))\n                            - dsum * distWeight\n                            - alive * 0.02;\n\n                nb.push_back(move(x));\n            }\n        }\n\n        sort(nb.begin(), nb.end(), [](const BeamNode& a, const BeamNode& b) {\n            return a.heuristic > b.heuristic;\n        });\n\n        if ((int)nb.size() > beamWidth) nb.resize(beamWidth);\n        beam.swap(nb);\n    }\n\n    string best;\n    double bestVal = -1.0;\n    for (auto& node : beam) {\n        double val = evaluate(node.route);\n        if (val > bestVal) {\n            bestVal = val;\n            best = node.route;\n        }\n    }\n\n    return best;\n}\n\nchar randomBiasedChar() {\n    // Since target is bottom-right, D/R are generally more useful.\n    int x = rng() % 100;\n    if (x < 38) return 'D';\n    if (x < 76) return 'R';\n    if (x < 88) return 'U';\n    return 'L';\n}\n\nstring mutateString(string s, double strength) {\n    if (s.empty()) s = string(1, randomBiasedChar());\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n\n    int ops = 1 + (rng() % max(1, (int)strength));\n\n    for (int op = 0; op < ops; op++) {\n        int type = rng() % 5;\n\n        if (type == 0) {\n            // Replace one character.\n            int pos = rng() % s.size();\n            char c = dc[rng() % 4];\n            s[pos] = c;\n        } else if (type == 1 && (int)s.size() < MAXL) {\n            // Insert.\n            int pos = rng() % (s.size() + 1);\n            char c = randomBiasedChar();\n            s.insert(s.begin() + pos, c);\n        } else if (type == 2 && s.size() > 1) {\n            // Delete.\n            int pos = rng() % s.size();\n            s.erase(s.begin() + pos);\n        } else if (type == 3) {\n            // Change short segment.\n            int len = 1 + rng() % 8;\n            int pos = rng() % s.size();\n            for (int k = 0; k < len && pos + k < (int)s.size(); k++) {\n                s[pos + k] = randomBiasedChar();\n            }\n        } else {\n            // Duplicate local character/segment.\n            if ((int)s.size() < MAXL) {\n                int pos = rng() % s.size();\n                int len = 1 + rng() % min(6, (int)s.size() - pos);\n                string seg = s.substr(pos, len);\n                int ipos = rng() % (s.size() + 1);\n                s.insert(ipos, seg);\n                if ((int)s.size() > MAXL) s.resize(MAXL);\n            }\n        }\n    }\n\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n    return s;\n}\n\nvoid deterministicSingleCharImprove(string& best, double& bestVal, chrono::steady_clock::time_point endTime) {\n    bool improved = true;\n\n    while (improved && chrono::steady_clock::now() < endTime) {\n        improved = false;\n\n        vector<int> positions(best.size());\n        iota(positions.begin(), positions.end(), 0);\n        shuffle(positions.begin(), positions.end(), rng);\n\n        for (int pos : positions) {\n            if (chrono::steady_clock::now() >= endTime) break;\n\n            char old = best[pos];\n            char bestChar = old;\n            double localBest = bestVal;\n\n            for (char c : {'U', 'D', 'L', 'R'}) {\n                if (c == old) continue;\n                string cand = best;\n                cand[pos] = c;\n                double val = evaluate(cand);\n                if (val > localBest) {\n                    localBest = val;\n                    bestChar = c;\n                }\n            }\n\n            if (bestChar != old) {\n                best[pos] = bestChar;\n                bestVal = localBest;\n                improved = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n    auto endTime = startTime + chrono::milliseconds(1850);\n\n    cin >> si_ >> sj_ >> ti_ >> tj_ >> pforget;\n    for (int i = 0; i < N; i++) cin >> hwall[i];\n    for (int i = 0; i < N - 1; i++) cin >> vwall[i];\n\n    rng.seed(\n        si_ * 1000003u +\n        sj_ * 9176u +\n        ti_ * 19260817u +\n        tj_ * 998244353u +\n        (unsigned)(pforget * 1000)\n    );\n\n    buildGraph();\n\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    bfsFrom(t, distT);\n    bfsFrom(s, distS);\n\n    vector<string> candidates;\n\n    string sp = shortestPath(s, t);\n    if (!sp.empty()) {\n        candidates.push_back(sp);\n        candidates.push_back(repeatWhole(sp));\n\n        for (int r = 2; r <= 10; r++) {\n            candidates.push_back(repeatChars(sp, r));\n        }\n\n        for (int trial = 0; trial < 60; trial++) {\n            string rsp = shortestPath(s, t, true);\n            if (!rsp.empty()) {\n                candidates.push_back(rsp);\n                candidates.push_back(repeatChars(rsp, 2 + rng() % 6));\n                candidates.push_back(repeatWhole(rsp));\n            }\n        }\n    }\n\n    for (int r = 1; r <= 10; r++) {\n        candidates.push_back(distDescentPath(r, false));\n        for (int k = 0; k < 8; k++) {\n            candidates.push_back(distDescentPath(r, true));\n        }\n    }\n\n    vector<double> temps = {0.0, 0.02, 0.05, 0.1, 0.2, 0.4, 0.8, 1.5, 3.0};\n    vector<double> penalties = {0.0, 0.05, 0.15, 0.3, 0.7, 1.5, 3.0};\n    vector<double> bonuses = {0.2, 0.5, 1.0, 2.0, 4.0};\n\n    for (double temp : temps) {\n        for (double pen : penalties) {\n            for (double bonus : bonuses) {\n                candidates.push_back(greedyDistribution(temp, pen, bonus));\n            }\n        }\n    }\n\n    // Beam search candidates. Small beam to stay fast.\n    candidates.push_back(beamSearchRoute(8, 120, 1.0, 0.03));\n    candidates.push_back(beamSearchRoute(10, 150, 1.0, 0.02));\n    candidates.push_back(beamSearchRoute(12, 200, 1.0, 0.015));\n\n    // Waypoint candidates.\n    vector<int> cells(V);\n    iota(cells.begin(), cells.end(), 0);\n\n    sort(cells.begin(), cells.end(), [&](int a, int b) {\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n\n        int ascore = distS[a] + distT[a] + abs(ai - 10) + abs(aj - 10);\n        int bscore = distS[b] + distT[b] + abs(bi - 10) + abs(bj - 10);\n        return ascore < bscore;\n    });\n\n    for (int idx = 0; idx < min(V, 100); idx++) {\n        int mid = cells[idx];\n\n        string a = shortestPath(s, mid, true);\n        string b = shortestPath(mid, t, true);\n\n        if (a.empty() || b.empty()) continue;\n\n        string path = a + b;\n        if ((int)path.size() > MAXL) path.resize(MAXL);\n\n        candidates.push_back(path);\n        candidates.push_back(repeatWhole(path));\n\n        for (int r = 2; r <= 5; r++) {\n            candidates.push_back(repeatChars(path, r));\n        }\n    }\n\n    // Simple biased random strings.\n    for (int trial = 0; trial < 300; trial++) {\n        string r;\n        int len = 80 + rng() % 121;\n        for (int i = 0; i < len; i++) {\n            r.push_back(randomBiasedChar());\n        }\n        candidates.push_back(r);\n    }\n\n    string best = sp.empty() ? string(\"D\") : sp;\n    double bestVal = evaluate(best);\n\n    // Evaluate generated candidates.\n    for (string cand : candidates) {\n        if (chrono::steady_clock::now() >= endTime) break;\n\n        if (cand.empty()) continue;\n        if ((int)cand.size() > MAXL) cand.resize(MAXL);\n\n        double val = evaluate(cand);\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n    }\n\n    // Deterministic improvement on best.\n    auto improveEnd = startTime + chrono::milliseconds(1450);\n    deterministicSingleCharImprove(best, bestVal, improveEnd);\n\n    // Random hill climbing / simulated mutation.\n    int stagnant = 0;\n    while (chrono::steady_clock::now() < endTime) {\n        double strength = 1.0 + min(20, stagnant / 20);\n        string cand = mutateString(best, strength);\n        double val = evaluate(cand);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n            stagnant = 0;\n        } else {\n            stagnant++;\n        }\n\n        // Occasionally mutate a repeated shortest path, to escape local optimum.\n        if (stagnant % 200 == 199 && !sp.empty()) {\n            string base;\n            int mode = rng() % 3;\n            if (mode == 0) base = repeatChars(sp, 2 + rng() % 8);\n            else if (mode == 1) base = repeatWhole(sp);\n            else base = greedyDistribution(0.5, 0.5, 1.0);\n\n            string cand2 = mutateString(base, 10);\n            double val2 = evaluate(cand2);\n            if (val2 > bestVal) {\n                bestVal = val2;\n                best = cand2;\n                stagnant = 0;\n            }\n        }\n    }\n\n    if (best.empty()) best = \"D\";\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n\n    cout << best << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N * 4;\n\nint to_dir[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\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) {\n        return (int)(next_u64() % n);\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint rotate_state(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (0 <= t && t <= 3) t = (t + 1) & 3;\n        else if (t == 4) t = 5;\n        else if (t == 5) t = 4;\n        else if (t == 6) t = 7;\n        else if (t == 7) t = 6;\n    }\n    return t;\n}\n\nint norm_pair(int a, int b) {\n    if (a > b) swap(a, b);\n    return a * 4 + b;\n}\n\nbool state_has_pair(int t, int a, int b) {\n    int p = norm_pair(a, b);\n    for (int d = 0; d < 4; d++) {\n        if (to_dir[t][d] != -1) {\n            int q = norm_pair(d, to_dir[t][d]);\n            if (p == q) return true;\n        }\n    }\n    return false;\n}\n\nint rotation_for_pair(int base, int a, int b) {\n    for (int r = 0; r < 4; r++) {\n        int t = rotate_state(base, r);\n        if (state_has_pair(t, a, b)) return r;\n    }\n    return -1;\n}\n\nstruct Rect {\n    int r1, c1, r2, c2;\n    int len;\n    uint64_t mask[15]; // 900 bits\n};\n\nstruct Solver {\n    vector<string> s;\n    array<int, N * N> base{};\n    array<int, N * N> rot{};\n    array<int, N * N> tile{};\n    array<int, N * N> best_rot{};\n    array<int, N * N> fixed_cell{};\n    XorShift rng;\n\n    int id(int i, int j, int d) const {\n        return ((i * N + j) << 2) | d;\n    }\n\n    tuple<int,int,int> decode(int x) const {\n        int d = x & 3;\n        x >>= 2;\n        return {x / N, x % N, d};\n    }\n\n    int nxt(int x) const {\n        auto [i, j, d] = decode(x);\n        int t = tile[i * N + j];\n        int d2 = to_dir[t][d];\n        if (d2 == -1) return -1;\n        int ni = i + di[d2], nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n        return id(ni, nj, (d2 + 2) & 3);\n    }\n\n    long long evaluate() const {\n        static int state[V], seen[V], dep[V];\n\n        for (int i = 0; i < V; i++) {\n            state[i] = 0;\n            seen[i] = -1;\n            dep[i] = 0;\n        }\n\n        vector<int> loops;\n        loops.reserve(32);\n\n        for (int st = 0; st < V; st++) {\n            if (state[st]) continue;\n\n            int cur = st;\n            vector<int> path;\n            path.reserve(256);\n\n            while (true) {\n                if (cur == -1) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 2) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 1) {\n                    if (seen[cur] == st) {\n                        int len = (int)path.size() - dep[cur];\n                        if (len > 0) loops.push_back(len);\n                    }\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n\n                state[cur] = 1;\n                seen[cur] = st;\n                dep[cur] = (int)path.size();\n                path.push_back(cur);\n                cur = nxt(cur);\n            }\n        }\n\n        if ((int)loops.size() <= 1) return 0;\n        nth_element(loops.begin(), loops.begin(), loops.end(), greater<int>());\n        int a = loops[0];\n        nth_element(loops.begin() + 1, loops.begin() + 1, loops.end(), greater<int>());\n        int b = loops[1];\n        return 1LL * a * b;\n    }\n\n    void rebuild_tile() {\n        for (int i = 0; i < N * N; i++) {\n            tile[i] = rotate_state(base[i], rot[i]);\n        }\n    }\n\n    bool desired_pair_for_rect(const Rect& rc, int i, int j, int &a, int &b) const {\n        bool top = (i == rc.r1);\n        bool bottom = (i == rc.r2);\n        bool left = (j == rc.c1);\n        bool right = (j == rc.c2);\n\n        if (!top && !bottom && !left && !right) return false;\n\n        if (top && left) {\n            a = 2; b = 3; // right-down\n        } else if (top && right) {\n            a = 0; b = 3; // left-down\n        } else if (bottom && left) {\n            a = 1; b = 2; // up-right\n        } else if (bottom && right) {\n            a = 0; b = 1; // left-up\n        } else if (top || bottom) {\n            a = 0; b = 2; // horizontal\n        } else {\n            a = 1; b = 3; // vertical\n        }\n        return true;\n    }\n\n    bool build_rect(int r1, int c1, int r2, int c2, Rect &rc) const {\n        if (r2 <= r1 || c2 <= c1) return false;\n\n        rc.r1 = r1; rc.c1 = c1; rc.r2 = r2; rc.c2 = c2;\n        rc.len = 2 * ((r2 - r1) + (c2 - c1));\n        memset(rc.mask, 0, sizeof(rc.mask));\n\n        for (int i = r1; i <= r2; i++) {\n            for (int j = c1; j <= c2; j++) {\n                int a, b;\n                if (!desired_pair_for_rect(rc, i, j, a, b)) continue;\n                int idx = i * N + j;\n                if (rotation_for_pair(base[idx], a, b) == -1) return false;\n                rc.mask[idx >> 6] |= 1ULL << (idx & 63);\n            }\n        }\n        return true;\n    }\n\n    bool disjoint(const Rect& a, const Rect& b) const {\n        for (int k = 0; k < 15; k++) {\n            if (a.mask[k] & b.mask[k]) return false;\n        }\n        return true;\n    }\n\n    void apply_rect(const Rect& rc) {\n        for (int i = rc.r1; i <= rc.r2; i++) {\n            for (int j = rc.c1; j <= rc.c2; j++) {\n                int a, b;\n                if (!desired_pair_for_rect(rc, i, j, a, b)) continue;\n                int idx = i * N + j;\n                int r = rotation_for_pair(base[idx], a, b);\n                if (r >= 0) {\n                    rot[idx] = r;\n                    fixed_cell[idx] = 1;\n                }\n            }\n        }\n    }\n\n    void fill_random_free() {\n        for (int i = 0; i < N * N; i++) {\n            if (fixed_cell[i]) continue;\n            int maxr = (base[i] <= 3 ? 4 : 2);\n            rot[i] = rng.next_int(maxr);\n        }\n        rebuild_tile();\n    }\n\n    void construct_rect_solution() {\n        vector<Rect> rects;\n\n        // Enumerate many rectangles. Smallest side 2 is allowed.\n        for (int r1 = 0; r1 < N; r1++) {\n            for (int r2 = r1 + 1; r2 < N; r2++) {\n                for (int c1 = 0; c1 < N; c1++) {\n                    for (int c2 = c1 + 1; c2 < N; c2++) {\n                        int len = 2 * ((r2 - r1) + (c2 - c1));\n                        if (len < 16) continue;\n                        Rect rc;\n                        if (build_rect(r1, c1, r2, c2, rc)) {\n                            rects.push_back(rc);\n                        }\n                    }\n                }\n            }\n        }\n\n        sort(rects.begin(), rects.end(), [](const Rect& a, const Rect& b) {\n            return a.len > b.len;\n        });\n\n        // Limit candidates for pair search to save time.\n        if ((int)rects.size() > 2500) rects.resize(2500);\n\n        long long best_prod = -1;\n        int bi = -1, bj = -1;\n\n        for (int i = 0; i < (int)rects.size(); i++) {\n            if (1LL * rects[i].len * rects[i].len < best_prod) break;\n            for (int j = i + 1; j < (int)rects.size(); j++) {\n                long long prod = 1LL * rects[i].len * rects[j].len;\n                if (prod <= best_prod) break;\n                if (disjoint(rects[i], rects[j])) {\n                    best_prod = prod;\n                    bi = i;\n                    bj = j;\n                    break;\n                }\n            }\n        }\n\n        fixed_cell.fill(0);\n        rot.fill(0);\n\n        if (bi != -1) {\n            apply_rect(rects[bi]);\n            apply_rect(rects[bj]);\n        }\n\n        fill_random_free();\n    }\n\n    void improve_free_cells(double until_sec, const Timer& timer) {\n        long long cur = evaluate();\n        long long best = cur;\n        best_rot = rot;\n\n        int iter = 0;\n        while (timer.elapsed() < until_sec) {\n            iter++;\n\n            int p = rng.next_int(N * N);\n            if (fixed_cell[p]) continue;\n\n            int oldr = rot[p];\n            int oldt = tile[p];\n\n            int maxr = (base[p] <= 3 ? 4 : 2);\n            int nr = rng.next_int(maxr);\n            if (nr == oldr) nr = (nr + 1) % maxr;\n\n            rot[p] = nr;\n            tile[p] = rotate_state(base[p], nr);\n\n            long long ns = evaluate();\n            long long diff = ns - cur;\n\n            double progress = timer.elapsed() / until_sec;\n            double temp = 2000.0 * (1.0 - progress) + 5.0;\n\n            bool accept = false;\n            if (diff >= 0) accept = true;\n            else if (rng.next_double() < exp((double)diff / temp)) accept = true;\n\n            if (accept) {\n                cur = ns;\n                if (cur > best) {\n                    best = cur;\n                    best_rot = rot;\n                }\n            } else {\n                rot[p] = oldr;\n                tile[p] = oldt;\n            }\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n    }\n\n    void solve() {\n        s.resize(N);\n        for (int i = 0; i < N; i++) cin >> s[i];\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                base[i * N + j] = s[i][j] - '0';\n            }\n        }\n\n        Timer timer;\n\n        construct_rect_solution();\n\n        long long best_score = evaluate();\n        best_rot = rot;\n\n        // Try several random fills while keeping the guaranteed rectangles.\n        while (timer.elapsed() < 0.35) {\n            auto saved_fixed = fixed_cell;\n            fill_random_free();\n            long long sc = evaluate();\n            if (sc > best_score) {\n                best_score = sc;\n                best_rot = rot;\n            }\n            fixed_cell = saved_fixed;\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n\n        improve_free_cells(1.90, timer);\n\n        string ans;\n        ans.reserve(N * N);\n        for (int i = 0; i < N * N; i++) {\n            ans.push_back(char('0' + rot[i]));\n        }\n        cout << ans << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        sz.assign(n,1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[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(sz[a]<sz[b]) swap(a,b);\n        p[b]=a; sz[a]+=sz[b];\n        return true;\n    }\n};\n\nint N,Tlim;\nvector<int> init_board;\nint total_cells;\n\nint hexval(char c){\n    if('0'<=c && c<='9') return c-'0';\n    return c-'a'+10;\n}\n\nstruct EvalResult {\n    int largest_tree;\n    int edges;\n    int cycle_edges;\n    int comps;\n};\n\nEvalResult evaluate_board(const vector<unsigned char>& b){\n    int M = N*N;\n    DSU dsu(M);\n    vector<int> active(M,0);\n    int active_cnt=0;\n    for(int i=0;i<M;i++){\n        if(b[i]!=0){\n            active[i]=1;\n            active_cnt++;\n        }\n    }\n\n    int edges=0, cyc=0;\n\n    for(int r=0;r<N;r++){\n        for(int c=0;c<N;c++){\n            int id=r*N+c;\n            if(!active[id]) continue;\n            int v=b[id];\n\n            if(c+1<N){\n                int nid=id+1;\n                if(active[nid] && (v&4) && (b[nid]&1)){\n                    edges++;\n                    if(!dsu.unite(id,nid)) cyc++;\n                }\n            }\n            if(r+1<N){\n                int nid=id+N;\n                if(active[nid] && (v&8) && (b[nid]&2)){\n                    edges++;\n                    if(!dsu.unite(id,nid)) cyc++;\n                }\n            }\n        }\n    }\n\n    unordered_map<int,int> vc, ec;\n    vc.reserve(M*2);\n    ec.reserve(M*2);\n\n    for(int i=0;i<M;i++){\n        if(active[i]) vc[dsu.find(i)]++;\n    }\n\n    for(int r=0;r<N;r++){\n        for(int c=0;c<N;c++){\n            int id=r*N+c;\n            if(!active[id]) continue;\n            int v=b[id];\n\n            if(c+1<N){\n                int nid=id+1;\n                if(active[nid] && (v&4) && (b[nid]&1)){\n                    ec[dsu.find(id)]++;\n                }\n            }\n            if(r+1<N){\n                int nid=id+N;\n                if(active[nid] && (v&8) && (b[nid]&2)){\n                    ec[dsu.find(id)]++;\n                }\n            }\n        }\n    }\n\n    int best=1;\n    int comps=0;\n    for(auto &kv: vc){\n        int root=kv.first;\n        int vcnt=kv.second;\n        int e=(ec.count(root)?ec[root]:0);\n        comps++;\n        if(e==vcnt-1){\n            best=max(best,vcnt);\n        }\n    }\n\n    return {best, edges, cyc, comps};\n}\n\nstruct State {\n    vector<unsigned char> b;\n    int emp;\n    string path;\n    char last;\n    int score;\n    int tree;\n};\n\nint heuristic_score(const vector<unsigned char>& b, int depth){\n    auto e = evaluate_board(b);\n    int full = N*N-1;\n\n    int score = 0;\n    score += e.largest_tree * 1000000;\n    score += e.edges * 2500;\n    score -= e.cycle_edges * 10000;\n    score -= e.comps * 300;\n    if(e.largest_tree == full){\n        score += 100000000;\n        score -= depth * 1000;\n    }\n    return score;\n}\n\nchar opposite(char c){\n    if(c=='U') return 'D';\n    if(c=='D') return 'U';\n    if(c=='L') return 'R';\n    if(c=='R') return 'L';\n    return '?';\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    total_cells = N*N;\n    init_board.resize(total_cells);\n\n    int emp=0;\n    for(int i=0;i<N;i++){\n        string s; cin >> s;\n        for(int j=0;j<N;j++){\n            int v=hexval(s[j]);\n            init_board[i*N+j]=v;\n            if(v==0) emp=i*N+j;\n        }\n    }\n\n    Timer timer;\n\n    vector<unsigned char> startb(total_cells);\n    for(int i=0;i<total_cells;i++) startb[i]=init_board[i];\n\n    State start;\n    start.b=startb;\n    start.emp=emp;\n    start.path=\"\";\n    start.last='?';\n    start.score=heuristic_score(start.b,0);\n    start.tree=evaluate_board(start.b).largest_tree;\n\n    State best=start;\n\n    int beamWidth;\n    if(N<=6) beamWidth=900;\n    else if(N==7) beamWidth=650;\n    else if(N==8) beamWidth=430;\n    else if(N==9) beamWidth=280;\n    else beamWidth=190;\n\n    vector<State> beam;\n    beam.push_back(start);\n\n    const int dr[4]={-1,1,0,0};\n    const int dc[4]={0,0,-1,1};\n    const char mv[4]={'U','D','L','R'};\n\n    int maxDepth=Tlim;\n\n    for(int depth=0; depth<maxDepth; depth++){\n        if(timer.elapsed() > 2.85) break;\n\n        vector<State> cand;\n        cand.reserve(beam.size()*3);\n\n        for(const State& st: beam){\n            int er=st.emp/N, ec=st.emp%N;\n\n            for(int k=0;k<4;k++){\n                char m=mv[k];\n                if(st.last!='?' && opposite(st.last)==m) continue;\n\n                int nr=er+dr[k], nc=ec+dc[k];\n                if(nr<0 || nr>=N || nc<0 || nc>=N) continue;\n\n                int np=nr*N+nc;\n\n                State ns;\n                ns.b=st.b;\n                swap(ns.b[st.emp], ns.b[np]);\n                ns.emp=np;\n                ns.path=st.path;\n                ns.path.push_back(m);\n                ns.last=m;\n\n                auto ev = evaluate_board(ns.b);\n                ns.tree=ev.largest_tree;\n\n                int score=0;\n                score += ev.largest_tree * 1000000;\n                score += ev.edges * 2500;\n                score -= ev.cycle_edges * 10000;\n                score -= ev.comps * 300;\n\n                if(ev.largest_tree == N*N-1){\n                    score += 100000000;\n                    score -= (int)ns.path.size()*5000;\n                } else {\n                    score -= (int)ns.path.size()*10;\n                }\n\n                // Mild preference for keeping the blank near the boundary,\n                // because the generated original blank was bottom-right.\n                int rr=ns.emp/N, cc=ns.emp%N;\n                int distBR=abs(rr-(N-1))+abs(cc-(N-1));\n                score -= distBR*80;\n\n                ns.score=score;\n\n                if(ns.tree > best.tree ||\n                   (ns.tree==best.tree && ns.score>best.score)){\n                    best=ns;\n                    if(best.tree==N*N-1){\n                        // Full tree found. Still could improve length, but good enough.\n                    }\n                }\n\n                cand.push_back(move(ns));\n            }\n        }\n\n        if(cand.empty()) break;\n\n        int keep = min<int>(beamWidth, cand.size());\n\n        nth_element(cand.begin(), cand.begin()+keep, cand.end(),\n            [](const State& a, const State& b){\n                return a.score > b.score;\n            });\n        cand.resize(keep);\n\n        sort(cand.begin(), cand.end(),\n            [](const State& a, const State& b){\n                return a.score > b.score;\n            });\n\n        // Remove exact duplicate boards among top states.\n        vector<State> nb;\n        nb.reserve(keep);\n        unordered_set<string> seen;\n        seen.reserve(keep*2);\n\n        for(auto &s: cand){\n            string key;\n            key.resize(total_cells);\n            for(int i=0;i<total_cells;i++) key[i]=char(s.b[i]);\n            key.push_back(char(s.emp));\n            if(seen.insert(key).second){\n                nb.push_back(move(s));\n                if((int)nb.size()>=keep) break;\n            }\n        }\n\n        beam.swap(nb);\n\n        // If full tree is found fairly early, spend a little more time trying\n        // but stop before timeout.\n        if(best.tree==N*N-1 && timer.elapsed()>1.5) break;\n    }\n\n    if((int)best.path.size() > Tlim) best.path.resize(Tlim);\n    cout << best.path << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n\n    vector<int> a(11);\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // ----------------------------------------------------------------------\n    // Heuristic:\n    // Use 100 parallel-ish grid cuts: vertical and horizontal quantile cuts.\n    //\n    // Since strawberries are uniformly random, a rectangular grid tends to\n    // create many small cells.  We choose the number of vertical / horizontal\n    // strips so that the average strawberries per cell is around the weighted\n    // average target piece size.  Then cut at quantiles so each strip contains\n    // a roughly equal number of strawberries.\n    //\n    // This is a simple, robust baseline for AHC012.\n    // ----------------------------------------------------------------------\n\n    int totalAttendees = 0;\n    for (int d = 1; d <= 10; d++) totalAttendees += a[d];\n\n    double avgTarget = (double)N / max(1, totalAttendees); // about 1..10\n    int desiredCells = max(1, (int)round((double)N / avgTarget)); // roughly attendees count\n    desiredCells = min(desiredCells, K * K / 4);\n\n    // Need (vx+1)*(hy+1) cells, vx+hy<=100.\n    // Select vx,hy minimizing difference from desiredCells and balanced aspect.\n    int bestV = 50, bestH = 50;\n    double bestCost = 1e100;\n    for (int vx = 0; vx <= K; vx++) {\n        for (int hy = 0; hy + vx <= K; hy++) {\n            int cells = (vx + 1) * (hy + 1);\n            double cost = abs(cells - desiredCells);\n            cost += 0.05 * abs(vx - hy);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestV = vx;\n                bestH = hy;\n            }\n        }\n    }\n\n    vector<int> xs, ys;\n    xs.reserve(N);\n    ys.reserve(N);\n    for (auto &pt : p) {\n        xs.push_back(pt.x);\n        ys.push_back(pt.y);\n    }\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    vector<array<int,4>> lines;\n\n    auto add_vertical = [&](int x) {\n        // line x = const\n        lines.push_back({x, -1000000000, x, 1000000000});\n    };\n    auto add_horizontal = [&](int y) {\n        // line y = const\n        lines.push_back({-1000000000, y, 1000000000, y});\n    };\n\n    // Quantile cuts between consecutive coordinates.\n    for (int i = 1; i <= bestV; i++) {\n        int idx = (long long)N * i / (bestV + 1);\n        if (idx <= 0 || idx >= N) continue;\n        int x1 = xs[idx - 1], x2 = xs[idx];\n        int cut;\n        if (x1 == x2) cut = x1 + 1;\n        else cut = (x1 + x2) / 2;\n        add_vertical(cut);\n    }\n\n    for (int i = 1; i <= bestH; i++) {\n        int idx = (long long)N * i / (bestH + 1);\n        if (idx <= 0 || idx >= N) continue;\n        int y1 = ys[idx - 1], y2 = ys[idx];\n        int cut;\n        if (y1 == y2) cut = y1 + 1;\n        else cut = (y1 + y2) / 2;\n        add_horizontal(cut);\n    }\n\n    // Fallback / improvement: if duplicate quantile cuts reduced the count,\n    // add several diagonal cuts through the origin with different slopes.\n    // This increases fragmentation without much risk.\n    int diagId = 0;\n    while ((int)lines.size() < K && diagId < 200) {\n        double theta = M_PI * diagId / 200.0;\n        int dx = (int)round(cos(theta) * 1000000000.0);\n        int dy = (int)round(sin(theta) * 1000000000.0);\n        if (dx == 0 && dy == 0) {\n            diagId++;\n            continue;\n        }\n        lines.push_back({-dx, -dy, dx, dy});\n        diagId++;\n    }\n\n    if ((int)lines.size() > K) lines.resize(K);\n\n    cout << lines.size() << '\\n';\n    for (auto &ln : lines) {\n        cout << ln[0] << ' ' << ln[1] << ' ' << ln[2] << ' ' << ln[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    int score;\n    int lenSum;\n};\n\nint N, M;\nvector<vector<int>> dotGrid;\nset<tuple<int,int,int,int>> usedSeg;\nvector<Move> answerMoves;\n\nint weightPoint(int x, int y) {\n    int c = (N - 1) / 2;\n    int dx = x - c;\n    int dy = y - c;\n    return dx * dx + dy * dy + 1;\n}\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ntuple<int,int,int,int> segKey(int x1, int y1, int x2, int y2) {\n    if (x1 > x2 || (x1 == x2 && y1 > y2)) {\n        swap(x1, x2);\n        swap(y1, y2);\n    }\n    return {x1, y1, x2, y2};\n}\n\nint gcdAbs(int a, int b) {\n    return std::gcd(abs(a), abs(b));\n}\n\nbool checkSideNoDotAndNoSeg(int ax, int ay, int bx, int by,\n                            int ex1, int ey1,\n                            int ex2, int ey2,\n                            int ex3, int ey3) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n\n        if (usedSeg.count(segKey(x, y, nx, ny))) return false;\n    }\n\n    for (int i = 1; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n\n        if ((x == ex1 && y == ey1) ||\n            (x == ex2 && y == ey2) ||\n            (x == ex3 && y == ey3)) {\n            continue;\n        }\n\n        if (dotGrid[x][y]) return false;\n    }\n\n    return true;\n}\n\nvoid addSideSegments(int ax, int ay, int bx, int by) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n        usedSeg.insert(segKey(x, y, nx, ny));\n    }\n}\n\nbool legalMove(const Move& mv) {\n    int x1 = mv.x1, y1 = mv.y1;\n    int x2 = mv.x2, y2 = mv.y2;\n    int x3 = mv.x3, y3 = mv.y3;\n    int x4 = mv.x4, y4 = mv.y4;\n\n    if (!inside(x1, y1) || !inside(x2, y2) || !inside(x3, y3) || !inside(x4, y4)) return false;\n    if (dotGrid[x1][y1]) return false;\n    if (!dotGrid[x2][y2] || !dotGrid[x3][y3] || !dotGrid[x4][y4]) return false;\n\n    if (!checkSideNoDotAndNoSeg(x1, y1, x2, y2, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x2, y2, x3, y3, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x3, y3, x4, y4, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x4, y4, x1, y1, x2, y2, x3, y3, x4, y4)) return false;\n\n    return true;\n}\n\nvoid applyMove(const Move& mv) {\n    dotGrid[mv.x1][mv.y1] = 1;\n\n    addSideSegments(mv.x1, mv.y1, mv.x2, mv.y2);\n    addSideSegments(mv.x2, mv.y2, mv.x3, mv.y3);\n    addSideSegments(mv.x3, mv.y3, mv.x4, mv.y4);\n    addSideSegments(mv.x4, mv.y4, mv.x1, mv.y1);\n\n    answerMoves.push_back(mv);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n    dotGrid.assign(N, vector<int>(N, 0));\n\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        dotGrid[x][y] = 1;\n    }\n\n    auto startTime = chrono::steady_clock::now();\n\n    vector<pair<int,int>> dirs = {\n        {1, 0}, {0, 1}, {-1, 0}, {0, -1},\n        {1, 1}, {-1, 1}, {-1, -1}, {1, -1}\n    };\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (elapsed > 4.75) break;\n\n        Move best;\n        bool found = false;\n\n        vector<pair<int,int>> dots;\n        dots.reserve(N * N);\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y < N; y++) {\n                if (dotGrid[x][y]) dots.push_back({x, y});\n            }\n        }\n\n        for (auto [x3, y3] : dots) {\n            for (auto [dx, dy] : dirs) {\n                int rdx = -dy;\n                int rdy = dx;\n\n                for (int sign : {-1, 1}) {\n                    int bx = rdx * sign;\n                    int by = rdy * sign;\n\n                    for (int l1 = 1; l1 < N; l1++) {\n                        int x2 = x3 + dx * l1;\n                        int y2 = y3 + dy * l1;\n                        if (!inside(x2, y2)) break;\n                        if (!dotGrid[x2][y2]) continue;\n\n                        for (int l2 = 1; l2 < N; l2++) {\n                            int x4 = x3 + bx * l2;\n                            int y4 = y3 + by * l2;\n                            if (!inside(x4, y4)) break;\n                            if (!dotGrid[x4][y4]) continue;\n\n                            int x1 = x2 + bx * l2;\n                            int y1 = y2 + by * l2;\n                            if (!inside(x1, y1)) break;\n                            if (dotGrid[x1][y1]) continue;\n\n                            Move mv;\n                            mv.x1 = x1; mv.y1 = y1;\n                            mv.x2 = x2; mv.y2 = y2;\n                            mv.x3 = x3; mv.y3 = y3;\n                            mv.x4 = x4; mv.y4 = y4;\n                            mv.score = weightPoint(x1, y1);\n                            mv.lenSum = l1 + l2;\n\n                            if (!legalMove(mv)) continue;\n\n                            if (!found ||\n                                mv.score > best.score ||\n                                (mv.score == best.score && mv.lenSum < best.lenSum)) {\n                                best = mv;\n                                found = true;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        if (!found) break;\n        applyMove(best);\n    }\n\n    cout << answerMoves.size() << '\\n';\n    for (auto &mv : answerMoves) {\n        cout << mv.x1 << ' ' << mv.y1 << ' '\n             << mv.x2 << ' ' << mv.y2 << ' '\n             << mv.x3 << ' ' << mv.y3 << ' '\n             << mv.x4 << ' ' << mv.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\n\nint f[100];\nint board_[N][N];\n\nstruct Pos {\n    int r, c;\n};\n\nconst char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n\nint dr4[4] = {-1, 1, 0, 0};\nint dc4[4] = {0, 0, -1, 1};\n\narray<Pos, 4> corner = {\n    Pos{0, 0},\n    Pos{9, 9},\n    Pos{0, 9},\n    Pos{9, 0}\n};\n\nPos targetPos[4];\n\nvoid tilt_board(const int src[N][N], int dst[N][N], int dir) {\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) dst[r][c] = 0;\n    }\n\n    if (dir == 0) { // F: up\n        for (int c = 0; c < N; c++) {\n            int write = 0;\n            for (int r = 0; r < N; r++) {\n                if (src[r][c]) {\n                    dst[write++][c] = src[r][c];\n                }\n            }\n        }\n    } else if (dir == 1) { // B: down\n        for (int c = 0; c < N; c++) {\n            int write = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                if (src[r][c]) {\n                    dst[write--][c] = src[r][c];\n                }\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < N; r++) {\n            int write = 0;\n            for (int c = 0; c < N; c++) {\n                if (src[r][c]) {\n                    dst[r][write++] = src[r][c];\n                }\n            }\n        }\n    } else { // R\n        for (int r = 0; r < N; r++) {\n            int write = N - 1;\n            for (int c = N - 1; c >= 0; c--) {\n                if (src[r][c]) {\n                    dst[r][write--] = src[r][c];\n                }\n            }\n        }\n    }\n}\n\ndouble evaluate(const int b[N][N], int turn) {\n    bool vis[N][N] = {};\n    double compScore = 0.0;\n    double edgeScore = 0.0;\n    double distScore = 0.0;\n    double compactScore = 0.0;\n\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int x = b[r][c];\n            if (!x) continue;\n\n            Pos t = targetPos[x];\n            int man = abs(r - t.r) + abs(c - t.c);\n            distScore += (18 - man);\n\n            for (int k = 1; k <= 2; k++) {\n                // mild pull toward target row/col\n            }\n\n            if (r + 1 < N && b[r + 1][c] == x) edgeScore += 1.0;\n            if (c + 1 < N && b[r][c + 1] == x) edgeScore += 1.0;\n        }\n    }\n\n    for (int sr = 0; sr < N; sr++) {\n        for (int sc = 0; sc < N; sc++) {\n            if (!b[sr][sc] || vis[sr][sc]) continue;\n\n            int color = b[sr][sc];\n            queue<pair<int,int>> q;\n            q.push({sr, sc});\n            vis[sr][sc] = true;\n\n            int sz = 0;\n            int minr = sr, maxr = sr, minc = sc, maxc = sc;\n\n            while (!q.empty()) {\n                auto [r, c] = q.front();\n                q.pop();\n                sz++;\n\n                minr = min(minr, r);\n                maxr = max(maxr, r);\n                minc = min(minc, c);\n                maxc = max(maxc, c);\n\n                for (int d = 0; d < 4; d++) {\n                    int nr = r + dr4[d];\n                    int nc = c + dc4[d];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (vis[nr][nc]) continue;\n                    if (b[nr][nc] != color) continue;\n                    vis[nr][nc] = true;\n                    q.push({nr, nc});\n                }\n            }\n\n            compScore += sz * sz;\n\n            int boxArea = (maxr - minr + 1) * (maxc - minc + 1);\n            compactScore += 0.2 * sz * sz / max(1, boxArea);\n        }\n    }\n\n    // Dynamic weighting:\n    // Earlier: encourage geometric separation.\n    // Later: prioritize actual connected components.\n    double progress = turn / 100.0;\n\n    double wComp = 8.0 + 20.0 * progress;\n    double wEdge = 12.0;\n    double wDist = 1.5 * (1.0 - progress) + 0.3;\n    double wCompact = 10.0;\n\n    return wComp * compScore + wEdge * edgeScore + wDist * distScore + wCompact * compactScore;\n}\n\nvoid place_candy(int p, int flavor) {\n    int cnt = 0;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            if (board_[r][c] == 0) {\n                cnt++;\n                if (cnt == p) {\n                    board_[r][c] = flavor;\n                    return;\n                }\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 100; i++) cin >> f[i];\n\n    int cnt[4] = {};\n    for (int i = 0; i < 100; i++) cnt[f[i]]++;\n\n    vector<int> flavors = {1, 2, 3};\n    sort(flavors.begin(), flavors.end(), [&](int a, int b) {\n        return cnt[a] > cnt[b];\n    });\n\n    // Assign three flavors to separated target corners.\n    // Largest: upper-left, second: lower-right, third: upper-right.\n    targetPos[flavors[0]] = {0, 0};\n    targetPos[flavors[1]] = {9, 9};\n    targetPos[flavors[2]] = {0, 9};\n\n    memset(board_, 0, sizeof(board_));\n\n    for (int turn = 1; turn <= 100; turn++) {\n        int p;\n        if (!(cin >> p)) break;\n\n        place_candy(p, f[turn - 1]);\n\n        int bestDir = 0;\n        double bestVal = -1e100;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int nb[N][N];\n            tilt_board(board_, nb, dir);\n            double val = evaluate(nb, turn);\n\n            // Tiny deterministic tie-breaker to avoid excessive oscillation.\n            if (dir == 0 || dir == 2) val += 0.001;\n\n            if (val > bestVal) {\n                bestVal = val;\n                bestDir = dir;\n            }\n        }\n\n        int nb[N][N];\n        tilt_board(board_, nb, bestDir);\n        memcpy(board_, nb, sizeof(board_));\n\n        cout << DIR_CH[bestDir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint M, N;\ndouble EPS;\n\nstruct Features {\n    vector<double> deg;      // sorted degrees\n    vector<double> nds;      // sorted neighbor-degree sums\n    vector<double> local;    // sorted local two-hop-ish signatures\n    double edges = 0;\n    double deg2 = 0;\n};\n\nint choose_N(int M, double e) {\n    if (e < 1e-12) {\n        int n = 4;\n        while (n * (n - 1) / 2 < M) n++;\n        return n;\n    }\n\n    int n;\n    if (e <= 0.02) n = 16;\n    else if (e <= 0.05) n = 22;\n    else if (e <= 0.08) n = 30;\n    else if (e <= 0.12) n = 40;\n    else if (e <= 0.16) n = 52;\n    else if (e <= 0.20) n = 64;\n    else if (e <= 0.25) n = 76;\n    else if (e <= 0.30) n = 88;\n    else n = 100;\n\n    if (M >= 70) n += 4;\n    if (M >= 90) n += 4;\n    return min(100, max(4, n));\n}\n\nstring mat_to_str(const vector<vector<unsigned char>>& a) {\n    string s;\n    s.reserve(N * (N - 1) / 2);\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            s.push_back(a[i][j] ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nvector<vector<unsigned char>> str_to_mat(const string& s) {\n    vector<vector<unsigned char>> a(N, vector<unsigned char>(N, 0));\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (s[p] == '1') a[i][j] = a[j][i] = 1;\n            p++;\n        }\n    }\n    return a;\n}\n\nFeatures calc_features_from_mat(const vector<vector<unsigned char>>& a) {\n    Features f;\n    vector<int> deg(N, 0);\n    for (int i = 0; i < N; i++) {\n        int d = 0;\n        for (int j = 0; j < N; j++) d += a[i][j];\n        deg[i] = d;\n    }\n\n    f.deg.resize(N);\n    for (int i = 0; i < N; i++) f.deg[i] = deg[i];\n    sort(f.deg.begin(), f.deg.end());\n\n    f.edges = accumulate(deg.begin(), deg.end(), 0) / 2.0;\n    f.deg2 = 0;\n    for (int d : deg) f.deg2 += 1.0 * d * d;\n\n    vector<double> nds(N, 0.0);\n    vector<double> local(N, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        double s = 0;\n        double t = 0;\n        for (int j = 0; j < N; j++) {\n            if (a[i][j]) {\n                s += deg[j];\n                t += sqrt((double)deg[j] + 1.0);\n            }\n        }\n        nds[i] = s;\n        local[i] = s + 7.0 * t + 0.2 * deg[i] * deg[i];\n    }\n\n    sort(nds.begin(), nds.end());\n    sort(local.begin(), local.end());\n    f.nds = move(nds);\n    f.local = move(local);\n\n    return f;\n}\n\n// Approximate expected fingerprint after edge flips.\n// For degrees this is exact in expectation.\n// For neighbor-degree sums/local signatures this approximation is not exact,\n// but it gives a useful bias correction.\nFeatures expected_noisy_features(const vector<vector<unsigned char>>& a) {\n    Features raw = calc_features_from_mat(a);\n\n    if (EPS < 1e-12) return raw;\n\n    double c = 1.0 - 2.0 * EPS;\n    double base = EPS * (N - 1);\n\n    Features f;\n    f.deg.resize(N);\n    for (int i = 0; i < N; i++) {\n        f.deg[i] = base + c * raw.deg[i];\n    }\n    sort(f.deg.begin(), f.deg.end());\n\n    f.edges = EPS * (N * (N - 1) / 2.0) + c * raw.edges;\n\n    // Approximate degree second moment under independent edge flips.\n    // d' = sum Bernoulli(q_ij), Var = sum q(1-q)\n    f.deg2 = 0;\n    vector<double> expDeg(N, 0), varDeg(N, 0);\n    for (int i = 0; i < N; i++) {\n        double ed = 0, va = 0;\n        for (int j = 0; j < N; j++) if (i != j) {\n            double q = a[i][j] ? (1.0 - EPS) : EPS;\n            ed += q;\n            va += q * (1.0 - q);\n        }\n        expDeg[i] = ed;\n        varDeg[i] = va;\n        f.deg2 += ed * ed + va;\n    }\n\n    // Expected neighbor-degree-sum approximation:\n    // sum_j A'ij * E[deg'_j]\n    vector<double> nds(N, 0.0), local(N, 0.0);\n    for (int i = 0; i < N; i++) {\n        double s = 0, t = 0;\n        for (int j = 0; j < N; j++) if (i != j) {\n            double q = a[i][j] ? (1.0 - EPS) : EPS;\n            s += q * expDeg[j];\n            t += q * sqrt(expDeg[j] + 1.0);\n        }\n        nds[i] = s;\n        local[i] = s + 7.0 * t + 0.2 * expDeg[i] * expDeg[i];\n    }\n\n    sort(nds.begin(), nds.end());\n    sort(local.begin(), local.end());\n    f.nds = move(nds);\n    f.local = move(local);\n\n    return f;\n}\n\n// Deterministic structured graph.\n// It combines threshold graph, modular bands, and density offset.\n// This gives richer permutation-invariant signatures than degree-only codes.\nvector<vector<unsigned char>> make_graph(int k) {\n    vector<vector<unsigned char>> a(N, vector<unsigned char>(N, 0));\n\n    double x = (M == 1 ? 0.5 : (double)k / (M - 1));\n\n    // Extreme densities are useful for high noise because channel contrast shrinks.\n    double lo = (EPS >= 0.25 ? 0.015 : 0.06);\n    double hi = (EPS >= 0.25 ? 0.985 : 0.94);\n\n    double density = lo + (hi - lo) * x;\n\n    vector<double> w(N);\n    for (int i = 0; i < N; i++) {\n        double u = (i + 0.5) / N;\n        // monotonic component + code-dependent waves\n        w[i] =\n            1.8 * (u - 0.5)\n            + 0.35 * sin(2.0 * M_PI * (u * (2 + (k % 7)) + 0.173 * k))\n            + 0.20 * cos(2.0 * M_PI * (u * (3 + (k % 5)) + 0.071 * k));\n    }\n\n    // Convert desired density to a threshold quantile.\n    vector<double> vals;\n    vals.reserve(N * (N - 1) / 2);\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            double band = 0.0;\n\n            // Several deterministic pair features.\n            int d = abs(i - j);\n            band += 0.22 * cos(2.0 * M_PI * d / max(2, N));\n            band += 0.12 * sin(2.0 * M_PI * ((i + j + 3 * k) % max(3, N)) / max(3, N));\n\n            int mod1 = 3 + (k % 5);\n            int mod2 = 5 + (k % 7);\n            if ((i % mod1) == (j % mod1)) band += 0.35;\n            if ((i % mod2) == (j % mod2)) band -= 0.20;\n\n            vals.push_back(w[i] + w[j] + band);\n        }\n    }\n\n    vector<double> sorted = vals;\n    sort(sorted.begin(), sorted.end());\n    int E = N * (N - 1) / 2;\n    int need = (int)llround(density * E);\n    need = max(0, min(E, need));\n\n    double th;\n    if (need <= 0) th = 1e100;\n    else if (need >= E) th = -1e100;\n    else th = sorted[E - need];\n\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (vals[p] >= th) a[i][j] = a[j][i] = 1;\n            p++;\n        }\n    }\n\n    return a;\n}\n\ndouble vec_dist_sorted(const vector<double>& a, const vector<double>& b, double scale) {\n    double s = 0;\n    int n = (int)a.size();\n    for (int i = 0; i < n; i++) {\n        double d = (a[i] - b[i]) / scale;\n        s += d * d;\n    }\n    return s / n;\n}\n\ndouble distance_features(const Features& obs, const Features& ref) {\n    double sd = sqrt(max(1e-9, EPS * (1.0 - EPS) * (N - 1))) + 1.0;\n    double snds = max(3.0, N * sd);\n    double sloc = max(5.0, N * sd);\n\n    double score = 0.0;\n\n    score += 1.00 * vec_dist_sorted(obs.deg, ref.deg, sd);\n    score += 0.25 * vec_dist_sorted(obs.nds, ref.nds, snds);\n    score += 0.12 * vec_dist_sorted(obs.local, ref.local, sloc);\n\n    double eScale = sqrt(max(1.0, EPS * (1.0 - EPS) * (N * (N - 1) / 2.0))) + 2.0;\n    double ed = (obs.edges - ref.edges) / eScale;\n    score += 1.80 * ed * ed;\n\n    double d2Scale = max(10.0, N * N * sd);\n    double d2 = (obs.deg2 - ref.deg2) / d2Scale;\n    score += 0.20 * d2 * d2;\n\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> M >> EPS;\n    N = choose_N(M, EPS);\n\n    int E = N * (N - 1) / 2;\n\n    vector<string> out_graphs(M);\n    vector<vector<unsigned char>> mats[M > 0 ? 1 : 1]; // dummy, not used\n\n    vector<vector<vector<unsigned char>>> graphs(M);\n    vector<Features> refs(M);\n\n    if (EPS < 1e-12) {\n        for (int k = 0; k < M; k++) {\n            string s(E, '0');\n            for (int i = 0; i < k; i++) s[i] = '1';\n            out_graphs[k] = s;\n            graphs[k] = str_to_mat(s);\n            refs[k] = calc_features_from_mat(graphs[k]);\n        }\n    } else {\n        // Generate candidate graph for each message.\n        for (int k = 0; k < M; k++) {\n            graphs[k] = make_graph(k);\n            out_graphs[k] = mat_to_str(graphs[k]);\n            refs[k] = expected_noisy_features(graphs[k]);\n        }\n    }\n\n    cout << N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << out_graphs[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        if (EPS < 1e-12) {\n            int ones = 0;\n            for (char c : H) ones += (c == '1');\n            int ans = min(M - 1, max(0, ones));\n            cout << ans << '\\n';\n            cout.flush();\n            continue;\n        }\n\n        auto hm = str_to_mat(H);\n        Features obs = calc_features_from_mat(hm);\n\n        int best = 0;\n        double bestScore = 1e300;\n\n        for (int k = 0; k < M; k++) {\n            double sc = distance_features(obs, refs[k]);\n            if (sc < bestScore) {\n                bestScore = sc;\n                best = k;\n            }\n        }\n\n        cout << best << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    double mx, my;\n};\n\nstatic uint64_t rng_state = 88172645463325252ull;\nuint64_t xorshift64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\nint rnd_int(int l, int r) {\n    return l + (int)(xorshift64() % (uint64_t)(r - l + 1));\n}\ndouble rnd01() {\n    return (xorshift64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int root(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = root(a), b = root(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> adj(N);\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 = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n\n    vector<double> X(N), Y(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    for (int i = 0; i < M; i++) {\n        edges[i].mx = (X[edges[i].u] + X[edges[i].v]) * 0.5;\n        edges[i].my = (Y[edges[i].u] + Y[edges[i].v]) * 0.5;\n    }\n\n    // ---------- Approximate edge importance ----------\n    vector<double> imp(M, 1.0);\n\n    vector<int> landmarks;\n    {\n        vector<pair<double,int>> vals;\n        for (int i = 0; i < N; i++) vals.push_back({X[i] + Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i] - Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        int samples = min(N, 36);\n        while ((int)landmarks.size() < samples) landmarks.push_back(rnd_int(0, N - 1));\n\n        sort(landmarks.begin(), landmarks.end());\n        landmarks.erase(unique(landmarks.begin(), landmarks.end()), landmarks.end());\n    }\n\n    const long long INF = (1LL << 60);\n    vector<long long> dist(N);\n    vector<int> parEdge(N);\n\n    for (int s : landmarks) {\n        fill(dist.begin(), dist.end(), INF);\n        fill(parEdge.begin(), parEdge.end(), -1);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != dist[u]) continue;\n\n            for (auto [v, ei] : adj[u]) {\n                long long nd = du + edges[ei].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    parEdge[v] = ei;\n                    pq.push({nd, v});\n                }\n            }\n        }\n\n        for (int v = 0; v < N; v++) {\n            if (parEdge[v] >= 0) imp[parEdge[v]] += 1.0;\n        }\n    }\n\n    double maxImp = *max_element(imp.begin(), imp.end());\n    for (int i = 0; i < M; i++) {\n        imp[i] = sqrt(imp[i] / maxImp);\n        imp[i] += 0.12 * sqrt((double)edges[i].w / 1000000.0);\n    }\n\n    // ---------- Connectivity checker ----------\n    vector<int> banned(M, 0);\n    int banVersion = 1;\n\n    vector<int> markDay(M, -1);\n\n    auto isConnectedDay = [&](const vector<int>& dayEdges) -> bool {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n        for (int e : dayEdges) banned[e] = banVersion;\n\n        vector<int> vis(N, 0);\n        queue<int> q;\n        vis[0] = 1;\n        q.push(0);\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n        return cnt == N;\n    };\n\n    auto isConnectedWithExtra = [&](const vector<int>& dayEdges, int extra) -> bool {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n        for (int e : dayEdges) banned[e] = banVersion;\n        if (extra >= 0) banned[extra] = banVersion;\n\n        vector<int> vis(N, 0);\n        queue<int> q;\n        vis[0] = 1;\n        q.push(0);\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n        return cnt == N;\n    };\n\n    // ---------- Objective state ----------\n    vector<int> ans(M, -1), load(D, 0);\n    vector<double> dayImp(D, 0.0);\n    vector<vector<int>> dayEdges(D);\n    vector<vector<unsigned short>> dayVertCnt(D, vector<unsigned short>(N, 0));\n\n    auto pairCost = [&](int a, int b) -> double {\n        double dx = edges[a].mx - edges[b].mx;\n        double dy = edges[a].my - edges[b].my;\n        double d2 = dx * dx + dy * dy;\n\n        double c = 18000.0 / (d2 + 900.0);\n        if (edges[a].u == edges[b].u || edges[a].u == edges[b].v ||\n            edges[a].v == edges[b].u || edges[a].v == edges[b].v) c += 2.5;\n\n        return c * (0.7 + 0.9 * (imp[a] + imp[b]));\n    };\n\n    auto addCostToDay = [&](int e, int d) -> double {\n        double c = 0.0;\n        for (int f : dayEdges[d]) c += pairCost(e, f);\n\n        c += 2.5 * imp[e] * dayImp[d];\n\n        int u = edges[e].u, v = edges[e].v;\n        c += 8.0 * dayVertCnt[d][u];\n        c += 8.0 * dayVertCnt[d][v];\n\n        double target = (double)M / D;\n        c += 0.3 * max(0.0, load[d] + 1 - target);\n\n        return c;\n    };\n\n    auto assignEdge = [&](int e, int d) {\n        ans[e] = d;\n        load[d]++;\n        dayImp[d] += imp[e];\n        dayEdges[d].push_back(e);\n        dayVertCnt[d][edges[e].u]++;\n        dayVertCnt[d][edges[e].v]++;\n    };\n\n    auto removeFromDayVec = [&](int e, int d) {\n        auto &vec = dayEdges[d];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i] == e) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n\n    auto removeEdge = [&](int e, int d) {\n        load[d]--;\n        dayImp[d] -= imp[e];\n        dayVertCnt[d][edges[e].u]--;\n        dayVertCnt[d][edges[e].v]--;\n        removeFromDayVec(e, d);\n        ans[e] = -1;\n    };\n\n    auto edgeContribution = [&](int e, int d) -> double {\n        double c = 0.0;\n        for (int f : dayEdges[d]) {\n            if (f != e) c += pairCost(e, f);\n        }\n\n        c += 2.5 * imp[e] * max(0.0, dayImp[d] - imp[e]);\n\n        int u = edges[e].u, v = edges[e].v;\n        c += 8.0 * max(0, (int)dayVertCnt[d][u] - 1);\n        c += 8.0 * max(0, (int)dayVertCnt[d][v] - 1);\n\n        return c;\n    };\n\n    // ---------- Initial construction with connectivity guard ----------\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabs(imp[a] - imp[b]) > 1e-12) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    for (int e : ord) {\n        int bestD = -1;\n        double best = 1e100;\n\n        // First try only days that remain connected.\n        for (int d = 0; d < D; d++) {\n            if (load[d] >= K) continue;\n\n            double c = addCostToDay(e, d);\n\n            // Check promising days first effectively by using a soft preliminary filter.\n            bool ok = isConnectedWithExtra(dayEdges[d], e);\n            if (!ok) continue;\n\n            if (c < best) {\n                best = c;\n                bestD = d;\n            }\n        }\n\n        // If impossible due to greedy constraints, allow any day with capacity.\n        // This should be rare because K is loose and original graph is 2-edge-connected.\n        if (bestD < 0) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= K) continue;\n                double c = addCostToDay(e, d) + 1e6;\n                if (c < best) {\n                    best = c;\n                    bestD = d;\n                }\n            }\n        }\n\n        if (bestD < 0) {\n            // Should never happen because D*K > M.\n            bestD = min_element(load.begin(), load.end()) - load.begin();\n        }\n\n        assignEdge(e, bestD);\n    }\n\n    // ---------- Repair disconnected days if any ----------\n    auto repairDisconnected = [&]() {\n        bool changed = true;\n        int rounds = 0;\n\n        while (changed && rounds < 200) {\n            changed = false;\n            rounds++;\n\n            for (int d = 0; d < D; d++) {\n                while (!isConnectedDay(dayEdges[d])) {\n                    if (dayEdges[d].empty()) break;\n\n                    int chosen = -1;\n                    double worst = -1;\n\n                    for (int e : dayEdges[d]) {\n                        double c = edgeContribution(e, d) + 100.0 * imp[e];\n                        if (c > worst) {\n                            worst = c;\n                            chosen = e;\n                        }\n                    }\n\n                    if (chosen < 0) break;\n\n                    int src = d;\n                    removeEdge(chosen, src);\n\n                    int bestD = -1;\n                    double best = 1e100;\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd == src) continue;\n                        if (load[nd] >= K) continue;\n                        if (!isConnectedWithExtra(dayEdges[nd], chosen)) continue;\n                        double c = addCostToDay(chosen, nd);\n                        if (c < best) {\n                            best = c;\n                            bestD = nd;\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        for (int nd = 0; nd < D; nd++) {\n                            if (nd == src) continue;\n                            if (load[nd] >= K) continue;\n                            double c = addCostToDay(chosen, nd) + 1e6;\n                            if (c < best) {\n                                best = c;\n                                bestD = nd;\n                            }\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        assignEdge(chosen, src);\n                        break;\n                    } else {\n                        assignEdge(chosen, bestD);\n                        changed = true;\n                    }\n                }\n            }\n        }\n    };\n\n    repairDisconnected();\n\n    // ---------- Connectivity-safe local search ----------\n    double timeLimit = 5.75;\n    int iter = 0;\n\n    while (timer.elapsed() < timeLimit) {\n        iter++;\n\n        if ((xorshift64() & 3) != 0) {\n            int e = rnd_int(0, M - 1);\n            int a = ans[e];\n            int b = rnd_int(0, D - 1);\n            if (a == b || load[b] >= K) continue;\n\n            double oldc = edgeContribution(e, a);\n\n            removeEdge(e, a);\n\n            // Removing from a cannot hurt connectivity.\n            bool okB = isConnectedWithExtra(dayEdges[b], e);\n            if (!okB) {\n                assignEdge(e, a);\n                continue;\n            }\n\n            double newc = addCostToDay(e, b);\n\n            double t = max(0.001, 0.06 * (1.0 - timer.elapsed() / timeLimit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) assignEdge(e, b);\n            else assignEdge(e, a);\n\n        } else {\n            int e1 = rnd_int(0, M - 1);\n            int e2 = rnd_int(0, M - 1);\n            if (e1 == e2) continue;\n\n            int d1 = ans[e1];\n            int d2 = ans[e2];\n            if (d1 == d2) continue;\n\n            double oldc = edgeContribution(e1, d1) + edgeContribution(e2, d2);\n\n            removeEdge(e1, d1);\n            removeEdge(e2, d2);\n\n            bool ok1 = isConnectedWithExtra(dayEdges[d1], e2);\n            bool ok2 = isConnectedWithExtra(dayEdges[d2], e1);\n\n            if (!ok1 || !ok2) {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n                continue;\n            }\n\n            double newc = addCostToDay(e1, d2) + addCostToDay(e2, d1);\n\n            double t = max(0.001, 0.06 * (1.0 - timer.elapsed() / timeLimit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) {\n                assignEdge(e1, d2);\n                assignEdge(e2, d1);\n            } else {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n            }\n        }\n\n        if ((iter & 4095) == 0 && timer.elapsed() < 5.2) {\n            repairDisconnected();\n        }\n    }\n\n    repairDisconnected();\n\n    // Emergency legality fallback for any unassigned edge, though normally unnecessary.\n    for (int i = 0; i < M; i++) {\n        if (ans[i] < 0) {\n            int d = min_element(load.begin(), load.end()) - load.begin();\n            assignEdge(i, d);\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << ans[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Seg {\n    int x, y, z, dir;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for (int i = 0; i < 2; i++) {\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    const int N3 = D * D * D;\n\n    auto id = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    vector<vector<int>> occ(2, vector<int>(N3, 0));\n    vector<vector<int>> ans(2, vector<int>(N3, 0));\n\n    /*\n      Build sparse valid objects.\n\n      For each z layer:\n      X = visible x positions in front silhouette\n      Y = visible y positions in right silhouette\n\n      We need voxels whose x projection covers X and y projection covers Y.\n      A cyclic pairing creates max(|X|, |Y|) voxels.\n    */\n    for (int t = 0; t < 2; t++) {\n        for (int z = 0; z < D; z++) {\n            vector<int> xs, ys;\n            for (int x = 0; x < D; x++) {\n                if (f[t][z][x] == '1') xs.push_back(x);\n            }\n            for (int y = 0; y < D; y++) {\n                if (r[t][z][y] == '1') ys.push_back(y);\n            }\n\n            int m = max(xs.size(), ys.size());\n\n            for (int k = 0; k < m; k++) {\n                int x = xs[k % xs.size()];\n                int y = ys[k % ys.size()];\n                occ[t][id(x, y, z)] = 1;\n            }\n        }\n    }\n\n    int block_id = 0;\n\n    const int dx[3] = {1, 0, 0};\n    const int dy[3] = {0, 1, 0};\n    const int dz[3] = {0, 0, 1};\n\n    auto can_segment = [&](int t, int x, int y, int z, int dir, int len) {\n        for (int k = 0; k < len; k++) {\n            int nx = x + dx[dir] * k;\n            int ny = y + dy[dir] * k;\n            int nz = z + dz[dir] * k;\n\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) return false;\n\n            int p = id(nx, ny, nz);\n            if (!occ[t][p] || ans[t][p] != 0) return false;\n        }\n        return true;\n    };\n\n    auto place_segment = [&](int t, int x, int y, int z, int dir, int len, int bid) {\n        for (int k = 0; k < len; k++) {\n            int nx = x + dx[dir] * k;\n            int ny = y + dy[dir] * k;\n            int nz = z + dz[dir] * k;\n            ans[t][id(nx, ny, nz)] = bid;\n        }\n    };\n\n    mt19937 rng(1234567);\n\n    /*\n      Pair long straight segments.\n      Since the object is sparse, this is fast.\n    */\n    for (int len = D; len >= 2; len--) {\n        bool updated = true;\n\n        while (updated) {\n            updated = false;\n\n            vector<Seg> segs[2];\n\n            for (int t = 0; t < 2; t++) {\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                            for (int dir = 0; dir < 3; dir++) {\n                                if (can_segment(t, x, y, z, dir, len)) {\n                                    segs[t].push_back({x, y, z, dir});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (segs[0].empty() || segs[1].empty()) continue;\n\n            shuffle(segs[0].begin(), segs[0].end(), rng);\n            shuffle(segs[1].begin(), segs[1].end(), rng);\n\n            size_t p0 = 0;\n            size_t p1 = 0;\n\n            while (p0 < segs[0].size() && p1 < segs[1].size()) {\n                while (p0 < segs[0].size() &&\n                       !can_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z, segs[0][p0].dir, len)) {\n                    p0++;\n                }\n                while (p1 < segs[1].size() &&\n                       !can_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z, segs[1][p1].dir, len)) {\n                    p1++;\n                }\n\n                if (p0 >= segs[0].size() || p1 >= segs[1].size()) break;\n\n                block_id++;\n                place_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z,\n                              segs[0][p0].dir, len, block_id);\n                place_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z,\n                              segs[1][p1].dir, len, block_id);\n\n                updated = true;\n                p0++;\n                p1++;\n            }\n        }\n    }\n\n    /*\n      Pair remaining unit cubes where possible.\n    */\n    vector<int> rem[2];\n\n    for (int t = 0; t < 2; t++) {\n        for (int p = 0; p < N3; p++) {\n            if (occ[t][p] && ans[t][p] == 0) {\n                rem[t].push_back(p);\n            }\n        }\n    }\n\n    int common_units = min((int)rem[0].size(), (int)rem[1].size());\n\n    for (int i = 0; i < common_units; i++) {\n        block_id++;\n        ans[0][rem[0][i]] = block_id;\n        ans[1][rem[1][i]] = block_id;\n    }\n\n    for (int i = common_units; i < (int)rem[0].size(); i++) {\n        block_id++;\n        ans[0][rem[0][i]] = block_id;\n    }\n\n    for (int i = common_units; i < (int)rem[1].size(); i++) {\n        block_id++;\n        ans[1][rem[1][i]] = block_id;\n    }\n\n    cout << block_id << '\\n';\n\n    for (int t = 0; t < 2; t++) {\n        for (int p = 0; p < N3; p++) {\n            if (p) cout << ' ';\n            cout << ans[t][p];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        sz.assign(n,1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[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(sz[a]<sz[b]) swap(a,b);\n        p[b]=a;\n        sz[a]+=sz[b];\n        return true;\n    }\n};\n\nstatic inline long long sqdist(long long x1,long long y1,long long x2,long long y2){\n    long long dx=x1-x2, dy=y1-y2;\n    return dx*dx+dy*dy;\n}\n\nstruct Solver {\n    int N, M, K;\n    vector<int> x, y, a, b;\n    vector<Edge> edges;\n    vector<vector<pair<int,int>>> g;\n\n    vector<vector<int>> d2;                 // station-resident squared distance\n    vector<vector<pair<int,int>>> cand;     // resident -> sorted stations\n    vector<vector<long long>> dist;\n    vector<vector<int>> prevEdge, prevNode;\n\n    vector<int> bestP, bestB;\n    long long bestCost = (1LL<<62);\n\n    chrono::steady_clock::time_point st;\n    double timeLimit = 1.90;\n\n    bool time_ok() {\n        double t = chrono::duration<double>(chrono::steady_clock::now() - st).count();\n        return t < timeLimit;\n    }\n\n    int ceil_sqrt_int(int val){\n        int r = (int)ceil(sqrt((double)val));\n        while(1LL*r*r < val) r++;\n        while(r>0 && 1LL*(r-1)*(r-1) >= val) r--;\n        return r;\n    }\n\n    long long calc_cost(const vector<int>& P, const vector<int>& B){\n        long long s=0;\n        for(int p:P) s += 1LL*p*p;\n        for(int i=0;i<M;i++) if(B[i]) s += edges[i].w;\n        return s;\n    }\n\n    void add_path(vector<int>& B, int s, int t){\n        int cur=t;\n        while(cur!=s){\n            int ei = prevEdge[s][cur];\n            if(ei<0) break;\n            B[ei]=1;\n            cur = prevNode[s][cur];\n        }\n    }\n\n    vector<int> build_edges_metric_mst(const vector<int>& P){\n        vector<int> terminals;\n        terminals.push_back(0);\n        for(int i=0;i<N;i++) if(P[i]>0 && i!=0) terminals.push_back(i);\n\n        vector<int> B(M,0);\n        int T = terminals.size();\n        if(T <= 1) return B;\n\n        struct ME {\n            long long w;\n            int i, j;\n            bool operator<(const ME& other) const { return w < other.w; }\n        };\n\n        vector<ME> mes;\n        mes.reserve(T*T);\n        for(int i=0;i<T;i++){\n            for(int j=i+1;j<T;j++){\n                mes.push_back({dist[terminals[i]][terminals[j]], i, j});\n            }\n        }\n        sort(mes.begin(), mes.end());\n\n        DSU dsu(T);\n        int cnt=0;\n        for(auto &e: mes){\n            if(dsu.unite(e.i, e.j)){\n                add_path(B, terminals[e.i], terminals[e.j]);\n                cnt++;\n                if(cnt == T-1) break;\n            }\n        }\n\n        prune_edges(P, B);\n        return B;\n    }\n\n    void prune_edges(const vector<int>& P, vector<int>& B){\n        vector<vector<pair<int,int>>> tg(N);\n        vector<int> deg(N,0);\n        for(int i=0;i<M;i++) if(B[i]){\n            int u=edges[i].u, v=edges[i].v;\n            tg[u].push_back({v,i});\n            tg[v].push_back({u,i});\n            deg[u]++; deg[v]++;\n        }\n\n        queue<int> q;\n        for(int i=1;i<N;i++){\n            if(deg[i]==1 && P[i]==0) q.push(i);\n        }\n\n        while(!q.empty()){\n            int v=q.front(); q.pop();\n            if(v==0 || P[v]>0 || deg[v]!=1) continue;\n\n            int rem=-1, to=-1;\n            for(auto [nv,ei]: tg[v]){\n                if(B[ei]){\n                    rem=ei;\n                    to=nv;\n                    break;\n                }\n            }\n            if(rem<0) continue;\n\n            B[rem]=0;\n            deg[v]--;\n            deg[to]--;\n            if(to!=0 && deg[to]==1 && P[to]==0) q.push(to);\n        }\n    }\n\n    vector<int> recomputeP_from_assigned(const vector<vector<int>>& assigned){\n        vector<int> P(N,0);\n        for(int i=0;i<N;i++){\n            int md=0;\n            for(int k: assigned[i]) md=max(md, d2[i][k]);\n            P[i]=ceil_sqrt_int(md);\n            if(P[i]>5000) P[i]=5000;\n        }\n        return P;\n    }\n\n    void evaluate_assignment(vector<vector<int>> assigned){\n        vector<int> assign(K, -1);\n        for(int i=0;i<N;i++) for(int k: assigned[i]) assign[k]=i;\n\n        refine_assignment(assigned, assign);\n\n        vector<int> P = recomputeP_from_assigned(assigned);\n        final_shrink(P);\n        vector<int> B = build_edges_metric_mst(P);\n        long long cost = calc_cost(P, B);\n\n        if(cost < bestCost){\n            bestCost = cost;\n            bestP = P;\n            bestB = B;\n        }\n    }\n\n    void refine_assignment(vector<vector<int>>& assigned, vector<int>& assign){\n        for(int outer=0; outer<6 && time_ok(); outer++){\n            bool changed=false;\n\n            vector<int> curMax(N,0), secondMax(N,0), cntMax(N,0);\n            for(int i=0;i<N;i++){\n                for(int k: assigned[i]){\n                    int dd=d2[i][k];\n                    if(dd > curMax[i]){\n                        secondMax[i]=curMax[i];\n                        curMax[i]=dd;\n                        cntMax[i]=1;\n                    }else if(dd == curMax[i]){\n                        cntMax[i]++;\n                    }else if(dd > secondMax[i]){\n                        secondMax[i]=dd;\n                    }\n                }\n            }\n\n            vector<int> order(K);\n            iota(order.begin(), order.end(), 0);\n            shuffle(order.begin(), order.end(), mt19937(outer + 12345));\n\n            for(int k: order){\n                int old = assign[k];\n                if(old < 0) continue;\n\n                int oldAfterD2 = curMax[old];\n                if(d2[old][k] == curMax[old] && cntMax[old] == 1) oldAfterD2 = secondMax[old];\n\n                int oldR = ceil_sqrt_int(curMax[old]);\n                int oldAfterR = ceil_sqrt_int(oldAfterD2);\n                long long oldDelta = 1LL*oldAfterR*oldAfterR - 1LL*oldR*oldR;\n\n                long long bestDelta = 0;\n                int bestI = old;\n\n                int lim = min(35, (int)cand[k].size());\n                for(int z=0; z<lim; z++){\n                    int ni = cand[k][z].second;\n                    if(ni == old) continue;\n\n                    int r0 = ceil_sqrt_int(curMax[ni]);\n                    int r1 = ceil_sqrt_int(max(curMax[ni], d2[ni][k]));\n\n                    long long delta = oldDelta + 1LL*r1*r1 - 1LL*r0*r0;\n\n                    // Approximate connection effect.\n                    if(assigned[ni].empty()) delta += dist[0][ni] / 6;\n                    if(assigned[old].size() == 1) delta -= dist[0][old] / 6;\n\n                    if(delta < bestDelta){\n                        bestDelta = delta;\n                        bestI = ni;\n                    }\n                }\n\n                if(bestI != old){\n                    auto &v = assigned[old];\n                    auto it = find(v.begin(), v.end(), k);\n                    if(it != v.end()) v.erase(it);\n                    assigned[bestI].push_back(k);\n                    assign[k] = bestI;\n                    changed = true;\n                }\n            }\n\n            try_delete_stations(assigned, assign);\n            if(!changed) break;\n        }\n    }\n\n    void try_delete_stations(vector<vector<int>>& assigned, vector<int>& assign){\n        vector<int> stations;\n        for(int i=0;i<N;i++) if(!assigned[i].empty()) stations.push_back(i);\n\n        sort(stations.begin(), stations.end(), [&](int p, int q){\n            return assigned[p].size() < assigned[q].size();\n        });\n\n        int tries=0;\n        for(int rem: stations){\n            if(!time_ok()) return;\n            if(assigned[rem].empty()) continue;\n            if((int)assigned[rem].size() > 180) continue;\n            if(++tries > 40) break;\n\n            vector<vector<int>> backupAssigned = assigned;\n            vector<int> backupAssign = assign;\n\n            vector<int> Pold = recomputeP_from_assigned(assigned);\n            vector<int> Bold = build_edges_metric_mst(Pold);\n            long long oldCost = calc_cost(Pold, Bold);\n\n            vector<int> residents = assigned[rem];\n            assigned[rem].clear();\n\n            bool ok=true;\n            for(int k: residents){\n                long long bestInc = (1LL<<60);\n                int bestI = -1;\n\n                int lim = min(45, (int)cand[k].size());\n                for(int z=0; z<lim; z++){\n                    int ni = cand[k][z].second;\n                    if(ni == rem) continue;\n\n                    int md=0;\n                    for(int kk: assigned[ni]) md=max(md, d2[ni][kk]);\n\n                    int r0=ceil_sqrt_int(md);\n                    int r1=ceil_sqrt_int(max(md, d2[ni][k]));\n                    long long inc = 1LL*r1*r1 - 1LL*r0*r0;\n                    if(assigned[ni].empty()) inc += dist[0][ni] / 6;\n\n                    if(inc < bestInc){\n                        bestInc = inc;\n                        bestI = ni;\n                    }\n                }\n\n                if(bestI < 0){\n                    ok=false;\n                    break;\n                }\n                assigned[bestI].push_back(k);\n                assign[k]=bestI;\n            }\n\n            if(!ok){\n                assigned = backupAssigned;\n                assign = backupAssign;\n                continue;\n            }\n\n            vector<int> Pnew = recomputeP_from_assigned(assigned);\n            vector<int> Bnew = build_edges_metric_mst(Pnew);\n            long long newCost = calc_cost(Pnew, Bnew);\n\n            if(newCost < oldCost){\n                // keep\n            }else{\n                assigned = backupAssigned;\n                assign = backupAssign;\n            }\n        }\n    }\n\n    void final_shrink(vector<int>& P){\n        // Exact shrink: each positive station radius only needs to hit at least one resident\n        // if residents are still covered globally. Repeatedly lower radii to critical values.\n        vector<vector<int>> coverers(K);\n        for(int k=0;k<K;k++){\n            for(int i=0;i<N;i++){\n                if(P[i] > 0 && 1LL*P[i]*P[i] >= d2[i][k]) coverers[k].push_back(i);\n            }\n        }\n\n        for(int i=0;i<N;i++){\n            if(P[i]==0) continue;\n\n            vector<int> critical;\n            critical.push_back(0);\n            for(int k=0;k<K;k++){\n                if(1LL*P[i]*P[i] >= d2[i][k]){\n                    critical.push_back(ceil_sqrt_int(d2[i][k]));\n                }\n            }\n            sort(critical.begin(), critical.end());\n            critical.erase(unique(critical.begin(), critical.end()), critical.end());\n\n            int best = P[i];\n            for(int idx=(int)critical.size()-1; idx>=0; idx--){\n                int r = critical[idx];\n                bool ok=true;\n                for(int k=0;k<K;k++){\n                    bool was = (1LL*P[i]*P[i] >= d2[i][k]);\n                    bool now = (1LL*r*r >= d2[i][k]);\n                    if(was && !now){\n                        bool other=false;\n                        for(int j: coverers[k]){\n                            if(j!=i){\n                                other=true;\n                                break;\n                            }\n                        }\n                        if(!other){\n                            ok=false;\n                            break;\n                        }\n                    }\n                }\n                if(ok) best=r;\n                else break;\n            }\n\n            if(best < P[i]){\n                for(int k=0;k<K;k++){\n                    bool was = (1LL*P[i]*P[i] >= d2[i][k]);\n                    bool now = (1LL*best*best >= d2[i][k]);\n                    if(was && !now){\n                        auto &v=coverers[k];\n                        v.erase(find(v.begin(), v.end(), i));\n                    }\n                }\n                P[i]=best;\n            }\n        }\n    }\n\n    void build_initial_marginal(int lim, long long connDiv){\n        vector<vector<int>> assigned(N);\n        vector<int> assign(K,-1);\n        vector<int> maxd(N,0);\n\n        vector<int> order(K);\n        iota(order.begin(), order.end(), 0);\n\n        // Process hard-to-cover residents first.\n        sort(order.begin(), order.end(), [&](int p, int q){\n            return cand[p][0].first > cand[q][0].first;\n        });\n\n        for(int k: order){\n            long long best = (1LL<<60);\n            int bi = cand[k][0].second;\n\n            int L = min(lim, (int)cand[k].size());\n            for(int z=0; z<L; z++){\n                int i = cand[k][z].second;\n                int oldr = ceil_sqrt_int(maxd[i]);\n                int newr = ceil_sqrt_int(max(maxd[i], d2[i][k]));\n                long long inc = 1LL*newr*newr - 1LL*oldr*oldr;\n                if(assigned[i].empty()) inc += dist[0][i] / connDiv;\n\n                if(inc < best){\n                    best = inc;\n                    bi = i;\n                }\n            }\n\n            assign[k]=bi;\n            assigned[bi].push_back(k);\n            maxd[bi]=max(maxd[bi], d2[bi][k]);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void build_initial_setcover(long long connDiv, int radiiStep){\n        vector<char> covered(K, 0);\n        int remaining = K;\n\n        vector<vector<int>> assigned(N);\n        vector<int> assign(K,-1);\n\n        vector<int> possibleR;\n        for(int r=300; r<=5000; r+=radiiStep) possibleR.push_back(r);\n        possibleR.push_back(5000);\n        sort(possibleR.begin(), possibleR.end());\n        possibleR.erase(unique(possibleR.begin(), possibleR.end()), possibleR.end());\n\n        for(int iter=0; remaining>0 && iter<150 && time_ok(); iter++){\n            double bestScore = -1;\n            int bestI=-1, bestR=0;\n            vector<int> bestList;\n\n            for(int i=0;i<N;i++){\n                vector<pair<int,int>> ds;\n                ds.reserve(K);\n                for(int k=0;k<K;k++) if(!covered[k]){\n                    if(d2[i][k] <= 5000LL*5000LL) ds.push_back({d2[i][k], k});\n                }\n                if(ds.empty()) continue;\n                sort(ds.begin(), ds.end());\n\n                int ptr=0;\n                vector<int> curList;\n                for(int r: possibleR){\n                    int rr = r*r;\n                    while(ptr<(int)ds.size() && ds[ptr].first <= rr){\n                        curList.push_back(ds[ptr].second);\n                        ptr++;\n                    }\n                    int gain = curList.size();\n                    if(gain == 0) continue;\n\n                    long long cost = 1LL*r*r + dist[0][i]/connDiv;\n                    double score = (double)gain * (double)gain / (double)cost;\n\n                    if(score > bestScore){\n                        bestScore = score;\n                        bestI = i;\n                        bestR = r;\n                        bestList = curList;\n                    }\n                }\n            }\n\n            if(bestI < 0) break;\n\n            for(int k: bestList){\n                if(!covered[k]){\n                    covered[k]=1;\n                    remaining--;\n                    assign[k]=bestI;\n                    assigned[bestI].push_back(k);\n                }\n            }\n        }\n\n        // Assign leftovers.\n        for(int k=0;k<K;k++){\n            if(assign[k]>=0) continue;\n\n            long long best = (1LL<<60);\n            int bi = cand[k][0].second;\n            int L = min(50, (int)cand[k].size());\n            for(int z=0; z<L; z++){\n                int i=cand[k][z].second;\n                int md=0;\n                for(int kk: assigned[i]) md=max(md, d2[i][kk]);\n                int r0=ceil_sqrt_int(md);\n                int r1=ceil_sqrt_int(max(md, d2[i][k]));\n                long long inc=1LL*r1*r1-1LL*r0*r0;\n                if(assigned[i].empty()) inc += dist[0][i]/connDiv;\n                if(inc<best){\n                    best=inc;\n                    bi=i;\n                }\n            }\n            assign[k]=bi;\n            assigned[bi].push_back(k);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void prepare(){\n        d2.assign(N, vector<int>(K));\n        for(int i=0;i<N;i++){\n            for(int k=0;k<K;k++){\n                d2[i][k]=(int)sqdist(x[i], y[i], a[k], b[k]);\n            }\n        }\n\n        cand.assign(K, {});\n        for(int k=0;k<K;k++){\n            cand[k].reserve(N);\n            for(int i=0;i<N;i++){\n                if(d2[i][k] <= 5000LL*5000LL) cand[k].push_back({d2[i][k], i});\n            }\n            if(cand[k].empty()){\n                for(int i=0;i<N;i++) cand[k].push_back({d2[i][k], i});\n            }\n            sort(cand[k].begin(), cand[k].end());\n        }\n\n        const long long INF = (1LL<<60);\n        dist.assign(N, vector<long long>(N, INF));\n        prevEdge.assign(N, vector<int>(N, -1));\n        prevNode.assign(N, vector<int>(N, -1));\n\n        for(int s=0;s<N;s++){\n            priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n            dist[s][s]=0;\n            pq.push({0,s});\n\n            while(!pq.empty()){\n                auto [cd, v] = pq.top();\n                pq.pop();\n                if(cd != dist[s][v]) continue;\n\n                for(auto [to, ei]: g[v]){\n                    long long nd = cd + edges[ei].w;\n                    if(nd < dist[s][to]){\n                        dist[s][to]=nd;\n                        prevEdge[s][to]=ei;\n                        prevNode[s][to]=v;\n                        pq.push({nd,to});\n                    }\n                }\n            }\n        }\n    }\n\n    void solve(){\n        st = chrono::steady_clock::now();\n        prepare();\n\n        bestP.assign(N,0);\n        bestB.assign(M,0);\n\n        build_initial_marginal(12, 4);\n        if(time_ok()) build_initial_marginal(25, 5);\n        if(time_ok()) build_initial_marginal(60, 6);\n        if(time_ok()) build_initial_marginal(100, 8);\n\n        if(time_ok()) build_initial_setcover(5, 350);\n        if(time_ok()) build_initial_setcover(8, 500);\n        if(time_ok()) build_initial_setcover(12, 700);\n\n        // Safety coverage check.\n        for(int k=0;k<K;k++){\n            bool ok=false;\n            for(int i=0;i<N;i++){\n                if(1LL*bestP[i]*bestP[i] >= d2[i][k]){\n                    ok=true;\n                    break;\n                }\n            }\n            if(!ok){\n                int bi=cand[k][0].second;\n                bestP[bi]=max(bestP[bi], ceil_sqrt_int(d2[bi][k]));\n                if(bestP[bi]>5000) bestP[bi]=5000;\n            }\n        }\n\n        final_shrink(bestP);\n        bestB = build_edges_metric_mst(bestP);\n    }\n};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    cin >> solver.N >> solver.M >> solver.K;\n\n    solver.x.resize(solver.N);\n    solver.y.resize(solver.N);\n    for(int i=0;i<solver.N;i++){\n        cin >> solver.x[i] >> solver.y[i];\n    }\n\n    solver.edges.resize(solver.M);\n    solver.g.assign(solver.N, {});\n    for(int i=0;i<solver.M;i++){\n        int u,v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        solver.edges[i] = {u,v,w};\n        solver.g[u].push_back({v,i});\n        solver.g[v].push_back({u,i});\n    }\n\n    solver.a.resize(solver.K);\n    solver.b.resize(solver.K);\n    for(int k=0;k<solver.K;k++){\n        cin >> solver.a[k] >> solver.b[k];\n    }\n\n    solver.solve();\n\n    for(int i=0;i<solver.N;i++){\n        if(i) cout << ' ';\n        cout << solver.bestP[i];\n    }\n    cout << '\\n';\n\n    for(int i=0;i<solver.M;i++){\n        if(i) cout << ' ';\n        cout << solver.bestB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int LIM = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nint a[N][N];\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y <= x;\n}\n\nbool adjacent(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && abs(y1 - y2) == 1) return true;\n    if (x2 == x1 + 1 && (y2 == y1 || y2 == y1 + 1)) return true;\n    if (x2 == x1 - 1 && (y1 == y2 || y1 == y2 + 1)) return true;\n    return false;\n}\n\nint violation_count_cell(int x, int y) {\n    if (x >= N - 1) return 0;\n    int c = 0;\n    if (a[x][y] > a[x + 1][y]) c++;\n    if (a[x][y] > a[x + 1][y + 1]) c++;\n    return c;\n}\n\nint total_violations() {\n    int e = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            e += violation_count_cell(x, y);\n        }\n    }\n    return e;\n}\n\nint severity(int x, int y) {\n    if (x >= N - 1) return 0;\n    int s = 0;\n    if (a[x][y] > a[x + 1][y]) s += a[x][y] - a[x + 1][y];\n    if (a[x][y] > a[x + 1][y + 1]) s += a[x][y] - a[x + 1][y + 1];\n    return s;\n}\n\nvector<pair<int,int>> affected_cells(int x, int y) {\n    vector<pair<int,int>> v;\n    for (int dx = -1; dx <= 1; dx++) {\n        for (int dy = -1; dy <= 1; dy++) {\n            int nx = x + dx, ny = y + dy;\n            if (inside(nx, ny) && nx < N - 1) {\n                v.push_back({nx, ny});\n            }\n        }\n    }\n    if (x > 0) {\n        if (inside(x - 1, y - 1)) v.push_back({x - 1, y - 1});\n        if (inside(x - 1, y)) v.push_back({x - 1, y});\n    }\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> a[x][y];\n        }\n    }\n\n    vector<Op> ops;\n\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        if ((int)ops.size() >= LIM) return false;\n        if (!adjacent(x1, y1, x2, y2)) return false;\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n        return true;\n    };\n\n    using Node = tuple<int,int,int,int>; \n    // severity, timestamp, x, y\n\n    priority_queue<Node> pq;\n    vector<vector<int>> stamp(N);\n    vector<vector<int>> pushed(N);\n    for (int x = 0; x < N; x++) {\n        stamp[x].assign(x + 1, 0);\n        pushed[x].assign(x + 1, 0);\n    }\n\n    int timer = 1;\n\n    auto push_cell = [&](int x, int y) {\n        if (!inside(x, y) || x >= N - 1) return;\n        int s = severity(x, y);\n        if (s <= 0) return;\n        pushed[x][y] = ++timer;\n        pq.emplace(s, pushed[x][y], x, y);\n    };\n\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            push_cell(x, y);\n        }\n    }\n\n    while (!pq.empty() && (int)ops.size() < LIM) {\n        auto [s_old, id, x, y] = pq.top();\n        pq.pop();\n\n        if (id != pushed[x][y]) continue;\n        int s_now = severity(x, y);\n        if (s_now <= 0) continue;\n        if (s_now != s_old) {\n            push_cell(x, y);\n            continue;\n        }\n\n        int lx = x + 1, ly = y;\n        int rx = x + 1, ry = y + 1;\n\n        int bx = -1, by = -1;\n        if (a[x][y] > a[lx][ly] || a[x][y] > a[rx][ry]) {\n            if (a[lx][ly] < a[rx][ry]) {\n                bx = lx; by = ly;\n            } else {\n                bx = rx; by = ry;\n            }\n        }\n\n        if (bx == -1) continue;\n\n        do_swap(x, y, bx, by);\n\n        auto aff1 = affected_cells(x, y);\n        auto aff2 = affected_cells(bx, by);\n        aff1.insert(aff1.end(), aff2.begin(), aff2.end());\n        sort(aff1.begin(), aff1.end());\n        aff1.erase(unique(aff1.begin(), aff1.end()), aff1.end());\n\n        for (auto [ux, uy] : aff1) {\n            push_cell(ux, uy);\n        }\n    }\n\n    /*\n      If the priority-queue heapification failed to solve everything,\n      use a limited fallback deterministic repair pass.\n      This keeps the solution safe: it will usually still reach E=0.\n    */\n    bool changed = true;\n    while (changed && (int)ops.size() < LIM) {\n        changed = false;\n        for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n            for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                while (violation_count_cell(x, y) > 0 && (int)ops.size() < LIM) {\n                    int ly = y, ry = y + 1;\n                    if (a[x + 1][ly] < a[x + 1][ry]) {\n                        do_swap(x, y, x + 1, ly);\n                    } else {\n                        do_swap(x, y, x + 1, ry);\n                    }\n                    changed = true;\n                }\n            }\n        }\n    }\n\n    /*\n      Final emergency fallback:\n      If still invalid, continue local repair top-down/bottom-up alternately.\n      In most random cases this is not needed.\n    */\n    for (int pass = 0; pass < 200 && total_violations() > 0 && (int)ops.size() < LIM; pass++) {\n        if (pass % 2 == 0) {\n            for (int x = 0; x < N - 1 && (int)ops.size() < LIM; x++) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (violation_count_cell(x, y) > 0) {\n                        int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n                        do_swap(x, y, x + 1, by);\n                    }\n                }\n            }\n        } else {\n            for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (violation_count_cell(x, y) > 0) {\n                        int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n                        do_swap(x, y, x + 1, by);\n                    }\n                }\n            }\n        }\n    }\n\n    cout << ops.size() << '\\n';\n    for (auto &op : ops) {\n        cout << op.x1 << ' ' << op.y1 << ' ' << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c;\n};\n\nint D, N;\nconst int ENTR = 0;\nconst int ENTC = 4;\n\nbool obstacle[9][9];\nbool occupied_[9][9];\nint valAt[9][9];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nbool isEntrance(int r, int c) {\n    return r == ENTR && c == ENTC;\n}\n\n// Reachable empty cells from entrance.\n// Containers and obstacles are blocked.\nvector<vector<int>> reachableEmpty() {\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    queue<pair<int,int>> q;\n\n    if (!obstacle[ENTR][ENTC] && !occupied_[ENTR][ENTC]) {\n        vis[ENTR][ENTC] = 1;\n        q.push({ENTR, ENTC});\n    }\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc)) continue;\n            if (vis[nr][nc]) continue;\n            if (obstacle[nr][nc] || occupied_[nr][nc]) continue;\n            vis[nr][nc] = 1;\n            q.push({nr, nc});\n        }\n    }\n    return vis;\n}\n\n// If we occupy (br,bc), will every remaining empty non-obstacle non-entrance\n// cell still be reachable from entrance?\nbool keepsConnectivity(int br, int bc) {\n    occupied_[br][bc] = true;\n    auto vis = reachableEmpty();\n    occupied_[br][bc] = false;\n\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (isEntrance(r,c)) continue;\n            if (obstacle[r][c]) continue;\n            if (occupied_[r][c]) continue;\n            if (r == br && c == bc) continue;\n            if (!vis[r][c]) return false;\n        }\n    }\n    return true;\n}\n\n// BFS distance from entrance ignoring containers.\nvector<vector<int>> baseDistance() {\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n\n    dist[ENTR][ENTC] = 0;\n    q.push({ENTR, ENTC});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr,nc});\n        }\n    }\n    return dist;\n}\n\nbool removableContainer(int r, int c, const vector<vector<int>>& emptyReach) {\n    if (!occupied_[r][c]) return false;\n\n    for (int k = 0; k < 4; k++) {\n        int nr = r + dr[k], nc = c + dc[k];\n        if (!inside(nr,nc)) continue;\n        if (emptyReach[nr][nc]) return true;\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    memset(obstacle, 0, sizeof(obstacle));\n    memset(occupied_, 0, sizeof(occupied_));\n    for (int r = 0; r < 9; r++) {\n        for (int c = 0; c < 9; c++) {\n            valAt[r][c] = -1;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    int M = D * D - 1 - N;\n\n    auto dist = baseDistance();\n\n    vector<Cell> allCells;\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (isEntrance(r,c)) continue;\n            if (obstacle[r][c]) continue;\n            allCells.push_back({r,c});\n        }\n    }\n\n    // Rank: shallow cells small rank, deep cells large rank.\n    sort(allCells.begin(), allCells.end(), [&](const Cell& a, const Cell& b) {\n        int da = dist[a.r][a.c];\n        int db = dist[b.r][b.c];\n        if (da != db) return da < db;\n\n        int sa = abs(a.c - ENTC);\n        int sb = abs(b.c - ENTC);\n        if (sa != sb) return sa < sb;\n\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    int rankOf[9][9];\n    memset(rankOf, -1, sizeof(rankOf));\n    for (int i = 0; i < (int)allCells.size(); i++) {\n        rankOf[allCells[i].r][allCells[i].c] = i;\n    }\n\n    // Online placement\n    for (int d = 0; d < M; d++) {\n        int t;\n        cin >> t;\n\n        auto reach = reachableEmpty();\n\n        Cell best = {-1, -1};\n        long long bestScore = LLONG_MAX;\n\n        // Larger labels are assigned deeper.\n        int targetRank = t;\n\n        // First pass: safe cells only.\n        for (const auto& cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (occupied_[r][c]) continue;\n            if (!reach[r][c]) continue;\n\n            bool safe = keepsConnectivity(r, c);\n            if (!safe) continue;\n\n            int rk = rankOf[r][c];\n\n            long long score = 0;\n            score += 1000LL * abs(rk - targetRank);\n\n            // Prefer occupying farther cells.\n            score -= 20LL * dist[r][c];\n\n            // Slightly avoid main entrance column.\n            if (c == ENTC) score += 100;\n\n            // Prefer side pockets.\n            score -= 5LL * abs(c - ENTC);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = cell;\n            }\n        }\n\n        // Second pass: any reachable cell.\n        if (best.r == -1) {\n            bestScore = LLONG_MAX;\n            for (const auto& cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (occupied_[r][c]) continue;\n                if (!reach[r][c]) continue;\n\n                int rk = rankOf[r][c];\n                long long score = 1000LL * abs(rk - targetRank) - 20LL * dist[r][c];\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = cell;\n                }\n            }\n        }\n\n        // Absolute emergency fallback: choose first empty non-obstacle cell.\n        // In a valid reachable state this should never be used, but prevents -1 output.\n        if (best.r == -1) {\n            for (const auto& cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (!occupied_[r][c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        occupied_[best.r][best.c] = true;\n        valAt[best.r][best.c] = t;\n\n        cout << best.r << \" \" << best.c << '\\n';\n        cout.flush();\n    }\n\n    // Removal phase\n    vector<Cell> answer;\n    answer.reserve(M);\n\n    for (int step = 0; step < M; step++) {\n        auto emptyReach = reachableEmpty();\n\n        Cell best = {-1, -1};\n        int bestVal = INT_MAX;\n\n        // Greedily remove the smallest currently accessible label.\n        for (const auto& cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (!occupied_[r][c]) continue;\n            if (!removableContainer(r,c,emptyReach)) continue;\n\n            if (valAt[r][c] < bestVal) {\n                bestVal = valAt[r][c];\n                best = cell;\n            }\n        }\n\n        // If greedy found nothing, choose any occupied cell as fallback.\n        // This should not happen if placement was valid.\n        if (best.r == -1) {\n            for (const auto& cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (occupied_[r][c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        answer.push_back(best);\n        occupied_[best.r][best.c] = false;\n        valAt[best.r][best.c] = -1;\n    }\n\n    for (const auto& cell : answer) {\n        cout << cell.r << \" \" << cell.c << '\\n';\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 50;\nstatic const int M = 100;\n\nint n, m;\narray<array<int, N>, N> g;\nbool targetAdj[M + 1][M + 1];\nint colorCnt[M + 1];\n\nchrono::steady_clock::time_point startTime;\ndouble timeLimit = 1.90;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\nvoid addAdj(bool adj[M + 1][M + 1], int a, int b) {\n    if (a == b) return;\n    if (a > b) swap(a, b);\n    adj[a][b] = adj[b][a] = true;\n}\n\nvoid computeAdj(const array<array<int, N>, N>& grid, bool adj[M + 1][M + 1]) {\n    for (int i = 0; i <= M; i++) {\n        for (int j = 0; j <= M; j++) adj[i][j] = false;\n    }\n\n    for (int i = 0; i < n; i++) {\n        addAdj(adj, 0, grid[i][0]);\n        addAdj(adj, 0, grid[i][n - 1]);\n    }\n    for (int j = 0; j < n; j++) {\n        addAdj(adj, 0, grid[0][j]);\n        addAdj(adj, 0, grid[n - 1][j]);\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i + 1 < n) addAdj(adj, grid[i][j], grid[i + 1][j]);\n            if (j + 1 < n) addAdj(adj, grid[i][j], grid[i][j + 1]);\n        }\n    }\n}\n\nbool checkAdjacency() {\n    bool curAdj[M + 1][M + 1];\n    computeAdj(g, curAdj);\n    for (int i = 0; i <= m; i++) {\n        for (int j = 0; j <= m; j++) {\n            if (curAdj[i][j] != targetAdj[i][j]) return false;\n        }\n    }\n    return true;\n}\n\nbool checkZeroConnected() {\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n\n    for (int i = 0; i < n; i++) {\n        if (g[i][0] == 0 && !vis[i][0]) {\n            vis[i][0] = true;\n            q.push({i, 0});\n        }\n        if (g[i][n - 1] == 0 && !vis[i][n - 1]) {\n            vis[i][n - 1] = true;\n            q.push({i, n - 1});\n        }\n    }\n    for (int j = 0; j < n; j++) {\n        if (g[0][j] == 0 && !vis[0][j]) {\n            vis[0][j] = true;\n            q.push({0, j});\n        }\n        if (g[n - 1][j] == 0 && !vis[n - 1][j]) {\n            vis[n - 1][j] = true;\n            q.push({n - 1, j});\n        }\n    }\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        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 (vis[ni][nj] || g[ni][nj] != 0) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == 0 && !vis[i][j]) return false;\n        }\n    }\n    return true;\n}\n\nbool checkColorConnected(int c) {\n    if (colorCnt[c] <= 0) return false;\n\n    bool found = false;\n    int si = -1, sj = -1;\n    for (int i = 0; i < n && !found; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == c) {\n                si = i;\n                sj = j;\n                found = true;\n                break;\n            }\n        }\n    }\n\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n    vis[si][sj] = true;\n    q.push({si, sj});\n    int cnt = 0;\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        cnt++;\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 (!vis[ni][nj] && g[ni][nj] == c) {\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n    }\n\n    return cnt == colorCnt[c];\n}\n\nbool fullCheck() {\n    if (!checkZeroConnected()) return false;\n\n    for (int c = 1; c <= m; c++) {\n        if (!checkColorConnected(c)) return false;\n    }\n\n    if (!checkAdjacency()) return false;\n    return true;\n}\n\nbool tryEraseCell(int i, int j) {\n    int c = g[i][j];\n    if (c == 0) return false;\n    if (colorCnt[c] <= 1) return false;\n\n    g[i][j] = 0;\n    colorCnt[c]--;\n    colorCnt[0]++;\n\n    bool ok = fullCheck();\n\n    if (!ok) {\n        g[i][j] = c;\n        colorCnt[c]++;\n        colorCnt[0]--;\n    }\n    return ok;\n}\n\nint zeroCount() {\n    int z = 0;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == 0) z++;\n        }\n    }\n    return z;\n}\n\nvoid printGrid() {\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}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    startTime = chrono::steady_clock::now();\n\n    cin >> n >> m;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            cin >> g[i][j];\n            colorCnt[g[i][j]]++;\n        }\n    }\n\n    computeAdj(g, targetAdj);\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++) cells.push_back({i, j});\n    }\n\n    mt19937 rng(1234567);\n\n    int pass = 0;\n    while (elapsed() < timeLimit) {\n        pass++;\n\n        // Mix several orders. Boundary-first is often useful because zeros must touch outside.\n        if (pass % 4 == 1) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, N - 1 - a.first, N - 1 - a.second});\n                int db = min({b.first, b.second, N - 1 - b.first, N - 1 - b.second});\n                return da < db;\n            });\n        } else if (pass % 4 == 2) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, N - 1 - a.first, N - 1 - a.second});\n                int db = min({b.first, b.second, N - 1 - b.first, N - 1 - b.second});\n                return da > db;\n            });\n        } else {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n\n        bool changed = false;\n        for (auto [i, j] : cells) {\n            if (elapsed() > timeLimit) break;\n            if (tryEraseCell(i, j)) changed = true;\n        }\n\n        if (!changed && pass > 6) {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n    }\n\n    printGrid();\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    vector<int> ord;              // light -> heavy estimated\n    vector<vector<int>> groups;\n    vector<int> ans;\n\n    char query_vec(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        char c;\n        cin >> c;\n        used++;\n        return c;\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query_vec(L, R);\n    }\n\n    // returns true if item a is lighter than item b\n    bool less_item(int a, int b) {\n        char c = query_single(a, b);\n        return c == '<';\n    }\n\n    // compare current groups\n    // returns -1 if A lighter, 0 if equal/unknown, 1 if A heavier\n    int compare_group(int a, int b) {\n        if (groups[a].empty() && groups[b].empty()) return 0;\n        if (groups[a].empty()) return -1;\n        if (groups[b].empty()) return 1;\n        char c = query_vec(groups[a], groups[b]);\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    void bounded_insertion_sort() {\n        ord.clear();\n        ord.push_back(0);\n\n        for (int i = 1; i < N; i++) {\n            if (used >= Q) {\n                ord.push_back(i);\n                continue;\n            }\n\n            // Binary insertion if enough budget, otherwise linear fallback.\n            int lo = 0, hi = (int)ord.size();\n            while (lo < hi && used < Q) {\n                int mid = (lo + hi) / 2;\n                // if i < ord[mid], go left\n                bool lt = less_item(i, ord[mid]);\n                if (lt) hi = mid;\n                else lo = mid + 1;\n            }\n            ord.insert(ord.begin() + lo, i);\n        }\n\n        // If sorting was interrupted, ord still contains all items.\n        vector<int> seen(N, 0);\n        for (int x : ord) seen[x] = 1;\n        for (int i = 0; i < N; i++) {\n            if (!seen[i]) ord.push_back(i);\n        }\n    }\n\n    int find_lightest_group() {\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (used >= Q) break;\n            int cmp = compare_group(g, best);\n            if (cmp == -1) best = g;\n        }\n        return best;\n    }\n\n    void make_partition() {\n        groups.assign(D, {});\n        ans.assign(N, 0);\n\n        // Put heaviest estimated items first.\n        vector<int> heavy_to_light = ord;\n        reverse(heavy_to_light.begin(), heavy_to_light.end());\n\n        for (int item : heavy_to_light) {\n            int g;\n            if (used + D - 1 <= Q) {\n                g = find_lightest_group();\n            } else {\n                // query budget is tight: deterministic fallback\n                int mn = 0;\n                for (int i = 1; i < D; i++) {\n                    if (groups[i].size() < groups[mn].size()) mn = i;\n                }\n                g = mn;\n            }\n            groups[g].push_back(item);\n            ans[item] = g;\n        }\n    }\n\n    void spend_remaining_queries() {\n        // Use remaining queries in harmless but somewhat informative ways.\n        int ptr = 0;\n        while (used < Q) {\n            bool done = false;\n\n            // Prefer comparing non-empty groups.\n            for (int k = 0; k < D && used < Q; k++) {\n                int a = (ptr + k) % D;\n                int b = (ptr + k + 1) % D;\n                if (a == b) continue;\n                if (!groups[a].empty() && !groups[b].empty()) {\n                    query_vec(groups[a], groups[b]);\n                    done = true;\n                    break;\n                }\n            }\n            ptr++;\n\n            if (!done && used < Q) {\n                int a = used % N;\n                int b = (a + 1) % N;\n                query_single(a, b);\n            }\n        }\n    }\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        bounded_insertion_sort();\n\n        if (used < Q) {\n            make_partition();\n        } else {\n            // No budget left: simple sorted round-robin.\n            groups.assign(D, {});\n            ans.assign(N, 0);\n            vector<int> heavy_to_light = ord;\n            reverse(heavy_to_light.begin(), heavy_to_light.end());\n            for (int i = 0; i < (int)heavy_to_light.size(); i++) {\n                int g = i % D;\n                ans[heavy_to_light[i]] = g;\n                groups[g].push_back(heavy_to_light[i]);\n            }\n        }\n\n        spend_remaining_queries();\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << ans[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 200;\nstatic const int M = 10;\n\nstruct Solver {\n    int n, m;\n    vector<vector<int>> st;\n    vector<pair<int,int>> ans;\n\n    Solver(int n_, int m_, vector<vector<int>> s_) : n(n_), m(m_), st(std::move(s_)) {}\n\n    int find_stack(const vector<vector<int>>& a, int v) const {\n        for (int i = 0; i < m; i++) {\n            for (int x : a[i]) if (x == v) return i;\n        }\n        return -1;\n    }\n\n    int find_index(const vector<int>& s, int v) const {\n        for (int i = 0; i < (int)s.size(); i++) if (s[i] == v) return i;\n        return -1;\n    }\n\n    void remove_greedy_real(int &cur) {\n        bool changed = true;\n        while (cur <= n && changed) {\n            changed = false;\n            for (int i = 0; i < m; i++) {\n                if (!st[i].empty() && st[i].back() == cur) {\n                    st[i].pop_back();\n                    ans.push_back({cur, 0});\n                    cur++;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    int remove_greedy_sim(vector<vector<int>>& a, int cur, int limitCur) const {\n        bool changed = true;\n        while (cur <= limitCur && changed) {\n            changed = false;\n            for (int i = 0; i < m; i++) {\n                if (!a[i].empty() && a[i].back() == cur) {\n                    a[i].pop_back();\n                    cur++;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        return cur;\n    }\n\n    // Static evaluation of a state after processing current/future boxes.\n    double static_eval(const vector<vector<int>>& a, int cur) const {\n        double score = 0.0;\n\n        // Penalize \"bad\" adjacent boundaries.\n        // Good from bottom to top is decreasing, i.e. lower box > upper box.\n        for (int i = 0; i < m; i++) {\n            const auto& s = a[i];\n\n            score += 0.8 * (int)s.size();\n\n            for (int j = 0; j + 1 < (int)s.size(); j++) {\n                int lower = s[j];\n                int upper = s[j + 1];\n                if (lower < upper) {\n                    // smaller below larger: upper blocks smaller\n                    score += 8.0;\n                    if (lower < cur + 40) score += 10.0;\n                } else {\n                    score -= 1.0;\n                }\n            }\n\n            // Upcoming boxes should be close to top.\n            int h = (int)s.size();\n            for (int j = 0; j < h; j++) {\n                int v = s[j];\n                if (v >= cur && v < cur + 35) {\n                    int above = h - 1 - j;\n                    score += above * (38 - (v - cur)) * 0.33;\n                }\n            }\n\n            // Very small top is good.\n            if (!s.empty()) {\n                int top = s.back();\n                if (top >= cur && top < cur + 25) {\n                    score -= (30 - (top - cur)) * 1.5;\n                }\n            }\n        }\n\n        return score;\n    }\n\n    int choose_rollout_destination(int src, int idx, int cur) {\n        vector<int> seg;\n        for (int j = idx + 1; j < (int)st[src].size(); j++) seg.push_back(st[src][j]);\n\n        int k = (int)seg.size();\n        int moveBottom = seg.front();\n        int moveTop = seg.back();\n        int segMin = *min_element(seg.begin(), seg.end());\n\n        int bestDst = -1;\n        double bestScore = 1e100;\n\n        for (int dst = 0; dst < m; dst++) {\n            if (dst == src) continue;\n\n            vector<vector<int>> a = st;\n\n            // Apply candidate move.\n            for (int x : seg) a[dst].push_back(x);\n            a[src].resize(idx + 1);\n\n            int simCur = cur;\n            double cost = k + 1;\n\n            simCur = remove_greedy_sim(a, simCur, n);\n\n            // Short greedy rollout.\n            // It does not need to output operations; only estimates future cost.\n            int rolloutEnd = min(n, cur + 45);\n            int steps = 0;\n            while (simCur <= rolloutEnd && steps < 45) {\n                int s = find_stack(a, simCur);\n                if (s < 0) {\n                    simCur++;\n                    continue;\n                }\n                int id = find_index(a[s], simCur);\n                if (id == (int)a[s].size() - 1) {\n                    simCur = remove_greedy_sim(a, simCur, rolloutEnd);\n                    continue;\n                }\n\n                vector<int> sg;\n                for (int j = id + 1; j < (int)a[s].size(); j++) sg.push_back(a[s][j]);\n                int kk = (int)sg.size();\n\n                int sgBottom = sg.front();\n                int sgTop = sg.back();\n                int sgMin = *min_element(sg.begin(), sg.end());\n\n                int bd = -1;\n                double bs = 1e100;\n                for (int d = 0; d < m; d++) {\n                    if (d == s) continue;\n                    double sc = 0.0;\n\n                    if (a[d].empty()) {\n                        sc -= 250.0;\n                        sc += kk * 2.0;\n                    } else {\n                        int top = a[d].back();\n                        if (top > sgBottom) {\n                            sc -= 180.0;\n                            sc += (top - sgBottom) * 0.8;\n                        } else {\n                            sc += 350.0 + (sgBottom - top) * 5.0;\n                        }\n\n                        if (top < simCur + 25) {\n                            sc += 500.0 + (simCur + 25 - top) * 5.0;\n                        }\n\n                        sc += abs(top - sgBottom) * 0.5;\n                    }\n\n                    sc += (int)a[d].size() * 3.0;\n                    if (sgMin < simCur + 25) sc += (int)a[d].size() * 4.0;\n                    if (sgTop < simCur + 20) sc += (int)a[d].size() * 4.0;\n\n                    if (sc < bs) {\n                        bs = sc;\n                        bd = d;\n                    }\n                }\n\n                cost += kk + 1;\n\n                for (int x : sg) a[bd].push_back(x);\n                a[s].resize(id + 1);\n                simCur = remove_greedy_sim(a, simCur, rolloutEnd);\n                steps++;\n            }\n\n            double score = cost * 100.0 + static_eval(a, simCur);\n\n            // Extra immediate boundary adjustment.\n            if (!st[dst].empty()) {\n                int top = st[dst].back();\n                if (top > moveBottom) score -= 80.0;\n                else score += 120.0;\n                if (top < cur + 25) score += 300.0;\n            } else {\n                score -= 60.0;\n            }\n\n            // If segment contains a very soon box, prefer low destination height.\n            if (segMin < cur + 25) score += st[dst].size() * 25.0;\n            if (moveTop < cur + 25) score += st[dst].size() * 20.0;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestDst = dst;\n            }\n        }\n\n        if (bestDst == -1) bestDst = (src + 1) % m;\n        return bestDst;\n    }\n\n    void solve() {\n        int cur = 1;\n        remove_greedy_real(cur);\n\n        while (cur <= n) {\n            int src = find_stack(st, cur);\n            if (src < 0) {\n                remove_greedy_real(cur);\n                continue;\n            }\n\n            int idx = find_index(st[src], cur);\n            if (idx == (int)st[src].size() - 1) {\n                remove_greedy_real(cur);\n                continue;\n            }\n\n            int dst = choose_rollout_destination(src, idx, cur);\n\n            int v = st[src][idx + 1];\n            ans.push_back({v, dst + 1});\n\n            for (int j = idx + 1; j < (int)st[src].size(); j++) {\n                st[dst].push_back(st[src][j]);\n            }\n            st[src].resize(idx + 1);\n\n            remove_greedy_real(cur);\n\n            if ((int)ans.size() > 4900) break;\n        }\n\n        // Safety fallback, should essentially never be needed.\n        while (cur <= n && (int)ans.size() < 5000) {\n            remove_greedy_real(cur);\n            if (cur > n) break;\n\n            int src = find_stack(st, cur);\n            int idx = find_index(st[src], cur);\n\n            if (idx == (int)st[src].size() - 1) continue;\n\n            int dst = -1;\n            for (int i = 0; i < m; i++) {\n                if (i != src && st[i].empty()) {\n                    dst = i;\n                    break;\n                }\n            }\n            if (dst == -1) {\n                int bestH = INT_MAX;\n                for (int i = 0; i < m; i++) {\n                    if (i == src) continue;\n                    if ((int)st[i].size() < bestH) {\n                        bestH = st[i].size();\n                        dst = i;\n                    }\n                }\n            }\n\n            int v = st[src][idx + 1];\n            ans.push_back({v, dst + 1});\n            for (int j = idx + 1; j < (int)st[src].size(); j++) {\n                st[dst].push_back(st[src][j]);\n            }\n            st[src].resize(idx + 1);\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> st(m);\n    int h = n / m;\n    for (int i = 0; i < m; i++) {\n        st[i].resize(h);\n        for (int j = 0; j < h; j++) cin >> st[i][j];\n    }\n\n    Solver solver(n, m, st);\n    solver.solve();\n\n    if ((int)solver.ans.size() > 5000) {\n        solver.ans.resize(5000);\n    }\n\n    for (auto [v, to] : solver.ans) {\n        cout << v << ' ' << to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Child {\n    int to;\n    char dir;\n    char back;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> d[i][j];\n    }\n\n    int V = N * N;\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto pos = [&](int x) { return pair<int,int>(x / N, x % N); };\n\n    vector<vector<pair<int,char>>> g(V);\n\n    auto add_edge = [&](int a, int b, char c) {\n        g[a].push_back({b, c});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int cur = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(cur, id(i + 1, j), 'D');\n                add_edge(id(i + 1, j), cur, 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(cur, id(i, j + 1), 'R');\n                add_edge(id(i, j + 1), cur, 'L');\n            }\n        }\n    }\n\n    vector<int> parent(V, -1), parent_dir(V, -1);\n    vector<vector<int>> tree(V);\n\n    // Build a spanning tree. Prefer high-d neighboring cells while constructing.\n    vector<int> visited(V, 0);\n    priority_queue<pair<int,int>> pq;\n    visited[0] = 1;\n    pq.push({d[0][0], 0});\n\n    while (!pq.empty()) {\n        auto [_, u] = pq.top();\n        pq.pop();\n\n        vector<pair<int,char>> ng = g[u];\n        sort(ng.begin(), ng.end(), [&](auto &a, auto &b) {\n            auto [ai, aj] = pos(a.first);\n            auto [bi, bj] = pos(b.first);\n            return d[ai][aj] > d[bi][bj];\n        });\n\n        for (auto [to, c] : ng) {\n            if (!visited[to]) {\n                visited[to] = 1;\n                parent[to] = u;\n                parent_dir[to] = c;\n                tree[u].push_back(to);\n                pq.push({d[pos(to).first][pos(to).second], to});\n            }\n        }\n    }\n\n    // In rare case priority construction somehow misses none due connected guarantee,\n    // but keep a fallback DFS spanning tree for safety.\n    bool ok = true;\n    for (int i = 0; i < V; i++) if (!visited[i]) ok = false;\n\n    if (!ok) {\n        parent.assign(V, -1);\n        parent_dir.assign(V, -1);\n        tree.assign(V, {});\n        visited.assign(V, 0);\n\n        stack<int> st;\n        st.push(0);\n        visited[0] = 1;\n\n        while (!st.empty()) {\n            int u = st.top();\n            st.pop();\n            for (auto [to, c] : g[u]) {\n                if (!visited[to]) {\n                    visited[to] = 1;\n                    parent[to] = u;\n                    parent_dir[to] = c;\n                    tree[u].push_back(to);\n                    st.push(to);\n                }\n            }\n        }\n    }\n\n    vector<long long> sub(V, 0);\n\n    function<void(int)> calc = [&](int u) {\n        auto [i, j] = pos(u);\n        sub[u] = d[i][j];\n        for (int to : tree[u]) {\n            calc(to);\n            sub[u] += sub[to];\n        }\n    };\n    calc(0);\n\n    auto opposite = [&](char c) {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        return 'L';\n    };\n\n    for (int u = 0; u < V; u++) {\n        sort(tree[u].begin(), tree[u].end(), [&](int a, int b) {\n            return sub[a] > sub[b];\n        });\n    }\n\n    string ans;\n    ans.reserve(2 * V + 10);\n\n    function<void(int)> dfs = [&](int u) {\n        for (int to : tree[u]) {\n            char c = (char)parent_dir[to];\n            ans.push_back(c);\n            dfs(to);\n            ans.push_back(opposite(c));\n        }\n    };\n\n    dfs(0);\n\n    if ((int)ans.size() > 100000) {\n        // This will never happen for N<=40 with the tree tour,\n        // but keep output legal if modified.\n        ans.resize(100000);\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int r, c;\n};\n\nint manhattan(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint overlap_len(const string& a, const string& b) {\n    int best = 0;\n    for (int k = 1; k <= 4; k++) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[5 - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) best = k;\n    }\n    return best;\n}\n\nstring build_superstring_from_order(const vector<string>& t, const vector<int>& ord,\n                                    const vector<vector<int>>& ov) {\n    string s = t[ord[0]];\n    for (int i = 1; i < (int)ord.size(); i++) {\n        int a = ord[i - 1];\n        int b = ord[i];\n        int k = ov[a][b];\n        s += t[b].substr(k);\n    }\n    return s;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    Pos start;\n    cin >> start.r >> start.c;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) ov[i][j] = overlap_len(t[i], t[j]);\n        }\n    }\n\n    mt19937 rng(71236721);\n\n    vector<int> best_order;\n    string best_super;\n    int best_len = INT_MAX;\n\n    auto eval_order = [&](const vector<int>& ord) {\n        int len = 5;\n        for (int i = 1; i < M; i++) {\n            len += 5 - ov[ord[i - 1]][ord[i]];\n        }\n        return len;\n    };\n\n    auto make_greedy_order = [&](int st, double noise) {\n        vector<int> ord;\n        vector<char> used(M, false);\n        ord.reserve(M);\n\n        int cur = st;\n        ord.push_back(cur);\n        used[cur] = true;\n\n        for (int step = 1; step < M; step++) {\n            int best = -1;\n            double best_score = -1e100;\n\n            for (int nxt = 0; nxt < M; nxt++) {\n                if (used[nxt]) continue;\n\n                double score = ov[cur][nxt] * 1000.0;\n\n                // Tie-breaking: prefer words that also have many possible outgoing overlaps.\n                int mxout = 0;\n                for (int z = 0; z < M; z++) {\n                    if (!used[z] && z != nxt) mxout = max(mxout, ov[nxt][z]);\n                }\n                score += mxout * 10.0;\n\n                if (noise > 0) {\n                    score += uniform_real_distribution<double>(0.0, noise)(rng);\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best = nxt;\n                }\n            }\n\n            cur = best;\n            used[cur] = true;\n            ord.push_back(cur);\n        }\n\n        return ord;\n    };\n\n    // Deterministic starts.\n    for (int st = 0; st < M; st++) {\n        vector<int> ord = make_greedy_order(st, 0.0);\n        int len = eval_order(ord);\n        if (len < best_len) {\n            best_len = len;\n            best_order = ord;\n        }\n    }\n\n    // Randomized greedy attempts.\n    auto time_start = chrono::steady_clock::now();\n    int attempts = 0;\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - time_start).count();\n        if (elapsed > 0.45) break;\n\n        int st = uniform_int_distribution<int>(0, M - 1)(rng);\n        double noise = 800.0;\n        vector<int> ord = make_greedy_order(st, noise);\n        int len = eval_order(ord);\n        if (len < best_len) {\n            best_len = len;\n            best_order = ord;\n        }\n        attempts++;\n    }\n\n    // Local improvement by trying swaps/reversals with quick full reevaluation.\n    // M is only 200, so this is cheap.\n    bool improved = true;\n    int loop = 0;\n    while (improved && loop < 30) {\n        improved = false;\n        loop++;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 1; j < M; j++) {\n                vector<int> cand = best_order;\n                swap(cand[i], cand[j]);\n                int len = eval_order(cand);\n                if (len < best_len) {\n                    best_len = len;\n                    best_order.swap(cand);\n                    improved = true;\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 2; j < M; j++) {\n                vector<int> cand = best_order;\n                reverse(cand.begin() + i, cand.begin() + j + 1);\n                int len = eval_order(cand);\n                if (len < best_len) {\n                    best_len = len;\n                    best_order.swap(cand);\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    best_super = build_superstring_from_order(t, best_order, ov);\n\n    // Safety: if somehow too long, simple concatenation is still <=1000.\n    if ((int)best_super.size() > 5000) {\n        best_super.clear();\n        for (auto& x : t) best_super += x;\n    }\n\n    vector<vector<Pos>> occ(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            occ[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    int L = best_super.size();\n    const int INF = 1e9;\n\n    vector<vector<int>> dp(L);\n    vector<vector<int>> pre(L);\n\n    for (int idx = 0; idx < L; idx++) {\n        int ch = best_super[idx] - 'A';\n        int sz = occ[ch].size();\n        dp[idx].assign(sz, INF);\n        pre[idx].assign(sz, -1);\n\n        if (idx == 0) {\n            for (int k = 0; k < sz; k++) {\n                dp[idx][k] = manhattan(start, occ[ch][k]) + 1;\n            }\n        } else {\n            int pch = best_super[idx - 1] - 'A';\n            int psz = occ[pch].size();\n\n            for (int k = 0; k < sz; k++) {\n                for (int pk = 0; pk < psz; pk++) {\n                    int val = dp[idx - 1][pk] + manhattan(occ[pch][pk], occ[ch][k]) + 1;\n                    if (val < dp[idx][k]) {\n                        dp[idx][k] = val;\n                        pre[idx][k] = pk;\n                    }\n                }\n            }\n        }\n    }\n\n    int last_ch = best_super[L - 1] - 'A';\n    int best_last = 0;\n    for (int k = 1; k < (int)occ[last_ch].size(); k++) {\n        if (dp[L - 1][k] < dp[L - 1][best_last]) best_last = k;\n    }\n\n    vector<Pos> answer(L);\n    int cur_idx = best_last;\n    for (int idx = L - 1; idx >= 0; idx--) {\n        int ch = best_super[idx] - 'A';\n        answer[idx] = occ[ch][cur_idx];\n        cur_idx = pre[idx][cur_idx];\n    }\n\n    for (auto& p : answer) {\n        cout << p.r << ' ' << p.c << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<unsigned long long> bits;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n\n    int V = N * N;\n    int W = (V + 63) / 64;\n\n    vector<vector<pair<int,int>>> shape(M);\n    vector<int> h(M, 0), w(M, 0);\n\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        shape[k].resize(d);\n        for (int t = 0; t < d; t++) {\n            int i, j;\n            cin >> i >> j;\n            shape[k][t] = {i, j};\n            h[k] = max(h[k], i + 1);\n            w[k] = max(w[k], j + 1);\n        }\n    }\n\n    vector<vector<Placement>> cand(M);\n\n    for (int k = 0; k < M; k++) {\n        for (int si = 0; si + h[k] <= N; si++) {\n            for (int sj = 0; sj + w[k] <= N; sj++) {\n                Placement p;\n                p.bits.assign(W, 0);\n                for (auto [di, dj] : shape[k]) {\n                    int ni = si + di;\n                    int nj = sj + dj;\n                    int id = ni * N + nj;\n                    p.cells.push_back(id);\n                    p.bits[id >> 6] |= 1ULL << (id & 63);\n                }\n                cand[k].push_back(std::move(p));\n            }\n        }\n    }\n\n    vector<int> known(V, -1);\n    vector<int> drilled_positive;\n\n    auto contains_cell = [&](const Placement& p, int id) -> bool {\n        return (p.bits[id >> 6] >> (id & 63)) & 1ULL;\n    };\n\n    auto filter_candidates = [&](int id, int val) {\n        for (int k = 0; k < M; k++) {\n            vector<Placement> nxt;\n            nxt.reserve(cand[k].size());\n\n            for (auto &p : cand[k]) {\n                bool has = contains_cell(p, id);\n\n                /*\n                   Exact drill result val is total number of fields covering id.\n                   For a single field candidate:\n                   - If val == 0, no field may cover id.\n                   - If val > 0, the field may or may not cover id.\n                     So positive information alone cannot eliminate individual\n                     candidates safely without considering combinations.\n                */\n                if (val == 0 && has) continue;\n                nxt.push_back(std::move(p));\n            }\n\n            cand[k].swap(nxt);\n        }\n    };\n\n    auto build_union_from_singletons = [&]() -> vector<int> {\n        vector<int> mark(V, 0);\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n            const Placement& p = cand[k][0];\n            for (int id : p.cells) mark[id] = 1;\n        }\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            if (mark[id]) ans.push_back(id);\n        }\n        return ans;\n    };\n\n    auto build_union_most_likely = [&]() -> vector<int> {\n        vector<int> mark(V, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n\n            int best_idx = 0;\n            int best_score = -1;\n\n            for (int idx = 0; idx < (int)cand[k].size(); idx++) {\n                int score = 0;\n                for (int id : cand[k][idx].cells) {\n                    if (known[id] > 0) score += 1000;\n                    else if (known[id] == 0) score -= 1000000;\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best_idx = idx;\n                }\n            }\n\n            for (int id : cand[k][best_idx].cells) mark[id] = 1;\n        }\n\n        for (int id : drilled_positive) mark[id] = 1;\n\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            if (mark[id]) ans.push_back(id);\n        }\n        return ans;\n    };\n\n    auto output_answer = [&](const vector<int>& ans) -> bool {\n        cout << \"a \" << ans.size();\n        for (int id : ans) {\n            cout << ' ' << id / N << ' ' << id % N;\n        }\n        cout << endl;\n        cout.flush();\n\n        int res;\n        cin >> res;\n        return res == 1;\n    };\n\n    auto drill = [&](int id) -> int {\n        cout << \"q 1 \" << id / N << ' ' << id % N << endl;\n        cout.flush();\n\n        int val;\n        cin >> val;\n\n        known[id] = val;\n        if (val > 0) drilled_positive.push_back(id);\n        filter_candidates(id, val);\n        return val;\n    };\n\n    int op_count = 0;\n    int op_limit = 2 * N * N;\n\n    auto all_singleton = [&]() -> bool {\n        for (int k = 0; k < M; k++) {\n            if ((int)cand[k].size() != 1) return false;\n        }\n        return true;\n    };\n\n    auto choose_next_cell = [&]() -> int {\n        vector<double> cover_sum(V, 0.0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n            double inv = 1.0 / cand[k].size();\n            for (auto &p : cand[k]) {\n                for (int id : p.cells) {\n                    cover_sum[id] += inv;\n                }\n            }\n        }\n\n        int best = -1;\n        double best_score = -1.0;\n\n        for (int id = 0; id < V; id++) {\n            if (known[id] != -1) continue;\n\n            double p = cover_sum[id] / max(1, M);\n            double entropy_score = 1.0 - abs(2.0 * p - 1.0);\n\n            /*\n               Prefer cells that are likely to be oil but still uncertain.\n               Positive cells help locate shapes, zero cells prune candidates.\n            */\n            double oil_likelihood = min(1.0, cover_sum[id]);\n            double score = entropy_score + 0.35 * oil_likelihood;\n\n            if (score > best_score) {\n                best_score = score;\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id = 0; id < V; id++) {\n                if (known[id] == -1) return id;\n            }\n        }\n\n        return best;\n    };\n\n    while (op_count + 1 < op_limit) {\n        if (all_singleton()) {\n            vector<int> ans = build_union_from_singletons();\n            op_count++;\n            if (output_answer(ans)) return 0;\n        }\n\n        int remaining_product_log = 0;\n        bool small_uncertainty = true;\n        for (int k = 0; k < M; k++) {\n            if ((int)cand[k].size() > 4) small_uncertainty = false;\n        }\n\n        if (small_uncertainty && op_count + 1 < op_limit) {\n            vector<int> ans = build_union_most_likely();\n            op_count++;\n            if (output_answer(ans)) return 0;\n        }\n\n        int id = choose_next_cell();\n        if (id < 0) break;\n\n        drill(id);\n        op_count++;\n    }\n\n    /*\n       Safe fallback: drill every remaining unknown cell exactly.\n       This preserves correctness as long as operation limit remains.\n    */\n    for (int id = 0; id < V && op_count + 1 < op_limit; id++) {\n        if (known[id] == -1) {\n            drill(id);\n            op_count++;\n        }\n    }\n\n    vector<int> final_ans;\n    for (int id = 0; id < V; id++) {\n        if (known[id] > 0) final_ans.push_back(id);\n    }\n\n    op_count++;\n    output_answer(final_ans);\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int WFIX = 1000;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        auto now = chrono::steady_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n};\n\nint W, D, N;\nvector<vector<int>> A;\nvector<vector<int>> wid;\n\nlong long shortage_cost_day(int d) {\n    long long c = 0;\n    for (int k = 0; k < N; k++) {\n        long long area = 1LL * W * wid[d][k];\n        if (A[d][k] > area) c += 100LL * (A[d][k] - area);\n    }\n    return c;\n}\n\nvector<int> boundaries_day(int d) {\n    vector<int> b;\n    int x = 0;\n    for (int k = 0; k < N - 1; k++) {\n        x += wid[d][k];\n        b.push_back(x);\n    }\n    return b;\n}\n\nlong long transition_cost_pair(int d) {\n    // Cost between day d-1 and d for full-height vertical strips.\n    if (d <= 0) return 0;\n    vector<int> b0 = boundaries_day(d - 1);\n    vector<int> b1 = boundaries_day(d);\n\n    // Internal vertical segment at boundary x exists for y=0..W-1.\n    // Symmetric difference of boundary x sets times W.\n    int i = 0, j = 0;\n    int common = 0;\n    while (i < (int)b0.size() && j < (int)b1.size()) {\n        if (b0[i] == b1[j]) {\n            common++;\n            i++;\n            j++;\n        } else if (b0[i] < b1[j]) {\n            i++;\n        } else {\n            j++;\n        }\n    }\n    int diff = (int)b0.size() + (int)b1.size() - 2 * common;\n    return 1LL * W * diff;\n}\n\nlong long total_score_like() {\n    long long c = 0;\n    for (int d = 0; d < D; d++) c += shortage_cost_day(d);\n    for (int d = 1; d < D; d++) c += transition_cost_pair(d);\n    return c;\n}\n\nlong long local_part_cost(int d) {\n    long long c = shortage_cost_day(d);\n    if (d >= 1) c += transition_cost_pair(d);\n    if (d + 1 < D) c += transition_cost_pair(d + 1);\n    return c;\n}\n\nvoid normalize_day_initial(int d) {\n    wid[d].assign(N, 1);\n\n    vector<int> req(N);\n    long long sum = 0;\n    for (int k = 0; k < N; k++) {\n        req[k] = max(1, (A[d][k] + W - 1) / W);\n        wid[d][k] = req[k];\n        sum += wid[d][k];\n    }\n\n    if (sum < W) {\n        // Add extra space to large requests first; no shortage benefit usually,\n        // but it may reduce future shortage after local search movement.\n        int rem = W - (int)sum;\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int x, int y) {\n            return A[d][x] > A[d][y];\n        });\n        int p = 0;\n        while (rem--) {\n            wid[d][ord[p]]++;\n            p++;\n            if (p == N) p = 0;\n        }\n    } else if (sum > W) {\n        int over = (int)(sum - W);\n\n        // Remove columns where damage is smallest.\n        // Damage of reducing width by 1:\n        // 100 * increase in shortage = 100 * min(W, max(0, A-area_after) - max(0,A-area_before)).\n        while (over > 0) {\n            int bestK = -1;\n            long long bestDamage = LLONG_MAX;\n            for (int k = 0; k < N; k++) {\n                if (wid[d][k] <= 1) continue;\n                long long beforeArea = 1LL * W * wid[d][k];\n                long long afterArea = 1LL * W * (wid[d][k] - 1);\n                long long beforeShort = max(0LL, 1LL * A[d][k] - beforeArea);\n                long long afterShort = max(0LL, 1LL * A[d][k] - afterArea);\n                long long dmg = 100LL * (afterShort - beforeShort);\n                // Tie-break: reduce larger widths.\n                dmg = dmg * 10000 - wid[d][k];\n                if (dmg < bestDamage) {\n                    bestDamage = dmg;\n                    bestK = k;\n                }\n            }\n            if (bestK < 0) break;\n            wid[d][bestK]--;\n            over--;\n        }\n    }\n}\n\nvoid initialize_solution() {\n    wid.assign(D, vector<int>(N, 1));\n\n    // Candidate 1: per-day demand layout.\n    vector<vector<int>> bestWid(D, vector<int>(N));\n    for (int d = 0; d < D; d++) normalize_day_initial(d);\n    bestWid = wid;\n    long long bestScore = total_score_like();\n\n    // Candidate 2: fixed median/DP-like stable layout from previous approach.\n    vector<vector<long long>> cost(N, vector<long long>(W + 1, 0));\n    for (int k = 0; k < N; k++) {\n        for (int w = 1; w <= W; w++) {\n            long long c = 0;\n            long long area = 1LL * W * w;\n            for (int d = 0; d < D; d++) {\n                if (A[d][k] > area) c += 100LL * (A[d][k] - area);\n            }\n            cost[k][w] = c;\n        }\n    }\n\n    const long long INF = (1LL << 60);\n    vector<vector<long long>> dp(N + 1, vector<long long>(W + 1, INF));\n    vector<vector<int>> pre(N + 1, vector<int>(W + 1, -1));\n    dp[0][0] = 0;\n    for (int k = 0; k < N; k++) {\n        for (int used = 0; used <= W; used++) if (dp[k][used] < INF) {\n            int remain = N - k - 1;\n            for (int ww = 1; used + ww + remain <= W; ww++) {\n                long long nv = dp[k][used] + cost[k][ww];\n                if (nv < dp[k + 1][used + ww]) {\n                    dp[k + 1][used + ww] = nv;\n                    pre[k + 1][used + ww] = ww;\n                }\n            }\n        }\n    }\n\n    int bu = N;\n    for (int u = N; u <= W; u++) {\n        if (dp[N][u] < dp[N][bu]) bu = u;\n    }\n\n    vector<int> fixed(N);\n    int cur = bu;\n    for (int k = N; k >= 1; k--) {\n        fixed[k - 1] = pre[k][cur];\n        cur -= fixed[k - 1];\n    }\n\n    int used = accumulate(fixed.begin(), fixed.end(), 0);\n    while (used < W) {\n        int bestK = 0;\n        long long bestGain = LLONG_MIN;\n        for (int k = 0; k < N; k++) {\n            long long gain = cost[k][fixed[k]] - cost[k][fixed[k] + 1];\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestK = k;\n            }\n        }\n        fixed[bestK]++;\n        used++;\n    }\n\n    wid.assign(D, fixed);\n    long long sc2 = total_score_like();\n    if (sc2 < bestScore) {\n        bestScore = sc2;\n        bestWid = wid;\n    }\n\n    wid = bestWid;\n}\n\nvoid greedy_local_search(const Timer& timer) {\n    XorShift rng;\n    long long curScore = total_score_like();\n\n    // Deterministic adjacent-transfer improvement.\n    bool improved = true;\n    int pass = 0;\n    while (improved && pass < 30 && timer.elapsed() < 2.5) {\n        improved = false;\n        pass++;\n\n        for (int d = 0; d < D && timer.elapsed() < 2.5; d++) {\n            bool dayImp = true;\n            int inner = 0;\n            while (dayImp && inner < 200) {\n                dayImp = false;\n                inner++;\n\n                long long base = local_part_cost(d);\n                int bestFrom = -1, bestTo = -1;\n                long long bestDelta = 0;\n\n                // Try all one-column moves within this day.\n                for (int from = 0; from < N; from++) {\n                    if (wid[d][from] <= 1) continue;\n                    for (int to = 0; to < N; to++) {\n                        if (from == to) continue;\n\n                        wid[d][from]--;\n                        wid[d][to]++;\n                        long long nc = local_part_cost(d);\n                        wid[d][from]++;\n                        wid[d][to]--;\n\n                        long long delta = nc - base;\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestFrom = from;\n                            bestTo = to;\n                        }\n                    }\n                }\n\n                if (bestDelta < 0) {\n                    wid[d][bestFrom]--;\n                    wid[d][bestTo]++;\n                    curScore += bestDelta;\n                    improved = true;\n                    dayImp = true;\n                }\n            }\n        }\n    }\n\n    // Randomized hill climbing, including larger jumps.\n    double TL = 2.85;\n    while (timer.elapsed() < TL) {\n        int d = rng.randint(0, D - 1);\n        int from = rng.randint(0, N - 1);\n        int to = rng.randint(0, N - 1);\n        if (from == to || wid[d][from] <= 1) continue;\n\n        int maxMove = min(wid[d][from] - 1, 10);\n        if (maxMove <= 0) continue;\n        int mv = 1;\n        if ((rng.next() & 7) == 0) mv = rng.randint(1, maxMove);\n\n        long long base = local_part_cost(d);\n        wid[d][from] -= mv;\n        wid[d][to] += mv;\n        long long nc = local_part_cost(d);\n\n        if (nc <= base) {\n            curScore += nc - base;\n        } else {\n            wid[d][from] += mv;\n            wid[d][to] -= mv;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> W >> D >> N;\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    initialize_solution();\n    greedy_local_search(timer);\n\n    // Output vertical full-height strips.\n    for (int d = 0; d < D; d++) {\n        int x = 0;\n        for (int k = 0; k < N; k++) {\n            int x2 = x + wid[d][k];\n\n            // Safety correction for final rectangle.\n            if (k == N - 1) x2 = W;\n\n            // Rect: top-left (0,x), bottom-right (W,x2)\n            // Since every width is >=1 and sum is W, valid.\n            cout << 0 << ' ' << x << ' ' << W << ' ' << x2 << '\\n';\n            x = x2;\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr long long MOD = 998244353LL;\nstatic constexpr int N = 9;\nstatic constexpr int M = 20;\nstatic constexpr int K = 81;\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct Cand {\n    long long gain;\n    int m, p, q;\n    bool operator<(const Cand& other) const {\n        return gain > other.gain;\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    XorShift() {}\n    XorShift(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n    double uniform() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nlong long calc_score(const array<array<long long, N>, N>& b) {\n    long long score = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            score += b[i][j];\n        }\n    }\n    return score;\n}\n\nlong long calc_gain(\n    const array<array<long long, N>, N>& b,\n    const long long s[M][3][3],\n    int m,\n    int p,\n    int q\n) {\n    long long gain = 0;\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            long long oldv = b[p + i][q + j];\n            long long nv = oldv + s[m][i][j];\n            if (nv >= MOD) nv -= MOD;\n            gain += nv - oldv;\n        }\n    }\n    return gain;\n}\n\nvoid apply_op(\n    array<array<long long, N>, N>& b,\n    const long long s[M][3][3],\n    int m,\n    int p,\n    int q\n) {\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            b[p + i][q + j] += s[m][i][j];\n            if (b[p + i][q + j] >= MOD) b[p + i][q + j] -= MOD;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m_input, k_input;\n    cin >> n >> m_input >> k_input;\n\n    array<array<long long, N>, N> initial{};\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    static long long stamp[M][3][3];\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamp[m][i][j];\n            }\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    vector<Op> best_ops;\n    long long best_score = calc_score(initial);\n\n    XorShift rng(\n        chrono::steady_clock::now().time_since_epoch().count()\n    );\n\n    int trial = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        array<array<long long, N>, N> b = initial;\n        vector<Op> ops;\n        long long score = calc_score(b);\n\n        for (int step = 0; step < K; step++) {\n            vector<Cand> cands;\n            cands.reserve(M * 49);\n\n            for (int sm = 0; sm < M; sm++) {\n                for (int p = 0; p <= N - 3; p++) {\n                    for (int q = 0; q <= N - 3; q++) {\n                        long long g = calc_gain(b, stamp, sm, p, q);\n                        if (g > 0) {\n                            cands.push_back({g, sm, p, q});\n                        }\n                    }\n                }\n            }\n\n            if (cands.empty()) break;\n\n            sort(cands.begin(), cands.end());\n\n            Cand chosen = cands[0];\n\n            if (trial > 0) {\n                int top = min<int>((int)cands.size(), 12);\n\n                // Earlier steps are randomized more, later steps become greedier.\n                double temp = 1.0 - double(step) / K;\n                double r = rng.uniform();\n\n                if (r < 0.70 + 0.25 * (1.0 - temp)) {\n                    chosen = cands[0];\n                } else {\n                    int idx = rng.randint(0, top - 1);\n                    chosen = cands[idx];\n                }\n            }\n\n            apply_op(b, stamp, chosen.m, chosen.p, chosen.q);\n            score += chosen.gain;\n            ops.push_back({chosen.m, chosen.p, chosen.q});\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n\n        trial++;\n    }\n\n    cout << best_ops.size() << '\\n';\n    for (auto &op : best_ops) {\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static constexpr int N = 5;\n\n    vector<vector<int>> A;\n    vector<int> ptr;\n    vector<vector<int>> grid;\n    vector<pair<int,int>> pos;\n\n    vector<string> ans;\n\n    int cr = 0, cc = 0;\n    bool holding = false;\n    int hold = -1;\n\n    Solver(const vector<vector<int>>& A_) : A(A_) {\n        ptr.assign(N, 0);\n        grid.assign(N, vector<int>(N, -1));\n        pos.assign(N * N, {-1, -1});\n        ans.assign(N, \"\");\n\n        // Initial receiving phase before turn 0.\n        for (int i = 0; i < N; i++) {\n            grid[i][0] = A[i][0];\n            pos[A[i][0]] = {i, 0};\n            ptr[i] = 1;\n        }\n    }\n\n    void append_large(char c) {\n        ans[0].push_back(c);\n\n        if (c == 'U') cr--;\n        else if (c == 'D') cr++;\n        else if (c == 'L') cc--;\n        else if (c == 'R') cc++;\n    }\n\n    void append_turn(char c0) {\n        append_large(c0);\n    }\n\n    void receive_phase_after_turn() {\n        // This function is called logically after a turn is completed.\n        // Actual receiving happens at the start of the next turn.\n        // Instead of simulating time phase-by-phase exactly here,\n        // we update receiving gates before every crane action.\n    }\n\n    void do_receive() {\n        for (int i = 0; i < N; i++) {\n            if (ptr[i] < N && grid[i][0] == -1) {\n                // If the large crane is holding a container and is at this cell,\n                // receiving would be blocked. Avoid depending on subtle rules.\n                if (holding && cr == i && cc == 0) continue;\n\n                int x = A[i][ptr[i]++];\n                grid[i][0] = x;\n                pos[x] = {i, 0};\n            }\n        }\n    }\n\n    void move_one(char c) {\n        do_receive();\n        append_turn(c);\n    }\n\n    void move_to(int tr, int tc) {\n        while (cr < tr) move_one('D');\n        while (cr > tr) move_one('U');\n        while (cc < tc) move_one('R');\n        while (cc > tc) move_one('L');\n    }\n\n    void pick() {\n        do_receive();\n\n        int x = grid[cr][cc];\n        // Must be valid.\n        if (x == -1) {\n            // Should never happen.\n            append_turn('.');\n            return;\n        }\n\n        append_turn('P');\n\n        holding = true;\n        hold = x;\n        grid[cr][cc] = -1;\n        pos[x] = {-1, -1};\n    }\n\n    void release() {\n        do_receive();\n\n        append_turn('Q');\n\n        holding = false;\n\n        // If released at dispatch gate, it disappears at end of turn.\n        if (cc == N - 1) {\n            pos[hold] = {-2, -2}; // dispatched\n        } else {\n            grid[cr][cc] = hold;\n            pos[hold] = {cr, cc};\n        }\n\n        hold = -1;\n    }\n\n    bool is_dispatch_cell(int r, int c) {\n        return c == N - 1;\n    }\n\n    bool is_receiving_cell(int r, int c) {\n        return c == 0;\n    }\n\n    vector<pair<int,int>> storage_candidates() {\n        vector<pair<int,int>> cells;\n\n        // Prefer inner cells close to the center/right side.\n        // Columns 1..3 are safe storage.\n        for (int c = 1; c <= 3; c++) {\n            for (int r = 0; r < N; r++) {\n                cells.push_back({r, c});\n            }\n        }\n\n        // Also allow exhausted receiving gates as storage fallback.\n        for (int r = 0; r < N; r++) {\n            cells.push_back({r, 0});\n        }\n\n        return cells;\n    }\n\n    pair<int,int> find_empty_storage() {\n        auto cells = storage_candidates();\n\n        pair<int,int> best = {-1, -1};\n        int bestDist = 1e9;\n\n        for (auto [r, c] : cells) {\n            if (grid[r][c] != -1) continue;\n            if (is_dispatch_cell(r, c)) continue;\n\n            // Avoid using a receiving gate that still has unrevealed containers.\n            if (c == 0 && ptr[r] < N) continue;\n\n            int d = abs(cr - r) + abs(cc - c);\n            if (d < bestDist) {\n                bestDist = d;\n                best = {r, c};\n            }\n        }\n\n        return best;\n    }\n\n    void carry_to(int r, int c) {\n        move_to(r, c);\n        release();\n    }\n\n    void deliver_held_to_correct_gate() {\n        int dest = hold / N;\n        move_to(dest, N - 1);\n        release();\n    }\n\n    bool target_on_grid(int target) {\n        return pos[target].first >= 0;\n    }\n\n    void pick_container_at(pair<int,int> p) {\n        move_to(p.first, p.second);\n        pick();\n    }\n\n    int choose_revealing_row(int target) {\n        // If target is still hidden, reveal from its input row if known.\n        // Otherwise choose any row with visible front container / remaining queue.\n        int targetRow = -1;\n        for (int r = 0; r < N; r++) {\n            for (int k = ptr[r]; k < N; k++) {\n                if (A[r][k] == target) {\n                    targetRow = r;\n                    break;\n                }\n            }\n            if (targetRow != -1) break;\n        }\n\n        if (targetRow != -1) {\n            if (grid[targetRow][0] != -1) return targetRow;\n        }\n\n        // Prefer rows whose front gate has a container.\n        int best = -1;\n        int bestDist = 1e9;\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] != -1) {\n                int d = abs(cr - r) + abs(cc - 0);\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = r;\n                }\n            }\n        }\n\n        return best;\n    }\n\n    void store_held() {\n        auto p = find_empty_storage();\n\n        // In this small instance, this should normally succeed.\n        // If not, dispatch the held container to its correct gate.\n        // This may introduce inversions, but avoids deadlock.\n        if (p.first == -1) {\n            deliver_held_to_correct_gate();\n            return;\n        }\n\n        carry_to(p.first, p.second);\n    }\n\n    void solve_exact_order() {\n        // Turn 0 small cranes bomb. We let crane 0 do useful work normally.\n        for (int i = 1; i < N; i++) ans[i].push_back('B');\n\n        for (int target = 0; target < N * N; target++) {\n            while (true) {\n                if (target_on_grid(target)) {\n                    pick_container_at(pos[target]);\n                    deliver_held_to_correct_gate();\n                    break;\n                }\n\n                int row = choose_revealing_row(target);\n\n                if (row == -1) {\n                    // Should not happen unless all remaining containers are hidden\n                    // behind blocked gates, but then some gate must contain something.\n                    move_one('.');\n                    continue;\n                }\n\n                move_to(row, 0);\n                pick();\n\n                if (hold == target) {\n                    deliver_held_to_correct_gate();\n                    break;\n                } else {\n                    store_held();\n                }\n            }\n        }\n    }\n\n    vector<string> run() {\n        solve_exact_order();\n\n        int L = 0;\n        for (auto &s : ans) L = max(L, (int)s.size());\n        for (auto &s : ans) {\n            while ((int)s.size() < L) s.push_back('.');\n        }\n\n        return ans;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    Solver solver(A);\n    auto ans = solver.run();\n\n    for (auto &s : ans) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<vector<int>> H;\n\nstruct Result {\n    long long cost = (1LL << 60);\n    vector<string> ops;\n};\n\nstruct Cell {\n    int r, c;\n    int v;\n};\n\nstruct Params {\n    double emptyDistW;\n    double deliverDistW;\n    double amountBonus;\n    double sourceToSinkW;\n};\n\nint manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nvoid move_to(vector<string>& ops, long long& cost, long long load,\n             int& r, int& c, int nr, int nc) {\n    while (r < nr) {\n        ops.push_back(\"D\");\n        cost += 100 + load;\n        r++;\n    }\n    while (r > nr) {\n        ops.push_back(\"U\");\n        cost += 100 + load;\n        r--;\n    }\n    while (c < nc) {\n        ops.push_back(\"R\");\n        cost += 100 + load;\n        c++;\n    }\n    while (c > nc) {\n        ops.push_back(\"L\");\n        cost += 100 + load;\n        c--;\n    }\n}\n\nResult simulate_greedy(const Params& par) {\n    vector<Cell> pos, neg;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (H[i][j] > 0) pos.push_back({i, j, H[i][j]});\n            if (H[i][j] < 0) neg.push_back({i, j, -H[i][j]});\n        }\n    }\n\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n    int lastSrcR = 0, lastSrcC = 0;\n\n    int remainPos = 0, remainNeg = 0;\n    for (auto& x : pos) remainPos += x.v;\n    for (auto& x : neg) remainNeg += x.v;\n\n    while (remainNeg > 0) {\n        if (load == 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)pos.size(); i++) {\n                if (pos[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, pos[i].r, pos[i].c);\n\n                // Prefer sources that have nearby remaining sinks.\n                int nearestSink = 1000000;\n                for (auto& g : neg) {\n                    if (g.v <= 0) continue;\n                    nearestSink = min(nearestSink, manhattan(pos[i].r, pos[i].c, g.r, g.c));\n                }\n\n                double score =\n                    par.emptyDistW * dcur\n                    + par.sourceToSinkW * nearestSink\n                    - par.amountBonus * sqrt((double)pos[i].v);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, pos[best].r, pos[best].c);\n\n            int d = pos[best].v;\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            remainPos -= d;\n            pos[best].v = 0;\n            lastSrcR = r;\n            lastSrcC = c;\n        }\n\n        while (load > 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)neg.size(); i++) {\n                if (neg[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, neg[i].r, neg[i].c);\n                int dsrc = manhattan(lastSrcR, lastSrcC, neg[i].r, neg[i].c);\n                int give = min<long long>(load, neg[i].v);\n\n                double score =\n                    par.deliverDistW * dcur\n                    + 0.25 * dsrc\n                    - par.amountBonus * sqrt((double)give);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, neg[best].r, neg[best].c);\n\n            int d = min<long long>(load, neg[best].v);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            neg[best].v -= d;\n            remainNeg -= d;\n        }\n    }\n\n    if ((int)ops.size() > 100000) {\n        Result bad;\n        return bad;\n    }\n\n    return {cost, ops};\n}\n\n// Previous snake fallback, useful for cases where greedy behaves poorly.\nResult simulate_path(const vector<pair<int,int>>& path) {\n    vector<vector<int>> h = H;\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n\n    auto process_cell = [&](int i, int j) {\n        if (h[i][j] > 0) {\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        } else if (h[i][j] < 0 && load > 0) {\n            int d = min<long long>(-h[i][j], load);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] += d;\n        }\n    };\n\n    for (auto [i,j] : path) {\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (int idx = (int)path.size() - 1; idx >= 0; idx--) {\n        auto [i,j] = path[idx];\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] > 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        }\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] < 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = -h[i][j];\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] = 0;\n        }\n    }\n\n    return {cost, ops};\n}\n\nvector<pair<int,int>> row_snake() {\n    vector<pair<int,int>> p;\n    for (int i = 0; i < N; i++) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; j++) p.push_back({i,j});\n        } else {\n            for (int j = N - 1; j >= 0; j--) p.push_back({i,j});\n        }\n    }\n    return p;\n}\n\nvector<pair<int,int>> col_snake() {\n    vector<pair<int,int>> p;\n    for (int j = 0; j < N; j++) {\n        if (j % 2 == 0) {\n            for (int i = 0; i < N; i++) p.push_back({i,j});\n        } else {\n            for (int i = N - 1; i >= 0; i--) p.push_back({i,j});\n        }\n    }\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    H.assign(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> H[i][j];\n    }\n\n    Result best;\n\n    vector<Params> params = {\n        {1.0, 1.0, 0.0, 0.0},\n        {1.0, 1.0, 1.0, 0.2},\n        {1.0, 1.0, 2.0, 0.5},\n        {1.0, 1.3, 1.0, 0.5},\n        {1.3, 1.0, 1.0, 0.5},\n        {0.7, 1.2, 2.0, 0.8},\n        {1.5, 0.8, 1.5, 0.3},\n        {1.0, 2.0, 2.0, 1.0},\n        {2.0, 1.0, 2.0, 1.0},\n        {0.5, 1.5, 1.0, 1.0},\n    };\n\n    for (auto& p : params) {\n        Result res = simulate_greedy(p);\n        if (res.cost < best.cost) best = move(res);\n    }\n\n    vector<vector<pair<int,int>>> paths;\n    paths.push_back(row_snake());\n    paths.push_back(col_snake());\n\n    for (int k = 0; k < 2; k++) {\n        auto q = paths[k];\n        reverse(q.begin(), q.end());\n        paths.push_back(q);\n    }\n\n    for (auto& path : paths) {\n        Result res = simulate_path(path);\n        if ((int)res.ops.size() <= 100000 && res.cost < best.cost) {\n            best = move(res);\n        }\n    }\n\n    for (auto& s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ull) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n    double rand01() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int S = 2 * N * (N - 1); // 60\n    const int C = N * N;           // 36\n\n    vector<vector<int>> X(S, vector<int>(M));\n    for (int i = 0; i < S; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    vector<pair<int,int>> edges;\n    vector<vector<int>> incident(C);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (j + 1 < N) {\n                int id2 = id + 1;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n            if (i + 1 < N) {\n                int id2 = id + N;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n        }\n    }\n\n    vector<int> deg(C, 0);\n    for (auto [a,b] : edges) {\n        deg[a]++;\n        deg[b]++;\n    }\n\n    vector<int> blackCells, whiteCells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if ((i + j) & 1) whiteCells.push_back(id);\n            else blackCells.push_back(id);\n        }\n    }\n\n    auto sort_cells = [&](vector<int>& v) {\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n    };\n    sort_cells(blackCells);\n    sort_cells(whiteCells);\n\n    auto start_time = chrono::steady_clock::now();\n    XorShift rng(123456789);\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> mx(M, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) mx[l] = max(mx[l], X[i][l]);\n        }\n\n        int mxSum = accumulate(mx.begin(), mx.end(), 0);\n\n        vector<int> sumv(S, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) sumv[i] += X[i][l];\n        }\n\n        double phase = (double)turn / max(1, T - 1); // 0 early, 1 late\n\n        vector<double> seedScore(S, 0);\n        for (int i = 0; i < S; i++) {\n            double norm = 0;\n            double elite = 0;\n            double sq = 0;\n            for (int l = 0; l < M; l++) {\n                double r = (double)X[i][l] / max(1, mx[l]);\n                norm += 100.0 * r;\n                sq += 100.0 * r * r;\n                if (X[i][l] == mx[l]) elite += 90.0;\n                else if (X[i][l] >= mx[l] * 0.95) elite += 45.0;\n                else if (X[i][l] >= mx[l] * 0.88) elite += 18.0;\n            }\n            seedScore[i] = (0.95 + 0.55 * phase) * sumv[i]\n                         + 0.75 * norm\n                         + 0.25 * sq\n                         + elite;\n        }\n\n        vector<int> selected;\n        vector<int> used(S, 0);\n\n        // Must keep coordinate champions.\n        vector<int> champions;\n        for (int l = 0; l < M; l++) {\n            int best = 0;\n            for (int i = 1; i < S; i++) {\n                if (X[i][l] > X[best][l] ||\n                    (X[i][l] == X[best][l] && sumv[i] > sumv[best])) {\n                    best = i;\n                }\n            }\n            champions.push_back(best);\n        }\n        sort(champions.begin(), champions.end());\n        champions.erase(unique(champions.begin(), champions.end()), champions.end());\n\n        sort(champions.begin(), champions.end(), [&](int a, int b) {\n            return seedScore[a] > seedScore[b];\n        });\n\n        for (int id : champions) {\n            if (!used[id] && (int)selected.size() < C) {\n                used[id] = 1;\n                selected.push_back(id);\n            }\n        }\n\n        // Add several high-value seeds.\n        vector<int> ord(S);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            return seedScore[a] > seedScore[b];\n        });\n\n        int highTake = 8 + (int)(6 * phase);\n        for (int id : ord) {\n            if ((int)selected.size() >= highTake) break;\n            if (!used[id]) {\n                used[id] = 1;\n                selected.push_back(id);\n            }\n        }\n\n        vector<int> cover(M, 0);\n        for (int id : selected) {\n            for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[id][l]);\n        }\n\n        // Greedy marginal coverage/value selection.\n        while ((int)selected.size() < C) {\n            int best = -1;\n            double bestSc = -1e100;\n\n            for (int i = 0; i < S; i++) if (!used[i]) {\n                double gain = 0;\n                for (int l = 0; l < M; l++) {\n                    int d = max(0, X[i][l] - cover[l]);\n                    gain += 11.0 * d;\n                    double r = (double)X[i][l] / max(1, mx[l]);\n                    gain += 25.0 * r;\n                    if (X[i][l] >= mx[l] * 0.92) gain += 18.0;\n                }\n\n                // Complementarity with already selected seeds.\n                double comp = 0;\n                for (int id : selected) {\n                    int pairMax = 0;\n                    for (int l = 0; l < M; l++) {\n                        pairMax += max(X[i][l], X[id][l]);\n                    }\n                    comp = max(comp, (double)pairMax);\n                }\n\n                double sc = gain\n                          + (0.50 + 0.45 * phase) * seedScore[i]\n                          + 0.18 * comp\n                          + rng.rand01() * 1e-3;\n\n                if (sc > bestSc) {\n                    bestSc = sc;\n                    best = i;\n                }\n            }\n\n            used[best] = 1;\n            selected.push_back(best);\n            for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[best][l]);\n        }\n\n        // Precompute pair scores.\n        vector<vector<double>> P(S, vector<double>(S, 0));\n\n        for (int a = 0; a < S; a++) {\n            for (int b = a + 1; b < S; b++) {\n                int maxsum = 0;\n                int minsum = 0;\n                int diff = 0;\n                int near = 0;\n                int bothHigh = 0;\n\n                for (int l = 0; l < M; l++) {\n                    int ma = max(X[a][l], X[b][l]);\n                    int mi = min(X[a][l], X[b][l]);\n                    maxsum += ma;\n                    minsum += mi;\n                    diff += abs(X[a][l] - X[b][l]);\n\n                    if (ma >= mx[l] * 0.90) near++;\n                    if (X[a][l] >= mx[l] * 0.75 && X[b][l] >= mx[l] * 0.75) bothHigh++;\n                }\n\n                double expected = 0.5 * (sumv[a] + sumv[b]);\n\n                // Approximate probability-oriented bonus:\n                // high coordinate-wise max is very important.\n                double sc = 0;\n                sc += (1.55 + 0.30 * phase) * maxsum;\n                sc += (0.30 + 0.70 * phase) * expected;\n                sc += 0.25 * minsum;\n                sc += (0.18 - 0.08 * phase) * diff;\n                sc += 28.0 * near;\n                sc += 5.0 * bothHigh;\n\n                // If the pair coordinate-wise max is close to current theoretical max,\n                // it deserves extra attention.\n                if (mxSum > 0) {\n                    double ratio = (double)maxsum / mxSum;\n                    sc += 180.0 * ratio * ratio;\n                }\n\n                P[a][b] = P[b][a] = sc;\n            }\n        }\n\n        // Initial bipartite placement.\n        vector<int> groupA, groupB;\n\n        // Seed groupA with strongest selected seed, then balance by complementarity.\n        vector<int> rem = selected;\n        sort(rem.begin(), rem.end(), [&](int a, int b) {\n            return seedScore[a] > seedScore[b];\n        });\n\n        groupA.push_back(rem[0]);\n\n        for (int idx = 1; idx < (int)rem.size(); idx++) {\n            int id = rem[idx];\n\n            if ((int)groupA.size() >= 18) {\n                groupB.push_back(id);\n                continue;\n            }\n            if ((int)groupB.size() >= 18) {\n                groupA.push_back(id);\n                continue;\n            }\n\n            double toA = 0, toB = 0;\n            for (int x : groupA) toB += P[id][x]; // putting id in B creates cross edges with A\n            for (int x : groupB) toA += P[id][x]; // putting id in A creates cross edges with B\n\n            // Prefer balanced and high cross complementarity.\n            if (toA > toB) groupA.push_back(id);\n            else groupB.push_back(id);\n        }\n\n        while ((int)groupA.size() < 18) {\n            groupA.push_back(groupB.back());\n            groupB.pop_back();\n        }\n        while ((int)groupB.size() < 18) {\n            groupB.push_back(groupA.back());\n            groupA.pop_back();\n        }\n\n        sort(groupA.begin(), groupA.end(), [&](int a, int b) {\n            return seedScore[a] > seedScore[b];\n        });\n        sort(groupB.begin(), groupB.end(), [&](int a, int b) {\n            return seedScore[a] > seedScore[b];\n        });\n\n        vector<int> posSeed(C, -1);\n        for (int i = 0; i < 18; i++) {\n            posSeed[blackCells[i]] = groupA[i];\n            posSeed[whiteCells[i]] = groupB[i];\n        }\n\n        auto edgeScoreAt = [&](int eid) -> double {\n            auto [u,v] = edges[eid];\n            return P[posSeed[u]][posSeed[v]];\n        };\n\n        double curScore = 0;\n        for (int e = 0; e < (int)edges.size(); e++) curScore += edgeScoreAt(e);\n\n        auto localContribution = [&](int a, int b) {\n            double s = 0;\n            static bool mark[64];\n            fill(mark, mark + C, false);\n            vector<int> es;\n            for (int e : incident[a]) es.push_back(e);\n            for (int e : incident[b]) es.push_back(e);\n            sort(es.begin(), es.end());\n            es.erase(unique(es.begin(), es.end()), es.end());\n            for (int e : es) s += edgeScoreAt(e);\n            return s;\n        };\n\n        int iterations = 65000;\n        for (int it = 0; it < iterations; it++) {\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > 1.88) break;\n\n            int a = rng.randint(C);\n            int b = rng.randint(C);\n            if (a == b) continue;\n\n            vector<int> es;\n            for (int e : incident[a]) es.push_back(e);\n            for (int e : incident[b]) es.push_back(e);\n            sort(es.begin(), es.end());\n            es.erase(unique(es.begin(), es.end()), es.end());\n\n            double before = 0;\n            for (int e : es) before += edgeScoreAt(e);\n\n            swap(posSeed[a], posSeed[b]);\n\n            double after = 0;\n            for (int e : es) after += edgeScoreAt(e);\n\n            double delta = after - before;\n\n            // Simulated annealing.\n            double progress = (double)it / iterations;\n            double temp = 70.0 * (1.0 - progress) + 2.0;\n            bool accept = false;\n            if (delta >= 0) accept = true;\n            else if (exp(delta / temp) > rng.rand01()) accept = true;\n\n            if (accept) {\n                curScore += delta;\n            } else {\n                swap(posSeed[a], posSeed[b]);\n            }\n        }\n\n        vector<vector<int>> A(N, vector<int>(N));\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                A[i][j] = posSeed[i * N + 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 << A[i][j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < S; i++) {\n            for (int j = 0; j < M; j++) cin >> X[i][j];\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\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    vector<Pos> src, dst;\n    vector<vector<int>> src_id(N, vector<int>(N, -1));\n    vector<vector<int>> dst_id(N, vector<int>(N, -1));\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] == '0') {\n                src_id[i][j] = (int)src.size();\n                src.push_back({i, j});\n            }\n            if (s[i][j] == '0' && t[i][j] == '1') {\n                dst_id[i][j] = (int)dst.size();\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    int K = (int)src.size();\n\n    // Star arm: root + up to V-1 fingertips, all length 1.\n    int F = max(1, V - 1);\n    int Vp = F + 1;\n\n    vector<int> finger_dir(F, 0); // 0:R, 1:D, 2:L, 3:U\n    vector<int> holding(F, -1);   // pair id held by finger, -1 if empty\n\n    const int dx[4] = {0, 1, 0, -1};\n    const int dy[4] = {1, 0, -1, 0};\n    const char mvchar[4] = {'R', 'D', 'L', 'U'};\n\n    auto inside = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    int root_x = 0, root_y = 0;\n    vector<string> ops;\n\n    auto add_op = [&](char mv, const vector<char>& rot, const vector<char>& act) {\n        string op(2 * Vp, '.');\n        op[0] = mv;\n\n        for (int f = 0; f < F; f++) {\n            op[1 + f] = rot[f];\n            op[Vp + 1 + f] = act[f];\n        }\n\n        // update root\n        if (mv == 'U') root_x--;\n        if (mv == 'D') root_x++;\n        if (mv == 'L') root_y--;\n        if (mv == 'R') root_y++;\n\n        // update dirs\n        for (int f = 0; f < F; f++) {\n            if (rot[f] == 'L') finger_dir[f] = (finger_dir[f] + 3) % 4;\n            if (rot[f] == 'R') finger_dir[f] = (finger_dir[f] + 1) % 4;\n        }\n\n        ops.push_back(op);\n    };\n\n    auto blank_rot = [&]() {\n        return vector<char>(F, '.');\n    };\n    auto blank_act = [&]() {\n        return vector<char>(F, '.');\n    };\n\n    auto move_root_to = [&](int tx, int ty) {\n        while (root_x < tx) add_op('D', blank_rot(), blank_act());\n        while (root_x > tx) add_op('U', blank_rot(), blank_act());\n        while (root_y < ty) add_op('R', blank_rot(), blank_act());\n        while (root_y > ty) add_op('L', blank_rot(), blank_act());\n    };\n\n    auto rotate_fingers_to = [&](const vector<int>& target_dir) {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            vector<char> rot(F, '.');\n            vector<char> act(F, '.');\n\n            for (int f = 0; f < F; f++) {\n                if (target_dir[f] < 0) continue;\n                if (finger_dir[f] == target_dir[f]) continue;\n\n                int diff = (target_dir[f] - finger_dir[f] + 4) % 4;\n                if (diff == 1 || diff == 2) {\n                    rot[f] = 'R';\n                    changed = true;\n                } else if (diff == 3) {\n                    rot[f] = 'L';\n                    changed = true;\n                }\n            }\n\n            if (changed) add_op('.', rot, act);\n        }\n    };\n\n    // Greedy pairing: each source to nearest unused destination.\n    vector<int> pair_dst(K, -1);\n    vector<int> used_dst(K, 0);\n    for (int i = 0; i < K; i++) {\n        int best = -1;\n        int best_dist = INT_MAX;\n        for (int j = 0; j < K; j++) {\n            if (used_dst[j]) continue;\n            int d = abs(src[i].x - dst[j].x) + abs(src[i].y - dst[j].y);\n            if (d < best_dist) {\n                best_dist = d;\n                best = j;\n            }\n        }\n        pair_dst[i] = best;\n        used_dst[best] = 1;\n    }\n\n    vector<int> done(K, 0);\n    int remaining = K;\n\n    auto possible_roots_for_cell = [&](Pos p) {\n        vector<pair<int, Pos>> res;\n        for (int d = 0; d < 4; d++) {\n            int rx = p.x - dx[d];\n            int ry = p.y - dy[d];\n            if (inside(rx, ry)) res.push_back({d, {rx, ry}});\n        }\n        return res;\n    };\n\n    auto choose_nearest_undone_source = [&]() {\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n            for (auto [d, r] : possible_roots_for_cell(src[i])) {\n                int cost = abs(root_x - r.x) + abs(root_y - r.y);\n                if (cost < best_cost) {\n                    best_cost = cost;\n                    best = i;\n                }\n            }\n        }\n        return best;\n    };\n\n    while (remaining > 0) {\n        int seed = choose_nearest_undone_source();\n        if (seed < 0) break;\n\n        /*\n            Pick phase.\n            Move root next to seed source, then also pick other sources adjacent\n            to the same root if fingers are available.\n        */\n        Pos seed_src = src[seed];\n\n        int best_d = -1;\n        Pos best_root{-1, -1};\n        int best_cost = INT_MAX;\n\n        for (auto [d, r] : possible_roots_for_cell(seed_src)) {\n            int c = abs(root_x - r.x) + abs(root_y - r.y);\n            if (c < best_cost) {\n                best_cost = c;\n                best_d = d;\n                best_root = r;\n            }\n        }\n\n        move_root_to(best_root.x, best_root.y);\n\n        vector<int> pick_pairs;\n        vector<int> pick_dirs;\n\n        // First seed.\n        pick_pairs.push_back(seed);\n        pick_dirs.push_back(best_d);\n\n        // Other adjacent undone sources.\n        for (int d = 0; d < 4 && (int)pick_pairs.size() < F; d++) {\n            int x = root_x + dx[d];\n            int y = root_y + dy[d];\n            if (!inside(x, y)) continue;\n            int id = src_id[x][y];\n            if (id < 0 || done[id]) continue;\n            if (id == seed) continue;\n            pick_pairs.push_back(id);\n            pick_dirs.push_back(d);\n        }\n\n        int cnt = (int)pick_pairs.size();\n\n        vector<int> target_dir(F, -1);\n        vector<int> assigned_finger(cnt, -1);\n        vector<int> used_finger(F, 0);\n\n        for (int k = 0; k < cnt; k++) {\n            int d = pick_dirs[k];\n            int best_f = -1;\n            int best_rot = INT_MAX;\n            for (int f = 0; f < F; f++) {\n                if (used_finger[f]) continue;\n                int diff = abs(finger_dir[f] - d);\n                int rc = min(diff, 4 - diff);\n                if (rc < best_rot) {\n                    best_rot = rc;\n                    best_f = f;\n                }\n            }\n            assigned_finger[k] = best_f;\n            used_finger[best_f] = 1;\n            target_dir[best_f] = d;\n        }\n\n        rotate_fingers_to(target_dir);\n\n        {\n            vector<char> rot = blank_rot();\n            vector<char> act = blank_act();\n            for (int k = 0; k < cnt; k++) {\n                int f = assigned_finger[k];\n                int pid = pick_pairs[k];\n                act[f] = 'P';\n                holding[f] = pid;\n                // Remove takoyaki from source occupancy.\n                s[src[pid].x][src[pid].y] = '0';\n            }\n            add_op('.', rot, act);\n        }\n\n        /*\n            Place phase.\n            We choose a destination root based on the first carried item.\n            Then place all carried items whose destinations are adjacent to this root.\n            If some carried items are not adjacent, place them one by one.\n        */\n        vector<int> carrying;\n        for (int f = 0; f < F; f++) {\n            if (holding[f] >= 0) carrying.push_back(f);\n        }\n\n        while (!carrying.empty()) {\n            int f0 = carrying[0];\n            int pid0 = holding[f0];\n            Pos dest0 = dst[pair_dst[pid0]];\n\n            int pd = -1;\n            Pos place_root{-1, -1};\n            int pcost = INT_MAX;\n\n            for (auto [d, r] : possible_roots_for_cell(dest0)) {\n                int c = abs(root_x - r.x) + abs(root_y - r.y);\n                if (c < pcost) {\n                    pcost = c;\n                    pd = d;\n                    place_root = r;\n                }\n            }\n\n            move_root_to(place_root.x, place_root.y);\n\n            vector<int> place_fingers;\n            vector<int> place_dirs;\n\n            for (int f : carrying) {\n                int pid = holding[f];\n                Pos q = dst[pair_dst[pid]];\n\n                for (int d = 0; d < 4; d++) {\n                    if (root_x + dx[d] == q.x && root_y + dy[d] == q.y) {\n                        place_fingers.push_back(f);\n                        place_dirs.push_back(d);\n                        break;\n                    }\n                }\n            }\n\n            vector<int> tdir(F, -1);\n            for (int i = 0; i < (int)place_fingers.size(); i++) {\n                tdir[place_fingers[i]] = place_dirs[i];\n            }\n\n            rotate_fingers_to(tdir);\n\n            {\n                vector<char> rot = blank_rot();\n                vector<char> act = blank_act();\n\n                for (int f : place_fingers) {\n                    int pid = holding[f];\n                    int did = pair_dst[pid];\n                    Pos q = dst[did];\n\n                    act[f] = 'P';\n                    holding[f] = -1;\n                    done[pid] = 1;\n                    remaining--;\n\n                    s[q.x][q.y] = '1';\n                }\n\n                add_op('.', rot, act);\n            }\n\n            carrying.clear();\n            for (int f = 0; f < F; f++) {\n                if (holding[f] >= 0) carrying.push_back(f);\n            }\n        }\n    }\n\n    // Output design.\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << 1 << '\\n';\n    }\n\n    // Initial root position was actually (0,0).\n    cout << 0 << ' ' << 0 << '\\n';\n\n    for (const string& op : ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n    bool operator==(const Pt& o) const { return x == o.x && y == o.y; }\n};\n\nstruct Fish {\n    int x, y, t;\n};\n\nstatic const int LIM = 100000;\nstatic const int NF = 5000;\n\nlong long perimeter_poly(const vector<Pt>& p) {\n    long long res = 0;\n    int m = (int)p.size();\n    for (int i = 0; i < m; i++) {\n        auto a = p[i], b = p[(i + 1) % m];\n        res += abs(a.x - b.x) + abs(a.y - b.y);\n    }\n    return res;\n}\n\nvector<Pt> simplify_poly(vector<Pt> p) {\n    if (p.empty()) return p;\n    vector<Pt> q;\n    for (auto v : p) {\n        if (q.empty() || !(q.back() == v)) q.push_back(v);\n    }\n    if (q.size() > 1 && q.front() == q.back()) q.pop_back();\n\n    bool changed = true;\n    while (changed && q.size() >= 4) {\n        changed = false;\n        vector<Pt> r;\n        int m = q.size();\n        r.reserve(m);\n        for (int i = 0; i < m; i++) {\n            Pt a = q[(i - 1 + m) % m], b = q[i], c = q[(i + 1) % m];\n            if ((a.x == b.x && b.x == c.x) || (a.y == b.y && b.y == c.y)) {\n                changed = true;\n            } else {\n                r.push_back(b);\n            }\n        }\n        q.swap(r);\n    }\n    return q;\n}\n\nbool inside_poly(const vector<Pt>& poly, int x, int y) {\n    bool in = false;\n    int m = poly.size();\n    for (int i = 0, j = m - 1; i < m; j = i++) {\n        Pt a = poly[j], b = poly[i];\n\n        if (a.x == b.x && x == a.x && min(a.y,b.y) <= y && y <= max(a.y,b.y)) return true;\n        if (a.y == b.y && y == a.y && min(a.x,b.x) <= x && x <= max(a.x,b.x)) return true;\n\n        if ((a.y > y) != (b.y > y)) {\n            long double xx = (long double)(b.x - a.x) * (y - a.y) / (long double)(b.y - a.y) + a.x;\n            if (xx >= x) in = !in;\n        }\n    }\n    return in;\n}\n\nint eval_exact(const vector<Pt>& poly, const vector<Fish>& fish) {\n    int s = 0;\n    for (auto &f : fish) {\n        if (inside_poly(poly, f.x, f.y)) s += f.t;\n    }\n    return s;\n}\n\nbool legal_basic(const vector<Pt>& p) {\n    if ((int)p.size() < 4 || (int)p.size() > 1000) return false;\n    if (perimeter_poly(p) > 400000) return false;\n    set<pair<int,int>> st;\n    for (auto &v : p) {\n        if (v.x < 0 || v.x > LIM || v.y < 0 || v.y > LIM) return false;\n        if (!st.insert({v.x, v.y}).second) return false;\n    }\n    for (int i = 0; i < (int)p.size(); i++) {\n        Pt a = p[i], b = p[(i + 1) % p.size()];\n        if (!(a.x == b.x || a.y == b.y)) return false;\n    }\n    return true;\n}\n\nstruct CandComp {\n    int score;\n    int per;\n    vector<pair<int,int>> cells;\n};\n\nvector<Pt> boundary_from_cells_fast(const vector<pair<int,int>>& cells, int G, int W, int H) {\n    vector<vector<unsigned char>> occ(W, vector<unsigned char>(H, 0));\n    for (auto [i,j] : cells) occ[i][j] = 1;\n\n    map<pair<int,int>, vector<pair<int,int>>> adj;\n\n    auto add = [&](int x1, int y1, int x2, int y2) {\n        adj[{x1,y1}].push_back({x2,y2});\n    };\n\n    for (auto [i,j] : cells) {\n        int x0 = i * G, x1 = min(LIM, (i + 1) * G);\n        int y0 = j * G, y1 = min(LIM, (j + 1) * G);\n\n        if (j == 0 || !occ[i][j - 1]) add(x0, y0, x1, y0);\n        if (i == W - 1 || !occ[i + 1][j]) add(x1, y0, x1, y1);\n        if (j == H - 1 || !occ[i][j + 1]) add(x1, y1, x0, y1);\n        if (i == 0 || !occ[i - 1][j]) add(x0, y1, x0, y0);\n    }\n\n    if (adj.empty()) return {};\n\n    pair<int,int> start = adj.begin()->first;\n    for (auto &kv : adj) {\n        if (kv.first.second < start.second ||\n            (kv.first.second == start.second && kv.first.first < start.first)) {\n            start = kv.first;\n        }\n    }\n\n    vector<Pt> poly;\n    pair<int,int> cur = start;\n    pair<int,int> prev = {-1,-1};\n\n    for (int iter = 0; iter < 10000; iter++) {\n        poly.push_back({cur.first, cur.second});\n        auto &v = adj[cur];\n        if (v.empty()) break;\n\n        pair<int,int> nxt = v[0];\n        if (v.size() >= 2 && v[0] == prev) nxt = v[1];\n\n        // erase chosen edge\n        for (int k = 0; k < (int)v.size(); k++) {\n            if (v[k] == nxt) {\n                v.erase(v.begin() + k);\n                break;\n            }\n        }\n\n        prev = cur;\n        cur = nxt;\n        if (cur == start) break;\n    }\n\n    return simplify_poly(poly);\n}\n\nvector<CandComp> find_components(const vector<vector<unsigned char>>& sel,\n                                const vector<vector<int>>& diff) {\n    int W = sel.size(), H = sel[0].size();\n    vector<vector<unsigned char>> vis(W, vector<unsigned char>(H, 0));\n    vector<CandComp> comps;\n    int dx[4] = {1,-1,0,0};\n    int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n        if (!sel[i][j] || vis[i][j]) continue;\n\n        CandComp cc;\n        cc.score = 0;\n        cc.per = 0;\n\n        queue<pair<int,int>> q;\n        q.push({i,j});\n        vis[i][j] = 1;\n\n        while (!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            cc.cells.push_back({x,y});\n            cc.score += diff[x][y];\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= W || ny < 0 || ny >= H || !sel[nx][ny]) {\n                    cc.per++;\n                } else if (!vis[nx][ny]) {\n                    vis[nx][ny] = 1;\n                    q.push({nx,ny});\n                }\n            }\n        }\n\n        comps.push_back(move(cc));\n    }\n\n    sort(comps.begin(), comps.end(), [](const CandComp& a, const CandComp& b) {\n        return a.score > b.score;\n    });\n    return comps;\n}\n\nvector<Pt> rect_poly(int x1, int y1, int x2, int y2) {\n    x1 = max(0, min(LIM, x1));\n    x2 = max(0, min(LIM, x2));\n    y1 = max(0, min(LIM, y1));\n    y2 = max(0, min(LIM, y2));\n    if (x1 > x2) swap(x1,x2);\n    if (y1 > y2) swap(y1,y2);\n    if (x1 == x2) x2 = min(LIM, x1 + 1);\n    if (y1 == y2) y2 = min(LIM, y1 + 1);\n    return {{x1,y1},{x2,y1},{x2,y2},{x1,y2}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    vector<Fish> fish;\n    fish.reserve(2 * n);\n\n    for (int i = 0; i < 2 * n; i++) {\n        int x, y;\n        cin >> x >> y;\n        fish.push_back({x, y, i < n ? 1 : -1});\n    }\n\n    vector<Pt> best = rect_poly(0, 0, 1, 1);\n    int bestScore = eval_exact(best, fish);\n\n    vector<int> gridSizes = {1000, 1500, 2000};\n    vector<double> thresholds = {-0.15, 0.0, 0.25, 0.5};\n\n    int exactEvalCount = 0;\n    const int MAX_EXACT_EVAL = 45;\n\n    for (int G : gridSizes) {\n        int W = (LIM + G) / G;\n        int H = (LIM + G) / G;\n\n        vector<vector<int>> diff(W, vector<int>(H, 0));\n        for (auto &f : fish) {\n            int ix = min(W - 1, f.x / G);\n            int iy = min(H - 1, f.y / G);\n            diff[ix][iy] += f.t;\n        }\n\n        vector<vector<double>> sm(W, vector<double>(H, 0.0));\n        for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n            double s = 0, w = 0;\n            for (int dx = -1; dx <= 1; dx++) for (int dy = -1; dy <= 1; dy++) {\n                int ni = i + dx, nj = j + dy;\n                if (ni < 0 || ni >= W || nj < 0 || nj >= H) continue;\n                double ww = (dx == 0 && dy == 0 ? 4.0 : (dx == 0 || dy == 0 ? 2.0 : 1.0));\n                s += ww * diff[ni][nj];\n                w += ww;\n            }\n            sm[i][j] = s / w;\n        }\n\n        for (double th : thresholds) {\n            vector<vector<unsigned char>> sel(W, vector<unsigned char>(H, 0));\n            for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n                if (sm[i][j] > th) sel[i][j] = 1;\n            }\n\n            auto comps = find_components(sel, diff);\n\n            int checked = 0;\n            for (auto &cc : comps) {\n                if (cc.score <= 0) break;\n                if (checked >= 6) break;\n                checked++;\n\n                long long approxPer = 1LL * cc.per * G;\n                if (approxPer > 400000) continue;\n                if ((int)cc.cells.size() > 2500) continue;\n\n                vector<Pt> poly = boundary_from_cells_fast(cc.cells, G, W, H);\n                poly = simplify_poly(poly);\n\n                if (!legal_basic(poly)) continue;\n\n                int approxUpper = cc.score + 30;\n                if (approxUpper < bestScore) continue;\n\n                int sc = eval_exact(poly, fish);\n                exactEvalCount++;\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    best = poly;\n                }\n\n                if (exactEvalCount >= MAX_EXACT_EVAL) break;\n            }\n\n            if (exactEvalCount >= MAX_EXACT_EVAL) break;\n        }\n\n        if (exactEvalCount >= MAX_EXACT_EVAL) break;\n    }\n\n    // Fast rectangle fallback using several fixed square sizes around mackerel-rich areas.\n    // Only few candidates are exactly evaluated.\n    vector<pair<int,int>> centers;\n    for (int G : {5000, 8000, 12000, 16000}) {\n        int W = (LIM + G) / G;\n        int H = (LIM + G) / G;\n        vector<vector<int>> d(W, vector<int>(H, 0));\n        for (auto &f : fish) {\n            d[min(W-1, f.x/G)][min(H-1, f.y/G)] += f.t;\n        }\n        vector<tuple<int,int,int>> cells;\n        for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n            cells.push_back({d[i][j], i, j});\n        }\n        sort(cells.rbegin(), cells.rend());\n        for (int k=0;k<min(8,(int)cells.size());k++) {\n            auto [v,i,j]=cells[k];\n            centers.push_back({min(LIM, i*G+G/2), min(LIM, j*G+G/2)});\n        }\n    }\n\n    int rectEval = 0;\n    for (auto [cx,cy] : centers) {\n        for (int sx : {6000,10000,15000,22000,30000,45000}) {\n            for (int sy : {6000,10000,15000,22000,30000,45000}) {\n                if (2LL*(sx+sy) > 400000) continue;\n                vector<Pt> p = rect_poly(cx-sx/2, cy-sy/2, cx+sx/2, cy+sy/2);\n                int sc = eval_exact(p, fish);\n                rectEval++;\n                if (sc > bestScore && legal_basic(p)) {\n                    bestScore = sc;\n                    best = p;\n                }\n                if (rectEval > 180) break;\n            }\n            if (rectEval > 180) break;\n        }\n        if (rectEval > 180) break;\n    }\n\n    best = simplify_poly(best);\n    if (!legal_basic(best)) best = rect_poly(0,0,1,1);\n\n    cout << best.size() << '\\n';\n    for (auto &p : best) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    long long w, h;\n};\n\nstruct Op {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Placed {\n    long long x1, y1, x2, y2;\n};\n\nstruct Cand {\n    long long score;\n    vector<Op> ops;\n};\n\nstatic inline bool overlap1d(long long l1, long long r1, long long l2, long long r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nlong long simulate_score(const vector<Op>& ops, const vector<Rect>& rects) {\n    int N = rects.size();\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n\n    long long W = 0, H = 0;\n\n    for (auto &op : ops) {\n        int i = op.p;\n        long long w = rects[i].w;\n        long long h = rects[i].h;\n        if (op.r) swap(w, h);\n\n        long long x = 0, y = 0;\n\n        if (op.d == 'U') {\n            if (op.b == -1) x = 0;\n            else x = pos[op.b].x2;\n\n            y = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(x, x + w, pos[j].x1, pos[j].x2)) {\n                    y = max(y, pos[j].y2);\n                }\n            }\n        } else {\n            if (op.b == -1) y = 0;\n            else y = pos[op.b].y2;\n\n            x = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(y, y + h, pos[j].y1, pos[j].y2)) {\n                    x = max(x, pos[j].x2);\n                }\n            }\n        }\n\n        pos[i] = {x, y, x + w, y + h};\n        used[i] = 1;\n        W = max(W, x + w);\n        H = max(H, y + h);\n    }\n\n    long long penalty = 0;\n    for (int i = 0; i < N; i++) if (!used[i]) {\n        penalty += rects[i].w + rects[i].h;\n    }\n\n    return W + H + penalty;\n}\n\nvector<int> make_rotation_policy(const vector<Rect>& a, int mode, int seed) {\n    int N = a.size();\n    vector<int> r(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        long long w = a[i].w, h = a[i].h;\n\n        if (mode == 0) {\n            r[i] = 0;\n        } else if (mode == 1) {\n            // make width <= height\n            r[i] = (w > h);\n        } else if (mode == 2) {\n            // make width >= height\n            r[i] = (w < h);\n        } else if (mode == 3) {\n            r[i] = ((i + seed) & 1);\n        } else if (mode == 4) {\n            r[i] = ((i / 2 + seed) & 1);\n        } else if (mode == 5) {\n            uint32_t x = (uint32_t)(i * 1103515245u + seed * 12345u + 998244353u);\n            r[i] = (x >> 30) & 1;\n        } else {\n            // rotate if it makes current orientation closer to square-ish average\n            r[i] = (abs((long long)w - (long long)h) > 0 && ((i + mode + seed) % 3 == 0));\n        }\n    }\n\n    return r;\n}\n\nvector<Op> make_vertical_shelves(const vector<Rect>& a, const vector<int>& r, long double targetH, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int last_col_first = -1;\n    int prev = -1;\n    long double curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newCol = false;\n\n        if (i == 0) {\n            newCol = true;\n        } else {\n            long double projected = curH + hh[i];\n\n            if (projected > targetH) {\n                long double before = fabsl(targetH - curH);\n                long double after = fabsl(targetH - projected);\n\n                if (variant == 0) {\n                    newCol = true;\n                } else if (variant == 1) {\n                    newCol = after > before * 0.85L;\n                } else if (variant == 2) {\n                    newCol = after > before * 0.65L;\n                } else {\n                    newCol = after > before;\n                }\n            }\n        }\n\n        if (newCol) {\n            if (last_col_first == -1) ops.push_back({i, r[i], 'U', -1});\n            else ops.push_back({i, r[i], 'U', last_col_first});\n            last_col_first = i;\n            curH = hh[i];\n        } else {\n            ops.push_back({i, r[i], 'L', prev});\n            curH += hh[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\nvector<Op> make_horizontal_shelves(const vector<Rect>& a, const vector<int>& r, long double targetW, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int first_row = -1;\n    int prev = -1;\n    long double curW = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newRow = false;\n\n        if (i == 0) {\n            newRow = true;\n        } else {\n            long double projected = curW + ww[i];\n\n            if (projected > targetW) {\n                long double before = fabsl(targetW - curW);\n                long double after = fabsl(targetW - projected);\n\n                if (variant == 0) {\n                    newRow = true;\n                } else if (variant == 1) {\n                    newRow = after > before * 0.85L;\n                } else if (variant == 2) {\n                    newRow = after > before * 0.65L;\n                } else {\n                    newRow = after > before;\n                }\n            }\n        }\n\n        if (newRow) {\n            if (first_row == -1) ops.push_back({i, r[i], 'L', -1});\n            else ops.push_back({i, r[i], 'L', first_row});\n            first_row = i;\n            curW = ww[i];\n        } else {\n            ops.push_back({i, r[i], 'U', prev});\n            curW += ww[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\n// A skyline-like greedy: for each rectangle, choose among legal references the placement\n// that minimizes current predicted W+H.\n// This is stronger than plain shelves, while respecting increasing index order.\nvector<Op> make_greedy_anchor_layout(const vector<Rect>& a, const vector<int>& r, int beam_mode) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long long bestVal = LLONG_MAX;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n        for (int b = 0; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            long long x = 0, y = 0;\n\n            if (d == 'U') {\n                x = (b == -1 ? 0 : pos[b].x2);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(x, x + wi, pos[j].x1, pos[j].x2)) {\n                        y = max(y, pos[j].y2);\n                    }\n                }\n            } else {\n                y = (b == -1 ? 0 : pos[b].y2);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(y, y + hi, pos[j].y1, pos[j].y2)) {\n                        x = max(x, pos[j].x2);\n                    }\n                }\n            }\n\n            long long nW = max(curW, x + wi);\n            long long nH = max(curH, y + hi);\n\n            long long val;\n            if (beam_mode == 0) {\n                val = nW + nH;\n            } else if (beam_mode == 1) {\n                val = nW + nH + llabs(nW - nH) / 4;\n            } else if (beam_mode == 2) {\n                val = max(nW, nH) * 2 + min(nW, nH);\n            } else {\n                val = nW + nH + (long long)(0.000001L * (long double)nW * (long double)nH);\n            }\n\n            // small deterministic tie-breaker preferring compact lower-left\n            val = val * 1000000LL + x + y;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = {x, y, x + wi, y + hi};\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\n// Variant: split into blocks, and inside each block use greedy anchors.\n// New block is biased to start from axes / previous block.\nvector<Op> make_mixed_layout(const vector<Rect>& a, const vector<int>& r, int blockSize, int mode) {\n    int N = a.size();\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long long bestVal = LLONG_MAX;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n\n        int start = max(0, i - blockSize);\n        for (int b = start; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        // also try some older structural anchors\n        for (int b = 0; b < i; b += max(1, blockSize / 2)) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            long long x = 0, y = 0;\n\n            if (d == 'U') {\n                x = (b == -1 ? 0 : pos[b].x2);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(x, x + wi, pos[j].x1, pos[j].x2)) {\n                        y = max(y, pos[j].y2);\n                    }\n                }\n            } else {\n                y = (b == -1 ? 0 : pos[b].y2);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(y, y + hi, pos[j].y1, pos[j].y2)) {\n                        x = max(x, pos[j].x2);\n                    }\n                }\n            }\n\n            long long nW = max(curW, x + wi);\n            long long nH = max(curH, y + hi);\n\n            long long val;\n            if (mode == 0) {\n                val = nW + nH;\n            } else if (mode == 1) {\n                val = nW + nH + llabs(nW - nH) / 3;\n            } else {\n                val = max(nW, nH) * 2 + min(nW, nH);\n            }\n\n            val = val * 1000000LL + x + y;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = {x, y, x + wi, y + hi};\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n\n    vector<Rect> a(N);\n    for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n    long double area = 0;\n    for (auto &e : a) area += (long double)e.w * (long double)e.h;\n    long double root = sqrt(area);\n\n    vector<Cand> cands;\n    cands.reserve(5000);\n\n    auto add_candidate = [&](const vector<Op>& ops) {\n        long long sc = simulate_score(ops, a);\n        cands.push_back({sc, ops});\n    };\n\n    // Shelf candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 8; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n\n            for (int k = 0; k < 45; k++) {\n                long double factor = 0.45L + 0.035L * k;\n                for (int var = 0; var < 4; var++) {\n                    add_candidate(make_vertical_shelves(a, r, root * factor, var));\n                    add_candidate(make_horizontal_shelves(a, r, root * factor, var));\n                }\n            }\n        }\n    }\n\n    // Greedy anchor candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 12; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bm = 0; bm < 4; bm++) {\n                add_candidate(make_greedy_anchor_layout(a, r, bm));\n            }\n        }\n    }\n\n    // Mixed restricted-anchor candidates.\n    vector<int> blockSizes = {4, 6, 8, 10, 12, 15, 20, 30};\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 6; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bs : blockSizes) {\n                for (int bm = 0; bm < 3; bm++) {\n                    add_candidate(make_mixed_layout(a, r, bs, bm));\n                }\n            }\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& x, const Cand& y) {\n        return x.score < y.score;\n    });\n\n    // Remove exact duplicate operation sequences among top candidates.\n    vector<Cand> uniq;\n    uniq.reserve(cands.size());\n\n    auto signature = [](const vector<Op>& ops) {\n        string s;\n        s.reserve(ops.size() * 8);\n        for (auto &op : ops) {\n            s += char(op.r + '0');\n            s += op.d;\n            s += char((op.b + 2) % 251);\n            s += ',';\n        }\n        return s;\n    };\n\n    unordered_set<string> seen;\n    for (auto &c : cands) {\n        string sig = signature(c.ops);\n        if (seen.insert(sig).second) {\n            uniq.push_back(std::move(c));\n            if ((int)uniq.size() >= max(T * 3, 300)) break;\n        }\n    }\n\n    if (uniq.empty()) {\n        vector<int> r(N, 0);\n        add_candidate(make_vertical_shelves(a, r, root, 0));\n        uniq = cands;\n    }\n\n    // Query best predicted candidates.\n    // If T is larger than available unique candidates, cycle through them.\n    long long bestObserved = LLONG_MAX;\n\n    for (int t = 0; t < T; t++) {\n        const vector<Op>& ops = uniq[t % uniq.size()].ops;\n\n        cout << ops.size() << '\\n';\n        for (auto &op : ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        if (!cin) return 0;\n\n        bestObserved = min(bestObserved, Wp + Hp);\n    }\n\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 1000;\nstatic constexpr int H = 10;\n\nstruct Solver {\n    int n, m, h;\n    vector<int> A;\n    vector<vector<int>> g;\n    vector<pair<int,int>> xy;\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n    double TL = 1.90;\n\n    Solver() : rng(71236721) {}\n\n    double elapsed() {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    long long calcScore(const vector<int>& par) {\n        vector<vector<int>> ch(n);\n        vector<int> roots;\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -1) roots.push_back(v);\n            else ch[par[v]].push_back(v);\n        }\n        long long score = 1;\n        vector<int> dep(n, -1);\n        queue<int> q;\n        for (int r : roots) {\n            dep[r] = 0;\n            q.push(r);\n        }\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            score += 1LL * (dep[v] + 1) * A[v];\n            for (int to : ch[v]) {\n                dep[to] = dep[v] + 1;\n                q.push(to);\n            }\n        }\n        return score;\n    }\n\n    vector<int> allDistancesFrom(int s) {\n        vector<int> d(n, 1e9);\n        queue<int> q;\n        d[s] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (d[v] == H) continue;\n            for (int to : g[v]) {\n                if (d[to] > d[v] + 1) {\n                    d[to] = d[v] + 1;\n                    q.push(to);\n                }\n            }\n        }\n        return d;\n    }\n\n    vector<int> construct(double lowBias, double noise, bool randomOrder) {\n        vector<char> covered(n, 0), isRoot(n, 0);\n        vector<int> roots;\n        int coveredCnt = 0;\n\n        vector<vector<int>> reach(n);\n        for (int s = 0; s < n; s++) {\n            vector<int> d(n, -1);\n            queue<int> q;\n            d[s] = 0;\n            q.push(s);\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                reach[s].push_back(v);\n                if (d[v] == H) continue;\n                for (int to : g[v]) {\n                    if (d[to] == -1) {\n                        d[to] = d[v] + 1;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        while (coveredCnt < n) {\n            int best = -1;\n            double bestVal = -1e100;\n            vector<int> cand(n);\n            iota(cand.begin(), cand.end(), 0);\n            if (randomOrder) shuffle(cand.begin(), cand.end(), rng);\n\n            for (int v : cand) {\n                if (isRoot[v]) continue;\n                int gain = 0;\n                int gainW = 0;\n                for (int u : reach[v]) {\n                    if (!covered[u]) {\n                        gain++;\n                        gainW += A[u];\n                    }\n                }\n                if (gain == 0) continue;\n                double rnoise = noise * uniform_real_distribution<double>(-1.0, 1.0)(rng);\n                double val = gain * 1000.0 - lowBias * A[v] + 0.05 * gainW + rnoise;\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = v;\n                }\n            }\n\n            if (best == -1) {\n                for (int v = 0; v < n; v++) if (!covered[v]) {\n                    best = v;\n                    break;\n                }\n            }\n\n            roots.push_back(best);\n            isRoot[best] = 1;\n            for (int u : reach[best]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        vector<int> dist(n, 1e9), par(n, -2), owner(n, -1);\n        struct Node {\n            double key;\n            int v;\n            bool operator<(const Node& o) const { return key > o.key; }\n        };\n        priority_queue<Node> pq;\n\n        for (int r : roots) {\n            dist[r] = 0;\n            par[r] = -1;\n            owner[r] = r;\n            double key = 0.0 + 0.002 * A[r];\n            pq.push({key, r});\n        }\n\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int v = cur.v;\n            if (cur.key > dist[v] + 1000) {}\n            if (dist[v] == H) continue;\n\n            vector<int> ns = g[v];\n            shuffle(ns.begin(), ns.end(), rng);\n            for (int to : ns) {\n                if (dist[to] == 1e9) {\n                    dist[to] = dist[v] + 1;\n                    par[to] = v;\n                    owner[to] = owner[v];\n                    double key = dist[to] + 0.012 * (100 - A[to])\n                               + uniform_real_distribution<double>(0.0, 0.02)(rng);\n                    pq.push({key, to});\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) {\n                par[v] = -1;\n            }\n        }\n        return par;\n    }\n\n    vector<int> rerootTrees(const vector<int>& par0) {\n        vector<int> par = par0;\n        vector<vector<int>> treeAdj(n);\n        for (int v = 0; v < n; v++) {\n            if (par[v] != -1) {\n                treeAdj[v].push_back(par[v]);\n                treeAdj[par[v]].push_back(v);\n            }\n        }\n\n        vector<int> compId(n, -1);\n        vector<vector<int>> comps;\n        for (int s = 0; s < n; s++) if (compId[s] == -1) {\n            int id = comps.size();\n            comps.push_back({});\n            queue<int> q;\n            q.push(s);\n            compId[s] = id;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                comps.back().push_back(v);\n                for (int to : treeAdj[v]) {\n                    if (compId[to] == -1) {\n                        compId[to] = id;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        vector<int> newPar(n, -2);\n\n        for (auto &comp : comps) {\n            int bestRoot = comp[0];\n            long long bestVal = LLONG_MIN;\n            vector<int> bestDist;\n\n            for (int r : comp) {\n                unordered_map<int,int> dummy;\n                vector<int> d(n, -1);\n                queue<int> q;\n                d[r] = 0;\n                q.push(r);\n                int mx = 0;\n                long long val = 0;\n                while (!q.empty()) {\n                    int v = q.front(); q.pop();\n                    mx = max(mx, d[v]);\n                    val += 1LL * (d[v] + 1) * A[v];\n                    for (int to : treeAdj[v]) {\n                        if (d[to] == -1) {\n                            d[to] = d[v] + 1;\n                            q.push(to);\n                        }\n                    }\n                }\n                if (mx <= H && val > bestVal) {\n                    bestVal = val;\n                    bestRoot = r;\n                    bestDist.swap(d);\n                }\n            }\n\n            queue<int> q;\n            vector<int> seen(n, 0);\n            newPar[bestRoot] = -1;\n            seen[bestRoot] = 1;\n            q.push(bestRoot);\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                for (int to : treeAdj[v]) {\n                    if (!seen[to]) {\n                        seen[to] = 1;\n                        newPar[to] = v;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (newPar[v] == -2) newPar[v] = -1;\n        }\n        return newPar;\n    }\n\n    void solve() {\n        cin >> n >> m >> h;\n        A.resize(n);\n        for (int i = 0; i < n; i++) cin >> A[i];\n        g.assign(n, {});\n        for (int i = 0; i < m; i++) {\n            int u, v;\n            cin >> u >> v;\n            g[u].push_back(v);\n            g[v].push_back(u);\n        }\n        xy.resize(n);\n        for (int i = 0; i < n; i++) cin >> xy[i].first >> xy[i].second;\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestPar(n, -1);\n        long long bestScore = -1;\n\n        int iter = 0;\n        while (elapsed() < TL) {\n            double lowBias = 5.0 + (iter % 10) * 8.0;\n            double noise = 100.0 + (iter % 7) * 300.0;\n            bool ro = (iter % 2);\n\n            vector<int> par = construct(lowBias, noise, ro);\n            par = rerootTrees(par);\n            long long sc = calcScore(par);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPar = par;\n            }\n            iter++;\n        }\n\n        for (int i = 0; i < n; i++) {\n            if (i) cout << ' ';\n            cout << bestPar[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc042":"#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    cin >> N;\n    vector<string> board(N);\n    for (int i = 0; i < N; i++) cin >> board[i];\n\n    vector<pair<char,int>> ans;\n\n    auto oni_count = [&]() {\n        int c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (board[i][j] == 'x') c++;\n            }\n        }\n        return c;\n    };\n\n    while (oni_count() > 0) {\n        struct Cand {\n            int cost;\n            int removed;\n            char dir;\n            int p;\n            int k;\n            vector<pair<int,int>> cells;\n        };\n\n        Cand best;\n        best.cost = 1e9;\n        best.removed = -1;\n\n        auto update = [&](Cand c) {\n            if (c.removed <= 0) return;\n\n            // Prefer better efficiency, then fewer moves.\n            long long lhs = 1LL * c.removed * best.cost;\n            long long rhs = 1LL * best.removed * c.cost;\n\n            if (best.removed == -1 || lhs > rhs ||\n                (lhs == rhs && c.cost < best.cost) ||\n                (lhs == rhs && c.cost == best.cost && c.removed > best.removed)) {\n                best = c;\n            }\n        };\n\n        // Upward cycles.\n        for (int j = 0; j < N; j++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int i = 0; i < N; i++) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (i + 1);\n                    c.removed = removed;\n                    c.dir = 'U';\n                    c.p = j;\n                    c.k = i + 1;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // Downward cycles.\n        for (int j = 0; j < N; j++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int i = N - 1; i >= 0; i--) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (N - i);\n                    c.removed = removed;\n                    c.dir = 'D';\n                    c.p = j;\n                    c.k = N - i;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // Left cycles.\n        for (int i = 0; i < N; i++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int j = 0; j < N; j++) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (j + 1);\n                    c.removed = removed;\n                    c.dir = 'L';\n                    c.p = i;\n                    c.k = j + 1;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // Right cycles.\n        for (int i = 0; i < N; i++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n            for (int j = N - 1; j >= 0; j--) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Cand c;\n                    c.cost = 2 * (N - j);\n                    c.removed = removed;\n                    c.dir = 'R';\n                    c.p = i;\n                    c.k = N - j;\n                    c.cells = cells;\n                    update(c);\n                }\n            }\n        }\n\n        // The input guarantee ensures this should never fail.\n        if (best.removed <= 0) break;\n\n        for (auto [i, j] : best.cells) {\n            if (board[i][j] == 'x') board[i][j] = '.';\n        }\n\n        char rev;\n        if (best.dir == 'U') rev = 'D';\n        else if (best.dir == 'D') rev = 'U';\n        else if (best.dir == 'L') rev = 'R';\n        else rev = 'L';\n\n        for (int t = 0; t < best.k; t++) ans.push_back({best.dir, best.p});\n        for (int t = 0; t < best.k; t++) ans.push_back({rev, best.p});\n    }\n\n    // Guaranteed by the simple construction: at most 40 Oni * 40 moves = 1600.\n    // Still, avoid illegal output just in case.\n    if ((int)ans.size() > 4 * N * N) {\n        ans.resize(4 * N * N);\n    }\n\n    for (auto [d, p] : ans) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 100;\nstatic const int L = 500000;\n\nstruct Plan {\n    int a[N], b[N];\n};\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 88172645463325252ull) : x(seed) {}\n\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint eval_plan(const Plan& p, const vector<int>& T) {\n    static int cnt[N];\n    for (int i = 0; i < N; i++) cnt[i] = 0;\n\n    int x = 0;\n    for (int week = 0; week < L; week++) {\n        cnt[x]++;\n        if (cnt[x] & 1) x = p.a[x];\n        else x = p.b[x];\n    }\n\n    int err = 0;\n    for (int i = 0; i < N; i++) {\n        err += abs(cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint sample_weighted(const vector<int>& pref, RNG& rng) {\n    int v = rng.next_int(1, L);\n    int id = lower_bound(pref.begin(), pref.end(), v) - pref.begin();\n    if (id >= N) id = N - 1;\n    return id;\n}\n\nPlan random_plan(const vector<int>& pref, RNG& rng) {\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        p.a[i] = sample_weighted(pref, rng);\n        p.b[i] = sample_weighted(pref, rng);\n    }\n    return p;\n}\n\nPlan weighted_balance_plan(const vector<int>& T, RNG& rng, double noise) {\n    struct Item {\n        int src;\n        double w;\n        double key;\n    };\n\n    vector<Item> items;\n    items.reserve(200);\n\n    for (int i = 0; i < N; i++) {\n        double w = T[i] * 0.5;\n        items.push_back({i, w, w * (1.0 + noise * (rng.next_double() - 0.5))});\n        items.push_back({i, w, w * (1.0 + noise * (rng.next_double() - 0.5))});\n    }\n\n    sort(items.begin(), items.end(), [](const Item& x, const Item& y) {\n        return x.key > y.key;\n    });\n\n    vector<double> load(N, 0.0);\n    vector<vector<int>> to_src(N);\n\n    vector<pair<int, int>> assigned;\n    assigned.reserve(200);\n\n    for (const auto& it : items) {\n        int best = 0;\n        double best_score = -1e100;\n\n        for (int j = 0; j < N; j++) {\n            double rem = T[j] - load[j];\n\n            double score = rem;\n\n            score += noise * 2000.0 * (rng.next_double() - 0.5);\n\n            if (score > best_score) {\n                best_score = score;\n                best = j;\n            }\n        }\n\n        load[best] += it.w;\n        assigned.push_back({it.src, best});\n    }\n\n    vector<int> outs[N];\n    for (auto [s, d] : assigned) {\n        outs[s].push_back(d);\n    }\n\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        while ((int)outs[i].size() < 2) {\n            outs[i].push_back(rng.next_int(0, N - 1));\n        }\n\n        if (rng.next_int(0, 1)) swap(outs[i][0], outs[i][1]);\n\n        p.a[i] = outs[i][0];\n        p.b[i] = outs[i][1];\n    }\n\n    return p;\n}\n\nPlan quota_plan(const vector<int>& T, RNG& rng) {\n    vector<double> rem(N);\n    vector<int> q(N, 0);\n\n    int sumq = 0;\n    for (int i = 0; i < N; i++) {\n        double exact = 200.0 * T[i] / L;\n        q[i] = (int)floor(exact);\n        rem[i] = exact - q[i];\n        sumq += q[i];\n    }\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        return rem[x] > rem[y];\n    });\n\n    for (int k = 0; sumq < 200; k++, sumq++) {\n        q[ord[k % N]]++;\n    }\n\n    vector<int> edges;\n    edges.reserve(200);\n    for (int i = 0; i < N; i++) {\n        for (int c = 0; c < q[i]; c++) edges.push_back(i);\n    }\n\n    while ((int)edges.size() < 200) {\n        edges.push_back(rng.next_int(0, N - 1));\n    }\n\n    shuffle(edges.begin(), edges.end(), mt19937((uint32_t)rng.next_u64()));\n\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        p.a[i] = edges[2 * i];\n        p.b[i] = edges[2 * i + 1];\n    }\n    return p;\n}\n\nPlan mutate_plan(const Plan& base, const vector<int>& pref, RNG& rng, int changes) {\n    Plan p = base;\n    for (int k = 0; k < changes; k++) {\n        int i = rng.next_int(0, N - 1);\n        int side = rng.next_int(0, 1);\n        int to = sample_weighted(pref, rng);\n        if (side == 0) p.a[i] = to;\n        else p.b[i] = to;\n    }\n    return p;\n}\n\nPlan swap_mutate_plan(const Plan& base, RNG& rng, int changes) {\n    Plan p = base;\n\n    for (int k = 0; k < changes; k++) {\n        int i1 = rng.next_int(0, N - 1);\n        int i2 = rng.next_int(0, N - 1);\n        int s1 = rng.next_int(0, 1);\n        int s2 = rng.next_int(0, 1);\n\n        int* e1 = (s1 == 0 ? &p.a[i1] : &p.b[i1]);\n        int* e2 = (s2 == 0 ? &p.a[i2] : &p.b[i2]);\n\n        swap(*e1, *e2);\n    }\n\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n\n    vector<int> T(N);\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    vector<int> pref(N);\n    for (int i = 0; i < N; i++) {\n        pref[i] = T[i] + (i ? pref[i - 1] : 0);\n    }\n\n    RNG rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    Plan best;\n    for (int i = 0; i < N; i++) {\n        best.a[i] = best.b[i] = 0;\n    }\n\n    int best_err = eval_plan(best, T);\n\n    auto start = chrono::steady_clock::now();\n\n    int iter = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 1.88) break;\n\n        Plan cand;\n\n        int mode = iter % 10;\n\n        if (mode <= 5) {\n            double noise;\n            if (mode == 0) noise = 0.00;\n            else if (mode == 1) noise = 0.05;\n            else if (mode == 2) noise = 0.10;\n            else if (mode == 3) noise = 0.20;\n            else if (mode == 4) noise = 0.35;\n            else noise = 0.60;\n\n            cand = weighted_balance_plan(T, rng, noise);\n        } else if (mode == 6) {\n            cand = quota_plan(T, rng);\n        } else if (mode == 7) {\n            cand = random_plan(pref, rng);\n        } else if (mode == 8) {\n            int changes = 1 + rng.next_int(0, 3);\n            cand = mutate_plan(best, pref, rng, changes);\n        } else {\n            int changes = 1 + rng.next_int(0, 5);\n            cand = swap_mutate_plan(best, rng, changes);\n        }\n\n        int err = eval_plan(cand, T);\n\n        if (err < best_err) {\n            best_err = err;\n            best = cand;\n        }\n\n        iter++;\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    bool operator<(const Edge& o) const {\n        if (w != o.w) return w < o.w;\n        if (u != o.u) return u < o.u;\n        return v < o.v;\n    }\n};\n\nstatic uint64_t rng_state = 88172645463325252ull;\nuint64_t xorshift64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\nint rnd_int(int l, int r) {\n    return l + (int)(xorshift64() % (uint64_t)(r - l + 1));\n}\ndouble rnd_double() {\n    return (xorshift64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<double> x(N), y(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        x[i] = (lx[i] + rx[i]) * 0.5;\n        y[i] = (ly[i] + ry[i]) * 0.5;\n    }\n\n    auto distApproxD = [&](int a, int b) -> double {\n        double dx = x[a] - x[b];\n        double dy = y[a] - y[b];\n        return sqrt(dx * dx + dy * dy);\n    };\n    auto distApprox = [&](int a, int b) -> long long {\n        return (long long)distApproxD(a, b);\n    };\n    auto dist2 = [&](int a, int b) -> double {\n        double dx = x[a] - x[b];\n        double dy = y[a] - y[b];\n        return dx * dx + dy * dy;\n    };\n\n    // Approximate MST cost of one group using complete graph.\n    // Groups are usually small on average; for large groups this is still okay for N=800.\n    auto approxMSTCost = [&](const vector<int>& v) -> double {\n        int s = (int)v.size();\n        if (s <= 1) return 0.0;\n        vector<double> mn(s, 1e100);\n        vector<char> used(s, 0);\n        mn[0] = 0;\n        double cost = 0;\n        for (int it = 0; it < s; it++) {\n            int best = -1;\n            for (int i = 0; i < s; i++) {\n                if (!used[i] && (best == -1 || mn[i] < mn[best])) best = i;\n            }\n            used[best] = 1;\n            cost += mn[best];\n            for (int j = 0; j < s; j++) if (!used[j]) {\n                double d = distApproxD(v[best], v[j]);\n                if (d < mn[j]) mn[j] = d;\n            }\n        }\n        return cost;\n    };\n\n    vector<int> sortedGroupIds(M);\n    iota(sortedGroupIds.begin(), sortedGroupIds.end(), 0);\n\n    // A recursive geometric partitioning.\n    function<void(vector<int>&, vector<int>&, vector<vector<int>>&, int)> recBuild =\n        [&](vector<int>& pts, vector<int>& gids, vector<vector<int>>& groups, int depth) {\n            if (gids.empty()) return;\n            if ((int)gids.size() == 1) {\n                groups[gids[0]] = pts;\n                return;\n            }\n\n            double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n            for (int p : pts) {\n                minx = min(minx, x[p]);\n                maxx = max(maxx, x[p]);\n                miny = min(miny, y[p]);\n                maxy = max(maxy, y[p]);\n            }\n\n            int total = pts.size();\n            int halfTarget = total / 2;\n\n            // Choose a prefix of group sizes whose sum is close to half.\n            vector<int> order = gids;\n\n            // Randomize group order a bit. Large groups first tends to reduce fragmentation.\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                return G[a] > G[b];\n            });\n            if (depth % 2 == 1) {\n                for (int i = 0; i + 1 < (int)order.size(); i += 2) {\n                    if (rnd_double() < 0.35) swap(order[i], order[i + 1]);\n                }\n            }\n\n            vector<int> leftG, rightG;\n            int sumL = 0;\n            for (int id : order) {\n                if (sumL < halfTarget) {\n                    leftG.push_back(id);\n                    sumL += G[id];\n                } else {\n                    rightG.push_back(id);\n                }\n            }\n\n            // Local correction: try moving one group to improve balance.\n            bool changed = true;\n            while (changed) {\n                changed = false;\n                int curDiff = abs(sumL - (total - sumL));\n                for (int i = 0; i < (int)leftG.size(); i++) {\n                    int ns = sumL - G[leftG[i]];\n                    int nd = abs(ns - (total - ns));\n                    if (!leftG.empty() && !rightG.empty() && nd < curDiff) {\n                        rightG.push_back(leftG[i]);\n                        leftG.erase(leftG.begin() + i);\n                        sumL = ns;\n                        changed = true;\n                        break;\n                    }\n                }\n                if (changed) continue;\n                for (int i = 0; i < (int)rightG.size(); i++) {\n                    int ns = sumL + G[rightG[i]];\n                    int nd = abs(ns - (total - ns));\n                    if (nd < curDiff) {\n                        leftG.push_back(rightG[i]);\n                        rightG.erase(rightG.begin() + i);\n                        sumL = ns;\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n\n            if (leftG.empty() || rightG.empty()) {\n                leftG.clear();\n                rightG.clear();\n                sumL = 0;\n                for (int i = 0; i < (int)order.size(); i++) {\n                    if (i < (int)order.size() / 2) {\n                        leftG.push_back(order[i]);\n                        sumL += G[order[i]];\n                    } else {\n                        rightG.push_back(order[i]);\n                    }\n                }\n            }\n\n            bool splitX;\n            double sx = maxx - minx;\n            double sy = maxy - miny;\n            if (fabs(sx - sy) < 1e-9) splitX = rnd_int(0, 1);\n            else splitX = sx > sy;\n\n            // Randomly flip axis sometimes to produce alternative partitions.\n            if (rnd_double() < 0.12) splitX = !splitX;\n\n            sort(pts.begin(), pts.end(), [&](int a, int b) {\n                double va = splitX ? x[a] : y[a];\n                double vb = splitX ? x[b] : y[b];\n                if (va != vb) return va < vb;\n                return (splitX ? y[a] : x[a]) < (splitX ? y[b] : x[b]);\n            });\n\n            vector<int> leftPts(pts.begin(), pts.begin() + sumL);\n            vector<int> rightPts(pts.begin() + sumL, pts.end());\n\n            recBuild(leftPts, leftG, groups, depth + 1);\n            recBuild(rightPts, rightG, groups, depth + 1);\n        };\n\n    auto buildMorton = [&]() {\n        vector<vector<int>> groups(M);\n        vector<int> cities(N);\n        iota(cities.begin(), cities.end(), 0);\n\n        auto morton_key = [&](int i) -> long long {\n            int xi = max(0, min(10000, (int)x[i]));\n            int yi = max(0, min(10000, (int)y[i]));\n            long long key = 0;\n            for (int b = 0; b < 14; b++) {\n                key |= ((long long)((xi >> b) & 1)) << (2 * b);\n                key |= ((long long)((yi >> b) & 1)) << (2 * b + 1);\n            }\n            return key;\n        };\n\n        sort(cities.begin(), cities.end(), [&](int a, int b) {\n            long long ka = morton_key(a), kb = morton_key(b);\n            if (ka != kb) return ka < kb;\n            return x[a] < x[b];\n        });\n\n        int ptr = 0;\n        for (int k = 0; k < M; k++) {\n            groups[k].assign(cities.begin() + ptr, cities.begin() + ptr + G[k]);\n            ptr += G[k];\n        }\n        return groups;\n    };\n\n    auto scoreGroups = [&](const vector<vector<int>>& groups) -> double {\n        double s = 0;\n        for (int k = 0; k < M; k++) {\n            const auto& v = groups[k];\n            int n = v.size();\n            if (n <= 1) continue;\n\n            // For speed in repeated attempts, use compactness + small MST approximation.\n            if (n <= 35) {\n                s += approxMSTCost(v);\n            } else {\n                double cx = 0, cy = 0;\n                for (int p : v) {\n                    cx += x[p];\n                    cy += y[p];\n                }\n                cx /= n;\n                cy /= n;\n                vector<double> ds;\n                ds.reserve(n);\n                for (int p : v) {\n                    double dx = x[p] - cx;\n                    double dy = y[p] - cy;\n                    ds.push_back(sqrt(dx * dx + dy * dy));\n                }\n                sort(ds.begin(), ds.end());\n                double val = 0;\n                for (int i = 0; i < n; i++) val += ds[i];\n                s += val * 0.42;\n            }\n        }\n        return s;\n    };\n\n    vector<vector<int>> bestGroups = buildMorton();\n    double bestScore = scoreGroups(bestGroups);\n\n    // Multiple recursive partition attempts.\n    int attempts = 70;\n    if (M <= 20) attempts = 120;\n    if (M >= 200) attempts = 35;\n\n    for (int at = 0; at < attempts && timer.sec() < 0.85; at++) {\n        vector<vector<int>> groups(M);\n        vector<int> pts(N), gids(M);\n        iota(pts.begin(), pts.end(), 0);\n        iota(gids.begin(), gids.end(), 0);\n\n        // Randomize group IDs before recursive bisection.\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n        for (int i = 0; i + 1 < M; i++) {\n            if (rnd_double() < 0.20) swap(gids[i], gids[rnd_int(i, M - 1)]);\n        }\n\n        recBuild(pts, gids, groups, 0);\n\n        // Sort each group along local principal-ish axis.\n        for (int k = 0; k < M; k++) {\n            double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n            for (int p : groups[k]) {\n                minx = min(minx, x[p]);\n                maxx = max(maxx, x[p]);\n                miny = min(miny, y[p]);\n                maxy = max(maxy, y[p]);\n            }\n            bool sx = (maxx - minx) >= (maxy - miny);\n            sort(groups[k].begin(), groups[k].end(), [&](int a, int b) {\n                double va = sx ? x[a] : y[a];\n                double vb = sx ? x[b] : y[b];\n                if (va != vb) return va < vb;\n                return (sx ? y[a] : x[a]) < (sx ? y[b] : x[b]);\n            });\n        }\n\n        double sc = scoreGroups(groups);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestGroups = groups;\n        }\n    }\n\n    vector<vector<int>> groups = bestGroups;\n\n    // A small boundary local improvement between groups:\n    // try random swaps of nearby boundary candidates if compactness improves.\n    auto groupApproxCostFast = [&](const vector<int>& v) -> double {\n        int n = v.size();\n        if (n <= 1) return 0;\n        double cx = 0, cy = 0;\n        for (int p : v) {\n            cx += x[p];\n            cy += y[p];\n        }\n        cx /= n;\n        cy /= n;\n        double s = 0;\n        for (int p : v) {\n            double dx = x[p] - cx;\n            double dy = y[p] - cy;\n            s += sqrt(dx * dx + dy * dy);\n        }\n        return s;\n    };\n\n    vector<double> gcost(M);\n    for (int k = 0; k < M; k++) gcost[k] = groupApproxCostFast(groups[k]);\n\n    for (int iter = 0; iter < 6000 && timer.sec() < 1.15; iter++) {\n        int a = rnd_int(0, M - 1);\n        int b = rnd_int(0, M - 1);\n        if (a == b || groups[a].empty() || groups[b].empty()) continue;\n\n        // Only consider spatially possibly close groups.\n        int ia = rnd_int(0, (int)groups[a].size() - 1);\n        int cityA = groups[a][ia];\n\n        int bestIb = -1;\n        double bestD = 1e100;\n        int trials = min(8, (int)groups[b].size());\n        for (int t = 0; t < trials; t++) {\n            int ib = rnd_int(0, (int)groups[b].size() - 1);\n            int cityB = groups[b][ib];\n            double d = dist2(cityA, cityB);\n            if (d < bestD) {\n                bestD = d;\n                bestIb = ib;\n            }\n        }\n        if (bestIb < 0) continue;\n\n        double old = gcost[a] + gcost[b];\n        swap(groups[a][ia], groups[b][bestIb]);\n        double na = groupApproxCostFast(groups[a]);\n        double nb = groupApproxCostFast(groups[b]);\n        double nw = na + nb;\n\n        if (nw + 1e-9 < old) {\n            gcost[a] = na;\n            gcost[b] = nb;\n        } else {\n            swap(groups[a][ia], groups[b][bestIb]);\n        }\n    }\n\n    for (int k = 0; k < M; k++) {\n        double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n        for (int p : groups[k]) {\n            minx = min(minx, x[p]);\n            maxx = max(maxx, x[p]);\n            miny = min(miny, y[p]);\n            maxy = max(maxy, y[p]);\n        }\n        bool sx = (maxx - minx) >= (maxy - miny);\n        sort(groups[k].begin(), groups[k].end(), [&](int a, int b) {\n            double va = sx ? x[a] : y[a];\n            double vb = sx ? x[b] : y[b];\n            if (va != vb) return va < vb;\n            return (sx ? y[a] : x[a]) < (sx ? y[b] : x[b]);\n        });\n    }\n\n    vector<vector<pair<int,int>>> queriedEdges(M);\n    int qcnt = 0;\n\n    auto query = [&](const vector<int>& c) -> vector<pair<int,int>> {\n        cout << \"? \" << c.size();\n        for (int v : c) cout << ' ' << v;\n        cout << endl;\n        cout.flush();\n\n        vector<pair<int,int>> ret;\n        for (int i = 0; i < (int)c.size() - 1; i++) {\n            int a, b;\n            cin >> a >> b;\n            if (a > b) swap(a, b);\n            ret.push_back({a, b});\n        }\n        return ret;\n    };\n\n    // Query whole small groups first. This gives exact final MST for those groups.\n    vector<int> qorder(M);\n    iota(qorder.begin(), qorder.end(), 0);\n    sort(qorder.begin(), qorder.end(), [&](int a, int b) {\n        bool aa = (G[a] >= 2 && G[a] <= L);\n        bool bb = (G[b] >= 2 && G[b] <= L);\n        if (aa != bb) return aa > bb;\n        return G[a] < G[b];\n    });\n\n    vector<int> exactGroup(M, 0);\n    for (int k : qorder) {\n        if (qcnt >= Q) break;\n        if (G[k] >= 2 && G[k] <= L) {\n            auto ret = query(groups[k]);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            exactGroup[k] = 1;\n        }\n    }\n\n    // For larger groups, query nearest-neighborhoods instead of simple chunks.\n    // This tends to reveal true short edges useful for the final MST.\n    vector<int> largeOrder(M);\n    iota(largeOrder.begin(), largeOrder.end(), 0);\n    sort(largeOrder.begin(), largeOrder.end(), [&](int a, int b) {\n        return G[a] > G[b];\n    });\n\n    for (int k : largeOrder) {\n        if (qcnt >= Q) break;\n        int s = groups[k].size();\n        if (s < 2 || exactGroup[k]) continue;\n\n        int targetQueries = 1;\n        if (s >= 80) targetQueries = 6;\n        else if (s >= 50) targetQueries = 4;\n        else if (s >= 25) targetQueries = 3;\n        else if (s >= 12) targetQueries = 2;\n\n        targetQueries = min(targetQueries, Q - qcnt);\n\n        vector<int> anchors = groups[k];\n        // prefer spread anchors\n        sort(anchors.begin(), anchors.end(), [&](int a, int b) {\n            if (x[a] != x[b]) return x[a] < x[b];\n            return y[a] < y[b];\n        });\n\n        for (int tq = 0; tq < targetQueries && qcnt < Q; tq++) {\n            int anchor;\n            if (targetQueries == 1) anchor = anchors[s / 2];\n            else anchor = anchors[(long long)tq * (s - 1) / (targetQueries - 1)];\n\n            vector<pair<double,int>> nb;\n            nb.reserve(s);\n            for (int p : groups[k]) {\n                nb.push_back({dist2(anchor, p), p});\n            }\n            sort(nb.begin(), nb.end());\n\n            vector<int> c;\n            for (int i = 0; i < min(L, (int)nb.size()); i++) c.push_back(nb[i].second);\n            if ((int)c.size() >= 2) {\n                auto ret = query(c);\n                qcnt++;\n                queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            }\n        }\n    }\n\n    // Use remaining queries on medium groups with sliding local windows.\n    for (int k = 0; k < M && qcnt < Q; k++) {\n        int s = groups[k].size();\n        if (s < 2 || exactGroup[k]) continue;\n        int step = max(2, L - 2);\n        for (int st = 0; st < s && qcnt < Q; st += step) {\n            int en = min(s, st + L);\n            if (en - st < 2) break;\n            vector<int> c(groups[k].begin() + st, groups[k].begin() + en);\n            auto ret = query(c);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            if (en == s) break;\n        }\n    }\n\n    // Build final spanning trees.\n    vector<vector<pair<int,int>>> answerEdges(M);\n\n    for (int k = 0; k < M; k++) {\n        int s = groups[k].size();\n        if (s <= 1) continue;\n\n        unordered_set<long long> seen;\n        seen.reserve(s * 32);\n\n        auto keyEdge = [&](int a, int b) -> long long {\n            if (a > b) swap(a, b);\n            return ((long long)a << 32) ^ (unsigned int)b;\n        };\n\n        vector<Edge> cand;\n\n        auto addEdge = [&](int a, int b, long long bonus) {\n            if (a == b) return;\n            int u = min(a, b), v = max(a, b);\n            long long key = keyEdge(u, v);\n            if (seen.insert(key).second) {\n                cand.push_back({u, v, distApprox(u, v) + bonus});\n            }\n        };\n\n        // Queried true-MST edges: slight discount, not forced.\n        for (auto [a, b] : queriedEdges[k]) {\n            addEdge(a, b, -200);\n        }\n\n        // Approximate k nearest neighbors.\n        int K = min(s - 1, 18);\n        for (int ii = 0; ii < s; ii++) {\n            int a = groups[k][ii];\n            vector<pair<double,int>> nb;\n            nb.reserve(s - 1);\n            for (int jj = 0; jj < s; jj++) if (ii != jj) {\n                int b = groups[k][jj];\n                nb.push_back({dist2(a, b), b});\n            }\n            if ((int)nb.size() > K) {\n                nth_element(nb.begin(), nb.begin() + K, nb.end());\n                nb.resize(K);\n            }\n            for (auto &pr : nb) addEdge(a, pr.second, 0);\n        }\n\n        // Consecutive edges fallback.\n        for (int i = 0; i + 1 < s; i++) {\n            addEdge(groups[k][i], groups[k][i + 1], 500);\n        }\n\n        sort(cand.begin(), cand.end());\n\n        DSU dsu(N);\n        for (auto &e : cand) {\n            if ((int)answerEdges[k].size() == s - 1) break;\n            if (dsu.unite(e.u, e.v)) {\n                answerEdges[k].push_back({e.u, e.v});\n            }\n        }\n\n        // Guaranteed fallback.\n        for (int i = 0; i + 1 < s && (int)answerEdges[k].size() < s - 1; i++) {\n            int a = groups[k][i], b = groups[k][i + 1];\n            if (dsu.unite(a, b)) answerEdges[k].push_back({a, b});\n        }\n    }\n\n    cout << \"!\" << '\\n';\n    for (int k = 0; k < M; k++) {\n        for (int i = 0; i < (int)groups[k].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[k][i];\n        }\n        cout << '\\n';\n        for (auto [a, b] : answerEdges[k]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Action {\n    char a, d;\n};\n\nstruct Prev {\n    int pi, pj;\n    Action act;\n    bool used = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    vector<pair<int,int>> p(M);\n    for (int i = 0; i < M; i++) {\n        cin >> p[i].first >> p[i].second;\n    }\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    vector<Action> answer;\n\n    for (int t = 0; t + 1 < M; t++) {\n        auto [si, sj] = p[t];\n        auto [gi, gj] = p[t + 1];\n\n        vector<vector<int>> dist(N, vector<int>(N, -1));\n        vector<vector<Prev>> prv(N, vector<Prev>(N));\n\n        queue<pair<int,int>> q;\n        dist[si][sj] = 0;\n        q.push({si, sj});\n\n        while (!q.empty()) {\n            auto [i, j] = q.front();\n            q.pop();\n\n            if (i == gi && j == gj) break;\n\n            for (int dir = 0; dir < 4; dir++) {\n                // Move\n                {\n                    int ni = i + di[dir];\n                    int nj = j + dj[dir];\n                    if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                        if (dist[ni][nj] == -1) {\n                            dist[ni][nj] = dist[i][j] + 1;\n                            prv[ni][nj] = {i, j, {'M', dc[dir]}, true};\n                            q.push({ni, nj});\n                        }\n                    }\n                }\n\n                // Slide: since there are no internal blocks, this goes to the border.\n                {\n                    int ni = i;\n                    int nj = j;\n                    while (true) {\n                        int ti = ni + di[dir];\n                        int tj = nj + dj[dir];\n                        if (ti < 0 || ti >= N || tj < 0 || tj >= N) break;\n                        ni = ti;\n                        nj = tj;\n                    }\n\n                    if (ni != i || nj != j) {\n                        if (dist[ni][nj] == -1) {\n                            dist[ni][nj] = dist[i][j] + 1;\n                            prv[ni][nj] = {i, j, {'S', dc[dir]}, true};\n                            q.push({ni, nj});\n                        }\n                    }\n                }\n            }\n        }\n\n        vector<Action> path;\n        int ci = gi, cj = gj;\n\n        while (!(ci == si && cj == sj)) {\n            Prev pr = prv[ci][cj];\n            path.push_back(pr.act);\n            ci = pr.pi;\n            cj = pr.pj;\n        }\n\n        reverse(path.begin(), path.end());\n        for (auto a : path) answer.push_back(a);\n    }\n\n    // The limit is 2*N*M = 1600. This strategy should be far below it.\n    int limit = 2 * N * M;\n    if ((int)answer.size() > limit) {\n        answer.resize(limit);\n    }\n\n    for (auto [a, d] : answer) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Input {\n    int n;\n    vector<int> x, y;\n    vector<long long> r;\n};\n\nstatic constexpr int W = 10000;\nstatic constexpr double TIME_LIMIT = 4.85;\n\nchrono::steady_clock::time_point start_time;\n\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nlong long area(const Rect& e) {\n    return 1LL * (e.c - e.a) * (e.d - e.b);\n}\n\nbool overlap_interval(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\ndouble rect_score(long long s, long long r) {\n    double mn = (double)min(s, r);\n    double mx = (double)max(s, r);\n    double q = mn / mx;\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble total_score(const vector<Rect>& rects, const Input& in) {\n    double res = 0;\n    for (int i = 0; i < in.n; i++) {\n        res += rect_score(area(rects[i]), in.r[i]);\n    }\n    return res;\n}\n\nbool contains_point_after_shrink(const Rect& r, int x, int y) {\n    return r.a <= x && x < r.c && r.b <= y && y < r.d;\n}\n\nint max_expand_dir(const vector<Rect>& rects, int idx, int dir) {\n    const Rect& cur = rects[idx];\n    int n = rects.size();\n\n    if (dir == 0) {\n        int lim = cur.a;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.c <= cur.a) {\n                lim = min(lim, cur.a - o.c);\n            }\n        }\n        return lim;\n    } else if (dir == 1) {\n        int lim = W - cur.c;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.a >= cur.c) {\n                lim = min(lim, o.a - cur.c);\n            }\n        }\n        return lim;\n    } else if (dir == 2) {\n        int lim = cur.b;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.d <= cur.b) {\n                lim = min(lim, cur.b - o.d);\n            }\n        }\n        return lim;\n    } else {\n        int lim = W - cur.d;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.b >= cur.d) {\n                lim = min(lim, o.b - cur.d);\n            }\n        }\n        return lim;\n    }\n}\n\nRect expanded(Rect r, int dir, int delta) {\n    if (dir == 0) r.a -= delta;\n    else if (dir == 1) r.c += delta;\n    else if (dir == 2) r.b -= delta;\n    else r.d += delta;\n    return r;\n}\n\nRect shrunk(Rect r, int dir, int delta) {\n    if (dir == 0) r.a += delta;\n    else if (dir == 1) r.c -= delta;\n    else if (dir == 2) r.b += delta;\n    else r.d -= delta;\n    return r;\n}\n\nbool valid_rect_for_point(const Rect& r, int x, int y) {\n    return r.a <= x && x < r.c && r.b <= y && y < r.d && r.a < r.c && r.b < r.d;\n}\n\nvector<int> candidate_deltas(int mx, long long cur_area, long long target, int len) {\n    vector<int> cand;\n    if (mx <= 0) return cand;\n\n    cand.push_back(1);\n    cand.push_back(mx);\n\n    long long need = target - cur_area;\n\n    if (need != 0) {\n        long long ab = llabs(need);\n        long long f = ab / len;\n        long long c = (ab + len - 1) / len;\n\n        for (long long v : {f - 2, f - 1, f, f + 1, f + 2,\n                            c - 2, c - 1, c, c + 1, c + 2}) {\n            if (1 <= v && v <= mx) cand.push_back((int)v);\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    return cand;\n}\n\nvoid greedy_expand(vector<Rect>& rects, const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int stagnate = 0;\n\n    while (elapsed() < TIME_LIMIT && stagnate < 35) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-15;\n\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1)\n                    ? rects[id].d - rects[id].b\n                    : rects[id].c - rects[id].a;\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    gain += 1e-13 * delta;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_dir != -1) {\n                rects[id] = expanded(rects[id], best_dir, best_delta);\n                changed = true;\n            }\n        }\n\n        if (changed) stagnate = 0;\n        else stagnate++;\n    }\n}\n\nvoid local_refine(vector<Rect>& rects, const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int loop = 0;\n\n    while (elapsed() < TIME_LIMIT && loop < 300) {\n        loop++;\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_type = -1; // 0 expand, 1 shrink\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-14;\n\n            // Expansion moves\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1)\n                    ? rects[id].d - rects[id].b\n                    : rects[id].c - rects[id].a;\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 0;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            // Shrink moves\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = 0;\n\n                if (dir == 0) {\n                    mx = in.x[id] - rects[id].a;\n                } else if (dir == 1) {\n                    mx = rects[id].c - (in.x[id] + 1);\n                } else if (dir == 2) {\n                    mx = in.y[id] - rects[id].b;\n                } else {\n                    mx = rects[id].d - (in.y[id] + 1);\n                }\n\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1)\n                    ? rects[id].d - rects[id].b\n                    : rects[id].c - rects[id].a;\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = shrunk(rects[id], dir, delta);\n                    if (!valid_rect_for_point(nr, in.x[id], in.y[id])) continue;\n\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 1;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_type != -1) {\n                if (best_type == 0) {\n                    rects[id] = expanded(rects[id], best_dir, best_delta);\n                } else {\n                    rects[id] = shrunk(rects[id], best_dir, best_delta);\n                }\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n}\n\nvector<Rect> solve_once(const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<Rect> rects(n);\n\n    for (int i = 0; i < n; i++) {\n        rects[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n    }\n\n    greedy_expand(rects, in, rng);\n    local_refine(rects, in, rng);\n\n    return rects;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    Input in;\n    cin >> in.n;\n    in.x.resize(in.n);\n    in.y.resize(in.n);\n    in.r.resize(in.n);\n\n    for (int i = 0; i < in.n; i++) {\n        cin >> in.x[i] >> in.y[i] >> in.r[i];\n    }\n\n    mt19937 rng(1234567);\n\n    vector<Rect> best;\n    double best_score = -1.0;\n\n    int trials = 0;\n\n    while (elapsed() < TIME_LIMIT) {\n        auto rects = solve_once(in, rng);\n        double sc = total_score(rects, in);\n\n        if (sc > best_score) {\n            best_score = sc;\n            best = rects;\n        }\n\n        trials++;\n    }\n\n    if (best.empty()) {\n        best.resize(in.n);\n        for (int i = 0; i < in.n; i++) {\n            best[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n        }\n    }\n\n    for (int i = 0; i < in.n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' '\n             << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr double TIME_LIMIT = 1.93;\n\nint si, sj;\nint tile_id[N][N];\nint pval[N][N];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\ninline bool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() {\n        st = chrono::high_resolution_clock::now();\n    }\n    double elapsed() const {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline int next_int(int n) {\n        return (int)(next() % n);\n    }\n};\n\nstruct Candidate {\n    int dir;\n    int ni, nj;\n    int eval;\n};\n\nstruct Params {\n    int w_score;\n    int w_deg;\n    int w_near;\n    int w_best2;\n    int w_sum2;\n    int w_best3;\n    int noise;\n    int deg1_penalty;\n    int dead_penalty;\n    int random_pick_rate;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tile = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> tile_id[i][j];\n            max_tile = max(max_tile, tile_id[i][j]);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> pval[i][j];\n        }\n    }\n\n    int M = max_tile + 1;\n\n    vector<Params> params = {\n        {100, 18, 3, 35, 1, 12, 150, 250, 2500, 17},\n        {120, 12, 2, 25, 1, 10, 220, 150, 2200, 20},\n        { 90, 45, 4, 30, 1, 10, 120, 400, 3000, 14},\n        {105,-20, 3, 20, 1,  8, 150,   0, 2000, 18},\n        {135,  5, 2, 15, 0,  5, 280,  80, 1800, 24},\n        { 95, 30, 7, 35, 1, 12, 180, 250, 2600, 18},\n        {110, 25, 1, 45, 0, 15, 170, 250, 2600, 16},\n        {100, 60, 2, 20, 0,  8, 100, 500, 3500, 12},\n        {150,  0, 1, 10, 0,  3, 350,  50, 1500, 28},\n        { 80, 70, 5, 25, 1,  8, 100, 600, 3800, 10},\n        {115,-35, 3, 25, 0,  7, 160,-100, 1700, 18},\n        {105, 20, 5, 40, 1, 14, 260, 200, 2400, 22},\n\n        // Additional variants\n        {125, 18, 4, 32, 1, 12, 200, 200, 2300, 20},\n        { 85, 80, 3, 18, 0,  6,  80, 700, 4200,  8},\n        {160,-10, 1,  8, 0,  2, 400,   0, 1200, 30},\n        {100,-55, 2, 35, 0, 10, 180,-150, 1600, 20},\n        {115, 35, 6, 30, 1, 10, 150, 350, 3000, 15},\n        {130,  8, 5, 25, 1,  8, 250, 150, 2100, 24},\n        { 95, 55, 1, 40, 0, 16, 130, 450, 3300, 13},\n        {140, 15, 0, 20, 0,  6, 320, 100, 1800, 26}\n    };\n\n    Timer timer;\n    XorShift rng;\n\n    vector<unsigned char> visited(M, 0);\n\n    string best_path;\n    int best_score = pval[si][sj];\n\n    int iter = 0;\n\n    while (timer.elapsed() < TIME_LIMIT) {\n        iter++;\n\n        fill(visited.begin(), visited.end(), 0);\n\n        int ci = si;\n        int cj = sj;\n        int score = pval[ci][cj];\n\n        visited[tile_id[ci][cj]] = 1;\n\n        string path;\n        path.reserve(2500);\n\n        const Params& par = params[(iter + rng.next_int((int)params.size())) % params.size()];\n\n        while (true) {\n            Candidate cand[4];\n            int cn = 0;\n\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n\n                if (!inside(ni, nj)) continue;\n\n                int tid = tile_id[ni][nj];\n                if (visited[tid]) continue;\n\n                visited[tid] = 1;\n\n                int deg = 0;\n                int near_score = 0;\n                int best2 = 0;\n                int sum2 = 0;\n                int best3 = 0;\n\n                for (int e = 0; e < 4; e++) {\n                    int xi = ni + di[e];\n                    int xj = nj + dj[e];\n\n                    if (!inside(xi, xj)) continue;\n\n                    int nt = tile_id[xi][xj];\n                    if (visited[nt]) continue;\n\n                    deg++;\n                    near_score += pval[xi][xj];\n\n                    visited[nt] = 1;\n\n                    int local_best2 = 0;\n                    int local_best3 = 0;\n\n                    for (int f = 0; f < 4; f++) {\n                        int yi = xi + di[f];\n                        int yj = xj + dj[f];\n\n                        if (!inside(yi, yj)) continue;\n\n                        int yt = tile_id[yi][yj];\n                        if (visited[yt]) continue;\n\n                        local_best2 = max(local_best2, pval[yi][yj]);\n\n                        visited[yt] = 1;\n\n                        int local3 = 0;\n                        for (int g = 0; g < 4; g++) {\n                            int zi = yi + di[g];\n                            int zj = yj + dj[g];\n\n                            if (!inside(zi, zj)) continue;\n\n                            int zt = tile_id[zi][zj];\n                            if (visited[zt]) continue;\n\n                            local3 = max(local3, pval[zi][zj]);\n                        }\n\n                        visited[yt] = 0;\n\n                        local_best3 = max(local_best3, pval[yi][yj] + local3);\n                    }\n\n                    visited[nt] = 0;\n\n                    best2 = max(best2, pval[xi][xj] + local_best2);\n                    best3 = max(best3, pval[xi][xj] + local_best3);\n                    sum2 += pval[xi][xj];\n                }\n\n                visited[tid] = 0;\n\n                int eval = 0;\n                eval += par.w_score * pval[ni][nj];\n                eval += par.w_deg * deg;\n                eval += par.w_near * near_score;\n                eval += par.w_best2 * best2;\n                eval += par.w_sum2 * sum2;\n                eval += par.w_best3 * best3;\n                eval += rng.next_int(par.noise + 1);\n\n                if (deg == 0) eval -= par.dead_penalty;\n                else if (deg == 1) eval -= par.deg1_penalty;\n\n                cand[cn++] = {d, ni, nj, eval};\n            }\n\n            if (cn == 0) break;\n\n            sort(cand, cand + cn, [](const Candidate& a, const Candidate& b) {\n                return a.eval > b.eval;\n            });\n\n            int choose = 0;\n            int r = rng.next_int(100);\n\n            if (r < par.random_pick_rate) {\n                if (cn >= 4 && rng.next_int(100) < 8) {\n                    choose = 3;\n                } else if (cn >= 3 && rng.next_int(100) < 25) {\n                    choose = 2;\n                } else if (cn >= 2) {\n                    choose = 1;\n                }\n            }\n\n            Candidate c = cand[choose];\n\n            path.push_back(dc[c.dir]);\n            ci = c.ni;\n            cj = c.nj;\n\n            visited[tile_id[ci][cj]] = 1;\n            score += pval[ci][cj];\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n        }\n    }\n\n    cout << best_path << '\\n';\n\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int Q = 1000;\n\nstruct UsedEdge {\n    int type; // 0: horizontal, 1: vertical\n    int a, b;\n};\n\ndouble h_edge[N][N - 1];\ndouble v_edge[N - 1][N];\nint h_cnt[N][N - 1];\nint v_cnt[N - 1][N];\n\ndouble row_cost[N]; // horizontal cost by row\ndouble col_cost[N]; // vertical cost by column\n\nvector<UsedEdge> prev_edges;\nint prev_si, prev_sj, prev_ti, prev_tj;\n\nmt19937 rng(1234567);\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos(int x) {\n    return {x / N, x % N};\n}\n\ndouble clamp_cost(double x) {\n    return max(100.0, min(10000.0, x));\n}\n\ndouble get_h_cost(int i, int j, int turn) {\n    double coarse = row_cost[i];\n    double local = h_edge[i][j];\n\n    // Early: trust row model. Later: allow local deviations.\n    double local_w = min(0.45, h_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\ndouble get_v_cost(int i, int j, int turn) {\n    double coarse = col_cost[j];\n    double local = v_edge[i][j];\n\n    double local_w = min(0.45, v_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\nvector<UsedEdge> path_edges(int si, int sj, const string& path) {\n    vector<UsedEdge> edges;\n    int i = si, j = sj;\n    for (char c : path) {\n        if (c == 'U') {\n            edges.push_back({1, i - 1, j});\n            --i;\n        } else if (c == 'D') {\n            edges.push_back({1, i, j});\n            ++i;\n        } else if (c == 'L') {\n            edges.push_back({0, i, j - 1});\n            --j;\n        } else if (c == 'R') {\n            edges.push_back({0, i, j});\n            ++j;\n        }\n    }\n    return edges;\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool vertical_first) {\n    string s;\n    if (vertical_first) {\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n    } else {\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n    }\n    return s;\n}\n\nstring randomized_manhattan(int si, int sj, int ti, int tj) {\n    string s;\n    int i = si, j = sj;\n\n    while (i != ti || j != tj) {\n        vector<char> cand;\n        if (i < ti) cand.push_back('D');\n        if (i > ti) cand.push_back('U');\n        if (j < tj) cand.push_back('R');\n        if (j > tj) cand.push_back('L');\n\n        char c = cand[rng() % cand.size()];\n        s.push_back(c);\n\n        if (c == 'D') ++i;\n        else if (c == 'U') --i;\n        else if (c == 'R') ++j;\n        else --j;\n    }\n\n    return s;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    vector<double> dist(V, 1e100);\n    vector<int> par(V, -1);\n    vector<char> pch(V, '?');\n\n    priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n\n    int S = id(si, sj);\n    int T = id(ti, tj);\n\n    dist[S] = 0.0;\n    pq.push({0.0, S});\n\n    while (!pq.empty()) {\n        auto [d, x] = pq.top();\n        pq.pop();\n\n        if (d != dist[x]) continue;\n        if (x == T) break;\n\n        auto [i, j] = pos(x);\n\n        auto relax = [&](int ni, int nj, double w, char c) {\n            int y = id(ni, nj);\n            if (dist[y] > d + w) {\n                dist[y] = d + w;\n                par[y] = x;\n                pch[y] = c;\n                pq.push({dist[y], y});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, get_v_cost(i - 1, j, turn), 'U');\n        if (i + 1 < N) relax(i + 1, j, get_v_cost(i, j, turn), 'D');\n        if (j > 0) relax(i, j - 1, get_h_cost(i, j - 1, turn), 'L');\n        if (j + 1 < N) relax(i, j + 1, get_h_cost(i, j, turn), 'R');\n    }\n\n    string res;\n    int cur = T;\n    while (cur != S) {\n        if (cur < 0 || pch[cur] == '?') {\n            return manhattan_path(si, sj, ti, tj, true);\n        }\n        res.push_back(pch[cur]);\n        cur = par[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nbool valid_simple_path(int si, int sj, int ti, int tj, const string& s) {\n    bool seen[N][N] = {};\n    int i = si, j = sj;\n    seen[i][j] = true;\n\n    for (char c : s) {\n        if (c == 'U') --i;\n        else if (c == 'D') ++i;\n        else if (c == 'L') --j;\n        else if (c == 'R') ++j;\n        else return false;\n\n        if (i < 0 || i >= N || j < 0 || j >= N) return false;\n        if (seen[i][j]) return false;\n        seen[i][j] = true;\n    }\n\n    return i == ti && j == tj;\n}\n\nvoid update_from_result(int measured, int turn) {\n    if (prev_edges.empty()) return;\n\n    int row_use[N] = {};\n    int col_use[N] = {};\n\n    double pred_coarse = 0.0;\n    double pred_edge = 0.0;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            row_use[e.a]++;\n            pred_coarse += row_cost[e.a];\n            pred_edge += h_edge[e.a][e.b];\n        } else {\n            col_use[e.b]++;\n            pred_coarse += col_cost[e.b];\n            pred_edge += v_edge[e.a][e.b];\n        }\n    }\n\n    double pred = 0.75 * pred_coarse + 0.25 * pred_edge;\n    if (pred <= 1.0) return;\n\n    // Observation noise is multiplicative 0.9-1.1.\n    // Clamp residual to avoid overreacting.\n    double ratio = measured / pred;\n    ratio = max(0.75, min(1.25, ratio));\n    double target = pred * ratio;\n    double err = target - pred;\n\n    double norm = 1e-9;\n    for (int i = 0; i < N; i++) norm += row_use[i] * row_use[i];\n    for (int j = 0; j < N; j++) norm += col_use[j] * col_use[j];\n\n    // Coarse 60-parameter online regression.\n    double lr = 0.55;\n    if (turn > 100) lr = 0.42;\n    if (turn > 300) lr = 0.32;\n    if (turn > 600) lr = 0.24;\n\n    for (int i = 0; i < N; i++) {\n        if (row_use[i]) {\n            row_cost[i] += lr * err * row_use[i] / norm;\n            row_cost[i] = clamp_cost(row_cost[i]);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        if (col_use[j]) {\n            col_cost[j] += lr * err * col_use[j] / norm;\n            col_cost[j] = clamp_cost(col_cost[j]);\n        }\n    }\n\n    // Local edge correction.\n    // This captures random delta and some M=2 breakpoint behavior.\n    double edge_norm = max(1, (int)prev_edges.size());\n    double edge_lr = 0.20;\n    if (turn > 200) edge_lr = 0.16;\n    if (turn > 600) edge_lr = 0.11;\n\n    double per_edge_delta = edge_lr * err / edge_norm;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            int i = e.a, j = e.b;\n            h_edge[i][j] += per_edge_delta;\n            h_edge[i][j] = clamp_cost(h_edge[i][j]);\n            h_cnt[i][j]++;\n        } else {\n            int i = e.a, j = e.b;\n            v_edge[i][j] += per_edge_delta;\n            v_edge[i][j] = clamp_cost(v_edge[i][j]);\n            v_cnt[i][j]++;\n        }\n    }\n\n    // Keep edge estimates weakly tied to their coarse row/column model.\n    // Prevents bad noisy single observations from dominating.\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            int i = e.a, j = e.b;\n            h_edge[i][j] = 0.985 * h_edge[i][j] + 0.015 * row_cost[i];\n        } else {\n            int i = e.a, j = e.b;\n            v_edge[i][j] = 0.985 * v_edge[i][j] + 0.015 * col_cost[j];\n        }\n    }\n}\n\nstring choose_path(int si, int sj, int ti, int tj, int turn) {\n    // Exploration phase. Use monotone paths, which are always simple and shortest\n    // in number of steps, while still giving useful learning signals.\n    if (turn < 20) {\n        if (turn % 3 == 0) return manhattan_path(si, sj, ti, tj, true);\n        if (turn % 3 == 1) return manhattan_path(si, sj, ti, tj, false);\n        return randomized_manhattan(si, sj, ti, tj);\n    }\n\n    string best = dijkstra_path(si, sj, ti, tj, turn);\n\n    // Sparse continuing exploration in first half.\n    // Only use monotone paths, so path length is not excessive.\n    if (turn < 220 && turn % 17 == 0) {\n        string alt = randomized_manhattan(si, sj, ti, tj);\n\n        // Avoid very long detours. Randomized Manhattan has exact Manhattan length,\n        // so it is safe in step count.\n        if ((int)alt.size() <= (int)best.size() + 4) {\n            best = alt;\n        }\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; i++) {\n        row_cost[i] = 5000.0;\n        for (int j = 0; j < N - 1; j++) {\n            h_edge[i][j] = 5000.0;\n            h_cnt[i][j] = 0;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        col_cost[j] = 5000.0;\n    }\n\n    for (int i = 0; i < N - 1; i++) {\n        for (int j = 0; j < N; j++) {\n            v_edge[i][j] = 5000.0;\n            v_cnt[i][j] = 0;\n        }\n    }\n\n    int measured = -1;\n\n    for (int turn = 0; turn < Q; turn++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        if (turn > 0) {\n            update_from_result(measured, turn);\n        }\n\n        string ans = choose_path(si, sj, ti, tj, turn);\n\n        if (!valid_simple_path(si, sj, ti, tj, ans)) {\n            ans = manhattan_path(si, sj, ti, tj, true);\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        prev_si = si;\n        prev_sj = sj;\n        prev_ti = ti;\n        prev_tj = tj;\n        prev_edges = path_edges(si, sj, ans);\n\n        cin >> measured;\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int MAXM = 800;\nstatic const string ALPHA = \"ABCDEFGH\";\n\nint M;\nvector<string> S;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nbool cyclic_contains(const string& line, const string& pat) {\n    int L = (int)line.size();\n    int K = (int)pat.size();\n\n    for (int st = 0; st < L; ++st) {\n        bool ok = true;\n        for (int p = 0; p < K; ++p) {\n            if (line[(st + p) % L] != pat[p]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n\n    return false;\n}\n\nint overlap_suffix_prefix(const string& a, const string& b) {\n    int la = (int)a.size();\n    int lb = (int)b.size();\n    int lim = min(la, lb);\n\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[la - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n\n    return 0;\n}\n\nstring canonical_rotation(const string& s) {\n    string best = s;\n    for (int sh = 1; sh < (int)s.size(); ++sh) {\n        string t = s.substr(sh) + s.substr(0, sh);\n        if (t < best) best = t;\n    }\n    return best;\n}\n\nstruct Cand {\n    string line;\n    bitset<MAXM> cover;\n    int cnt;\n};\n\nbitset<MAXM> calc_cover(const string& line) {\n    bitset<MAXM> bs;\n    for (int i = 0; i < M; ++i) {\n        if (cyclic_contains(line, S[i])) bs.set(i);\n    }\n    return bs;\n}\n\nint gain_count(const bitset<MAXM>& cover, const bitset<MAXM>& used) {\n    return (int)(cover & (~used)).count();\n}\n\nstring extend_to_20(string t, mt19937& rng, char fillChar) {\n    while ((int)t.size() < N) {\n        if ((rng() % 100) < 75) t += fillChar;\n        else t += ALPHA[rng() % 8];\n    }\n    if ((int)t.size() > N) t.resize(N);\n    return t;\n}\n\nvoid add_candidate(\n    vector<Cand>& cands,\n    unordered_set<string>& seen,\n    string t,\n    mt19937& rng,\n    char fillChar\n) {\n    if ((int)t.size() < N) t = extend_to_20(t, rng, fillChar);\n    if ((int)t.size() > N) return;\n\n    string can = canonical_rotation(t);\n    if (!seen.insert(can).second) return;\n\n    bitset<MAXM> cov = calc_cover(t);\n    int cnt = (int)cov.count();\n    if (cnt > 0) {\n        cands.push_back({t, cov, cnt});\n    }\n}\n\nvector<Cand> generate_candidates(mt19937& rng, Timer& timer) {\n    vector<int> freq(8, 0);\n    for (const string& s : S) {\n        for (char c : s) freq[c - 'A']++;\n    }\n\n    int bestCharId = max_element(freq.begin(), freq.end()) - freq.begin();\n    char fillChar = ALPHA[bestCharId];\n\n    vector<Cand> cands;\n    unordered_set<string> seen;\n    seen.reserve(10000);\n\n    for (const string& s : S) {\n        add_candidate(cands, seen, s, rng, fillChar);\n    }\n\n    vector<int> ids(M);\n    iota(ids.begin(), ids.end(), 0);\n\n    int trials = 0;\n\n    while (timer.elapsed() < 0.95 && trials < 6000) {\n        trials++;\n\n        string cur = S[rng() % M];\n\n        for (int step = 0; step < 8; ++step) {\n            int bestId = -1;\n            int bestOv = -1;\n            string bestMerge;\n\n            for (int rep = 0; rep < 35; ++rep) {\n                int id = rng() % M;\n                const string& b = S[id];\n\n                if (cur.find(b) != string::npos) {\n                    bestId = id;\n                    bestOv = 1000;\n                    bestMerge = cur;\n                    break;\n                }\n\n                int ov1 = overlap_suffix_prefix(cur, b);\n                int len1 = (int)cur.size() + (int)b.size() - ov1;\n\n                if (len1 <= N && ov1 > bestOv) {\n                    bestOv = ov1;\n                    bestId = id;\n                    bestMerge = cur + b.substr(ov1);\n                }\n\n                int ov2 = overlap_suffix_prefix(b, cur);\n                int len2 = (int)cur.size() + (int)b.size() - ov2;\n\n                if (len2 <= N && ov2 > bestOv) {\n                    bestOv = ov2;\n                    bestId = id;\n                    bestMerge = b + cur.substr(ov2);\n                }\n            }\n\n            if (bestId == -1 || bestOv < 2) break;\n\n            cur = bestMerge;\n            add_candidate(cands, seen, cur, rng, fillChar);\n        }\n\n        add_candidate(cands, seen, cur, rng, fillChar);\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n        if (a.cnt != b.cnt) return a.cnt > b.cnt;\n        return a.line < b.line;\n    });\n\n    if ((int)cands.size() > 1800) cands.resize(1800);\n\n    return cands;\n}\n\nvector<string> greedy_select_rows(const vector<Cand>& cands, mt19937& rng) {\n    bitset<MAXM> used;\n    vector<string> rows;\n\n    for (int step = 0; step < N; ++step) {\n        int best = -1;\n        int bestGain = -1;\n\n        int lim = (int)cands.size();\n\n        for (int i = 0; i < lim; ++i) {\n            int gain = gain_count(cands[i].cover, used);\n            if (gain > bestGain) {\n                bestGain = gain;\n                best = i;\n            }\n        }\n\n        if (best == -1 || bestGain <= 0) break;\n\n        rows.push_back(cands[best].line);\n        used |= cands[best].cover;\n    }\n\n    while ((int)rows.size() < N) {\n        rows.push_back(string(N, ALPHA[rng() % 8]));\n    }\n\n    return rows;\n}\n\nvector<string> randomized_select_rows(const vector<Cand>& cands, mt19937& rng, Timer& timer) {\n    vector<string> bestRows = greedy_select_rows(cands, rng);\n\n    bitset<MAXM> bestUsed;\n    for (const string& row : bestRows) {\n        bestUsed |= calc_cover(row);\n    }\n    int bestScore = (int)bestUsed.count();\n\n    int C = (int)cands.size();\n    int attempts = 0;\n\n    while (timer.elapsed() < 2.55) {\n        attempts++;\n\n        bitset<MAXM> used;\n        vector<string> rows;\n\n        for (int step = 0; step < N; ++step) {\n            vector<pair<int, int>> top;\n            top.reserve(8);\n\n            int lim = min(C, 1000);\n\n            for (int i = 0; i < lim; ++i) {\n                int gain = gain_count(cands[i].cover, used);\n                if (gain <= 0) continue;\n\n                if ((int)top.size() < 8) {\n                    top.push_back({gain, i});\n                    sort(top.rbegin(), top.rend());\n                } else if (gain > top.back().first) {\n                    top.back() = {gain, i};\n                    sort(top.rbegin(), top.rend());\n                }\n            }\n\n            if (top.empty()) break;\n\n            int chooseRange = min((int)top.size(), 3 + (int)(rng() % 3));\n            int pick = rng() % chooseRange;\n\n            int id = top[pick].second;\n            rows.push_back(cands[id].line);\n            used |= cands[id].cover;\n        }\n\n        while ((int)rows.size() < N) {\n            rows.push_back(string(N, ALPHA[rng() % 8]));\n        }\n\n        int sc = (int)used.count();\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRows = rows;\n        }\n    }\n\n    return bestRows;\n}\n\nint evaluate_grid_full(const vector<string>& grid) {\n    vector<string> cols(N, string(N, 'A'));\n\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) {\n            cols[j][i] = grid[i][j];\n        }\n    }\n\n    int c = 0;\n\n    for (const string& s : S) {\n        bool ok = false;\n\n        for (int i = 0; i < N && !ok; ++i) {\n            if (cyclic_contains(grid[i], s)) ok = true;\n        }\n\n        for (int j = 0; j < N && !ok; ++j) {\n            if (cyclic_contains(cols[j], s)) ok = true;\n        }\n\n        if (ok) c++;\n    }\n\n    return c;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputN;\n    cin >> inputN >> M;\n\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    Timer timer;\n    mt19937 rng(123456789);\n\n    vector<Cand> cands = generate_candidates(rng, timer);\n\n    if (cands.empty()) {\n        for (int i = 0; i < N; ++i) {\n            cout << string(N, 'A') << '\\n';\n        }\n        return 0;\n    }\n\n    vector<string> rows = randomized_select_rows(cands, rng, timer);\n\n    for (int i = 0; i < N; ++i) {\n        cout << rows[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct PQNode {\n    int d, v;\n    bool operator<(const PQNode& other) const {\n        return d > other.d;\n    }\n};\n\nstruct DijkstraResult {\n    vector<int> dist;\n    vector<int> par;\n    vector<int> parDir;\n};\n\nstruct CandidateSolution {\n    long long cost = (1LL << 60);\n    vector<int> nodes;\n    vector<int> route;\n    vector<vector<int>> distMat;\n    vector<DijkstraResult> dijs;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    const int V = N * N;\n    const int INF = 1e9;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    auto pos = [&](int v) {\n        return pair<int,int>{v / N, v % N};\n    };\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n\n    vector<int> isroad(V, 0), weight(V, 0), road_ids;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                int v = id(i, j);\n                isroad[v] = 1;\n                weight[v] = grid[i][j] - '0';\n                road_ids.push_back(v);\n            }\n        }\n    }\n\n    int R = (int)road_ids.size();\n    int start = id(si, sj);\n\n    vector<vector<int>> visible(V);\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n            vector<int> seg;\n            int k = j;\n            while (k < N && grid[i][k] != '#') {\n                seg.push_back(id(i, k));\n                k++;\n            }\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n            j = k;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n            vector<int> seg;\n            int k = i;\n            while (k < N && grid[k][j] != '#') {\n                seg.push_back(id(k, j));\n                k++;\n            }\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n            i = k;\n        }\n    }\n\n    for (int v : road_ids) {\n        auto &a = visible[v];\n        sort(a.begin(), a.end());\n        a.erase(unique(a.begin(), a.end()), a.end());\n    }\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    auto dijkstra = [&](int s) {\n        DijkstraResult res;\n        res.dist.assign(V, INF);\n        res.par.assign(V, -1);\n        res.parDir.assign(V, -1);\n\n        priority_queue<PQNode> pq;\n        res.dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n\n            if (d != res.dist[v]) continue;\n\n            auto [i, j] = pos(v);\n\n            for (int z = 0; z < 4; z++) {\n                int ni = i + di[z];\n                int nj = j + dj[z];\n\n                if (!inside(ni, nj)) continue;\n                if (grid[ni][nj] == '#') continue;\n\n                int nv = id(ni, nj);\n                int nd = d + weight[nv];\n\n                if (nd < res.dist[nv]) {\n                    res.dist[nv] = nd;\n                    res.par[nv] = v;\n                    res.parDir[nv] = z;\n                    pq.push({nd, nv});\n                }\n            }\n        }\n\n        return res;\n    };\n\n    auto restore_path = [&](int s, int t, const vector<int>& par,\n                            const vector<int>& parDir) {\n        string path;\n        int cur = t;\n\n        while (cur != s) {\n            int z = parDir[cur];\n            path.push_back(dc[z]);\n            cur = par[cur];\n        }\n\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    DijkstraResult dijStart = dijkstra(start);\n\n    auto coverage_complete = [&](const vector<int>& target_cells) {\n        vector<char> cov(V, 0);\n        int cnt = 0;\n\n        auto add = [&](int v) {\n            for (int u : visible[v]) {\n                if (!cov[u]) {\n                    cov[u] = 1;\n                    cnt++;\n                }\n            }\n        };\n\n        add(start);\n        for (int v : target_cells) add(v);\n\n        return cnt == R;\n    };\n\n    auto build_target_set = [&](double distPow, double interBonus, double noiseCoef) {\n        vector<char> covered(V, 0);\n        int covered_count = 0;\n\n        auto apply_cover = [&](int v) {\n            for (int u : visible[v]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    covered_count++;\n                }\n            }\n        };\n\n        vector<int> targets;\n        apply_cover(start);\n\n        int step = 0;\n\n        while (covered_count < R) {\n            int best = -1;\n            double bestScore = -1.0;\n\n            for (int v : road_ids) {\n                int gain = 0;\n                for (int u : visible[v]) {\n                    if (!covered[u]) gain++;\n                }\n                if (gain == 0) continue;\n\n                double score = (double)gain;\n                score /= pow((double)dijStart.dist[v] + 20.0, distPow);\n\n                auto [i, j] = pos(v);\n                int deg = 0;\n                for (int z = 0; z < 4; z++) {\n                    int ni = i + di[z];\n                    int nj = j + dj[z];\n                    if (inside(ni, nj) && grid[ni][nj] != '#') deg++;\n                }\n                if (deg >= 3) score *= interBonus;\n\n                unsigned h = (unsigned)(v * 1103515245u + step * 12345u);\n                double rnd = ((h >> 8) & 1023) / 1023.0;\n                score *= 1.0 + noiseCoef * (rnd - 0.5);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = v;\n                }\n            }\n\n            if (best == -1) break;\n\n            targets.push_back(best);\n            apply_cover(best);\n            step++;\n        }\n\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n        return targets;\n    };\n\n    auto remove_redundant_targets = [&](vector<int> targets) {\n        vector<int> result;\n        for (int v : targets) {\n            if (v != start) result.push_back(v);\n        }\n\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n\n            vector<int> coverCount(V, 0);\n            auto add = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            add(start);\n            for (int v : result) add(v);\n\n            vector<pair<int,int>> ord;\n            for (int idx = 0; idx < (int)result.size(); idx++) {\n                ord.push_back({(int)visible[result[idx]].size(), idx});\n            }\n\n            sort(ord.begin(), ord.end());\n\n            vector<char> removed(result.size(), 0);\n\n            for (auto [sz, idx] : ord) {\n                if (removed[idx]) continue;\n                int v = result[idx];\n\n                bool ok = true;\n                for (int u : visible[v]) {\n                    if (coverCount[u] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n\n                if (ok) {\n                    removed[idx] = 1;\n                    changed = true;\n                    for (int u : visible[v]) coverCount[u]--;\n                }\n            }\n\n            if (changed) {\n                vector<int> nxt;\n                for (int i = 0; i < (int)result.size(); i++) {\n                    if (!removed[i]) nxt.push_back(result[i]);\n                }\n                result.swap(nxt);\n            }\n        }\n\n        return result;\n    };\n\n    auto route_cost_from_order = [&](const vector<vector<int>>& distMat,\n                                     const vector<int>& route) {\n        long long cost = 0;\n        int prev = 0;\n        for (int x : route) {\n            cost += distMat[prev][x];\n            prev = x;\n        }\n        cost += distMat[prev][0];\n        return cost;\n    };\n\n    auto two_opt = [&](vector<int>& route, const vector<vector<int>>& distMat) {\n        int L = (int)route.size();\n\n        bool improved = true;\n        int iter = 0;\n\n        while (improved && iter < 400) {\n            improved = false;\n            iter++;\n\n            for (int l = 0; l < L && !improved; l++) {\n                for (int r = l + 1; r < L && !improved; r++) {\n                    int a = (l == 0 ? 0 : route[l - 1]);\n                    int b = route[l];\n                    int c = route[r];\n                    int d = (r + 1 == L ? 0 : route[r + 1]);\n\n                    int before = distMat[a][b] + distMat[c][d];\n                    int after  = distMat[a][c] + distMat[b][d];\n\n                    if (after < before) {\n                        reverse(route.begin() + l, route.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    };\n\n    auto solve_tsp_for_targets = [&](const vector<int>& target_cells) {\n        CandidateSolution sol;\n\n        vector<int> nodes;\n        nodes.push_back(start);\n        for (int v : target_cells) {\n            if (v != start) nodes.push_back(v);\n        }\n\n        sort(nodes.begin() + 1, nodes.end());\n        nodes.erase(unique(nodes.begin() + 1, nodes.end()), nodes.end());\n\n        int M = (int)nodes.size();\n\n        vector<DijkstraResult> dijs(M);\n        vector<vector<int>> distMat(M, vector<int>(M, INF));\n\n        for (int a = 0; a < M; a++) {\n            dijs[a] = dijkstra(nodes[a]);\n            for (int b = 0; b < M; b++) {\n                distMat[a][b] = dijs[a].dist[nodes[b]];\n            }\n        }\n\n        vector<int> remaining;\n        for (int i = 1; i < M; i++) remaining.push_back(i);\n\n        vector<int> route;\n\n        if (!remaining.empty()) {\n            int first = remaining[0];\n            for (int x : remaining) {\n                if (distMat[0][x] + distMat[x][0] <\n                    distMat[0][first] + distMat[first][0]) {\n                    first = x;\n                }\n            }\n\n            route.push_back(first);\n            remaining.erase(find(remaining.begin(), remaining.end(), first));\n        }\n\n        while (!remaining.empty()) {\n            int bestNode = -1;\n            int bestPos = -1;\n            int bestInc = INF;\n\n            for (int x : remaining) {\n                int L = (int)route.size();\n\n                for (int p = 0; p <= L; p++) {\n                    int a = (p == 0 ? 0 : route[p - 1]);\n                    int b = (p == L ? 0 : route[p]);\n\n                    int inc = distMat[a][x] + distMat[x][b] - distMat[a][b];\n\n                    if (inc < bestInc) {\n                        bestInc = inc;\n                        bestNode = x;\n                        bestPos = p;\n                    }\n                }\n            }\n\n            route.insert(route.begin() + bestPos, bestNode);\n            remaining.erase(find(remaining.begin(), remaining.end(), bestNode));\n        }\n\n        two_opt(route, distMat);\n\n        sol.cost = route_cost_from_order(distMat, route);\n        sol.nodes = move(nodes);\n        sol.route = move(route);\n        sol.distMat = move(distMat);\n        sol.dijs = move(dijs);\n\n        return sol;\n    };\n\n    auto route_aware_delete = [&](CandidateSolution& sol) {\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n\n            vector<int> target_cells;\n            for (int idx : sol.route) target_cells.push_back(sol.nodes[idx]);\n\n            vector<int> coverCount(V, 0);\n            auto addCount = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            addCount(start);\n            for (int v : target_cells) addCount(v);\n\n            int L = (int)sol.route.size();\n            int bestRemovePos = -1;\n            int bestGain = 0;\n\n            for (int p = 0; p < L; p++) {\n                int idx = sol.route[p];\n                int v = sol.nodes[idx];\n\n                bool ok = true;\n                for (int u : visible[v]) {\n                    if (coverCount[u] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n\n                int a = (p == 0 ? 0 : sol.route[p - 1]);\n                int b = idx;\n                int c = (p + 1 == L ? 0 : sol.route[p + 1]);\n\n                int gain = sol.distMat[a][b] + sol.distMat[b][c] - sol.distMat[a][c];\n\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestRemovePos = p;\n                }\n            }\n\n            if (bestRemovePos != -1) {\n                sol.route.erase(sol.route.begin() + bestRemovePos);\n                sol.cost -= bestGain;\n                changed = true;\n            }\n        }\n    };\n\n    // Multiple greedy variants.\n    vector<tuple<double,double,double>> params = {\n        {0.06, 1.00, 0.00},\n        {0.10, 1.02, 0.00},\n        {0.15, 1.05, 0.00},\n        {0.18, 1.08, 0.00},\n        {0.22, 1.10, 0.00},\n        {0.28, 1.12, 0.00},\n        {0.34, 1.15, 0.00},\n        {0.18, 1.08, 0.04},\n        {0.18, 1.08, 0.08},\n        {0.24, 1.12, 0.06},\n        {0.30, 1.15, 0.08}\n    };\n\n    CandidateSolution bestSol;\n\n    for (auto [distPow, interBonus, noiseCoef] : params) {\n        vector<int> targets = build_target_set(distPow, interBonus, noiseCoef);\n        targets = remove_redundant_targets(targets);\n\n        if (!coverage_complete(targets)) continue;\n\n        CandidateSolution sol = solve_tsp_for_targets(targets);\n        route_aware_delete(sol);\n        two_opt(sol.route, sol.distMat);\n        sol.cost = route_cost_from_order(sol.distMat, sol.route);\n\n        if (sol.cost < bestSol.cost) {\n            bestSol = move(sol);\n        }\n    }\n\n    // ------------------------------------------------------------\n    // Route-aware relocation.\n    // ------------------------------------------------------------\n\n    auto build_solution_from_route_cells = [&](const vector<int>& cells) {\n        vector<int> cleaned;\n        for (int v : cells) {\n            if (v != start) cleaned.push_back(v);\n        }\n        sort(cleaned.begin(), cleaned.end());\n        cleaned.erase(unique(cleaned.begin(), cleaned.end()), cleaned.end());\n        return solve_tsp_for_targets(cleaned);\n    };\n\n    {\n        vector<int> cells;\n        for (int idx : bestSol.route) cells.push_back(bestSol.nodes[idx]);\n\n        bool improvedReloc = true;\n        int relocIter = 0;\n\n        while (improvedReloc && relocIter < 3) {\n            improvedReloc = false;\n            relocIter++;\n\n            CandidateSolution curSol = build_solution_from_route_cells(cells);\n            route_aware_delete(curSol);\n            two_opt(curSol.route, curSol.distMat);\n            curSol.cost = route_cost_from_order(curSol.distMat, curSol.route);\n\n            cells.clear();\n            for (int idx : curSol.route) cells.push_back(curSol.nodes[idx]);\n\n            vector<int> coverCount(V, 0);\n            auto addCount = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            addCount(start);\n            for (int v : cells) addCount(v);\n\n            int L = (int)cells.size();\n\n            for (int p = 0; p < L; p++) {\n                int oldv = cells[p];\n\n                int prevv = (p == 0 ? start : cells[p - 1]);\n                int nextv = (p + 1 == L ? start : cells[p + 1]);\n\n                DijkstraResult dijPrev = dijkstra(prevv);\n                DijkstraResult dijNewDummy;\n\n                int oldLocal = dijPrev.dist[oldv] + dijkstra(oldv).dist[nextv];\n\n                vector<int> mustRemain;\n                for (int u : visible[oldv]) {\n                    if (coverCount[u] <= 1) mustRemain.push_back(u);\n                }\n\n                auto [oi, oj] = pos(oldv);\n\n                int bestNew = oldv;\n                int bestLocal = oldLocal;\n\n                for (int cand : road_ids) {\n                    auto [ci, cj] = pos(cand);\n                    int man = abs(ci - oi) + abs(cj - oj);\n                    if (man > 8) continue;\n\n                    if (cand == oldv) continue;\n\n                    bool coversMust = true;\n                    for (int u : mustRemain) {\n                        if (!binary_search(visible[cand].begin(), visible[cand].end(), u)) {\n                            coversMust = false;\n                            break;\n                        }\n                    }\n                    if (!coversMust) continue;\n\n                    int local1 = dijPrev.dist[cand];\n                    if (local1 >= INF) continue;\n\n                    DijkstraResult dijCand = dijkstra(cand);\n                    int local2 = dijCand.dist[nextv];\n                    if (local2 >= INF) continue;\n\n                    int local = local1 + local2;\n                    if (local < bestLocal) {\n                        bestLocal = local;\n                        bestNew = cand;\n                    }\n                }\n\n                if (bestNew != oldv) {\n                    for (int u : visible[oldv]) coverCount[u]--;\n                    cells[p] = bestNew;\n                    for (int u : visible[bestNew]) coverCount[u]++;\n                    improvedReloc = true;\n                }\n            }\n        }\n\n        CandidateSolution relocSol = build_solution_from_route_cells(cells);\n        route_aware_delete(relocSol);\n        two_opt(relocSol.route, relocSol.distMat);\n        relocSol.cost = route_cost_from_order(relocSol.distMat, relocSol.route);\n\n        if (relocSol.cost < bestSol.cost && coverage_complete(cells)) {\n            bestSol = move(relocSol);\n        }\n    }\n\n    route_aware_delete(bestSol);\n    two_opt(bestSol.route, bestSol.distMat);\n    bestSol.cost = route_cost_from_order(bestSol.distMat, bestSol.route);\n\n    // ------------------------------------------------------------\n    // Output path.\n    // ------------------------------------------------------------\n\n    string answer;\n    int prev = 0;\n\n    for (int x : bestSol.route) {\n        answer += restore_path(\n            bestSol.nodes[prev],\n            bestSol.nodes[x],\n            bestSol.dijs[prev].par,\n            bestSol.dijs[prev].parDir\n        );\n        prev = x;\n    }\n\n    answer += restore_path(\n        bestSol.nodes[prev],\n        bestSol.nodes[0],\n        bestSol.dijs[prev].par,\n        bestSol.dijs[prev].parDir\n    );\n\n    cout << answer << '\\n';\n\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    vector<int> d;\n    vector<int> pre;\n    vector<int> nxt;\n};\n\nstruct Obs {\n    int task;\n    int dur;\n};\n\nstruct Edge {\n    int to, rev, cap;\n    int cost;\n};\n\nstruct MinCostFlow {\n    int n;\n    vector<vector<Edge>> g;\n\n    MinCostFlow(int n = 0) : n(n), g(n) {}\n\n    void addEdge(int fr, int to, int cap, int cost) {\n        Edge a{to, (int)g[to].size(), cap, cost};\n        Edge b{fr, (int)g[fr].size(), 0, -cost};\n        g[fr].push_back(a);\n        g[to].push_back(b);\n    }\n\n    pair<int,int> flow(int s, int t, int maxf) {\n        int flow = 0, cost = 0;\n        const int INF = 1e9;\n        vector<int> h(n, 0), dist(n), pv(n), pe(n);\n\n        while (flow < maxf) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n\n            priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n            pq.push({0, s});\n\n            while (!pq.empty()) {\n                auto [d, v] = pq.top();\n                pq.pop();\n                if (dist[v] != d) continue;\n\n                for (int i = 0; i < (int)g[v].size(); i++) {\n                    Edge &e = g[v][i];\n                    if (e.cap <= 0) continue;\n                    int nd = d + e.cost + h[v] - h[e.to];\n                    if (nd < dist[e.to]) {\n                        dist[e.to] = nd;\n                        pv[e.to] = v;\n                        pe[e.to] = i;\n                        pq.push({nd, e.to});\n                    }\n                }\n            }\n\n            if (dist[t] == INF) break;\n\n            for (int v = 0; v < n; v++) {\n                if (dist[v] < INF) h[v] += dist[v];\n            }\n\n            int add = maxf - flow;\n            for (int v = t; v != s; v = pv[v]) {\n                add = min(add, g[pv[v]][pe[v]].cap);\n            }\n\n            for (int v = t; v != s; v = pv[v]) {\n                Edge &e = g[pv[v]][pe[v]];\n                e.cap -= add;\n                g[v][e.rev].cap += add;\n                cost += add * e.cost;\n            }\n\n            flow += add;\n        }\n\n        return {flow, cost};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<Task> tasks(N);\n    vector<double> dsum(N, 0.0), dmaxv(N, 0.0), avgD(K, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; k++) {\n            cin >> tasks[i].d[k];\n            dsum[i] += tasks[i].d[k];\n            dmaxv[i] = max(dmaxv[i], (double)tasks[i].d[k]);\n            avgD[k] += tasks[i].d[k];\n        }\n    }\n    for (int k = 0; k < K; k++) avgD[k] /= N;\n\n    vector<int> indeg0(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        tasks[u].nxt.push_back(v);\n        tasks[v].pre.push_back(u);\n        indeg0[v]++;\n    }\n\n    vector<double> crit(N, 1.0), unlock(N, 0.0), nearUnlock(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double bestCrit = 0.0;\n        double sumUnlock = 0.0;\n        double near = tasks[i].nxt.size();\n\n        for (int v : tasks[i].nxt) {\n            bestCrit = max(bestCrit, crit[v]);\n            sumUnlock += 1.0 + 0.17 * unlock[v];\n            near += 0.22 * tasks[v].nxt.size();\n        }\n\n        double ownHard = dsum[i] / max(1, K);\n        crit[i] = 1.0 + bestCrit + 0.018 * ownHard;\n        unlock[i] = min(2500.0, sumUnlock);\n        nearUnlock[i] = near;\n    }\n\n    vector<double> basePriority(N);\n    for (int i = 0; i < N; i++) {\n        basePriority[i] =\n            36.0 * crit[i]\n            + 4.7 * nearUnlock[i]\n            + 0.13 * unlock[i]\n            + 0.028 * dsum[i]\n            + 0.028 * dmaxv[i]\n            - 0.001 * i;\n    }\n\n    vector<int> status(N, -1);\n    vector<int> remPre = indeg0;\n\n    vector<int> readyList;\n    vector<char> inReady(N, 0);\n    for (int i = 0; i < N; i++) {\n        if (remPre[i] == 0) {\n            readyList.push_back(i);\n            inReady[i] = 1;\n        }\n    }\n\n    vector<int> memberTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    for (int j = 0; j < M; j++) {\n        double scale = 0.96 + 0.10 * ((j % 5) - 2);\n        if (scale < 0.75) scale = 0.75;\n\n        for (int k = 0; k < K; k++) {\n            double spec = 0.0;\n            if (k % M == j) spec += 3.0;\n            if ((k + j) % 7 == 0) spec += 2.0;\n            if ((2 * k + j) % 11 == 0) spec += 1.5;\n            skill[j][k] = max(0.0, avgD[k] * scale + spec);\n        }\n    }\n\n    vector<vector<Obs>> observations(M);\n    vector<double> speed(M, 1.0);\n\n    auto raw_shortage = [&](int task, int member) {\n        double w = 0.0;\n        for (int k = 0; k < K; k++) {\n            w += max(0.0, (double)tasks[task].d[k] - skill[member][k]);\n        }\n        return w;\n    };\n\n    auto estimate_duration = [&](int task, int member) {\n        double w = raw_shortage(task, member);\n        double e = max(1.0, w);\n        e *= speed[member];\n        if (e < 1.0) e = 1.0;\n        return e;\n    };\n\n    auto refit_member = [&](int j) {\n        int nobs = (int)observations[j].size();\n        if (nobs == 0) return;\n\n        int passes = 6;\n        if (nobs > 20) passes = 4;\n        if (nobs > 60) passes = 3;\n\n        double baseLR = 0.038 / sqrt(1.0 + 0.04 * nobs);\n\n        for (int pass = 0; pass < passes; pass++) {\n            for (const Obs &ob : observations[j]) {\n                int t = ob.task;\n                int dur = ob.dur;\n\n                double pred = 0.0;\n                vector<int> active;\n                active.reserve(K);\n\n                for (int k = 0; k < K; k++) {\n                    double gap = (double)tasks[t].d[k] - skill[j][k];\n                    if (gap > 0.0) {\n                        pred += gap;\n                        active.push_back(k);\n                    }\n                }\n\n                double lo, hi;\n                if (dur <= 1) {\n                    lo = 0.0;\n                    hi = 3.0;\n                } else {\n                    lo = max(0.0, (double)dur - 3.0);\n                    hi = (double)dur + 3.0;\n                }\n\n                double err = 0.0;\n                if (pred < lo) err = pred - lo;\n                else if (pred > hi) err = pred - hi;\n\n                if (fabs(err) > 1e-9) {\n                    if (!active.empty()) {\n                        double delta = baseLR * err / sqrt((double)active.size());\n                        for (int k : active) {\n                            skill[j][k] += delta;\n                        }\n                    } else if (err < 0.0) {\n                        double dec = baseLR * (-err) / max(1.0, dsum[t]);\n                        for (int k = 0; k < K; k++) {\n                            skill[j][k] -= dec * tasks[t].d[k];\n                        }\n                    }\n                }\n\n                if (dur == 1) {\n                    double lr = 0.018 / sqrt(1.0 + 0.03 * nobs);\n                    for (int k = 0; k < K; k++) {\n                        if (skill[j][k] < tasks[t].d[k]) {\n                            skill[j][k] += lr * ((double)tasks[t].d[k] - skill[j][k]);\n                        }\n                    }\n                }\n\n                for (int k = 0; k < K; k++) {\n                    if (skill[j][k] < 0.0) skill[j][k] = 0.0;\n                    if (skill[j][k] > 80.0) skill[j][k] = 80.0;\n                }\n            }\n        }\n    };\n\n    auto update_speed = [&](int j) {\n        int nobs = observations[j].size();\n        if (nobs == 0) return;\n\n        int use = min(nobs, 20);\n        double sumLog = 0.0;\n        int cnt = 0;\n\n        for (int idx = nobs - use; idx < nobs; idx++) {\n            const Obs &ob = observations[j][idx];\n            double pred = max(1.0, raw_shortage(ob.task, j));\n            double ratio = (double)ob.dur / pred;\n            ratio = min(3.0, max(0.35, ratio));\n            sumLog += log(ratio);\n            cnt++;\n        }\n\n        if (cnt > 0) {\n            double target = exp(sumLog / cnt);\n            double alpha = min(0.35, 0.08 + 0.015 * nobs);\n            speed[j] = speed[j] * (1.0 - alpha) + target * alpha;\n            if (speed[j] < 0.55) speed[j] = 0.55;\n            if (speed[j] > 1.80) speed[j] = 1.80;\n        }\n    };\n\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        vector<int> readyTasks;\n        readyTasks.reserve(readyList.size());\n        for (int t : readyList) {\n            if (status[t] == -1 && remPre[t] == 0) readyTasks.push_back(t);\n        }\n\n        sort(readyTasks.begin(), readyTasks.end(), [&](int a, int b) {\n            if (basePriority[a] != basePriority[b]) return basePriority[a] > basePriority[b];\n            return a < b;\n        });\n\n        vector<int> freeMembers;\n        for (int j = 0; j < M; j++) {\n            if (memberTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        vector<pair<int,int>> assignments;\n\n        if (!freeMembers.empty() && !readyTasks.empty()) {\n            int F = (int)freeMembers.size();\n            int C = min((int)readyTasks.size(), max(60, F * 12));\n\n            vector<int> candTasks(readyTasks.begin(), readyTasks.begin() + C);\n\n            int S = 0;\n            int memberOffset = 1;\n            int taskOffset = memberOffset + F;\n            int T = taskOffset + C;\n            int V = T + 1;\n\n            MinCostFlow mf(V);\n\n            for (int a = 0; a < F; a++) {\n                mf.addEdge(S, memberOffset + a, 1, 0);\n            }\n\n            for (int b = 0; b < C; b++) {\n                mf.addEdge(taskOffset + b, T, 1, 0);\n            }\n\n            // Dummy task edges allow not assigning a free member.\n            // But using a real ready task usually has positive utility.\n            const int SCALE = 1000;\n            const int OFFSET = 1000000;\n\n            vector<vector<int>> edgeIndex(F, vector<int>(C, -1));\n\n            for (int a = 0; a < F; a++) {\n                int j = freeMembers[a];\n\n                for (int b = 0; b < C; b++) {\n                    int t = candTasks[b];\n\n                    double est = estimate_duration(t, j);\n                    int cnt = observations[j].size();\n\n                    double uncertaintyPenalty = 0.0;\n                    if (cnt < 2) uncertaintyPenalty = 0.08 * est + 2.0;\n                    else if (cnt < 6) uncertaintyPenalty = 0.025 * est;\n\n                    double exploreBonus = 0.0;\n                    if (cnt < 5 && est <= 9.0) exploreBonus = 1.5;\n\n                    double criticalBonus = 0.18 * crit[t];\n\n                    double util =\n                        basePriority[t] / pow(est + 1.0, 0.91)\n                        - uncertaintyPenalty\n                        + exploreBonus\n                        + criticalBonus;\n\n                    // Convert maximize utility to min cost.\n                    int cost = OFFSET - (int)round(util * SCALE);\n                    if (cost < 0) cost = 0;\n\n                    edgeIndex[a][b] = (int)mf.g[memberOffset + a].size();\n                    mf.addEdge(memberOffset + a, taskOffset + b, 1, cost);\n                }\n            }\n\n            mf.flow(S, T, F);\n\n            for (int a = 0; a < F; a++) {\n                int node = memberOffset + a;\n                for (int ei = 0; ei < (int)mf.g[node].size(); ei++) {\n                    Edge &e = mf.g[node][ei];\n                    if (e.to >= taskOffset && e.to < taskOffset + C && e.cap == 0) {\n                        int b = e.to - taskOffset;\n                        int j = freeMembers[a];\n                        int t = candTasks[b];\n                        assignments.push_back({j, t});\n                    }\n                }\n            }\n        }\n\n        for (auto [j, t] : assignments) {\n            status[t] = 0;\n            inReady[t] = 0;\n            memberTask[j] = t;\n            startDay[j] = day;\n        }\n\n        cout << assignments.size();\n        for (auto [j, t] : assignments) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        string line;\n        if (!getline(cin >> ws, line)) return 0;\n\n        stringstream ss(line);\n        int nfin;\n        ss >> nfin;\n\n        if (nfin == -1) {\n            return 0;\n        }\n\n        for (int z = 0; z < nfin; z++) {\n            int memberInput;\n            ss >> memberInput;\n            int j = memberInput - 1;\n\n            int t = memberTask[j];\n            if (t < 0) continue;\n\n            int duration = day - startDay[j] + 1;\n\n            status[t] = 1;\n            memberTask[j] = -1;\n            startDay[j] = -1;\n\n            observations[j].push_back({t, duration});\n            refit_member(j);\n            update_speed(j);\n\n            for (int v : tasks[t].nxt) {\n                remPre[v]--;\n                if (remPre[v] == 0 && status[v] == -1 && !inReady[v]) {\n                    readyList.push_back(v);\n                    inReady[v] = 1;\n                }\n            }\n\n            /*\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; k++) {\n                cout << ' ' << (int)round(skill[j][k]);\n            }\n            cout << '\\n';\n            cout.flush();\n            */\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n};\n\nconst Point OFFICE{400, 400};\nvector<Order> ords(1000);\n\nstatic inline int mdist(const Point& p, const Point& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstatic inline int mdist_xy(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nstatic inline Point pickup_point(int id) {\n    return {ords[id].a, ords[id].b};\n}\n\nstatic inline Point delivery_point(int id) {\n    return {ords[id].c, ords[id].d};\n}\n\nint path_length_points(const vector<Point>& pts) {\n    int s = 0;\n    for (int i = 0; i + 1 < (int)pts.size(); i++) {\n        s += mdist(pts[i], pts[i + 1]);\n    }\n    return s;\n}\n\nvector<int> nearest_path(const vector<int>& ids, bool pickup, Point start) {\n    int n = ids.size();\n    vector<int> path;\n    path.reserve(n);\n    vector<char> used(n, false);\n\n    Point cur = start;\n    for (int step = 0; step < n; step++) {\n        int best = -1;\n        int bestd = INT_MAX;\n\n        for (int i = 0; i < n; i++) {\n            if (used[i]) continue;\n            Point p = pickup ? pickup_point(ids[i]) : delivery_point(ids[i]);\n            int d = mdist(cur, p);\n            if (d < bestd) {\n                bestd = d;\n                best = i;\n            }\n        }\n\n        used[best] = true;\n        path.push_back(ids[best]);\n        cur = pickup ? pickup_point(ids[best]) : delivery_point(ids[best]);\n    }\n\n    return path;\n}\n\nint segment_cost(const vector<int>& path, bool pickup, Point start, Point goal) {\n    int cost = 0;\n    Point cur = start;\n    for (int id : path) {\n        Point p = pickup ? pickup_point(id) : delivery_point(id);\n        cost += mdist(cur, p);\n        cur = p;\n    }\n    cost += mdist(cur, goal);\n    return cost;\n}\n\nvoid two_opt(vector<int>& path, bool pickup, Point start, Point goal) {\n    int n = path.size();\n    if (n <= 2) return;\n\n    auto getp = [&](int idx) -> Point {\n        if (idx == -1) return start;\n        if (idx == n) return goal;\n        return pickup ? pickup_point(path[idx]) : delivery_point(path[idx]);\n    };\n\n    bool improved = true;\n    int loop = 0;\n\n    while (improved && loop < 30) {\n        improved = false;\n        loop++;\n\n        for (int i = 0; i < n - 1; i++) {\n            Point A = getp(i - 1);\n            Point B = getp(i);\n\n            for (int k = i + 1; k < n; k++) {\n                Point C = getp(k);\n                Point D = getp(k + 1);\n\n                int before = mdist(A, B) + mdist(C, D);\n                int after = mdist(A, C) + mdist(B, D);\n\n                if (after < before) {\n                    reverse(path.begin() + i, path.begin() + k + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    vector<int> ids;\n    vector<int> pickups;\n    vector<int> deliveries;\n    vector<Point> route;\n    int cost;\n};\n\nSolution build_solution(vector<int> ids) {\n    Solution sol;\n    sol.ids = ids;\n\n    sol.pickups = nearest_path(ids, true, OFFICE);\n\n    Point after_pickups = OFFICE;\n    if (!sol.pickups.empty()) {\n        after_pickups = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_path(ids, false, after_pickups);\n\n    Point first_del = sol.deliveries.empty() ? OFFICE : delivery_point(sol.deliveries.front());\n\n    two_opt(sol.pickups, true, OFFICE, first_del);\n\n    after_pickups = OFFICE;\n    if (!sol.pickups.empty()) {\n        after_pickups = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_path(ids, false, after_pickups);\n    two_opt(sol.deliveries, false, after_pickups, OFFICE);\n\n    sol.route.clear();\n    sol.route.reserve(102);\n    sol.route.push_back(OFFICE);\n\n    for (int id : sol.pickups) sol.route.push_back(pickup_point(id));\n    for (int id : sol.deliveries) sol.route.push_back(delivery_point(id));\n\n    sol.route.push_back(OFFICE);\n    sol.cost = path_length_points(sol.route);\n\n    return sol;\n}\n\nvector<int> top50_by(function<int(int)> scorer) {\n    vector<pair<int, int>> v;\n    v.reserve(1000);\n    for (int i = 0; i < 1000; i++) v.push_back({scorer(i), i});\n    sort(v.begin(), v.end());\n\n    vector<int> ids;\n    for (int i = 0; i < 50; i++) ids.push_back(v[i].second);\n    return ids;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 1000; i++) {\n        cin >> ords[i].a >> ords[i].b >> ords[i].c >> ords[i].d;\n    }\n\n    auto start_time = chrono::steady_clock::now();\n\n    auto score_round = [&](int i) {\n        return mdist_xy(400, 400, ords[i].a, ords[i].b)\n             + mdist_xy(ords[i].a, ords[i].b, ords[i].c, ords[i].d)\n             + mdist_xy(ords[i].c, ords[i].d, 400, 400);\n    };\n\n    auto score_center = [&](int i) {\n        return mdist_xy(400, 400, ords[i].a, ords[i].b)\n             + mdist_xy(400, 400, ords[i].c, ords[i].d);\n    };\n\n    auto score_pick = [&](int i) {\n        return mdist_xy(400, 400, ords[i].a, ords[i].b);\n    };\n\n    auto score_del = [&](int i) {\n        return mdist_xy(400, 400, ords[i].c, ords[i].d);\n    };\n\n    vector<vector<int>> initials;\n    initials.push_back(top50_by(score_round));\n    initials.push_back(top50_by(score_center));\n    initials.push_back(top50_by(score_pick));\n    initials.push_back(top50_by(score_del));\n\n    Solution best;\n    best.cost = INT_MAX;\n\n    for (auto ids : initials) {\n        Solution sol = build_solution(ids);\n        if (sol.cost < best.cost) best = sol;\n    }\n\n    vector<pair<int, int>> ranked;\n    for (int i = 0; i < 1000; i++) ranked.push_back({score_round(i), i});\n    sort(ranked.begin(), ranked.end());\n\n    vector<int> pool;\n    int pool_size = 220;\n    for (int i = 0; i < pool_size; i++) pool.push_back(ranked[i].second);\n\n    mt19937 rng(1234567);\n\n    Solution cur = best;\n    vector<int> cur_ids = cur.ids;\n\n    while (true) {\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        vector<int> next_ids = cur_ids;\n        unordered_set<int> selected(next_ids.begin(), next_ids.end());\n\n        int remove_pos = uniform_int_distribution<int>(0, 49)(rng);\n\n        vector<int> candidates;\n        for (int id : pool) {\n            if (!selected.count(id)) candidates.push_back(id);\n        }\n        if (candidates.empty()) continue;\n\n        int add_id = candidates[uniform_int_distribution<int>(0, (int)candidates.size() - 1)(rng)];\n        next_ids[remove_pos] = add_id;\n\n        sort(next_ids.begin(), next_ids.end());\n        next_ids.erase(unique(next_ids.begin(), next_ids.end()), next_ids.end());\n        if ((int)next_ids.size() != 50) continue;\n\n        Solution nxt = build_solution(next_ids);\n\n        int diff = nxt.cost - cur.cost;\n        double temp = 40.0 * (1.85 - elapsed) / 1.85 + 1.0;\n\n        bool accept = false;\n        if (diff < 0) accept = true;\n        else {\n            double prob = exp(-diff / temp);\n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur = nxt;\n            cur_ids = next_ids;\n        }\n\n        if (nxt.cost < best.cost) {\n            best = nxt;\n        }\n    }\n\n    cout << 50;\n    for (int id : best.ids) {\n        cout << ' ' << id + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (auto& p : best.route) {\n        cout << ' ' << p.x << ' ' << p.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#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) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[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 (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct KEdge {\n    int w;\n    int id;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return id < other.id;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n        long long dx = x[edges[i].u] - x[edges[i].v];\n        long long dy = y[edges[i].u] - y[edges[i].v];\n        edges[i].d = (int)llround(sqrt((double)(dx * dx + dy * dy)));\n    }\n\n    DSU accepted(N);\n    vector<int> actual(M, -1);\n    vector<char> used(M, 0);\n\n    double coef = 1.92;\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        actual[i] = l;\n\n        bool take = false;\n\n        int ru = accepted.find(edges[i].u);\n        int rv = accepted.find(edges[i].v);\n\n        if (ru != rv) {\n            // Safety check:\n            // If the current edge is a bridge among accepted-components\n            // using only edges i..M-1, then it must be taken.\n            {\n                unordered_map<int, int> mp;\n                mp.reserve(N * 2);\n                vector<int> roots;\n                roots.reserve(N);\n                for (int v = 0; v < N; v++) {\n                    int r = accepted.find(v);\n                    if (!mp.count(r)) {\n                        int id = (int)mp.size();\n                        mp[r] = id;\n                        roots.push_back(r);\n                    }\n                }\n\n                int C = (int)mp.size();\n                vector<vector<pair<int,int>>> g(C);\n                g.reserve(C);\n\n                for (int j = i; j < M; j++) {\n                    int a = mp[accepted.find(edges[j].u)];\n                    int b = mp[accepted.find(edges[j].v)];\n                    if (a == b) continue;\n                    g[a].push_back({b, j});\n                    g[b].push_back({a, j});\n                }\n\n                int cu = mp[ru], cv = mp[rv];\n                vector<int> tin(C, -1), low(C, -1);\n                int timer = 0;\n                bool is_bridge = false;\n\n                function<void(int,int)> dfs = [&](int v, int pe) {\n                    tin[v] = low[v] = timer++;\n                    for (auto [to, eid] : g[v]) {\n                        if (eid == pe) continue;\n                        if (tin[to] != -1) {\n                            low[v] = min(low[v], tin[to]);\n                        } else {\n                            dfs(to, eid);\n                            low[v] = min(low[v], low[to]);\n                            if (low[to] > tin[v] && eid == i) {\n                                is_bridge = true;\n                            }\n                        }\n                    }\n                };\n\n                for (int v = 0; v < C; v++) {\n                    if (tin[v] == -1) dfs(v, -1);\n                }\n\n                if (is_bridge) take = true;\n            }\n\n            // Predicted MST membership test.\n            if (!take) {\n                vector<KEdge> order;\n                order.reserve(M);\n\n                for (int j = 0; j < M; j++) {\n                    int w;\n                    if (j <= i) {\n                        w = actual[j];\n                    } else {\n                        w = max(1, (int)round(coef * edges[j].d));\n                    }\n                    order.push_back({w, j});\n                }\n\n                sort(order.begin(), order.end());\n\n                DSU tmp(N);\n                bool in_predicted_mst = false;\n\n                for (auto [w, id] : order) {\n                    if (tmp.unite(edges[id].u, edges[id].v)) {\n                        if (id == i) {\n                            in_predicted_mst = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (in_predicted_mst) {\n                    // Avoid very bad edges unless needed.\n                    double ratio = (double)l / max(1, edges[i].d);\n\n                    int comps = 0;\n                    for (int v = 0; v < N; v++) {\n                        if (accepted.find(v) == v) comps++;\n                    }\n\n                    double progress = (double)i / M;\n                    double limit = 2.18 - 0.28 * progress;\n                    if (comps > 80) limit += 0.10;\n                    if (comps < 30) limit -= 0.10;\n\n                    if (ratio <= limit || i > M - 420) {\n                        take = true;\n                    }\n                }\n            }\n\n            // Endgame: be less selective.\n            if (!take) {\n                int comps = 0;\n                for (int v = 0; v < N; v++) {\n                    if (accepted.find(v) == v) comps++;\n                }\n\n                int remaining = M - i;\n                if (remaining <= comps * 2) {\n                    take = true;\n                }\n            }\n        }\n\n        if (take) {\n            accepted.unite(edges[i].u, edges[i].v);\n            used[i] = 1;\n            cout << 1 << endl;\n        } else {\n            cout << 0 << endl;\n        }\n        cout.flush();\n\n        // Slight adaptation from observed average ratio.\n        if (i > 0 && i % 100 == 0) {\n            double sum = 0;\n            int cnt = 0;\n            for (int j = 0; j <= i; j++) {\n                sum += (double)actual[j] / max(1, edges[j].d);\n                cnt++;\n            }\n            double avg = sum / cnt;\n            coef = 0.75 * coef + 0.25 * avg;\n            coef = min(2.08, max(1.78, coef));\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstruct Task {\n    int bx, by;\n    int hx, hy;\n    char build;\n};\n\nstruct Room {\n    int id;\n    int x1, x2, y1, y2;\n    vector<Task> tasks;\n    vector<Pos> standby;\n};\n\nconst int H = 30, W = 30, TURNS = 300;\nint N, M;\nvector<Pos> pet, human_pos;\nvector<int> pet_type;\nbool wall[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar mvC[4] = {'U', 'D', 'L', 'R'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\nint dirIndex(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    if (c == 'R') return 3;\n    return -1;\n}\n\nint buildDirIndex(char c) {\n    if (c == 'u') return 0;\n    if (c == 'd') return 1;\n    if (c == 'l') return 2;\n    if (c == 'r') return 3;\n    return -1;\n}\n\nbool hasPet(int x, int y) {\n    for (auto &p : pet) if (p.x == x && p.y == y) return true;\n    return false;\n}\n\nbool hasHuman(int x, int y) {\n    for (auto &h : human_pos) if (h.x == x && h.y == y) return true;\n    return false;\n}\n\nbool canBuildCell(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (wall[x][y]) return true;\n    if (hasPet(x, y) || hasHuman(x, y)) return false;\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && hasPet(nx, ny)) return false;\n    }\n    return true;\n}\n\nbool canMoveCellCurrent(int x, int y) {\n    return inside(x, y) && !wall[x][y];\n}\n\nbool inRect(Pos p, int x1, int x2, int y1, int y2) {\n    return x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2;\n}\n\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nchar stepToward(Pos cur, Pos goal, const bool reserved[31][31]) {\n    int bestd = 1e9;\n    char best = '.';\n\n    for (int d = 0; d < 4; d++) {\n        int nx = cur.x + dx[d], ny = cur.y + dy[d];\n        if (!inside(nx, ny)) continue;\n        if (wall[nx][ny]) continue;\n        if (reserved[nx][ny]) continue;\n\n        int md = abs(nx - goal.x) + abs(ny - goal.y);\n        if (md < bestd) {\n            bestd = md;\n            best = mvC[d];\n        }\n    }\n    return best;\n}\n\nvoid applyHumanActions(const string &ans) {\n    vector<Pos> newh = human_pos;\n    vector<pair<int,int>> builds;\n\n    for (int i = 0; i < M; i++) {\n        int d = buildDirIndex(ans[i]);\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d];\n            int ny = human_pos[i].y + dy[d];\n            if (inside(nx, ny) && canBuildCell(nx, ny)) builds.push_back({nx, ny});\n        }\n    }\n\n    for (auto &b : builds) wall[b.first][b.second] = true;\n\n    for (int i = 0; i < M; i++) {\n        int d = dirIndex(ans[i]);\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d];\n            int ny = human_pos[i].y + dy[d];\n            if (inside(nx, ny) && !wall[nx][ny]) newh[i] = {nx, ny};\n        }\n    }\n\n    human_pos = newh;\n}\n\nvoid applyPetMoves(const vector<string>& moves) {\n    for (int i = 0; i < N; i++) {\n        for (char c : moves[i]) {\n            int d = dirIndex(c);\n            if (d >= 0) {\n                int nx = pet[i].x + dx[d];\n                int ny = pet[i].y + dy[d];\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pet[i] = {nx, ny};\n                }\n            }\n        }\n    }\n}\n\nRoom makeRoom(int id) {\n    Room r;\n    r.id = id;\n\n    if (id == 0) {\n        // top-left, interior [1..8][1..8]\n        r.x1 = 1; r.x2 = 8; r.y1 = 1; r.y2 = 8;\n        for (int y = 1; y <= 8; y++) r.tasks.push_back({9, y, 8, y, 'd'});\n        for (int x = 1; x <= 8; x++) r.tasks.push_back({x, 9, x, 8, 'r'});\n        for (int x = 2; x <= 7; x++) for (int y = 2; y <= 7; y++) r.standby.push_back({x, y});\n    } else if (id == 1) {\n        // top-right, interior [1..8][23..30]\n        r.x1 = 1; r.x2 = 8; r.y1 = 23; r.y2 = 30;\n        for (int y = 23; y <= 30; y++) r.tasks.push_back({9, y, 8, y, 'd'});\n        for (int x = 1; x <= 8; x++) r.tasks.push_back({x, 22, x, 23, 'l'});\n        for (int x = 2; x <= 7; x++) for (int y = 24; y <= 29; y++) r.standby.push_back({x, y});\n    } else if (id == 2) {\n        // bottom-left, interior [23..30][1..8]\n        r.x1 = 23; r.x2 = 30; r.y1 = 1; r.y2 = 8;\n        for (int y = 1; y <= 8; y++) r.tasks.push_back({22, y, 23, y, 'u'});\n        for (int x = 23; x <= 30; x++) r.tasks.push_back({x, 9, x, 8, 'r'});\n        for (int x = 24; x <= 29; x++) for (int y = 2; y <= 7; y++) r.standby.push_back({x, y});\n    } else {\n        // bottom-right, interior [23..30][23..30]\n        r.x1 = 23; r.x2 = 30; r.y1 = 23; r.y2 = 30;\n        for (int y = 23; y <= 30; y++) r.tasks.push_back({22, y, 23, y, 'u'});\n        for (int x = 23; x <= 30; x++) r.tasks.push_back({x, 22, x, 23, 'l'});\n        for (int x = 24; x <= 29; x++) for (int y = 24; y <= 29; y++) r.standby.push_back({x, y});\n    }\n\n    return r;\n}\n\nbool actionLegalNow(int i, char c, const bool reserved[31][31]) {\n    if (c == '.') return true;\n\n    int md = dirIndex(c);\n    if (md >= 0) {\n        int nx = human_pos[i].x + dx[md];\n        int ny = human_pos[i].y + dy[md];\n        return inside(nx, ny) && !wall[nx][ny] && !reserved[nx][ny];\n    }\n\n    int bd = buildDirIndex(c);\n    if (bd >= 0) {\n        int bx = human_pos[i].x + dx[bd];\n        int by = human_pos[i].y + dy[bd];\n        return inside(bx, by) && canBuildCell(bx, by);\n    }\n\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pet.resize(N);\n    pet_type.resize(N);\n    for (int i = 0; i < N; i++) cin >> pet[i].x >> pet[i].y >> pet_type[i];\n\n    cin >> M;\n    human_pos.resize(M);\n    for (int i = 0; i < M; i++) cin >> human_pos[i].x >> human_pos[i].y;\n\n    memset(wall, 0, sizeof(wall));\n\n    vector<Room> rooms;\n    for (int id = 0; id < 4; id++) rooms.push_back(makeRoom(id));\n\n    int bestId = 0;\n    long long bestScore = (1LL << 60);\n\n    for (int id = 0; id < 4; id++) {\n        Room &r = rooms[id];\n\n        int petsInside = 0;\n        int petsNear = 0;\n        for (auto &p : pet) {\n            if (inRect(p, r.x1, r.x2, r.y1, r.y2)) petsInside++;\n            if (r.x1 - 2 <= p.x && p.x <= r.x2 + 2 &&\n                r.y1 - 2 <= p.y && p.y <= r.y2 + 2) petsNear++;\n        }\n\n        Pos center{(r.x1 + r.x2) / 2, (r.y1 + r.y2) / 2};\n        long long travel = 0;\n        for (auto &h : human_pos) travel += manhattan(h, center);\n\n        long long score = 1000000LL * petsInside + 100000LL * petsNear + travel;\n        if (score < bestScore) {\n            bestScore = score;\n            bestId = id;\n        }\n    }\n\n    Room room = rooms[bestId];\n\n    vector<Pos> home(M);\n    for (int i = 0; i < M; i++) {\n        if (!room.standby.empty()) home[i] = room.standby[i % room.standby.size()];\n        else home[i] = {(room.x1 + room.x2) / 2, (room.y1 + room.y2) / 2};\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        string ans(M, '.');\n        bool reserved[31][31];\n        memset(reserved, 0, sizeof(reserved));\n\n        vector<int> usedTask(room.tasks.size(), 0);\n\n        // Decide build actions first and reserve their cells.\n        for (int i = 0; i < M; i++) {\n            Pos cur = human_pos[i];\n\n            int best = -1;\n            for (int k = 0; k < (int)room.tasks.size(); k++) {\n                if (usedTask[k]) continue;\n                Task &t = room.tasks[k];\n                if (wall[t.bx][t.by]) continue;\n                if (reserved[t.bx][t.by]) continue;\n                if (cur.x == t.hx && cur.y == t.hy && canBuildCell(t.bx, t.by)) {\n                    best = k;\n                    break;\n                }\n            }\n\n            if (best != -1) {\n                Task &t = room.tasks[best];\n                ans[i] = t.build;\n                usedTask[best] = 1;\n                reserved[t.bx][t.by] = true;\n            }\n        }\n\n        // Decide moves while treating this turn's build cells as blocked.\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n            Pos cur = human_pos[i];\n\n            int best = -1;\n            int bd = 1e9;\n\n            for (int k = 0; k < (int)room.tasks.size(); k++) {\n                Task &t = room.tasks[k];\n                if (wall[t.bx][t.by]) continue;\n\n                // Do not target a standing cell that is being walled this turn.\n                if (reserved[t.hx][t.hy]) continue;\n\n                int d = manhattan(cur, {t.hx, t.hy});\n                if (!canBuildCell(t.bx, t.by)) d += 4;\n\n                if (d < bd) {\n                    bd = d;\n                    best = k;\n                }\n            }\n\n            Pos goal;\n            if (best != -1) goal = {room.tasks[best].hx, room.tasks[best].hy};\n            else goal = home[i];\n\n            if (cur.x != goal.x || cur.y != goal.y) {\n                char c = stepToward(cur, goal, reserved);\n                if (c != '.') ans[i] = c;\n            }\n        }\n\n        // Final legality check. If anything suspicious, cancel it.\n        for (int i = 0; i < M; i++) {\n            if (!actionLegalNow(i, ans[i], reserved)) {\n                ans[i] = '.';\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n\n        vector<string> pm(N);\n        for (int i = 0; i < N; i++) cin >> pm[i];\n        applyPetMoves(pm);\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int V = 400;\nstatic constexpr int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble pforget;\nstring hwall[N];\nstring vwall[N - 1];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\nint nxt[V][4];\nint distT[V];\nint distS[V];\n\nmt19937 rng(123456789);\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\nbool canMove(int i, int j, int d) {\n    if (d == 0) {\n        if (i == 0) return false;\n        return vwall[i - 1][j] == '0';\n    }\n    if (d == 1) {\n        if (i == N - 1) return false;\n        return vwall[i][j] == '0';\n    }\n    if (d == 2) {\n        if (j == 0) return false;\n        return hwall[i][j - 1] == '0';\n    }\n    if (d == 3) {\n        if (j == N - 1) return false;\n        return hwall[i][j] == '0';\n    }\n    return false;\n}\n\nvoid buildGraph() {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int v = id(i, j);\n            for (int d = 0; d < 4; d++) {\n                if (canMove(i, j, d)) nxt[v][d] = id(i + di[d], j + dj[d]);\n                else nxt[v][d] = v;\n            }\n        }\n    }\n}\n\nvoid bfsFrom(int src, int dist[V]) {\n    fill(dist, dist + V, 1e9);\n    queue<int> q;\n    dist[src] = 0;\n    q.push(src);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (dist[u] > dist[v] + 1) {\n                dist[u] = dist[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n}\n\nstring shortestPath(int s, int t, bool randomTie = false) {\n    vector<int> pre(V, -1), pred(V, -1);\n    queue<int> q;\n    pre[s] = s;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n        if (v == t) break;\n\n        array<int, 4> ord = {0, 1, 2, 3};\n        if (randomTie) shuffle(ord.begin(), ord.end(), rng);\n\n        for (int d : ord) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (pre[u] == -1) {\n                pre[u] = v;\n                pred[u] = d;\n                q.push(u);\n            }\n        }\n    }\n\n    if (pre[t] == -1) return \"\";\n\n    string res;\n    int cur = t;\n    while (cur != s) {\n        int d = pred[cur];\n        res.push_back(dc[d]);\n        cur = pre[cur];\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\ndouble evaluate(const string& route) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    static double prob[V], np[V];\n    fill(prob, prob + V, 0.0);\n    prob[s] = 1.0;\n\n    double expected = 0.0;\n\n    for (int step = 0; step < (int)route.size(); step++) {\n        int d;\n        if (route[step] == 'U') d = 0;\n        else if (route[step] == 'D') d = 1;\n        else if (route[step] == 'L') d = 2;\n        else d = 3;\n\n        fill(np, np + V, 0.0);\n\n        double moveProb = 1.0 - pforget;\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * moveProb;\n        }\n\n        double reach = np[t];\n        if (reach > 0.0) {\n            expected += reach * (401.0 - (step + 1));\n            np[t] = 0.0;\n        }\n\n        memcpy(prob, np, sizeof(prob));\n    }\n\n    return expected;\n}\n\nstring repeatChars(const string& base, int r) {\n    string res;\n    for (char c : base) {\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n    return res;\n}\n\nstring repeatWhole(const string& base) {\n    string res;\n    while ((int)res.size() < MAXL) {\n        for (char c : base) {\n            if ((int)res.size() >= MAXL) break;\n            res.push_back(c);\n        }\n    }\n    return res;\n}\n\nstring distDescentPath(int repeatBias, bool randomTie) {\n    int cur = id(si_, sj_);\n    int t = id(ti_, tj_);\n    string route;\n\n    while (cur != t && (int)route.size() < MAXL) {\n        vector<int> cand;\n        int best = distT[cur];\n\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[cur][d];\n            if (u != cur && distT[u] < best) {\n                cand.push_back(d);\n            }\n        }\n\n        if (cand.empty()) break;\n\n        int d;\n        if (randomTie) d = cand[rng() % cand.size()];\n        else {\n            d = cand[0];\n            for (int x : cand) {\n                if (distT[nxt[cur][x]] < distT[nxt[cur][d]]) d = x;\n            }\n        }\n\n        int rep = repeatBias;\n        for (int k = 0; k < rep && (int)route.size() < MAXL; k++) {\n            route.push_back(dc[d]);\n        }\n\n        cur = nxt[cur][d];\n    }\n\n    return route;\n}\n\nstring greedyDistribution(double temperature, double stayPenalty, double reachBonus, int lenLimit = MAXL) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<double> prob(V, 0.0), np(V, 0.0);\n    prob[s] = 1.0;\n\n    string route;\n\n    for (int step = 0; step < lenLimit; step++) {\n        double bestScore = 1e100;\n        vector<int> bestDirs;\n\n        for (int d = 0; d < 4; d++) {\n            fill(np.begin(), np.end(), 0.0);\n\n            for (int v = 0; v < V; v++) {\n                double pr = prob[v];\n                if (pr == 0.0) continue;\n                np[v] += pr * pforget;\n                np[nxt[v][d]] += pr * (1.0 - pforget);\n            }\n\n            double score = 0.0;\n\n            for (int v = 0; v < V; v++) {\n                double pr = np[v];\n                if (pr == 0.0) continue;\n\n                if (v == t) {\n                    score -= reachBonus * pr * (MAXL - step);\n                    continue;\n                }\n\n                score += pr * distT[v];\n\n                if (nxt[v][d] == v) {\n                    score += stayPenalty * pr;\n                }\n            }\n\n            if (temperature > 0.0) {\n                uniform_real_distribution<double> ud(-temperature, temperature);\n                score += ud(rng);\n            }\n\n            if (score + 1e-12 < bestScore) {\n                bestScore = score;\n                bestDirs.clear();\n                bestDirs.push_back(d);\n            } else if (abs(score - bestScore) < 1e-12) {\n                bestDirs.push_back(d);\n            }\n        }\n\n        int d = bestDirs[rng() % bestDirs.size()];\n        route.push_back(dc[d]);\n\n        fill(np.begin(), np.end(), 0.0);\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * (1.0 - pforget);\n        }\n\n        np[t] = 0.0;\n        prob.swap(np);\n\n        double alive = accumulate(prob.begin(), prob.end(), 0.0);\n        if (alive < 1e-12) break;\n    }\n\n    return route;\n}\n\nstruct BeamNode {\n    string route;\n    array<double, V> prob;\n    double heuristic;\n};\n\nstring beamSearchRoute(int beamWidth, int lenLimit, double reachWeight, double distWeight) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<BeamNode> beam;\n    BeamNode init;\n    init.route.clear();\n    init.prob.fill(0.0);\n    init.prob[s] = 1.0;\n    init.heuristic = 0.0;\n    beam.push_back(init);\n\n    for (int step = 0; step < lenLimit; step++) {\n        vector<BeamNode> nb;\n        nb.reserve(beam.size() * 4);\n\n        for (const auto& node : beam) {\n            for (int d = 0; d < 4; d++) {\n                BeamNode x;\n                x.route = node.route;\n                x.route.push_back(dc[d]);\n                x.prob.fill(0.0);\n\n                double reached = 0.0;\n                for (int v = 0; v < V; v++) {\n                    double pr = node.prob[v];\n                    if (pr == 0.0) continue;\n                    x.prob[v] += pr * pforget;\n                    x.prob[nxt[v][d]] += pr * (1.0 - pforget);\n                }\n\n                reached = x.prob[t];\n                x.prob[t] = 0.0;\n\n                double alive = 0.0;\n                double dsum = 0.0;\n                for (int v = 0; v < V; v++) {\n                    alive += x.prob[v];\n                    dsum += x.prob[v] * distT[v];\n                }\n\n                x.heuristic = node.heuristic\n                            + reached * reachWeight * (401.0 - (step + 1))\n                            - dsum * distWeight\n                            - alive * 0.02;\n\n                nb.push_back(move(x));\n            }\n        }\n\n        sort(nb.begin(), nb.end(), [](const BeamNode& a, const BeamNode& b) {\n            return a.heuristic > b.heuristic;\n        });\n\n        if ((int)nb.size() > beamWidth) nb.resize(beamWidth);\n        beam.swap(nb);\n    }\n\n    string best;\n    double bestVal = -1.0;\n    for (auto& node : beam) {\n        double val = evaluate(node.route);\n        if (val > bestVal) {\n            bestVal = val;\n            best = node.route;\n        }\n    }\n\n    return best;\n}\n\nchar randomBiasedChar() {\n    // Since target is bottom-right, D/R are generally more useful.\n    int x = rng() % 100;\n    if (x < 38) return 'D';\n    if (x < 76) return 'R';\n    if (x < 88) return 'U';\n    return 'L';\n}\n\nstring mutateString(string s, double strength) {\n    if (s.empty()) s = string(1, randomBiasedChar());\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n\n    int ops = 1 + (rng() % max(1, (int)strength));\n\n    for (int op = 0; op < ops; op++) {\n        int type = rng() % 5;\n\n        if (type == 0) {\n            // Replace one character.\n            int pos = rng() % s.size();\n            char c = dc[rng() % 4];\n            s[pos] = c;\n        } else if (type == 1 && (int)s.size() < MAXL) {\n            // Insert.\n            int pos = rng() % (s.size() + 1);\n            char c = randomBiasedChar();\n            s.insert(s.begin() + pos, c);\n        } else if (type == 2 && s.size() > 1) {\n            // Delete.\n            int pos = rng() % s.size();\n            s.erase(s.begin() + pos);\n        } else if (type == 3) {\n            // Change short segment.\n            int len = 1 + rng() % 8;\n            int pos = rng() % s.size();\n            for (int k = 0; k < len && pos + k < (int)s.size(); k++) {\n                s[pos + k] = randomBiasedChar();\n            }\n        } else {\n            // Duplicate local character/segment.\n            if ((int)s.size() < MAXL) {\n                int pos = rng() % s.size();\n                int len = 1 + rng() % min(6, (int)s.size() - pos);\n                string seg = s.substr(pos, len);\n                int ipos = rng() % (s.size() + 1);\n                s.insert(ipos, seg);\n                if ((int)s.size() > MAXL) s.resize(MAXL);\n            }\n        }\n    }\n\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n    return s;\n}\n\nvoid deterministicSingleCharImprove(string& best, double& bestVal, chrono::steady_clock::time_point endTime) {\n    bool improved = true;\n\n    while (improved && chrono::steady_clock::now() < endTime) {\n        improved = false;\n\n        vector<int> positions(best.size());\n        iota(positions.begin(), positions.end(), 0);\n        shuffle(positions.begin(), positions.end(), rng);\n\n        for (int pos : positions) {\n            if (chrono::steady_clock::now() >= endTime) break;\n\n            char old = best[pos];\n            char bestChar = old;\n            double localBest = bestVal;\n\n            for (char c : {'U', 'D', 'L', 'R'}) {\n                if (c == old) continue;\n                string cand = best;\n                cand[pos] = c;\n                double val = evaluate(cand);\n                if (val > localBest) {\n                    localBest = val;\n                    bestChar = c;\n                }\n            }\n\n            if (bestChar != old) {\n                best[pos] = bestChar;\n                bestVal = localBest;\n                improved = true;\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n    auto endTime = startTime + chrono::milliseconds(1850);\n\n    cin >> si_ >> sj_ >> ti_ >> tj_ >> pforget;\n    for (int i = 0; i < N; i++) cin >> hwall[i];\n    for (int i = 0; i < N - 1; i++) cin >> vwall[i];\n\n    rng.seed(\n        si_ * 1000003u +\n        sj_ * 9176u +\n        ti_ * 19260817u +\n        tj_ * 998244353u +\n        (unsigned)(pforget * 1000)\n    );\n\n    buildGraph();\n\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    bfsFrom(t, distT);\n    bfsFrom(s, distS);\n\n    vector<string> candidates;\n\n    string sp = shortestPath(s, t);\n    if (!sp.empty()) {\n        candidates.push_back(sp);\n        candidates.push_back(repeatWhole(sp));\n\n        for (int r = 2; r <= 10; r++) {\n            candidates.push_back(repeatChars(sp, r));\n        }\n\n        for (int trial = 0; trial < 60; trial++) {\n            string rsp = shortestPath(s, t, true);\n            if (!rsp.empty()) {\n                candidates.push_back(rsp);\n                candidates.push_back(repeatChars(rsp, 2 + rng() % 6));\n                candidates.push_back(repeatWhole(rsp));\n            }\n        }\n    }\n\n    for (int r = 1; r <= 10; r++) {\n        candidates.push_back(distDescentPath(r, false));\n        for (int k = 0; k < 8; k++) {\n            candidates.push_back(distDescentPath(r, true));\n        }\n    }\n\n    vector<double> temps = {0.0, 0.02, 0.05, 0.1, 0.2, 0.4, 0.8, 1.5, 3.0};\n    vector<double> penalties = {0.0, 0.05, 0.15, 0.3, 0.7, 1.5, 3.0};\n    vector<double> bonuses = {0.2, 0.5, 1.0, 2.0, 4.0};\n\n    for (double temp : temps) {\n        for (double pen : penalties) {\n            for (double bonus : bonuses) {\n                candidates.push_back(greedyDistribution(temp, pen, bonus));\n            }\n        }\n    }\n\n    // Beam search candidates. Small beam to stay fast.\n    candidates.push_back(beamSearchRoute(8, 120, 1.0, 0.03));\n    candidates.push_back(beamSearchRoute(10, 150, 1.0, 0.02));\n    candidates.push_back(beamSearchRoute(12, 200, 1.0, 0.015));\n\n    // Waypoint candidates.\n    vector<int> cells(V);\n    iota(cells.begin(), cells.end(), 0);\n\n    sort(cells.begin(), cells.end(), [&](int a, int b) {\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n\n        int ascore = distS[a] + distT[a] + abs(ai - 10) + abs(aj - 10);\n        int bscore = distS[b] + distT[b] + abs(bi - 10) + abs(bj - 10);\n        return ascore < bscore;\n    });\n\n    for (int idx = 0; idx < min(V, 100); idx++) {\n        int mid = cells[idx];\n\n        string a = shortestPath(s, mid, true);\n        string b = shortestPath(mid, t, true);\n\n        if (a.empty() || b.empty()) continue;\n\n        string path = a + b;\n        if ((int)path.size() > MAXL) path.resize(MAXL);\n\n        candidates.push_back(path);\n        candidates.push_back(repeatWhole(path));\n\n        for (int r = 2; r <= 5; r++) {\n            candidates.push_back(repeatChars(path, r));\n        }\n    }\n\n    // Simple biased random strings.\n    for (int trial = 0; trial < 300; trial++) {\n        string r;\n        int len = 80 + rng() % 121;\n        for (int i = 0; i < len; i++) {\n            r.push_back(randomBiasedChar());\n        }\n        candidates.push_back(r);\n    }\n\n    string best = sp.empty() ? string(\"D\") : sp;\n    double bestVal = evaluate(best);\n\n    // Evaluate generated candidates.\n    for (string cand : candidates) {\n        if (chrono::steady_clock::now() >= endTime) break;\n\n        if (cand.empty()) continue;\n        if ((int)cand.size() > MAXL) cand.resize(MAXL);\n\n        double val = evaluate(cand);\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n    }\n\n    // Deterministic improvement on best.\n    auto improveEnd = startTime + chrono::milliseconds(1450);\n    deterministicSingleCharImprove(best, bestVal, improveEnd);\n\n    // Random hill climbing / simulated mutation.\n    int stagnant = 0;\n    while (chrono::steady_clock::now() < endTime) {\n        double strength = 1.0 + min(20, stagnant / 20);\n        string cand = mutateString(best, strength);\n        double val = evaluate(cand);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n            stagnant = 0;\n        } else {\n            stagnant++;\n        }\n\n        // Occasionally mutate a repeated shortest path, to escape local optimum.\n        if (stagnant % 200 == 199 && !sp.empty()) {\n            string base;\n            int mode = rng() % 3;\n            if (mode == 0) base = repeatChars(sp, 2 + rng() % 8);\n            else if (mode == 1) base = repeatWhole(sp);\n            else base = greedyDistribution(0.5, 0.5, 1.0);\n\n            string cand2 = mutateString(base, 10);\n            double val2 = evaluate(cand2);\n            if (val2 > bestVal) {\n                bestVal = val2;\n                best = cand2;\n                stagnant = 0;\n            }\n        }\n    }\n\n    if (best.empty()) best = \"D\";\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n\n    cout << best << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N * 4;\n\nint to_dir[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\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) {\n        return (int)(next_u64() % n);\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint rotate_state(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (0 <= t && t <= 3) t = (t + 1) & 3;\n        else if (t == 4) t = 5;\n        else if (t == 5) t = 4;\n        else if (t == 6) t = 7;\n        else if (t == 7) t = 6;\n    }\n    return t;\n}\n\nint norm_pair(int a, int b) {\n    if (a > b) swap(a, b);\n    return a * 4 + b;\n}\n\nbool state_has_pair(int t, int a, int b) {\n    int p = norm_pair(a, b);\n    for (int d = 0; d < 4; d++) {\n        if (to_dir[t][d] != -1) {\n            int q = norm_pair(d, to_dir[t][d]);\n            if (p == q) return true;\n        }\n    }\n    return false;\n}\n\nint rotation_for_pair(int base, int a, int b) {\n    for (int r = 0; r < 4; r++) {\n        int t = rotate_state(base, r);\n        if (state_has_pair(t, a, b)) return r;\n    }\n    return -1;\n}\n\nstruct Rect {\n    int r1, c1, r2, c2;\n    int len;\n    uint64_t mask[15]; // 900 bits\n};\n\nstruct Solver {\n    vector<string> s;\n    array<int, N * N> base{};\n    array<int, N * N> rot{};\n    array<int, N * N> tile{};\n    array<int, N * N> best_rot{};\n    array<int, N * N> fixed_cell{};\n    XorShift rng;\n\n    int id(int i, int j, int d) const {\n        return ((i * N + j) << 2) | d;\n    }\n\n    tuple<int,int,int> decode(int x) const {\n        int d = x & 3;\n        x >>= 2;\n        return {x / N, x % N, d};\n    }\n\n    int nxt(int x) const {\n        auto [i, j, d] = decode(x);\n        int t = tile[i * N + j];\n        int d2 = to_dir[t][d];\n        if (d2 == -1) return -1;\n        int ni = i + di[d2], nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n        return id(ni, nj, (d2 + 2) & 3);\n    }\n\n    long long evaluate() const {\n        static int state[V], seen[V], dep[V];\n\n        for (int i = 0; i < V; i++) {\n            state[i] = 0;\n            seen[i] = -1;\n            dep[i] = 0;\n        }\n\n        vector<int> loops;\n        loops.reserve(32);\n\n        for (int st = 0; st < V; st++) {\n            if (state[st]) continue;\n\n            int cur = st;\n            vector<int> path;\n            path.reserve(256);\n\n            while (true) {\n                if (cur == -1) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 2) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 1) {\n                    if (seen[cur] == st) {\n                        int len = (int)path.size() - dep[cur];\n                        if (len > 0) loops.push_back(len);\n                    }\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n\n                state[cur] = 1;\n                seen[cur] = st;\n                dep[cur] = (int)path.size();\n                path.push_back(cur);\n                cur = nxt(cur);\n            }\n        }\n\n        if ((int)loops.size() <= 1) return 0;\n        nth_element(loops.begin(), loops.begin(), loops.end(), greater<int>());\n        int a = loops[0];\n        nth_element(loops.begin() + 1, loops.begin() + 1, loops.end(), greater<int>());\n        int b = loops[1];\n        return 1LL * a * b;\n    }\n\n    void rebuild_tile() {\n        for (int i = 0; i < N * N; i++) {\n            tile[i] = rotate_state(base[i], rot[i]);\n        }\n    }\n\n    bool desired_pair_for_rect(const Rect& rc, int i, int j, int &a, int &b) const {\n        bool top = (i == rc.r1);\n        bool bottom = (i == rc.r2);\n        bool left = (j == rc.c1);\n        bool right = (j == rc.c2);\n\n        if (!top && !bottom && !left && !right) return false;\n\n        if (top && left) {\n            a = 2; b = 3; // right-down\n        } else if (top && right) {\n            a = 0; b = 3; // left-down\n        } else if (bottom && left) {\n            a = 1; b = 2; // up-right\n        } else if (bottom && right) {\n            a = 0; b = 1; // left-up\n        } else if (top || bottom) {\n            a = 0; b = 2; // horizontal\n        } else {\n            a = 1; b = 3; // vertical\n        }\n        return true;\n    }\n\n    bool build_rect(int r1, int c1, int r2, int c2, Rect &rc) const {\n        if (r2 <= r1 || c2 <= c1) return false;\n\n        rc.r1 = r1; rc.c1 = c1; rc.r2 = r2; rc.c2 = c2;\n        rc.len = 2 * ((r2 - r1) + (c2 - c1));\n        memset(rc.mask, 0, sizeof(rc.mask));\n\n        for (int i = r1; i <= r2; i++) {\n            for (int j = c1; j <= c2; j++) {\n                int a, b;\n                if (!desired_pair_for_rect(rc, i, j, a, b)) continue;\n                int idx = i * N + j;\n                if (rotation_for_pair(base[idx], a, b) == -1) return false;\n                rc.mask[idx >> 6] |= 1ULL << (idx & 63);\n            }\n        }\n        return true;\n    }\n\n    bool disjoint(const Rect& a, const Rect& b) const {\n        for (int k = 0; k < 15; k++) {\n            if (a.mask[k] & b.mask[k]) return false;\n        }\n        return true;\n    }\n\n    void apply_rect(const Rect& rc) {\n        for (int i = rc.r1; i <= rc.r2; i++) {\n            for (int j = rc.c1; j <= rc.c2; j++) {\n                int a, b;\n                if (!desired_pair_for_rect(rc, i, j, a, b)) continue;\n                int idx = i * N + j;\n                int r = rotation_for_pair(base[idx], a, b);\n                if (r >= 0) {\n                    rot[idx] = r;\n                    fixed_cell[idx] = 1;\n                }\n            }\n        }\n    }\n\n    void fill_random_free() {\n        for (int i = 0; i < N * N; i++) {\n            if (fixed_cell[i]) continue;\n            int maxr = (base[i] <= 3 ? 4 : 2);\n            rot[i] = rng.next_int(maxr);\n        }\n        rebuild_tile();\n    }\n\n    void construct_rect_solution() {\n        vector<Rect> rects;\n\n        // Enumerate many rectangles. Smallest side 2 is allowed.\n        for (int r1 = 0; r1 < N; r1++) {\n            for (int r2 = r1 + 1; r2 < N; r2++) {\n                for (int c1 = 0; c1 < N; c1++) {\n                    for (int c2 = c1 + 1; c2 < N; c2++) {\n                        int len = 2 * ((r2 - r1) + (c2 - c1));\n                        if (len < 16) continue;\n                        Rect rc;\n                        if (build_rect(r1, c1, r2, c2, rc)) {\n                            rects.push_back(rc);\n                        }\n                    }\n                }\n            }\n        }\n\n        sort(rects.begin(), rects.end(), [](const Rect& a, const Rect& b) {\n            return a.len > b.len;\n        });\n\n        // Limit candidates for pair search to save time.\n        if ((int)rects.size() > 2500) rects.resize(2500);\n\n        long long best_prod = -1;\n        int bi = -1, bj = -1;\n\n        for (int i = 0; i < (int)rects.size(); i++) {\n            if (1LL * rects[i].len * rects[i].len < best_prod) break;\n            for (int j = i + 1; j < (int)rects.size(); j++) {\n                long long prod = 1LL * rects[i].len * rects[j].len;\n                if (prod <= best_prod) break;\n                if (disjoint(rects[i], rects[j])) {\n                    best_prod = prod;\n                    bi = i;\n                    bj = j;\n                    break;\n                }\n            }\n        }\n\n        fixed_cell.fill(0);\n        rot.fill(0);\n\n        if (bi != -1) {\n            apply_rect(rects[bi]);\n            apply_rect(rects[bj]);\n        }\n\n        fill_random_free();\n    }\n\n    void improve_free_cells(double until_sec, const Timer& timer) {\n        long long cur = evaluate();\n        long long best = cur;\n        best_rot = rot;\n\n        int iter = 0;\n        while (timer.elapsed() < until_sec) {\n            iter++;\n\n            int p = rng.next_int(N * N);\n            if (fixed_cell[p]) continue;\n\n            int oldr = rot[p];\n            int oldt = tile[p];\n\n            int maxr = (base[p] <= 3 ? 4 : 2);\n            int nr = rng.next_int(maxr);\n            if (nr == oldr) nr = (nr + 1) % maxr;\n\n            rot[p] = nr;\n            tile[p] = rotate_state(base[p], nr);\n\n            long long ns = evaluate();\n            long long diff = ns - cur;\n\n            double progress = timer.elapsed() / until_sec;\n            double temp = 2000.0 * (1.0 - progress) + 5.0;\n\n            bool accept = false;\n            if (diff >= 0) accept = true;\n            else if (rng.next_double() < exp((double)diff / temp)) accept = true;\n\n            if (accept) {\n                cur = ns;\n                if (cur > best) {\n                    best = cur;\n                    best_rot = rot;\n                }\n            } else {\n                rot[p] = oldr;\n                tile[p] = oldt;\n            }\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n    }\n\n    void solve() {\n        s.resize(N);\n        for (int i = 0; i < N; i++) cin >> s[i];\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                base[i * N + j] = s[i][j] - '0';\n            }\n        }\n\n        Timer timer;\n\n        construct_rect_solution();\n\n        long long best_score = evaluate();\n        best_rot = rot;\n\n        // Try several random fills while keeping the guaranteed rectangles.\n        while (timer.elapsed() < 0.35) {\n            auto saved_fixed = fixed_cell;\n            fill_random_free();\n            long long sc = evaluate();\n            if (sc > best_score) {\n                best_score = sc;\n                best_rot = rot;\n            }\n            fixed_cell = saved_fixed;\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n\n        improve_free_cells(1.90, timer);\n\n        string ans;\n        ans.reserve(N * N);\n        for (int i = 0; i < N * N; i++) {\n            ans.push_back(char('0' + rot[i]));\n        }\n        cout << ans << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer{ chrono::steady_clock::time_point s=chrono::steady_clock::now(); double elapsed(){return chrono::duration<double>(chrono::steady_clock::now()-s).count();}};\nint N,Tlim,M;\nvector<unsigned char> initb;\nmt19937 rng(1234567);\n\nint hv(char c){return c<='9'?c-'0':c-'a'+10;}\nstruct DSU{ vector<int> p,z; DSU(int n=0){init(n);} void init(int n){p.resize(n);z.assign(n,1);iota(p.begin(),p.end(),0);} int f(int x){while(p[x]!=x){p[x]=p[p[x]];x=p[x];}return x;} bool uni(int a,int b){a=f(a);b=f(b); if(a==b)return false; if(z[a]<z[b])swap(a,b); p[b]=a; z[a]+=z[b]; return true;}};\nstruct Ev{int lt,lc,e,cy,tc,co,iso;};\n\nEv evalb(const vector<unsigned char>& b){\n    DSU d(M); int edges=0,cy=0; bool act[105];\n    for(int i=0;i<M;i++) act[i]=b[i]!=0;\n    for(int r=0;r<N;r++)for(int c=0;c<N;c++){\n        int id=r*N+c; if(!act[id])continue; int v=b[id];\n        if(c+1<N){int ni=id+1; if(act[ni]&&(v&4)&&(b[ni]&1)){edges++; if(!d.uni(id,ni))cy++;}}\n        if(r+1<N){int ni=id+N; if(act[ni]&&(v&8)&&(b[ni]&2)){edges++; if(!d.uni(id,ni))cy++;}}\n    }\n    int vc[105]={},ec[105]={};\n    for(int i=0;i<M;i++) if(act[i]) vc[d.f(i)]++;\n    for(int r=0;r<N;r++)for(int c=0;c<N;c++){\n        int id=r*N+c; if(!act[id])continue; int v=b[id];\n        if(c+1<N){int ni=id+1; if(act[ni]&&(v&4)&&(b[ni]&1)) ec[d.f(id)]++;}\n        if(r+1<N){int ni=id+N; if(act[ni]&&(v&8)&&(b[ni]&2)) ec[d.f(id)]++;}\n    }\n    Ev e{0,0,edges,cy,0,0,0};\n    for(int i=0;i<M;i++)if(vc[i]){\n        e.co++; e.lc=max(e.lc,vc[i]); if(vc[i]==1)e.iso++;\n        if(ec[i]==vc[i]-1){e.tc++; e.lt=max(e.lt,vc[i]);}\n    }\n    return e;\n}\nint offscore(const vector<unsigned char>& b,int k){ Ev e=evalb(b); if(e.lt==M-1)return 1000000000-k*1000; return e.lt*1000000; }\nchar opp(char c){ if(c=='U')return'D'; if(c=='D')return'U'; if(c=='L')return'R'; if(c=='R')return'L'; return'?';}\nbool apply(vector<unsigned char>& b,int& emp,char m){\n    int r=emp/N,c=emp%N,nr=r,nc=c;\n    if(m=='U')nr--; if(m=='D')nr++; if(m=='L')nc--; if(m=='R')nc++;\n    if(nr<0||nr>=N||nc<0||nc>=N)return false;\n    int np=nr*N+nc; swap(b[emp],b[np]); emp=np; return true;\n}\nstring keyb(const vector<unsigned char>& b,int emp){\n    string s; s.resize(M+1); for(int i=0;i<M;i++)s[i]=char(b[i]); s[M]=char(emp); return s;\n}\nstruct State{vector<unsigned char>b; int emp; string p; char last; int sc;};\nstruct Res{vector<unsigned char>b; int emp; string ans; int score;};\n\nint hscore(const Ev& e,int emp,int plen,int d,int mode){\n    int sc=e.lt*1000000;\n    if(mode==0){\n        sc+=e.lc*18000+e.e*4500-e.cy*45000-e.co*1800-e.iso*1200+e.tc*1200;\n    }else if(mode==1){\n        sc+=e.lc*26000+e.e*3000-e.cy*70000-e.co*1200-e.iso*800+e.tc*2500;\n    }else{\n        sc+=e.lc*10000+e.e*8000-e.cy*25000-e.co*2500-e.iso*1800+e.tc*800;\n    }\n    if(e.lt==M-1) sc+=500000000-(plen+d)*8000;\n    else sc-=d*20;\n    int r=emp/N,c=emp%N;\n    sc-=(abs(r-(N-1))+abs(c-(N-1)))*100;\n    return sc;\n}\nRes beam(const vector<unsigned char>& sb,int se,const string& pref,double endt,Timer& tim,int mode,int bwscale){\n    Res best{sb,se,pref,offscore(sb,pref.size())};\n    State st{sb,se,\"\",'?',0}; st.sc=hscore(evalb(sb),se,pref.size(),0,mode);\n    vector<State> beam{move(st)};\n    int base = (N==6?1500:N==7?1050:N==8?700:N==9?450:310);\n    int BW=max(70,base*bwscale/100);\n    if(!pref.empty()) BW=max(60,BW*2/3);\n    char mv[4]={'U','D','L','R'}; int dr[4]={-1,1,0,0},dc[4]={0,0,-1,1};\n    int maxD=Tlim-(int)pref.size();\n    for(int dep=0;dep<maxD;dep++){\n        if(tim.elapsed()>endt)break;\n        vector<State> cand; cand.reserve(beam.size()*4);\n        for(auto &s:beam){\n            int r=s.emp/N,c=s.emp%N;\n            for(int k=0;k<4;k++){\n                char m=mv[k];\n                if(s.last!='?'&&opp(s.last)==m) continue;\n                int nr=r+dr[k],nc=c+dc[k]; if(nr<0||nr>=N||nc<0||nc>=N)continue;\n                int np=nr*N+nc;\n                State ns; ns.b=s.b; swap(ns.b[s.emp],ns.b[np]); ns.emp=np; ns.p=s.p; ns.p.push_back(m); ns.last=m;\n                Ev e=evalb(ns.b); ns.sc=hscore(e,ns.emp,pref.size(),ns.p.size(),mode);\n                int os = (e.lt==M-1?1000000000-(int)(pref.size()+ns.p.size())*1000:e.lt*1000000);\n                if(os>best.score){best.score=os; best.b=ns.b; best.emp=ns.emp; best.ans=pref+ns.p;}\n                cand.push_back(move(ns));\n            }\n        }\n        if(cand.empty())break;\n        int keep=min(BW,(int)cand.size());\n        nth_element(cand.begin(),cand.begin()+keep,cand.end(),[](auto&a,auto&b){return a.sc>b.sc;});\n        cand.resize(keep);\n        sort(cand.begin(),cand.end(),[](auto&a,auto&b){return a.sc>b.sc;});\n        unordered_set<string> seen; seen.reserve(keep*3);\n        vector<State> nb; nb.reserve(keep);\n        for(auto &s:cand){ string k=keyb(s.b,s.emp); if(seen.insert(k).second){nb.push_back(move(s)); if((int)nb.size()>=keep)break;}}\n        beam.swap(nb);\n    }\n    return best;\n}\nstring rw(vector<unsigned char>& b,int& e,int len){\n    string p; char last='?'; char mv[4]={'U','D','L','R'};\n    for(int i=0;i<len;i++){\n        vector<char> le; int r=e/N,c=e%N;\n        for(char m:mv){ if(last!='?'&&opp(last)==m)continue; int nr=r,nc=c; if(m=='U')nr--; if(m=='D')nr++; if(m=='L')nc--; if(m=='R')nc++; if(0<=nr&&nr<N&&0<=nc&&nc<N)le.push_back(m);}\n        if(le.empty())break;\n        char m=le[uniform_int_distribution<int>(0,(int)le.size()-1)(rng)];\n        apply(b,e,m); p.push_back(m); last=m;\n    }\n    return p;\n}\n\nint main(){\n    ios::sync_with_stdio(false); cin.tie(nullptr);\n    cin>>N>>Tlim; M=N*N; initb.assign(M,0); int emp=0;\n    for(int i=0;i<N;i++){string s;cin>>s;for(int j=0;j<N;j++){initb[i*N+j]=hv(s[j]); if(initb[i*N+j]==0)emp=i*N+j;}}\n    Timer tim;\n    Res gb{initb,emp,\"\",offscore(initb,0)};\n    vector<tuple<vector<unsigned char>,int,string,int,int>> starts;\n    starts.push_back({initb,emp,\"\",0,120});\n    int rest=(N<=6?8:N==7?7:N==8?5:4);\n    for(int i=0;i<rest;i++){\n        vector<unsigned char>b=initb; int e=emp;\n        int len=(i%4+1)*N/1;\n        string p=rw(b,e,len);\n        starts.push_back({b,e,p,i%3,90});\n    }\n    int idx=0;\n    for(auto &tu:starts){\n        if(tim.elapsed()>2.82)break;\n        auto [b,e,p,mode,sc]=tu;\n        double remain=2.86;\n        Res r=beam(b,e,p,remain,tim,mode,sc);\n        if(r.score>gb.score) gb=r;\n        idx++;\n    }\n    if((int)gb.ans.size()>Tlim) gb.ans.resize(Tlim);\n    cout<<gb.ans<<\"\\n\";\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n\n    vector<int> a(11);\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // ----------------------------------------------------------------------\n    // Heuristic:\n    // Use 100 parallel-ish grid cuts: vertical and horizontal quantile cuts.\n    //\n    // Since strawberries are uniformly random, a rectangular grid tends to\n    // create many small cells.  We choose the number of vertical / horizontal\n    // strips so that the average strawberries per cell is around the weighted\n    // average target piece size.  Then cut at quantiles so each strip contains\n    // a roughly equal number of strawberries.\n    //\n    // This is a simple, robust baseline for AHC012.\n    // ----------------------------------------------------------------------\n\n    int totalAttendees = 0;\n    for (int d = 1; d <= 10; d++) totalAttendees += a[d];\n\n    double avgTarget = (double)N / max(1, totalAttendees); // about 1..10\n    int desiredCells = max(1, (int)round((double)N / avgTarget)); // roughly attendees count\n    desiredCells = min(desiredCells, K * K / 4);\n\n    // Need (vx+1)*(hy+1) cells, vx+hy<=100.\n    // Select vx,hy minimizing difference from desiredCells and balanced aspect.\n    int bestV = 50, bestH = 50;\n    double bestCost = 1e100;\n    for (int vx = 0; vx <= K; vx++) {\n        for (int hy = 0; hy + vx <= K; hy++) {\n            int cells = (vx + 1) * (hy + 1);\n            double cost = abs(cells - desiredCells);\n            cost += 0.05 * abs(vx - hy);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestV = vx;\n                bestH = hy;\n            }\n        }\n    }\n\n    vector<int> xs, ys;\n    xs.reserve(N);\n    ys.reserve(N);\n    for (auto &pt : p) {\n        xs.push_back(pt.x);\n        ys.push_back(pt.y);\n    }\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    vector<array<int,4>> lines;\n\n    auto add_vertical = [&](int x) {\n        // line x = const\n        lines.push_back({x, -1000000000, x, 1000000000});\n    };\n    auto add_horizontal = [&](int y) {\n        // line y = const\n        lines.push_back({-1000000000, y, 1000000000, y});\n    };\n\n    // Quantile cuts between consecutive coordinates.\n    for (int i = 1; i <= bestV; i++) {\n        int idx = (long long)N * i / (bestV + 1);\n        if (idx <= 0 || idx >= N) continue;\n        int x1 = xs[idx - 1], x2 = xs[idx];\n        int cut;\n        if (x1 == x2) cut = x1 + 1;\n        else cut = (x1 + x2) / 2;\n        add_vertical(cut);\n    }\n\n    for (int i = 1; i <= bestH; i++) {\n        int idx = (long long)N * i / (bestH + 1);\n        if (idx <= 0 || idx >= N) continue;\n        int y1 = ys[idx - 1], y2 = ys[idx];\n        int cut;\n        if (y1 == y2) cut = y1 + 1;\n        else cut = (y1 + y2) / 2;\n        add_horizontal(cut);\n    }\n\n    // Fallback / improvement: if duplicate quantile cuts reduced the count,\n    // add several diagonal cuts through the origin with different slopes.\n    // This increases fragmentation without much risk.\n    int diagId = 0;\n    while ((int)lines.size() < K && diagId < 200) {\n        double theta = M_PI * diagId / 200.0;\n        int dx = (int)round(cos(theta) * 1000000000.0);\n        int dy = (int)round(sin(theta) * 1000000000.0);\n        if (dx == 0 && dy == 0) {\n            diagId++;\n            continue;\n        }\n        lines.push_back({-dx, -dy, dx, dy});\n        diagId++;\n    }\n\n    if ((int)lines.size() > K) lines.resize(K);\n\n    cout << lines.size() << '\\n';\n    for (auto &ln : lines) {\n        cout << ln[0] << ' ' << ln[1] << ' ' << ln[2] << ' ' << ln[3] << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    int score;\n    int lenSum;\n};\n\nint N, M;\nvector<vector<unsigned char>> dotGrid;\nset<tuple<int,int,int,int>> usedSeg;\nvector<Move> answerMoves;\nvector<vector<int>> W;\n\nchrono::steady_clock::time_point startTime;\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ntuple<int,int,int,int> segKey(int x1, int y1, int x2, int y2) {\n    if (x1 > x2 || (x1 == x2 && y1 > y2)) {\n        swap(x1, x2);\n        swap(y1, y2);\n    }\n    return {x1, y1, x2, y2};\n}\n\nint gcdAbs(int a, int b) {\n    return std::gcd(abs(a), abs(b));\n}\n\nbool checkSideNoDotAndNoSeg(int ax, int ay, int bx, int by,\n                            int ex1, int ey1,\n                            int ex2, int ey2,\n                            int ex3, int ey3) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n        if (usedSeg.count(segKey(x, y, nx, ny))) return false;\n    }\n\n    for (int i = 1; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n\n        if ((x == ex1 && y == ey1) ||\n            (x == ex2 && y == ey2) ||\n            (x == ex3 && y == ey3)) {\n            continue;\n        }\n\n        if (dotGrid[x][y]) return false;\n    }\n\n    return true;\n}\n\nvoid addSideSegments(int ax, int ay, int bx, int by) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n        usedSeg.insert(segKey(x, y, nx, ny));\n    }\n}\n\nbool legalMove(const Move& mv) {\n    int x1 = mv.x1, y1 = mv.y1;\n    int x2 = mv.x2, y2 = mv.y2;\n    int x3 = mv.x3, y3 = mv.y3;\n    int x4 = mv.x4, y4 = mv.y4;\n\n    if (!inside(x1, y1) || !inside(x2, y2) || !inside(x3, y3) || !inside(x4, y4)) return false;\n    if (dotGrid[x1][y1]) return false;\n    if (!dotGrid[x2][y2] || !dotGrid[x3][y3] || !dotGrid[x4][y4]) return false;\n\n    if (!checkSideNoDotAndNoSeg(x1, y1, x2, y2, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x2, y2, x3, y3, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x3, y3, x4, y4, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x4, y4, x1, y1, x2, y2, x3, y3, x4, y4)) return false;\n\n    return true;\n}\n\nvoid applyMove(const Move& mv) {\n    dotGrid[mv.x1][mv.y1] = 1;\n\n    addSideSegments(mv.x1, mv.y1, mv.x2, mv.y2);\n    addSideSegments(mv.x2, mv.y2, mv.x3, mv.y3);\n    addSideSegments(mv.x3, mv.y3, mv.x4, mv.y4);\n    addSideSegments(mv.x4, mv.y4, mv.x1, mv.y1);\n\n    answerMoves.push_back(mv);\n}\n\nvector<pair<int,int>> dirs = {\n    {1, 0}, {0, 1}, {-1, 0}, {0, -1},\n    {1, 1}, {-1, 1}, {-1, -1}, {1, -1}\n};\n\nlong long moveValue(const Move& mv) {\n    // Moderate penalty: only used as tie-break / small correction.\n    // Weight range is roughly up to 1800, length up to about 120.\n    return 10000LL * mv.score - 120LL * mv.lenSum;\n}\n\nbool findBestMove(Move& best) {\n    bool found = false;\n    long long bestVal = LLONG_MIN;\n\n    vector<pair<int,int>> dots;\n    dots.reserve(N * N);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            if (dotGrid[x][y]) dots.push_back({x, y});\n        }\n    }\n\n    for (auto [x3, y3] : dots) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (elapsed > 4.82) return found;\n\n        for (auto [dx, dy] : dirs) {\n            int rdx = -dy;\n            int rdy = dx;\n\n            for (int sign : {-1, 1}) {\n                int bx = rdx * sign;\n                int by = rdy * sign;\n\n                for (int l1 = 1; l1 < N; l1++) {\n                    int x2 = x3 + dx * l1;\n                    int y2 = y3 + dy * l1;\n                    if (!inside(x2, y2)) break;\n                    if (!dotGrid[x2][y2]) continue;\n\n                    for (int l2 = 1; l2 < N; l2++) {\n                        int x4 = x3 + bx * l2;\n                        int y4 = y3 + by * l2;\n                        if (!inside(x4, y4)) break;\n                        if (!dotGrid[x4][y4]) continue;\n\n                        int x1 = x2 + bx * l2;\n                        int y1 = y2 + by * l2;\n                        if (!inside(x1, y1)) break;\n                        if (dotGrid[x1][y1]) continue;\n\n                        Move mv;\n                        mv.x1 = x1; mv.y1 = y1;\n                        mv.x2 = x2; mv.y2 = y2;\n                        mv.x3 = x3; mv.y3 = y3;\n                        mv.x4 = x4; mv.y4 = y4;\n                        mv.score = W[x1][y1];\n                        mv.lenSum = l1 + l2;\n\n                        if (!legalMove(mv)) continue;\n\n                        long long val = moveValue(mv);\n\n                        // Prefer slightly shorter rectangles if value is equal.\n                        if (!found ||\n                            val > bestVal ||\n                            (val == bestVal && mv.lenSum < best.lenSum)) {\n                            found = true;\n                            bestVal = val;\n                            best = mv;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return found;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    dotGrid.assign(N, vector<unsigned char>(N, 0));\n    W.assign(N, vector<int>(N, 0));\n\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            int dx = x - c;\n            int dy = y - c;\n            W[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        dotGrid[x][y] = 1;\n    }\n\n    startTime = chrono::steady_clock::now();\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (elapsed > 4.82) break;\n\n        Move best;\n        if (!findBestMove(best)) break;\n\n        applyMove(best);\n    }\n\n    cout << answerMoves.size() << '\\n';\n    for (auto &mv : answerMoves) {\n        cout << mv.x1 << ' ' << mv.y1 << ' '\n             << mv.x2 << ' ' << mv.y2 << ' '\n             << mv.x3 << ' ' << mv.y3 << ' '\n             << mv.x4 << ' ' << mv.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int T = 100;\n\nint f[T];\nint targetColor[100];\nint cntFlavor[4];\n\nconst char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    inline uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n};\n\nRNG global_rng(987654321);\n\nstruct Board {\n    unsigned char a[100];\n};\n\ninline void clear_board(Board& b) {\n    memset(b.a, 0, sizeof(b.a));\n}\n\nvoid tilt_board(const Board& src, Board& dst, int dir) {\n    memset(dst.a, 0, sizeof(dst.a));\n\n    if (dir == 0) { // F\n        for (int c = 0; c < N; c++) {\n            int w = 0;\n            for (int r = 0; r < N; r++) {\n                int idx = r * 10 + c;\n                int v = src.a[idx];\n                if (v) dst.a[w++ * 10 + c] = (unsigned char)v;\n            }\n        }\n    } else if (dir == 1) { // B\n        for (int c = 0; c < N; c++) {\n            int w = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                int idx = r * 10 + c;\n                int v = src.a[idx];\n                if (v) dst.a[w-- * 10 + c] = (unsigned char)v;\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < N; r++) {\n            int w = 0;\n            int base = r * 10;\n            for (int c = 0; c < N; c++) {\n                int v = src.a[base + c];\n                if (v) dst.a[base + w++] = (unsigned char)v;\n            }\n        }\n    } else { // R\n        for (int r = 0; r < N; r++) {\n            int w = N - 1;\n            int base = r * 10;\n            for (int c = N - 1; c >= 0; c--) {\n                int v = src.a[base + c];\n                if (v) dst.a[base + w--] = (unsigned char)v;\n            }\n        }\n    }\n}\n\nvoid place_by_index(Board& b, int p, int flavor) {\n    int cnt = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b.a[i] == 0) {\n            cnt++;\n            if (cnt == p) {\n                b.a[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\ninline int empty_count(const Board& b) {\n    int e = 0;\n    for (int i = 0; i < 100; i++) if (b.a[i] == 0) e++;\n    return e;\n}\n\nvoid place_random(Board& b, int flavor, RNG& rng) {\n    int e = empty_count(b);\n    int p = rng.next_int(1, e);\n    place_by_index(b, p, flavor);\n}\n\nint component_score(const Board& b) {\n    bool vis[100] = {};\n    int q[100];\n    int score = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b.a[s] == 0 || vis[s]) continue;\n\n        int col = b.a[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            int r = v / 10;\n            int c = v % 10;\n\n            if (r > 0) {\n                int nv = v - 10;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (r < 9) {\n                int nv = v + 10;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (c > 0) {\n                int nv = v - 1;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (c < 9) {\n                int nv = v + 1;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n        }\n\n        score += sz * sz;\n    }\n\n    return score;\n}\n\ninline int edge_score(const Board& b) {\n    int s = 0;\n    for (int r = 0; r < N; r++) {\n        int base = r * 10;\n        for (int c = 0; c < N; c++) {\n            int idx = base + c;\n            int x = b.a[idx];\n            if (!x) continue;\n            if (r + 1 < N && b.a[idx + 10] == x) s++;\n            if (c + 1 < N && b.a[idx + 1] == x) s++;\n        }\n    }\n    return s;\n}\n\ninline int target_match_score(const Board& b) {\n    int s = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b.a[i] && b.a[i] == targetColor[i]) s++;\n    }\n    return s;\n}\n\ndouble target_neighbor_score(const Board& b) {\n    double s = 0.0;\n\n    for (int i = 0; i < 100; i++) {\n        int x = b.a[i];\n        if (!x) continue;\n\n        int r = i / 10;\n        int c = i % 10;\n\n        // Reward being near target-color cells, not only exactly on them.\n        for (int j = 0; j < 100; j++) {\n            if (targetColor[j] != x) continue;\n            int rr = j / 10;\n            int cc = j % 10;\n            int d = abs(r - rr) + abs(c - cc);\n            if (d <= 3) {\n                s += 4 - d;\n            }\n        }\n    }\n\n    return s;\n}\n\ndouble eval_board(const Board& b, int turn) {\n    double progress = turn * 0.01;\n\n    int comp = component_score(b);\n    int edge = edge_score(b);\n    int match = target_match_score(b);\n    double nearTarget = target_neighbor_score(b);\n\n    return comp * (10.0 + 38.0 * progress)\n         + edge * 18.0\n         + match * (90.0 * (1.0 - 0.3 * progress))\n         + nearTarget * (7.0 * (1.0 - 0.5 * progress));\n}\n\nint greedy_dir(const Board& b, int turn) {\n    int best = 0;\n    double bestVal = -1e100;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb;\n        tilt_board(b, nb, d);\n        double val = eval_board(nb, turn);\n\n        if (d == 0) val += 0.003;\n        if (d == 2) val += 0.002;\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\ndouble rollout_limited(Board b, int nextTurn, int horizon, RNG rng) {\n    int endTurn = min(T, nextTurn + horizon - 1);\n\n    for (int turn = nextTurn; turn <= endTurn; turn++) {\n        place_random(b, f[turn - 1], rng);\n\n        int gd = greedy_dir(b, turn);\n        Board nb;\n        tilt_board(b, nb, gd);\n        b = nb;\n    }\n\n    return eval_board(b, endTurn);\n}\n\nint choose_dir(const Board& current, int turn) {\n    int rollouts;\n    int horizon;\n\n    if (turn <= 18) {\n        rollouts = 7;\n        horizon = 30;\n    } else if (turn <= 38) {\n        rollouts = 6;\n        horizon = 26;\n    } else if (turn <= 58) {\n        rollouts = 5;\n        horizon = 22;\n    } else if (turn <= 78) {\n        rollouts = 4;\n        horizon = 16;\n    } else {\n        return greedy_dir(current, turn);\n    }\n\n    int bestDir = 0;\n    double bestVal = -1e100;\n\n    for (int d = 0; d < 4; d++) {\n        Board after;\n        tilt_board(current, after, d);\n\n        double sum = eval_board(after, turn) * 0.4;\n\n        for (int k = 0; k < rollouts; k++) {\n            uint64_t seed = global_rng.next_u64()\n                          ^ ((uint64_t)turn << 32)\n                          ^ ((uint64_t)d << 16)\n                          ^ (uint64_t)k;\n            RNG rr(seed);\n            sum += rollout_limited(after, turn + 1, horizon, rr);\n        }\n\n        double avg = sum / (rollouts + 0.4);\n\n        if (d == 0) avg += 0.01;\n        if (d == 2) avg += 0.005;\n\n        if (avg > bestVal) {\n            bestVal = avg;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nvoid build_target_board() {\n    vector<int> flavors = {1, 2, 3};\n\n    sort(flavors.begin(), flavors.end(), [&](int a, int b) {\n        return cntFlavor[a] > cntFlavor[b];\n    });\n\n    // Snake path. Consecutive blocks become connected compact-ish regions.\n    vector<int> path;\n    path.reserve(100);\n\n    for (int r = 0; r < N; r++) {\n        if (r % 2 == 0) {\n            for (int c = 0; c < N; c++) path.push_back(r * 10 + c);\n        } else {\n            for (int c = N - 1; c >= 0; c--) path.push_back(r * 10 + c);\n        }\n    }\n\n    int ptr = 0;\n    for (int fl : flavors) {\n        for (int k = 0; k < cntFlavor[fl]; k++) {\n            targetColor[path[ptr++]] = fl;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < T; i++) {\n        cin >> f[i];\n        cntFlavor[f[i]]++;\n    }\n\n    build_target_board();\n\n    Board cur;\n    clear_board(cur);\n\n    for (int turn = 1; turn <= T; turn++) {\n        int p;\n        if (!(cin >> p)) break;\n\n        place_by_index(cur, p, f[turn - 1]);\n\n        int dir = choose_dir(cur, turn);\n\n        Board nb;\n        tilt_board(cur, nb, dir);\n        cur = nb;\n\n        cout << DIR_CH[dir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint M, N;\ndouble EPS;\n\nstruct Code {\n    int a, b;                 // clique sizes, a >= b >= 0\n    string graph;\n    vector<double> edeg;      // expected sorted degrees desc\n    double eedges;\n    double edeg2;\n};\n\nint choose_N(int M, double e) {\n    if (e < 1e-12) {\n        int n = 4;\n        while (n * (n - 1) / 2 < M) n++;\n        return n;\n    }\n\n    // Two-clique codes benefit from large N under noise.\n    if (e <= 0.01) return max(8, min(100, M / 2 + 10));\n    if (e <= 0.03) return max(18, min(100, M / 2 + 18));\n    if (e <= 0.06) return max(30, min(100, M / 2 + 30));\n    if (e <= 0.10) return max(45, min(100, M / 2 + 45));\n    if (e <= 0.15) return max(65, min(100, M / 2 + 60));\n    return 100;\n}\n\nstring make_two_clique_graph(int a, int b) {\n    string s;\n    s.reserve(N * (N - 1) / 2);\n\n    int bStart = a;\n    int bEnd = a + b;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = false;\n            if (i < a && j < a) e = true;\n            if (bStart <= i && i < bEnd && bStart <= j && j < bEnd) e = true;\n            s.push_back(e ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nvector<int> parse_degrees_desc(const string& s) {\n    vector<int> d(N, 0);\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (s[p] == '1') {\n                d[i]++;\n                d[j]++;\n            }\n            p++;\n        }\n    }\n    sort(d.begin(), d.end(), greater<int>());\n    return d;\n}\n\nCode make_code(int a, int b) {\n    if (a < b) swap(a, b);\n\n    Code c;\n    c.a = a;\n    c.b = b;\n    c.graph = make_two_clique_graph(a, b);\n\n    int E = N * (N - 1) / 2;\n    int origEdges = a * (a - 1) / 2 + b * (b - 1) / 2;\n\n    c.eedges = (1.0 - EPS) * origEdges + EPS * (E - origEdges);\n\n    double base = EPS * (N - 1);\n    double coef = 1.0 - 2.0 * EPS;\n\n    c.edeg.clear();\n    c.edeg.reserve(N);\n\n    for (int i = 0; i < a; i++) c.edeg.push_back(base + coef * (a - 1));\n    for (int i = 0; i < b; i++) c.edeg.push_back(base + coef * (b - 1));\n    for (int i = 0; i < N - a - b; i++) c.edeg.push_back(base);\n\n    sort(c.edeg.begin(), c.edeg.end(), greater<double>());\n\n    c.edeg2 = 0;\n    for (double x : c.edeg) c.edeg2 += x * x;\n\n    return c;\n}\n\ndouble profile_distance(const Code& x, const Code& y) {\n    double degreeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N - 1))) + 1.0;\n    double edgeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N * (N - 1) / 2.0))) + 1.0;\n\n    double s = 0;\n    for (int i = 0; i < N; i++) {\n        double d = (x.edeg[i] - y.edeg[i]) / degreeSigma;\n        s += d * d;\n    }\n    s /= N;\n\n    double e = (x.eedges - y.eedges) / edgeSigma;\n    s += 2.0 * e * e;\n\n    double d2scale = max(10.0, N * N * degreeSigma);\n    double d2 = (x.edeg2 - y.edeg2) / d2scale;\n    s += 0.2 * d2 * d2;\n\n    return s;\n}\n\ndouble obs_distance(const vector<int>& deg, int obsEdges, double obsDeg2, const Code& c) {\n    double degreeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N - 1))) + 1.0;\n    double edgeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N * (N - 1) / 2.0))) + 1.0;\n\n    double s = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double d = (deg[i] - c.edeg[i]) / degreeSigma;\n        s += d * d;\n    }\n    s /= N;\n\n    double e = (obsEdges - c.eedges) / edgeSigma;\n    s += 2.5 * e * e;\n\n    double d2scale = max(10.0, N * N * degreeSigma);\n    double d2 = (obsDeg2 - c.edeg2) / d2scale;\n    s += 0.3 * d2 * d2;\n\n    // Plateau sums: compare top a and top a+b degrees.\n    if (c.a > 0) {\n        double topA = 0;\n        for (int i = 0; i < c.a; i++) topA += deg[i];\n\n        double expTopA = 0;\n        for (int i = 0; i < c.a; i++) expTopA += c.edeg[i];\n\n        double scale = max(1.0, sqrt((double)c.a) * degreeSigma);\n        double z = (topA - expTopA) / scale;\n        s += 0.7 * z * z;\n    }\n\n    if (c.a + c.b > 0 && c.a + c.b <= N) {\n        int r = c.a + c.b;\n        double topAB = 0;\n        for (int i = 0; i < r; i++) topAB += deg[i];\n\n        double expTopAB = 0;\n        for (int i = 0; i < r; i++) expTopAB += c.edeg[i];\n\n        double scale = max(1.0, sqrt((double)r) * degreeSigma);\n        double z = (topAB - expTopAB) / scale;\n        s += 0.5 * z * z;\n    }\n\n    return s;\n}\n\nvector<Code> build_codebook() {\n    vector<Code> cand;\n\n    // Candidate pairs. Avoid very tiny cliques at high noise.\n    int minClique;\n    if (EPS <= 0.03) minClique = 0;\n    else if (EPS <= 0.08) minClique = 3;\n    else if (EPS <= 0.15) minClique = 5;\n    else if (EPS <= 0.25) minClique = 7;\n    else if (EPS <= 0.35) minClique = 9;\n    else minClique = 11;\n\n    for (int a = minClique; a <= N; a++) {\n        for (int b = 0; b <= a; b++) {\n            if (a + b > N) continue;\n            if (b > 0 && b < minClique) continue;\n            if (a == 0 && b == 0) continue;\n\n            // Keep enough isolated vertices for baseline unless noise is tiny.\n            if (EPS >= 0.10 && N - a - b < 3) continue;\n\n            cand.push_back(make_code(a, b));\n        }\n    }\n\n    // Add empty graph candidate for low-noise / small M cases.\n    if (EPS <= 0.10) cand.push_back(make_code(0, 0));\n\n    // Sort by edge count / main clique size to get broad initial coverage.\n    sort(cand.begin(), cand.end(), [](const Code& x, const Code& y) {\n        if (x.eedges != y.eedges) return x.eedges < y.eedges;\n        if (x.a != y.a) return x.a < y.a;\n        return x.b < y.b;\n    });\n\n    vector<Code> selected;\n    selected.reserve(M);\n\n    // First pick low, high, and middle-like anchors.\n    if (!cand.empty()) {\n        selected.push_back(cand.front());\n        if ((int)selected.size() < M) selected.push_back(cand.back());\n        if ((int)selected.size() < M) selected.push_back(cand[cand.size() / 2]);\n    }\n\n    vector<double> mind(cand.size(), 1e100);\n\n    auto same_code = [](const Code& x, const Code& y) {\n        return x.a == y.a && x.b == y.b;\n    };\n\n    for (size_t i = 0; i < cand.size(); i++) {\n        for (auto &s : selected) {\n            if (same_code(cand[i], s)) mind[i] = -1;\n            else mind[i] = min(mind[i], profile_distance(cand[i], s));\n        }\n    }\n\n    while ((int)selected.size() < M) {\n        int best = -1;\n        double bestVal = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (mind[i] < 0) continue;\n\n            // Prefer useful density range, but mostly maximize minimum distance.\n            double val = mind[i];\n\n            // Mild penalty for too extreme full-size structure under high eps.\n            int iso = N - cand[i].a - cand[i].b;\n            if (EPS >= 0.20 && iso < 5) val *= 0.95;\n\n            if (val > bestVal) {\n                bestVal = val;\n                best = i;\n            }\n        }\n\n        if (best < 0) break;\n\n        selected.push_back(cand[best]);\n        mind[best] = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (mind[i] < 0) continue;\n            mind[i] = min(mind[i], profile_distance(cand[i], cand[best]));\n        }\n    }\n\n    // If something went wrong, fill with clique sizes.\n    for (int r = 1; (int)selected.size() < M && r <= N; r++) {\n        selected.push_back(make_code(r, 0));\n    }\n\n    // Reorder by edge count for a smoother message index.\n    sort(selected.begin(), selected.end(), [](const Code& x, const Code& y) {\n        if (x.eedges != y.eedges) return x.eedges < y.eedges;\n        if (x.a != y.a) return x.a < y.a;\n        return x.b < y.b;\n    });\n\n    if ((int)selected.size() > M) selected.resize(M);\n\n    return selected;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> M >> EPS;\n    N = choose_N(M, EPS);\n    int E = N * (N - 1) / 2;\n\n    if (EPS < 1e-12) {\n        cout << N << '\\n';\n        for (int k = 0; k < M; k++) {\n            string s(E, '0');\n            for (int i = 0; i < k; i++) s[i] = '1';\n            cout << s << '\\n';\n        }\n        cout.flush();\n\n        for (int q = 0; q < 100; q++) {\n            string H;\n            cin >> H;\n            int ones = 0;\n            for (char c : H) ones += (c == '1');\n            cout << min(M - 1, ones) << '\\n';\n            cout.flush();\n        }\n        return 0;\n    }\n\n    vector<Code> codebook = build_codebook();\n\n    cout << N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << codebook[k].graph << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        vector<int> deg = parse_degrees_desc(H);\n        int obsEdges = accumulate(deg.begin(), deg.end(), 0) / 2;\n\n        double obsDeg2 = 0;\n        for (int x : deg) obsDeg2 += 1.0 * x * x;\n\n        int best = 0;\n        double bestScore = 1e300;\n\n        for (int k = 0; k < M; k++) {\n            double sc = obs_distance(deg, obsEdges, obsDeg2, codebook[k]);\n            if (sc < bestScore) {\n                bestScore = sc;\n                best = k;\n            }\n        }\n\n        cout << best << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    double mx, my;\n};\n\nstatic uint64_t rng_state = 88172645463325252ull;\nuint64_t xorshift64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\nint rnd_int(int l, int r) {\n    return l + (int)(xorshift64() % (uint64_t)(r - l + 1));\n}\ndouble rnd01() {\n    return (xorshift64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> adj(N);\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 = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n\n    vector<double> X(N), Y(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    for (int i = 0; i < M; i++) {\n        edges[i].mx = (X[edges[i].u] + X[edges[i].v]) * 0.5;\n        edges[i].my = (Y[edges[i].u] + Y[edges[i].v]) * 0.5;\n    }\n\n    // ---------- Dijkstra utility ----------\n    const long long INF = (1LL << 60);\n    vector<int> banned(M, 0);\n    int banVersion = 1;\n\n    auto dijkstra = [&](int s, const vector<int>* rem) -> vector<long long> {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n        if (rem) {\n            for (int e : *rem) banned[e] = banVersion;\n        }\n\n        vector<long long> dist(N, INF);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != dist[u]) continue;\n\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n                long long nd = du + edges[ei].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pq.push({nd, v});\n                }\n            }\n        }\n        return dist;\n    };\n\n    // ---------- Approximate edge importance ----------\n    vector<double> imp(M, 1.0);\n\n    vector<int> landmarks;\n    {\n        vector<pair<double,int>> vals;\n        for (int i = 0; i < N; i++) vals.push_back({X[i] + Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i] - Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({Y[i], i});\n        sort(vals.begin(), vals.end());\n        landmarks.push_back(vals.front().second);\n        landmarks.push_back(vals.back().second);\n\n        int samples = min(N, 36);\n        while ((int)landmarks.size() < samples) landmarks.push_back(rnd_int(0, N - 1));\n\n        sort(landmarks.begin(), landmarks.end());\n        landmarks.erase(unique(landmarks.begin(), landmarks.end()), landmarks.end());\n    }\n\n    vector<long long> distTmp(N);\n    vector<int> parEdge(N);\n\n    for (int s : landmarks) {\n        fill(distTmp.begin(), distTmp.end(), INF);\n        fill(parEdge.begin(), parEdge.end(), -1);\n\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n        distTmp[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != distTmp[u]) continue;\n\n            for (auto [v, ei] : adj[u]) {\n                long long nd = du + edges[ei].w;\n                if (nd < distTmp[v]) {\n                    distTmp[v] = nd;\n                    parEdge[v] = ei;\n                    pq.push({nd, v});\n                }\n            }\n        }\n\n        for (int v = 0; v < N; v++) {\n            if (parEdge[v] >= 0) imp[parEdge[v]] += 1.0;\n        }\n    }\n\n    double maxImp = *max_element(imp.begin(), imp.end());\n    for (int i = 0; i < M; i++) {\n        imp[i] = sqrt(imp[i] / maxImp);\n        imp[i] += 0.12 * sqrt((double)edges[i].w / 1000000.0);\n    }\n\n    // ---------- Connectivity checker ----------\n    auto isConnectedDay = [&](const vector<int>& dayEdges) -> bool {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n        for (int e : dayEdges) banned[e] = banVersion;\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n        vis[0] = 1;\n        q.push(0);\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n        return cnt == N;\n    };\n\n    auto isConnectedWithExtra = [&](const vector<int>& dayEdges, int extra) -> bool {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n        for (int e : dayEdges) banned[e] = banVersion;\n        if (extra >= 0) banned[extra] = banVersion;\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n        vis[0] = 1;\n        q.push(0);\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n        return cnt == N;\n    };\n\n    // ---------- State ----------\n    vector<int> ans(M, -1), load(D, 0);\n    vector<double> dayImp(D, 0.0);\n    vector<vector<int>> dayEdges(D);\n    vector<vector<unsigned short>> dayVertCnt(D, vector<unsigned short>(N, 0));\n\n    auto pairCost = [&](int a, int b) -> double {\n        double dx = edges[a].mx - edges[b].mx;\n        double dy = edges[a].my - edges[b].my;\n        double d2 = dx * dx + dy * dy;\n\n        double c = 18000.0 / (d2 + 900.0);\n        if (edges[a].u == edges[b].u || edges[a].u == edges[b].v ||\n            edges[a].v == edges[b].u || edges[a].v == edges[b].v) c += 2.5;\n\n        return c * (0.7 + 0.9 * (imp[a] + imp[b]));\n    };\n\n    auto addCostToDay = [&](int e, int d) -> double {\n        double c = 0.0;\n        for (int f : dayEdges[d]) c += pairCost(e, f);\n\n        c += 2.5 * imp[e] * dayImp[d];\n\n        int u = edges[e].u, v = edges[e].v;\n        c += 8.0 * dayVertCnt[d][u];\n        c += 8.0 * dayVertCnt[d][v];\n\n        double target = (double)M / D;\n        c += 0.3 * max(0.0, load[d] + 1 - target);\n\n        return c;\n    };\n\n    auto assignEdge = [&](int e, int d) {\n        ans[e] = d;\n        load[d]++;\n        dayImp[d] += imp[e];\n        dayEdges[d].push_back(e);\n        dayVertCnt[d][edges[e].u]++;\n        dayVertCnt[d][edges[e].v]++;\n    };\n\n    auto removeFromDayVec = [&](int e, int d) {\n        auto &vec = dayEdges[d];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i] == e) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n\n    auto removeEdge = [&](int e, int d) {\n        load[d]--;\n        dayImp[d] -= imp[e];\n        dayVertCnt[d][edges[e].u]--;\n        dayVertCnt[d][edges[e].v]--;\n        removeFromDayVec(e, d);\n        ans[e] = -1;\n    };\n\n    auto edgeContribution = [&](int e, int d) -> double {\n        double c = 0.0;\n        for (int f : dayEdges[d]) {\n            if (f != e) c += pairCost(e, f);\n        }\n\n        c += 2.5 * imp[e] * max(0.0, dayImp[d] - imp[e]);\n\n        int u = edges[e].u, v = edges[e].v;\n        c += 8.0 * max(0, (int)dayVertCnt[d][u] - 1);\n        c += 8.0 * max(0, (int)dayVertCnt[d][v] - 1);\n\n        return c;\n    };\n\n    // ---------- Initial construction ----------\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabs(imp[a] - imp[b]) > 1e-12) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    for (int e : ord) {\n        int bestD = -1;\n        double best = 1e100;\n\n        for (int d = 0; d < D; d++) {\n            if (load[d] >= K) continue;\n\n            double c = addCostToDay(e, d);\n            if (!isConnectedWithExtra(dayEdges[d], e)) continue;\n\n            if (c < best) {\n                best = c;\n                bestD = d;\n            }\n        }\n\n        if (bestD < 0) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= K) continue;\n                double c = addCostToDay(e, d) + 1e6;\n                if (c < best) {\n                    best = c;\n                    bestD = d;\n                }\n            }\n        }\n\n        if (bestD < 0) bestD = min_element(load.begin(), load.end()) - load.begin();\n\n        assignEdge(e, bestD);\n    }\n\n    auto repairDisconnected = [&]() {\n        bool changed = true;\n        int rounds = 0;\n\n        while (changed && rounds < 200) {\n            changed = false;\n            rounds++;\n\n            for (int d = 0; d < D; d++) {\n                while (!isConnectedDay(dayEdges[d])) {\n                    if (dayEdges[d].empty()) break;\n\n                    int chosen = -1;\n                    double worst = -1;\n\n                    for (int e : dayEdges[d]) {\n                        double c = edgeContribution(e, d) + 100.0 * imp[e];\n                        if (c > worst) {\n                            worst = c;\n                            chosen = e;\n                        }\n                    }\n\n                    if (chosen < 0) break;\n\n                    int src = d;\n                    removeEdge(chosen, src);\n\n                    int bestD = -1;\n                    double best = 1e100;\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd == src) continue;\n                        if (load[nd] >= K) continue;\n                        if (!isConnectedWithExtra(dayEdges[nd], chosen)) continue;\n\n                        double c = addCostToDay(chosen, nd);\n                        if (c < best) {\n                            best = c;\n                            bestD = nd;\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        for (int nd = 0; nd < D; nd++) {\n                            if (nd == src) continue;\n                            if (load[nd] >= K) continue;\n\n                            double c = addCostToDay(chosen, nd) + 1e6;\n                            if (c < best) {\n                                best = c;\n                                bestD = nd;\n                            }\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        assignEdge(chosen, src);\n                        break;\n                    } else {\n                        assignEdge(chosen, bestD);\n                        changed = true;\n                    }\n                }\n            }\n        }\n    };\n\n    repairDisconnected();\n\n    // ---------- Short surrogate local search ----------\n    double phase1Limit = 3.15;\n\n    while (timer.elapsed() < phase1Limit) {\n        if ((xorshift64() & 3) != 0) {\n            int e = rnd_int(0, M - 1);\n            int a = ans[e];\n            int b = rnd_int(0, D - 1);\n            if (a == b || load[b] >= K) continue;\n\n            double oldc = edgeContribution(e, a);\n            removeEdge(e, a);\n\n            if (!isConnectedWithExtra(dayEdges[b], e)) {\n                assignEdge(e, a);\n                continue;\n            }\n\n            double newc = addCostToDay(e, b);\n\n            double t = max(0.001, 0.05 * (1.0 - timer.elapsed() / phase1Limit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) assignEdge(e, b);\n            else assignEdge(e, a);\n\n        } else {\n            int e1 = rnd_int(0, M - 1);\n            int e2 = rnd_int(0, M - 1);\n            if (e1 == e2) continue;\n\n            int d1 = ans[e1];\n            int d2 = ans[e2];\n            if (d1 == d2) continue;\n\n            double oldc = edgeContribution(e1, d1) + edgeContribution(e2, d2);\n\n            removeEdge(e1, d1);\n            removeEdge(e2, d2);\n\n            bool ok1 = isConnectedWithExtra(dayEdges[d1], e2);\n            bool ok2 = isConnectedWithExtra(dayEdges[d2], e1);\n\n            if (!ok1 || !ok2) {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n                continue;\n            }\n\n            double newc = addCostToDay(e1, d2) + addCostToDay(e2, d1);\n\n            double t = max(0.001, 0.05 * (1.0 - timer.elapsed() / phase1Limit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) {\n                assignEdge(e1, d2);\n                assignEdge(e2, d1);\n            } else {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n            }\n        }\n    }\n\n    repairDisconnected();\n\n    // ---------- Sampled real score evaluation ----------\n    vector<int> scoreSources;\n    {\n        vector<pair<double,int>> vals;\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i] + Y[i], i});\n        sort(vals.begin(), vals.end());\n        scoreSources.push_back(vals.front().second);\n        scoreSources.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i] - Y[i], i});\n        sort(vals.begin(), vals.end());\n        scoreSources.push_back(vals.front().second);\n        scoreSources.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({X[i], i});\n        sort(vals.begin(), vals.end());\n        scoreSources.push_back(vals.front().second);\n        scoreSources.push_back(vals.back().second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({Y[i], i});\n        sort(vals.begin(), vals.end());\n        scoreSources.push_back(vals.front().second);\n        scoreSources.push_back(vals.back().second);\n\n        int S = min(N, 24);\n        while ((int)scoreSources.size() < S) scoreSources.push_back(rnd_int(0, N - 1));\n\n        sort(scoreSources.begin(), scoreSources.end());\n        scoreSources.erase(unique(scoreSources.begin(), scoreSources.end()), scoreSources.end());\n    }\n\n    int S = scoreSources.size();\n    vector<vector<long long>> origDist(S);\n\n    for (int i = 0; i < S; i++) {\n        origDist[i] = dijkstra(scoreSources[i], nullptr);\n    }\n\n    auto sampledDayScore = [&](const vector<int>& rem) -> double {\n        double total = 0.0;\n\n        for (int si = 0; si < S; si++) {\n            vector<long long> nd = dijkstra(scoreSources[si], &rem);\n            const auto &od = origDist[si];\n\n            for (int v = 0; v < N; v++) {\n                if (v == scoreSources[si]) continue;\n\n                if (nd[v] >= INF / 4) {\n                    total += 1e9;\n                } else {\n                    total += (double)(nd[v] - od[v]);\n                }\n            }\n        }\n\n        return total / max(1, S);\n    };\n\n    vector<double> dayScore(D);\n    auto recomputeDayScore = [&](int d) {\n        dayScore[d] = sampledDayScore(dayEdges[d]);\n    };\n\n    for (int d = 0; d < D; d++) recomputeDayScore(d);\n\n    auto totalSampleScore = [&]() {\n        double s = 0.0;\n        for (double x : dayScore) s += x;\n        return s;\n    };\n\n    // ---------- Direct sampled-score improvement ----------\n    double phase2Limit = 5.75;\n\n    while (timer.elapsed() < phase2Limit) {\n        int worstDay = max_element(dayScore.begin(), dayScore.end()) - dayScore.begin();\n\n        bool improved = false;\n\n        // Try several candidate moves from worst day.\n        vector<int> cand = dayEdges[worstDay];\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            return edgeContribution(a, worstDay) + 20.0 * imp[a] >\n                   edgeContribution(b, worstDay) + 20.0 * imp[b];\n        });\n\n        int tryEdges = min((int)cand.size(), 12);\n\n        double currentTotal = totalSampleScore();\n\n        for (int ii = 0; ii < tryEdges && timer.elapsed() < phase2Limit; ii++) {\n            int e = cand[ii];\n            int a = worstDay;\n\n            for (int b = 0; b < D && timer.elapsed() < phase2Limit; b++) {\n                if (a == b || load[b] >= K) continue;\n\n                removeEdge(e, a);\n\n                if (!isConnectedWithExtra(dayEdges[b], e)) {\n                    assignEdge(e, a);\n                    continue;\n                }\n\n                assignEdge(e, b);\n\n                if (!isConnectedDay(dayEdges[a])) {\n                    removeEdge(e, b);\n                    assignEdge(e, a);\n                    continue;\n                }\n\n                double oldA = dayScore[a], oldB = dayScore[b];\n\n                double newA = sampledDayScore(dayEdges[a]);\n                double newB = sampledDayScore(dayEdges[b]);\n\n                double newTotal = currentTotal - oldA - oldB + newA + newB;\n\n                if (newTotal + 1e-7 < currentTotal) {\n                    dayScore[a] = newA;\n                    dayScore[b] = newB;\n                    improved = true;\n                    currentTotal = newTotal;\n                    break;\n                } else {\n                    removeEdge(e, b);\n                    assignEdge(e, a);\n                }\n            }\n\n            if (improved) break;\n        }\n\n        if (improved) continue;\n\n        // Try swaps involving worst day.\n        for (int ii = 0; ii < min((int)cand.size(), 8) && timer.elapsed() < phase2Limit; ii++) {\n            int e1 = cand[ii];\n            int d1 = worstDay;\n\n            int d2 = rnd_int(0, D - 1);\n            if (d1 == d2 || dayEdges[d2].empty()) continue;\n\n            vector<int> cand2 = dayEdges[d2];\n            int trials2 = min((int)cand2.size(), 8);\n\n            for (int tt = 0; tt < trials2 && timer.elapsed() < phase2Limit; tt++) {\n                int e2 = cand2[rnd_int(0, (int)cand2.size() - 1)];\n\n                double currentTotal = totalSampleScore();\n\n                removeEdge(e1, d1);\n                removeEdge(e2, d2);\n\n                bool ok1 = isConnectedWithExtra(dayEdges[d1], e2);\n                bool ok2 = isConnectedWithExtra(dayEdges[d2], e1);\n\n                if (!ok1 || !ok2) {\n                    assignEdge(e1, d1);\n                    assignEdge(e2, d2);\n                    continue;\n                }\n\n                assignEdge(e1, d2);\n                assignEdge(e2, d1);\n\n                double old1 = dayScore[d1], old2 = dayScore[d2];\n                double new1 = sampledDayScore(dayEdges[d1]);\n                double new2 = sampledDayScore(dayEdges[d2]);\n\n                double newTotal = currentTotal - old1 - old2 + new1 + new2;\n\n                if (newTotal + 1e-7 < currentTotal) {\n                    dayScore[d1] = new1;\n                    dayScore[d2] = new2;\n                    improved = true;\n                    break;\n                } else {\n                    removeEdge(e1, d2);\n                    removeEdge(e2, d1);\n                    assignEdge(e1, d1);\n                    assignEdge(e2, d2);\n                }\n            }\n\n            if (improved) break;\n        }\n\n        if (!improved) {\n            // Avoid repeatedly focusing only on one stuck day:\n            // mildly perturb stored score so the next loop may inspect another bad day.\n            dayScore[worstDay] *= 0.995;\n        }\n    }\n\n    repairDisconnected();\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << ans[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Seg {\n    int x, y, z, dir;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for (int i = 0; i < 2; i++) {\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    const int N3 = D * D * D;\n\n    auto id = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    vector<vector<int>> occ(2, vector<int>(N3, 0));\n    vector<vector<int>> ans(2, vector<int>(N3, 0));\n\n    /*\n      Sparse construction with vertical continuity.\n\n      For each object:\n      - At every z layer we need to cover all visible x and visible y.\n      - We preserve previous layer (x,y) pairs whenever possible.\n      - This tends to create vertical columns, which become large shared\n        straight blocks after rotation/translation.\n    */\n    for (int t = 0; t < 2; t++) {\n        vector<pair<int, int>> prev_pairs;\n\n        for (int z = 0; z < D; z++) {\n            vector<int> xs, ys;\n            vector<int> hasX(D, 0), hasY(D, 0);\n\n            for (int x = 0; x < D; x++) {\n                if (f[t][z][x] == '1') {\n                    xs.push_back(x);\n                    hasX[x] = 1;\n                }\n            }\n            for (int y = 0; y < D; y++) {\n                if (r[t][z][y] == '1') {\n                    ys.push_back(y);\n                    hasY[y] = 1;\n                }\n            }\n\n            vector<int> coveredX(D, 0), coveredY(D, 0);\n            vector<pair<int, int>> cur_pairs;\n\n            // Preserve previous layer pairs if possible.\n            for (auto [x, y] : prev_pairs) {\n                if (hasX[x] && hasY[y] && !coveredX[x] && !coveredY[y]) {\n                    cur_pairs.push_back({x, y});\n                    coveredX[x] = 1;\n                    coveredY[y] = 1;\n                }\n            }\n\n            vector<int> remX, remY;\n            for (int x : xs) {\n                if (!coveredX[x]) remX.push_back(x);\n            }\n            for (int y : ys) {\n                if (!coveredY[y]) remY.push_back(y);\n            }\n\n            /*\n              Fill uncovered x/y.\n\n              If one side has fewer remaining elements, reuse its values.\n              Reuse is allowed because multiple voxels may share the same x\n              or the same y.\n            */\n            int m = max(remX.size(), remY.size());\n\n            for (int k = 0; k < m; k++) {\n                int x, y;\n\n                if (!remX.empty()) {\n                    x = remX[k % remX.size()];\n                } else {\n                    // all x covered; pick a stable visible x\n                    x = xs[0];\n                }\n\n                if (!remY.empty()) {\n                    y = remY[k % remY.size()];\n                } else {\n                    // all y covered; pick a stable visible y\n                    y = ys[0];\n                }\n\n                cur_pairs.push_back({x, y});\n                coveredX[x] = 1;\n                coveredY[y] = 1;\n            }\n\n            sort(cur_pairs.begin(), cur_pairs.end());\n            cur_pairs.erase(unique(cur_pairs.begin(), cur_pairs.end()), cur_pairs.end());\n\n            for (auto [x, y] : cur_pairs) {\n                occ[t][id(x, y, z)] = 1;\n            }\n\n            prev_pairs = cur_pairs;\n        }\n    }\n\n    int block_id = 0;\n\n    const int dx[3] = {1, 0, 0};\n    const int dy[3] = {0, 1, 0};\n    const int dz[3] = {0, 0, 1};\n\n    auto can_segment = [&](int t, int x, int y, int z, int dir, int len) {\n        for (int k = 0; k < len; k++) {\n            int nx = x + dx[dir] * k;\n            int ny = y + dy[dir] * k;\n            int nz = z + dz[dir] * k;\n\n            if (nx < 0 || nx >= D || ny < 0 || ny >= D || nz < 0 || nz >= D) return false;\n\n            int p = id(nx, ny, nz);\n            if (!occ[t][p] || ans[t][p] != 0) return false;\n        }\n        return true;\n    };\n\n    auto place_segment = [&](int t, int x, int y, int z, int dir, int len, int bid) {\n        for (int k = 0; k < len; k++) {\n            int nx = x + dx[dir] * k;\n            int ny = y + dy[dir] * k;\n            int nz = z + dz[dir] * k;\n            ans[t][id(nx, ny, nz)] = bid;\n        }\n    };\n\n    mt19937 rng(1234567);\n\n    /*\n      Pair long straight segments between the two objects.\n\n      A straight segment of the same length is the same block under rotation.\n    */\n    for (int len = D; len >= 2; len--) {\n        bool updated = true;\n\n        while (updated) {\n            updated = false;\n\n            vector<Seg> segs[2];\n\n            for (int t = 0; t < 2; t++) {\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                            for (int dir = 0; dir < 3; dir++) {\n                                if (can_segment(t, x, y, z, dir, len)) {\n                                    segs[t].push_back({x, y, z, dir});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (segs[0].empty() || segs[1].empty()) continue;\n\n            shuffle(segs[0].begin(), segs[0].end(), rng);\n            shuffle(segs[1].begin(), segs[1].end(), rng);\n\n            size_t p0 = 0;\n            size_t p1 = 0;\n\n            while (p0 < segs[0].size() && p1 < segs[1].size()) {\n                while (p0 < segs[0].size() &&\n                       !can_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z,\n                                    segs[0][p0].dir, len)) {\n                    p0++;\n                }\n\n                while (p1 < segs[1].size() &&\n                       !can_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z,\n                                    segs[1][p1].dir, len)) {\n                    p1++;\n                }\n\n                if (p0 >= segs[0].size() || p1 >= segs[1].size()) break;\n\n                block_id++;\n                place_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z,\n                              segs[0][p0].dir, len, block_id);\n                place_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z,\n                              segs[1][p1].dir, len, block_id);\n\n                updated = true;\n                p0++;\n                p1++;\n            }\n        }\n    }\n\n    /*\n      Pair remaining unit cubes.\n    */\n    vector<int> rem[2];\n\n    for (int t = 0; t < 2; t++) {\n        for (int p = 0; p < N3; p++) {\n            if (occ[t][p] && ans[t][p] == 0) {\n                rem[t].push_back(p);\n            }\n        }\n    }\n\n    int common_units = min((int)rem[0].size(), (int)rem[1].size());\n\n    for (int i = 0; i < common_units; i++) {\n        block_id++;\n        ans[0][rem[0][i]] = block_id;\n        ans[1][rem[1][i]] = block_id;\n    }\n\n    for (int i = common_units; i < (int)rem[0].size(); i++) {\n        block_id++;\n        ans[0][rem[0][i]] = block_id;\n    }\n\n    for (int i = common_units; i < (int)rem[1].size(); i++) {\n        block_id++;\n        ans[1][rem[1][i]] = block_id;\n    }\n\n    cout << block_id << '\\n';\n\n    for (int t = 0; t < 2; t++) {\n        for (int p = 0; p < N3; p++) {\n            if (p) cout << ' ';\n            cout << ans[t][p];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        sz.assign(n,1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[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(sz[a]<sz[b]) swap(a,b);\n        p[b]=a;\n        sz[a]+=sz[b];\n        return true;\n    }\n};\n\nstatic inline long long sqdist(long long x1,long long y1,long long x2,long long y2){\n    long long dx=x1-x2, dy=y1-y2;\n    return dx*dx+dy*dy;\n}\n\nstruct Solver {\n    int N, M, K;\n    vector<int> x, y, a, b;\n    vector<Edge> edges;\n    vector<vector<pair<int,int>>> g;\n\n    vector<vector<int>> d2;\n    vector<vector<pair<int,int>>> cand;\n\n    vector<vector<long long>> dist;\n    vector<vector<int>> prevEdge, prevNode;\n\n    vector<int> bestP, bestB;\n    long long bestCost = (1LL<<62);\n\n    chrono::steady_clock::time_point st;\n    double timeLimit = 1.93;\n\n    bool time_ok() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count() < timeLimit;\n    }\n\n    int ceil_sqrt_int(int val) const {\n        int r=(int)ceil(sqrt((double)val));\n        while(1LL*r*r < val) r++;\n        while(r>0 && 1LL*(r-1)*(r-1) >= val) r--;\n        return r;\n    }\n\n    long long calc_cost(const vector<int>& P, const vector<int>& B) const {\n        long long s=0;\n        for(int p:P) s += 1LL*p*p;\n        for(int i=0;i<M;i++) if(B[i]) s += edges[i].w;\n        return s;\n    }\n\n    void add_path(vector<int>& B, int s, int t) const {\n        int cur=t;\n        while(cur!=s){\n            int ei=prevEdge[s][cur];\n            if(ei<0) break;\n            B[ei]=1;\n            cur=prevNode[s][cur];\n        }\n    }\n\n    void prune_edges(const vector<int>& P, vector<int>& B) const {\n        vector<vector<pair<int,int>>> tg(N);\n        vector<int> deg(N,0);\n        for(int i=0;i<M;i++) if(B[i]){\n            int u=edges[i].u, v=edges[i].v;\n            tg[u].push_back({v,i});\n            tg[v].push_back({u,i});\n            deg[u]++; deg[v]++;\n        }\n\n        queue<int> q;\n        for(int i=1;i<N;i++){\n            if(P[i]==0 && deg[i]==1) q.push(i);\n        }\n\n        while(!q.empty()){\n            int v=q.front(); q.pop();\n            if(v==0 || P[v]>0 || deg[v]!=1) continue;\n\n            int rem=-1, to=-1;\n            for(auto [nv,ei]: tg[v]){\n                if(B[ei]){\n                    rem=ei;\n                    to=nv;\n                    break;\n                }\n            }\n            if(rem<0) continue;\n\n            B[rem]=0;\n            deg[v]--;\n            deg[to]--;\n            if(to!=0 && P[to]==0 && deg[to]==1) q.push(to);\n        }\n    }\n\n    vector<int> build_edges_root_union(const vector<int>& P) const {\n        vector<int> B(M,0);\n        for(int i=0;i<N;i++){\n            if(P[i]>0) add_path(B,0,i);\n        }\n        prune_edges(P,B);\n        return B;\n    }\n\n    vector<int> build_edges_metric_mst(const vector<int>& P) const {\n        vector<int> terminals;\n        terminals.push_back(0);\n        for(int i=1;i<N;i++) if(P[i]>0) terminals.push_back(i);\n\n        vector<int> B(M,0);\n        int T=terminals.size();\n        if(T<=1) return B;\n\n        struct ME {\n            long long w;\n            int i,j;\n            bool operator<(const ME& o) const { return w<o.w; }\n        };\n\n        vector<ME> es;\n        es.reserve(T*T/2);\n        for(int i=0;i<T;i++){\n            for(int j=i+1;j<T;j++){\n                es.push_back({dist[terminals[i]][terminals[j]], i, j});\n            }\n        }\n        sort(es.begin(), es.end());\n\n        DSU dsu(T);\n        int used=0;\n        for(auto &e: es){\n            if(dsu.unite(e.i,e.j)){\n                add_path(B, terminals[e.i], terminals[e.j]);\n                used++;\n                if(used==T-1) break;\n            }\n        }\n\n        prune_edges(P,B);\n        return B;\n    }\n\n    vector<int> best_edges_for_P(const vector<int>& P) const {\n        vector<int> b1=build_edges_metric_mst(P);\n        long long c1=calc_cost(P,b1);\n        vector<int> b2=build_edges_root_union(P);\n        long long c2=calc_cost(P,b2);\n        return (c2<c1 ? b2 : b1);\n    }\n\n    long long total_cost_for_P(const vector<int>& P) const {\n        vector<int> B=best_edges_for_P(P);\n        return calc_cost(P,B);\n    }\n\n    vector<int> recomputeP_from_assigned(const vector<vector<int>>& assigned) const {\n        vector<int> P(N,0);\n        for(int i=0;i<N;i++){\n            int md=0;\n            for(int k: assigned[i]) md=max(md,d2[i][k]);\n            P[i]=ceil_sqrt_int(md);\n            if(P[i]>5000) P[i]=5000;\n        }\n        return P;\n    }\n\n    bool all_covered(const vector<int>& P) const {\n        for(int k=0;k<K;k++){\n            bool ok=false;\n            for(int i=0;i<N;i++){\n                if(P[i]>0 && 1LL*P[i]*P[i]>=d2[i][k]){\n                    ok=true;\n                    break;\n                }\n            }\n            if(!ok) return false;\n        }\n        return true;\n    }\n\n    vector<int> coverage_count(const vector<int>& P) const {\n        vector<int> cnt(K,0);\n        for(int i=0;i<N;i++){\n            if(P[i]==0) continue;\n            long long rr=1LL*P[i]*P[i];\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=rr) cnt[k]++;\n            }\n        }\n        return cnt;\n    }\n\n    void global_reduce(vector<int>& P) const {\n        vector<int> covCnt=coverage_count(P);\n\n        vector<int> ord(N);\n        iota(ord.begin(),ord.end(),0);\n        sort(ord.begin(),ord.end(),[&](int p,int q){\n            return P[p]<P[q];\n        });\n\n        for(int i: ord){\n            if(P[i]==0) continue;\n            long long rr=1LL*P[i]*P[i];\n            bool ok=true;\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=rr && covCnt[k]<=1){\n                    ok=false;\n                    break;\n                }\n            }\n            if(ok){\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=rr) covCnt[k]--;\n                }\n                P[i]=0;\n            }\n        }\n\n        ord.clear();\n        for(int i=0;i<N;i++) if(P[i]>0) ord.push_back(i);\n        sort(ord.begin(),ord.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        for(int i: ord){\n            if(P[i]==0) continue;\n\n            vector<int> critical;\n            critical.push_back(0);\n            long long oldrr=1LL*P[i]*P[i];\n\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=oldrr) critical.push_back(ceil_sqrt_int(d2[i][k]));\n            }\n\n            sort(critical.begin(),critical.end());\n            critical.erase(unique(critical.begin(),critical.end()),critical.end());\n\n            int best=P[i];\n            for(int idx=(int)critical.size()-1; idx>=0; idx--){\n                int r=critical[idx];\n                long long nrr=1LL*r*r;\n                bool ok=true;\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=oldrr && d2[i][k]>nrr && covCnt[k]<=1){\n                        ok=false;\n                        break;\n                    }\n                }\n                if(ok) best=r;\n                else break;\n            }\n\n            if(best<P[i]){\n                long long nrr=1LL*best*best;\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=oldrr && d2[i][k]>nrr) covCnt[k]--;\n                }\n                P[i]=best;\n            }\n        }\n    }\n\n    void repair_uncovered(vector<int>& P, int maxCand=45) const {\n        while(true){\n            vector<int> uncovered;\n            uncovered.reserve(K);\n\n            for(int k=0;k<K;k++){\n                bool ok=false;\n                for(int i=0;i<N;i++){\n                    if(P[i]>0 && 1LL*P[i]*P[i]>=d2[i][k]){\n                        ok=true;\n                        break;\n                    }\n                }\n                if(!ok) uncovered.push_back(k);\n            }\n\n            if(uncovered.empty()) break;\n\n            long long bestVal=(1LL<<62);\n            int bestI=-1;\n            vector<int> bestResidents;\n            int bestNewR=0;\n\n            // Evaluate expanding/adding station.\n            for(int i=0;i<N;i++){\n                vector<pair<int,int>> ds;\n                ds.reserve(uncovered.size());\n                for(int k: uncovered){\n                    if(d2[i][k] <= 5000LL*5000LL){\n                        ds.push_back({d2[i][k],k});\n                    }\n                }\n                if(ds.empty()) continue;\n\n                sort(ds.begin(),ds.end());\n                vector<int> cur;\n                int lastD=-1;\n\n                for(auto [dd,k]: ds){\n                    cur.push_back(k);\n                    if(dd==lastD) continue;\n                    lastD=dd;\n\n                    int nr=ceil_sqrt_int(dd);\n                    if(nr<P[i]) nr=P[i];\n                    if(nr>5000) continue;\n\n                    long long inc=1LL*nr*nr - 1LL*P[i]*P[i];\n                    if(P[i]==0) inc += dist[0][i]/7;\n\n                    // Prefer covering many uncovered residents.\n                    long long val = inc / max(1, (int)cur.size());\n                    val -= (long long)cur.size()*20;\n\n                    if(val<bestVal){\n                        bestVal=val;\n                        bestI=i;\n                        bestResidents=cur;\n                        bestNewR=nr;\n                    }\n                }\n            }\n\n            if(bestI<0){\n                // Fallback.\n                int k=uncovered[0];\n                int bi=cand[k][0].second;\n                P[bi]=max(P[bi],ceil_sqrt_int(d2[bi][k]));\n                P[bi]=min(P[bi],5000);\n            }else{\n                P[bestI]=bestNewR;\n            }\n        }\n    }\n\n    void drop_repair_local_search(vector<int>& P){\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        for(int pass=0; pass<2 && time_ok(); pass++){\n            bool improved=false;\n\n            vector<int> active;\n            for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n            sort(active.begin(),active.end(),[&](int p,int q){\n                long long cp=1LL*P[p]*P[p]+dist[0][p]/5;\n                long long cq=1LL*P[q]*P[q]+dist[0][q]/5;\n                return cp>cq;\n            });\n\n            int trials=0;\n            for(int rem: active){\n                if(!time_ok()) return;\n                if(P[rem]==0) continue;\n                if(++trials>70) break;\n\n                vector<int> NP=P;\n                NP[rem]=0;\n                repair_uncovered(NP,50);\n                global_reduce(NP);\n\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    improved=true;\n                }\n            }\n\n            if(!improved) break;\n        }\n    }\n\n    void expand_to_remove(vector<int>& P){\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        int tested=0;\n        for(int rem: active){\n            if(!time_ok() || tested>70) break;\n            tested++;\n            if(P[rem]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> needResidents;\n            long long rrem=1LL*P[rem]*P[rem];\n\n            for(int k=0;k<K;k++){\n                if(d2[rem][k]<=rrem && covCnt[k]==1) needResidents.push_back(k);\n            }\n\n            if(needResidents.empty()){\n                P[rem]=0;\n                global_reduce(P);\n                base=total_cost_for_P(P);\n                continue;\n            }\n\n            vector<int> candidates;\n            for(int k: needResidents){\n                int lim=min(10,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int i=cand[k][z].second;\n                    if(i!=rem) candidates.push_back(i);\n                }\n            }\n\n            sort(candidates.begin(),candidates.end());\n            candidates.erase(unique(candidates.begin(),candidates.end()),candidates.end());\n\n            int cnt=0;\n            for(int add: candidates){\n                if(!time_ok() || cnt>30) break;\n                cnt++;\n\n                vector<int> NP=P;\n                NP[rem]=0;\n                int nr=NP[add];\n\n                bool ok=true;\n                for(int k: needResidents){\n                    nr=max(nr,ceil_sqrt_int(d2[add][k]));\n                    if(nr>5000){\n                        ok=false;\n                        break;\n                    }\n                }\n                if(!ok) continue;\n\n                NP[add]=nr;\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    break;\n                }\n            }\n        }\n    }\n\n    void try_station_relocation(vector<int>& P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        int tested=0;\n        for(int old: active){\n            if(!time_ok() || tested>60) break;\n            tested++;\n            if(P[old]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> uniqueResidents;\n            long long rr=1LL*P[old]*P[old];\n            for(int k=0;k<K;k++){\n                if(d2[old][k]<=rr && covCnt[k]==1) uniqueResidents.push_back(k);\n            }\n\n            vector<int> candidateStations;\n            if(uniqueResidents.empty()){\n                vector<int> NP=P;\n                NP[old]=0;\n                global_reduce(NP);\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                }\n                continue;\n            }\n\n            for(int k: uniqueResidents){\n                int lim=min(8,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni!=old) candidateStations.push_back(ni);\n                }\n            }\n\n            sort(candidateStations.begin(),candidateStations.end());\n            candidateStations.erase(unique(candidateStations.begin(),candidateStations.end()),candidateStations.end());\n\n            int cnt=0;\n            for(int ni: candidateStations){\n                if(!time_ok() || cnt>20) break;\n                cnt++;\n\n                vector<int> NP=P;\n                NP[old]=0;\n                int need=NP[ni];\n\n                bool ok=true;\n                for(int k: uniqueResidents){\n                    need=max(need,ceil_sqrt_int(d2[ni][k]));\n                    if(need>5000){\n                        ok=false;\n                        break;\n                    }\n                }\n                if(!ok) continue;\n\n                NP[ni]=need;\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    break;\n                }\n            }\n        }\n    }\n\n    void refine_assignment(vector<vector<int>>& assigned, vector<int>& assign){\n        for(int outer=0; outer<7 && time_ok(); outer++){\n            vector<int> curMax(N,0), secondMax(N,0), cntMax(N,0);\n            for(int i=0;i<N;i++){\n                for(int k: assigned[i]){\n                    int dd=d2[i][k];\n                    if(dd>curMax[i]){\n                        secondMax[i]=curMax[i];\n                        curMax[i]=dd;\n                        cntMax[i]=1;\n                    }else if(dd==curMax[i]){\n                        cntMax[i]++;\n                    }else if(dd>secondMax[i]){\n                        secondMax[i]=dd;\n                    }\n                }\n            }\n\n            bool changed=false;\n            vector<int> order(K);\n            iota(order.begin(),order.end(),0);\n            shuffle(order.begin(),order.end(),mt19937(1234567+outer));\n\n            for(int k: order){\n                int old=assign[k];\n                if(old<0) continue;\n\n                int oldAfter=curMax[old];\n                if(d2[old][k]==curMax[old] && cntMax[old]==1) oldAfter=secondMax[old];\n\n                int oldR=ceil_sqrt_int(curMax[old]);\n                int oldAfterR=ceil_sqrt_int(oldAfter);\n                long long deltaOld=1LL*oldAfterR*oldAfterR-1LL*oldR*oldR;\n\n                long long bestDelta=0;\n                int bestI=old;\n\n                int lim=min(45,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni==old) continue;\n\n                    int r0=ceil_sqrt_int(curMax[ni]);\n                    int r1=ceil_sqrt_int(max(curMax[ni],d2[ni][k]));\n                    long long delta=deltaOld+1LL*r1*r1-1LL*r0*r0;\n\n                    if(assigned[ni].empty()) delta += dist[0][ni]/7;\n                    if(assigned[old].size()==1) delta -= dist[0][old]/7;\n\n                    if(delta<bestDelta){\n                        bestDelta=delta;\n                        bestI=ni;\n                    }\n                }\n\n                if(bestI!=old){\n                    auto &v=assigned[old];\n                    auto it=find(v.begin(),v.end(),k);\n                    if(it!=v.end()) v.erase(it);\n                    assigned[bestI].push_back(k);\n                    assign[k]=bestI;\n                    changed=true;\n                }\n            }\n\n            try_delete_stations(assigned,assign);\n            if(!changed) break;\n        }\n    }\n\n    void try_delete_stations(vector<vector<int>>& assigned, vector<int>& assign){\n        vector<int> stations;\n        for(int i=0;i<N;i++) if(!assigned[i].empty()) stations.push_back(i);\n\n        sort(stations.begin(),stations.end(),[&](int p,int q){\n            return assigned[p].size()<assigned[q].size();\n        });\n\n        int tries=0;\n        for(int rem: stations){\n            if(!time_ok()) return;\n            if(assigned[rem].empty()) continue;\n            if((int)assigned[rem].size()>220) continue;\n            if(++tries>50) break;\n\n            auto backupA=assigned;\n            auto backupAssign=assign;\n\n            vector<int> oldP=recomputeP_from_assigned(assigned);\n            global_reduce(oldP);\n            long long oldCost=total_cost_for_P(oldP);\n\n            vector<int> residents=assigned[rem];\n            assigned[rem].clear();\n\n            bool ok=true;\n            for(int k: residents){\n                long long bestInc=(1LL<<60);\n                int bestI=-1;\n\n                int lim=min(60,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni==rem) continue;\n\n                    int md=0;\n                    for(int kk: assigned[ni]) md=max(md,d2[ni][kk]);\n\n                    int r0=ceil_sqrt_int(md);\n                    int r1=ceil_sqrt_int(max(md,d2[ni][k]));\n                    long long inc=1LL*r1*r1-1LL*r0*r0;\n                    if(assigned[ni].empty()) inc += dist[0][ni]/7;\n\n                    if(inc<bestInc){\n                        bestInc=inc;\n                        bestI=ni;\n                    }\n                }\n\n                if(bestI<0){\n                    ok=false;\n                    break;\n                }\n\n                assigned[bestI].push_back(k);\n                assign[k]=bestI;\n            }\n\n            if(ok){\n                vector<int> newP=recomputeP_from_assigned(assigned);\n                global_reduce(newP);\n                long long newCost=total_cost_for_P(newP);\n                if(newCost<oldCost) continue;\n            }\n\n            assigned=backupA;\n            assign=backupAssign;\n        }\n    }\n\n    void evaluate_P(vector<int> P){\n        for(int &p:P){\n            p=max(0,min(5000,p));\n        }\n\n        repair_uncovered(P);\n        global_reduce(P);\n\n        if(time_ok()) expand_to_remove(P);\n        if(time_ok()) try_station_relocation(P);\n        if(time_ok()) drop_repair_local_search(P);\n        global_reduce(P);\n\n        if(!all_covered(P)) repair_uncovered(P);\n        global_reduce(P);\n\n        vector<int> B=best_edges_for_P(P);\n        long long c=calc_cost(P,B);\n\n        if(c<bestCost){\n            bestCost=c;\n            bestP=P;\n            bestB=B;\n        }\n    }\n\n    void evaluate_assignment(vector<vector<int>> assigned){\n        vector<int> assign(K,-1);\n        for(int i=0;i<N;i++){\n            for(int k: assigned[i]) assign[k]=i;\n        }\n\n        refine_assignment(assigned,assign);\n\n        vector<int> P=recomputeP_from_assigned(assigned);\n        evaluate_P(P);\n    }\n\n    void build_initial_nearest(){\n        vector<vector<int>> assigned(N);\n        for(int k=0;k<K;k++){\n            assigned[cand[k][0].second].push_back(k);\n        }\n        evaluate_assignment(assigned);\n    }\n\n    void build_initial_marginal(int lim, long long connDiv, int orderMode){\n        vector<vector<int>> assigned(N);\n        vector<int> maxd(N,0);\n\n        vector<int> order(K);\n        iota(order.begin(),order.end(),0);\n\n        if(orderMode==0){\n            sort(order.begin(),order.end(),[&](int p,int q){\n                return cand[p][0].first>cand[q][0].first;\n            });\n        }else if(orderMode==1){\n            sort(order.begin(),order.end(),[&](int p,int q){\n                return cand[p][0].first<cand[q][0].first;\n            });\n        }else{\n            shuffle(order.begin(),order.end(),mt19937(777+orderMode));\n        }\n\n        for(int k: order){\n            long long best=(1LL<<60);\n            int bi=cand[k][0].second;\n\n            int L=min(lim,(int)cand[k].size());\n            for(int z=0;z<L;z++){\n                int i=cand[k][z].second;\n                int r0=ceil_sqrt_int(maxd[i]);\n                int r1=ceil_sqrt_int(max(maxd[i],d2[i][k]));\n                long long inc=1LL*r1*r1-1LL*r0*r0;\n                if(assigned[i].empty()) inc += dist[0][i]/connDiv;\n\n                if(inc<best){\n                    best=inc;\n                    bi=i;\n                }\n            }\n\n            assigned[bi].push_back(k);\n            maxd[bi]=max(maxd[bi],d2[bi][k]);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void build_initial_setcover(long long connDiv, int radiiStep, double powGain){\n        vector<char> covered(K,0);\n        int remaining=K;\n        vector<vector<int>> assigned(N);\n        vector<int> assign(K,-1);\n\n        vector<int> possibleR;\n        for(int r=250;r<=5000;r+=radiiStep) possibleR.push_back(r);\n        possibleR.push_back(5000);\n        sort(possibleR.begin(),possibleR.end());\n        possibleR.erase(unique(possibleR.begin(),possibleR.end()),possibleR.end());\n\n        for(int iter=0; remaining>0 && iter<180 && time_ok(); iter++){\n            double bestScore=-1;\n            int bestI=-1;\n            vector<int> bestList;\n\n            for(int i=0;i<N;i++){\n                vector<pair<int,int>> ds;\n                ds.reserve(remaining);\n                for(int k=0;k<K;k++){\n                    if(!covered[k] && d2[i][k]<=5000LL*5000LL){\n                        ds.push_back({d2[i][k],k});\n                    }\n                }\n                if(ds.empty()) continue;\n\n                sort(ds.begin(),ds.end());\n                vector<int> cur;\n                int ptr=0;\n\n                for(int r: possibleR){\n                    int rr=r*r;\n                    while(ptr<(int)ds.size() && ds[ptr].first<=rr){\n                        cur.push_back(ds[ptr].second);\n                        ptr++;\n                    }\n\n                    int gain=cur.size();\n                    if(gain==0) continue;\n\n                    long long cost=1LL*r*r + dist[0][i]/connDiv;\n                    double score=pow((double)gain,powGain)/(double)cost;\n\n                    if(score>bestScore){\n                        bestScore=score;\n                        bestI=i;\n                        bestList=cur;\n                    }\n                }\n            }\n\n            if(bestI<0) break;\n\n            for(int k: bestList){\n                if(!covered[k]){\n                    covered[k]=1;\n                    remaining--;\n                    assign[k]=bestI;\n                    assigned[bestI].push_back(k);\n                }\n            }\n        }\n\n        for(int k=0;k<K;k++){\n            if(assign[k]>=0) continue;\n\n            long long best=(1LL<<60);\n            int bi=cand[k][0].second;\n            int L=min(60,(int)cand[k].size());\n\n            for(int z=0;z<L;z++){\n                int i=cand[k][z].second;\n                int md=0;\n                for(int kk: assigned[i]) md=max(md,d2[i][kk]);\n\n                int r0=ceil_sqrt_int(md);\n                int r1=ceil_sqrt_int(max(md,d2[i][k]));\n                long long inc=1LL*r1*r1-1LL*r0*r0;\n                if(assigned[i].empty()) inc += dist[0][i]/connDiv;\n\n                if(inc<best){\n                    best=inc;\n                    bi=i;\n                }\n            }\n\n            assign[k]=bi;\n            assigned[bi].push_back(k);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void prepare(){\n        d2.assign(N,vector<int>(K));\n        for(int i=0;i<N;i++){\n            for(int k=0;k<K;k++){\n                d2[i][k]=(int)sqdist(x[i],y[i],a[k],b[k]);\n            }\n        }\n\n        cand.assign(K,{});\n        for(int k=0;k<K;k++){\n            cand[k].reserve(N);\n            for(int i=0;i<N;i++){\n                if(d2[i][k]<=5000LL*5000LL) cand[k].push_back({d2[i][k],i});\n            }\n            if(cand[k].empty()){\n                for(int i=0;i<N;i++) cand[k].push_back({d2[i][k],i});\n            }\n            sort(cand[k].begin(),cand[k].end());\n        }\n\n        const long long INF=(1LL<<60);\n        dist.assign(N,vector<long long>(N,INF));\n        prevEdge.assign(N,vector<int>(N,-1));\n        prevNode.assign(N,vector<int>(N,-1));\n\n        for(int s=0;s<N;s++){\n            priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>> pq;\n            dist[s][s]=0;\n            pq.push({0,s});\n\n            while(!pq.empty()){\n                auto [cd,v]=pq.top();\n                pq.pop();\n                if(cd!=dist[s][v]) continue;\n\n                for(auto [to,ei]: g[v]){\n                    long long nd=cd+edges[ei].w;\n                    if(nd<dist[s][to]){\n                        dist[s][to]=nd;\n                        prevEdge[s][to]=ei;\n                        prevNode[s][to]=v;\n                        pq.push({nd,to});\n                    }\n                }\n            }\n        }\n    }\n\n    void solve(){\n        st=chrono::steady_clock::now();\n        prepare();\n\n        bestP.assign(N,0);\n        bestB.assign(M,0);\n\n        build_initial_nearest();\n\n        if(time_ok()) build_initial_marginal(12,4,0);\n        if(time_ok()) build_initial_marginal(25,5,0);\n        if(time_ok()) build_initial_marginal(60,7,0);\n        if(time_ok()) build_initial_marginal(100,9,0);\n\n        if(time_ok()) build_initial_marginal(25,5,1);\n        if(time_ok()) build_initial_marginal(50,7,2);\n        if(time_ok()) build_initial_marginal(80,10,3);\n\n        if(time_ok()) build_initial_setcover(5,300,1.35);\n        if(time_ok()) build_initial_setcover(8,450,1.45);\n        if(time_ok()) build_initial_setcover(12,650,1.55);\n\n        for(int k=0;k<K;k++){\n            bool ok=false;\n            for(int i=0;i<N;i++){\n                if(bestP[i]>0 && 1LL*bestP[i]*bestP[i]>=d2[i][k]){\n                    ok=true;\n                    break;\n                }\n            }\n            if(!ok){\n                int bi=cand[k][0].second;\n                bestP[bi]=max(bestP[bi],ceil_sqrt_int(d2[bi][k]));\n                bestP[bi]=min(bestP[bi],5000);\n            }\n        }\n\n        global_reduce(bestP);\n        bestB=best_edges_for_P(bestP);\n    }\n};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    cin >> solver.N >> solver.M >> solver.K;\n\n    solver.x.resize(solver.N);\n    solver.y.resize(solver.N);\n    for(int i=0;i<solver.N;i++){\n        cin >> solver.x[i] >> solver.y[i];\n    }\n\n    solver.edges.resize(solver.M);\n    solver.g.assign(solver.N,{});\n    for(int i=0;i<solver.M;i++){\n        int u,v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n        solver.edges[i]={u,v,w};\n        solver.g[u].push_back({v,i});\n        solver.g[v].push_back({u,i});\n    }\n\n    solver.a.resize(solver.K);\n    solver.b.resize(solver.K);\n    for(int k=0;k<solver.K;k++){\n        cin >> solver.a[k] >> solver.b[k];\n    }\n\n    solver.solve();\n\n    for(int i=0;i<solver.N;i++){\n        if(i) cout << ' ';\n        cout << solver.bestP[i];\n    }\n    cout << '\\n';\n\n    for(int i=0;i<solver.M;i++){\n        if(i) cout << ' ';\n        cout << solver.bestB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int LIM = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nusing Board = array<array<int, N>, N>;\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y <= x;\n}\n\nbool adjacent_cell(int x1, int y1, int x2, int y2) {\n    if (x1 == x2 && abs(y1 - y2) == 1) return true;\n    if (x2 == x1 + 1 && (y2 == y1 || y2 == y1 + 1)) return true;\n    if (x2 == x1 - 1 && (y1 == y2 || y1 == y2 + 1)) return true;\n    return false;\n}\n\nint cell_violation(const Board& a, int x, int y) {\n    if (x < 0 || x >= N - 1 || y < 0 || y > x) return 0;\n    int c = 0;\n    if (a[x][y] > a[x + 1][y]) c++;\n    if (a[x][y] > a[x + 1][y + 1]) c++;\n    return c;\n}\n\nint cell_severity(const Board& a, int x, int y) {\n    if (x < 0 || x >= N - 1 || y < 0 || y > x) return 0;\n    int s = 0;\n    if (a[x][y] > a[x + 1][y]) s += a[x][y] - a[x + 1][y];\n    if (a[x][y] > a[x + 1][y + 1]) s += a[x][y] - a[x + 1][y + 1];\n    return s;\n}\n\nint total_violations(const Board& a) {\n    int e = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            e += cell_violation(a, x, y);\n        }\n    }\n    return e;\n}\n\nBoard apply_ops(const Board& init, const vector<Op>& ops, int skip = -1) {\n    Board a = init;\n    for (int i = 0; i < (int)ops.size(); i++) {\n        if (i == skip) continue;\n        const auto& op = ops[i];\n        swap(a[op.x1][op.y1], a[op.x2][op.y2]);\n    }\n    return a;\n}\n\nbool valid_after_skip(const Board& init, const vector<Op>& ops, int skip) {\n    Board a = init;\n    for (int i = 0; i < (int)ops.size(); i++) {\n        if (i == skip) continue;\n        const auto& op = ops[i];\n        swap(a[op.x1][op.y1], a[op.x2][op.y2]);\n    }\n    return total_violations(a) == 0;\n}\n\nstruct Result {\n    bool ok = false;\n    vector<Op> ops;\n};\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 123456789) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n    double uniform01() {\n        return (next() & 0xffffff) / double(0x1000000);\n    }\n};\n\nvector<pair<int,int>> local_cells_around(int x, int y) {\n    vector<pair<int,int>> v;\n    for (int dx = -2; dx <= 1; dx++) {\n        for (int dy = -2; dy <= 2; dy++) {\n            int nx = x + dx, ny = y + dy;\n            if (inside(nx, ny) && nx < N - 1) {\n                if (abs(nx - x) + abs(ny - y) <= 3) v.push_back({nx, ny});\n            }\n        }\n    }\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nvector<pair<int,int>> affected_union(int x1, int y1, int x2, int y2) {\n    auto a = local_cells_around(x1, y1);\n    auto b = local_cells_around(x2, y2);\n    a.insert(a.end(), b.begin(), b.end());\n    sort(a.begin(), a.end());\n    a.erase(unique(a.begin(), a.end()), a.end());\n    return a;\n}\n\nstruct Policy {\n    int order_type;\n    double w_vio;\n    double w_sev;\n    double w_depth;\n    double w_small;\n    uint32_t seed;\n};\n\nResult solve_with_policy(const Board& init, const Policy& pol) {\n    Board a = init;\n    vector<Op> ops;\n    XorShift rng(pol.seed);\n\n    auto do_swap = [&](int x1, int y1, int x2, int y2) -> bool {\n        if ((int)ops.size() >= LIM) return false;\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n        return true;\n    };\n\n    auto candidate_score = [&](int x1, int y1, int x2, int y2) {\n        auto aff = affected_union(x1, y1, x2, y2);\n\n        int vio_before = 0, sev_before = 0;\n        for (auto [x, y] : aff) {\n            vio_before += cell_violation(a, x, y);\n            sev_before += cell_severity(a, x, y);\n        }\n\n        swap(a[x1][y1], a[x2][y2]);\n\n        int vio_after = 0, sev_after = 0;\n        for (auto [x, y] : aff) {\n            vio_after += cell_violation(a, x, y);\n            sev_after += cell_severity(a, x, y);\n        }\n\n        int moved_up = a[x1][y1];\n        swap(a[x1][y1], a[x2][y2]);\n\n        double score = 0;\n        score += pol.w_vio * double(vio_before - vio_after);\n        score += pol.w_sev * double(sev_before - sev_after);\n        score += pol.w_depth * double(x1);\n        score += pol.w_small * double(464 - moved_up) / 464.0;\n        score += 1e-6 * rng.uniform01();\n        return score;\n    };\n\n    auto repair_cell = [&](int x, int y) -> bool {\n        if (x >= N - 1) return false;\n        if (cell_violation(a, x, y) == 0) return false;\n\n        vector<pair<int,int>> cand;\n        if (a[x][y] > a[x + 1][y]) cand.push_back({x + 1, y});\n        if (a[x][y] > a[x + 1][y + 1]) cand.push_back({x + 1, y + 1});\n        if (cand.empty()) return false;\n\n        int bx = cand[0].first, by = cand[0].second;\n        double best_score = -1e100;\n\n        for (auto [cx, cy] : cand) {\n            double sc = candidate_score(x, y, cx, cy);\n            if (sc > best_score) {\n                best_score = sc;\n                bx = cx;\n                by = cy;\n            }\n        }\n\n        return do_swap(x, y, bx, by);\n    };\n\n    int lastE = total_violations(a);\n    int stagnant = 0;\n\n    for (int pass = 0; pass < 500 && (int)ops.size() < LIM; pass++) {\n        int before_ops = ops.size();\n\n        int mode = pol.order_type;\n        if (mode == 2) mode = pass & 1;\n\n        if (mode == 0) {\n            for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (cell_violation(a, x, y)) repair_cell(x, y);\n                }\n            }\n        } else {\n            for (int x = 0; x < N - 1 && (int)ops.size() < LIM; x++) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (cell_violation(a, x, y)) repair_cell(x, y);\n                }\n            }\n        }\n\n        int E = total_violations(a);\n        if (E == 0) return {true, ops};\n\n        if ((int)ops.size() == before_ops) break;\n        if (E >= lastE) stagnant++;\n        else stagnant = 0;\n        lastE = E;\n\n        if (stagnant >= 30 && ops.size() > 3000) break;\n    }\n\n    return {total_violations(a) == 0, ops};\n}\n\nResult fallback_solve(const Board& init) {\n    Board a = init;\n    vector<Op> ops;\n\n    auto do_swap = [&](int x1, int y1, int x2, int y2) -> bool {\n        if ((int)ops.size() >= LIM) return false;\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n        return true;\n    };\n\n    using Node = tuple<int,int,int,int>;\n    priority_queue<Node> pq;\n    vector<vector<int>> pushed(N);\n    for (int x = 0; x < N; x++) pushed[x].assign(x + 1, 0);\n    int timer = 0;\n\n    auto push_cell = [&](int x, int y) {\n        if (!inside(x, y) || x >= N - 1) return;\n        int s = cell_severity(a, x, y);\n        if (s <= 0) return;\n        pushed[x][y] = ++timer;\n        pq.emplace(s, pushed[x][y], x, y);\n    };\n\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) push_cell(x, y);\n    }\n\n    while (!pq.empty() && (int)ops.size() < LIM) {\n        auto [sold, id, x, y] = pq.top();\n        pq.pop();\n        if (id != pushed[x][y]) continue;\n        int snow = cell_severity(a, x, y);\n        if (snow <= 0) continue;\n        if (snow != sold) {\n            push_cell(x, y);\n            continue;\n        }\n\n        int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n        if (!(a[x][y] > a[x + 1][by])) continue;\n\n        do_swap(x, y, x + 1, by);\n\n        for (int dx = -2; dx <= 2; dx++) {\n            for (int dy = -2; dy <= 2; dy++) {\n                push_cell(x + dx, y + dy);\n                push_cell(x + 1 + dx, by + dy);\n            }\n        }\n    }\n\n    for (int pass = 0; pass < 500 && total_violations(a) > 0 && (int)ops.size() < LIM; pass++) {\n        for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n            for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                if (cell_violation(a, x, y)) {\n                    int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n                    do_swap(x, y, x + 1, by);\n                }\n            }\n        }\n    }\n\n    return {total_violations(a) == 0, ops};\n}\n\nvector<Op> prune_sequence_single_deletion(\n    const Board& init,\n    vector<Op> ops,\n    chrono::steady_clock::time_point start\n) {\n    bool improved = true;\n    int pass = 0;\n\n    while (improved && pass < 3) {\n        improved = false;\n        pass++;\n\n        for (int i = 0; i < (int)ops.size(); i++) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.93) {\n                return ops;\n            }\n\n            if (valid_after_skip(init, ops, i)) {\n                ops.erase(ops.begin() + i);\n                improved = true;\n                i--;\n            }\n        }\n    }\n\n    return ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start = chrono::steady_clock::now();\n\n    Board init{};\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            cin >> init[x][y];\n        }\n    }\n\n    Result best;\n    best.ok = false;\n\n    Result fb = fallback_solve(init);\n    if (fb.ok) best = fb;\n\n    vector<Policy> policies;\n    uint32_t base_seed = 2463534242u;\n\n    for (int order = 0; order < 3; order++) {\n        policies.push_back({order, 1000.0, 1.0, 0.0, 0.0, base_seed += 101});\n        policies.push_back({order, 500.0, 2.0, 0.0, 0.2, base_seed += 101});\n        policies.push_back({order, 200.0, 5.0, 0.1, 0.0, base_seed += 101});\n        policies.push_back({order, 100.0, 10.0, 0.2, 0.5, base_seed += 101});\n        policies.push_back({order, 1000.0, 0.0, 0.0, 1.0, base_seed += 101});\n    }\n\n    for (int i = 0; i < (int)policies.size(); i++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() > 1.15) break;\n\n        Result r = solve_with_policy(init, policies[i]);\n        if (r.ok && (!best.ok || r.ops.size() < best.ops.size())) {\n            best = move(r);\n        }\n    }\n\n    XorShift rng(1234567);\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() > 1.15) break;\n\n        Policy p;\n        p.order_type = rng.randint(3);\n        p.w_vio = 100.0 + rng.randint(1200);\n        p.w_sev = 0.5 + rng.randint(1200) / 100.0;\n        p.w_depth = rng.randint(50) / 100.0;\n        p.w_small = rng.randint(100) / 100.0;\n        p.seed = rng.next();\n\n        Result r = solve_with_policy(init, p);\n        if (r.ok && (!best.ok || r.ops.size() < best.ops.size())) {\n            best = move(r);\n        }\n    }\n\n    if (!best.ok) best = fb;\n\n    if (best.ok) {\n        best.ops = prune_sequence_single_deletion(init, best.ops, start);\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (auto &op : best.ops) {\n        cout << op.x1 << ' ' << op.y1 << ' ' << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c;\n};\n\nint D, N;\nconst int ENTR = 0;\nconst int ENTC = 4;\n\nbool obstacle[9][9];\nbool occupied_[9][9];\nint valAt[9][9];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nbool isEntrance(int r, int c) {\n    return r == ENTR && c == ENTC;\n}\n\n// Reachable empty cells from entrance.\n// Containers and obstacles are blocked.\nvector<vector<int>> reachableEmpty() {\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    queue<pair<int,int>> q;\n\n    if (!obstacle[ENTR][ENTC] && !occupied_[ENTR][ENTC]) {\n        vis[ENTR][ENTC] = 1;\n        q.push({ENTR, ENTC});\n    }\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr, nc)) continue;\n            if (vis[nr][nc]) continue;\n            if (obstacle[nr][nc] || occupied_[nr][nc]) continue;\n            vis[nr][nc] = 1;\n            q.push({nr, nc});\n        }\n    }\n    return vis;\n}\n\n// If we occupy (br,bc), will every remaining empty non-obstacle non-entrance\n// cell still be reachable from entrance?\nbool keepsConnectivity(int br, int bc) {\n    occupied_[br][bc] = true;\n    auto vis = reachableEmpty();\n    occupied_[br][bc] = false;\n\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (isEntrance(r,c)) continue;\n            if (obstacle[r][c]) continue;\n            if (occupied_[r][c]) continue;\n            if (r == br && c == bc) continue;\n            if (!vis[r][c]) return false;\n        }\n    }\n    return true;\n}\n\n// BFS distance from entrance ignoring containers.\nvector<vector<int>> baseDistance() {\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n\n    dist[ENTR][ENTC] = 0;\n    q.push({ENTR, ENTC});\n\n    while (!q.empty()) {\n        auto [r, c] = q.front();\n        q.pop();\n\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (obstacle[nr][nc]) continue;\n            if (dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr,nc});\n        }\n    }\n    return dist;\n}\n\nbool removableContainer(int r, int c, const vector<vector<int>>& emptyReach) {\n    if (!occupied_[r][c]) return false;\n\n    for (int k = 0; k < 4; k++) {\n        int nr = r + dr[k], nc = c + dc[k];\n        if (!inside(nr,nc)) continue;\n        if (emptyReach[nr][nc]) return true;\n    }\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    memset(obstacle, 0, sizeof(obstacle));\n    memset(occupied_, 0, sizeof(occupied_));\n    for (int r = 0; r < 9; r++) {\n        for (int c = 0; c < 9; c++) {\n            valAt[r][c] = -1;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = true;\n    }\n\n    int M = D * D - 1 - N;\n\n    auto dist = baseDistance();\n\n    vector<Cell> allCells;\n    for (int r = 0; r < D; r++) {\n        for (int c = 0; c < D; c++) {\n            if (isEntrance(r,c)) continue;\n            if (obstacle[r][c]) continue;\n            allCells.push_back({r,c});\n        }\n    }\n\n    // Rank: shallow cells small rank, deep cells large rank.\n    sort(allCells.begin(), allCells.end(), [&](const Cell& a, const Cell& b) {\n        int da = dist[a.r][a.c];\n        int db = dist[b.r][b.c];\n        if (da != db) return da < db;\n\n        int sa = abs(a.c - ENTC);\n        int sb = abs(b.c - ENTC);\n        if (sa != sb) return sa < sb;\n\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    int rankOf[9][9];\n    memset(rankOf, -1, sizeof(rankOf));\n    for (int i = 0; i < (int)allCells.size(); i++) {\n        rankOf[allCells[i].r][allCells[i].c] = i;\n    }\n\n    // Online placement\n    for (int d = 0; d < M; d++) {\n        int t;\n        cin >> t;\n\n        auto reach = reachableEmpty();\n\n        Cell best = {-1, -1};\n        long long bestScore = LLONG_MAX;\n\n        // Larger labels are assigned deeper.\n        int targetRank = t;\n\n        // First pass: safe cells only.\n        for (const auto& cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (occupied_[r][c]) continue;\n            if (!reach[r][c]) continue;\n\n            bool safe = keepsConnectivity(r, c);\n            if (!safe) continue;\n\n            int rk = rankOf[r][c];\n\n            long long score = 0;\n            score += 1000LL * abs(rk - targetRank);\n\n            // Prefer occupying farther cells.\n            score -= 20LL * dist[r][c];\n\n            // Slightly avoid main entrance column.\n            if (c == ENTC) score += 100;\n\n            // Prefer side pockets.\n            score -= 5LL * abs(c - ENTC);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = cell;\n            }\n        }\n\n        // Second pass: any reachable cell.\n        if (best.r == -1) {\n            bestScore = LLONG_MAX;\n            for (const auto& cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (occupied_[r][c]) continue;\n                if (!reach[r][c]) continue;\n\n                int rk = rankOf[r][c];\n                long long score = 1000LL * abs(rk - targetRank) - 20LL * dist[r][c];\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = cell;\n                }\n            }\n        }\n\n        // Absolute emergency fallback: choose first empty non-obstacle cell.\n        // In a valid reachable state this should never be used, but prevents -1 output.\n        if (best.r == -1) {\n            for (const auto& cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (!occupied_[r][c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        occupied_[best.r][best.c] = true;\n        valAt[best.r][best.c] = t;\n\n        cout << best.r << \" \" << best.c << '\\n';\n        cout.flush();\n    }\n\n    // Removal phase\n    vector<Cell> answer;\n    answer.reserve(M);\n\n    for (int step = 0; step < M; step++) {\n        auto emptyReach = reachableEmpty();\n\n        Cell best = {-1, -1};\n        int bestVal = INT_MAX;\n\n        // Greedily remove the smallest currently accessible label.\n        for (const auto& cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (!occupied_[r][c]) continue;\n            if (!removableContainer(r,c,emptyReach)) continue;\n\n            if (valAt[r][c] < bestVal) {\n                bestVal = valAt[r][c];\n                best = cell;\n            }\n        }\n\n        // If greedy found nothing, choose any occupied cell as fallback.\n        // This should not happen if placement was valid.\n        if (best.r == -1) {\n            for (const auto& cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (occupied_[r][c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        answer.push_back(best);\n        occupied_[best.r][best.c] = false;\n        valAt[best.r][best.c] = -1;\n    }\n\n    for (const auto& cell : answer) {\n        cout << cell.r << \" \" << cell.c << '\\n';\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 50;\nstatic const int M = 100;\n\nint n, m;\narray<array<int, N>, N> g, bestG;\nbool targetAdj[M + 1][M + 1];\nint colorCnt[M + 1];\n\nchrono::steady_clock::time_point startTime;\nconst double TL = 1.92;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\ninline bool inside(int i, int j) {\n    return 0 <= i && i < n && 0 <= j && j < n;\n}\n\nvoid addAdj(bool adj[M + 1][M + 1], int a, int b) {\n    if (a == b) return;\n    adj[a][b] = adj[b][a] = true;\n}\n\nvoid computeAdj(const array<array<int, N>, N>& grid, bool adj[M + 1][M + 1]) {\n    for (int i = 0; i <= M; i++)\n        for (int j = 0; j <= M; j++)\n            adj[i][j] = false;\n\n    for (int i = 0; i < n; i++) {\n        addAdj(adj, 0, grid[i][0]);\n        addAdj(adj, 0, grid[i][n - 1]);\n    }\n    for (int j = 0; j < n; j++) {\n        addAdj(adj, 0, grid[0][j]);\n        addAdj(adj, 0, grid[n - 1][j]);\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i + 1 < n) addAdj(adj, grid[i][j], grid[i + 1][j]);\n            if (j + 1 < n) addAdj(adj, grid[i][j], grid[i][j + 1]);\n        }\n    }\n}\n\nvoid recount() {\n    memset(colorCnt, 0, sizeof(colorCnt));\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            colorCnt[g[i][j]]++;\n}\n\nbool checkZeroConnected() {\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n\n    for (int i = 0; i < n; i++) {\n        if (g[i][0] == 0 && !vis[i][0]) vis[i][0] = true, q.push({i, 0});\n        if (g[i][n - 1] == 0 && !vis[i][n - 1]) vis[i][n - 1] = true, q.push({i, n - 1});\n    }\n    for (int j = 0; j < n; j++) {\n        if (g[0][j] == 0 && !vis[0][j]) vis[0][j] = true, q.push({0, j});\n        if (g[n - 1][j] == 0 && !vis[n - 1][j]) vis[n - 1][j] = true, q.push({n - 1, j});\n    }\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (!inside(ni, nj) || vis[ni][nj] || g[ni][nj] != 0) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (g[i][j] == 0 && !vis[i][j])\n                return false;\n\n    return true;\n}\n\nbool checkColorConnected(int c) {\n    if (colorCnt[c] <= 0) return false;\n\n    int si = -1, sj = -1;\n    for (int i = 0; i < n && si < 0; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == c) {\n                si = i;\n                sj = j;\n                break;\n            }\n        }\n    }\n\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n    vis[si][sj] = true;\n    q.push({si, sj});\n    int cnt = 0;\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        cnt++;\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (!inside(ni, nj) || vis[ni][nj] || g[ni][nj] != c) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    return cnt == colorCnt[c];\n}\n\nbool fullCheck() {\n    recount();\n\n    if (!checkZeroConnected()) return false;\n\n    for (int c = 1; c <= m; c++)\n        if (!checkColorConnected(c))\n            return false;\n\n    bool curAdj[M + 1][M + 1];\n    computeAdj(g, curAdj);\n\n    for (int i = 0; i <= m; i++)\n        for (int j = 0; j <= m; j++)\n            if (curAdj[i][j] != targetAdj[i][j])\n                return false;\n\n    return true;\n}\n\nint zeroCount() {\n    int z = 0;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (g[i][j] == 0)\n                z++;\n    return z;\n}\n\nbool trySetCell(int i, int j, int nc) {\n    int oc = g[i][j];\n    if (oc == nc) return false;\n    if (oc != 0 && colorCnt[oc] <= 1) return false;\n\n    int oldZero = colorCnt[0];\n\n    g[i][j] = nc;\n    colorCnt[oc]--;\n    colorCnt[nc]++;\n\n    bool ok = fullCheck();\n    bool improveOrNeutral = colorCnt[0] >= oldZero;\n\n    if (!ok || !improveOrNeutral) {\n        g[i][j] = oc;\n        colorCnt[oc]++;\n        colorCnt[nc]--;\n        return false;\n    }\n\n    return true;\n}\n\nbool tryDelete(int i, int j) {\n    if (g[i][j] == 0) return false;\n    return trySetCell(i, j, 0);\n}\n\nvoid greedyDeletion(double untilTime, mt19937& rng) {\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.push_back({i, j});\n\n    int pass = 0;\n    while (elapsed() < untilTime) {\n        pass++;\n\n        if (pass % 4 == 1) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, 49 - a.first, 49 - a.second});\n                int db = min({b.first, b.second, 49 - b.first, 49 - b.second});\n                return da < db;\n            });\n        } else if (pass % 4 == 2) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, 49 - a.first, 49 - a.second});\n                int db = min({b.first, b.second, 49 - b.first, 49 - b.second});\n                return da > db;\n            });\n        } else {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n\n        bool changed = false;\n        for (auto [i, j] : cells) {\n            if (elapsed() >= untilTime) break;\n            if (tryDelete(i, j)) changed = true;\n        }\n\n        if (!changed && pass >= 4) break;\n    }\n}\n\nvector<pair<int,int>> collectBoundaryCells() {\n    vector<pair<int,int>> v;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = g[i][j];\n            bool boundary = false;\n            static const int di[4] = {1, -1, 0, 0};\n            static const int dj[4] = {0, 0, 1, -1};\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) {\n                    if (c != 0) boundary = true;\n                } else if (g[ni][nj] != c) {\n                    boundary = true;\n                }\n            }\n            if (boundary) v.push_back({i, j});\n        }\n    }\n    return v;\n}\n\nvoid reshapePhase(double untilTime, mt19937& rng) {\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    int bestZero = zeroCount();\n    bestG = g;\n\n    while (elapsed() < untilTime) {\n        auto cells = collectBoundaryCells();\n        shuffle(cells.begin(), cells.end(), rng);\n\n        bool changed = false;\n\n        for (auto [i, j] : cells) {\n            if (elapsed() >= untilTime) break;\n\n            int oc = g[i][j];\n            if (oc == 0) continue;\n            if (colorCnt[oc] <= 1) continue;\n\n            vector<int> cand;\n            cand.push_back(0);\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) continue;\n                int nc = g[ni][nj];\n                if (nc != oc) cand.push_back(nc);\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int nc : cand) {\n                if (elapsed() >= untilTime) break;\n                if (nc == oc) continue;\n\n                int beforeZero = colorCnt[0];\n                if (trySetCell(i, j, nc)) {\n                    changed = true;\n\n                    int z = colorCnt[0];\n                    if (z > bestZero) {\n                        bestZero = z;\n                        bestG = g;\n                    }\n\n                    // Prefer real deletion; after one accepted move, go to next cell.\n                    break;\n                } else {\n                    // trySetCell restores itself\n                    (void)beforeZero;\n                }\n            }\n        }\n\n        if (!changed) break;\n\n        // After neutral recolors, try to harvest deletions.\n        greedyDeletion(min(untilTime, elapsed() + 0.25), rng);\n\n        int z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        }\n    }\n\n    g = bestG;\n    recount();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    startTime = chrono::steady_clock::now();\n\n    cin >> n >> m;\n\n    for (int i = 0; i <= M; i++)\n        for (int j = 0; j <= M; j++)\n            targetAdj[i][j] = false;\n\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> g[i][j];\n\n    computeAdj(g, targetAdj);\n    recount();\n\n    mt19937 rng(123456789);\n\n    greedyDeletion(0.70, rng);\n\n    bestG = g;\n    int bestZero = zeroCount();\n\n    while (elapsed() < TL) {\n        reshapePhase(min(TL, elapsed() + 0.40), rng);\n\n        int z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        } else {\n            g = bestG;\n            recount();\n        }\n\n        greedyDeletion(min(TL, elapsed() + 0.25), rng);\n\n        z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        } else {\n            g = bestG;\n            recount();\n        }\n    }\n\n    g = bestG;\n\n    // Safety: if something unexpected happens, the current best is still expected valid\n    // because every accepted move was full-checked.\n    // assert(fullCheck());\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\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    vector<int> ord;              // light -> heavy estimated\n    vector<vector<int>> groups;\n    vector<int> ans;\n\n    char query_vec(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        char c;\n        cin >> c;\n        used++;\n        return c;\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query_vec(L, R);\n    }\n\n    // returns true if item a is lighter than item b\n    bool less_item(int a, int b) {\n        char c = query_single(a, b);\n        return c == '<';\n    }\n\n    // compare current groups\n    // returns -1 if A lighter, 0 if equal/unknown, 1 if A heavier\n    int compare_group(int a, int b) {\n        if (groups[a].empty() && groups[b].empty()) return 0;\n        if (groups[a].empty()) return -1;\n        if (groups[b].empty()) return 1;\n        char c = query_vec(groups[a], groups[b]);\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    void bounded_insertion_sort() {\n        ord.clear();\n        ord.push_back(0);\n\n        for (int i = 1; i < N; i++) {\n            if (used >= Q) {\n                ord.push_back(i);\n                continue;\n            }\n\n            // Binary insertion if enough budget, otherwise linear fallback.\n            int lo = 0, hi = (int)ord.size();\n            while (lo < hi && used < Q) {\n                int mid = (lo + hi) / 2;\n                // if i < ord[mid], go left\n                bool lt = less_item(i, ord[mid]);\n                if (lt) hi = mid;\n                else lo = mid + 1;\n            }\n            ord.insert(ord.begin() + lo, i);\n        }\n\n        // If sorting was interrupted, ord still contains all items.\n        vector<int> seen(N, 0);\n        for (int x : ord) seen[x] = 1;\n        for (int i = 0; i < N; i++) {\n            if (!seen[i]) ord.push_back(i);\n        }\n    }\n\n    int find_lightest_group() {\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (used >= Q) break;\n            int cmp = compare_group(g, best);\n            if (cmp == -1) best = g;\n        }\n        return best;\n    }\n\n    void make_partition() {\n        groups.assign(D, {});\n        ans.assign(N, 0);\n\n        // Put heaviest estimated items first.\n        vector<int> heavy_to_light = ord;\n        reverse(heavy_to_light.begin(), heavy_to_light.end());\n\n        for (int item : heavy_to_light) {\n            int g;\n            if (used + D - 1 <= Q) {\n                g = find_lightest_group();\n            } else {\n                // query budget is tight: deterministic fallback\n                int mn = 0;\n                for (int i = 1; i < D; i++) {\n                    if (groups[i].size() < groups[mn].size()) mn = i;\n                }\n                g = mn;\n            }\n            groups[g].push_back(item);\n            ans[item] = g;\n        }\n    }\n\n    void spend_remaining_queries() {\n        // Use remaining queries in harmless but somewhat informative ways.\n        int ptr = 0;\n        while (used < Q) {\n            bool done = false;\n\n            // Prefer comparing non-empty groups.\n            for (int k = 0; k < D && used < Q; k++) {\n                int a = (ptr + k) % D;\n                int b = (ptr + k + 1) % D;\n                if (a == b) continue;\n                if (!groups[a].empty() && !groups[b].empty()) {\n                    query_vec(groups[a], groups[b]);\n                    done = true;\n                    break;\n                }\n            }\n            ptr++;\n\n            if (!done && used < Q) {\n                int a = used % N;\n                int b = (a + 1) % N;\n                query_single(a, b);\n            }\n        }\n    }\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        bounded_insertion_sort();\n\n        if (used < Q) {\n            make_partition();\n        } else {\n            // No budget left: simple sorted round-robin.\n            groups.assign(D, {});\n            ans.assign(N, 0);\n            vector<int> heavy_to_light = ord;\n            reverse(heavy_to_light.begin(), heavy_to_light.end());\n            for (int i = 0; i < (int)heavy_to_light.size(); i++) {\n                int g = i % D;\n                ans[heavy_to_light[i]] = g;\n                groups[g].push_back(heavy_to_light[i]);\n            }\n        }\n\n        spend_remaining_queries();\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << ans[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Config {\n    int mode; // 0 = rollout/structure, 1 = bucket-biased\n    int rolloutHorizon;\n    double costW;\n    double emptyBonus;\n    double goodBoundaryBonus;\n    double badBoundaryPenalty;\n    double badBoundaryDiffW;\n    double heightW;\n    double nearDepthW;\n    double topSmallBonus;\n    double coverSmallPenalty;\n    double staticW;\n    double bucketW;\n    int bucketSize;\n};\n\nstruct Result {\n    vector<pair<int,int>> ops;\n    int energy;\n};\n\nstruct PortfolioSolver {\n    int n, m;\n    vector<vector<int>> init;\n\n    PortfolioSolver(int n_, int m_, vector<vector<int>> init_)\n        : n(n_), m(m_), init(std::move(init_)) {}\n\n    int find_stack(const vector<vector<int>>& a, int v) const {\n        for (int i = 0; i < m; i++) {\n            for (int x : a[i]) if (x == v) return i;\n        }\n        return -1;\n    }\n\n    int find_index(const vector<int>& s, int v) const {\n        for (int i = 0; i < (int)s.size(); i++) {\n            if (s[i] == v) return i;\n        }\n        return -1;\n    }\n\n    int remove_greedy_sim(vector<vector<int>>& a, int cur, int limitCur) const {\n        bool changed = true;\n        while (cur <= limitCur && changed) {\n            changed = false;\n            for (int i = 0; i < m; i++) {\n                if (!a[i].empty() && a[i].back() == cur) {\n                    a[i].pop_back();\n                    cur++;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        return cur;\n    }\n\n    int bucket(int x, int bs) const {\n        return (x - 1) / bs;\n    }\n\n    double bucket_eval_stack(const vector<int>& s, int cur, const Config& cfg) const {\n        if (s.empty()) return -cfg.emptyBonus * 0.2;\n\n        double sc = 0.0;\n        int h = (int)s.size();\n\n        for (int j = 0; j + 1 < h; j++) {\n            int lower = s[j];\n            int upper = s[j + 1];\n\n            int bl = bucket(lower, cfg.bucketSize);\n            int bu = bucket(upper, cfg.bucketSize);\n\n            // Desired: lower value-range >= upper value-range.\n            if (bl < bu) {\n                sc += cfg.bucketW * (1 + bu - bl);\n                if (lower < cur + 50) sc += cfg.bucketW;\n            } else if (bl == bu) {\n                if (lower < upper) sc += cfg.bucketW * 0.6;\n                else sc -= cfg.bucketW * 0.15;\n            } else {\n                sc -= cfg.bucketW * 0.25;\n            }\n        }\n\n        // Boxes coming soon should be high.\n        for (int j = 0; j < h; j++) {\n            int v = s[j];\n            if (v >= cur && v < cur + 50) {\n                int above = h - 1 - j;\n                sc += above * (55 - (v - cur)) * 0.025 * cfg.bucketW;\n            }\n        }\n\n        return sc;\n    }\n\n    double static_eval(const vector<vector<int>>& a, int cur, const Config& cfg) const {\n        double score = 0.0;\n\n        for (int i = 0; i < m; i++) {\n            const auto& s = a[i];\n            int h = (int)s.size();\n\n            score += cfg.heightW * h;\n\n            for (int j = 0; j + 1 < h; j++) {\n                int lower = s[j];\n                int upper = s[j + 1];\n\n                if (lower < upper) {\n                    score += cfg.badBoundaryPenalty * 0.07;\n                    if (lower < cur + 45) score += cfg.badBoundaryPenalty * 0.07;\n                } else {\n                    score -= cfg.goodBoundaryBonus * 0.01;\n                }\n            }\n\n            for (int j = 0; j < h; j++) {\n                int v = s[j];\n                if (v >= cur && v < cur + 40) {\n                    int above = h - 1 - j;\n                    score += above * (42 - (v - cur)) * cfg.nearDepthW * 0.02;\n                }\n            }\n\n            if (!s.empty()) {\n                int top = s.back();\n                if (top >= cur && top < cur + 30) {\n                    score -= (32 - (top - cur)) * cfg.topSmallBonus * 0.03;\n                }\n            }\n\n            if (cfg.mode == 1) {\n                score += bucket_eval_stack(s, cur, cfg);\n            }\n        }\n\n        return score;\n    }\n\n    double destination_score(\n        const vector<vector<int>>& a,\n        int dst,\n        int src,\n        const vector<int>& seg,\n        int cur,\n        const Config& cfg\n    ) const {\n        int k = (int)seg.size();\n        int bottom = seg.front();\n        int topSeg = seg.back();\n        int segMin = *min_element(seg.begin(), seg.end());\n\n        double sc = 0.0;\n\n        if (a[dst].empty()) {\n            sc -= cfg.emptyBonus;\n            sc += k * 1.5;\n        } else {\n            int top = a[dst].back();\n\n            if (top > bottom) {\n                sc -= cfg.goodBoundaryBonus;\n                sc += (top - bottom) * 0.7;\n            } else {\n                sc += cfg.badBoundaryPenalty;\n                sc += (bottom - top) * cfg.badBoundaryDiffW;\n            }\n\n            if (top < cur + 25) {\n                sc += cfg.coverSmallPenalty;\n                sc += (cur + 25 - top) * 3.0;\n            }\n\n            sc += abs(top - bottom) * 0.35;\n\n            if (cfg.mode == 1) {\n                int bt = bucket(top, cfg.bucketSize);\n                int bb = bucket(bottom, cfg.bucketSize);\n                int bm = bucket(segMin, cfg.bucketSize);\n\n                // Prefer placing a segment on a later bucket.\n                if (bt > bb) {\n                    sc -= cfg.bucketW * (1 + bt - bb);\n                } else if (bt == bb) {\n                    if (top > bottom) sc -= cfg.bucketW * 0.4;\n                    else sc += cfg.bucketW * 0.8;\n                } else {\n                    sc += cfg.bucketW * (2 + bb - bt);\n                }\n\n                // Avoid covering destination tops from soon buckets.\n                if (top < cur + cfg.bucketSize * 2) {\n                    sc += cfg.bucketW * 2.5;\n                }\n\n                // If segment has soon boxes, keep it on shorter stacks.\n                if (segMin < cur + cfg.bucketSize * 2) {\n                    sc += (int)a[dst].size() * cfg.bucketW * 0.25;\n                }\n\n                // Encourage grouping by minimum bucket.\n                if (bt >= bm) sc -= cfg.bucketW * 0.5;\n            }\n        }\n\n        sc += (int)a[dst].size() * cfg.heightW;\n\n        if (segMin < cur + 25) sc += (int)a[dst].size() * cfg.nearDepthW;\n        if (topSeg < cur + 20) sc += (int)a[dst].size() * cfg.nearDepthW * 0.8;\n\n        return sc;\n    }\n\n    int choose_dst(\n        const vector<vector<int>>& st,\n        int src,\n        int idx,\n        int cur,\n        const Config& cfg\n    ) const {\n        vector<int> seg;\n        for (int j = idx + 1; j < (int)st[src].size(); j++) seg.push_back(st[src][j]);\n\n        int k = (int)seg.size();\n\n        int bestDst = -1;\n        double bestScore = 1e100;\n\n        for (int dst = 0; dst < m; dst++) {\n            if (dst == src) continue;\n\n            vector<vector<int>> a = st;\n\n            for (int x : seg) a[dst].push_back(x);\n            a[src].resize(idx + 1);\n\n            double futureCost = k + 1;\n            int simCur = cur;\n            simCur = remove_greedy_sim(a, simCur, n);\n\n            int rolloutEnd = min(n, cur + cfg.rolloutHorizon);\n            int steps = 0;\n\n            while (simCur <= rolloutEnd && steps < cfg.rolloutHorizon) {\n                int s = find_stack(a, simCur);\n                if (s < 0) {\n                    simCur++;\n                    continue;\n                }\n\n                int id = find_index(a[s], simCur);\n                if (id == (int)a[s].size() - 1) {\n                    simCur = remove_greedy_sim(a, simCur, rolloutEnd);\n                    continue;\n                }\n\n                vector<int> sg;\n                for (int j = id + 1; j < (int)a[s].size(); j++) sg.push_back(a[s][j]);\n                int kk = (int)sg.size();\n\n                int bd = -1;\n                double bs = 1e100;\n                for (int d = 0; d < m; d++) {\n                    if (d == s) continue;\n                    double ds = destination_score(a, d, s, sg, simCur, cfg);\n                    if (ds < bs) {\n                        bs = ds;\n                        bd = d;\n                    }\n                }\n\n                futureCost += kk + 1;\n\n                for (int x : sg) a[bd].push_back(x);\n                a[s].resize(id + 1);\n\n                simCur = remove_greedy_sim(a, simCur, rolloutEnd);\n                steps++;\n            }\n\n            double totalScore = cfg.costW * futureCost\n                              + cfg.staticW * static_eval(a, simCur, cfg)\n                              + destination_score(st, dst, src, seg, cur, cfg) * 0.15;\n\n            if (totalScore < bestScore) {\n                bestScore = totalScore;\n                bestDst = dst;\n            }\n        }\n\n        if (bestDst == -1) bestDst = (src + 1) % m;\n        return bestDst;\n    }\n\n    Result run_one(const Config& cfg) const {\n        vector<vector<int>> st = init;\n        vector<pair<int,int>> ops;\n        int energy = 0;\n        int cur = 1;\n\n        auto real_remove = [&]() {\n            bool changed = true;\n            while (cur <= n && changed) {\n                changed = false;\n                for (int i = 0; i < m; i++) {\n                    if (!st[i].empty() && st[i].back() == cur) {\n                        st[i].pop_back();\n                        ops.push_back({cur, 0});\n                        cur++;\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n        };\n\n        real_remove();\n\n        while (cur <= n && (int)ops.size() < 5000) {\n            int src = find_stack(st, cur);\n            if (src < 0) {\n                real_remove();\n                continue;\n            }\n\n            int idx = find_index(st[src], cur);\n\n            if (idx == (int)st[src].size() - 1) {\n                real_remove();\n                continue;\n            }\n\n            int dst = choose_dst(st, src, idx, cur, cfg);\n\n            int v = st[src][idx + 1];\n            int k = (int)st[src].size() - (idx + 1);\n\n            ops.push_back({v, dst + 1});\n            energy += k + 1;\n\n            for (int j = idx + 1; j < (int)st[src].size(); j++) {\n                st[dst].push_back(st[src][j]);\n            }\n            st[src].resize(idx + 1);\n\n            real_remove();\n        }\n\n        return {ops, energy};\n    }\n\n    Result solve() const {\n        vector<Config> configs = {\n            // Previous rollout family.\n            {0, 45, 100.0, 250.0, 180.0, 350.0, 5.0, 3.0, 4.0, 30.0, 500.0, 1.0, 0.0, 20},\n            {0, 55, 125.0, 220.0, 160.0, 380.0, 5.5, 3.0, 5.0, 25.0, 550.0, 0.8, 0.0, 20},\n            {0, 50, 90.0, 260.0, 220.0, 420.0, 6.0, 4.0, 5.5, 35.0, 650.0, 1.4, 0.0, 20},\n            {0, 45, 105.0, 350.0, 170.0, 360.0, 5.0, 3.5, 4.5, 30.0, 520.0, 1.0, 0.0, 20},\n            {0, 50, 100.0, 240.0, 170.0, 340.0, 5.0, 3.0, 4.5, 30.0, 850.0, 1.0, 0.0, 20},\n            {0, 55, 100.0, 230.0, 260.0, 430.0, 6.0, 3.0, 4.2, 35.0, 550.0, 1.1, 0.0, 20},\n            {0, 30, 120.0, 260.0, 190.0, 350.0, 4.5, 2.5, 3.5, 25.0, 450.0, 0.7, 0.0, 20},\n            {0, 70, 115.0, 220.0, 180.0, 360.0, 5.0, 3.5, 4.5, 30.0, 600.0, 1.0, 0.0, 20},\n            {0, 50, 100.0, 260.0, 180.0, 360.0, 5.0, 6.0, 5.0, 30.0, 550.0, 1.0, 0.0, 20},\n            {0, 55, 105.0, 240.0, 180.0, 380.0, 5.5, 3.0, 8.0, 35.0, 600.0, 1.2, 0.0, 20},\n\n            // Bucket-biased family.\n            {1, 45, 105.0, 260.0, 190.0, 380.0, 5.0, 3.0, 4.5, 30.0, 550.0, 1.0, 45.0, 20},\n            {1, 55, 110.0, 240.0, 200.0, 400.0, 5.5, 3.0, 5.0, 30.0, 600.0, 1.1, 55.0, 20},\n            {1, 60, 100.0, 280.0, 220.0, 420.0, 6.0, 4.0, 5.5, 35.0, 650.0, 1.2, 65.0, 25},\n            {1, 40, 120.0, 300.0, 180.0, 360.0, 5.0, 3.0, 4.0, 25.0, 520.0, 0.9, 50.0, 15},\n            {1, 70, 105.0, 230.0, 240.0, 440.0, 6.0, 3.5, 5.0, 35.0, 650.0, 1.2, 60.0, 20},\n            {1, 50, 95.0, 320.0, 180.0, 380.0, 5.0, 5.0, 6.0, 35.0, 700.0, 1.4, 70.0, 25},\n        };\n\n        Result best;\n        best.energy = INT_MAX;\n\n        for (const auto& cfg : configs) {\n            Result r = run_one(cfg);\n            if ((int)r.ops.size() <= 5000 && r.energy < best.energy) {\n                best = std::move(r);\n            }\n        }\n\n        return best;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> st(m);\n    int h = n / m;\n    for (int i = 0; i < m; i++) {\n        st[i].resize(h);\n        for (int j = 0; j < h; j++) cin >> st[i][j];\n    }\n\n    PortfolioSolver solver(n, m, st);\n    Result res = solver.solve();\n\n    for (auto [v, to] : res.ops) {\n        cout << v << ' ' << to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    char c;\n};\n\nstruct Candidate {\n    string route;\n    long double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startClock = chrono::steady_clock::now();\n    auto elapsed = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - startClock).count();\n    };\n\n    int N;\n    cin >> N;\n\n    vector<string> h(N - 1), v(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> v[i];\n\n    vector<vector<int>> d2(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> d2[i][j];\n    }\n\n    const int LIMIT = 100000;\n    int V = N * N;\n\n    auto id = [&](int i, int j) { return i * N + j; };\n    auto pos = [&](int x) { return pair<int,int>{x / N, x % N}; };\n\n    vector<int> dirt(V);\n    long long totalDirt = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            dirt[id(i, j)] = d2[i][j];\n            totalDirt += d2[i][j];\n        }\n    }\n\n    vector<vector<Edge>> g(V);\n\n    auto add_edge = [&](int a, int b, char c) {\n        g[a].push_back({b, c});\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int cur = id(i, j);\n            if (i + 1 < N && h[i][j] == '0') {\n                add_edge(cur, id(i + 1, j), 'D');\n                add_edge(id(i + 1, j), cur, 'U');\n            }\n            if (j + 1 < N && v[i][j] == '0') {\n                add_edge(cur, id(i, j + 1), 'R');\n                add_edge(id(i, j + 1), cur, 'L');\n            }\n        }\n    }\n\n    auto opposite = [&](char c) {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        return 'L';\n    };\n\n    vector<vector<int>> dist(V, vector<int>(V, -1));\n    vector<vector<int>> par(V, vector<int>(V, -1));\n    vector<vector<char>> parMove(V, vector<char>(V, '?'));\n\n    for (int s = 0; s < V; s++) {\n        queue<int> q;\n        dist[s][s] = 0;\n        q.push(s);\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            vector<Edge> es = g[u];\n            sort(es.begin(), es.end(), [&](const Edge& a, const Edge& b) {\n                return dirt[a.to] > dirt[b.to];\n            });\n\n            for (auto e : es) {\n                if (dist[s][e.to] == -1) {\n                    dist[s][e.to] = dist[s][u] + 1;\n                    par[s][e.to] = u;\n                    parMove[s][e.to] = e.c;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n\n    auto get_path = [&](int s, int t) {\n        string rev;\n        int cur = t;\n        while (cur != s) {\n            char c = parMove[s][cur];\n            rev.push_back(c);\n            cur = par[s][cur];\n        }\n        reverse(rev.begin(), rev.end());\n        return rev;\n    };\n\n    auto step_to = [&](int cur, char c) {\n        for (auto e : g[cur]) {\n            if (e.c == c) return e.to;\n        }\n        return -1;\n    };\n\n    auto evaluate = [&](const string& route) -> long double {\n        int L = (int)route.size();\n        if (L <= 0 || L > LIMIT) return 1e100L;\n\n        vector<vector<int>> visits(V);\n        int cur = 0;\n\n        for (int t = 1; t <= L; t++) {\n            cur = step_to(cur, route[t - 1]);\n            if (cur < 0) return 1e100L;\n            visits[cur].push_back(t);\n        }\n\n        if (cur != 0) return 1e100L;\n\n        for (int x = 0; x < V; x++) {\n            if (visits[x].empty()) return 1e100L;\n        }\n\n        long double total = 0;\n        for (int x = 0; x < V; x++) {\n            auto &ts = visits[x];\n\n            long long tri = 0;\n            int m = (int)ts.size();\n\n            for (int k = 0; k < m; k++) {\n                int a = ts[k];\n                int b = ts[(k + 1) % m];\n                int gap = (k + 1 < m ? b - a : b + L - a);\n                tri += 1LL * gap * (gap - 1) / 2;\n            }\n\n            total += (long double)dirt[x] * (long double)tri / (long double)L;\n        }\n\n        return total;\n    };\n\n    vector<Candidate> cands;\n\n    auto add_candidate = [&](const string& s) {\n        if (s.empty() || (int)s.size() > LIMIT) return;\n        long double sc = evaluate(s);\n        if (sc < 1e90L) cands.push_back({s, sc});\n    };\n\n    auto priority_value = [&](int x, int mode) -> long double {\n        auto [i, j] = pos(x);\n        long double center = abs(i - (N - 1) / 2.0L) + abs(j - (N - 1) / 2.0L);\n        long double val = 0;\n\n        switch (mode) {\n            case 0: val = dirt[x]; break;\n            case 1: val = -dirt[x]; break;\n            case 2: val = i * N + j; break;\n            case 3: val = -(i * N + j); break;\n            case 4: val = i + j; break;\n            case 5: val = -(i + j); break;\n            case 6: val = i - j; break;\n            case 7: val = j - i; break;\n            case 8: val = -center; break;\n            case 9: val = center; break;\n            case 10: val = dirt[x] - 5.0L * center; break;\n            case 11: val = dirt[x] + 5.0L * center; break;\n            default: val = dirt[x]; break;\n        }\n        return val;\n    };\n\n    auto make_dfs_candidate = [&](int buildMode, int orderMode) {\n        vector<int> vis(V, 0), parent(V, -1);\n        vector<char> pm(V, '?');\n        vector<vector<int>> tree(V);\n\n        function<void(int)> build = [&](int u) {\n            vis[u] = 1;\n            vector<Edge> es = g[u];\n\n            sort(es.begin(), es.end(), [&](const Edge& a, const Edge& b) {\n                long double pa = priority_value(a.to, buildMode);\n                long double pb = priority_value(b.to, buildMode);\n                if (pa != pb) return pa > pb;\n                return a.to < b.to;\n            });\n\n            for (auto e : es) {\n                if (!vis[e.to]) {\n                    parent[e.to] = u;\n                    pm[e.to] = e.c;\n                    tree[u].push_back(e.to);\n                    build(e.to);\n                }\n            }\n        };\n\n        build(0);\n\n        vector<long long> subD(V, 0);\n        vector<int> subSz(V, 0);\n\n        function<void(int)> calc = [&](int u) {\n            subD[u] = dirt[u];\n            subSz[u] = 1;\n            for (int to : tree[u]) {\n                calc(to);\n                subD[u] += subD[to];\n                subSz[u] += subSz[to];\n            }\n        };\n        calc(0);\n\n        for (int u = 0; u < V; u++) {\n            sort(tree[u].begin(), tree[u].end(), [&](int a, int b) {\n                if (orderMode == 0) return subD[a] > subD[b];\n                if (orderMode == 1) return subD[a] < subD[b];\n                if (orderMode == 2) return dirt[a] > dirt[b];\n                if (orderMode == 3) return dirt[a] < dirt[b];\n                if (orderMode == 4) return subSz[a] > subSz[b];\n                if (orderMode == 5) return subSz[a] < subSz[b];\n\n                auto [ai, aj] = pos(a);\n                auto [bi, bj] = pos(b);\n\n                if (orderMode == 6) return ai + aj < bi + bj;\n                if (orderMode == 7) return ai + aj > bi + bj;\n                if (orderMode == 8) return ai - aj < bi - bj;\n                return ai - aj > bi - bj;\n            });\n        }\n\n        string ans;\n        ans.reserve(2 * V + 10);\n\n        function<void(int)> tour = [&](int u) {\n            for (int to : tree[u]) {\n                ans.push_back(pm[to]);\n                tour(to);\n                ans.push_back(opposite(pm[to]));\n            }\n        };\n\n        tour(0);\n        return ans;\n    };\n\n    // More deterministic DFS candidates.\n    vector<int> buildModes = {0,1,2,3,4,5,6,7,8,9,10,11};\n    vector<int> orderModes = {0,1,2,3,4,5,6,7,8,9};\n    for (int bm : buildModes) {\n        for (int om : orderModes) {\n            if (elapsed() > 1.3) break;\n            add_candidate(make_dfs_candidate(bm, om));\n        }\n    }\n\n    auto make_greedy_cover = [&](int mode, double noise, mt19937 &rng) {\n        vector<char> unvis(V, 1);\n        unvis[0] = 0;\n        int remain = V - 1;\n        int cur = 0;\n        string ans;\n        ans.reserve(10000);\n        uniform_real_distribution<double> ur(-1.0, 1.0);\n\n        while (remain > 0) {\n            int best = -1;\n            long double bestScore = -1e100L;\n\n            for (int x = 0; x < V; x++) if (unvis[x]) {\n                int dd = max(1, dist[cur][x]);\n                auto [ci, cj] = pos(cur);\n                auto [xi, xj] = pos(x);\n                long double geo = abs(xi - ci) + abs(xj - cj);\n                long double score = 0;\n\n                if (mode == 0) score = -dd;\n                else if (mode == 1) score = (long double)dirt[x] / dd;\n                else if (mode == 2) score = (long double)dirt[x] / sqrt((long double)dd);\n                else if (mode == 3) score = (long double)dirt[x] - 10.0L * dd;\n                else if (mode == 4) score = (long double)sqrt((long double)dirt[x]) - dd;\n                else if (mode == 5) score = -dd + 0.05L * dirt[x] - 0.1L * geo;\n                else if (mode == 6) score = -dd + 0.02L * dirt[x] + 0.5L * geo;\n                else if (mode == 7) score = (long double)dirt[x] / (dd + 5);\n                else if (mode == 8) score = (long double)dirt[x] / pow((long double)dd, 0.75L);\n                else score = -dd + 0.01L * dirt[x];\n\n                score += noise * ur(rng);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = x;\n                }\n            }\n\n            string p = get_path(cur, best);\n            for (char c : p) {\n                ans.push_back(c);\n                cur = step_to(cur, c);\n                if (unvis[cur]) {\n                    unvis[cur] = 0;\n                    remain--;\n                }\n            }\n\n            if ((int)ans.size() > 90000) break;\n        }\n\n        ans += get_path(cur, 0);\n        return ans;\n    };\n\n    mt19937 rng(1234567);\n\n    for (int mode = 0; mode < 10; mode++) {\n        if (elapsed() > 1.5) break;\n        add_candidate(make_greedy_cover(mode, 0.0, rng));\n    }\n\n    int randomTrials = 0;\n    while (elapsed() < 1.75 && randomTrials < 80) {\n        int mode = randomTrials % 10;\n        double noise = 0.5 + (randomTrials % 7) * 0.8;\n        string s = make_greedy_cover(mode, noise, rng);\n        add_candidate(s);\n        randomTrials++;\n    }\n\n    // Hybrid candidates: concatenate several good short candidates if exact score improves.\n    sort(cands.begin(), cands.end(), [](const Candidate& a, const Candidate& b) {\n        return a.score < b.score;\n    });\n\n    int baseCount = min<int>(8, cands.size());\n    vector<string> extra;\n    for (int i = 0; i < baseCount; i++) {\n        for (int j = 0; j < baseCount; j++) {\n            if (i == j) continue;\n            if ((int)cands[i].route.size() + (int)cands[j].route.size() <= LIMIT) {\n                extra.push_back(cands[i].route + cands[j].route);\n            }\n        }\n    }\n\n    for (string &s : extra) {\n        if (elapsed() > 1.9) break;\n        add_candidate(s);\n    }\n\n    int bestIdx = 0;\n    for (int i = 1; i < (int)cands.size(); i++) {\n        if (cands[i].score < cands[bestIdx].score) bestIdx = i;\n    }\n\n    cout << cands[bestIdx].route << '\\n';\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int r, c;\n};\n\nint mdist(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint overlap_len(const string& a, const string& b) {\n    int best = 0;\n    for (int k = 1; k <= 4; k++) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[5 - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) best = k;\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    Pos start;\n    cin >> start.r >> start.c;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    vector<vector<Pos>> occ(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            occ[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) ov[i][j] = overlap_len(t[i], t[j]);\n        }\n    }\n\n    vector<vector<int>> letter_cost(26, vector<int>(26, 1000000));\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            for (auto& p : occ[a]) {\n                for (auto& q : occ[b]) {\n                    letter_cost[a][b] = min(letter_cost[a][b], mdist(p, q) + 1);\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> trans_cost(M, vector<int>(M, 0));\n    for (int a = 0; a < M; a++) {\n        for (int b = 0; b < M; b++) {\n            if (a == b) continue;\n\n            int k = ov[a][b];\n            int cost = 0;\n            char prev = t[a].back();\n\n            for (int p = k; p < 5; p++) {\n                char ch = t[b][p];\n                cost += letter_cost[prev - 'A'][ch - 'A'];\n                prev = ch;\n            }\n\n            trans_cost[a][b] = cost;\n        }\n    }\n\n    const int BIG = 10000;\n    const int PHYS_W = 18;\n\n    vector<vector<int>> edge(M, vector<int>(M, 0));\n    for (int a = 0; a < M; a++) {\n        for (int b = 0; b < M; b++) {\n            if (a == b) edge[a][b] = 0;\n            else edge[a][b] = (5 - ov[a][b]) * BIG + PHYS_W * trans_cost[a][b];\n        }\n    }\n\n    auto order_value = [&](const vector<int>& ord) {\n        int v = 5 * BIG;\n        for (int i = 1; i < M; i++) {\n            v += edge[ord[i - 1]][ord[i]];\n        }\n        return v;\n    };\n\n    auto build_string = [&](const vector<int>& ord) {\n        string s = t[ord[0]];\n        for (int i = 1; i < M; i++) {\n            int k = ov[ord[i - 1]][ord[i]];\n            s += t[ord[i]].substr(k);\n        }\n        return s;\n    };\n\n    mt19937 rng(314159265);\n\n    auto make_greedy = [&](int st, double noise, double cw) {\n        vector<int> ord;\n        vector<char> used(M, false);\n        ord.reserve(M);\n\n        int cur = st;\n        ord.push_back(cur);\n        used[cur] = true;\n\n        for (int step = 1; step < M; step++) {\n            int best = -1;\n            double best_score = -1e100;\n\n            for (int nxt = 0; nxt < M; nxt++) {\n                if (used[nxt]) continue;\n\n                int k = ov[cur][nxt];\n\n                int mxout = 0;\n                for (int z = 0; z < M; z++) {\n                    if (!used[z] && z != nxt) {\n                        mxout = max(mxout, ov[nxt][z]);\n                    }\n                }\n\n                double score = 0.0;\n                score += 1250.0 * k;\n                score += 18.0 * mxout;\n                score -= cw * trans_cost[cur][nxt];\n\n                if (noise > 0) {\n                    score += uniform_real_distribution<double>(0.0, noise)(rng);\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best = nxt;\n                }\n            }\n\n            cur = best;\n            used[cur] = true;\n            ord.push_back(cur);\n        }\n\n        return ord;\n    };\n\n    vector<int> best_ord;\n    int best_val = INT_MAX;\n\n    auto try_order = [&](const vector<int>& ord) {\n        int v = order_value(ord);\n        if (v < best_val) {\n            best_val = v;\n            best_ord = ord;\n        }\n    };\n\n    for (int st = 0; st < M; st++) {\n        try_order(make_greedy(st, 0.0, 2.5));\n    }\n\n    auto global_start = chrono::steady_clock::now();\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n        if (elapsed > 0.45) break;\n\n        int st = uniform_int_distribution<int>(0, M - 1)(rng);\n        double noise = uniform_real_distribution<double>(50.0, 650.0)(rng);\n        double cw = uniform_real_distribution<double>(0.5, 6.0)(rng);\n\n        try_order(make_greedy(st, noise, cw));\n    }\n\n    auto get_edge = [&](int a, int b) -> int {\n        if (a < 0 || b < 0) return 0;\n        return edge[a][b];\n    };\n\n    auto improve_swaps = [&]() {\n        bool improved = false;\n\n        for (int i = 0; i < M; i++) {\n            for (int j = i + 1; j < M; j++) {\n                int ai = best_ord[i];\n                int aj = best_ord[j];\n\n                int before = 0, after = 0;\n\n                if (i > 0) before += get_edge(best_ord[i - 1], best_ord[i]);\n                if (i + 1 < M) before += get_edge(best_ord[i], best_ord[i + 1]);\n                if (j > 0 && j - 1 != i) before += get_edge(best_ord[j - 1], best_ord[j]);\n                if (j + 1 < M) before += get_edge(best_ord[j], best_ord[j + 1]);\n\n                swap(best_ord[i], best_ord[j]);\n\n                if (i > 0) after += get_edge(best_ord[i - 1], best_ord[i]);\n                if (i + 1 < M) after += get_edge(best_ord[i], best_ord[i + 1]);\n                if (j > 0 && j - 1 != i) after += get_edge(best_ord[j - 1], best_ord[j]);\n                if (j + 1 < M) after += get_edge(best_ord[j], best_ord[j + 1]);\n\n                if (after < before) {\n                    best_val += after - before;\n                    improved = true;\n                } else {\n                    swap(best_ord[i], best_ord[j]);\n                }\n            }\n        }\n\n        return improved;\n    };\n\n    auto improve_reversal = [&]() {\n        bool improved = false;\n\n        for (int l = 0; l < M; l++) {\n            for (int r = l + 2; r < M; r++) {\n                int before = 0, after = 0;\n\n                if (l > 0) before += get_edge(best_ord[l - 1], best_ord[l]);\n                if (r + 1 < M) before += get_edge(best_ord[r], best_ord[r + 1]);\n\n                if (l > 0) after += get_edge(best_ord[l - 1], best_ord[r]);\n                if (r + 1 < M) after += get_edge(best_ord[l], best_ord[r + 1]);\n\n                // Internal directed edges are not preserved by reversal.\n                // Therefore only use reversal for short segments and compute exact local delta.\n                if (r - l <= 8) {\n                    before = 0;\n                    after = 0;\n\n                    for (int k = max(1, l); k <= r; k++) {\n                        before += get_edge(best_ord[k - 1], best_ord[k]);\n                    }\n                    if (r + 1 < M) before += get_edge(best_ord[r], best_ord[r + 1]);\n\n                    vector<int> tmp(best_ord.begin() + l, best_ord.begin() + r + 1);\n                    reverse(tmp.begin(), tmp.end());\n\n                    vector<int> seg = best_ord;\n                    reverse(seg.begin() + l, seg.begin() + r + 1);\n\n                    for (int k = max(1, l); k <= r; k++) {\n                        after += get_edge(seg[k - 1], seg[k]);\n                    }\n                    if (r + 1 < M) after += get_edge(seg[r], seg[r + 1]);\n                } else {\n                    continue;\n                }\n\n                if (after < before) {\n                    reverse(best_ord.begin() + l, best_ord.begin() + r + 1);\n                    best_val += after - before;\n                    improved = true;\n                }\n            }\n        }\n\n        return improved;\n    };\n\n    for (int round = 0; round < 4; round++) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n        if (elapsed > 1.15) break;\n\n        bool a = improve_swaps();\n\n        elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n        if (elapsed > 1.35) break;\n\n        bool b = improve_reversal();\n\n        if (!a && !b) break;\n    }\n\n    string s = build_string(best_ord);\n\n    int L = s.size();\n    const int INF = 1e9;\n\n    vector<vector<int>> dp(L);\n    vector<vector<int>> pre(L);\n\n    int c0 = s[0] - 'A';\n    dp[0].assign(occ[c0].size(), INF);\n    pre[0].assign(occ[c0].size(), -1);\n\n    for (int i = 0; i < (int)occ[c0].size(); i++) {\n        dp[0][i] = mdist(start, occ[c0][i]) + 1;\n    }\n\n    for (int p = 1; p < L; p++) {\n        int pc = s[p - 1] - 'A';\n        int cc = s[p] - 'A';\n\n        dp[p].assign(occ[cc].size(), INF);\n        pre[p].assign(occ[cc].size(), -1);\n\n        for (int i = 0; i < (int)occ[pc].size(); i++) {\n            if (dp[p - 1][i] >= INF) continue;\n            for (int j = 0; j < (int)occ[cc].size(); j++) {\n                int val = dp[p - 1][i] + mdist(occ[pc][i], occ[cc][j]) + 1;\n                if (val < dp[p][j]) {\n                    dp[p][j] = val;\n                    pre[p][j] = i;\n                }\n            }\n        }\n    }\n\n    int last_c = s.back() - 'A';\n    int best_last = 0;\n    for (int i = 1; i < (int)occ[last_c].size(); i++) {\n        if (dp[L - 1][i] < dp[L - 1][best_last]) {\n            best_last = i;\n        }\n    }\n\n    vector<Pos> ans(L);\n    int idx = best_last;\n\n    for (int p = L - 1; p >= 0; p--) {\n        int ch = s[p] - 'A';\n        ans[p] = occ[ch][idx];\n        idx = pre[p][idx];\n    }\n\n    for (auto& p : ans) {\n        cout << p.r << ' ' << p.c << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<unsigned long long> bits;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n\n    int V = N * N;\n    int W = (V + 63) / 64;\n\n    vector<vector<pair<int,int>>> shape(M);\n    vector<int> h(M, 0), w(M, 0);\n\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        shape[k].resize(d);\n        for (int t = 0; t < d; t++) {\n            int i, j;\n            cin >> i >> j;\n            shape[k][t] = {i, j};\n            h[k] = max(h[k], i + 1);\n            w[k] = max(w[k], j + 1);\n        }\n    }\n\n    vector<vector<Placement>> cand(M);\n\n    for (int k = 0; k < M; k++) {\n        for (int si = 0; si + h[k] <= N; si++) {\n            for (int sj = 0; sj + w[k] <= N; sj++) {\n                Placement p;\n                p.bits.assign(W, 0);\n                for (auto [di, dj] : shape[k]) {\n                    int ni = si + di;\n                    int nj = sj + dj;\n                    int id = ni * N + nj;\n                    p.cells.push_back(id);\n                    p.bits[id >> 6] |= 1ULL << (id & 63);\n                }\n                cand[k].push_back(std::move(p));\n            }\n        }\n    }\n\n    vector<int> known(V, -1);\n    vector<int> drilled_positive;\n\n    auto contains_cell = [&](const Placement& p, int id) -> bool {\n        return (p.bits[id >> 6] >> (id & 63)) & 1ULL;\n    };\n\n    auto filter_candidates = [&](int id, int val) {\n        for (int k = 0; k < M; k++) {\n            vector<Placement> nxt;\n            nxt.reserve(cand[k].size());\n\n            for (auto &p : cand[k]) {\n                bool has = contains_cell(p, id);\n\n                /*\n                   Exact drill result val is total number of fields covering id.\n                   For a single field candidate:\n                   - If val == 0, no field may cover id.\n                   - If val > 0, the field may or may not cover id.\n                     So positive information alone cannot eliminate individual\n                     candidates safely without considering combinations.\n                */\n                if (val == 0 && has) continue;\n                nxt.push_back(std::move(p));\n            }\n\n            cand[k].swap(nxt);\n        }\n    };\n\n    auto build_union_from_singletons = [&]() -> vector<int> {\n        vector<int> mark(V, 0);\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n            const Placement& p = cand[k][0];\n            for (int id : p.cells) mark[id] = 1;\n        }\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            if (mark[id]) ans.push_back(id);\n        }\n        return ans;\n    };\n\n    auto build_union_most_likely = [&]() -> vector<int> {\n        vector<int> mark(V, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n\n            int best_idx = 0;\n            int best_score = -1;\n\n            for (int idx = 0; idx < (int)cand[k].size(); idx++) {\n                int score = 0;\n                for (int id : cand[k][idx].cells) {\n                    if (known[id] > 0) score += 1000;\n                    else if (known[id] == 0) score -= 1000000;\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best_idx = idx;\n                }\n            }\n\n            for (int id : cand[k][best_idx].cells) mark[id] = 1;\n        }\n\n        for (int id : drilled_positive) mark[id] = 1;\n\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            if (mark[id]) ans.push_back(id);\n        }\n        return ans;\n    };\n\n    auto output_answer = [&](const vector<int>& ans) -> bool {\n        cout << \"a \" << ans.size();\n        for (int id : ans) {\n            cout << ' ' << id / N << ' ' << id % N;\n        }\n        cout << endl;\n        cout.flush();\n\n        int res;\n        cin >> res;\n        return res == 1;\n    };\n\n    auto drill = [&](int id) -> int {\n        cout << \"q 1 \" << id / N << ' ' << id % N << endl;\n        cout.flush();\n\n        int val;\n        cin >> val;\n\n        known[id] = val;\n        if (val > 0) drilled_positive.push_back(id);\n        filter_candidates(id, val);\n        return val;\n    };\n\n    int op_count = 0;\n    int op_limit = 2 * N * N;\n\n    auto all_singleton = [&]() -> bool {\n        for (int k = 0; k < M; k++) {\n            if ((int)cand[k].size() != 1) return false;\n        }\n        return true;\n    };\n\n    auto choose_next_cell = [&]() -> int {\n        vector<double> cover_sum(V, 0.0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n            double inv = 1.0 / cand[k].size();\n            for (auto &p : cand[k]) {\n                for (int id : p.cells) {\n                    cover_sum[id] += inv;\n                }\n            }\n        }\n\n        int best = -1;\n        double best_score = -1.0;\n\n        for (int id = 0; id < V; id++) {\n            if (known[id] != -1) continue;\n\n            double p = cover_sum[id] / max(1, M);\n            double entropy_score = 1.0 - abs(2.0 * p - 1.0);\n\n            /*\n               Prefer cells that are likely to be oil but still uncertain.\n               Positive cells help locate shapes, zero cells prune candidates.\n            */\n            double oil_likelihood = min(1.0, cover_sum[id]);\n            double score = entropy_score + 0.35 * oil_likelihood;\n\n            if (score > best_score) {\n                best_score = score;\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id = 0; id < V; id++) {\n                if (known[id] == -1) return id;\n            }\n        }\n\n        return best;\n    };\n\n    while (op_count + 1 < op_limit) {\n        if (all_singleton()) {\n            vector<int> ans = build_union_from_singletons();\n            op_count++;\n            if (output_answer(ans)) return 0;\n        }\n\n        int remaining_product_log = 0;\n        bool small_uncertainty = true;\n        for (int k = 0; k < M; k++) {\n            if ((int)cand[k].size() > 4) small_uncertainty = false;\n        }\n\n        if (small_uncertainty && op_count + 1 < op_limit) {\n            vector<int> ans = build_union_most_likely();\n            op_count++;\n            if (output_answer(ans)) return 0;\n        }\n\n        int id = choose_next_cell();\n        if (id < 0) break;\n\n        drill(id);\n        op_count++;\n    }\n\n    /*\n       Safe fallback: drill every remaining unknown cell exactly.\n       This preserves correctness as long as operation limit remains.\n    */\n    for (int id = 0; id < V && op_count + 1 < op_limit; id++) {\n        if (known[id] == -1) {\n            drill(id);\n            op_count++;\n        }\n    }\n\n    vector<int> final_ans;\n    for (int id = 0; id < V; id++) {\n        if (known[id] > 0) final_ans.push_back(id);\n    }\n\n    op_count++;\n    output_answer(final_ans);\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int WFIX = 1000;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        auto now = chrono::steady_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n};\n\nint W, D, N;\nvector<vector<int>> A;\nvector<vector<int>> wid;\n\nlong long shortage_cost_day(int d) {\n    long long c = 0;\n    for (int k = 0; k < N; k++) {\n        long long area = 1LL * W * wid[d][k];\n        if (A[d][k] > area) c += 100LL * (A[d][k] - area);\n    }\n    return c;\n}\n\nvector<int> boundaries_day(int d) {\n    vector<int> b;\n    int x = 0;\n    for (int k = 0; k < N - 1; k++) {\n        x += wid[d][k];\n        b.push_back(x);\n    }\n    return b;\n}\n\nlong long transition_cost_pair(int d) {\n    // Cost between day d-1 and d for full-height vertical strips.\n    if (d <= 0) return 0;\n    vector<int> b0 = boundaries_day(d - 1);\n    vector<int> b1 = boundaries_day(d);\n\n    // Internal vertical segment at boundary x exists for y=0..W-1.\n    // Symmetric difference of boundary x sets times W.\n    int i = 0, j = 0;\n    int common = 0;\n    while (i < (int)b0.size() && j < (int)b1.size()) {\n        if (b0[i] == b1[j]) {\n            common++;\n            i++;\n            j++;\n        } else if (b0[i] < b1[j]) {\n            i++;\n        } else {\n            j++;\n        }\n    }\n    int diff = (int)b0.size() + (int)b1.size() - 2 * common;\n    return 1LL * W * diff;\n}\n\nlong long total_score_like() {\n    long long c = 0;\n    for (int d = 0; d < D; d++) c += shortage_cost_day(d);\n    for (int d = 1; d < D; d++) c += transition_cost_pair(d);\n    return c;\n}\n\nlong long local_part_cost(int d) {\n    long long c = shortage_cost_day(d);\n    if (d >= 1) c += transition_cost_pair(d);\n    if (d + 1 < D) c += transition_cost_pair(d + 1);\n    return c;\n}\n\nvoid normalize_day_initial(int d) {\n    wid[d].assign(N, 1);\n\n    vector<int> req(N);\n    long long sum = 0;\n    for (int k = 0; k < N; k++) {\n        req[k] = max(1, (A[d][k] + W - 1) / W);\n        wid[d][k] = req[k];\n        sum += wid[d][k];\n    }\n\n    if (sum < W) {\n        // Add extra space to large requests first; no shortage benefit usually,\n        // but it may reduce future shortage after local search movement.\n        int rem = W - (int)sum;\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int x, int y) {\n            return A[d][x] > A[d][y];\n        });\n        int p = 0;\n        while (rem--) {\n            wid[d][ord[p]]++;\n            p++;\n            if (p == N) p = 0;\n        }\n    } else if (sum > W) {\n        int over = (int)(sum - W);\n\n        // Remove columns where damage is smallest.\n        // Damage of reducing width by 1:\n        // 100 * increase in shortage = 100 * min(W, max(0, A-area_after) - max(0,A-area_before)).\n        while (over > 0) {\n            int bestK = -1;\n            long long bestDamage = LLONG_MAX;\n            for (int k = 0; k < N; k++) {\n                if (wid[d][k] <= 1) continue;\n                long long beforeArea = 1LL * W * wid[d][k];\n                long long afterArea = 1LL * W * (wid[d][k] - 1);\n                long long beforeShort = max(0LL, 1LL * A[d][k] - beforeArea);\n                long long afterShort = max(0LL, 1LL * A[d][k] - afterArea);\n                long long dmg = 100LL * (afterShort - beforeShort);\n                // Tie-break: reduce larger widths.\n                dmg = dmg * 10000 - wid[d][k];\n                if (dmg < bestDamage) {\n                    bestDamage = dmg;\n                    bestK = k;\n                }\n            }\n            if (bestK < 0) break;\n            wid[d][bestK]--;\n            over--;\n        }\n    }\n}\n\nvoid initialize_solution() {\n    wid.assign(D, vector<int>(N, 1));\n\n    // Candidate 1: per-day demand layout.\n    vector<vector<int>> bestWid(D, vector<int>(N));\n    for (int d = 0; d < D; d++) normalize_day_initial(d);\n    bestWid = wid;\n    long long bestScore = total_score_like();\n\n    // Candidate 2: fixed median/DP-like stable layout from previous approach.\n    vector<vector<long long>> cost(N, vector<long long>(W + 1, 0));\n    for (int k = 0; k < N; k++) {\n        for (int w = 1; w <= W; w++) {\n            long long c = 0;\n            long long area = 1LL * W * w;\n            for (int d = 0; d < D; d++) {\n                if (A[d][k] > area) c += 100LL * (A[d][k] - area);\n            }\n            cost[k][w] = c;\n        }\n    }\n\n    const long long INF = (1LL << 60);\n    vector<vector<long long>> dp(N + 1, vector<long long>(W + 1, INF));\n    vector<vector<int>> pre(N + 1, vector<int>(W + 1, -1));\n    dp[0][0] = 0;\n    for (int k = 0; k < N; k++) {\n        for (int used = 0; used <= W; used++) if (dp[k][used] < INF) {\n            int remain = N - k - 1;\n            for (int ww = 1; used + ww + remain <= W; ww++) {\n                long long nv = dp[k][used] + cost[k][ww];\n                if (nv < dp[k + 1][used + ww]) {\n                    dp[k + 1][used + ww] = nv;\n                    pre[k + 1][used + ww] = ww;\n                }\n            }\n        }\n    }\n\n    int bu = N;\n    for (int u = N; u <= W; u++) {\n        if (dp[N][u] < dp[N][bu]) bu = u;\n    }\n\n    vector<int> fixed(N);\n    int cur = bu;\n    for (int k = N; k >= 1; k--) {\n        fixed[k - 1] = pre[k][cur];\n        cur -= fixed[k - 1];\n    }\n\n    int used = accumulate(fixed.begin(), fixed.end(), 0);\n    while (used < W) {\n        int bestK = 0;\n        long long bestGain = LLONG_MIN;\n        for (int k = 0; k < N; k++) {\n            long long gain = cost[k][fixed[k]] - cost[k][fixed[k] + 1];\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestK = k;\n            }\n        }\n        fixed[bestK]++;\n        used++;\n    }\n\n    wid.assign(D, fixed);\n    long long sc2 = total_score_like();\n    if (sc2 < bestScore) {\n        bestScore = sc2;\n        bestWid = wid;\n    }\n\n    wid = bestWid;\n}\n\nvoid greedy_local_search(const Timer& timer) {\n    XorShift rng;\n    long long curScore = total_score_like();\n\n    // Deterministic adjacent-transfer improvement.\n    bool improved = true;\n    int pass = 0;\n    while (improved && pass < 30 && timer.elapsed() < 2.5) {\n        improved = false;\n        pass++;\n\n        for (int d = 0; d < D && timer.elapsed() < 2.5; d++) {\n            bool dayImp = true;\n            int inner = 0;\n            while (dayImp && inner < 200) {\n                dayImp = false;\n                inner++;\n\n                long long base = local_part_cost(d);\n                int bestFrom = -1, bestTo = -1;\n                long long bestDelta = 0;\n\n                // Try all one-column moves within this day.\n                for (int from = 0; from < N; from++) {\n                    if (wid[d][from] <= 1) continue;\n                    for (int to = 0; to < N; to++) {\n                        if (from == to) continue;\n\n                        wid[d][from]--;\n                        wid[d][to]++;\n                        long long nc = local_part_cost(d);\n                        wid[d][from]++;\n                        wid[d][to]--;\n\n                        long long delta = nc - base;\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestFrom = from;\n                            bestTo = to;\n                        }\n                    }\n                }\n\n                if (bestDelta < 0) {\n                    wid[d][bestFrom]--;\n                    wid[d][bestTo]++;\n                    curScore += bestDelta;\n                    improved = true;\n                    dayImp = true;\n                }\n            }\n        }\n    }\n\n    // Randomized hill climbing, including larger jumps.\n    double TL = 2.85;\n    while (timer.elapsed() < TL) {\n        int d = rng.randint(0, D - 1);\n        int from = rng.randint(0, N - 1);\n        int to = rng.randint(0, N - 1);\n        if (from == to || wid[d][from] <= 1) continue;\n\n        int maxMove = min(wid[d][from] - 1, 10);\n        if (maxMove <= 0) continue;\n        int mv = 1;\n        if ((rng.next() & 7) == 0) mv = rng.randint(1, maxMove);\n\n        long long base = local_part_cost(d);\n        wid[d][from] -= mv;\n        wid[d][to] += mv;\n        long long nc = local_part_cost(d);\n\n        if (nc <= base) {\n            curScore += nc - base;\n        } else {\n            wid[d][from] += mv;\n            wid[d][to] -= mv;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> W >> D >> N;\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    initialize_solution();\n    greedy_local_search(timer);\n\n    // Output vertical full-height strips.\n    for (int d = 0; d < D; d++) {\n        int x = 0;\n        for (int k = 0; k < N; k++) {\n            int x2 = x + wid[d][k];\n\n            // Safety correction for final rectangle.\n            if (k == N - 1) x2 = W;\n\n            // Rect: top-left (0,x), bottom-right (W,x2)\n            // Since every width is >=1 and sum is W, valid.\n            cout << 0 << ' ' << x << ' ' << W << ' ' << x2 << '\\n';\n            x = x2;\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr long long MOD = 998244353LL;\nstatic constexpr int N = 9;\nstatic constexpr int M = 20;\nstatic constexpr int K = 81;\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct Cand {\n    long long gain;\n    int m, p, q;\n    bool operator<(const Cand& other) const {\n        return gain > other.gain;\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    XorShift() {}\n    XorShift(uint64_t seed) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n    double uniform() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nlong long calc_score(const array<array<long long, N>, N>& b) {\n    long long score = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            score += b[i][j];\n        }\n    }\n    return score;\n}\n\nlong long calc_gain(\n    const array<array<long long, N>, N>& b,\n    const long long s[M][3][3],\n    int m,\n    int p,\n    int q\n) {\n    long long gain = 0;\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            long long oldv = b[p + i][q + j];\n            long long nv = oldv + s[m][i][j];\n            if (nv >= MOD) nv -= MOD;\n            gain += nv - oldv;\n        }\n    }\n    return gain;\n}\n\nvoid apply_op(\n    array<array<long long, N>, N>& b,\n    const long long s[M][3][3],\n    int m,\n    int p,\n    int q\n) {\n    for (int i = 0; i < 3; i++) {\n        for (int j = 0; j < 3; j++) {\n            b[p + i][q + j] += s[m][i][j];\n            if (b[p + i][q + j] >= MOD) b[p + i][q + j] -= MOD;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m_input, k_input;\n    cin >> n >> m_input >> k_input;\n\n    array<array<long long, N>, N> initial{};\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> initial[i][j];\n        }\n    }\n\n    static long long stamp[M][3][3];\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamp[m][i][j];\n            }\n        }\n    }\n\n    auto start_time = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.85;\n\n    vector<Op> best_ops;\n    long long best_score = calc_score(initial);\n\n    XorShift rng(\n        chrono::steady_clock::now().time_since_epoch().count()\n    );\n\n    int trial = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > TIME_LIMIT) break;\n\n        array<array<long long, N>, N> b = initial;\n        vector<Op> ops;\n        long long score = calc_score(b);\n\n        for (int step = 0; step < K; step++) {\n            vector<Cand> cands;\n            cands.reserve(M * 49);\n\n            for (int sm = 0; sm < M; sm++) {\n                for (int p = 0; p <= N - 3; p++) {\n                    for (int q = 0; q <= N - 3; q++) {\n                        long long g = calc_gain(b, stamp, sm, p, q);\n                        if (g > 0) {\n                            cands.push_back({g, sm, p, q});\n                        }\n                    }\n                }\n            }\n\n            if (cands.empty()) break;\n\n            sort(cands.begin(), cands.end());\n\n            Cand chosen = cands[0];\n\n            if (trial > 0) {\n                int top = min<int>((int)cands.size(), 12);\n\n                // Earlier steps are randomized more, later steps become greedier.\n                double temp = 1.0 - double(step) / K;\n                double r = rng.uniform();\n\n                if (r < 0.70 + 0.25 * (1.0 - temp)) {\n                    chosen = cands[0];\n                } else {\n                    int idx = rng.randint(0, top - 1);\n                    chosen = cands[idx];\n                }\n            }\n\n            apply_op(b, stamp, chosen.m, chosen.p, chosen.q);\n            score += chosen.gain;\n            ops.push_back({chosen.m, chosen.p, chosen.q});\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_ops = ops;\n        }\n\n        trial++;\n    }\n\n    cout << best_ops.size() << '\\n';\n    for (auto &op : best_ops) {\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static constexpr int N = 5;\n\n    vector<vector<int>> A;\n    vector<int> ptr;\n    vector<vector<int>> grid;\n    vector<pair<int,int>> pos;\n\n    vector<string> ans;\n\n    int cr = 0, cc = 0;\n    bool holding = false;\n    int hold = -1;\n\n    Solver(const vector<vector<int>>& A_) : A(A_) {\n        ptr.assign(N, 0);\n        grid.assign(N, vector<int>(N, -1));\n        pos.assign(N * N, {-1, -1});\n        ans.assign(N, \"\");\n\n        // Initial receiving phase.\n        for (int i = 0; i < N; i++) {\n            grid[i][0] = A[i][0];\n            pos[A[i][0]] = {i, 0};\n            ptr[i] = 1;\n        }\n    }\n\n    void do_receive() {\n        for (int i = 0; i < N; i++) {\n            if (ptr[i] < N && grid[i][0] == -1) {\n                // Avoid relying on receiving onto a crane carrying a container.\n                if (holding && cr == i && cc == 0) continue;\n\n                int x = A[i][ptr[i]++];\n                grid[i][0] = x;\n                pos[x] = {i, 0};\n            }\n        }\n    }\n\n    void append_large(char c) {\n        ans[0].push_back(c);\n\n        if (c == 'U') cr--;\n        else if (c == 'D') cr++;\n        else if (c == 'L') cc--;\n        else if (c == 'R') cc++;\n    }\n\n    void move_one(char c) {\n        do_receive();\n        append_large(c);\n    }\n\n    void move_to(int tr, int tc) {\n        while (cr < tr) move_one('D');\n        while (cr > tr) move_one('U');\n\n        // Horizontal movement first toward the center/right is often useful.\n        while (cc < tc) move_one('R');\n        while (cc > tc) move_one('L');\n    }\n\n    void pick() {\n        do_receive();\n\n        int x = grid[cr][cc];\n\n        // Validity guard. Should not be needed.\n        if (x == -1) {\n            append_large('.');\n            return;\n        }\n\n        append_large('P');\n\n        holding = true;\n        hold = x;\n        grid[cr][cc] = -1;\n        pos[x] = {-1, -1};\n    }\n\n    void release() {\n        do_receive();\n\n        append_large('Q');\n\n        holding = false;\n\n        if (cc == N - 1) {\n            pos[hold] = {-2, -2}; // dispatched\n        } else {\n            grid[cr][cc] = hold;\n            pos[hold] = {cr, cc};\n        }\n\n        hold = -1;\n    }\n\n    void move_to_and_pick(pair<int,int> p) {\n        move_to(p.first, p.second);\n        pick();\n    }\n\n    void deliver_held_to_correct_gate() {\n        int dest = hold / N;\n        move_to(dest, N - 1);\n        release();\n    }\n\n    bool target_on_grid(int target) const {\n        return pos[target].first >= 0;\n    }\n\n    bool is_safe_storage_cell(int r, int c) const {\n        if (c == N - 1) return false;\n        if (grid[r][c] != -1) return false;\n        if (c == 0 && ptr[r] < N) return false;\n        return true;\n    }\n\n    pair<int,int> find_storage_for(int x) {\n        int dest = x / N;\n\n        vector<pair<int,int>> cand;\n\n        // Best: same row as final dispatch, close to dispatch side.\n        for (int c = 3; c >= 1; c--) {\n            cand.push_back({dest, c});\n        }\n\n        // Next: neighboring rows, still close to dispatch side.\n        for (int d = 1; d < N; d++) {\n            int r1 = dest - d;\n            int r2 = dest + d;\n\n            if (r1 >= 0) {\n                for (int c = 3; c >= 1; c--) cand.push_back({r1, c});\n            }\n            if (r2 < N) {\n                for (int c = 3; c >= 1; c--) cand.push_back({r2, c});\n            }\n        }\n\n        // Fallback: exhausted receiving gates.\n        for (int d = 0; d < N; d++) {\n            int r1 = dest - d;\n            int r2 = dest + d;\n\n            if (r1 >= 0) cand.push_back({r1, 0});\n            if (d != 0 && r2 < N) cand.push_back({r2, 0});\n        }\n\n        pair<int,int> best = {-1, -1};\n        int bestScore = 1e9;\n\n        for (auto [r, c] : cand) {\n            if (!is_safe_storage_cell(r, c)) continue;\n\n            // Cost estimate:\n            // current -> storage, then later storage -> dispatch.\n            int nowCost = abs(cr - r) + abs(cc - c);\n            int laterCost = abs(r - dest) + abs(c - (N - 1));\n\n            int score = nowCost + laterCost * 2;\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = {r, c};\n            }\n        }\n\n        return best;\n    }\n\n    void store_held() {\n        auto p = find_storage_for(hold);\n\n        // Should rarely happen.\n        if (p.first == -1) {\n            deliver_held_to_correct_gate();\n            return;\n        }\n\n        move_to(p.first, p.second);\n        release();\n    }\n\n    int choose_revealing_row(int target) {\n        // If target is hidden behind a specific gate, prefer that gate.\n        for (int r = 0; r < N; r++) {\n            for (int k = ptr[r]; k < N; k++) {\n                if (A[r][k] == target) {\n                    if (grid[r][0] != -1) return r;\n                }\n            }\n        }\n\n        // Otherwise nearest visible receiving gate.\n        int best = -1;\n        int bestDist = 1e9;\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] != -1) {\n                int d = abs(cr - r) + cc;\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = r;\n                }\n            }\n        }\n\n        return best;\n    }\n\n    void solve_exact_order() {\n        // Bomb small cranes.\n        for (int i = 1; i < N; i++) ans[i].push_back('B');\n\n        for (int target = 0; target < N * N; target++) {\n            while (true) {\n                if (target_on_grid(target)) {\n                    move_to_and_pick(pos[target]);\n                    deliver_held_to_correct_gate();\n                    break;\n                }\n\n                int row = choose_revealing_row(target);\n\n                if (row == -1) {\n                    move_one('.');\n                    continue;\n                }\n\n                move_to(row, 0);\n                pick();\n\n                if (hold == target) {\n                    deliver_held_to_correct_gate();\n                    break;\n                } else {\n                    store_held();\n                }\n            }\n        }\n    }\n\n    vector<string> run() {\n        solve_exact_order();\n\n        int L = 0;\n        for (auto &s : ans) L = max(L, (int)s.size());\n\n        for (auto &s : ans) {\n            while ((int)s.size() < L) s.push_back('.');\n        }\n\n        return ans;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    Solver solver(A);\n    auto ans = solver.run();\n\n    for (auto &s : ans) {\n        cout << s << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<vector<int>> H;\n\nstruct Result {\n    long long cost = (1LL << 60);\n    vector<string> ops;\n};\n\nstruct Cell {\n    int r, c;\n    int v;\n};\n\nstruct Params {\n    double emptyDistW;\n    double deliverDistW;\n    double amountBonus;\n    double sourceToSinkW;\n};\n\nint manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nvoid move_to(vector<string>& ops, long long& cost, long long load,\n             int& r, int& c, int nr, int nc) {\n    while (r < nr) {\n        ops.push_back(\"D\");\n        cost += 100 + load;\n        r++;\n    }\n    while (r > nr) {\n        ops.push_back(\"U\");\n        cost += 100 + load;\n        r--;\n    }\n    while (c < nc) {\n        ops.push_back(\"R\");\n        cost += 100 + load;\n        c++;\n    }\n    while (c > nc) {\n        ops.push_back(\"L\");\n        cost += 100 + load;\n        c--;\n    }\n}\n\nResult simulate_greedy(const Params& par) {\n    vector<Cell> pos, neg;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (H[i][j] > 0) pos.push_back({i, j, H[i][j]});\n            if (H[i][j] < 0) neg.push_back({i, j, -H[i][j]});\n        }\n    }\n\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n    int lastSrcR = 0, lastSrcC = 0;\n\n    int remainPos = 0, remainNeg = 0;\n    for (auto& x : pos) remainPos += x.v;\n    for (auto& x : neg) remainNeg += x.v;\n\n    while (remainNeg > 0) {\n        if (load == 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)pos.size(); i++) {\n                if (pos[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, pos[i].r, pos[i].c);\n\n                // Prefer sources that have nearby remaining sinks.\n                int nearestSink = 1000000;\n                for (auto& g : neg) {\n                    if (g.v <= 0) continue;\n                    nearestSink = min(nearestSink, manhattan(pos[i].r, pos[i].c, g.r, g.c));\n                }\n\n                double score =\n                    par.emptyDistW * dcur\n                    + par.sourceToSinkW * nearestSink\n                    - par.amountBonus * sqrt((double)pos[i].v);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, pos[best].r, pos[best].c);\n\n            int d = pos[best].v;\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            remainPos -= d;\n            pos[best].v = 0;\n            lastSrcR = r;\n            lastSrcC = c;\n        }\n\n        while (load > 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)neg.size(); i++) {\n                if (neg[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, neg[i].r, neg[i].c);\n                int dsrc = manhattan(lastSrcR, lastSrcC, neg[i].r, neg[i].c);\n                int give = min<long long>(load, neg[i].v);\n\n                double score =\n                    par.deliverDistW * dcur\n                    + 0.25 * dsrc\n                    - par.amountBonus * sqrt((double)give);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, neg[best].r, neg[best].c);\n\n            int d = min<long long>(load, neg[best].v);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            neg[best].v -= d;\n            remainNeg -= d;\n        }\n    }\n\n    if ((int)ops.size() > 100000) {\n        Result bad;\n        return bad;\n    }\n\n    return {cost, ops};\n}\n\n// Previous snake fallback, useful for cases where greedy behaves poorly.\nResult simulate_path(const vector<pair<int,int>>& path) {\n    vector<vector<int>> h = H;\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n\n    auto process_cell = [&](int i, int j) {\n        if (h[i][j] > 0) {\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        } else if (h[i][j] < 0 && load > 0) {\n            int d = min<long long>(-h[i][j], load);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] += d;\n        }\n    };\n\n    for (auto [i,j] : path) {\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (int idx = (int)path.size() - 1; idx >= 0; idx--) {\n        auto [i,j] = path[idx];\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] > 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        }\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] < 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = -h[i][j];\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] = 0;\n        }\n    }\n\n    return {cost, ops};\n}\n\nvector<pair<int,int>> row_snake() {\n    vector<pair<int,int>> p;\n    for (int i = 0; i < N; i++) {\n        if (i % 2 == 0) {\n            for (int j = 0; j < N; j++) p.push_back({i,j});\n        } else {\n            for (int j = N - 1; j >= 0; j--) p.push_back({i,j});\n        }\n    }\n    return p;\n}\n\nvector<pair<int,int>> col_snake() {\n    vector<pair<int,int>> p;\n    for (int j = 0; j < N; j++) {\n        if (j % 2 == 0) {\n            for (int i = 0; i < N; i++) p.push_back({i,j});\n        } else {\n            for (int i = N - 1; i >= 0; i--) p.push_back({i,j});\n        }\n    }\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    H.assign(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> H[i][j];\n    }\n\n    Result best;\n\n    vector<Params> params = {\n        {1.0, 1.0, 0.0, 0.0},\n        {1.0, 1.0, 1.0, 0.2},\n        {1.0, 1.0, 2.0, 0.5},\n        {1.0, 1.3, 1.0, 0.5},\n        {1.3, 1.0, 1.0, 0.5},\n        {0.7, 1.2, 2.0, 0.8},\n        {1.5, 0.8, 1.5, 0.3},\n        {1.0, 2.0, 2.0, 1.0},\n        {2.0, 1.0, 2.0, 1.0},\n        {0.5, 1.5, 1.0, 1.0},\n    };\n\n    for (auto& p : params) {\n        Result res = simulate_greedy(p);\n        if (res.cost < best.cost) best = move(res);\n    }\n\n    vector<vector<pair<int,int>>> paths;\n    paths.push_back(row_snake());\n    paths.push_back(col_snake());\n\n    for (int k = 0; k < 2; k++) {\n        auto q = paths[k];\n        reverse(q.begin(), q.end());\n        paths.push_back(q);\n    }\n\n    for (auto& path : paths) {\n        Result res = simulate_path(path);\n        if ((int)res.ops.size() <= 100000 && res.cost < best.cost) {\n            best = move(res);\n        }\n    }\n\n    for (auto& s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ull) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n    double rand01() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int S = 2 * N * (N - 1); // 60\n    const int C = N * N;           // 36\n\n    vector<vector<int>> X(S, vector<int>(M));\n    for (int i = 0; i < S; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    vector<int> target(M, 0);\n    for (int i = 0; i < S; i++) {\n        for (int l = 0; l < M; l++) target[l] = max(target[l], X[i][l]);\n    }\n    int targetSum = accumulate(target.begin(), target.end(), 0);\n\n    vector<pair<int,int>> edges;\n    vector<vector<int>> incident(C);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (j + 1 < N) {\n                int id2 = id + 1;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n            if (i + 1 < N) {\n                int id2 = id + N;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n        }\n    }\n\n    vector<int> deg(C, 0);\n    for (auto [a,b] : edges) {\n        deg[a]++;\n        deg[b]++;\n    }\n\n    vector<int> blackCells, whiteCells, allCells(C);\n    iota(allCells.begin(), allCells.end(), 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if ((i + j) & 1) whiteCells.push_back(id);\n            else blackCells.push_back(id);\n        }\n    }\n\n    auto sort_cells = [&](vector<int>& v) {\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n    };\n    sort_cells(blackCells);\n    sort_cells(whiteCells);\n    sort_cells(allCells);\n\n    auto start_time = chrono::steady_clock::now();\n    XorShift rng(246813579);\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> curMax(M, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) curMax[l] = max(curMax[l], X[i][l]);\n        }\n\n        vector<int> sumv(S, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) sumv[i] += X[i][l];\n        }\n\n        double phase = (double)turn / max(1, T - 1);\n        bool finalTurn = (turn == T - 1);\n\n        vector<double> seedScore(S, 0);\n        vector<double> valueScore(S, 0);\n        vector<double> targetFit(S, 0);\n        vector<double> curFit(S, 0);\n\n        for (int i = 0; i < S; i++) {\n            double tr = 0, trsq = 0;\n            double cr = 0, crsq = 0;\n            double elite = 0;\n            int nearTarget = 0;\n            int exactCur = 0;\n\n            for (int l = 0; l < M; l++) {\n                double rt = (double)X[i][l] / max(1, target[l]);\n                double rc = (double)X[i][l] / max(1, curMax[l]);\n                tr += 100.0 * rt;\n                trsq += 100.0 * rt * rt;\n                cr += 100.0 * rc;\n                crsq += 100.0 * rc * rc;\n\n                if (X[i][l] >= target[l] * 0.95) nearTarget++;\n                if (X[i][l] == curMax[l]) exactCur++;\n\n                if (X[i][l] == curMax[l]) elite += 70.0;\n                if (X[i][l] >= target[l] * 0.95) elite += 45.0;\n                else if (X[i][l] >= target[l] * 0.88) elite += 18.0;\n            }\n\n            targetFit[i] = tr + 0.45 * trsq + 32.0 * nearTarget;\n            curFit[i] = cr + 0.35 * crsq + 38.0 * exactCur;\n            valueScore[i] = sumv[i] + 0.55 * targetFit[i];\n\n            seedScore[i] =\n                (0.70 + 0.95 * phase) * sumv[i]\n                + 0.80 * targetFit[i]\n                + 0.38 * curFit[i]\n                + elite;\n        }\n\n        // Pair score.\n        vector<vector<double>> P(S, vector<double>(S, 0.0));\n\n        for (int a = 0; a < S; a++) {\n            for (int b = a + 1; b < S; b++) {\n                int maxsum = 0;\n                int minsum = 0;\n                int diff = 0;\n                int nearTarget = 0;\n                int nearCurrent = 0;\n                int exactCurrent = 0;\n                int bothMedium = 0;\n                double targetRatioSq = 0;\n\n                for (int l = 0; l < M; l++) {\n                    int ma = max(X[a][l], X[b][l]);\n                    int mi = min(X[a][l], X[b][l]);\n                    maxsum += ma;\n                    minsum += mi;\n                    diff += abs(X[a][l] - X[b][l]);\n\n                    double rt = (double)ma / max(1, target[l]);\n                    targetRatioSq += rt * rt;\n\n                    if (ma >= target[l] * 0.92) nearTarget++;\n                    if (ma >= curMax[l] * 0.92) nearCurrent++;\n                    if (ma == curMax[l]) exactCurrent++;\n                    if (X[a][l] >= target[l] * 0.70 && X[b][l] >= target[l] * 0.70) bothMedium++;\n                }\n\n                double expected = 0.5 * (sumv[a] + sumv[b]);\n                double closeToTarget = targetSum > 0 ? (double)maxsum / targetSum : 0.0;\n\n                double exploit = finalTurn ? 1.0 : phase;\n\n                double sc = 0;\n                sc += (1.70 + 0.55 * exploit) * maxsum;\n                sc += (0.18 + 1.10 * exploit) * expected;\n                sc += 0.16 * minsum;\n                sc += (0.24 - 0.13 * exploit) * diff;\n                sc += 34.0 * nearTarget;\n                sc += 18.0 * nearCurrent;\n                sc += 13.0 * exactCurrent;\n                sc += 7.0 * bothMedium;\n                sc += 18.0 * targetRatioSq;\n                sc += 300.0 * closeToTarget * closeToTarget;\n\n                P[a][b] = P[b][a] = sc;\n            }\n        }\n\n        auto make_selection = [&](int mode) {\n            vector<int> selected;\n            vector<int> used(S, 0);\n\n            auto add_seed = [&](int id) {\n                if (!used[id] && (int)selected.size() < C) {\n                    used[id] = 1;\n                    selected.push_back(id);\n                }\n            };\n\n            // Top 1 or top 2 coordinate champions.\n            int champDepth = (turn <= 6 ? 2 : 1);\n            if (mode == 3) champDepth = 2;\n\n            for (int l = 0; l < M; l++) {\n                vector<int> ids(S);\n                iota(ids.begin(), ids.end(), 0);\n                sort(ids.begin(), ids.end(), [&](int a, int b) {\n                    if (X[a][l] != X[b][l]) return X[a][l] > X[b][l];\n                    return seedScore[a] > seedScore[b];\n                });\n\n                for (int r = 0; r < champDepth; r++) add_seed(ids[r]);\n            }\n\n            vector<int> ord(S);\n            iota(ord.begin(), ord.end(), 0);\n\n            if (mode == 0) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n            } else if (mode == 1) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return targetFit[a] > targetFit[b];\n                });\n            } else if (mode == 2) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return valueScore[a] > valueScore[b];\n                });\n            } else {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return curFit[a] > curFit[b];\n                });\n            }\n\n            int mandatoryTop;\n            if (mode == 2) mandatoryTop = 14 + (int)(8 * phase);\n            else mandatoryTop = 10 + (int)(6 * phase);\n\n            for (int id : ord) {\n                if ((int)selected.size() >= mandatoryTop) break;\n                add_seed(id);\n            }\n\n            vector<int> cover(M, 0);\n            for (int id : selected) {\n                for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[id][l]);\n            }\n\n            while ((int)selected.size() < C) {\n                int best = -1;\n                double bestSc = -1e100;\n\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    double gain = 0;\n                    for (int l = 0; l < M; l++) {\n                        int d = max(0, X[i][l] - cover[l]);\n\n                        if (mode == 0) gain += 12.0 * d;\n                        if (mode == 1) gain += 15.0 * d;\n                        if (mode == 2) gain += 7.0 * d;\n                        if (mode == 3) gain += 13.0 * d;\n\n                        double rt = (double)X[i][l] / max(1, target[l]);\n                        double rc = (double)X[i][l] / max(1, curMax[l]);\n\n                        gain += 24.0 * rt + 12.0 * rc;\n                        if (X[i][l] >= target[l] * 0.92) gain += 18.0;\n                        if (X[i][l] == curMax[l]) gain += 22.0;\n                    }\n\n                    double bestPair = 0;\n                    double avgPair = 0;\n                    for (int id : selected) {\n                        bestPair = max(bestPair, P[i][id]);\n                        avgPair += P[i][id];\n                    }\n                    if (!selected.empty()) avgPair /= selected.size();\n\n                    double sc = gain\n                              + (0.32 + 0.55 * phase) * seedScore[i]\n                              + (mode == 2 ? 0.35 : 0.24) * bestPair\n                              + 0.08 * avgPair\n                              + rng.rand01() * 1e-5;\n\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n\n                add_seed(best);\n                for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[best][l]);\n            }\n\n            return selected;\n        };\n\n        auto layout_score = [&](const vector<int>& posSeed) {\n            double s = 0;\n            for (auto [u,v] : edges) s += P[posSeed[u]][posSeed[v]];\n            return s;\n        };\n\n        auto make_layouts = [&](const vector<int>& selected) {\n            vector<vector<int>> layouts;\n\n            // Layout A: complementary bipartite.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> gA, gB;\n                gA.push_back(rem[0]);\n\n                for (int idx = 1; idx < (int)rem.size(); idx++) {\n                    int id = rem[idx];\n\n                    if ((int)gA.size() >= 18) {\n                        gB.push_back(id);\n                        continue;\n                    }\n                    if ((int)gB.size() >= 18) {\n                        gA.push_back(id);\n                        continue;\n                    }\n\n                    double toA = 0, toB = 0;\n                    for (int x : gA) toB += P[id][x];\n                    for (int x : gB) toA += P[id][x];\n\n                    if (toA > toB) gA.push_back(id);\n                    else gB.push_back(id);\n                }\n\n                while ((int)gA.size() < 18) {\n                    gA.push_back(gB.back());\n                    gB.pop_back();\n                }\n                while ((int)gB.size() < 18) {\n                    gB.push_back(gA.back());\n                    gA.pop_back();\n                }\n\n                sort(gA.begin(), gA.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n                sort(gB.begin(), gB.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < 18; i++) {\n                    pos[blackCells[i]] = gA[i];\n                    pos[whiteCells[i]] = gB[i];\n                }\n                layouts.push_back(pos);\n            }\n\n            // Layout B: strength-degree.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < C; i++) pos[allCells[i]] = rem[i];\n                layouts.push_back(pos);\n            }\n\n            // Layout C: alternating target/value on bipartition.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return targetFit[a] > targetFit[b];\n                });\n\n                vector<int> gA, gB;\n                for (int i = 0; i < C; i++) {\n                    if (i % 2 == 0) gA.push_back(rem[i]);\n                    else gB.push_back(rem[i]);\n                }\n\n                sort(gA.begin(), gA.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n                sort(gB.begin(), gB.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < 18; i++) {\n                    pos[blackCells[i]] = gA[i];\n                    pos[whiteCells[i]] = gB[i];\n                }\n                layouts.push_back(pos);\n            }\n\n            return layouts;\n        };\n\n        auto improve_layout = [&](vector<int> posSeed, int iterations, double temp0) {\n            auto edgeScoreAt = [&](const vector<int>& ps, int eid) {\n                auto [u,v] = edges[eid];\n                return P[ps[u]][ps[v]];\n            };\n\n            double cur = layout_score(posSeed);\n\n            for (int it = 0; it < iterations; it++) {\n                int a = rng.randint(C);\n                int b = rng.randint(C);\n                if (a == b) continue;\n\n                vector<int> es;\n                for (int e : incident[a]) es.push_back(e);\n                for (int e : incident[b]) es.push_back(e);\n                sort(es.begin(), es.end());\n                es.erase(unique(es.begin(), es.end()), es.end());\n\n                double before = 0;\n                for (int e : es) before += edgeScoreAt(posSeed, e);\n\n                swap(posSeed[a], posSeed[b]);\n\n                double after = 0;\n                for (int e : es) after += edgeScoreAt(posSeed, e);\n\n                double delta = after - before;\n                double progress = (double)it / max(1, iterations);\n                double temp = temp0 * (1.0 - progress) + 1.0;\n\n                bool accept = false;\n                if (delta >= 0) accept = true;\n                else if (exp(delta / temp) > rng.rand01()) accept = true;\n\n                if (accept) {\n                    cur += delta;\n                } else {\n                    swap(posSeed[a], posSeed[b]);\n                }\n            }\n\n            return pair<double, vector<int>>(cur, posSeed);\n        };\n\n        vector<pair<double, vector<int>>> pool;\n\n        int modes = finalTurn ? 3 : 4;\n        for (int mode = 0; mode < modes; mode++) {\n            vector<int> sel = make_selection(mode);\n            vector<vector<int>> layouts = make_layouts(sel);\n\n            for (auto &lay : layouts) {\n                int shortIter = 2500;\n                auto res = improve_layout(lay, shortIter, 55.0);\n                pool.push_back(res);\n            }\n        }\n\n        sort(pool.begin(), pool.end(), [&](const auto& a, const auto& b) {\n            return a.first > b.first;\n        });\n\n        vector<int> posSeed = pool[0].second;\n\n        int longIter = 70000;\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.70) longIter = 20000;\n\n        auto finalRes = improve_layout(posSeed, longIter, 75.0);\n        posSeed = finalRes.second;\n\n        vector<vector<int>> A(N, vector<int>(N));\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                A[i][j] = posSeed[i * N + 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 << A[i][j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < S; i++) {\n            for (int j = 0; j < M; j++) cin >> X[i][j];\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\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    vector<Pos> src, dst;\n    vector<vector<int>> src_id(N, vector<int>(N, -1));\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] == '0') {\n                src_id[i][j] = (int)src.size();\n                src.push_back({i, j});\n            }\n            if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    int K = (int)src.size();\n\n    int F = max(1, V - 1);\n    int Vp = F + 1;\n\n    /*\n        Star arm, but each finger has different length.\n\n        Length pattern:\n        1,2,3,4,5, then repeat.\n        Capped by N-1.\n\n        This keeps many short useful fingers while allowing wider reach.\n    */\n    vector<int> len(F);\n    for (int f = 0; f < F; f++) {\n        len[f] = min(N - 1, 1 + (f % 5));\n    }\n\n    vector<int> finger_dir(F, 0); // 0:R, 1:D, 2:L, 3:U\n    vector<int> holding(F, -1);\n\n    const int dx[4] = {0, 1, 0, -1};\n    const int dy[4] = {1, 0, -1, 0};\n\n    auto inside = [&](int x, int y) {\n        return 0 <= x && x < N && y >= 0 && y < N;\n    };\n\n    auto manhattan = [&](Pos a, Pos b) {\n        return abs(a.x - b.x) + abs(a.y - b.y);\n    };\n\n    int root_x = 0, root_y = 0;\n    vector<string> ops;\n\n    auto add_op = [&](char mv, const vector<char>& rot, const vector<char>& act) {\n        string op(2 * Vp, '.');\n        op[0] = mv;\n\n        for (int f = 0; f < F; f++) {\n            op[1 + f] = rot[f];\n            op[Vp + 1 + f] = act[f];\n        }\n\n        if (mv == 'U') root_x--;\n        if (mv == 'D') root_x++;\n        if (mv == 'L') root_y--;\n        if (mv == 'R') root_y++;\n\n        for (int f = 0; f < F; f++) {\n            if (rot[f] == 'L') finger_dir[f] = (finger_dir[f] + 3) % 4;\n            if (rot[f] == 'R') finger_dir[f] = (finger_dir[f] + 1) % 4;\n        }\n\n        ops.push_back(op);\n    };\n\n    auto blank_rot = [&]() { return vector<char>(F, '.'); };\n    auto blank_act = [&]() { return vector<char>(F, '.'); };\n\n    auto move_root_to = [&](int tx, int ty) {\n        while (root_x < tx) add_op('D', blank_rot(), blank_act());\n        while (root_x > tx) add_op('U', blank_rot(), blank_act());\n        while (root_y < ty) add_op('R', blank_rot(), blank_act());\n        while (root_y > ty) add_op('L', blank_rot(), blank_act());\n    };\n\n    auto rotate_fingers_to = [&](const vector<int>& target_dir) {\n        while (true) {\n            vector<char> rot(F, '.');\n            vector<char> act(F, '.');\n            bool changed = false;\n\n            for (int f = 0; f < F; f++) {\n                if (target_dir[f] < 0) continue;\n                if (finger_dir[f] == target_dir[f]) continue;\n\n                int diff = (target_dir[f] - finger_dir[f] + 4) % 4;\n                if (diff == 1 || diff == 2) rot[f] = 'R';\n                else rot[f] = 'L';\n\n                changed = true;\n            }\n\n            if (!changed) break;\n            add_op('.', rot, act);\n        }\n    };\n\n    struct Reach {\n        int f;\n        int d;\n        Pos r;\n    };\n\n    auto reaches_for_cell = [&](Pos p) {\n        vector<Reach> res;\n        for (int f = 0; f < F; f++) {\n            for (int d = 0; d < 4; d++) {\n                int rx = p.x - dx[d] * len[f];\n                int ry = p.y - dy[d] * len[f];\n                if (inside(rx, ry)) {\n                    res.push_back({f, d, {rx, ry}});\n                }\n            }\n        }\n        return res;\n    };\n\n    auto finger_can_reach_from_root = [&](int f, Pos root, Pos p, int &dir_out) {\n        for (int d = 0; d < 4; d++) {\n            if (root.x + dx[d] * len[f] == p.x &&\n                root.y + dy[d] * len[f] == p.y) {\n                dir_out = d;\n                return true;\n            }\n        }\n        return false;\n    };\n\n    // Greedy matching by sorted all-pair distances.\n    vector<int> pair_dst(K, -1);\n    {\n        struct Edge {\n            int dist, i, j;\n        };\n        vector<Edge> edges;\n        edges.reserve(K * K);\n\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < K; j++) {\n                edges.push_back({manhattan(src[i], dst[j]), i, j});\n            }\n        }\n\n        sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) {\n            if (a.dist != b.dist) return a.dist < b.dist;\n            if (a.i != b.i) return a.i < b.i;\n            return a.j < b.j;\n        });\n\n        vector<int> used_s(K, 0), used_d(K, 0);\n        int matched = 0;\n        for (const auto& e : edges) {\n            if (!used_s[e.i] && !used_d[e.j]) {\n                used_s[e.i] = used_d[e.j] = 1;\n                pair_dst[e.i] = e.j;\n                matched++;\n                if (matched == K) break;\n            }\n        }\n    }\n\n    vector<int> done(K, 0);\n    int remaining = K;\n\n    auto min_root_dist_to_cell = [&](Pos p) {\n        int best = INT_MAX;\n        for (auto rc : reaches_for_cell(p)) {\n            int c = abs(root_x - rc.r.x) + abs(root_y - rc.r.y);\n            best = min(best, c);\n        }\n        return best;\n    };\n\n    auto choose_seed = [&]() {\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n\n            int approach = min_root_dist_to_cell(src[i]);\n            int transport = manhattan(src[i], dst[pair_dst[i]]);\n\n            int cost = approach * 5 + transport;\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best = i;\n            }\n        }\n\n        return best;\n    };\n\n    while (remaining > 0) {\n        int seed = choose_seed();\n        if (seed < 0) break;\n\n        // Choose best root/finger/dir to pick seed.\n        Reach best_reach{-1, -1, {-1, -1}};\n        int best_cost = INT_MAX;\n\n        for (auto rc : reaches_for_cell(src[seed])) {\n            int move_cost = abs(root_x - rc.r.x) + abs(root_y - rc.r.y);\n            int diff = abs(finger_dir[rc.f] - rc.d);\n            int rot_cost = min(diff, 4 - diff);\n            int cost = move_cost * 3 + rot_cost;\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_reach = rc;\n            }\n        }\n\n        move_root_to(best_reach.r.x, best_reach.r.y);\n\n        /*\n            Pick phase.\n            Among all undone sources reachable from current root, choose at most one\n            per finger. Prefer destinations near seed destination.\n        */\n        struct Cand {\n            int score;\n            int id;\n            int f;\n            int d;\n        };\n\n        vector<Cand> cands;\n        Pos seed_dest = dst[pair_dst[seed]];\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n\n            for (int f = 0; f < F; f++) {\n                int d;\n                if (finger_can_reach_from_root(f, {root_x, root_y}, src[i], d)) {\n                    Pos di = dst[pair_dst[i]];\n                    int diff = abs(finger_dir[f] - d);\n                    int rot = min(diff, 4 - diff);\n                    int score = manhattan(di, seed_dest) * 4\n                              + manhattan(src[i], src[seed])\n                              + rot;\n                    cands.push_back({score, i, f, d});\n                }\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            if (a.score != b.score) return a.score < b.score;\n            return a.id < b.id;\n        });\n\n        vector<int> used_f(F, 0), used_item(K, 0);\n        vector<int> pick_pairs;\n        vector<int> pick_fingers;\n        vector<int> pick_dirs;\n\n        // Ensure seed is picked if possible.\n        {\n            int bestf = -1, bestd = -1, bestr = INT_MAX;\n            for (int f = 0; f < F; f++) {\n                int d;\n                if (finger_can_reach_from_root(f, {root_x, root_y}, src[seed], d)) {\n                    int diff = abs(finger_dir[f] - d);\n                    int r = min(diff, 4 - diff);\n                    if (r < bestr) {\n                        bestr = r;\n                        bestf = f;\n                        bestd = d;\n                    }\n                }\n            }\n            if (bestf >= 0) {\n                used_f[bestf] = 1;\n                used_item[seed] = 1;\n                pick_pairs.push_back(seed);\n                pick_fingers.push_back(bestf);\n                pick_dirs.push_back(bestd);\n            }\n        }\n\n        for (auto c : cands) {\n            if ((int)pick_pairs.size() >= F) break;\n            if (used_f[c.f]) continue;\n            if (used_item[c.id]) continue;\n\n            used_f[c.f] = 1;\n            used_item[c.id] = 1;\n            pick_pairs.push_back(c.id);\n            pick_fingers.push_back(c.f);\n            pick_dirs.push_back(c.d);\n        }\n\n        int cnt = (int)pick_pairs.size();\n\n        vector<int> target_dir(F, -1);\n        for (int k = 0; k < cnt; k++) {\n            target_dir[pick_fingers[k]] = pick_dirs[k];\n        }\n\n        rotate_fingers_to(target_dir);\n\n        {\n            vector<char> rot = blank_rot();\n            vector<char> act = blank_act();\n\n            for (int k = 0; k < cnt; k++) {\n                int f = pick_fingers[k];\n                int pid = pick_pairs[k];\n\n                act[f] = 'P';\n                holding[f] = pid;\n                s[src[pid].x][src[pid].y] = '0';\n            }\n\n            add_op('.', rot, act);\n        }\n\n        vector<int> carrying;\n        for (int f = 0; f < F; f++) {\n            if (holding[f] >= 0) carrying.push_back(f);\n        }\n\n        /*\n            Place phase.\n            Repeatedly choose a root position maximizing number of carried items\n            placeable from there.\n        */\n        while (!carrying.empty()) {\n            int best_count = -1;\n            int best_cost2 = INT_MAX;\n            Pos best_root{-1, -1};\n\n            for (int f0 : carrying) {\n                int pid0 = holding[f0];\n                Pos q0 = dst[pair_dst[pid0]];\n\n                for (auto rc : reaches_for_cell(q0)) {\n                    Pos r = rc.r;\n\n                    int cnt_place = 0;\n                    for (int f : carrying) {\n                        int pid = holding[f];\n                        Pos q = dst[pair_dst[pid]];\n                        int dd;\n                        if (finger_can_reach_from_root(f, r, q, dd)) {\n                            cnt_place++;\n                        }\n                    }\n\n                    int cost = abs(root_x - r.x) + abs(root_y - r.y);\n\n                    if (cnt_place > best_count ||\n                        (cnt_place == best_count && cost < best_cost2)) {\n                        best_count = cnt_place;\n                        best_cost2 = cost;\n                        best_root = r;\n                    }\n                }\n            }\n\n            move_root_to(best_root.x, best_root.y);\n\n            vector<int> place_fingers;\n            vector<int> place_dirs;\n\n            for (int f : carrying) {\n                int pid = holding[f];\n                Pos q = dst[pair_dst[pid]];\n                int d;\n                if (finger_can_reach_from_root(f, {root_x, root_y}, q, d)) {\n                    place_fingers.push_back(f);\n                    place_dirs.push_back(d);\n                }\n            }\n\n            vector<int> tdir(F, -1);\n            for (int i = 0; i < (int)place_fingers.size(); i++) {\n                tdir[place_fingers[i]] = place_dirs[i];\n            }\n\n            rotate_fingers_to(tdir);\n\n            {\n                vector<char> rot = blank_rot();\n                vector<char> act = blank_act();\n\n                for (int f : place_fingers) {\n                    int pid = holding[f];\n                    int did = pair_dst[pid];\n                    Pos q = dst[did];\n\n                    act[f] = 'P';\n                    holding[f] = -1;\n                    done[pid] = 1;\n                    remaining--;\n                    s[q.x][q.y] = '1';\n                }\n\n                add_op('.', rot, act);\n            }\n\n            carrying.clear();\n            for (int f = 0; f < F; f++) {\n                if (holding[f] >= 0) carrying.push_back(f);\n            }\n        }\n    }\n\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << len[i - 1] << '\\n';\n    }\n    cout << 0 << ' ' << 0 << '\\n';\n\n    for (const string& op : ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n    bool operator==(const Pt& o) const { return x == o.x && y == o.y; }\n};\n\nstruct Fish {\n    int x, y, t;\n};\n\nstatic const int LIM = 100000;\n\nlong long perimeter_poly(const vector<Pt>& p) {\n    long long res = 0;\n    int m = (int)p.size();\n    for (int i = 0; i < m; i++) {\n        Pt a = p[i], b = p[(i + 1) % m];\n        res += abs(a.x - b.x) + abs(a.y - b.y);\n    }\n    return res;\n}\n\nvector<Pt> simplify_poly(vector<Pt> p) {\n    if (p.empty()) return p;\n\n    vector<Pt> q;\n    q.reserve(p.size());\n    for (auto v : p) {\n        if (q.empty() || !(q.back() == v)) q.push_back(v);\n    }\n    if (q.size() > 1 && q.front() == q.back()) q.pop_back();\n\n    bool changed = true;\n    while (changed && q.size() >= 4) {\n        changed = false;\n        vector<Pt> r;\n        r.reserve(q.size());\n        int m = q.size();\n        for (int i = 0; i < m; i++) {\n            Pt a = q[(i - 1 + m) % m], b = q[i], c = q[(i + 1) % m];\n            if ((a.x == b.x && b.x == c.x) || (a.y == b.y && b.y == c.y)) {\n                changed = true;\n            } else {\n                r.push_back(b);\n            }\n        }\n        q.swap(r);\n    }\n    return q;\n}\n\nbool inside_poly(const vector<Pt>& poly, int x, int y) {\n    bool in = false;\n    int m = poly.size();\n    for (int i = 0, j = m - 1; i < m; j = i++) {\n        Pt a = poly[j], b = poly[i];\n\n        if (a.x == b.x && x == a.x && min(a.y,b.y) <= y && y <= max(a.y,b.y)) return true;\n        if (a.y == b.y && y == a.y && min(a.x,b.x) <= x && x <= max(a.x,b.x)) return true;\n\n        if ((a.y > y) != (b.y > y)) {\n            long double xx = (long double)(b.x - a.x) * (y - a.y) / (long double)(b.y - a.y) + a.x;\n            if (xx >= x) in = !in;\n        }\n    }\n    return in;\n}\n\nint eval_exact(const vector<Pt>& poly, const vector<Fish>& fish) {\n    int s = 0;\n    for (auto &f : fish) {\n        if (inside_poly(poly, f.x, f.y)) s += f.t;\n    }\n    return s;\n}\n\nbool legal_basic(const vector<Pt>& p) {\n    if ((int)p.size() < 4 || (int)p.size() > 1000) return false;\n    if (perimeter_poly(p) > 400000) return false;\n\n    set<pair<int,int>> st;\n    for (auto &v : p) {\n        if (v.x < 0 || v.x > LIM || v.y < 0 || v.y > LIM) return false;\n        if (!st.insert({v.x, v.y}).second) return false;\n    }\n    for (int i = 0; i < (int)p.size(); i++) {\n        Pt a = p[i], b = p[(i + 1) % p.size()];\n        if (!(a.x == b.x || a.y == b.y)) return false;\n    }\n    return true;\n}\n\nvector<Pt> rect_poly(int x1, int y1, int x2, int y2) {\n    x1 = max(0, min(LIM, x1));\n    x2 = max(0, min(LIM, x2));\n    y1 = max(0, min(LIM, y1));\n    y2 = max(0, min(LIM, y2));\n    if (x1 > x2) swap(x1,x2);\n    if (y1 > y2) swap(y1,y2);\n    if (x1 == x2) x2 = min(LIM, x1 + 1);\n    if (y1 == y2) y2 = min(LIM, y1 + 1);\n    return {{x1,y1},{x2,y1},{x2,y2},{x1,y2}};\n}\n\nstruct CandComp {\n    int score = 0;\n    int per = 0;\n    int minx = 1e9, maxx = -1;\n    int miny = 1e9, maxy = -1;\n    vector<pair<int,int>> cells;\n};\n\npair<int,int> comp_center(const CandComp& c) {\n    long long sx = 0, sy = 0;\n    for (auto [x,y] : c.cells) {\n        sx += x;\n        sy += y;\n    }\n    if (c.cells.empty()) return {0,0};\n    return {(int)(sx / c.cells.size()), (int)(sy / c.cells.size())};\n}\n\nvector<CandComp> find_components(const vector<vector<unsigned char>>& sel,\n                                const vector<vector<int>>& diff) {\n    int W = sel.size(), H = sel[0].size();\n    vector<vector<unsigned char>> vis(W, vector<unsigned char>(H, 0));\n    vector<CandComp> comps;\n    int dx[4] = {1,-1,0,0};\n    int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n        if (!sel[i][j] || vis[i][j]) continue;\n\n        CandComp cc;\n        queue<pair<int,int>> q;\n        q.push({i,j});\n        vis[i][j] = 1;\n\n        while (!q.empty()) {\n            auto [x,y] = q.front();\n            q.pop();\n\n            cc.cells.push_back({x,y});\n            cc.score += diff[x][y];\n            cc.minx = min(cc.minx, x);\n            cc.maxx = max(cc.maxx, x);\n            cc.miny = min(cc.miny, y);\n            cc.maxy = max(cc.maxy, y);\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= W || ny < 0 || ny >= H || !sel[nx][ny]) {\n                    cc.per++;\n                } else if (!vis[nx][ny]) {\n                    vis[nx][ny] = 1;\n                    q.push({nx,ny});\n                }\n            }\n        }\n\n        comps.push_back(move(cc));\n    }\n\n    sort(comps.begin(), comps.end(), [](const CandComp& a, const CandComp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<Pt> boundary_from_selected(const vector<vector<unsigned char>>& occ, int G) {\n    int W = occ.size(), H = occ[0].size();\n\n    map<pair<int,int>, vector<pair<int,int>>> adj;\n\n    auto add = [&](int x1, int y1, int x2, int y2) {\n        adj[{x1,y1}].push_back({x2,y2});\n    };\n\n    for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n        if (!occ[i][j]) continue;\n\n        int x0 = i * G, x1 = min(LIM, (i + 1) * G);\n        int y0 = j * G, y1 = min(LIM, (j + 1) * G);\n\n        if (j == 0 || !occ[i][j - 1]) add(x0, y0, x1, y0);\n        if (i == W - 1 || !occ[i + 1][j]) add(x1, y0, x1, y1);\n        if (j == H - 1 || !occ[i][j + 1]) add(x1, y1, x0, y1);\n        if (i == 0 || !occ[i - 1][j]) add(x0, y1, x0, y0);\n    }\n\n    if (adj.empty()) return {};\n\n    pair<int,int> start = adj.begin()->first;\n    for (auto &kv : adj) {\n        if (kv.first.second < start.second ||\n            (kv.first.second == start.second && kv.first.first < start.first)) {\n            start = kv.first;\n        }\n    }\n\n    vector<Pt> poly;\n    pair<int,int> cur = start, prev = {-1,-1};\n\n    for (int iter = 0; iter < 30000; iter++) {\n        poly.push_back({cur.first, cur.second});\n\n        auto it = adj.find(cur);\n        if (it == adj.end() || it->second.empty()) break;\n\n        auto &v = it->second;\n        pair<int,int> nxt = v[0];\n        if (v.size() >= 2 && v[0] == prev) nxt = v[1];\n\n        for (int k = 0; k < (int)v.size(); k++) {\n            if (v[k] == nxt) {\n                v.erase(v.begin() + k);\n                break;\n            }\n        }\n\n        prev = cur;\n        cur = nxt;\n        if (cur == start) break;\n    }\n\n    return simplify_poly(poly);\n}\n\nvector<Pt> boundary_from_cells(const vector<pair<int,int>>& cells, int G, int W, int H) {\n    vector<vector<unsigned char>> occ(W, vector<unsigned char>(H, 0));\n    for (auto [i,j] : cells) occ[i][j] = 1;\n    return boundary_from_selected(occ, G);\n}\n\nint grid_perimeter(const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int per = 0;\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        if (i==0 || !occ[i-1][j]) per++;\n        if (i==W-1 || !occ[i+1][j]) per++;\n        if (j==0 || !occ[i][j-1]) per++;\n        if (j==H-1 || !occ[i][j+1]) per++;\n    }\n    return per;\n}\n\nvoid connect_point(vector<vector<unsigned char>>& occ, pair<int,int> a, pair<int,int> b) {\n    int x = a.first, y = a.second;\n    int tx = b.first, ty = b.second;\n\n    while (x != tx) {\n        occ[x][y] = 1;\n        x += (tx > x ? 1 : -1);\n    }\n    while (y != ty) {\n        occ[x][y] = 1;\n        y += (ty > y ? 1 : -1);\n    }\n    occ[x][y] = 1;\n}\n\nvoid add_component(vector<vector<unsigned char>>& occ, const CandComp& c) {\n    for (auto [x,y] : c.cells) occ[x][y] = 1;\n}\n\nvoid prune_leaves(vector<vector<unsigned char>>& occ, const vector<vector<int>>& diff) {\n    int W = occ.size(), H = occ[0].size();\n    queue<pair<int,int>> q;\n\n    auto deg = [&](int x, int y) {\n        int d = 0;\n        if (x > 0 && occ[x-1][y]) d++;\n        if (x+1 < W && occ[x+1][y]) d++;\n        if (y > 0 && occ[x][y-1]) d++;\n        if (y+1 < H && occ[x][y+1]) d++;\n        return d;\n    };\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n        if (occ[i][j] && diff[i][j] <= 0 && deg(i,j) <= 1) q.push({i,j});\n    }\n\n    while (!q.empty()) {\n        auto [x,y] = q.front();\n        q.pop();\n        if (!occ[x][y] || diff[x][y] > 0 || deg(x,y) > 1) continue;\n        occ[x][y] = 0;\n\n        for (auto [nx,ny] : {pair<int,int>{x-1,y}, {x+1,y}, {x,y-1}, {x,y+1}}) {\n            if (nx>=0 && nx<W && ny>=0 && ny<H && occ[nx][ny] && diff[nx][ny] <= 0 && deg(nx,ny) <= 1) {\n                q.push({nx,ny});\n            }\n        }\n    }\n}\n\nint manhattan_comp_to_occ(const CandComp& c, const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int best = 1e9;\n\n    // Fast approximation: compare center to occupied cells, limited scan is okay for ~100x100 grid.\n    auto cen = comp_center(c);\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        best = min(best, abs(cen.first - i) + abs(cen.second - j));\n    }\n    return best;\n}\n\npair<int,int> nearest_occ_cell(pair<int,int> p, const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int best = 1e9;\n    pair<int,int> bp = p;\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        int d = abs(p.first-i) + abs(p.second-j);\n        if (d < best) {\n            best = d;\n            bp = {i,j};\n        }\n    }\n    return bp;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    vector<Fish> fish;\n    fish.reserve(2 * n);\n\n    for (int i = 0; i < 2 * n; i++) {\n        int x, y;\n        cin >> x >> y;\n        fish.push_back({x, y, i < n ? 1 : -1});\n    }\n\n    vector<Pt> best = rect_poly(0,0,1,1);\n    int bestScore = eval_exact(best, fish);\n\n    int exactEvalCount = 0;\n    const int MAX_EXACT_EVAL = 95;\n\n    vector<int> gridSizes = {700, 850, 1000, 1250, 1600, 2000};\n    vector<double> thresholds = {-0.25, -0.10, 0.0, 0.20, 0.45, 0.75};\n\n    for (int G : gridSizes) {\n        int W = (LIM + G) / G;\n        int H = (LIM + G) / G;\n\n        vector<vector<int>> diff(W, vector<int>(H, 0));\n        for (auto &f : fish) {\n            int ix = min(W - 1, f.x / G);\n            int iy = min(H - 1, f.y / G);\n            diff[ix][iy] += f.t;\n        }\n\n        vector<vector<double>> sm(W, vector<double>(H, 0.0));\n        for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n            double s = 0, w = 0;\n            for (int dx=-1; dx<=1; dx++) for (int dy=-1; dy<=1; dy++) {\n                int ni=i+dx, nj=j+dy;\n                if (ni<0 || ni>=W || nj<0 || nj>=H) continue;\n                double ww = (dx==0 && dy==0 ? 4.0 : (dx==0 || dy==0 ? 2.0 : 1.0));\n                s += ww * diff[ni][nj];\n                w += ww;\n            }\n            sm[i][j] = s / w;\n        }\n\n        for (double th : thresholds) {\n            vector<vector<unsigned char>> sel(W, vector<unsigned char>(H, 0));\n            for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n                if (sm[i][j] > th) sel[i][j] = 1;\n            }\n\n            auto comps = find_components(sel, diff);\n\n            int checked = 0;\n            for (auto &cc : comps) {\n                if (cc.score <= 0) break;\n                if (checked >= 4) break;\n                checked++;\n\n                if (1LL * cc.per * G > 400000) continue;\n                if ((int)cc.cells.size() > 3500) continue;\n\n                vector<Pt> poly = boundary_from_cells(cc.cells, G, W, H);\n                poly = simplify_poly(poly);\n                if (!legal_basic(poly)) continue;\n\n                if (cc.score + 50 < bestScore) continue;\n\n                int sc = eval_exact(poly, fish);\n                exactEvalCount++;\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    best = poly;\n                }\n\n                if (exactEvalCount >= MAX_EXACT_EVAL) break;\n            }\n\n            if (exactEvalCount >= MAX_EXACT_EVAL) break;\n\n            // Cost-aware greedy merged candidates.\n            int K = min(12, (int)comps.size());\n            vector<int> usable;\n            for (int i=0;i<K;i++) {\n                if (comps[i].score > 0) usable.push_back(i);\n            }\n\n            vector<double> penalties = {0.0, 0.6, 1.0, 1.5, 2.2};\n\n            for (double pen : penalties) {\n                if (usable.empty()) continue;\n\n                vector<vector<unsigned char>> occ(W, vector<unsigned char>(H, 0));\n                vector<unsigned char> used(comps.size(), 0);\n\n                int start = usable[0];\n                add_component(occ, comps[start]);\n                used[start] = 1;\n\n                for (int step=1; step<=6; step++) {\n                    int bestId = -1;\n                    double bestGain = -1e100;\n\n                    for (int id : usable) if (!used[id]) {\n                        int d = manhattan_comp_to_occ(comps[id], occ);\n                        double gain = comps[id].score - pen * d;\n                        if (gain > bestGain) {\n                            bestGain = gain;\n                            bestId = id;\n                        }\n                    }\n\n                    if (bestId == -1) break;\n                    if (bestGain < -5.0 && step >= 2) break;\n\n                    auto ccen = comp_center(comps[bestId]);\n                    auto nearp = nearest_occ_cell(ccen, occ);\n                    connect_point(occ, nearp, ccen);\n                    add_component(occ, comps[bestId]);\n                    used[bestId] = 1;\n\n                    prune_leaves(occ, diff);\n\n                    int gper = grid_perimeter(occ);\n                    if (1LL * gper * G > 400000) continue;\n\n                    vector<Pt> poly = boundary_from_selected(occ, G);\n                    poly = simplify_poly(poly);\n\n                    if (!legal_basic(poly)) continue;\n\n                    int sc = eval_exact(poly, fish);\n                    exactEvalCount++;\n\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = poly;\n                    }\n\n                    if (exactEvalCount >= MAX_EXACT_EVAL) break;\n                }\n\n                if (exactEvalCount >= MAX_EXACT_EVAL) break;\n            }\n\n            if (exactEvalCount >= MAX_EXACT_EVAL) break;\n        }\n\n        if (exactEvalCount >= MAX_EXACT_EVAL) break;\n    }\n\n    // Coarse prefix-sum rectangle candidates.\n    {\n        const int G = 2000;\n        int W = (LIM + G) / G;\n        int H = (LIM + G) / G;\n        vector<vector<int>> a(W, vector<int>(H, 0));\n        for (auto &f : fish) {\n            a[min(W-1, f.x/G)][min(H-1, f.y/G)] += f.t;\n        }\n\n        vector<vector<int>> ps(W+1, vector<int>(H+1, 0));\n        for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n            ps[i+1][j+1] = ps[i+1][j] + ps[i][j+1] - ps[i][j] + a[i][j];\n        }\n\n        auto sum_rect = [&](int x1,int y1,int x2,int y2) {\n            return ps[x2][y2] - ps[x1][y2] - ps[x2][y1] + ps[x1][y1];\n        };\n\n        vector<tuple<int,int,int,int,int>> cand;\n        cand.reserve(200000);\n\n        for (int x1=0;x1<W;x1++) for (int x2=x1+1;x2<=W;x2++) {\n            int width = (x2 - x1) * G;\n            if (2 * width > 400000) continue;\n            int maxh = 400000 / 2 - width;\n            int maxCellsH = maxh / G;\n            if (maxCellsH <= 0) continue;\n\n            for (int y1=0;y1<H;y1++) {\n                int yMax = min(H, y1 + maxCellsH);\n                for (int y2=y1+1;y2<=yMax;y2++) {\n                    int s = sum_rect(x1,y1,x2,y2);\n                    if (s > 0) cand.push_back({s,x1,y1,x2,y2});\n                }\n            }\n        }\n\n        sort(cand.rbegin(), cand.rend());\n        int lim = min(120, (int)cand.size());\n        for (int k=0;k<lim;k++) {\n            auto [s,x1,y1,x2,y2] = cand[k];\n            vector<Pt> p = rect_poly(x1*G, y1*G, min(LIM,x2*G), min(LIM,y2*G));\n            if (!legal_basic(p)) continue;\n            int sc = eval_exact(p, fish);\n            if (sc > bestScore) {\n                bestScore = sc;\n                best = p;\n            }\n        }\n    }\n\n    best = simplify_poly(best);\n    if (!legal_basic(best)) {\n        best = rect_poly(0,0,1,1);\n    }\n\n    cout << best.size() << '\\n';\n    for (auto &p : best) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    long long w, h;\n};\n\nstruct Op {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Placed {\n    long long x1, y1, x2, y2;\n};\n\nstruct Cand {\n    long long score;\n    vector<Op> ops;\n};\n\nstatic inline bool overlap1d(long long l1, long long r1, long long l2, long long r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nlong long simulate_score(const vector<Op>& ops, const vector<Rect>& rects) {\n    int N = rects.size();\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n\n    long long W = 0, H = 0;\n\n    for (auto &op : ops) {\n        int i = op.p;\n        long long w = rects[i].w;\n        long long h = rects[i].h;\n        if (op.r) swap(w, h);\n\n        long long x = 0, y = 0;\n\n        if (op.d == 'U') {\n            if (op.b == -1) x = 0;\n            else x = pos[op.b].x2;\n\n            y = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(x, x + w, pos[j].x1, pos[j].x2)) {\n                    y = max(y, pos[j].y2);\n                }\n            }\n        } else {\n            if (op.b == -1) y = 0;\n            else y = pos[op.b].y2;\n\n            x = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(y, y + h, pos[j].y1, pos[j].y2)) {\n                    x = max(x, pos[j].x2);\n                }\n            }\n        }\n\n        pos[i] = {x, y, x + w, y + h};\n        used[i] = 1;\n        W = max(W, x + w);\n        H = max(H, y + h);\n    }\n\n    long long penalty = 0;\n    for (int i = 0; i < N; i++) if (!used[i]) {\n        penalty += rects[i].w + rects[i].h;\n    }\n\n    return W + H + penalty;\n}\n\nvector<int> make_rotation_policy(const vector<Rect>& a, int mode, int seed) {\n    int N = a.size();\n    vector<int> r(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        long long w = a[i].w, h = a[i].h;\n\n        if (mode == 0) {\n            r[i] = 0;\n        } else if (mode == 1) {\n            // make width <= height\n            r[i] = (w > h);\n        } else if (mode == 2) {\n            // make width >= height\n            r[i] = (w < h);\n        } else if (mode == 3) {\n            r[i] = ((i + seed) & 1);\n        } else if (mode == 4) {\n            r[i] = ((i / 2 + seed) & 1);\n        } else if (mode == 5) {\n            uint32_t x = (uint32_t)(i * 1103515245u + seed * 12345u + 998244353u);\n            r[i] = (x >> 30) & 1;\n        } else {\n            // rotate if it makes current orientation closer to square-ish average\n            r[i] = (abs((long long)w - (long long)h) > 0 && ((i + mode + seed) % 3 == 0));\n        }\n    }\n\n    return r;\n}\n\nvector<Op> make_vertical_shelves(const vector<Rect>& a, const vector<int>& r, long double targetH, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int last_col_first = -1;\n    int prev = -1;\n    long double curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newCol = false;\n\n        if (i == 0) {\n            newCol = true;\n        } else {\n            long double projected = curH + hh[i];\n\n            if (projected > targetH) {\n                long double before = fabsl(targetH - curH);\n                long double after = fabsl(targetH - projected);\n\n                if (variant == 0) {\n                    newCol = true;\n                } else if (variant == 1) {\n                    newCol = after > before * 0.85L;\n                } else if (variant == 2) {\n                    newCol = after > before * 0.65L;\n                } else {\n                    newCol = after > before;\n                }\n            }\n        }\n\n        if (newCol) {\n            if (last_col_first == -1) ops.push_back({i, r[i], 'U', -1});\n            else ops.push_back({i, r[i], 'U', last_col_first});\n            last_col_first = i;\n            curH = hh[i];\n        } else {\n            ops.push_back({i, r[i], 'L', prev});\n            curH += hh[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\nvector<Op> make_horizontal_shelves(const vector<Rect>& a, const vector<int>& r, long double targetW, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int first_row = -1;\n    int prev = -1;\n    long double curW = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newRow = false;\n\n        if (i == 0) {\n            newRow = true;\n        } else {\n            long double projected = curW + ww[i];\n\n            if (projected > targetW) {\n                long double before = fabsl(targetW - curW);\n                long double after = fabsl(targetW - projected);\n\n                if (variant == 0) {\n                    newRow = true;\n                } else if (variant == 1) {\n                    newRow = after > before * 0.85L;\n                } else if (variant == 2) {\n                    newRow = after > before * 0.65L;\n                } else {\n                    newRow = after > before;\n                }\n            }\n        }\n\n        if (newRow) {\n            if (first_row == -1) ops.push_back({i, r[i], 'L', -1});\n            else ops.push_back({i, r[i], 'L', first_row});\n            first_row = i;\n            curW = ww[i];\n        } else {\n            ops.push_back({i, r[i], 'U', prev});\n            curW += ww[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\n// A skyline-like greedy: for each rectangle, choose among legal references the placement\n// that minimizes current predicted W+H.\n// This is stronger than plain shelves, while respecting increasing index order.\nvector<Op> make_greedy_anchor_layout(const vector<Rect>& a, const vector<int>& r, int beam_mode) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long long bestVal = LLONG_MAX;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n        for (int b = 0; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            long long x = 0, y = 0;\n\n            if (d == 'U') {\n                x = (b == -1 ? 0 : pos[b].x2);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(x, x + wi, pos[j].x1, pos[j].x2)) {\n                        y = max(y, pos[j].y2);\n                    }\n                }\n            } else {\n                y = (b == -1 ? 0 : pos[b].y2);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(y, y + hi, pos[j].y1, pos[j].y2)) {\n                        x = max(x, pos[j].x2);\n                    }\n                }\n            }\n\n            long long nW = max(curW, x + wi);\n            long long nH = max(curH, y + hi);\n\n            long long val;\n            if (beam_mode == 0) {\n                val = nW + nH;\n            } else if (beam_mode == 1) {\n                val = nW + nH + llabs(nW - nH) / 4;\n            } else if (beam_mode == 2) {\n                val = max(nW, nH) * 2 + min(nW, nH);\n            } else {\n                val = nW + nH + (long long)(0.000001L * (long double)nW * (long double)nH);\n            }\n\n            // small deterministic tie-breaker preferring compact lower-left\n            val = val * 1000000LL + x + y;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = {x, y, x + wi, y + hi};\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\n// Variant: split into blocks, and inside each block use greedy anchors.\n// New block is biased to start from axes / previous block.\nvector<Op> make_mixed_layout(const vector<Rect>& a, const vector<int>& r, int blockSize, int mode) {\n    int N = a.size();\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long long bestVal = LLONG_MAX;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n\n        int start = max(0, i - blockSize);\n        for (int b = start; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        // also try some older structural anchors\n        for (int b = 0; b < i; b += max(1, blockSize / 2)) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            long long x = 0, y = 0;\n\n            if (d == 'U') {\n                x = (b == -1 ? 0 : pos[b].x2);\n                y = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(x, x + wi, pos[j].x1, pos[j].x2)) {\n                        y = max(y, pos[j].y2);\n                    }\n                }\n            } else {\n                y = (b == -1 ? 0 : pos[b].y2);\n                x = 0;\n                for (int j = 0; j < N; j++) if (used[j]) {\n                    if (overlap1d(y, y + hi, pos[j].y1, pos[j].y2)) {\n                        x = max(x, pos[j].x2);\n                    }\n                }\n            }\n\n            long long nW = max(curW, x + wi);\n            long long nH = max(curH, y + hi);\n\n            long long val;\n            if (mode == 0) {\n                val = nW + nH;\n            } else if (mode == 1) {\n                val = nW + nH + llabs(nW - nH) / 3;\n            } else {\n                val = max(nW, nH) * 2 + min(nW, nH);\n            }\n\n            val = val * 1000000LL + x + y;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = {x, y, x + wi, y + hi};\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n\n    vector<Rect> a(N);\n    for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n    long double area = 0;\n    for (auto &e : a) area += (long double)e.w * (long double)e.h;\n    long double root = sqrt(area);\n\n    vector<Cand> cands;\n    cands.reserve(5000);\n\n    auto add_candidate = [&](const vector<Op>& ops) {\n        long long sc = simulate_score(ops, a);\n        cands.push_back({sc, ops});\n    };\n\n    // Shelf candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 8; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n\n            for (int k = 0; k < 45; k++) {\n                long double factor = 0.45L + 0.035L * k;\n                for (int var = 0; var < 4; var++) {\n                    add_candidate(make_vertical_shelves(a, r, root * factor, var));\n                    add_candidate(make_horizontal_shelves(a, r, root * factor, var));\n                }\n            }\n        }\n    }\n\n    // Greedy anchor candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 12; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bm = 0; bm < 4; bm++) {\n                add_candidate(make_greedy_anchor_layout(a, r, bm));\n            }\n        }\n    }\n\n    // Mixed restricted-anchor candidates.\n    vector<int> blockSizes = {4, 6, 8, 10, 12, 15, 20, 30};\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 6; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bs : blockSizes) {\n                for (int bm = 0; bm < 3; bm++) {\n                    add_candidate(make_mixed_layout(a, r, bs, bm));\n                }\n            }\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& x, const Cand& y) {\n        return x.score < y.score;\n    });\n\n    // Remove exact duplicate operation sequences among top candidates.\n    vector<Cand> uniq;\n    uniq.reserve(cands.size());\n\n    auto signature = [](const vector<Op>& ops) {\n        string s;\n        s.reserve(ops.size() * 8);\n        for (auto &op : ops) {\n            s += char(op.r + '0');\n            s += op.d;\n            s += char((op.b + 2) % 251);\n            s += ',';\n        }\n        return s;\n    };\n\n    unordered_set<string> seen;\n    for (auto &c : cands) {\n        string sig = signature(c.ops);\n        if (seen.insert(sig).second) {\n            uniq.push_back(std::move(c));\n            if ((int)uniq.size() >= max(T * 3, 300)) break;\n        }\n    }\n\n    if (uniq.empty()) {\n        vector<int> r(N, 0);\n        add_candidate(make_vertical_shelves(a, r, root, 0));\n        uniq = cands;\n    }\n\n    // Query best predicted candidates.\n    // If T is larger than available unique candidates, cycle through them.\n    long long bestObserved = LLONG_MAX;\n\n    for (int t = 0; t < T; t++) {\n        const vector<Op>& ops = uniq[t % uniq.size()].ops;\n\n        cout << ops.size() << '\\n';\n        for (auto &op : ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        if (!cin) return 0;\n\n        bestObserved = min(bestObserved, Wp + Hp);\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>> g;\n    vector<pair<int,int>> xy;\n\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n    const double TL = 1.92;\n\n    Solver() : rng(123456789) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    double rnd(double l, double r) {\n        return uniform_real_distribution<double>(l, r)(rng);\n    }\n\n    long long calcScore(const vector<int>& par) {\n        vector<vector<int>> ch(n);\n        vector<int> roots;\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -1) {\n                roots.push_back(v);\n            } else {\n                ch[par[v]].push_back(v);\n            }\n        }\n\n        long long score = 1;\n        vector<int> dep(n, -1);\n        queue<int> q;\n\n        for (int r : roots) {\n            dep[r] = 0;\n            q.push(r);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            score += 1LL * (dep[v] + 1) * A[v];\n\n            for (int to : ch[v]) {\n                dep[to] = dep[v] + 1;\n                q.push(to);\n            }\n        }\n\n        return score;\n    }\n\n    vector<int> bfsConstruct(double lowBias, double noise, bool randomOrder) {\n        vector<vector<int>> reach(n);\n\n        for (int s = 0; s < n; s++) {\n            vector<int> d(n, -1);\n            queue<int> q;\n            d[s] = 0;\n            q.push(s);\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                reach[s].push_back(v);\n\n                if (d[v] == h) continue;\n\n                for (int to : g[v]) {\n                    if (d[to] == -1) {\n                        d[to] = d[v] + 1;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        vector<char> covered(n, 0), isRoot(n, 0);\n        vector<int> roots;\n        int coveredCnt = 0;\n\n        while (coveredCnt < n) {\n            int best = -1;\n            double bestVal = -1e100;\n\n            vector<int> cand(n);\n            iota(cand.begin(), cand.end(), 0);\n            if (randomOrder) shuffle(cand.begin(), cand.end(), rng);\n\n            for (int v : cand) {\n                if (isRoot[v]) continue;\n\n                int gain = 0;\n                int gainW = 0;\n\n                for (int u : reach[v]) {\n                    if (!covered[u]) {\n                        gain++;\n                        gainW += A[u];\n                    }\n                }\n\n                if (gain == 0) continue;\n\n                double val =\n                    gain * 1000.0\n                    - lowBias * A[v]\n                    + 0.04 * gainW\n                    + rnd(-noise, noise);\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = v;\n                }\n            }\n\n            if (best == -1) {\n                for (int v = 0; v < n; v++) {\n                    if (!covered[v]) {\n                        best = v;\n                        break;\n                    }\n                }\n            }\n\n            roots.push_back(best);\n            isRoot[best] = 1;\n\n            for (int u : reach[best]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        vector<int> dist(n, INT_MAX), par(n, -2);\n\n        struct Node {\n            double key;\n            int v;\n            bool operator<(const Node& other) const {\n                return key > other.key;\n            }\n        };\n\n        priority_queue<Node> pq;\n\n        for (int r : roots) {\n            dist[r] = 0;\n            par[r] = -1;\n            pq.push({0.003 * A[r], r});\n        }\n\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n\n            int v = cur.v;\n            if (dist[v] == h) continue;\n\n            vector<int> ns = g[v];\n            shuffle(ns.begin(), ns.end(), rng);\n\n            for (int to : ns) {\n                if (dist[to] == INT_MAX) {\n                    dist[to] = dist[v] + 1;\n                    par[to] = v;\n\n                    double key =\n                        dist[to]\n                        + 0.014 * (100 - A[to])\n                        + rnd(0.0, 0.04);\n\n                    pq.push({key, to});\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    vector<int> deepDfsConstruct(double rootBias, double childBias, double randomness) {\n        vector<int> par(n, -2), dep(n, -1);\n        vector<char> used(n, 0);\n        int usedCnt = 0;\n\n        vector<pair<double,int>> key;\n        key.reserve(n);\n\n        for (int v = 0; v < n; v++) {\n            key.push_back({A[v] * rootBias + rnd(0.0, randomness), v});\n        }\n\n        sort(key.begin(), key.end());\n\n        vector<int> order;\n        order.reserve(n);\n        for (auto [_, v] : key) order.push_back(v);\n\n        int ptr = 0;\n\n        while (usedCnt < n) {\n            int root = -1;\n\n            while (ptr < n && used[order[ptr]]) ptr++;\n            if (ptr < n) root = order[ptr];\n\n            if (root == -1) {\n                for (int v = 0; v < n; v++) {\n                    if (!used[v]) {\n                        root = v;\n                        break;\n                    }\n                }\n            }\n\n            used[root] = 1;\n            usedCnt++;\n            par[root] = -1;\n            dep[root] = 0;\n\n            vector<int> stk;\n            stk.push_back(root);\n\n            while (!stk.empty()) {\n                int v = stk.back();\n\n                if (dep[v] >= h) {\n                    stk.pop_back();\n                    continue;\n                }\n\n                vector<int> cand;\n                for (int to : g[v]) {\n                    if (!used[to]) cand.push_back(to);\n                }\n\n                if (cand.empty()) {\n                    stk.pop_back();\n                    continue;\n                }\n\n                int best = -1;\n                double bestScore = -1e100;\n\n                for (int to : cand) {\n                    int freeNei = 0;\n                    for (int w : g[to]) {\n                        if (!used[w]) freeNei++;\n                    }\n\n                    double sc =\n                        childBias * A[to]\n                        + 4.0 * freeNei\n                        + 12.0 * dep[v]\n                        + rnd(0.0, randomness);\n\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = to;\n                    }\n                }\n\n                used[best] = 1;\n                usedCnt++;\n                par[best] = v;\n                dep[best] = dep[v] + 1;\n                stk.push_back(best);\n\n                // Safe occasional branch.\n                if (dep[v] + 1 <= h && rnd(0.0, 1.0) < 0.15) {\n                    vector<int> cand2;\n                    for (int to : g[v]) {\n                        if (!used[to]) cand2.push_back(to);\n                    }\n\n                    if (!cand2.empty()) {\n                        int b2 = -1;\n                        double bs2 = -1e100;\n\n                        for (int to : cand2) {\n                            double sc =\n                                0.7 * childBias * A[to]\n                                + rnd(0.0, randomness);\n\n                            if (sc > bs2) {\n                                bs2 = sc;\n                                b2 = to;\n                            }\n                        }\n\n                        used[b2] = 1;\n                        usedCnt++;\n                        par[b2] = v;\n                        dep[b2] = dep[v] + 1;\n                        stk.push_back(b2);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    vector<int> greedyLayerConstruct(double randomness) {\n        vector<int> par(n, -2), dep(n, -1);\n        vector<char> used(n, 0);\n        int usedCnt = 0;\n\n        while (usedCnt < n) {\n            int root = -1;\n            double bestRootScore = 1e100;\n\n            for (int v = 0; v < n; v++) {\n                if (used[v]) continue;\n\n                int un = 0;\n                for (int to : g[v]) {\n                    if (!used[to]) un++;\n                }\n\n                double sc =\n                    A[v] * 5.0\n                    - un * 8.0\n                    + rnd(0.0, randomness);\n\n                if (sc < bestRootScore) {\n                    bestRootScore = sc;\n                    root = v;\n                }\n            }\n\n            used[root] = 1;\n            usedCnt++;\n            par[root] = -1;\n            dep[root] = 0;\n\n            vector<int> frontier = {root};\n\n            for (int d = 0; d < h && !frontier.empty(); d++) {\n                vector<pair<double, pair<int,int>>> cand;\n\n                for (int v : frontier) {\n                    for (int to : g[v]) {\n                        if (!used[to]) {\n                            int un = 0;\n                            for (int w : g[to]) {\n                                if (!used[w]) un++;\n                            }\n\n                            double sc =\n                                A[to] * (1.0 + 0.25 * d)\n                                + 2.5 * un\n                                + rnd(0.0, randomness);\n\n                            cand.push_back({-sc, {v, to}});\n                        }\n                    }\n                }\n\n                if (cand.empty()) break;\n\n                sort(cand.begin(), cand.end());\n\n                vector<int> next;\n\n                for (auto &e : cand) {\n                    int p = e.second.first;\n                    int v = e.second.second;\n\n                    if (used[v]) continue;\n\n                    used[v] = 1;\n                    usedCnt++;\n                    par[v] = p;\n                    dep[v] = d + 1;\n                    next.push_back(v);\n                }\n\n                frontier.swap(next);\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    vector<int> rerootTrees(const vector<int>& par0) {\n        vector<vector<int>> treeAdj(n);\n\n        for (int v = 0; v < n; v++) {\n            if (par0[v] != -1) {\n                treeAdj[v].push_back(par0[v]);\n                treeAdj[par0[v]].push_back(v);\n            }\n        }\n\n        vector<int> compId(n, -1);\n        vector<vector<int>> comps;\n\n        for (int s = 0; s < n; s++) {\n            if (compId[s] != -1) continue;\n\n            int id = (int)comps.size();\n            comps.push_back({});\n\n            queue<int> q;\n            q.push(s);\n            compId[s] = id;\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                comps.back().push_back(v);\n\n                for (int to : treeAdj[v]) {\n                    if (compId[to] == -1) {\n                        compId[to] = id;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        vector<int> newPar(n, -2);\n        vector<int> d(n);\n\n        for (auto &comp : comps) {\n            int bestRoot = comp[0];\n            long long bestVal = LLONG_MIN;\n\n            for (int r : comp) {\n                fill(d.begin(), d.end(), -1);\n\n                queue<int> q;\n                d[r] = 0;\n                q.push(r);\n\n                int mx = 0;\n                long long val = 0;\n\n                while (!q.empty()) {\n                    int v = q.front();\n                    q.pop();\n\n                    mx = max(mx, d[v]);\n                    val += 1LL * (d[v] + 1) * A[v];\n\n                    for (int to : treeAdj[v]) {\n                        if (d[to] == -1) {\n                            d[to] = d[v] + 1;\n                            q.push(to);\n                        }\n                    }\n                }\n\n                if (mx <= h && val > bestVal) {\n                    bestVal = val;\n                    bestRoot = r;\n                }\n            }\n\n            vector<char> seen(n, 0);\n            queue<int> q;\n\n            newPar[bestRoot] = -1;\n            seen[bestRoot] = 1;\n            q.push(bestRoot);\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                for (int to : treeAdj[v]) {\n                    if (!seen[to]) {\n                        seen[to] = 1;\n                        newPar[to] = v;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (newPar[v] == -2) newPar[v] = -1;\n        }\n\n        return newPar;\n    }\n\n    void solve() {\n        cin >> n >> m >> h;\n\n        A.resize(n);\n        for (int i = 0; i < n; i++) cin >> A[i];\n\n        g.assign(n, {});\n        for (int i = 0; i < m; i++) {\n            int u, v;\n            cin >> u >> v;\n            g[u].push_back(v);\n            g[v].push_back(u);\n        }\n\n        xy.resize(n);\n        for (int i = 0; i < n; i++) {\n            cin >> xy[i].first >> xy[i].second;\n        }\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestPar(n, -1);\n        long long bestScore = -1;\n\n        int iter = 0;\n\n        while (elapsed() < TL) {\n            vector<int> par;\n\n            int mode = iter % 6;\n\n            if (mode == 0 || mode == 1) {\n                double lowBias = 8.0 + (iter % 11) * 7.0;\n                double noise = 100.0 + (iter % 9) * 250.0;\n                par = bfsConstruct(lowBias, noise, iter & 1);\n            } else if (mode == 2 || mode == 3 || mode == 4) {\n                double rootBias = 2.0 + (iter % 7);\n                double childBias = 8.0 + (iter % 13) * 2.0;\n                double randomness = 20.0 + (iter % 17) * 12.0;\n                par = deepDfsConstruct(rootBias, childBias, randomness);\n            } else {\n                double randomness = 20.0 + (iter % 19) * 15.0;\n                par = greedyLayerConstruct(randomness);\n            }\n\n            par = rerootTrees(par);\n\n            long long sc = calcScore(par);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPar = par;\n            }\n\n            iter++;\n        }\n\n        for (int i = 0; i < n; i++) {\n            if (i) cout << ' ';\n            cout << bestPar[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char d;\n    int p;\n};\n\nstruct Candidate {\n    int cost = 1e9;\n    int removed = -1;\n    char dir = '?';\n    int p = -1;\n    int k = -1;\n    vector<pair<int,int>> cells;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<string> board(N);\n    for (int i = 0; i < N; i++) cin >> board[i];\n\n    vector<Operation> ans;\n\n    auto oni_count = [&]() {\n        int c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (board[i][j] == 'x') c++;\n            }\n        }\n        return c;\n    };\n\n    auto better = [&](const Candidate& a, const Candidate& b) {\n        if (b.removed == -1) return true;\n\n        // Primary: better removed / cost.\n        long long lhs = 1LL * a.removed * b.cost;\n        long long rhs = 1LL * b.removed * a.cost;\n        if (lhs != rhs) return lhs > rhs;\n\n        // Secondary: remove more Oni at once.\n        if (a.removed != b.removed) return a.removed > b.removed;\n\n        // Tertiary: fewer moves.\n        if (a.cost != b.cost) return a.cost < b.cost;\n\n        // Final deterministic tie-break.\n        if (a.dir != b.dir) return a.dir < b.dir;\n        return a.p < b.p;\n    };\n\n    auto update = [&](Candidate& best, Candidate cand) {\n        if (cand.removed <= 0) return;\n        if (better(cand, best)) best = cand;\n    };\n\n    auto find_best_cycle = [&]() {\n        Candidate best;\n\n        // Upward cycles: column prefix with no Fukunokami.\n        for (int j = 0; j < N; j++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n\n            for (int i = 0; i < N; i++) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Candidate cand;\n                    cand.cost = 2 * (i + 1);\n                    cand.removed = removed;\n                    cand.dir = 'U';\n                    cand.p = j;\n                    cand.k = i + 1;\n                    cand.cells = cells;\n                    update(best, cand);\n                }\n            }\n        }\n\n        // Downward cycles: column suffix with no Fukunokami.\n        for (int j = 0; j < N; j++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n\n            for (int i = N - 1; i >= 0; i--) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Candidate cand;\n                    cand.cost = 2 * (N - i);\n                    cand.removed = removed;\n                    cand.dir = 'D';\n                    cand.p = j;\n                    cand.k = N - i;\n                    cand.cells = cells;\n                    update(best, cand);\n                }\n            }\n        }\n\n        // Left cycles: row prefix with no Fukunokami.\n        for (int i = 0; i < N; i++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n\n            for (int j = 0; j < N; j++) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Candidate cand;\n                    cand.cost = 2 * (j + 1);\n                    cand.removed = removed;\n                    cand.dir = 'L';\n                    cand.p = i;\n                    cand.k = j + 1;\n                    cand.cells = cells;\n                    update(best, cand);\n                }\n            }\n        }\n\n        // Right cycles: row suffix with no Fukunokami.\n        for (int i = 0; i < N; i++) {\n            bool hasFuku = false;\n            int removed = 0;\n            vector<pair<int,int>> cells;\n\n            for (int j = N - 1; j >= 0; j--) {\n                if (board[i][j] == 'o') hasFuku = true;\n                if (hasFuku) break;\n\n                cells.push_back({i, j});\n                if (board[i][j] == 'x') removed++;\n\n                if (removed > 0) {\n                    Candidate cand;\n                    cand.cost = 2 * (N - j);\n                    cand.removed = removed;\n                    cand.dir = 'R';\n                    cand.p = i;\n                    cand.k = N - j;\n                    cand.cells = cells;\n                    update(best, cand);\n                }\n            }\n        }\n\n        return best;\n    };\n\n    auto rev_dir = [](char d) {\n        if (d == 'U') return 'D';\n        if (d == 'D') return 'U';\n        if (d == 'L') return 'R';\n        return 'L';\n    };\n\n    while (oni_count() > 0) {\n        Candidate best = find_best_cycle();\n\n        // Guaranteed by problem constraints if Fukunokami positions are preserved.\n        if (best.removed <= 0) break;\n\n        for (auto [i, j] : best.cells) {\n            if (board[i][j] == 'x') board[i][j] = '.';\n        }\n\n        char r = rev_dir(best.dir);\n\n        for (int t = 0; t < best.k; t++) ans.push_back({best.dir, best.p});\n        for (int t = 0; t < best.k; t++) ans.push_back({r, best.p});\n    }\n\n    // This method is guaranteed to stay within 4N^2.\n    // Still keep the guard for safety.\n    if ((int)ans.size() > 4 * N * N) {\n        ans.resize(4 * N * N);\n    }\n\n    for (auto [d, p] : ans) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 100;\nstatic const int L = 500000;\n\nstruct Plan {\n    int a[N], b[N];\n};\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 88172645463325252ull) : x(seed) {}\n\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint eval_plan(const Plan& p, const vector<int>& T) {\n    static int cnt[N];\n    for (int i = 0; i < N; i++) cnt[i] = 0;\n\n    int x = 0;\n    for (int week = 0; week < L; week++) {\n        cnt[x]++;\n        if (cnt[x] & 1) x = p.a[x];\n        else x = p.b[x];\n    }\n\n    int err = 0;\n    for (int i = 0; i < N; i++) {\n        err += abs(cnt[i] - T[i]);\n    }\n    return err;\n}\n\nint sample_weighted(const vector<int>& pref, RNG& rng) {\n    int v = rng.next_int(1, L);\n    int id = lower_bound(pref.begin(), pref.end(), v) - pref.begin();\n    if (id >= N) id = N - 1;\n    return id;\n}\n\nPlan random_plan(const vector<int>& pref, RNG& rng) {\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        p.a[i] = sample_weighted(pref, rng);\n        p.b[i] = sample_weighted(pref, rng);\n    }\n    return p;\n}\n\nPlan weighted_balance_plan(const vector<int>& T, RNG& rng, double noise) {\n    struct Item {\n        int src;\n        double w;\n        double key;\n    };\n\n    vector<Item> items;\n    items.reserve(200);\n\n    for (int i = 0; i < N; i++) {\n        double w = T[i] * 0.5;\n        items.push_back({i, w, w * (1.0 + noise * (rng.next_double() - 0.5))});\n        items.push_back({i, w, w * (1.0 + noise * (rng.next_double() - 0.5))});\n    }\n\n    sort(items.begin(), items.end(), [](const Item& x, const Item& y) {\n        return x.key > y.key;\n    });\n\n    vector<double> load(N, 0.0);\n    vector<vector<int>> to_src(N);\n\n    vector<pair<int, int>> assigned;\n    assigned.reserve(200);\n\n    for (const auto& it : items) {\n        int best = 0;\n        double best_score = -1e100;\n\n        for (int j = 0; j < N; j++) {\n            double rem = T[j] - load[j];\n\n            double score = rem;\n\n            score += noise * 2000.0 * (rng.next_double() - 0.5);\n\n            if (score > best_score) {\n                best_score = score;\n                best = j;\n            }\n        }\n\n        load[best] += it.w;\n        assigned.push_back({it.src, best});\n    }\n\n    vector<int> outs[N];\n    for (auto [s, d] : assigned) {\n        outs[s].push_back(d);\n    }\n\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        while ((int)outs[i].size() < 2) {\n            outs[i].push_back(rng.next_int(0, N - 1));\n        }\n\n        if (rng.next_int(0, 1)) swap(outs[i][0], outs[i][1]);\n\n        p.a[i] = outs[i][0];\n        p.b[i] = outs[i][1];\n    }\n\n    return p;\n}\n\nPlan quota_plan(const vector<int>& T, RNG& rng) {\n    vector<double> rem(N);\n    vector<int> q(N, 0);\n\n    int sumq = 0;\n    for (int i = 0; i < N; i++) {\n        double exact = 200.0 * T[i] / L;\n        q[i] = (int)floor(exact);\n        rem[i] = exact - q[i];\n        sumq += q[i];\n    }\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        return rem[x] > rem[y];\n    });\n\n    for (int k = 0; sumq < 200; k++, sumq++) {\n        q[ord[k % N]]++;\n    }\n\n    vector<int> edges;\n    edges.reserve(200);\n    for (int i = 0; i < N; i++) {\n        for (int c = 0; c < q[i]; c++) edges.push_back(i);\n    }\n\n    while ((int)edges.size() < 200) {\n        edges.push_back(rng.next_int(0, N - 1));\n    }\n\n    shuffle(edges.begin(), edges.end(), mt19937((uint32_t)rng.next_u64()));\n\n    Plan p;\n    for (int i = 0; i < N; i++) {\n        p.a[i] = edges[2 * i];\n        p.b[i] = edges[2 * i + 1];\n    }\n    return p;\n}\n\nPlan mutate_plan(const Plan& base, const vector<int>& pref, RNG& rng, int changes) {\n    Plan p = base;\n    for (int k = 0; k < changes; k++) {\n        int i = rng.next_int(0, N - 1);\n        int side = rng.next_int(0, 1);\n        int to = sample_weighted(pref, rng);\n        if (side == 0) p.a[i] = to;\n        else p.b[i] = to;\n    }\n    return p;\n}\n\nPlan swap_mutate_plan(const Plan& base, RNG& rng, int changes) {\n    Plan p = base;\n\n    for (int k = 0; k < changes; k++) {\n        int i1 = rng.next_int(0, N - 1);\n        int i2 = rng.next_int(0, N - 1);\n        int s1 = rng.next_int(0, 1);\n        int s2 = rng.next_int(0, 1);\n\n        int* e1 = (s1 == 0 ? &p.a[i1] : &p.b[i1]);\n        int* e2 = (s2 == 0 ? &p.a[i2] : &p.b[i2]);\n\n        swap(*e1, *e2);\n    }\n\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n\n    vector<int> T(N);\n    for (int i = 0; i < N; i++) cin >> T[i];\n\n    vector<int> pref(N);\n    for (int i = 0; i < N; i++) {\n        pref[i] = T[i] + (i ? pref[i - 1] : 0);\n    }\n\n    RNG rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    Plan best;\n    for (int i = 0; i < N; i++) {\n        best.a[i] = best.b[i] = 0;\n    }\n\n    int best_err = eval_plan(best, T);\n\n    auto start = chrono::steady_clock::now();\n\n    int iter = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n        if (elapsed > 1.88) break;\n\n        Plan cand;\n\n        int mode = iter % 10;\n\n        if (mode <= 5) {\n            double noise;\n            if (mode == 0) noise = 0.00;\n            else if (mode == 1) noise = 0.05;\n            else if (mode == 2) noise = 0.10;\n            else if (mode == 3) noise = 0.20;\n            else if (mode == 4) noise = 0.35;\n            else noise = 0.60;\n\n            cand = weighted_balance_plan(T, rng, noise);\n        } else if (mode == 6) {\n            cand = quota_plan(T, rng);\n        } else if (mode == 7) {\n            cand = random_plan(pref, rng);\n        } else if (mode == 8) {\n            int changes = 1 + rng.next_int(0, 3);\n            cand = mutate_plan(best, pref, rng, changes);\n        } else {\n            int changes = 1 + rng.next_int(0, 5);\n            cand = swap_mutate_plan(best, rng, changes);\n        }\n\n        int err = eval_plan(cand, T);\n\n        if (err < best_err) {\n            best_err = err;\n            best = cand;\n        }\n\n        iter++;\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    bool operator<(const Edge& o) const {\n        if (w != o.w) return w < o.w;\n        if (u != o.u) return u < o.u;\n        return v < o.v;\n    }\n};\n\nstatic uint64_t rng_state = 98765432123456789ULL;\n\nuint64_t rng64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\nint rnd_int(int l, int r) {\n    return l + (int)(rng64() % (uint64_t)(r - l + 1));\n}\ndouble rnd01() {\n    return (rng64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<double> x(N), y(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        x[i] = 0.5 * (lx[i] + rx[i]);\n        y[i] = 0.5 * (ly[i] + ry[i]);\n    }\n\n    vector<vector<double>> dmat(N, vector<double>(N, 0));\n    vector<vector<int>> idist(N, vector<int>(N, 0));\n    vector<vector<int>> nearest(N);\n\n    for (int i = 0; i < N; i++) {\n        nearest[i].reserve(N - 1);\n        for (int j = 0; j < N; j++) if (i != j) nearest[i].push_back(j);\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            double dx = x[i] - x[j];\n            double dy = y[i] - y[j];\n            double d = sqrt(dx * dx + dy * dy);\n            dmat[i][j] = dmat[j][i] = d;\n            idist[i][j] = idist[j][i] = (int)d;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        sort(nearest[i].begin(), nearest[i].end(), [&](int a, int b) {\n            return dmat[i][a] < dmat[i][b];\n        });\n    }\n\n    auto mstCost = [&](const vector<int>& v) -> double {\n        int n = (int)v.size();\n        if (n <= 1) return 0.0;\n        vector<double> mn(n, 1e100);\n        vector<char> used(n, 0);\n        mn[0] = 0;\n        double cost = 0;\n\n        for (int it = 0; it < n; it++) {\n            int bi = -1;\n            for (int i = 0; i < n; i++) {\n                if (!used[i] && (bi == -1 || mn[i] < mn[bi])) bi = i;\n            }\n            used[bi] = 1;\n            cost += mn[bi];\n\n            int a = v[bi];\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                double d = dmat[a][v[j]];\n                if (d < mn[j]) mn[j] = d;\n            }\n        }\n        return cost;\n    };\n\n    auto totalMSTCost = [&](const vector<vector<int>>& groups) -> double {\n        double s = 0;\n        for (auto &g : groups) s += mstCost(g);\n        return s;\n    };\n\n    auto makeByOrder = [&](const vector<int>& order) {\n        vector<vector<int>> groups(M);\n        int p = 0;\n        for (int k = 0; k < M; k++) {\n            groups[k].assign(order.begin() + p, order.begin() + p + G[k]);\n            p += G[k];\n        }\n        return groups;\n    };\n\n    vector<vector<vector<int>>> candidates;\n\n    auto addCandidate = [&](vector<vector<int>> g) {\n        bool ok = true;\n        vector<int> cnt(N, 0);\n        for (int k = 0; k < M; k++) {\n            if ((int)g[k].size() != G[k]) ok = false;\n            for (int v : g[k]) if (0 <= v && v < N) cnt[v]++;\n        }\n        for (int i = 0; i < N; i++) if (cnt[i] != 1) ok = false;\n        if (ok) candidates.push_back(std::move(g));\n    };\n\n    auto mortonKey = [&](int i, bool swapxy, bool revx, bool revy) -> long long {\n        int xi = max(0, min(10000, (int)x[i]));\n        int yi = max(0, min(10000, (int)y[i]));\n        if (revx) xi = 10000 - xi;\n        if (revy) yi = 10000 - yi;\n        if (swapxy) swap(xi, yi);\n\n        long long key = 0;\n        for (int b = 0; b < 14; b++) {\n            key |= ((long long)((xi >> b) & 1)) << (2 * b);\n            key |= ((long long)((yi >> b) & 1)) << (2 * b + 1);\n        }\n        return key;\n    };\n\n    // Linear / space-filling candidates.\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (x[a] != x[b]) return x[a] < x[b];\n            return y[a] < y[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (y[a] != y[b]) return y[a] < y[b];\n            return x[a] < x[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        for (int sw = 0; sw < 2; sw++) {\n            for (int rxv = 0; rxv < 2; rxv++) {\n                for (int ryv = 0; ryv < 2; ryv++) {\n                    iota(ord.begin(), ord.end(), 0);\n                    sort(ord.begin(), ord.end(), [&](int a, int b) {\n                        long long ka = mortonKey(a, sw, rxv, ryv);\n                        long long kb = mortonKey(b, sw, rxv, ryv);\n                        if (ka != kb) return ka < kb;\n                        return a < b;\n                    });\n                    addCandidate(makeByOrder(ord));\n                }\n            }\n        }\n\n        for (int B : {4, 5, 7, 8, 10, 12, 16, 20}) {\n            for (int mode = 0; mode < 2; mode++) {\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int ca = min(B - 1, max(0, (int)(x[a] * B / 10001.0)));\n                    int cb = min(B - 1, max(0, (int)(x[b] * B / 10001.0)));\n                    int ra = min(B - 1, max(0, (int)(y[a] * B / 10001.0)));\n                    int rb = min(B - 1, max(0, (int)(y[b] * B / 10001.0)));\n\n                    long long ka, kb;\n                    if (mode == 0) {\n                        ka = (long long)ra * B + ((ra & 1) ? (B - 1 - ca) : ca);\n                        kb = (long long)rb * B + ((rb & 1) ? (B - 1 - cb) : cb);\n                    } else {\n                        ka = (long long)ca * B + ((ca & 1) ? (B - 1 - ra) : ra);\n                        kb = (long long)cb * B + ((cb & 1) ? (B - 1 - rb) : rb);\n                    }\n\n                    if (ka != kb) return ka < kb;\n                    return mode == 0 ? x[a] < x[b] : y[a] < y[b];\n                });\n                addCandidate(makeByOrder(ord));\n            }\n        }\n    }\n\n    // Recursive bisection candidates.\n    function<void(vector<int>&, vector<int>&, vector<vector<int>>&, int)> recBuild =\n        [&](vector<int>& pts, vector<int>& gids, vector<vector<int>>& groups, int depth) {\n            if (gids.empty()) return;\n            if ((int)gids.size() == 1) {\n                groups[gids[0]] = pts;\n                return;\n            }\n\n            double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n            for (int p : pts) {\n                minx = min(minx, x[p]);\n                maxx = max(maxx, x[p]);\n                miny = min(miny, y[p]);\n                maxy = max(maxy, y[p]);\n            }\n\n            vector<int> order = gids;\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                if (G[a] != G[b]) return G[a] > G[b];\n                return a < b;\n            });\n\n            for (int i = 0; i < (int)order.size(); i++) {\n                if (rnd01() < 0.25) {\n                    int j = rnd_int(i, (int)order.size() - 1);\n                    swap(order[i], order[j]);\n                }\n            }\n\n            int total = (int)pts.size();\n            int target = total / 2;\n\n            vector<int> leftG, rightG;\n            int sumL = 0;\n            for (int id : order) {\n                if (sumL < target) {\n                    leftG.push_back(id);\n                    sumL += G[id];\n                } else {\n                    rightG.push_back(id);\n                }\n            }\n\n            bool improved = true;\n            while (improved) {\n                improved = false;\n                int cur = abs(sumL - (total - sumL));\n\n                for (int i = 0; i < (int)leftG.size(); i++) {\n                    int ns = sumL - G[leftG[i]];\n                    int nd = abs(ns - (total - ns));\n                    if (!rightG.empty() && nd < cur) {\n                        rightG.push_back(leftG[i]);\n                        leftG.erase(leftG.begin() + i);\n                        sumL = ns;\n                        improved = true;\n                        break;\n                    }\n                }\n\n                if (improved) continue;\n\n                for (int i = 0; i < (int)rightG.size(); i++) {\n                    int ns = sumL + G[rightG[i]];\n                    int nd = abs(ns - (total - ns));\n                    if (nd < cur) {\n                        leftG.push_back(rightG[i]);\n                        rightG.erase(rightG.begin() + i);\n                        sumL = ns;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n\n            if (leftG.empty() || rightG.empty()) {\n                leftG.clear();\n                rightG.clear();\n                sumL = 0;\n                for (int i = 0; i < (int)order.size(); i++) {\n                    if (i < (int)order.size() / 2) {\n                        leftG.push_back(order[i]);\n                        sumL += G[order[i]];\n                    } else {\n                        rightG.push_back(order[i]);\n                    }\n                }\n            }\n\n            bool splitX = (maxx - minx) >= (maxy - miny);\n            if (rnd01() < 0.15) splitX = !splitX;\n\n            sort(pts.begin(), pts.end(), [&](int a, int b) {\n                double va = splitX ? x[a] : y[a];\n                double vb = splitX ? x[b] : y[b];\n                if (va != vb) return va < vb;\n                return (splitX ? y[a] : x[a]) < (splitX ? y[b] : x[b]);\n            });\n\n            vector<int> lpts(pts.begin(), pts.begin() + sumL);\n            vector<int> rpts(pts.begin() + sumL, pts.end());\n\n            recBuild(lpts, leftG, groups, depth + 1);\n            recBuild(rpts, rightG, groups, depth + 1);\n        };\n\n    int recAttempts = 70;\n    if (M <= 20) recAttempts = 110;\n    if (M >= 180) recAttempts = 35;\n\n    for (int at = 0; at < recAttempts && timer.sec() < 0.8; at++) {\n        vector<int> pts(N), gids(M);\n        iota(pts.begin(), pts.end(), 0);\n        iota(gids.begin(), gids.end(), 0);\n\n        vector<vector<int>> g(M);\n        recBuild(pts, gids, g, 0);\n        addCandidate(g);\n    }\n\n    // Capacity-constrained seed clustering candidates.\n    auto buildSeedCluster = [&](int variant) {\n        vector<vector<int>> groups(M);\n        vector<int> gids(M);\n        iota(gids.begin(), gids.end(), 0);\n\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n\n        vector<int> seeds(M, -1);\n        vector<int> all(N);\n        iota(all.begin(), all.end(), 0);\n\n        if (variant % 5 == 0) {\n            seeds[gids[0]] = min_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] + y[a] < x[b] + y[b];\n            })[0];\n        } else if (variant % 5 == 1) {\n            seeds[gids[0]] = min_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] - y[a] < x[b] - y[b];\n            })[0];\n        } else {\n            seeds[gids[0]] = rnd_int(0, N - 1);\n        }\n\n        vector<int> chosen;\n        chosen.push_back(seeds[gids[0]]);\n\n        for (int idx = 1; idx < M; idx++) {\n            int gid = gids[idx];\n            int bestCity = -1;\n            double bestVal = -1;\n\n            int trials = (variant < 5 ? N : min(N, 160));\n            for (int tt = 0; tt < trials; tt++) {\n                int c = (trials == N ? tt : rnd_int(0, N - 1));\n\n                double md = 1e100;\n                for (int s : chosen) md = min(md, dmat[c][s]);\n\n                // Larger groups prefer slightly more central seeds.\n                double noise = 1.0 + 0.10 * (rnd01() - 0.5);\n                double val = md * noise;\n                if (val > bestVal) {\n                    bestVal = val;\n                    bestCity = c;\n                }\n            }\n\n            seeds[gid] = bestCity;\n            chosen.push_back(bestCity);\n        }\n\n        vector<int> remCap = G;\n        vector<int> assigned(N, -1);\n\n        // Process cities by confidence: cities with one very near seed first.\n        vector<int> cityOrder(N);\n        iota(cityOrder.begin(), cityOrder.end(), 0);\n        sort(cityOrder.begin(), cityOrder.end(), [&](int a, int b) {\n            double ba = 1e100, sa = 1e100;\n            double bb = 1e100, sb = 1e100;\n\n            for (int k = 0; k < M; k++) {\n                double da = dmat[a][seeds[k]];\n                if (da < ba) {\n                    sa = ba;\n                    ba = da;\n                } else if (da < sa) {\n                    sa = da;\n                }\n\n                double db = dmat[b][seeds[k]];\n                if (db < bb) {\n                    sb = bb;\n                    bb = db;\n                } else if (db < sb) {\n                    sb = db;\n                }\n            }\n\n            double ca = sa - ba;\n            double cb = sb - bb;\n            return ca > cb;\n        });\n\n        for (int c : cityOrder) {\n            int bestK = -1;\n            double bestD = 1e100;\n\n            for (int k = 0; k < M; k++) {\n                if (remCap[k] <= 0) continue;\n                double d = dmat[c][seeds[k]];\n                d *= (1.0 + 0.05 * (rnd01() - 0.5));\n                if (d < bestD) {\n                    bestD = d;\n                    bestK = k;\n                }\n            }\n\n            if (bestK < 0) {\n                for (int k = 0; k < M; k++) if (remCap[k] > 0) {\n                    bestK = k;\n                    break;\n                }\n            }\n\n            assigned[c] = bestK;\n            remCap[bestK]--;\n            groups[bestK].push_back(c);\n        }\n\n        return groups;\n    };\n\n    int seedAttempts = 35;\n    if (M <= 30) seedAttempts = 70;\n    if (M >= 180) seedAttempts = 15;\n\n    for (int at = 0; at < seedAttempts && timer.sec() < 1.05; at++) {\n        addCandidate(buildSeedCluster(at));\n    }\n\n    vector<vector<int>> groups;\n    double bestScore = 1e100;\n\n    for (auto &cand : candidates) {\n        double sc = totalMSTCost(cand);\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = cand;\n        }\n    }\n\n    // Maintain city -> group and position.\n    vector<int> belong(N), posInGroup(N);\n    auto rebuildBelong = [&]() {\n        for (int k = 0; k < M; k++) {\n            for (int i = 0; i < (int)groups[k].size(); i++) {\n                belong[groups[k][i]] = k;\n                posInGroup[groups[k][i]] = i;\n            }\n        }\n    };\n    rebuildBelong();\n\n    vector<double> gCost(M);\n    for (int k = 0; k < M; k++) gCost[k] = mstCost(groups[k]);\n\n    // Stronger local improvement:\n    // Try swapping cities that are spatial nearest but currently in different groups.\n    for (int iter = 0; iter < 9000 && timer.sec() < 1.35; iter++) {\n        int aCity = rnd_int(0, N - 1);\n        int ga = belong[aCity];\n\n        int bCity = -1;\n        int scan = min(40, N - 1);\n        int offset = rnd_int(0, max(0, scan - 1));\n\n        for (int t = 0; t < scan; t++) {\n            int cand = nearest[aCity][(t + offset) % scan];\n            if (belong[cand] != ga) {\n                bCity = cand;\n                break;\n            }\n        }\n\n        if (bCity < 0) continue;\n\n        int gb = belong[bCity];\n        if (ga == gb) continue;\n\n        int ia = posInGroup[aCity];\n        int ib = posInGroup[bCity];\n\n        double old = gCost[ga] + gCost[gb];\n\n        swap(groups[ga][ia], groups[gb][ib]);\n\n        double na = mstCost(groups[ga]);\n        double nb = mstCost(groups[gb]);\n        double nw = na + nb;\n\n        if (nw + 1e-9 < old) {\n            gCost[ga] = na;\n            gCost[gb] = nb;\n\n            belong[aCity] = gb;\n            belong[bCity] = ga;\n            posInGroup[aCity] = ib;\n            posInGroup[bCity] = ia;\n        } else {\n            swap(groups[ga][ia], groups[gb][ib]);\n        }\n    }\n\n    // Sort inside groups by long axis.\n    for (int k = 0; k < M; k++) {\n        double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n        for (int p : groups[k]) {\n            minx = min(minx, x[p]);\n            maxx = max(maxx, x[p]);\n            miny = min(miny, y[p]);\n            maxy = max(maxy, y[p]);\n        }\n\n        bool sx = (maxx - minx) >= (maxy - miny);\n        sort(groups[k].begin(), groups[k].end(), [&](int a, int b) {\n            double va = sx ? x[a] : y[a];\n            double vb = sx ? x[b] : y[b];\n            if (va != vb) return va < vb;\n            return (sx ? y[a] : x[a]) < (sx ? y[b] : x[b]);\n        });\n    }\n\n    vector<vector<pair<int,int>>> queriedEdges(M);\n    int qcnt = 0;\n\n    auto query = [&](const vector<int>& c) -> vector<pair<int,int>> {\n        cout << \"? \" << c.size();\n        for (int v : c) cout << ' ' << v;\n        cout << endl;\n        cout.flush();\n\n        vector<pair<int,int>> ret;\n        for (int i = 0; i < (int)c.size() - 1; i++) {\n            int a, b;\n            cin >> a >> b;\n            if (a > b) swap(a, b);\n            ret.push_back({a, b});\n        }\n        return ret;\n    };\n\n    // Query exact MST for groups of size <= L.\n    vector<int> qorder(M);\n    iota(qorder.begin(), qorder.end(), 0);\n    sort(qorder.begin(), qorder.end(), [&](int a, int b) {\n        bool aa = (G[a] >= 2 && G[a] <= L);\n        bool bb = (G[b] >= 2 && G[b] <= L);\n        if (aa != bb) return aa > bb;\n        return G[a] < G[b];\n    });\n\n    vector<int> exact(M, 0);\n    for (int k : qorder) {\n        if (qcnt >= Q) break;\n        if (G[k] >= 2 && G[k] <= L) {\n            auto ret = query(groups[k]);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            exact[k] = 1;\n        }\n    }\n\n    vector<int> imp(M);\n    iota(imp.begin(), imp.end(), 0);\n    sort(imp.begin(), imp.end(), [&](int a, int b) {\n        double va = gCost[a] / max(1, G[a] - 1);\n        double vb = gCost[b] / max(1, G[b] - 1);\n        return va > vb;\n    });\n\n    // Query local nearest neighborhoods for important groups.\n    for (int k : imp) {\n        if (qcnt >= Q) break;\n        int s = groups[k].size();\n        if (s < 2 || exact[k]) continue;\n\n        int tq = 1;\n        if (s >= 120) tq = 10;\n        else if (s >= 80) tq = 8;\n        else if (s >= 50) tq = 5;\n        else if (s >= 25) tq = 3;\n        else if (s >= 10) tq = 2;\n\n        tq = min(tq, Q - qcnt);\n\n        for (int t = 0; t < tq && qcnt < Q; t++) {\n            int anchor = groups[k][(long long)t * (s - 1) / max(1, tq - 1)];\n\n            vector<pair<double,int>> nb;\n            nb.reserve(s);\n            for (int p : groups[k]) nb.push_back({dmat[anchor][p], p});\n            sort(nb.begin(), nb.end());\n\n            vector<int> c;\n            for (int i = 0; i < min(L, (int)nb.size()); i++) c.push_back(nb[i].second);\n\n            if ((int)c.size() >= 2) {\n                auto ret = query(c);\n                qcnt++;\n                queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            }\n        }\n    }\n\n    // Remaining queries: sliding windows.\n    for (int k : imp) {\n        if (qcnt >= Q) break;\n        if (exact[k]) continue;\n        int s = groups[k].size();\n        if (s < 2) continue;\n\n        int step = max(2, L - 1);\n        for (int st = 0; st < s && qcnt < Q; st += step) {\n            int en = min(s, st + L);\n            if (en - st < 2) break;\n\n            vector<int> c(groups[k].begin() + st, groups[k].begin() + en);\n            auto ret = query(c);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n\n            if (en == s) break;\n        }\n    }\n\n    vector<vector<pair<int,int>>> ansEdges(M);\n\n    auto ekey = [](int a, int b) -> long long {\n        if (a > b) swap(a, b);\n        return ((long long)a << 32) ^ (unsigned int)b;\n    };\n\n    for (int k = 0; k < M; k++) {\n        int s = groups[k].size();\n        if (s <= 1) continue;\n\n        unordered_set<long long> qset;\n        qset.reserve(queriedEdges[k].size() * 2 + 10);\n\n        for (auto [a, b] : queriedEdges[k]) qset.insert(ekey(a, b));\n\n        vector<Edge> edges;\n        edges.reserve(s * (s - 1) / 2);\n\n        for (int i = 0; i < s; i++) {\n            for (int j = i + 1; j < s; j++) {\n                int a = groups[k][i], b = groups[k][j];\n                long long w = idist[a][b];\n\n                // Queried MST edges are trusted but not forced.\n                if (qset.count(ekey(a, b))) w -= 400;\n\n                edges.push_back({a, b, w});\n            }\n        }\n\n        sort(edges.begin(), edges.end());\n\n        DSU dsu(N);\n        for (auto &e : edges) {\n            if ((int)ansEdges[k].size() == s - 1) break;\n            if (dsu.unite(e.u, e.v)) {\n                ansEdges[k].push_back({e.u, e.v});\n            }\n        }\n\n        // Safety fallback.\n        for (int i = 0; i + 1 < s && (int)ansEdges[k].size() < s - 1; i++) {\n            if (dsu.unite(groups[k][i], groups[k][i + 1])) {\n                ansEdges[k].push_back({groups[k][i], groups[k][i + 1]});\n            }\n        }\n    }\n\n    cout << \"!\" << '\\n';\n    for (int k = 0; k < M; k++) {\n        for (int i = 0; i < (int)groups[k].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[k][i];\n        }\n        cout << '\\n';\n\n        for (auto [a, b] : ansEdges[k]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Action {\n    char a, d;\n};\n\nstruct Prev {\n    int pi = -1;\n    int pj = -1;\n    Action act;\n};\n\nint N, M;\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'};\n\nbool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nint dir_id(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\npair<int,int> slide_dest(int i, int j, int dir, const vector<vector<int>>& block) {\n    while (true) {\n        int ni = i + di[dir];\n        int nj = j + dj[dir];\n\n        if (!inside(ni, nj)) break;\n        if (block[ni][nj]) break;\n\n        i = ni;\n        j = nj;\n    }\n\n    return {i, j};\n}\n\nvector<Action> bfs_path(\n    pair<int,int> start,\n    pair<int,int> goal,\n    const vector<vector<int>>& block\n) {\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<Prev>> prv(N, vector<Prev>(N));\n\n    queue<pair<int,int>> q;\n    dist[start.first][start.second] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        if (i == goal.first && j == goal.second) break;\n\n        for (int dir = 0; dir < 4; dir++) {\n            // Move\n            {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n\n                if (inside(ni, nj) && !block[ni][nj] && dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    prv[ni][nj] = {i, j, {'M', dc[dir]}};\n                    q.push({ni, nj});\n                }\n            }\n\n            // Slide\n            {\n                auto [ni, nj] = slide_dest(i, j, dir, block);\n\n                if ((ni != i || nj != j) && dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    prv[ni][nj] = {i, j, {'S', dc[dir]}};\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n\n    vector<Action> path;\n\n    if (dist[goal.first][goal.second] == -1) {\n        return path;\n    }\n\n    int ci = goal.first;\n    int cj = goal.second;\n\n    while (!(ci == start.first && cj == start.second)) {\n        Prev pr = prv[ci][cj];\n        path.push_back(pr.act);\n        ci = pr.pi;\n        cj = pr.pj;\n    }\n\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nbool apply_action(\n    pair<int,int>& pos,\n    vector<vector<int>>& block,\n    Action act\n) {\n    int dir = dir_id(act.d);\n\n    if (act.a == 'M') {\n        int ni = pos.first + di[dir];\n        int nj = pos.second + dj[dir];\n\n        if (!inside(ni, nj)) return false;\n        if (block[ni][nj]) return false;\n\n        pos = {ni, nj};\n        return true;\n    }\n\n    if (act.a == 'S') {\n        pos = slide_dest(pos.first, pos.second, dir, block);\n        return true;\n    }\n\n    if (act.a == 'A') {\n        int ni = pos.first + di[dir];\n        int nj = pos.second + dj[dir];\n\n        if (!inside(ni, nj)) return false;\n\n        block[ni][nj] ^= 1;\n        return true;\n    }\n\n    return false;\n}\n\nbool is_target_cell(const vector<pair<int,int>>& p, int i, int j) {\n    for (auto [x, y] : p) {\n        if (x == i && y == j) return true;\n    }\n    return false;\n}\n\nbool simulate_full(\n    const vector<pair<int,int>>& p,\n    const vector<Action>& ans\n) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    pair<int,int> pos = p[0];\n    int next_target = 1;\n\n    for (auto act : ans) {\n        if (!apply_action(pos, block, act)) {\n            return false;\n        }\n\n        if (next_target < M && pos == p[next_target]) {\n            next_target++;\n        }\n    }\n\n    return next_target == M;\n}\n\nvector<Action> baseline_solution(const vector<pair<int,int>>& p) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    vector<Action> ans;\n\n    pair<int,int> cur = p[0];\n\n    for (int t = 1; t < M; t++) {\n        auto path = bfs_path(cur, p[t], block);\n\n        for (auto a : path) {\n            ans.push_back(a);\n            apply_action(cur, block, a);\n        }\n    }\n\n    return ans;\n}\n\nvector<Action> construct_blocks(\n    pair<int,int>& cur,\n    vector<vector<int>>& block,\n    const vector<pair<int,int>>& wanted,\n    const vector<pair<int,int>>& p\n) {\n    vector<Action> res;\n\n    for (auto [bi, bj] : wanted) {\n        if (!inside(bi, bj)) continue;\n        if (block[bi][bj]) continue;\n        if (is_target_cell(p, bi, bj)) continue;\n\n        vector<Action> best;\n        bool found = false;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int si = bi - di[dir];\n            int sj = bj - dj[dir];\n\n            if (!inside(si, sj)) continue;\n            if (block[si][sj]) continue;\n\n            auto path = bfs_path(cur, {si, sj}, block);\n\n            if (path.empty() && cur != make_pair(si, sj)) continue;\n\n            vector<Action> cand = path;\n            cand.push_back({'A', dc[dir]});\n\n            if (!found || cand.size() < best.size()) {\n                found = true;\n                best = cand;\n            }\n        }\n\n        if (!found) continue;\n\n        for (auto a : best) {\n            res.push_back(a);\n            bool ok = apply_action(cur, block, a);\n            if (!ok) return {};\n        }\n    }\n\n    return res;\n}\n\nvector<Action> solve_with_initial_blocks(\n    const vector<pair<int,int>>& p,\n    const vector<pair<int,int>>& wanted_blocks\n) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    pair<int,int> cur = p[0];\n\n    vector<Action> ans;\n\n    auto build = construct_blocks(cur, block, wanted_blocks, p);\n    ans.insert(ans.end(), build.begin(), build.end());\n\n    for (int t = 1; t < M; t++) {\n        auto goal = p[t];\n\n        if (block[goal.first][goal.second]) {\n            return {};\n        }\n\n        auto path = bfs_path(cur, goal, block);\n\n        if (path.empty() && cur != goal) {\n            return {};\n        }\n\n        for (auto a : path) {\n            ans.push_back(a);\n            bool ok = apply_action(cur, block, a);\n            if (!ok) return {};\n        }\n    }\n\n    return ans;\n}\n\nvector<pair<int,int>> unique_cells(vector<pair<int,int>> v) {\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    vector<pair<int,int>> p(M);\n    for (int i = 0; i < M; i++) {\n        cin >> p[i].first >> p[i].second;\n    }\n\n    vector<Action> best = baseline_solution(p);\n\n    vector<vector<pair<int,int>>> candidates;\n\n    candidates.push_back({});\n\n    // Small sparse lattices.\n    for (int step : {5, 6, 7}) {\n        for (int oi = 1; oi < step; oi++) {\n            for (int oj = 1; oj < step; oj++) {\n                vector<pair<int,int>> cells;\n\n                for (int i = oi; i < N; i += step) {\n                    for (int j = oj; j < N; j += step) {\n                        cells.push_back({i, j});\n                    }\n                }\n\n                cells = unique_cells(cells);\n\n                if ((int)cells.size() <= 10) {\n                    candidates.push_back(cells);\n                }\n            }\n        }\n    }\n\n    // Candidate stoppers near future targets, but limited.\n    {\n        map<pair<int,int>, int> score;\n\n        for (int t = 1; t < M; t++) {\n            int i = p[t].first;\n            int j = p[t].second;\n\n            for (int dir = 0; dir < 4; dir++) {\n                int bi = i + di[dir];\n                int bj = j + dj[dir];\n\n                if (!inside(bi, bj)) continue;\n                if (is_target_cell(p, bi, bj)) continue;\n\n                score[{bi, bj}]++;\n            }\n        }\n\n        vector<pair<int,pair<int,int>>> ord;\n\n        for (auto [cell, sc] : score) {\n            ord.push_back({-sc, cell});\n        }\n\n        sort(ord.begin(), ord.end());\n\n        for (int lim : {4, 6, 8, 10}) {\n            vector<pair<int,int>> cells;\n\n            for (int k = 0; k < (int)ord.size() && k < lim; k++) {\n                cells.push_back(ord[k].second);\n            }\n\n            candidates.push_back(unique_cells(cells));\n        }\n    }\n\n    for (auto cells : candidates) {\n        auto ans = solve_with_initial_blocks(p, cells);\n\n        if (ans.empty()) continue;\n        if ((int)ans.size() > 2 * N * M) continue;\n        if (!simulate_full(p, ans)) continue;\n\n        if (ans.size() < best.size()) {\n            best = ans;\n        }\n    }\n\n    // Final safety check. If anything went wrong, return baseline.\n    if ((int)best.size() > 2 * N * M || !simulate_full(p, best)) {\n        best = baseline_solution(p);\n    }\n\n    for (auto [a, d] : best) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Input {\n    int n;\n    vector<int> x, y;\n    vector<long long> r;\n};\n\nstatic constexpr int W = 10000;\nstatic constexpr double TIME_LIMIT = 4.82;\n\nchrono::steady_clock::time_point start_time;\n\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nlong long area(const Rect& e) {\n    return 1LL * (e.c - e.a) * (e.d - e.b);\n}\n\nint width(const Rect& r) {\n    return r.c - r.a;\n}\n\nint height(const Rect& r) {\n    return r.d - r.b;\n}\n\nbool overlap_interval(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nbool overlap_rect(const Rect& p, const Rect& q) {\n    return overlap_interval(p.a, p.c, q.a, q.c)\n        && overlap_interval(p.b, p.d, q.b, q.d);\n}\n\ndouble rect_score(long long s, long long r) {\n    double mn = (double)min(s, r);\n    double mx = (double)max(s, r);\n    double q = mn / mx;\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble total_score(const vector<Rect>& rects, const Input& in) {\n    double res = 0;\n    for (int i = 0; i < in.n; i++) {\n        res += rect_score(area(rects[i]), in.r[i]);\n    }\n    return res;\n}\n\nbool valid_rect_for_point(const Rect& r, int x, int y) {\n    return r.a <= x && x < r.c && r.b <= y && y < r.d && r.a < r.c && r.b < r.d;\n}\n\nbool validate_solution(const vector<Rect>& rects, const Input& in) {\n    int n = in.n;\n    if ((int)rects.size() != n) return false;\n\n    for (int i = 0; i < n; i++) {\n        const Rect& r = rects[i];\n\n        if (r.a < 0 || r.b < 0 || r.c > W || r.d > W) return false;\n        if (r.a >= r.c || r.b >= r.d) return false;\n        if (!valid_rect_for_point(r, in.x[i], in.y[i])) return false;\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            if (overlap_rect(rects[i], rects[j])) return false;\n        }\n    }\n\n    return true;\n}\n\nint max_expand_dir(const vector<Rect>& rects, int idx, int dir) {\n    const Rect& cur = rects[idx];\n    int n = rects.size();\n\n    if (dir == 0) {\n        int lim = cur.a;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.c <= cur.a) {\n                lim = min(lim, cur.a - o.c);\n            }\n        }\n        return lim;\n    } else if (dir == 1) {\n        int lim = W - cur.c;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.a >= cur.c) {\n                lim = min(lim, o.a - cur.c);\n            }\n        }\n        return lim;\n    } else if (dir == 2) {\n        int lim = cur.b;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.d <= cur.b) {\n                lim = min(lim, cur.b - o.d);\n            }\n        }\n        return lim;\n    } else {\n        int lim = W - cur.d;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.b >= cur.d) {\n                lim = min(lim, o.b - cur.d);\n            }\n        }\n        return lim;\n    }\n}\n\nRect expanded(Rect r, int dir, int delta) {\n    if (dir == 0) r.a -= delta;\n    else if (dir == 1) r.c += delta;\n    else if (dir == 2) r.b -= delta;\n    else r.d += delta;\n    return r;\n}\n\nRect shrunk(Rect r, int dir, int delta) {\n    if (dir == 0) r.a += delta;\n    else if (dir == 1) r.c -= delta;\n    else if (dir == 2) r.b += delta;\n    else r.d -= delta;\n    return r;\n}\n\nvector<int> candidate_deltas(int mx, long long cur_area, long long target, int len) {\n    vector<int> cand;\n    if (mx <= 0) return cand;\n\n    cand.push_back(1);\n    cand.push_back(mx);\n\n    long long need = target - cur_area;\n\n    if (need != 0) {\n        long long ab = llabs(need);\n        long long f = ab / len;\n        long long c = (ab + len - 1) / len;\n\n        for (long long v : {f - 2, f - 1, f, f + 1, f + 2,\n                            c - 2, c - 1, c, c + 1, c + 2}) {\n            if (1 <= v && v <= mx) cand.push_back((int)v);\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    return cand;\n}\n\nvoid greedy_expand(vector<Rect>& rects, const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int stagnate = 0;\n\n    while (elapsed() < TIME_LIMIT && stagnate < 35) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-15;\n\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1) ? height(rects[id]) : width(rects[id]);\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    gain += 1e-13 * delta;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_dir != -1) {\n                rects[id] = expanded(rects[id], best_dir, best_delta);\n                changed = true;\n            }\n        }\n\n        if (changed) stagnate = 0;\n        else stagnate++;\n    }\n}\n\nvoid local_refine(vector<Rect>& rects, const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int loop = 0;\n\n    while (elapsed() < TIME_LIMIT && loop < 250) {\n        loop++;\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_type = -1;\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-14;\n\n            // Expansion\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1) ? height(rects[id]) : width(rects[id]);\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 0;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            // Shrink\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = 0;\n\n                if (dir == 0) {\n                    mx = in.x[id] - rects[id].a;\n                } else if (dir == 1) {\n                    mx = rects[id].c - (in.x[id] + 1);\n                } else if (dir == 2) {\n                    mx = in.y[id] - rects[id].b;\n                } else {\n                    mx = rects[id].d - (in.y[id] + 1);\n                }\n\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1) ? height(rects[id]) : width(rects[id]);\n\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = shrunk(rects[id], dir, delta);\n                    if (!valid_rect_for_point(nr, in.x[id], in.y[id])) continue;\n\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 1;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_type != -1) {\n                if (best_type == 0) {\n                    rects[id] = expanded(rects[id], best_dir, best_delta);\n                } else {\n                    rects[id] = shrunk(rects[id], best_dir, best_delta);\n                }\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n}\n\nvector<Rect> solve_once(const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<Rect> rects(n);\n\n    for (int i = 0; i < n; i++) {\n        rects[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n    }\n\n    greedy_expand(rects, in, rng);\n    local_refine(rects, in, rng);\n\n    return rects;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    Input in;\n    cin >> in.n;\n    in.x.resize(in.n);\n    in.y.resize(in.n);\n    in.r.resize(in.n);\n\n    for (int i = 0; i < in.n; i++) {\n        cin >> in.x[i] >> in.y[i] >> in.r[i];\n    }\n\n    mt19937 rng(1234567);\n\n    vector<Rect> best;\n    double best_score = -1.0;\n\n    while (elapsed() < TIME_LIMIT) {\n        auto rects = solve_once(in, rng);\n\n        if (!validate_solution(rects, in)) {\n            continue;\n        }\n\n        double sc = total_score(rects, in);\n\n        if (sc > best_score) {\n            best_score = sc;\n            best = rects;\n        }\n    }\n\n    if (best.empty()) {\n        best.resize(in.n);\n        for (int i = 0; i < in.n; i++) {\n            best[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n        }\n    }\n\n    if (!validate_solution(best, in)) {\n        for (int i = 0; i < in.n; i++) {\n            best[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n        }\n    }\n\n    for (int i = 0; i < in.n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' '\n             << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr double TIME_LIMIT = 1.93;\n\nint si, sj;\nint tile_id[N][N];\nint pval[N][N];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\ninline bool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() {\n        st = chrono::high_resolution_clock::now();\n    }\n    double elapsed() const {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline int next_int(int n) {\n        return (int)(next() % n);\n    }\n};\n\nstruct Candidate {\n    int dir;\n    int ni, nj;\n    int eval;\n};\n\nstruct Params {\n    int w_score;\n    int w_deg;\n    int w_near;\n    int w_best2;\n    int w_sum2;\n    int w_best3;\n    int noise;\n    int deg1_penalty;\n    int dead_penalty;\n    int random_pick_rate;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tile = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> tile_id[i][j];\n            max_tile = max(max_tile, tile_id[i][j]);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> pval[i][j];\n        }\n    }\n\n    int M = max_tile + 1;\n\n    vector<Params> params = {\n        {100, 18, 3, 35, 1, 12, 150, 250, 2500, 17},\n        {120, 12, 2, 25, 1, 10, 220, 150, 2200, 20},\n        { 90, 45, 4, 30, 1, 10, 120, 400, 3000, 14},\n        {105,-20, 3, 20, 1,  8, 150,   0, 2000, 18},\n        {135,  5, 2, 15, 0,  5, 280,  80, 1800, 24},\n        { 95, 30, 7, 35, 1, 12, 180, 250, 2600, 18},\n        {110, 25, 1, 45, 0, 15, 170, 250, 2600, 16},\n        {100, 60, 2, 20, 0,  8, 100, 500, 3500, 12},\n        {150,  0, 1, 10, 0,  3, 350,  50, 1500, 28},\n        { 80, 70, 5, 25, 1,  8, 100, 600, 3800, 10},\n        {115,-35, 3, 25, 0,  7, 160,-100, 1700, 18},\n        {105, 20, 5, 40, 1, 14, 260, 200, 2400, 22},\n\n        // Additional variants\n        {125, 18, 4, 32, 1, 12, 200, 200, 2300, 20},\n        { 85, 80, 3, 18, 0,  6,  80, 700, 4200,  8},\n        {160,-10, 1,  8, 0,  2, 400,   0, 1200, 30},\n        {100,-55, 2, 35, 0, 10, 180,-150, 1600, 20},\n        {115, 35, 6, 30, 1, 10, 150, 350, 3000, 15},\n        {130,  8, 5, 25, 1,  8, 250, 150, 2100, 24},\n        { 95, 55, 1, 40, 0, 16, 130, 450, 3300, 13},\n        {140, 15, 0, 20, 0,  6, 320, 100, 1800, 26}\n    };\n\n    Timer timer;\n    XorShift rng;\n\n    vector<unsigned char> visited(M, 0);\n\n    string best_path;\n    int best_score = pval[si][sj];\n\n    int iter = 0;\n\n    while (timer.elapsed() < TIME_LIMIT) {\n        iter++;\n\n        fill(visited.begin(), visited.end(), 0);\n\n        int ci = si;\n        int cj = sj;\n        int score = pval[ci][cj];\n\n        visited[tile_id[ci][cj]] = 1;\n\n        string path;\n        path.reserve(2500);\n\n        const Params& par = params[(iter + rng.next_int((int)params.size())) % params.size()];\n\n        while (true) {\n            Candidate cand[4];\n            int cn = 0;\n\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n\n                if (!inside(ni, nj)) continue;\n\n                int tid = tile_id[ni][nj];\n                if (visited[tid]) continue;\n\n                visited[tid] = 1;\n\n                int deg = 0;\n                int near_score = 0;\n                int best2 = 0;\n                int sum2 = 0;\n                int best3 = 0;\n\n                for (int e = 0; e < 4; e++) {\n                    int xi = ni + di[e];\n                    int xj = nj + dj[e];\n\n                    if (!inside(xi, xj)) continue;\n\n                    int nt = tile_id[xi][xj];\n                    if (visited[nt]) continue;\n\n                    deg++;\n                    near_score += pval[xi][xj];\n\n                    visited[nt] = 1;\n\n                    int local_best2 = 0;\n                    int local_best3 = 0;\n\n                    for (int f = 0; f < 4; f++) {\n                        int yi = xi + di[f];\n                        int yj = xj + dj[f];\n\n                        if (!inside(yi, yj)) continue;\n\n                        int yt = tile_id[yi][yj];\n                        if (visited[yt]) continue;\n\n                        local_best2 = max(local_best2, pval[yi][yj]);\n\n                        visited[yt] = 1;\n\n                        int local3 = 0;\n                        for (int g = 0; g < 4; g++) {\n                            int zi = yi + di[g];\n                            int zj = yj + dj[g];\n\n                            if (!inside(zi, zj)) continue;\n\n                            int zt = tile_id[zi][zj];\n                            if (visited[zt]) continue;\n\n                            local3 = max(local3, pval[zi][zj]);\n                        }\n\n                        visited[yt] = 0;\n\n                        local_best3 = max(local_best3, pval[yi][yj] + local3);\n                    }\n\n                    visited[nt] = 0;\n\n                    best2 = max(best2, pval[xi][xj] + local_best2);\n                    best3 = max(best3, pval[xi][xj] + local_best3);\n                    sum2 += pval[xi][xj];\n                }\n\n                visited[tid] = 0;\n\n                int eval = 0;\n                eval += par.w_score * pval[ni][nj];\n                eval += par.w_deg * deg;\n                eval += par.w_near * near_score;\n                eval += par.w_best2 * best2;\n                eval += par.w_sum2 * sum2;\n                eval += par.w_best3 * best3;\n                eval += rng.next_int(par.noise + 1);\n\n                if (deg == 0) eval -= par.dead_penalty;\n                else if (deg == 1) eval -= par.deg1_penalty;\n\n                cand[cn++] = {d, ni, nj, eval};\n            }\n\n            if (cn == 0) break;\n\n            sort(cand, cand + cn, [](const Candidate& a, const Candidate& b) {\n                return a.eval > b.eval;\n            });\n\n            int choose = 0;\n            int r = rng.next_int(100);\n\n            if (r < par.random_pick_rate) {\n                if (cn >= 4 && rng.next_int(100) < 8) {\n                    choose = 3;\n                } else if (cn >= 3 && rng.next_int(100) < 25) {\n                    choose = 2;\n                } else if (cn >= 2) {\n                    choose = 1;\n                }\n            }\n\n            Candidate c = cand[choose];\n\n            path.push_back(dc[c.dir]);\n            ci = c.ni;\n            cj = c.nj;\n\n            visited[tile_id[ci][cj]] = 1;\n            score += pval[ci][cj];\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n        }\n    }\n\n    cout << best_path << '\\n';\n\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int Q = 1000;\n\nstruct UsedEdge {\n    int type; // 0: horizontal, 1: vertical\n    int a, b;\n};\n\ndouble h_edge[N][N - 1];\ndouble v_edge[N - 1][N];\nint h_cnt[N][N - 1];\nint v_cnt[N - 1][N];\n\ndouble row_cost[N]; // horizontal cost by row\ndouble col_cost[N]; // vertical cost by column\n\nvector<UsedEdge> prev_edges;\n\nmt19937 rng(1234567);\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos(int x) {\n    return {x / N, x % N};\n}\n\ndouble clamp_cost(double x) {\n    return max(100.0, min(10000.0, x));\n}\n\ndouble get_h_cost(int i, int j, int turn) {\n    double coarse = row_cost[i];\n    double local = h_edge[i][j];\n\n    double local_w = min(0.45, h_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\ndouble get_v_cost(int i, int j, int turn) {\n    double coarse = col_cost[j];\n    double local = v_edge[i][j];\n\n    double local_w = min(0.45, v_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\ndouble coarse_h_cost(int i, int j, int turn) {\n    double local_w = min(0.20, h_cnt[i][j] / 20.0);\n    if (turn < 300) local_w *= 0.5;\n    return clamp_cost((1.0 - local_w) * row_cost[i] + local_w * h_edge[i][j]);\n}\n\ndouble coarse_v_cost(int i, int j, int turn) {\n    double local_w = min(0.20, v_cnt[i][j] / 20.0);\n    if (turn < 300) local_w *= 0.5;\n    return clamp_cost((1.0 - local_w) * col_cost[j] + local_w * v_edge[i][j]);\n}\n\nvector<UsedEdge> path_edges(int si, int sj, const string& path) {\n    vector<UsedEdge> edges;\n    int i = si, j = sj;\n\n    for (char c : path) {\n        if (c == 'U') {\n            edges.push_back({1, i - 1, j});\n            --i;\n        } else if (c == 'D') {\n            edges.push_back({1, i, j});\n            ++i;\n        } else if (c == 'L') {\n            edges.push_back({0, i, j - 1});\n            --j;\n        } else if (c == 'R') {\n            edges.push_back({0, i, j});\n            ++j;\n        }\n    }\n\n    return edges;\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool vertical_first) {\n    string s;\n\n    if (vertical_first) {\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n    } else {\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n    }\n\n    return s;\n}\n\nstring randomized_manhattan(int si, int sj, int ti, int tj) {\n    string s;\n    int i = si, j = sj;\n\n    while (i != ti || j != tj) {\n        vector<char> cand;\n        if (i < ti) cand.push_back('D');\n        if (i > ti) cand.push_back('U');\n        if (j < tj) cand.push_back('R');\n        if (j > tj) cand.push_back('L');\n\n        char c = cand[rng() % cand.size()];\n        s.push_back(c);\n\n        if (c == 'D') ++i;\n        else if (c == 'U') --i;\n        else if (c == 'R') ++j;\n        else --j;\n    }\n\n    return s;\n}\n\nstring monotone_dp_path(int si, int sj, int ti, int tj, int turn) {\n    int di = (ti >= si ? 1 : -1);\n    int dj = (tj >= sj ? 1 : -1);\n\n    int H = abs(ti - si);\n    int W = abs(tj - sj);\n\n    vector<vector<double>> dp(H + 1, vector<double>(W + 1, 1e100));\n    vector<vector<char>> par(H + 1, vector<char>(W + 1, '?'));\n\n    dp[0][0] = 0.0;\n\n    for (int a = 0; a <= H; a++) {\n        for (int b = 0; b <= W; b++) {\n            int i = si + di * a;\n            int j = sj + dj * b;\n\n            if (a < H) {\n                int ni = i + di;\n                double w;\n                char c;\n                if (di == 1) {\n                    w = coarse_v_cost(i, j, turn);\n                    c = 'D';\n                } else {\n                    w = coarse_v_cost(i - 1, j, turn);\n                    c = 'U';\n                }\n\n                if (dp[a + 1][b] > dp[a][b] + w) {\n                    dp[a + 1][b] = dp[a][b] + w;\n                    par[a + 1][b] = c;\n                }\n            }\n\n            if (b < W) {\n                int nj = j + dj;\n                double w;\n                char c;\n                if (dj == 1) {\n                    w = coarse_h_cost(i, j, turn);\n                    c = 'R';\n                } else {\n                    w = coarse_h_cost(i, j - 1, turn);\n                    c = 'L';\n                }\n\n                if (dp[a][b + 1] > dp[a][b] + w) {\n                    dp[a][b + 1] = dp[a][b] + w;\n                    par[a][b + 1] = c;\n                }\n            }\n        }\n    }\n\n    string res;\n    int a = H, b = W;\n    while (a > 0 || b > 0) {\n        char c = par[a][b];\n        res.push_back(c);\n\n        if (c == 'D' || c == 'U') {\n            a--;\n        } else {\n            b--;\n        }\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    vector<double> dist(V, 1e100);\n    vector<int> par(V, -1);\n    vector<char> pch(V, '?');\n\n    priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n\n    int S = id(si, sj);\n    int T = id(ti, tj);\n\n    dist[S] = 0.0;\n    pq.push({0.0, S});\n\n    while (!pq.empty()) {\n        auto [d, x] = pq.top();\n        pq.pop();\n\n        if (d != dist[x]) continue;\n        if (x == T) break;\n\n        auto [i, j] = pos(x);\n\n        auto relax = [&](int ni, int nj, double w, char c) {\n            int y = id(ni, nj);\n            if (dist[y] > d + w) {\n                dist[y] = d + w;\n                par[y] = x;\n                pch[y] = c;\n                pq.push({dist[y], y});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, get_v_cost(i - 1, j, turn), 'U');\n        if (i + 1 < N) relax(i + 1, j, get_v_cost(i, j, turn), 'D');\n        if (j > 0) relax(i, j - 1, get_h_cost(i, j - 1, turn), 'L');\n        if (j + 1 < N) relax(i, j + 1, get_h_cost(i, j, turn), 'R');\n    }\n\n    string res;\n    int cur = T;\n    while (cur != S) {\n        if (cur < 0 || pch[cur] == '?') {\n            return manhattan_path(si, sj, ti, tj, true);\n        }\n\n        res.push_back(pch[cur]);\n        cur = par[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nbool valid_simple_path(int si, int sj, int ti, int tj, const string& s) {\n    bool seen[N][N] = {};\n    int i = si, j = sj;\n    seen[i][j] = true;\n\n    for (char c : s) {\n        if (c == 'U') --i;\n        else if (c == 'D') ++i;\n        else if (c == 'L') --j;\n        else if (c == 'R') ++j;\n        else return false;\n\n        if (i < 0 || i >= N || j < 0 || j >= N) return false;\n        if (seen[i][j]) return false;\n        seen[i][j] = true;\n    }\n\n    return i == ti && j == tj;\n}\n\nvoid update_from_result(int measured, int turn) {\n    if (prev_edges.empty()) return;\n\n    int row_use[N] = {};\n    int col_use[N] = {};\n\n    double pred_coarse = 0.0;\n    double pred_edge = 0.0;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            row_use[e.a]++;\n            pred_coarse += row_cost[e.a];\n            pred_edge += h_edge[e.a][e.b];\n        } else {\n            col_use[e.b]++;\n            pred_coarse += col_cost[e.b];\n            pred_edge += v_edge[e.a][e.b];\n        }\n    }\n\n    double pred = 0.75 * pred_coarse + 0.25 * pred_edge;\n    if (pred <= 1.0) return;\n\n    double ratio = measured / pred;\n    ratio = max(0.75, min(1.25, ratio));\n    double target = pred * ratio;\n    double err = target - pred;\n\n    // Coarse 60-parameter online regression.\n    double norm = 1e-9;\n    for (int i = 0; i < N; i++) norm += row_use[i] * row_use[i];\n    for (int j = 0; j < N; j++) norm += col_use[j] * col_use[j];\n\n    double lr = 0.55;\n    if (turn > 100) lr = 0.42;\n    if (turn > 300) lr = 0.32;\n    if (turn > 600) lr = 0.24;\n\n    for (int i = 0; i < N; i++) {\n        if (row_use[i]) {\n            row_cost[i] += lr * err * row_use[i] / norm;\n            row_cost[i] = clamp_cost(row_cost[i]);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        if (col_use[j]) {\n            col_cost[j] += lr * err * col_use[j] / norm;\n            col_cost[j] = clamp_cost(col_cost[j]);\n        }\n    }\n\n    // Local edge correction.\n    double edge_norm = max(1, (int)prev_edges.size());\n    double edge_lr = 0.20;\n    if (turn > 200) edge_lr = 0.16;\n    if (turn > 600) edge_lr = 0.11;\n\n    double per_edge_delta = edge_lr * err / edge_norm;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            int i = e.a, j = e.b;\n            h_edge[i][j] += per_edge_delta;\n            h_edge[i][j] = clamp_cost(h_edge[i][j]);\n            h_cnt[i][j]++;\n\n            h_edge[i][j] = 0.985 * h_edge[i][j] + 0.015 * row_cost[i];\n        } else {\n            int i = e.a, j = e.b;\n            v_edge[i][j] += per_edge_delta;\n            v_edge[i][j] = clamp_cost(v_edge[i][j]);\n            v_cnt[i][j]++;\n\n            v_edge[i][j] = 0.985 * v_edge[i][j] + 0.015 * col_cost[j];\n        }\n    }\n}\n\nstring choose_path(int si, int sj, int ti, int tj, int turn) {\n    // Initial exploration.\n    if (turn < 20) {\n        if (turn % 3 == 0) return manhattan_path(si, sj, ti, tj, true);\n        if (turn % 3 == 1) return manhattan_path(si, sj, ti, tj, false);\n        return randomized_manhattan(si, sj, ti, tj);\n    }\n\n    // In early-mid phase, monotone DP is safer than full Dijkstra with noisy estimates.\n    if (turn < 90) {\n        return monotone_dp_path(si, sj, ti, tj, turn);\n    }\n\n    string best = dijkstra_path(si, sj, ti, tj, turn);\n\n    // Occasional monotone exploration.\n    if (turn < 260 && turn % 17 == 0) {\n        string alt = monotone_dp_path(si, sj, ti, tj, turn);\n        if ((int)alt.size() <= (int)best.size() + 4) best = alt;\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; i++) {\n        row_cost[i] = 5000.0;\n        for (int j = 0; j < N - 1; j++) {\n            h_edge[i][j] = 5000.0;\n            h_cnt[i][j] = 0;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        col_cost[j] = 5000.0;\n    }\n\n    for (int i = 0; i < N - 1; i++) {\n        for (int j = 0; j < N; j++) {\n            v_edge[i][j] = 5000.0;\n            v_cnt[i][j] = 0;\n        }\n    }\n\n    int measured = -1;\n\n    for (int turn = 0; turn < Q; turn++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        if (turn > 0) {\n            update_from_result(measured, turn);\n        }\n\n        string ans = choose_path(si, sj, ti, tj, turn);\n\n        if (!valid_simple_path(si, sj, ti, tj, ans)) {\n            ans = manhattan_path(si, sj, ti, tj, true);\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        prev_edges = path_edges(si, sj, ans);\n\n        cin >> measured;\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int MAXM = 800;\nstatic const string ALPHA = \"ABCDEFGH\";\n\nint M;\nvector<string> S;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nbool cyclic_contains(const string& line, const string& pat) {\n    int L = (int)line.size();\n    int K = (int)pat.size();\n\n    for (int st = 0; st < L; ++st) {\n        bool ok = true;\n        for (int p = 0; p < K; ++p) {\n            if (line[(st + p) % L] != pat[p]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n\n    return false;\n}\n\nint overlap_suffix_prefix(const string& a, const string& b) {\n    int la = (int)a.size();\n    int lb = (int)b.size();\n    int lim = min(la, lb);\n\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[la - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n\n    return 0;\n}\n\nstring canonical_rotation(const string& s) {\n    string best = s;\n    for (int sh = 1; sh < (int)s.size(); ++sh) {\n        string t = s.substr(sh) + s.substr(0, sh);\n        if (t < best) best = t;\n    }\n    return best;\n}\n\nstruct Cand {\n    string line;\n    bitset<MAXM> cover;\n    int cnt;\n};\n\nbitset<MAXM> calc_cover(const string& line) {\n    bitset<MAXM> bs;\n    for (int i = 0; i < M; ++i) {\n        if (cyclic_contains(line, S[i])) bs.set(i);\n    }\n    return bs;\n}\n\nint gain_count(const bitset<MAXM>& cover, const bitset<MAXM>& used) {\n    return (int)(cover & (~used)).count();\n}\n\nstring extend_to_20(string t, mt19937& rng, char fillChar) {\n    while ((int)t.size() < N) {\n        if ((rng() % 100) < 75) t += fillChar;\n        else t += ALPHA[rng() % 8];\n    }\n\n    if ((int)t.size() > N) t.resize(N);\n    return t;\n}\n\nvoid add_candidate(\n    vector<Cand>& cands,\n    unordered_set<string>& seen,\n    string t,\n    mt19937& rng,\n    char fillChar\n) {\n    if ((int)t.size() < N) t = extend_to_20(t, rng, fillChar);\n    if ((int)t.size() > N) return;\n\n    string can = canonical_rotation(t);\n    if (!seen.insert(can).second) return;\n\n    bitset<MAXM> cov = calc_cover(t);\n    int cnt = (int)cov.count();\n\n    if (cnt > 0) {\n        cands.push_back({t, cov, cnt});\n    }\n}\n\nvector<Cand> generate_candidates(mt19937& rng, Timer& timer) {\n    vector<int> freq(8, 0);\n    for (const string& s : S) {\n        for (char c : s) freq[c - 'A']++;\n    }\n\n    int bestCharId = max_element(freq.begin(), freq.end()) - freq.begin();\n    char fillChar = ALPHA[bestCharId];\n\n    vector<Cand> cands;\n    unordered_set<string> seen;\n    seen.reserve(12000);\n\n    for (const string& s : S) {\n        add_candidate(cands, seen, s, rng, fillChar);\n    }\n\n    int trials = 0;\n\n    while (timer.elapsed() < 0.95 && trials < 6500) {\n        trials++;\n\n        string cur = S[rng() % M];\n\n        for (int step = 0; step < 8; ++step) {\n            int bestId = -1;\n            int bestOv = -1;\n            string bestMerge;\n\n            for (int rep = 0; rep < 35; ++rep) {\n                int id = rng() % M;\n                const string& b = S[id];\n\n                if (cur.find(b) != string::npos) {\n                    bestId = id;\n                    bestOv = 1000;\n                    bestMerge = cur;\n                    break;\n                }\n\n                int ov1 = overlap_suffix_prefix(cur, b);\n                int len1 = (int)cur.size() + (int)b.size() - ov1;\n\n                if (len1 <= N && ov1 > bestOv) {\n                    bestOv = ov1;\n                    bestId = id;\n                    bestMerge = cur + b.substr(ov1);\n                }\n\n                int ov2 = overlap_suffix_prefix(b, cur);\n                int len2 = (int)cur.size() + (int)b.size() - ov2;\n\n                if (len2 <= N && ov2 > bestOv) {\n                    bestOv = ov2;\n                    bestId = id;\n                    bestMerge = b + cur.substr(ov2);\n                }\n            }\n\n            if (bestId == -1 || bestOv < 2) break;\n\n            cur = bestMerge;\n            add_candidate(cands, seen, cur, rng, fillChar);\n        }\n\n        add_candidate(cands, seen, cur, rng, fillChar);\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n        if (a.cnt != b.cnt) return a.cnt > b.cnt;\n        return a.line < b.line;\n    });\n\n    if ((int)cands.size() > 1800) cands.resize(1800);\n    return cands;\n}\n\nvector<string> greedy_select_rows(const vector<Cand>& cands, mt19937& rng, bitset<MAXM>& usedOut) {\n    bitset<MAXM> used;\n    vector<string> rows;\n\n    for (int step = 0; step < N; ++step) {\n        int best = -1;\n        int bestGain = -1;\n\n        for (int i = 0; i < (int)cands.size(); ++i) {\n            int gain = gain_count(cands[i].cover, used);\n            if (gain > bestGain) {\n                bestGain = gain;\n                best = i;\n            }\n        }\n\n        if (best == -1 || bestGain <= 0) break;\n\n        rows.push_back(cands[best].line);\n        used |= cands[best].cover;\n    }\n\n    while ((int)rows.size() < N) {\n        rows.push_back(string(N, ALPHA[rng() % 8]));\n    }\n\n    usedOut = used;\n    return rows;\n}\n\nvector<string> local_replace_rows(\n    vector<string> rows,\n    const vector<Cand>& cands,\n    Timer& timer\n) {\n    vector<bitset<MAXM>> rowCov(N);\n\n    for (int i = 0; i < N; ++i) rowCov[i] = calc_cover(rows[i]);\n\n    bitset<MAXM> used;\n    for (int i = 0; i < N; ++i) used |= rowCov[i];\n\n    int curScore = (int)used.count();\n    int candLim = min((int)cands.size(), 1000);\n\n    bool improved = true;\n\n    while (improved && timer.elapsed() < 2.42) {\n        improved = false;\n\n        for (int r = 0; r < N && timer.elapsed() < 2.42; ++r) {\n            bitset<MAXM> without;\n            for (int i = 0; i < N; ++i) {\n                if (i != r) without |= rowCov[i];\n            }\n\n            int bestScore = curScore;\n            int bestCand = -1;\n\n            for (int ci = 0; ci < candLim; ++ci) {\n                bitset<MAXM> tmp = without | cands[ci].cover;\n                int sc = (int)tmp.count();\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestCand = ci;\n                }\n            }\n\n            if (bestCand != -1) {\n                rows[r] = cands[bestCand].line;\n                rowCov[r] = cands[bestCand].cover;\n                used = without | rowCov[r];\n                curScore = bestScore;\n                improved = true;\n            }\n        }\n    }\n\n    return rows;\n}\n\nvector<string> local_replace_two_rows(\n    vector<string> rows,\n    const vector<Cand>& cands,\n    Timer& timer\n) {\n    vector<bitset<MAXM>> rowCov(N);\n    for (int i = 0; i < N; ++i) rowCov[i] = calc_cover(rows[i]);\n\n    bitset<MAXM> used;\n    for (int i = 0; i < N; ++i) used |= rowCov[i];\n    int curScore = (int)used.count();\n\n    int candLim = min((int)cands.size(), 650);\n\n    bool improved = true;\n\n    while (improved && timer.elapsed() < 2.52) {\n        improved = false;\n\n        for (int r1 = 0; r1 < N && timer.elapsed() < 2.52; ++r1) {\n            for (int r2 = r1 + 1; r2 < N && timer.elapsed() < 2.52; ++r2) {\n                bitset<MAXM> base;\n                for (int i = 0; i < N; ++i) {\n                    if (i != r1 && i != r2) base |= rowCov[i];\n                }\n\n                int bestA = -1;\n                int bestB = -1;\n                int bestScore = curScore;\n\n                // Greedy two-candidate replacement:\n                int firstBest = -1;\n                int firstBestScore = -1;\n\n                for (int a = 0; a < candLim; ++a) {\n                    int sc = (int)(base | cands[a].cover).count();\n                    if (sc > firstBestScore) {\n                        firstBestScore = sc;\n                        firstBest = a;\n                    }\n                }\n\n                if (firstBest == -1) continue;\n\n                bitset<MAXM> base2 = base | cands[firstBest].cover;\n\n                for (int b = 0; b < candLim; ++b) {\n                    if (b == firstBest) continue;\n                    int sc = (int)(base2 | cands[b].cover).count();\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestA = firstBest;\n                        bestB = b;\n                    }\n                }\n\n                if (bestA != -1 && bestB != -1 && bestScore > curScore) {\n                    rows[r1] = cands[bestA].line;\n                    rows[r2] = cands[bestB].line;\n                    rowCov[r1] = cands[bestA].cover;\n                    rowCov[r2] = cands[bestB].cover;\n\n                    used = base | rowCov[r1] | rowCov[r2];\n                    curScore = bestScore;\n                    improved = true;\n                    goto NEXT_PASS;\n                }\n            }\n        }\n\nNEXT_PASS:\n        ;\n    }\n\n    return rows;\n}\n\nvector<string> randomized_select_rows(\n    const vector<Cand>& cands,\n    mt19937& rng,\n    Timer& timer,\n    bitset<MAXM>& bestUsedOut\n) {\n    vector<string> bestRows = greedy_select_rows(cands, rng, bestUsedOut);\n    int bestScore = (int)bestUsedOut.count();\n\n    int C = (int)cands.size();\n\n    while (timer.elapsed() < 2.16) {\n        bitset<MAXM> used;\n        vector<string> rows;\n\n        for (int step = 0; step < N; ++step) {\n            vector<pair<int, int>> top;\n            top.reserve(10);\n\n            int lim = min(C, 1000);\n\n            for (int i = 0; i < lim; ++i) {\n                int gain = gain_count(cands[i].cover, used);\n                if (gain <= 0) continue;\n\n                if ((int)top.size() < 10) {\n                    top.push_back({gain, i});\n                    sort(top.rbegin(), top.rend());\n                } else if (gain > top.back().first) {\n                    top.back() = {gain, i};\n                    sort(top.rbegin(), top.rend());\n                }\n            }\n\n            if (top.empty()) break;\n\n            int chooseRange = min((int)top.size(), 4);\n            int pick = rng() % chooseRange;\n\n            int id = top[pick].second;\n            rows.push_back(cands[id].line);\n            used |= cands[id].cover;\n        }\n\n        while ((int)rows.size() < N) {\n            rows.push_back(string(N, ALPHA[rng() % 8]));\n        }\n\n        int sc = (int)used.count();\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRows = rows;\n            bestUsedOut = used;\n        }\n    }\n\n    bestRows = local_replace_rows(bestRows, cands, timer);\n\n    if (timer.elapsed() < 2.45) {\n        bestRows = local_replace_two_rows(bestRows, cands, timer);\n    }\n\n    bestUsedOut.reset();\n    for (const string& row : bestRows) {\n        bestUsedOut |= calc_cover(row);\n    }\n\n    return bestRows;\n}\n\nbitset<MAXM> grid_cover_bitset(const vector<string>& grid) {\n    vector<string> cols(N, string(N, 'A'));\n\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) cols[j][i] = grid[i][j];\n    }\n\n    bitset<MAXM> bs;\n\n    for (int idx = 0; idx < M; ++idx) {\n        bool ok = false;\n\n        for (int i = 0; i < N && !ok; ++i) {\n            if (cyclic_contains(grid[i], S[idx])) ok = true;\n        }\n\n        for (int j = 0; j < N && !ok; ++j) {\n            if (cyclic_contains(cols[j], S[idx])) ok = true;\n        }\n\n        if (ok) bs.set(idx);\n    }\n\n    return bs;\n}\n\nvector<string> improve_columns(\n    vector<string> grid,\n    const vector<Cand>& cands,\n    mt19937& rng,\n    Timer& timer\n) {\n    bitset<MAXM> curCover = grid_cover_bitset(grid);\n    int curScore = (int)curCover.count();\n\n    vector<int> colOrder(N);\n    iota(colOrder.begin(), colOrder.end(), 0);\n    shuffle(colOrder.begin(), colOrder.end(), rng);\n\n    int candLim = min((int)cands.size(), 80);\n\n    for (int col : colOrder) {\n        if (timer.elapsed() > 2.72) break;\n\n        int bestGainScore = curScore;\n        string bestCol;\n        bool improved = false;\n\n        for (int ci = 0; ci < candLim; ++ci) {\n            if (timer.elapsed() > 2.72) break;\n\n            const string& line = cands[ci].line;\n\n            for (int sh = 0; sh < N; ++sh) {\n                vector<string> tmp = grid;\n\n                for (int i = 0; i < N; ++i) {\n                    tmp[i][col] = line[(i + sh) % N];\n                }\n\n                bitset<MAXM> cov = grid_cover_bitset(tmp);\n                int sc = (int)cov.count();\n\n                if (sc > bestGainScore) {\n                    bestGainScore = sc;\n                    bestCol.clear();\n                    for (int i = 0; i < N; ++i) {\n                        bestCol.push_back(line[(i + sh) % N]);\n                    }\n                    improved = true;\n                }\n            }\n        }\n\n        if (improved) {\n            for (int i = 0; i < N; ++i) grid[i][col] = bestCol[i];\n            curCover = grid_cover_bitset(grid);\n            curScore = (int)curCover.count();\n        }\n    }\n\n    return grid;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputN;\n    cin >> inputN >> M;\n\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    Timer timer;\n    mt19937 rng(123456789);\n\n    vector<Cand> cands = generate_candidates(rng, timer);\n\n    if (cands.empty()) {\n        for (int i = 0; i < N; ++i) {\n            cout << string(N, 'A') << '\\n';\n        }\n        return 0;\n    }\n\n    bitset<MAXM> rowUsed;\n    vector<string> rows = randomized_select_rows(cands, rng, timer, rowUsed);\n\n    vector<string> grid = rows;\n\n    if (timer.elapsed() < 2.55) {\n        grid = improve_columns(grid, cands, rng, timer);\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << grid[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct PQNode {\n    int d, v;\n    bool operator<(const PQNode& other) const {\n        return d > other.d;\n    }\n};\n\nstruct DijkstraResult {\n    vector<int> dist;\n    vector<int> par;\n    vector<int> parDir;\n};\n\nstruct CandidateSolution {\n    long long cost = (1LL << 60);\n    vector<int> nodes;\n    vector<int> route;\n    vector<vector<int>> distMat;\n    vector<DijkstraResult> dijs;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    const int V = N * N;\n    const int INF = 1e9;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    auto pos = [&](int v) {\n        return pair<int,int>{v / N, v % N};\n    };\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n\n    vector<int> isroad(V, 0), weight(V, 0), road_ids;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                int v = id(i, j);\n                isroad[v] = 1;\n                weight[v] = grid[i][j] - '0';\n                road_ids.push_back(v);\n            }\n        }\n    }\n\n    int R = (int)road_ids.size();\n    int start = id(si, sj);\n\n    vector<vector<int>> visible(V);\n\n    vector<int> hid(V, -1), vid(V, -1);\n    vector<vector<int>> hsegCells, vsegCells;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n\n            vector<int> seg;\n            int k = j;\n            while (k < N && grid[i][k] != '#') {\n                int v = id(i, k);\n                hid[v] = (int)hsegCells.size();\n                seg.push_back(v);\n                k++;\n            }\n\n            hsegCells.push_back(seg);\n\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n\n            j = k;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n\n            vector<int> seg;\n            int k = i;\n            while (k < N && grid[k][j] != '#') {\n                int v = id(k, j);\n                vid[v] = (int)vsegCells.size();\n                seg.push_back(v);\n                k++;\n            }\n\n            vsegCells.push_back(seg);\n\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n\n            i = k;\n        }\n    }\n\n    for (int v : road_ids) {\n        auto &a = visible[v];\n        sort(a.begin(), a.end());\n        a.erase(unique(a.begin(), a.end()), a.end());\n    }\n\n    int H = (int)hsegCells.size();\n    int W = (int)vsegCells.size();\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    auto dijkstra = [&](int s) {\n        DijkstraResult res;\n        res.dist.assign(V, INF);\n        res.par.assign(V, -1);\n        res.parDir.assign(V, -1);\n\n        priority_queue<PQNode> pq;\n        res.dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n\n            if (d != res.dist[v]) continue;\n\n            auto [i, j] = pos(v);\n\n            for (int z = 0; z < 4; z++) {\n                int ni = i + di[z];\n                int nj = j + dj[z];\n\n                if (!inside(ni, nj)) continue;\n                if (grid[ni][nj] == '#') continue;\n\n                int nv = id(ni, nj);\n                int nd = d + weight[nv];\n\n                if (nd < res.dist[nv]) {\n                    res.dist[nv] = nd;\n                    res.par[nv] = v;\n                    res.parDir[nv] = z;\n                    pq.push({nd, nv});\n                }\n            }\n        }\n\n        return res;\n    };\n\n    auto restore_path = [&](int s, int t, const vector<int>& par,\n                            const vector<int>& parDir) {\n        string path;\n        int cur = t;\n\n        while (cur != s) {\n            int z = parDir[cur];\n            path.push_back(dc[z]);\n            cur = par[cur];\n        }\n\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    DijkstraResult dijStart = dijkstra(start);\n\n    auto coverage_complete = [&](const vector<int>& target_cells) {\n        vector<char> cov(V, 0);\n        int cnt = 0;\n\n        auto add = [&](int v) {\n            for (int u : visible[v]) {\n                if (!cov[u]) {\n                    cov[u] = 1;\n                    cnt++;\n                }\n            }\n        };\n\n        add(start);\n        for (int v : target_cells) add(v);\n\n        return cnt == R;\n    };\n\n    auto solution_cells = [&](const CandidateSolution& sol) {\n        vector<int> cells;\n        for (int idx : sol.route) cells.push_back(sol.nodes[idx]);\n        return cells;\n    };\n\n    auto build_target_set_cell = [&](double distPow, double interBonus, double noiseCoef) {\n        vector<char> covered(V, 0);\n        int covered_count = 0;\n\n        auto apply_cover = [&](int v) {\n            for (int u : visible[v]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    covered_count++;\n                }\n            }\n        };\n\n        vector<int> targets;\n        apply_cover(start);\n\n        int step = 0;\n\n        while (covered_count < R) {\n            int best = -1;\n            double bestScore = -1.0;\n\n            for (int v : road_ids) {\n                int gain = 0;\n                for (int u : visible[v]) {\n                    if (!covered[u]) gain++;\n                }\n                if (gain == 0) continue;\n\n                double score = (double)gain;\n                score /= pow((double)dijStart.dist[v] + 20.0, distPow);\n\n                auto [i, j] = pos(v);\n                int deg = 0;\n                for (int z = 0; z < 4; z++) {\n                    int ni = i + di[z];\n                    int nj = j + dj[z];\n                    if (inside(ni, nj) && grid[ni][nj] != '#') deg++;\n                }\n                if (deg >= 3) score *= interBonus;\n\n                unsigned h = (unsigned)(v * 1103515245u + step * 12345u);\n                double rnd = ((h >> 8) & 1023) / 1023.0;\n                score *= 1.0 + noiseCoef * (rnd - 0.5);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = v;\n                }\n            }\n\n            if (best == -1) break;\n\n            targets.push_back(best);\n            apply_cover(best);\n            step++;\n        }\n\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n        return targets;\n    };\n\n    auto build_target_set_segment = [&](double distPow, double lengthBonus, double noiseCoef) {\n        vector<char> hSeen(H, 0), vSeen(W, 0);\n\n        auto covered_count_now = [&]() {\n            int cnt = 0;\n            for (int v : road_ids) {\n                if (hSeen[hid[v]] || vSeen[vid[v]]) cnt++;\n            }\n            return cnt;\n        };\n\n        auto apply = [&](int v) {\n            hSeen[hid[v]] = 1;\n            vSeen[vid[v]] = 1;\n        };\n\n        vector<int> targets;\n        apply(start);\n\n        int covered_count = covered_count_now();\n        int step = 0;\n\n        while (covered_count < R) {\n            int best = -1;\n            double bestScore = -1.0;\n\n            for (int v : road_ids) {\n                int h = hid[v];\n                int w = vid[v];\n\n                if (hSeen[h] && vSeen[w]) continue;\n\n                int gain = 0;\n\n                for (int u : hsegCells[h]) {\n                    if (!(hSeen[hid[u]] || vSeen[vid[u]])) gain++;\n                }\n\n                for (int u : vsegCells[w]) {\n                    if (!(hSeen[hid[u]] || vSeen[vid[u]])) gain++;\n                }\n\n                if (!(hSeen[h] || vSeen[w])) gain--;\n\n                if (gain <= 0) continue;\n\n                double score = (double)gain;\n                score /= pow((double)dijStart.dist[v] + 20.0, distPow);\n\n                int lenSum = (int)hsegCells[h].size() + (int)vsegCells[w].size();\n                score *= 1.0 + lengthBonus * sqrt((double)lenSum);\n\n                unsigned hh = (unsigned)(v * 2654435761u + step * 97u);\n                double rnd = ((hh >> 7) & 1023) / 1023.0;\n                score *= 1.0 + noiseCoef * (rnd - 0.5);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = v;\n                }\n            }\n\n            if (best == -1) break;\n\n            targets.push_back(best);\n            apply(best);\n            covered_count = covered_count_now();\n            step++;\n        }\n\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n        return targets;\n    };\n\n    auto remove_redundant_targets = [&](vector<int> targets) {\n        vector<int> result;\n        for (int v : targets) {\n            if (v != start) result.push_back(v);\n        }\n\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n\n            vector<int> coverCount(V, 0);\n            auto add = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            add(start);\n            for (int v : result) add(v);\n\n            vector<pair<int,int>> ord;\n            for (int idx = 0; idx < (int)result.size(); idx++) {\n                ord.push_back({(int)visible[result[idx]].size(), idx});\n            }\n\n            sort(ord.begin(), ord.end());\n\n            vector<char> removed(result.size(), 0);\n\n            for (auto [sz, idx] : ord) {\n                if (removed[idx]) continue;\n                int v = result[idx];\n\n                bool ok = true;\n                for (int u : visible[v]) {\n                    if (coverCount[u] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n\n                if (ok) {\n                    removed[idx] = 1;\n                    changed = true;\n                    for (int u : visible[v]) coverCount[u]--;\n                }\n            }\n\n            if (changed) {\n                vector<int> nxt;\n                for (int i = 0; i < (int)result.size(); i++) {\n                    if (!removed[i]) nxt.push_back(result[i]);\n                }\n                result.swap(nxt);\n            }\n        }\n\n        return result;\n    };\n\n    auto route_cost_from_order = [&](const vector<vector<int>>& distMat,\n                                     const vector<int>& route) {\n        long long cost = 0;\n        int prev = 0;\n        for (int x : route) {\n            cost += distMat[prev][x];\n            prev = x;\n        }\n        cost += distMat[prev][0];\n        return cost;\n    };\n\n    auto two_opt = [&](vector<int>& route, const vector<vector<int>>& distMat) {\n        int L = (int)route.size();\n\n        bool improved = true;\n        int iter = 0;\n\n        while (improved && iter < 500) {\n            improved = false;\n            iter++;\n\n            for (int l = 0; l < L && !improved; l++) {\n                for (int r = l + 1; r < L && !improved; r++) {\n                    int a = (l == 0 ? 0 : route[l - 1]);\n                    int b = route[l];\n                    int c = route[r];\n                    int d = (r + 1 == L ? 0 : route[r + 1]);\n\n                    int before = distMat[a][b] + distMat[c][d];\n                    int after  = distMat[a][c] + distMat[b][d];\n\n                    if (after < before) {\n                        reverse(route.begin() + l, route.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    };\n\n    auto solve_tsp_for_targets = [&](const vector<int>& target_cells) {\n        CandidateSolution sol;\n\n        vector<int> nodes;\n        nodes.push_back(start);\n        for (int v : target_cells) {\n            if (v != start) nodes.push_back(v);\n        }\n\n        sort(nodes.begin() + 1, nodes.end());\n        nodes.erase(unique(nodes.begin() + 1, nodes.end()), nodes.end());\n\n        int M = (int)nodes.size();\n\n        vector<DijkstraResult> dijs(M);\n        vector<vector<int>> distMat(M, vector<int>(M, INF));\n\n        for (int a = 0; a < M; a++) {\n            dijs[a] = dijkstra(nodes[a]);\n            for (int b = 0; b < M; b++) {\n                distMat[a][b] = dijs[a].dist[nodes[b]];\n            }\n        }\n\n        vector<int> remaining;\n        for (int i = 1; i < M; i++) remaining.push_back(i);\n\n        vector<int> route;\n\n        if (!remaining.empty()) {\n            int first = remaining[0];\n            for (int x : remaining) {\n                if (distMat[0][x] + distMat[x][0] <\n                    distMat[0][first] + distMat[first][0]) {\n                    first = x;\n                }\n            }\n\n            route.push_back(first);\n            remaining.erase(find(remaining.begin(), remaining.end(), first));\n        }\n\n        while (!remaining.empty()) {\n            int bestNode = -1;\n            int bestPos = -1;\n            int bestInc = INF;\n\n            for (int x : remaining) {\n                int L = (int)route.size();\n\n                for (int p = 0; p <= L; p++) {\n                    int a = (p == 0 ? 0 : route[p - 1]);\n                    int b = (p == L ? 0 : route[p]);\n\n                    int inc = distMat[a][x] + distMat[x][b] - distMat[a][b];\n\n                    if (inc < bestInc) {\n                        bestInc = inc;\n                        bestNode = x;\n                        bestPos = p;\n                    }\n                }\n            }\n\n            route.insert(route.begin() + bestPos, bestNode);\n            remaining.erase(find(remaining.begin(), remaining.end(), bestNode));\n        }\n\n        two_opt(route, distMat);\n\n        sol.cost = route_cost_from_order(distMat, route);\n        sol.nodes = move(nodes);\n        sol.route = move(route);\n        sol.distMat = move(distMat);\n        sol.dijs = move(dijs);\n\n        return sol;\n    };\n\n    auto route_aware_delete = [&](CandidateSolution& sol) {\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n\n            vector<int> target_cells;\n            for (int idx : sol.route) target_cells.push_back(sol.nodes[idx]);\n\n            vector<int> coverCount(V, 0);\n            auto addCount = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            addCount(start);\n            for (int v : target_cells) addCount(v);\n\n            int L = (int)sol.route.size();\n            int bestRemovePos = -1;\n            int bestGain = 0;\n\n            for (int p = 0; p < L; p++) {\n                int idx = sol.route[p];\n                int v = sol.nodes[idx];\n\n                bool ok = true;\n                for (int u : visible[v]) {\n                    if (coverCount[u] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n\n                int a = (p == 0 ? 0 : sol.route[p - 1]);\n                int b = idx;\n                int c = (p + 1 == L ? 0 : sol.route[p + 1]);\n\n                int gain = sol.distMat[a][b] + sol.distMat[b][c] - sol.distMat[a][c];\n\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestRemovePos = p;\n                }\n            }\n\n            if (bestRemovePos != -1) {\n                sol.route.erase(sol.route.begin() + bestRemovePos);\n                sol.cost -= bestGain;\n                changed = true;\n            }\n        }\n    };\n\n    auto build_solution_from_route_cells = [&](const vector<int>& cells) {\n        vector<int> cleaned;\n        for (int v : cells) {\n            if (v != start) cleaned.push_back(v);\n        }\n        sort(cleaned.begin(), cleaned.end());\n        cleaned.erase(unique(cleaned.begin(), cleaned.end()), cleaned.end());\n        return solve_tsp_for_targets(cleaned);\n    };\n\n    auto improve_by_relocation = [&](CandidateSolution base) {\n        vector<int> cells;\n        for (int idx : base.route) cells.push_back(base.nodes[idx]);\n\n        CandidateSolution bestLocal = base;\n\n        bool improvedReloc = true;\n        int relocIter = 0;\n\n        while (improvedReloc && relocIter < 3) {\n            improvedReloc = false;\n            relocIter++;\n\n            CandidateSolution curSol = build_solution_from_route_cells(cells);\n            route_aware_delete(curSol);\n            two_opt(curSol.route, curSol.distMat);\n            curSol.cost = route_cost_from_order(curSol.distMat, curSol.route);\n\n            if (curSol.cost < bestLocal.cost) bestLocal = curSol;\n\n            cells.clear();\n            for (int idx : curSol.route) cells.push_back(curSol.nodes[idx]);\n\n            vector<int> coverCount(V, 0);\n            auto addCount = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            addCount(start);\n            for (int v : cells) addCount(v);\n\n            int L = (int)cells.size();\n\n            for (int p = 0; p < L; p++) {\n                int oldv = cells[p];\n\n                int prevv = (p == 0 ? start : cells[p - 1]);\n                int nextv = (p + 1 == L ? start : cells[p + 1]);\n\n                DijkstraResult dijPrev = dijkstra(prevv);\n                DijkstraResult dijOld = dijkstra(oldv);\n\n                int oldLocal = dijPrev.dist[oldv] + dijOld.dist[nextv];\n\n                vector<int> mustRemain;\n                for (int u : visible[oldv]) {\n                    if (coverCount[u] <= 1) mustRemain.push_back(u);\n                }\n\n                auto [oi, oj] = pos(oldv);\n\n                int bestNew = oldv;\n                int bestLocalCost = oldLocal;\n\n                for (int cand : road_ids) {\n                    auto [ci, cj] = pos(cand);\n                    int man = abs(ci - oi) + abs(cj - oj);\n                    if (man > 9) continue;\n\n                    if (cand == oldv) continue;\n\n                    bool coversMust = true;\n                    for (int u : mustRemain) {\n                        if (!binary_search(visible[cand].begin(), visible[cand].end(), u)) {\n                            coversMust = false;\n                            break;\n                        }\n                    }\n                    if (!coversMust) continue;\n\n                    int local1 = dijPrev.dist[cand];\n                    if (local1 >= INF) continue;\n\n                    DijkstraResult dijCand = dijkstra(cand);\n                    int local2 = dijCand.dist[nextv];\n                    if (local2 >= INF) continue;\n\n                    int local = local1 + local2;\n                    if (local < bestLocalCost) {\n                        bestLocalCost = local;\n                        bestNew = cand;\n                    }\n                }\n\n                if (bestNew != oldv) {\n                    for (int u : visible[oldv]) coverCount[u]--;\n                    cells[p] = bestNew;\n                    for (int u : visible[bestNew]) coverCount[u]++;\n                    improvedReloc = true;\n                }\n            }\n        }\n\n        CandidateSolution relocSol = build_solution_from_route_cells(cells);\n        route_aware_delete(relocSol);\n        two_opt(relocSol.route, relocSol.distMat);\n        relocSol.cost = route_cost_from_order(relocSol.distMat, relocSol.route);\n\n        if (coverage_complete(cells) && relocSol.cost < bestLocal.cost) {\n            bestLocal = relocSol;\n        }\n\n        return bestLocal;\n    };\n\n    auto build_target_set_insertion = [&](double gainPow, double costPow, double noiseCoef) {\n        vector<int> nodes;\n        nodes.push_back(start);\n\n        vector<DijkstraResult> dijs;\n        dijs.push_back(dijStart);\n\n        vector<vector<int>> distMat(1, vector<int>(1, 0));\n        vector<int> route;\n\n        vector<char> covered(V, 0);\n        int covered_count = 0;\n\n        auto apply_cover = [&](int v) {\n            for (int u : visible[v]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    covered_count++;\n                }\n            }\n        };\n\n        apply_cover(start);\n\n        int step = 0;\n\n        while (covered_count < R) {\n            int bestCell = -1;\n            double bestScore = -1.0;\n\n            for (int v : road_ids) {\n                int gain = 0;\n                for (int u : visible[v]) {\n                    if (!covered[u]) gain++;\n                }\n                if (gain <= 0) continue;\n\n                int bestInc = INF;\n\n                int L = (int)route.size();\n\n                for (int p = 0; p <= L; p++) {\n                    int aidx = (p == 0 ? 0 : route[p - 1]);\n                    int bidx = (p == L ? 0 : route[p]);\n\n                    int b = nodes[bidx];\n\n                    int dab = distMat[aidx][bidx];\n                    int dav = dijs[aidx].dist[v];\n\n                    if (dav >= INF) continue;\n\n                    auto [vi, vj] = pos(v);\n                    auto [bi, bj] = pos(b);\n\n                    int estvb = (abs(vi - bi) + abs(vj - bj)) * 5;\n\n                    int inc = dav + estvb - dab;\n                    if (inc < bestInc) bestInc = inc;\n                }\n\n                if (bestInc < 1) bestInc = 1;\n\n                double score = pow((double)gain, gainPow) / pow((double)bestInc + 10.0, costPow);\n\n                unsigned h = (unsigned)(v * 747796405u + step * 2891336453u);\n                double rnd = ((h >> 9) & 1023) / 1023.0;\n                score *= 1.0 + noiseCoef * (rnd - 0.5);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestCell = v;\n                }\n            }\n\n            if (bestCell == -1) break;\n\n            int newIdx = (int)nodes.size();\n            nodes.push_back(bestCell);\n\n            DijkstraResult dijNew = dijkstra(bestCell);\n            dijs.push_back(move(dijNew));\n\n            int oldM = (int)distMat.size();\n            for (auto &row : distMat) row.push_back(INF);\n            distMat.push_back(vector<int>(oldM + 1, INF));\n\n            for (int i = 0; i <= oldM; i++) {\n                if (i < oldM) {\n                    distMat[i][newIdx] = dijs[i].dist[bestCell];\n                    distMat[newIdx][i] = dijs[newIdx].dist[nodes[i]];\n                }\n            }\n            distMat[newIdx][newIdx] = 0;\n\n            int L = (int)route.size();\n            int bestInc = INF;\n            int bestPos = 0;\n\n            for (int p = 0; p <= L; p++) {\n                int a = (p == 0 ? 0 : route[p - 1]);\n                int b = (p == L ? 0 : route[p]);\n\n                int inc = distMat[a][newIdx] + distMat[newIdx][b] - distMat[a][b];\n\n                if (inc < bestInc) {\n                    bestInc = inc;\n                    bestPos = p;\n                }\n            }\n\n            route.insert(route.begin() + bestPos, newIdx);\n            apply_cover(bestCell);\n            step++;\n        }\n\n        vector<int> targets;\n        for (int idx : route) targets.push_back(nodes[idx]);\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n        return targets;\n    };\n\n    vector<CandidateSolution> pool;\n\n    auto add_solution_to_pool = [&](CandidateSolution sol) {\n        if (sol.cost >= (1LL << 50)) return;\n        if (!coverage_complete(solution_cells(sol))) return;\n\n        pool.push_back(move(sol));\n\n        sort(pool.begin(), pool.end(), [](const CandidateSolution& a, const CandidateSolution& b) {\n            return a.cost < b.cost;\n        });\n\n        if ((int)pool.size() > 10) pool.resize(10);\n    };\n\n    auto process_targets = [&](vector<int> targets) {\n        targets = remove_redundant_targets(targets);\n        if (!coverage_complete(targets)) return;\n\n        CandidateSolution raw = solve_tsp_for_targets(targets);\n        raw.cost = route_cost_from_order(raw.distMat, raw.route);\n        add_solution_to_pool(raw);\n\n        CandidateSolution imp = raw;\n        route_aware_delete(imp);\n        two_opt(imp.route, imp.distMat);\n        imp.cost = route_cost_from_order(imp.distMat, imp.route);\n        add_solution_to_pool(imp);\n    };\n\n    vector<tuple<double,double,double>> cellParams = {\n        {0.04, 1.00, 0.00},\n        {0.06, 1.00, 0.00},\n        {0.10, 1.02, 0.00},\n        {0.15, 1.05, 0.00},\n        {0.18, 1.08, 0.00},\n        {0.22, 1.10, 0.00},\n        {0.28, 1.12, 0.00},\n        {0.34, 1.15, 0.00},\n        {0.18, 1.08, 0.04},\n        {0.18, 1.08, 0.08},\n        {0.24, 1.12, 0.06},\n        {0.30, 1.15, 0.08}\n    };\n\n    for (auto [distPow, interBonus, noiseCoef] : cellParams) {\n        process_targets(build_target_set_cell(distPow, interBonus, noiseCoef));\n    }\n\n    vector<tuple<double,double,double>> segParams = {\n        {0.00, 0.000, 0.00},\n        {0.08, 0.010, 0.00},\n        {0.14, 0.015, 0.00},\n        {0.20, 0.020, 0.00},\n        {0.28, 0.025, 0.00},\n        {0.18, 0.015, 0.05},\n        {0.24, 0.020, 0.08}\n    };\n\n    for (auto [distPow, lengthBonus, noiseCoef] : segParams) {\n        process_targets(build_target_set_segment(distPow, lengthBonus, noiseCoef));\n    }\n\n    vector<tuple<double,double,double>> insParams = {\n        {1.00, 0.80, 0.00},\n        {1.00, 1.00, 0.00},\n        {1.10, 1.00, 0.00},\n        {1.20, 1.10, 0.00},\n        {1.00, 1.00, 0.06},\n        {1.15, 1.05, 0.08}\n    };\n\n    for (auto [gainPow, costPow, noiseCoef] : insParams) {\n        process_targets(build_target_set_insertion(gainPow, costPow, noiseCoef));\n    }\n\n    int initialPoolSize = (int)pool.size();\n    for (int i = 0; i < min(initialPoolSize, 4); i++) {\n        CandidateSolution rel = improve_by_relocation(pool[i]);\n        rel.cost = route_cost_from_order(rel.distMat, rel.route);\n        add_solution_to_pool(rel);\n    }\n\n    // ------------------------------------------------------------\n    // One-add-many-delete repair.\n    // ------------------------------------------------------------\n\n    auto improve_by_add_delete = [&](const CandidateSolution& base) {\n        CandidateSolution best = base;\n\n        vector<int> baseCells = solution_cells(base);\n        unordered_set<int> used(baseCells.begin(), baseCells.end());\n        used.insert(start);\n\n        vector<int> routeCells = baseCells;\n\n        vector<pair<double,int>> candScores;\n\n        for (int v : road_ids) {\n            if (used.count(v)) continue;\n\n            int bestMan = 1e9;\n            auto [vi, vj] = pos(v);\n\n            for (int u : routeCells) {\n                auto [ui, uj] = pos(u);\n                bestMan = min(bestMan, abs(vi - ui) + abs(vj - uj));\n            }\n\n            auto [si0, sj0] = pos(start);\n            bestMan = min(bestMan, abs(vi - si0) + abs(vj - sj0));\n\n            int deg = 0;\n            for (int z = 0; z < 4; z++) {\n                int ni = vi + di[z];\n                int nj = vj + dj[z];\n                if (inside(ni, nj) && grid[ni][nj] != '#') deg++;\n            }\n\n            int lenSum = (int)hsegCells[hid[v]].size() + (int)vsegCells[vid[v]].size();\n\n            double score = (double)visible[v].size();\n            score += 0.8 * sqrt((double)lenSum);\n            if (deg >= 3) score *= 1.15;\n            score /= (double)(bestMan + 3);\n\n            candScores.push_back({-score, v});\n        }\n\n        sort(candScores.begin(), candScores.end());\n\n        int TRY = min(24, (int)candScores.size());\n\n        for (int ti = 0; ti < TRY; ti++) {\n            int addv = candScores[ti].second;\n\n            vector<int> cells = baseCells;\n            cells.push_back(addv);\n\n            CandidateSolution sol = build_solution_from_route_cells(cells);\n            route_aware_delete(sol);\n            two_opt(sol.route, sol.distMat);\n            sol.cost = route_cost_from_order(sol.distMat, sol.route);\n\n            if (sol.cost < best.cost && coverage_complete(solution_cells(sol))) {\n                best = move(sol);\n            }\n        }\n\n        return best;\n    };\n\n    int poolSizeBeforeAdd = (int)pool.size();\n    for (int i = 0; i < min(poolSizeBeforeAdd, 4); i++) {\n        CandidateSolution improved = improve_by_add_delete(pool[i]);\n        add_solution_to_pool(improved);\n    }\n\n    sort(pool.begin(), pool.end(), [](const CandidateSolution& a, const CandidateSolution& b) {\n        return a.cost < b.cost;\n    });\n\n    CandidateSolution bestSol = pool[0];\n\n    route_aware_delete(bestSol);\n    two_opt(bestSol.route, bestSol.distMat);\n    bestSol.cost = route_cost_from_order(bestSol.distMat, bestSol.route);\n\n    add_solution_to_pool(bestSol);\n\n    sort(pool.begin(), pool.end(), [](const CandidateSolution& a, const CandidateSolution& b) {\n        return a.cost < b.cost;\n    });\n\n    bestSol = pool[0];\n\n    string answer;\n    int prev = 0;\n\n    for (int x : bestSol.route) {\n        answer += restore_path(\n            bestSol.nodes[prev],\n            bestSol.nodes[x],\n            bestSol.dijs[prev].par,\n            bestSol.dijs[prev].parDir\n        );\n        prev = x;\n    }\n\n    answer += restore_path(\n        bestSol.nodes[prev],\n        bestSol.nodes[0],\n        bestSol.dijs[prev].par,\n        bestSol.dijs[prev].parDir\n    );\n\n    cout << answer << '\\n';\n\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    vector<int> d;\n    vector<int> pre;\n    vector<int> nxt;\n};\n\nstruct Obs {\n    int task;\n    int dur;\n};\n\nstruct Edge {\n    int to, rev, cap;\n    int cost;\n};\n\nstruct MinCostFlow {\n    int n;\n    vector<vector<Edge>> g;\n\n    MinCostFlow(int n = 0) : n(n), g(n) {}\n\n    void addEdge(int fr, int to, int cap, int cost) {\n        Edge a{to, (int)g[to].size(), cap, cost};\n        Edge b{fr, (int)g[fr].size(), 0, -cost};\n        g[fr].push_back(a);\n        g[to].push_back(b);\n    }\n\n    pair<int,int> flow(int s, int t, int maxf) {\n        int flow = 0, cost = 0;\n        const int INF = 1e9;\n        vector<int> h(n, 0), dist(n), pv(n), pe(n);\n\n        while (flow < maxf) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n\n            priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n            pq.push({0, s});\n\n            while (!pq.empty()) {\n                auto [d, v] = pq.top();\n                pq.pop();\n                if (dist[v] != d) continue;\n\n                for (int i = 0; i < (int)g[v].size(); i++) {\n                    Edge &e = g[v][i];\n                    if (e.cap <= 0) continue;\n                    int nd = d + e.cost + h[v] - h[e.to];\n                    if (nd < dist[e.to]) {\n                        dist[e.to] = nd;\n                        pv[e.to] = v;\n                        pe[e.to] = i;\n                        pq.push({nd, e.to});\n                    }\n                }\n            }\n\n            if (dist[t] == INF) break;\n\n            for (int v = 0; v < n; v++) {\n                if (dist[v] < INF) h[v] += dist[v];\n            }\n\n            int add = maxf - flow;\n            for (int v = t; v != s; v = pv[v]) {\n                add = min(add, g[pv[v]][pe[v]].cap);\n            }\n\n            for (int v = t; v != s; v = pv[v]) {\n                Edge &e = g[pv[v]][pe[v]];\n                e.cap -= add;\n                g[v][e.rev].cap += add;\n                cost += add * e.cost;\n            }\n\n            flow += add;\n        }\n\n        return {flow, cost};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<Task> tasks(N);\n    vector<double> dsum(N, 0.0), dmaxv(N, 0.0), avgD(K, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; k++) {\n            cin >> tasks[i].d[k];\n            dsum[i] += tasks[i].d[k];\n            dmaxv[i] = max(dmaxv[i], (double)tasks[i].d[k]);\n            avgD[k] += tasks[i].d[k];\n        }\n    }\n    for (int k = 0; k < K; k++) avgD[k] /= N;\n\n    vector<int> indeg0(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        tasks[u].nxt.push_back(v);\n        tasks[v].pre.push_back(u);\n        indeg0[v]++;\n    }\n\n    vector<double> crit(N, 1.0), unlock(N, 0.0), nearUnlock(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double bestCrit = 0.0;\n        double sumUnlock = 0.0;\n        double near = tasks[i].nxt.size();\n\n        for (int v : tasks[i].nxt) {\n            bestCrit = max(bestCrit, crit[v]);\n            sumUnlock += 1.0 + 0.17 * unlock[v];\n            near += 0.22 * tasks[v].nxt.size();\n        }\n\n        double ownHard = dsum[i] / max(1, K);\n        crit[i] = 1.0 + bestCrit + 0.018 * ownHard;\n        unlock[i] = min(2500.0, sumUnlock);\n        nearUnlock[i] = near;\n    }\n\n    vector<double> basePriority(N);\n    for (int i = 0; i < N; i++) {\n        basePriority[i] =\n            35.5 * crit[i]\n            + 4.8 * nearUnlock[i]\n            + 0.13 * unlock[i]\n            + 0.028 * dsum[i]\n            + 0.028 * dmaxv[i]\n            - 0.001 * i;\n    }\n\n    vector<int> status(N, -1);\n    vector<int> remPre = indeg0;\n    vector<int> readySince(N, -1);\n\n    vector<int> readyList;\n    vector<char> inReady(N, 0);\n    for (int i = 0; i < N; i++) {\n        if (remPre[i] == 0) {\n            readyList.push_back(i);\n            inReady[i] = 1;\n            readySince[i] = 1;\n        }\n    }\n\n    vector<int> memberTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    for (int j = 0; j < M; j++) {\n        double scale = 0.96 + 0.10 * ((j % 5) - 2);\n        if (scale < 0.75) scale = 0.75;\n\n        for (int k = 0; k < K; k++) {\n            double spec = 0.0;\n            if (k % M == j) spec += 3.0;\n            if ((k + j) % 7 == 0) spec += 2.0;\n            if ((2 * k + j) % 11 == 0) spec += 1.5;\n            skill[j][k] = max(0.0, avgD[k] * scale + spec);\n        }\n    }\n\n    vector<vector<Obs>> observations(M);\n    vector<double> speed(M, 1.0);\n\n    auto raw_shortage = [&](int task, int member) {\n        double w = 0.0;\n        for (int k = 0; k < K; k++) {\n            w += max(0.0, (double)tasks[task].d[k] - skill[member][k]);\n        }\n        return w;\n    };\n\n    auto estimate_duration = [&](int task, int member) {\n        double w = raw_shortage(task, member);\n        double e = max(1.0, w);\n        e *= speed[member];\n        if (e < 1.0) e = 1.0;\n        return e;\n    };\n\n    auto refit_member = [&](int j) {\n        int nobs = (int)observations[j].size();\n        if (nobs == 0) return;\n\n        int passes = 6;\n        if (nobs > 20) passes = 4;\n        if (nobs > 60) passes = 3;\n\n        double baseLR = 0.038 / sqrt(1.0 + 0.04 * nobs);\n\n        for (int pass = 0; pass < passes; pass++) {\n            for (const Obs &ob : observations[j]) {\n                int t = ob.task;\n                int dur = ob.dur;\n\n                double pred = 0.0;\n                vector<int> active;\n                active.reserve(K);\n\n                for (int k = 0; k < K; k++) {\n                    double gap = (double)tasks[t].d[k] - skill[j][k];\n                    if (gap > 0.0) {\n                        pred += gap;\n                        active.push_back(k);\n                    }\n                }\n\n                double lo, hi;\n                if (dur <= 1) {\n                    lo = 0.0;\n                    hi = 3.0;\n                } else {\n                    lo = max(0.0, (double)dur - 3.0);\n                    hi = (double)dur + 3.0;\n                }\n\n                double err = 0.0;\n                if (pred < lo) err = pred - lo;\n                else if (pred > hi) err = pred - hi;\n\n                if (fabs(err) > 1e-9) {\n                    if (!active.empty()) {\n                        double delta = baseLR * err / sqrt((double)active.size());\n                        for (int k : active) skill[j][k] += delta;\n                    } else if (err < 0.0) {\n                        double dec = baseLR * (-err) / max(1.0, dsum[t]);\n                        for (int k = 0; k < K; k++) skill[j][k] -= dec * tasks[t].d[k];\n                    }\n                }\n\n                if (dur == 1) {\n                    double lr = 0.018 / sqrt(1.0 + 0.03 * nobs);\n                    for (int k = 0; k < K; k++) {\n                        if (skill[j][k] < tasks[t].d[k]) {\n                            skill[j][k] += lr * ((double)tasks[t].d[k] - skill[j][k]);\n                        }\n                    }\n                }\n\n                for (int k = 0; k < K; k++) {\n                    if (skill[j][k] < 0.0) skill[j][k] = 0.0;\n                    if (skill[j][k] > 80.0) skill[j][k] = 80.0;\n                }\n            }\n        }\n    };\n\n    auto update_speed = [&](int j) {\n        int nobs = observations[j].size();\n        if (nobs == 0) return;\n\n        int use = min(nobs, 20);\n        double sumLog = 0.0;\n        int cnt = 0;\n\n        for (int idx = nobs - use; idx < nobs; idx++) {\n            const Obs &ob = observations[j][idx];\n            double pred = max(1.0, raw_shortage(ob.task, j));\n            double ratio = (double)ob.dur / pred;\n            ratio = min(3.0, max(0.35, ratio));\n            sumLog += log(ratio);\n            cnt++;\n        }\n\n        if (cnt > 0) {\n            double target = exp(sumLog / cnt);\n            double alpha = min(0.35, 0.08 + 0.015 * nobs);\n            speed[j] = speed[j] * (1.0 - alpha) + target * alpha;\n            if (speed[j] < 0.55) speed[j] = 0.55;\n            if (speed[j] > 1.80) speed[j] = 1.80;\n        }\n    };\n\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        vector<int> readyTasks;\n        readyTasks.reserve(readyList.size());\n        for (int t : readyList) {\n            if (status[t] == -1 && remPre[t] == 0) readyTasks.push_back(t);\n        }\n\n        vector<double> dynPriority(N, 0.0);\n        vector<double> immediateUnlock(N, 0.0);\n\n        for (int t : readyTasks) {\n            double almost = 0.0;\n            for (int v : tasks[t].nxt) {\n                if (status[v] == -1 && remPre[v] == 1) {\n                    almost += 1.0 + 0.08 * nearUnlock[v] + 0.04 * crit[v];\n                }\n            }\n            immediateUnlock[t] = almost;\n\n            double waitBonus = 0.0;\n            if (readySince[t] > 0) {\n                int wait = day - readySince[t];\n                waitBonus = min(25.0, 0.35 * wait);\n            }\n\n            dynPriority[t] =\n                basePriority[t]\n                + 7.0 * almost\n                + waitBonus;\n        }\n\n        sort(readyTasks.begin(), readyTasks.end(), [&](int a, int b) {\n            if (dynPriority[a] != dynPriority[b]) return dynPriority[a] > dynPriority[b];\n            return a < b;\n        });\n\n        vector<int> freeMembers;\n        for (int j = 0; j < M; j++) {\n            if (memberTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        vector<pair<int,int>> assignments;\n\n        if (!freeMembers.empty() && !readyTasks.empty()) {\n            int F = (int)freeMembers.size();\n\n            vector<int> candTasks;\n            vector<char> selected(N, 0);\n\n            auto addTask = [&](int t) {\n                if (!selected[t]) {\n                    selected[t] = 1;\n                    candTasks.push_back(t);\n                }\n            };\n\n            int topByPriority = min((int)readyTasks.size(), max(45, F * 9));\n            for (int i = 0; i < topByPriority; i++) addTask(readyTasks[i]);\n\n            // Add tasks that seem quickly finishable by some free member.\n            vector<pair<double,int>> easy;\n            easy.reserve(readyTasks.size());\n            int scanEasy = min((int)readyTasks.size(), 180);\n            for (int idx = 0; idx < scanEasy; idx++) {\n                int t = readyTasks[idx];\n                double bestEst = 1e100;\n                for (int j : freeMembers) {\n                    bestEst = min(bestEst, estimate_duration(t, j));\n                }\n                double key = bestEst - 0.08 * immediateUnlock[t] - 0.01 * basePriority[t];\n                easy.push_back({key, t});\n            }\n            sort(easy.begin(), easy.end());\n            int addEasy = min((int)easy.size(), max(20, F * 4));\n            for (int i = 0; i < addEasy; i++) addTask(easy[i].second);\n\n            // Keep graph bounded.\n            if ((int)candTasks.size() > 130) {\n                sort(candTasks.begin(), candTasks.end(), [&](int a, int b) {\n                    return dynPriority[a] > dynPriority[b];\n                });\n                candTasks.resize(130);\n            }\n\n            int C = (int)candTasks.size();\n\n            int S = 0;\n            int memberOffset = 1;\n            int taskOffset = memberOffset + F;\n            int T = taskOffset + C;\n            int V = T + 1;\n\n            MinCostFlow mf(V);\n\n            for (int a = 0; a < F; a++) {\n                mf.addEdge(S, memberOffset + a, 1, 0);\n            }\n            for (int b = 0; b < C; b++) {\n                mf.addEdge(taskOffset + b, T, 1, 0);\n            }\n\n            const int SCALE = 1000;\n            const int OFFSET = 1000000;\n\n            double expPow = 0.91;\n            if (day < 120) expPow = 0.82;\n            else if (day < 300) expPow = 0.87;\n\n            for (int a = 0; a < F; a++) {\n                int j = freeMembers[a];\n\n                for (int b = 0; b < C; b++) {\n                    int t = candTasks[b];\n\n                    double est = estimate_duration(t, j);\n                    int cnt = observations[j].size();\n\n                    double uncertaintyPenalty = 0.0;\n                    if (cnt < 2) uncertaintyPenalty = 0.06 * est + 1.5;\n                    else if (cnt < 6) uncertaintyPenalty = 0.020 * est;\n\n                    double exploreBonus = 0.0;\n                    if (cnt < 5 && est <= 10.0) exploreBonus = 1.2;\n\n                    double throughputBonus = 0.0;\n                    if ((int)readyTasks.size() > 35) {\n                        throughputBonus = 2.5 / sqrt(est + 0.5);\n                    }\n\n                    double util =\n                        dynPriority[t] / pow(est + 1.0, expPow)\n                        - uncertaintyPenalty\n                        + exploreBonus\n                        + throughputBonus\n                        + 0.22 * crit[t]\n                        + 1.3 * immediateUnlock[t];\n\n                    int cost = OFFSET - (int)round(util * SCALE);\n                    if (cost < 0) cost = 0;\n\n                    mf.addEdge(memberOffset + a, taskOffset + b, 1, cost);\n                }\n            }\n\n            mf.flow(S, T, F);\n\n            for (int a = 0; a < F; a++) {\n                int node = memberOffset + a;\n                for (Edge &e : mf.g[node]) {\n                    if (e.to >= taskOffset && e.to < taskOffset + C && e.cap == 0) {\n                        int b = e.to - taskOffset;\n                        int j = freeMembers[a];\n                        int t = candTasks[b];\n                        assignments.push_back({j, t});\n                    }\n                }\n            }\n        }\n\n        for (auto [j, t] : assignments) {\n            status[t] = 0;\n            inReady[t] = 0;\n            memberTask[j] = t;\n            startDay[j] = day;\n        }\n\n        cout << assignments.size();\n        for (auto [j, t] : assignments) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        string line;\n        if (!getline(cin >> ws, line)) return 0;\n\n        stringstream ss(line);\n        int nfin;\n        ss >> nfin;\n\n        if (nfin == -1) {\n            return 0;\n        }\n\n        for (int z = 0; z < nfin; z++) {\n            int memberInput;\n            ss >> memberInput;\n            int j = memberInput - 1;\n\n            int t = memberTask[j];\n            if (t < 0) continue;\n\n            int duration = day - startDay[j] + 1;\n\n            status[t] = 1;\n            memberTask[j] = -1;\n            startDay[j] = -1;\n\n            observations[j].push_back({t, duration});\n            refit_member(j);\n            update_speed(j);\n\n            for (int v : tasks[t].nxt) {\n                remPre[v]--;\n                if (remPre[v] == 0 && status[v] == -1 && !inReady[v]) {\n                    readyList.push_back(v);\n                    inReady[v] = 1;\n                    readySince[v] = day + 1;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n};\n\nconst Point OFFICE{400, 400};\nvector<Order> ords(1000);\n\nstatic inline int mdist(const Point& p, const Point& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstatic inline int mdist_xy(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nstatic inline Point pickup_point(int id) {\n    return {ords[id].a, ords[id].b};\n}\n\nstatic inline Point delivery_point(int id) {\n    return {ords[id].c, ords[id].d};\n}\n\nint path_length_points(const vector<Point>& pts) {\n    int s = 0;\n    for (int i = 0; i + 1 < (int)pts.size(); i++) {\n        s += mdist(pts[i], pts[i + 1]);\n    }\n    return s;\n}\n\nvector<int> nearest_path(const vector<int>& ids, bool pickup, Point start) {\n    int n = ids.size();\n    vector<int> path;\n    path.reserve(n);\n    vector<char> used(n, false);\n\n    Point cur = start;\n\n    for (int step = 0; step < n; step++) {\n        int best = -1;\n        int bestd = INT_MAX;\n\n        for (int i = 0; i < n; i++) {\n            if (used[i]) continue;\n\n            Point p = pickup ? pickup_point(ids[i]) : delivery_point(ids[i]);\n            int d = mdist(cur, p);\n\n            if (d < bestd) {\n                bestd = d;\n                best = i;\n            }\n        }\n\n        used[best] = true;\n        path.push_back(ids[best]);\n        cur = pickup ? pickup_point(ids[best]) : delivery_point(ids[best]);\n    }\n\n    return path;\n}\n\nvoid two_opt(vector<int>& path, bool pickup, Point start, Point goal) {\n    int n = path.size();\n    if (n <= 2) return;\n\n    auto getp = [&](int idx) -> Point {\n        if (idx == -1) return start;\n        if (idx == n) return goal;\n        return pickup ? pickup_point(path[idx]) : delivery_point(path[idx]);\n    };\n\n    bool improved = true;\n    int loop = 0;\n\n    while (improved && loop < 30) {\n        improved = false;\n        loop++;\n\n        for (int i = 0; i < n - 1; i++) {\n            Point A = getp(i - 1);\n            Point B = getp(i);\n\n            for (int k = i + 1; k < n; k++) {\n                Point C = getp(k);\n                Point D = getp(k + 1);\n\n                int before = mdist(A, B) + mdist(C, D);\n                int after = mdist(A, C) + mdist(B, D);\n\n                if (after < before) {\n                    reverse(path.begin() + i, path.begin() + k + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    vector<int> ids;\n    vector<int> pickups;\n    vector<int> deliveries;\n    vector<Point> route;\n    int cost;\n};\n\nSolution build_solution(vector<int> ids) {\n    Solution sol;\n    sol.ids = ids;\n\n    sol.pickups = nearest_path(ids, true, OFFICE);\n\n    Point after_pickups = OFFICE;\n    if (!sol.pickups.empty()) {\n        after_pickups = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_path(ids, false, after_pickups);\n\n    Point first_del = sol.deliveries.empty() ? OFFICE : delivery_point(sol.deliveries.front());\n\n    two_opt(sol.pickups, true, OFFICE, first_del);\n\n    after_pickups = OFFICE;\n    if (!sol.pickups.empty()) {\n        after_pickups = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_path(ids, false, after_pickups);\n    two_opt(sol.deliveries, false, after_pickups, OFFICE);\n\n    sol.route.clear();\n    sol.route.reserve(102);\n    sol.route.push_back(OFFICE);\n\n    for (int id : sol.pickups) sol.route.push_back(pickup_point(id));\n    for (int id : sol.deliveries) sol.route.push_back(delivery_point(id));\n\n    sol.route.push_back(OFFICE);\n    sol.cost = path_length_points(sol.route);\n\n    return sol;\n}\n\nvector<int> top50_by(function<int(int)> scorer) {\n    vector<pair<int, int>> v;\n    v.reserve(1000);\n    for (int i = 0; i < 1000; i++) v.push_back({scorer(i), i});\n    sort(v.begin(), v.end());\n\n    vector<int> ids;\n    ids.reserve(50);\n    for (int i = 0; i < 50; i++) ids.push_back(v[i].second);\n    return ids;\n}\n\nvector<int> topK_by(function<int(int)> scorer, int K) {\n    vector<pair<int, int>> v;\n    v.reserve(1000);\n    for (int i = 0; i < 1000; i++) v.push_back({scorer(i), i});\n    sort(v.begin(), v.end());\n\n    vector<int> ids;\n    ids.reserve(K);\n    for (int i = 0; i < K; i++) ids.push_back(v[i].second);\n    return ids;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 1000; i++) {\n        cin >> ords[i].a >> ords[i].b >> ords[i].c >> ords[i].d;\n    }\n\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> dPick(1000), dDel(1000), dDirect(1000), dRound(1000), dCenter(1000), dMax(1000);\n\n    for (int i = 0; i < 1000; i++) {\n        Point A = pickup_point(i);\n        Point B = delivery_point(i);\n\n        dPick[i] = mdist(OFFICE, A);\n        dDel[i] = mdist(OFFICE, B);\n        dDirect[i] = mdist(A, B);\n        dRound[i] = dPick[i] + dDirect[i] + dDel[i];\n        dCenter[i] = dPick[i] + dDel[i];\n        dMax[i] = max(dPick[i], dDel[i]);\n    }\n\n    auto score_round = [&](int i) {\n        return dRound[i];\n    };\n\n    auto score_center = [&](int i) {\n        return dCenter[i];\n    };\n\n    auto score_pick = [&](int i) {\n        return dPick[i];\n    };\n\n    auto score_del = [&](int i) {\n        return dDel[i];\n    };\n\n    auto score_max_direct = [&](int i) {\n        return dMax[i] * 2 + dDirect[i];\n    };\n\n    vector<vector<int>> initials;\n    initials.push_back(top50_by(score_round));\n    initials.push_back(top50_by(score_center));\n    initials.push_back(top50_by(score_pick));\n    initials.push_back(top50_by(score_del));\n    initials.push_back(top50_by(score_max_direct));\n\n    Solution best;\n    best.cost = INT_MAX;\n\n    for (auto ids : initials) {\n        Solution sol = build_solution(ids);\n        if (sol.cost < best.cost) best = sol;\n    }\n\n    vector<int> pool;\n    vector<char> in_pool(1000, false);\n\n    auto add_pool = [&](vector<int> v) {\n        for (int id : v) {\n            if (!in_pool[id]) {\n                in_pool[id] = true;\n                pool.push_back(id);\n            }\n        }\n    };\n\n    add_pool(topK_by(score_round, 180));\n    add_pool(topK_by(score_center, 180));\n    add_pool(topK_by(score_max_direct, 180));\n\n    // Keep pool bounded and stable by round score.\n    sort(pool.begin(), pool.end(), [&](int x, int y) {\n        if (dRound[x] != dRound[y]) return dRound[x] < dRound[y];\n        return x < y;\n    });\n\n    if ((int)pool.size() > 260) pool.resize(260);\n\n    mt19937 rng(1234567);\n\n    Solution cur = best;\n    vector<int> cur_ids = cur.ids;\n\n    while (true) {\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        vector<int> next_ids = cur_ids;\n        unordered_set<int> selected(next_ids.begin(), next_ids.end());\n\n        int remove_pos = uniform_int_distribution<int>(0, 49)(rng);\n\n        vector<int> candidates;\n        candidates.reserve(pool.size());\n        for (int id : pool) {\n            if (!selected.count(id)) candidates.push_back(id);\n        }\n        if (candidates.empty()) continue;\n\n        int add_id = candidates[uniform_int_distribution<int>(0, (int)candidates.size() - 1)(rng)];\n        next_ids[remove_pos] = add_id;\n\n        sort(next_ids.begin(), next_ids.end());\n        next_ids.erase(unique(next_ids.begin(), next_ids.end()), next_ids.end());\n        if ((int)next_ids.size() != 50) continue;\n\n        Solution nxt = build_solution(next_ids);\n\n        int diff = nxt.cost - cur.cost;\n        double temp = 40.0 * (1.85 - elapsed) / 1.85 + 1.0;\n\n        bool accept = false;\n        if (diff < 0) accept = true;\n        else {\n            double prob = exp(-diff / temp);\n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur = nxt;\n            cur_ids = next_ids;\n        }\n\n        if (nxt.cost < best.cost) {\n            best = nxt;\n        }\n    }\n\n    cout << 50;\n    for (int id : best.ids) {\n        cout << ' ' << id + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (auto& p : best.route) {\n        cout << ' ' << p.x << ' ' << p.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n\n    DSU(int n = 0) {\n        init(n);\n    }\n\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct KEdge {\n    int w;\n    int id;\n\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return id < other.id;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n\n        long long dx = x[edges[i].u] - x[edges[i].v];\n        long long dy = y[edges[i].u] - y[edges[i].v];\n\n        edges[i].d = (int)llround(sqrt((double)(dx * dx + dy * dy)));\n        edges[i].d = max(edges[i].d, 1);\n    }\n\n    DSU accepted(N);\n    vector<int> actual(M, -1);\n\n    double coef = 1.92;\n\n    auto in_predicted_mst = [&](int cur, double base_coef) -> bool {\n        vector<KEdge> order;\n        order.reserve(M);\n\n        double progress = (double)cur / M;\n\n        for (int j = 0; j < M; j++) {\n            int w;\n\n            if (j <= cur) {\n                w = actual[j];\n            } else {\n                double t = (double)(j - cur) / max(1, M - cur);\n\n                double c = base_coef;\n                c += 0.08 * t;\n                c += 0.05 * max(0.0, progress - 0.75);\n\n                w = max(1, (int)round(c * edges[j].d));\n            }\n\n            order.push_back({w, j});\n        }\n\n        sort(order.begin(), order.end());\n\n        DSU tmp(N);\n\n        for (auto [w, id] : order) {\n            if (tmp.unite(edges[id].u, edges[id].v)) {\n                if (id == cur) return true;\n            }\n        }\n\n        return false;\n    };\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        actual[i] = l;\n\n        bool take = false;\n\n        int ru = accepted.find(edges[i].u);\n        int rv = accepted.find(edges[i].v);\n\n        if (ru != rv) {\n            int comps = 0;\n            for (int v = 0; v < N; v++) {\n                if (accepted.find(v) == v) comps++;\n            }\n\n            // Safety check: current edge is a bridge among accepted-components\n            // using only current/future edges.\n            {\n                unordered_map<int, int> mp;\n                mp.reserve(N * 2);\n\n                for (int v = 0; v < N; v++) {\n                    int r = accepted.find(v);\n                    if (!mp.count(r)) {\n                        int id = (int)mp.size();\n                        mp[r] = id;\n                    }\n                }\n\n                int C = (int)mp.size();\n                vector<vector<pair<int, int>>> g(C);\n\n                for (int j = i; j < M; j++) {\n                    int a = mp[accepted.find(edges[j].u)];\n                    int b = mp[accepted.find(edges[j].v)];\n                    if (a == b) continue;\n\n                    g[a].push_back({b, j});\n                    g[b].push_back({a, j});\n                }\n\n                vector<int> tin(C, -1), low(C, -1);\n                int timer = 0;\n                bool is_bridge = false;\n\n                function<void(int, int)> dfs = [&](int v, int pe) {\n                    tin[v] = low[v] = timer++;\n\n                    for (auto [to, eid] : g[v]) {\n                        if (eid == pe) continue;\n\n                        if (tin[to] != -1) {\n                            low[v] = min(low[v], tin[to]);\n                        } else {\n                            dfs(to, eid);\n                            low[v] = min(low[v], low[to]);\n\n                            if (eid == i && low[to] > tin[v]) {\n                                is_bridge = true;\n                            }\n                        }\n                    }\n                };\n\n                for (int v = 0; v < C; v++) {\n                    if (tin[v] == -1) {\n                        dfs(v, -1);\n                    }\n                }\n\n                if (is_bridge) {\n                    take = true;\n                }\n            }\n\n            if (!take) {\n                double ratio = (double)l / edges[i].d;\n                double progress = (double)i / M;\n\n                int hit = 0;\n                int trials = 0;\n\n                auto test = [&](double c) {\n                    trials++;\n                    if (in_predicted_mst(i, c)) hit++;\n                };\n\n                test(coef - 0.06);\n                test(coef);\n                test(coef + 0.06);\n\n                // Small extra robustness late in the stream.\n                if (progress > 0.50) {\n                    test(coef - 0.10);\n                    test(coef + 0.10);\n                }\n\n                if (hit > 0) {\n                    double limit = 2.18 - 0.28 * progress;\n\n                    if (comps > 80) limit += 0.10;\n                    if (comps < 30) limit -= 0.10;\n\n                    // Normalize hit bonus by number of trials.\n                    double hrate = (double)hit / trials;\n                    if (hrate >= 0.80) limit += 0.05;\n                    else if (hrate <= 0.34) limit -= 0.03;\n\n                    if (progress > 0.80) limit -= 0.03;\n\n                    if (ratio <= limit || i > M - 420) {\n                        take = true;\n                    }\n                }\n            }\n\n            // Endgame fallback.\n            if (!take) {\n                int remaining = M - i;\n                if (remaining <= comps * 2) {\n                    take = true;\n                }\n            }\n        }\n\n        if (take) {\n            accepted.unite(edges[i].u, edges[i].v);\n            cout << 1 << '\\n';\n        } else {\n            cout << 0 << '\\n';\n        }\n\n        cout.flush();\n\n        if (i > 0 && i % 100 == 0) {\n            double sum = 0.0;\n\n            for (int j = 0; j <= i; j++) {\n                sum += (double)actual[j] / edges[j].d;\n            }\n\n            double avg = sum / (i + 1);\n            coef = 0.75 * coef + 0.25 * avg;\n            coef = min(2.08, max(1.78, coef));\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstruct Task {\n    int bx, by;\n    int hx, hy;\n    char build;\n};\n\nstruct Room {\n    int id;\n    int sz;\n    int x1, x2, y1, y2;\n    vector<Task> tasks;\n    vector<Pos> standby;\n};\n\nconst int H = 30, W = 30, TURNS = 300;\nint N, M;\nvector<Pos> pet, human_pos;\nvector<int> pet_type;\nbool wall[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar mvC[4] = {'U', 'D', 'L', 'R'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\nint dirIndex(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    if (c == 'R') return 3;\n    return -1;\n}\n\nint buildDirIndex(char c) {\n    if (c == 'u') return 0;\n    if (c == 'd') return 1;\n    if (c == 'l') return 2;\n    if (c == 'r') return 3;\n    return -1;\n}\n\nbool hasPet(int x, int y) {\n    for (auto &p : pet) {\n        if (p.x == x && p.y == y) return true;\n    }\n    return false;\n}\n\nbool hasHuman(int x, int y) {\n    for (auto &h : human_pos) {\n        if (h.x == x && h.y == y) return true;\n    }\n    return false;\n}\n\nbool canBuildCell(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (wall[x][y]) return true;\n    if (hasPet(x, y) || hasHuman(x, y)) return false;\n\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (inside(nx, ny) && hasPet(nx, ny)) return false;\n    }\n\n    return true;\n}\n\nbool inRect(Pos p, int x1, int x2, int y1, int y2) {\n    return x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2;\n}\n\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nchar stepToward(Pos cur, Pos goal, const bool reserved[31][31]) {\n    int bestd = INT_MAX;\n    char best = '.';\n\n    for (int d = 0; d < 4; d++) {\n        int nx = cur.x + dx[d];\n        int ny = cur.y + dy[d];\n\n        if (!inside(nx, ny)) continue;\n        if (wall[nx][ny]) continue;\n        if (reserved[nx][ny]) continue;\n\n        int md = abs(nx - goal.x) + abs(ny - goal.y);\n\n        if (md < bestd) {\n            bestd = md;\n            best = mvC[d];\n        }\n    }\n\n    return best;\n}\n\nvoid applyHumanActions(const string &ans) {\n    vector<Pos> newh = human_pos;\n    vector<pair<int, int>> builds;\n\n    for (int i = 0; i < M; i++) {\n        int d = buildDirIndex(ans[i]);\n\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d];\n            int ny = human_pos[i].y + dy[d];\n\n            if (inside(nx, ny) && canBuildCell(nx, ny)) {\n                builds.push_back({nx, ny});\n            }\n        }\n    }\n\n    for (auto &b : builds) {\n        wall[b.first][b.second] = true;\n    }\n\n    for (int i = 0; i < M; i++) {\n        int d = dirIndex(ans[i]);\n\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d];\n            int ny = human_pos[i].y + dy[d];\n\n            if (inside(nx, ny) && !wall[nx][ny]) {\n                newh[i] = {nx, ny};\n            }\n        }\n    }\n\n    human_pos = newh;\n}\n\nvoid applyPetMoves(const vector<string> &moves) {\n    for (int i = 0; i < N; i++) {\n        for (char c : moves[i]) {\n            int d = dirIndex(c);\n\n            if (d >= 0) {\n                int nx = pet[i].x + dx[d];\n                int ny = pet[i].y + dy[d];\n\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pet[i] = {nx, ny};\n                }\n            }\n        }\n    }\n}\n\nRoom makeRoom(int id, int sz) {\n    Room r;\n    r.id = id;\n    r.sz = sz;\n\n    if (id == 0) {\n        r.x1 = 1; r.x2 = sz; r.y1 = 1; r.y2 = sz;\n\n        for (int y = 1; y <= sz; y++) r.tasks.push_back({sz + 1, y, sz, y, 'd'});\n        for (int x = 1; x <= sz; x++) r.tasks.push_back({x, sz + 1, x, sz, 'r'});\n\n        for (int x = 2; x <= sz - 1; x++) {\n            for (int y = 2; y <= sz - 1; y++) r.standby.push_back({x, y});\n        }\n    } else if (id == 1) {\n        r.x1 = 1; r.x2 = sz; r.y1 = 31 - sz; r.y2 = 30;\n\n        for (int y = 31 - sz; y <= 30; y++) r.tasks.push_back({sz + 1, y, sz, y, 'd'});\n        for (int x = 1; x <= sz; x++) r.tasks.push_back({x, 30 - sz, x, 31 - sz, 'l'});\n\n        for (int x = 2; x <= sz - 1; x++) {\n            for (int y = 32 - sz; y <= 29; y++) r.standby.push_back({x, y});\n        }\n    } else if (id == 2) {\n        r.x1 = 31 - sz; r.x2 = 30; r.y1 = 1; r.y2 = sz;\n\n        for (int y = 1; y <= sz; y++) r.tasks.push_back({30 - sz, y, 31 - sz, y, 'u'});\n        for (int x = 31 - sz; x <= 30; x++) r.tasks.push_back({x, sz + 1, x, sz, 'r'});\n\n        for (int x = 32 - sz; x <= 29; x++) {\n            for (int y = 2; y <= sz - 1; y++) r.standby.push_back({x, y});\n        }\n    } else {\n        r.x1 = 31 - sz; r.x2 = 30; r.y1 = 31 - sz; r.y2 = 30;\n\n        for (int y = 31 - sz; y <= 30; y++) r.tasks.push_back({30 - sz, y, 31 - sz, y, 'u'});\n        for (int x = 31 - sz; x <= 30; x++) r.tasks.push_back({x, 30 - sz, x, 31 - sz, 'l'});\n\n        for (int x = 32 - sz; x <= 29; x++) {\n            for (int y = 32 - sz; y <= 29; y++) r.standby.push_back({x, y});\n        }\n    }\n\n    if (r.standby.empty()) {\n        r.standby.push_back({(r.x1 + r.x2) / 2, (r.y1 + r.y2) / 2});\n    }\n\n    return r;\n}\n\nstruct Eval {\n    long long risk;\n    int petsInside;\n    int petsNear;\n    long long travel;\n};\n\nEval evalRoom(const Room &r) {\n    int petsInside = 0;\n    int petsNear = 0;\n    int petsBoundaryNear = 0;\n\n    for (auto &p : pet) {\n        if (inRect(p, r.x1, r.x2, r.y1, r.y2)) petsInside++;\n\n        if (r.x1 - 2 <= p.x && p.x <= r.x2 + 2 &&\n            r.y1 - 2 <= p.y && p.y <= r.y2 + 2) {\n            petsNear++;\n        }\n\n        for (auto &t : r.tasks) {\n            if (manhattan(p, {t.bx, t.by}) <= 2) {\n                petsBoundaryNear++;\n                break;\n            }\n        }\n    }\n\n    Pos center{(r.x1 + r.x2) / 2, (r.y1 + r.y2) / 2};\n    long long travel = 0;\n\n    for (auto &h : human_pos) {\n        travel += manhattan(h, center);\n    }\n\n    // Comparable risk value. Lower is better.\n    long long risk = 0;\n    risk += 10000000LL * petsInside;\n    risk += 700000LL * petsNear;\n    risk += 350000LL * petsBoundaryNear;\n    risk += 20000LL * travel;\n\n    return {risk, petsInside, petsNear, travel};\n}\n\nbool actionLegalNow(int i, char c, const bool reserved[31][31]) {\n    if (c == '.') return true;\n\n    int md = dirIndex(c);\n    if (md >= 0) {\n        int nx = human_pos[i].x + dx[md];\n        int ny = human_pos[i].y + dy[md];\n\n        return inside(nx, ny) && !wall[nx][ny] && !reserved[nx][ny];\n    }\n\n    int bd = buildDirIndex(c);\n    if (bd >= 0) {\n        int bx = human_pos[i].x + dx[bd];\n        int by = human_pos[i].y + dy[bd];\n\n        return inside(bx, by) && canBuildCell(bx, by);\n    }\n\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pet.resize(N);\n    pet_type.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> pet[i].x >> pet[i].y >> pet_type[i];\n    }\n\n    cin >> M;\n    human_pos.resize(M);\n\n    for (int i = 0; i < M; i++) {\n        cin >> human_pos[i].x >> human_pos[i].y;\n    }\n\n    memset(wall, 0, sizeof(wall));\n\n    vector<Room> rooms8, rooms9;\n\n    for (int id = 0; id < 4; id++) {\n        rooms8.push_back(makeRoom(id, 8));\n        rooms9.push_back(makeRoom(id, 9));\n    }\n\n    Room best8 = rooms8[0];\n    Eval best8Eval = evalRoom(best8);\n\n    for (auto &r : rooms8) {\n        Eval e = evalRoom(r);\n        if (e.risk < best8Eval.risk) {\n            best8Eval = e;\n            best8 = r;\n        }\n    }\n\n    Room best9 = rooms9[0];\n    Eval best9Eval = evalRoom(best9);\n\n    for (auto &r : rooms9) {\n        Eval e = evalRoom(r);\n        if (e.risk < best9Eval.risk) {\n            best9Eval = e;\n            best9 = r;\n        }\n    }\n\n    Room room = best8;\n\n    // Use 9x9 only when it looks at least as safe.\n    // This conservative condition avoids most failures from larger rooms.\n    if (best9Eval.petsInside == 0 &&\n        best9Eval.petsNear <= best8Eval.petsNear &&\n        best9Eval.risk <= best8Eval.risk + 500000LL) {\n        room = best9;\n    }\n\n    vector<Pos> home(M);\n\n    for (int i = 0; i < M; i++) {\n        home[i] = room.standby[i % room.standby.size()];\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        string ans(M, '.');\n\n        bool reserved[31][31];\n        memset(reserved, 0, sizeof(reserved));\n\n        vector<int> usedTask(room.tasks.size(), 0);\n\n        // Build first and reserve new wall cells.\n        for (int i = 0; i < M; i++) {\n            Pos cur = human_pos[i];\n\n            int best = -1;\n\n            for (int k = 0; k < (int)room.tasks.size(); k++) {\n                if (usedTask[k]) continue;\n\n                Task &t = room.tasks[k];\n\n                if (wall[t.bx][t.by]) continue;\n                if (reserved[t.bx][t.by]) continue;\n\n                if (cur.x == t.hx && cur.y == t.hy && canBuildCell(t.bx, t.by)) {\n                    best = k;\n                    break;\n                }\n            }\n\n            if (best != -1) {\n                Task &t = room.tasks[best];\n                ans[i] = t.build;\n                usedTask[best] = 1;\n                reserved[t.bx][t.by] = true;\n            }\n        }\n\n        // Move toward nearest unfinished task.\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n\n            Pos cur = human_pos[i];\n\n            int best = -1;\n            int bestDist = INT_MAX;\n\n            for (int k = 0; k < (int)room.tasks.size(); k++) {\n                Task &t = room.tasks[k];\n\n                if (wall[t.bx][t.by]) continue;\n                if (reserved[t.hx][t.hy]) continue;\n\n                int d = manhattan(cur, {t.hx, t.hy});\n\n                if (!canBuildCell(t.bx, t.by)) d += 4;\n\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = k;\n                }\n            }\n\n            Pos goal;\n\n            if (best != -1) {\n                goal = {room.tasks[best].hx, room.tasks[best].hy};\n            } else {\n                goal = home[i];\n            }\n\n            if (cur.x != goal.x || cur.y != goal.y) {\n                char c = stepToward(cur, goal, reserved);\n                if (c != '.') ans[i] = c;\n            }\n        }\n\n        // Final legality filter.\n        for (int i = 0; i < M; i++) {\n            if (!actionLegalNow(i, ans[i], reserved)) {\n                ans[i] = '.';\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n\n        vector<string> pm(N);\n\n        for (int i = 0; i < N; i++) {\n            cin >> pm[i];\n        }\n\n        applyPetMoves(pm);\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int V = 400;\nstatic constexpr int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble pforget;\n\nstring hwall[N];\nstring vwall[N - 1];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\nint nxt[V][4];\nint distT[V];\nint distS[V];\n\nmt19937 rng;\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\nint dirId(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\nbool canMove(int i, int j, int d) {\n    if (d == 0) {\n        if (i == 0) return false;\n        return vwall[i - 1][j] == '0';\n    }\n    if (d == 1) {\n        if (i == N - 1) return false;\n        return vwall[i][j] == '0';\n    }\n    if (d == 2) {\n        if (j == 0) return false;\n        return hwall[i][j - 1] == '0';\n    }\n    if (d == 3) {\n        if (j == N - 1) return false;\n        return hwall[i][j] == '0';\n    }\n    return false;\n}\n\nvoid buildGraph() {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int v = id(i, j);\n            for (int d = 0; d < 4; d++) {\n                if (canMove(i, j, d)) nxt[v][d] = id(i + di[d], j + dj[d]);\n                else nxt[v][d] = v;\n            }\n        }\n    }\n}\n\nvoid bfsFrom(int src, int dist[V]) {\n    fill(dist, dist + V, 1e9);\n    queue<int> q;\n    dist[src] = 0;\n    q.push(src);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (dist[u] > dist[v] + 1) {\n                dist[u] = dist[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n}\n\nstring shortestPath(int s, int t, bool randomTie = false) {\n    vector<int> pre(V, -1), pred(V, -1);\n    queue<int> q;\n    pre[s] = s;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        if (v == t) break;\n\n        array<int, 4> ord = {0, 1, 2, 3};\n        if (randomTie) shuffle(ord.begin(), ord.end(), rng);\n\n        for (int d : ord) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n\n            if (pre[u] == -1) {\n                pre[u] = v;\n                pred[u] = d;\n                q.push(u);\n            }\n        }\n    }\n\n    if (pre[t] == -1) return \"\";\n\n    string res;\n    int cur = t;\n\n    while (cur != s) {\n        int d = pred[cur];\n        res.push_back(dc[d]);\n        cur = pre[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\ndouble evaluate(const string& route) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    static double prob[V], np[V];\n    fill(prob, prob + V, 0.0);\n    prob[s] = 1.0;\n\n    double expected = 0.0;\n    const double q = 1.0 - pforget;\n\n    for (int step = 0; step < (int)route.size(); step++) {\n        int d = dirId(route[step]);\n\n        fill(np, np + V, 0.0);\n\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * q;\n        }\n\n        double reach = np[t];\n\n        if (reach > 0.0) {\n            expected += reach * (401.0 - (step + 1));\n            np[t] = 0.0;\n        }\n\n        memcpy(prob, np, sizeof(prob));\n    }\n\n    return expected;\n}\n\narray<double, V> finalDistribution(const string& route) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    array<double, V> prob{}, np{};\n    prob.fill(0.0);\n    prob[s] = 1.0;\n\n    const double q = 1.0 - pforget;\n\n    for (char c : route) {\n        int d = dirId(c);\n        np.fill(0.0);\n\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * q;\n        }\n\n        np[t] = 0.0;\n        prob = np;\n    }\n\n    return prob;\n}\n\nstring repeatChars(const string& base, int r) {\n    string res;\n\n    for (char c : base) {\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring repeatWhole(const string& base) {\n    string res;\n    if (base.empty()) return res;\n\n    while ((int)res.size() < MAXL) {\n        for (char c : base) {\n            if ((int)res.size() >= MAXL) break;\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring noisyRepeatPath(const string& base) {\n    string res;\n    if (base.empty()) return res;\n\n    double mean = 1.0 / (1.0 - pforget);\n\n    for (char c : base) {\n        double noise = uniform_real_distribution<double>(-0.8, 1.8)(rng);\n        int r = max(1, (int)round(mean + noise));\n        r = min(r, 8);\n\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring stochasticExpandedPath(const string& base) {\n    string res;\n    if (base.empty()) return res;\n\n    double mean = 1.0 / (1.0 - pforget);\n    int ceilMean = max(1, (int)ceil(mean));\n\n    for (char c : base) {\n        int r;\n        int x = rng() % 100;\n\n        if (x < 20) r = 1;\n        else if (x < 70) r = ceilMean;\n        else if (x < 92) r = ceilMean + 1;\n        else r = ceilMean + 2;\n\n        r = min(r, 8);\n\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring deterministicDistRoute(int repeatBias, int lenLimit = MAXL) {\n    int cur = id(si_, sj_);\n    int t = id(ti_, tj_);\n    string route;\n\n    while ((int)route.size() < lenLimit && cur != t) {\n        int bd = -1;\n        int best = 1e9;\n\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[cur][d];\n\n            if (u != cur && distT[u] < best) {\n                best = distT[u];\n                bd = d;\n            }\n        }\n\n        if (bd == -1) break;\n\n        for (int k = 0; k < repeatBias && (int)route.size() < lenLimit; k++) {\n            route.push_back(dc[bd]);\n        }\n\n        cur = nxt[cur][bd];\n    }\n\n    return route;\n}\n\nstring greedyDistribution(double temperature, double stayPenalty, double reachBonus, int lenLimit = MAXL) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<double> prob(V, 0.0), np(V, 0.0);\n    prob[s] = 1.0;\n\n    string route;\n\n    for (int step = 0; step < lenLimit; step++) {\n        double bestScore = 1e100;\n        vector<int> bestDirs;\n\n        for (int d = 0; d < 4; d++) {\n            fill(np.begin(), np.end(), 0.0);\n\n            for (int v = 0; v < V; v++) {\n                double pr = prob[v];\n                if (pr == 0.0) continue;\n\n                np[v] += pr * pforget;\n                np[nxt[v][d]] += pr * (1.0 - pforget);\n            }\n\n            double score = 0.0;\n\n            for (int v = 0; v < V; v++) {\n                double pr = np[v];\n                if (pr == 0.0) continue;\n\n                if (v == t) {\n                    score -= reachBonus * pr * (MAXL - step);\n                    continue;\n                }\n\n                score += pr * distT[v];\n\n                if (nxt[v][d] == v) {\n                    score += stayPenalty * pr;\n                }\n            }\n\n            if (temperature > 0.0) {\n                score += uniform_real_distribution<double>(-temperature, temperature)(rng);\n            }\n\n            if (score + 1e-12 < bestScore) {\n                bestScore = score;\n                bestDirs.clear();\n                bestDirs.push_back(d);\n            } else if (abs(score - bestScore) < 1e-12) {\n                bestDirs.push_back(d);\n            }\n        }\n\n        int d = bestDirs[rng() % bestDirs.size()];\n        route.push_back(dc[d]);\n\n        fill(np.begin(), np.end(), 0.0);\n\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * (1.0 - pforget);\n        }\n\n        np[t] = 0.0;\n        prob.swap(np);\n\n        double alive = accumulate(prob.begin(), prob.end(), 0.0);\n        if (alive < 1e-12) break;\n    }\n\n    return route;\n}\n\nstruct BeamNode {\n    string route;\n    array<double, V> prob;\n    double heuristic;\n};\n\nstring beamSearchRoute(int beamWidth, int lenLimit, double reachWeight, double distWeight) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<BeamNode> beam;\n    BeamNode init;\n    init.route.clear();\n    init.prob.fill(0.0);\n    init.prob[s] = 1.0;\n    init.heuristic = 0.0;\n    beam.push_back(init);\n\n    for (int step = 0; step < lenLimit; step++) {\n        vector<BeamNode> nb;\n        nb.reserve(beam.size() * 4);\n\n        for (const auto& node : beam) {\n            for (int d = 0; d < 4; d++) {\n                BeamNode x;\n                x.route = node.route;\n                x.route.push_back(dc[d]);\n                x.prob.fill(0.0);\n\n                for (int v = 0; v < V; v++) {\n                    double pr = node.prob[v];\n                    if (pr == 0.0) continue;\n\n                    x.prob[v] += pr * pforget;\n                    x.prob[nxt[v][d]] += pr * (1.0 - pforget);\n                }\n\n                double reached = x.prob[t];\n                x.prob[t] = 0.0;\n\n                double alive = 0.0;\n                double dsum = 0.0;\n\n                for (int v = 0; v < V; v++) {\n                    alive += x.prob[v];\n                    dsum += x.prob[v] * distT[v];\n                }\n\n                x.heuristic = node.heuristic\n                            + reached * reachWeight * (401.0 - (step + 1))\n                            - dsum * distWeight\n                            - alive * 0.02;\n\n                nb.push_back(move(x));\n            }\n        }\n\n        sort(nb.begin(), nb.end(), [](const BeamNode& a, const BeamNode& b) {\n            return a.heuristic > b.heuristic;\n        });\n\n        if ((int)nb.size() > beamWidth) nb.resize(beamWidth);\n        beam.swap(nb);\n    }\n\n    string best;\n    double bestVal = -1.0;\n\n    for (auto& node : beam) {\n        double val = evaluate(node.route);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = node.route;\n        }\n    }\n\n    return best;\n}\n\nchar randomBiasedChar() {\n    int x = rng() % 100;\n    if (x < 38) return 'D';\n    if (x < 76) return 'R';\n    if (x < 88) return 'U';\n    return 'L';\n}\n\nstring suffixAppendRepair(const string& base) {\n    if (base.empty()) return base;\n    if ((int)base.size() >= MAXL) return base;\n\n    auto prob = finalDistribution(base);\n\n    int bestCell = -1;\n    double bestPr = 0.0;\n\n    for (int v = 0; v < V; v++) {\n        if (prob[v] > bestPr) {\n            bestPr = prob[v];\n            bestCell = v;\n        }\n    }\n\n    if (bestCell == -1 || bestPr < 1e-12) return base;\n\n    string tail = shortestPath(bestCell, id(ti_, tj_), true);\n    string res = base;\n\n    for (char c : tail) {\n        if ((int)res.size() >= MAXL) break;\n        int rep = 1 + rng() % 3;\n        for (int k = 0; k < rep && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring mutateString(string s, int strength) {\n    if (s.empty()) s = string(1, randomBiasedChar());\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n\n    int ops = 1 + (rng() % max(1, strength));\n\n    for (int op = 0; op < ops; op++) {\n        if (s.empty()) {\n            s.push_back(randomBiasedChar());\n            continue;\n        }\n\n        int n = (int)s.size();\n        int type = rng() % 7;\n\n        if (type == 0) {\n            int pos = rng() % n;\n            s[pos] = dc[rng() % 4];\n        } else if (type == 1) {\n            if ((int)s.size() < MAXL) {\n                int pos = rng() % ((int)s.size() + 1);\n                s.insert(s.begin() + pos, randomBiasedChar());\n            }\n        } else if (type == 2) {\n            if ((int)s.size() > 1) {\n                int pos = rng() % (int)s.size();\n                s.erase(s.begin() + pos);\n            }\n        } else if (type == 3) {\n            int pos = rng() % (int)s.size();\n            int avail = (int)s.size() - pos;\n            if (avail > 0) {\n                int len = 1 + rng() % min(8, avail);\n                for (int k = 0; k < len; k++) {\n                    s[pos + k] = randomBiasedChar();\n                }\n            }\n        } else if (type == 4) {\n            if ((int)s.size() < MAXL) {\n                int pos = rng() % (int)s.size();\n                int avail = (int)s.size() - pos;\n                if (avail > 0) {\n                    int len = 1 + rng() % min(6, avail);\n                    string seg = s.substr(pos, len);\n                    int ipos = rng() % ((int)s.size() + 1);\n                    s.insert(ipos, seg);\n                    if ((int)s.size() > MAXL) s.resize(MAXL);\n                }\n            }\n        } else if (type == 5) {\n            if ((int)s.size() >= 2) {\n                int l = rng() % (int)s.size();\n                int maxLen = min(8, (int)s.size() - l);\n                if (maxLen >= 2) {\n                    int len = 2 + rng() % (maxLen - 1);\n                    reverse(s.begin() + l, s.begin() + l + len);\n                }\n            }\n        } else {\n            if ((int)s.size() >= 2) {\n                int pos = rng() % ((int)s.size() - 1);\n                swap(s[pos], s[pos + 1]);\n            }\n        }\n\n        if ((int)s.size() > MAXL) s.resize(MAXL);\n        if (s.empty()) s.push_back(randomBiasedChar());\n    }\n\n    return s;\n}\n\nvoid deterministicSingleCharImprove(string& best, double& bestVal, chrono::steady_clock::time_point endTime) {\n    bool improved = true;\n\n    while (improved && chrono::steady_clock::now() < endTime) {\n        improved = false;\n\n        vector<int> positions(best.size());\n        iota(positions.begin(), positions.end(), 0);\n        shuffle(positions.begin(), positions.end(), rng);\n\n        for (int pos : positions) {\n            if (chrono::steady_clock::now() >= endTime) break;\n\n            char old = best[pos];\n            char bestChar = old;\n            double localBest = bestVal;\n\n            for (char c : {'U', 'D', 'L', 'R'}) {\n                if (c == old) continue;\n\n                string cand = best;\n                cand[pos] = c;\n\n                double val = evaluate(cand);\n\n                if (val > localBest) {\n                    localBest = val;\n                    bestChar = c;\n                }\n            }\n\n            if (bestChar != old) {\n                best[pos] = bestChar;\n                bestVal = localBest;\n                improved = true;\n            }\n        }\n    }\n}\n\nvoid deterministicSwapImprove(string& best, double& bestVal, chrono::steady_clock::time_point endTime) {\n    if (best.size() < 2) return;\n\n    bool improved = true;\n\n    while (improved && chrono::steady_clock::now() < endTime) {\n        improved = false;\n\n        vector<int> positions(best.size() - 1);\n        iota(positions.begin(), positions.end(), 0);\n        shuffle(positions.begin(), positions.end(), rng);\n\n        for (int pos : positions) {\n            if (chrono::steady_clock::now() >= endTime) break;\n            if (best[pos] == best[pos + 1]) continue;\n\n            string cand = best;\n            swap(cand[pos], cand[pos + 1]);\n\n            double val = evaluate(cand);\n\n            if (val > bestVal) {\n                bestVal = val;\n                best = cand;\n                improved = true;\n            }\n        }\n    }\n}\n\nvoid addCandidate(vector<string>& cands, const string& s) {\n    if (s.empty()) return;\n    string x = s;\n    if ((int)x.size() > MAXL) x.resize(MAXL);\n    cands.push_back(x);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n    auto endTime = startTime + chrono::milliseconds(1850);\n\n    cin >> si_ >> sj_ >> ti_ >> tj_ >> pforget;\n    for (int i = 0; i < N; i++) cin >> hwall[i];\n    for (int i = 0; i < N - 1; i++) cin >> vwall[i];\n\n    uint32_t seed = 1234567u;\n    seed ^= si_ * 1000003u;\n    seed ^= sj_ * 9176u;\n    seed ^= ti_ * 19260817u;\n    seed ^= tj_ * 998244353u;\n    seed ^= (uint32_t)(pforget * 1000);\n    rng.seed(seed);\n\n    buildGraph();\n\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    bfsFrom(t, distT);\n    bfsFrom(s, distS);\n\n    vector<string> candidates;\n\n    string sp = shortestPath(s, t);\n    addCandidate(candidates, sp);\n\n    if (!sp.empty()) {\n        addCandidate(candidates, repeatWhole(sp));\n\n        for (int r = 2; r <= 10; r++) {\n            addCandidate(candidates, repeatChars(sp, r));\n        }\n\n        for (int trial = 0; trial < 80; trial++) {\n            string rsp = shortestPath(s, t, true);\n            addCandidate(candidates, rsp);\n            addCandidate(candidates, repeatChars(rsp, 2 + rng() % 6));\n            addCandidate(candidates, repeatWhole(rsp));\n            addCandidate(candidates, noisyRepeatPath(rsp));\n            addCandidate(candidates, stochasticExpandedPath(rsp));\n        }\n    }\n\n    for (int r = 1; r <= 10; r++) {\n        addCandidate(candidates, deterministicDistRoute(r));\n    }\n\n    vector<double> temps = {0.0, 0.02, 0.05, 0.1, 0.2, 0.4, 0.8, 1.5, 3.0};\n    vector<double> penalties = {0.0, 0.05, 0.15, 0.3, 0.7, 1.5, 3.0};\n    vector<double> bonuses = {0.2, 0.5, 1.0, 2.0, 4.0};\n\n    for (double temp : temps) {\n        for (double pen : penalties) {\n            for (double bonus : bonuses) {\n                addCandidate(candidates, greedyDistribution(temp, pen, bonus));\n            }\n        }\n    }\n\n    addCandidate(candidates, beamSearchRoute(8, 120, 1.0, 0.03));\n    addCandidate(candidates, beamSearchRoute(10, 150, 1.0, 0.02));\n    addCandidate(candidates, beamSearchRoute(12, 200, 1.0, 0.015));\n\n    vector<int> cells(V);\n    iota(cells.begin(), cells.end(), 0);\n\n    sort(cells.begin(), cells.end(), [&](int a, int b) {\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n\n        int ascore = distS[a] + distT[a] + abs(ai - 10) + abs(aj - 10);\n        int bscore = distS[b] + distT[b] + abs(bi - 10) + abs(bj - 10);\n\n        return ascore < bscore;\n    });\n\n    for (int idx = 0; idx < min(V, 80); idx++) {\n        int mid = cells[idx];\n\n        string a = shortestPath(s, mid, true);\n        string b = shortestPath(mid, t, true);\n\n        if (a.empty() || b.empty()) continue;\n\n        string path = a + b;\n        if ((int)path.size() > MAXL) path.resize(MAXL);\n\n        addCandidate(candidates, path);\n        addCandidate(candidates, repeatWhole(path));\n        addCandidate(candidates, noisyRepeatPath(path));\n        addCandidate(candidates, stochasticExpandedPath(path));\n\n        for (int r = 2; r <= 5; r++) {\n            addCandidate(candidates, repeatChars(path, r));\n        }\n    }\n\n    for (int trial = 0; trial < 120; trial++) {\n        string r;\n        int len = 80 + rng() % 121;\n        for (int i = 0; i < len; i++) {\n            r.push_back(randomBiasedChar());\n        }\n        addCandidate(candidates, r);\n    }\n\n    string best = sp.empty() ? string(\"D\") : sp;\n    double bestVal = evaluate(best);\n\n    vector<pair<double, string>> elite;\n    elite.push_back({bestVal, best});\n\n    for (string cand : candidates) {\n        if (chrono::steady_clock::now() >= endTime) break;\n\n        if (cand.empty()) continue;\n        if ((int)cand.size() > MAXL) cand.resize(MAXL);\n\n        double val = evaluate(cand);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n\n        elite.push_back({val, cand});\n    }\n\n    sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    if ((int)elite.size() > 30) elite.resize(30);\n\n    int repairN = min(8, (int)elite.size());\n\n    for (int i = 0; i < repairN; i++) {\n        if (chrono::steady_clock::now() >= endTime) break;\n\n        string r = suffixAppendRepair(elite[i].second);\n        double val = evaluate(r);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = r;\n        }\n\n        elite.push_back({val, r});\n    }\n\n    sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    if ((int)elite.size() > 30) elite.resize(30);\n\n    auto charImproveEnd = startTime + chrono::milliseconds(1400);\n    deterministicSingleCharImprove(best, bestVal, charImproveEnd);\n\n    auto swapImproveEnd = startTime + chrono::milliseconds(1480);\n    deterministicSwapImprove(best, bestVal, swapImproveEnd);\n\n    int stagnant = 0;\n\n    while (chrono::steady_clock::now() < endTime) {\n        string base;\n\n        int mode = rng() % 100;\n\n        if (mode < 80) {\n            base = best;\n        } else {\n            int top = max(1, min(10, (int)elite.size()));\n            base = elite[rng() % top].second;\n        }\n\n        int strength = 1 + min(18, stagnant / 25);\n        string cand = mutateString(base, strength);\n\n        double val = evaluate(cand);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n            stagnant = 0;\n        } else {\n            stagnant++;\n        }\n\n        if (val > elite.back().first) {\n            elite.push_back({val, cand});\n            sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n                return a.first > b.first;\n            });\n            if ((int)elite.size() > 30) elite.resize(30);\n        }\n\n        if (stagnant % 180 == 179 && !sp.empty()) {\n            string base2;\n            int m = rng() % 4;\n\n            if (m == 0) base2 = repeatChars(sp, 2 + rng() % 8);\n            else if (m == 1) base2 = repeatWhole(sp);\n            else if (m == 2) base2 = stochasticExpandedPath(shortestPath(s, t, true));\n            else base2 = greedyDistribution(0.5, 0.5, 1.0);\n\n            string cand2 = mutateString(base2, 8);\n            double val2 = evaluate(cand2);\n\n            if (val2 > bestVal) {\n                bestVal = val2;\n                best = cand2;\n                stagnant = 0;\n            }\n\n            if (val2 > elite.back().first) {\n                elite.push_back({val2, cand2});\n                sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n                    return a.first > b.first;\n                });\n                if ((int)elite.size() > 30) elite.resize(30);\n            }\n        }\n    }\n\n    if (best.empty()) best = \"D\";\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n\n    cout << best << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N * 4;\n\nint to_dir[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\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) {\n        return (int)(next_u64() % n);\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint rotate_state(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (0 <= t && t <= 3) t = (t + 1) & 3;\n        else if (t == 4) t = 5;\n        else if (t == 5) t = 4;\n        else if (t == 6) t = 7;\n        else if (t == 7) t = 6;\n    }\n    return t;\n}\n\nint norm_pair(int a, int b) {\n    if (a > b) swap(a, b);\n    return a * 4 + b;\n}\n\nbool state_has_pair(int t, int a, int b) {\n    int p = norm_pair(a, b);\n    for (int d = 0; d < 4; d++) {\n        if (to_dir[t][d] != -1) {\n            int q = norm_pair(d, to_dir[t][d]);\n            if (p == q) return true;\n        }\n    }\n    return false;\n}\n\nint rotation_for_pair(int base, int a, int b) {\n    for (int r = 0; r < 4; r++) {\n        int t = rotate_state(base, r);\n        if (state_has_pair(t, a, b)) return r;\n    }\n    return -1;\n}\n\nint dir_between(int from_i, int from_j, int to_i, int to_j) {\n    if (to_i == from_i && to_j == from_j - 1) return 0;\n    if (to_i == from_i - 1 && to_j == from_j) return 1;\n    if (to_i == from_i && to_j == from_j + 1) return 2;\n    if (to_i == from_i + 1 && to_j == from_j) return 3;\n    return -1;\n}\n\nstruct Candidate {\n    vector<int> cells;\n    vector<unsigned char> req_a;\n    vector<unsigned char> req_b;\n    int len = 0;\n    uint64_t mask[15]{};\n};\n\nstruct Solver {\n    vector<string> s;\n    array<int, N * N> base{};\n    array<int, N * N> rot{};\n    array<int, N * N> tile{};\n    array<int, N * N> best_rot{};\n    array<int, N * N> fixed_cell{};\n    XorShift rng;\n\n    int feasible_pair[900][4][4]{};\n    int banned[900]{};\n\n    int id(int i, int j, int d) const {\n        return ((i * N + j) << 2) | d;\n    }\n\n    tuple<int,int,int> decode(int x) const {\n        int d = x & 3;\n        x >>= 2;\n        return {x / N, x % N, d};\n    }\n\n    int nxt(int x) const {\n        auto [i, j, d] = decode(x);\n        int t = tile[i * N + j];\n        int d2 = to_dir[t][d];\n        if (d2 == -1) return -1;\n        int ni = i + di[d2], nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n        return id(ni, nj, (d2 + 2) & 3);\n    }\n\n    long long evaluate() const {\n        static int state[V], seen[V], dep[V];\n\n        for (int i = 0; i < V; i++) {\n            state[i] = 0;\n            seen[i] = -1;\n            dep[i] = 0;\n        }\n\n        int best1 = 0, best2 = 0;\n\n        for (int st = 0; st < V; st++) {\n            if (state[st]) continue;\n\n            int cur = st;\n            vector<int> path;\n            path.reserve(256);\n\n            while (true) {\n                if (cur == -1) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 2) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 1) {\n                    if (seen[cur] == st) {\n                        int len = (int)path.size() - dep[cur];\n                        if (len >= best1) {\n                            best2 = best1;\n                            best1 = len;\n                        } else if (len > best2) {\n                            best2 = len;\n                        }\n                    }\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n\n                state[cur] = 1;\n                seen[cur] = st;\n                dep[cur] = (int)path.size();\n                path.push_back(cur);\n                cur = nxt(cur);\n            }\n        }\n\n        if (best2 == 0) return 0;\n        return 1LL * best1 * best2;\n    }\n\n    void rebuild_tile() {\n        for (int i = 0; i < N * N; i++) {\n            tile[i] = rotate_state(base[i], rot[i]);\n        }\n    }\n\n    bool disjoint(const Candidate& a, const Candidate& b) const {\n        for (int k = 0; k < 15; k++) {\n            if (a.mask[k] & b.mask[k]) return false;\n        }\n        return true;\n    }\n\n    bool make_candidate_from_cycle(const vector<int>& cyc, Candidate& cand) const {\n        int m = (int)cyc.size();\n        if (m < 8) return false;\n\n        cand.cells.clear();\n        cand.req_a.clear();\n        cand.req_b.clear();\n        cand.len = m;\n        memset(cand.mask, 0, sizeof(cand.mask));\n\n        static int used[N * N];\n        static int mark = 100000;\n        mark++;\n        if (mark == INT_MAX) {\n            memset(used, 0, sizeof(used));\n            mark = 100000;\n        }\n\n        for (int x : cyc) {\n            if (x < 0 || x >= N * N) return false;\n            if (banned[x]) return false;\n            if (used[x] == mark) return false;\n            used[x] = mark;\n        }\n\n        for (int k = 0; k < m; k++) {\n            int prev = cyc[(k - 1 + m) % m];\n            int cur = cyc[k];\n            int nxtc = cyc[(k + 1) % m];\n\n            int ci = cur / N, cj = cur % N;\n            int pi = prev / N, pj = prev % N;\n            int ni = nxtc / N, nj = nxtc % N;\n\n            int dprev = dir_between(ci, cj, pi, pj);\n            int dnxt = dir_between(ci, cj, ni, nj);\n            if (dprev == -1 || dnxt == -1 || dprev == dnxt) return false;\n\n            if (!feasible_pair[cur][dprev][dnxt]) return false;\n\n            cand.cells.push_back(cur);\n            cand.req_a.push_back((unsigned char)dprev);\n            cand.req_b.push_back((unsigned char)dnxt);\n            cand.mask[cur >> 6] |= 1ULL << (cur & 63);\n        }\n\n        return true;\n    }\n\n    void try_add_cycle(vector<Candidate>& cands, const vector<int>& cyc) const {\n        Candidate cand;\n        if (make_candidate_from_cycle(cyc, cand)) {\n            cands.push_back(std::move(cand));\n        }\n    }\n\n    void add_rect_candidates(vector<Candidate>& cands) const {\n        for (int r1 = 0; r1 < N; r1++) {\n            for (int r2 = r1 + 1; r2 < N; r2++) {\n                for (int c1 = 0; c1 < N; c1++) {\n                    for (int c2 = c1 + 1; c2 < N; c2++) {\n                        int len = 2 * ((r2 - r1) + (c2 - c1));\n                        if (len < 16) continue;\n\n                        vector<int> cyc;\n                        cyc.reserve(len);\n\n                        for (int j = c1; j < c2; j++) cyc.push_back(r1 * N + j);\n                        for (int i = r1; i < r2; i++) cyc.push_back(i * N + c2);\n                        for (int j = c2; j > c1; j--) cyc.push_back(r2 * N + j);\n                        for (int i = r2; i > r1; i--) cyc.push_back(i * N + c1);\n\n                        try_add_cycle(cands, cyc);\n                    }\n                }\n            }\n        }\n    }\n\n    bool feasible_random_cycle(Candidate& cand, int target_len) {\n        int si = rng.next_int(N);\n        int sj = rng.next_int(N);\n        int start = si * N + sj;\n        if (banned[start]) return false;\n\n        static int used[N * N];\n        static int mark = 1;\n        mark++;\n        if (mark == INT_MAX) {\n            memset(used, 0, sizeof(used));\n            mark = 1;\n        }\n\n        vector<int> path;\n        path.reserve(target_len + 8);\n        path.push_back(start);\n        used[start] = mark;\n\n        int ci = si, cj = sj;\n\n        for (int step = 0; step < target_len + 90; step++) {\n            vector<pair<int,int>> cand_dirs;\n            cand_dirs.reserve(4);\n\n            int cur = ci * N + cj;\n            int in_dir = -1;\n            if ((int)path.size() >= 2) {\n                int prev = path[path.size() - 2];\n                int pi = prev / N, pj = prev % N;\n                in_dir = dir_between(ci, cj, pi, pj);\n            }\n\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nid = ni * N + nj;\n\n                if (nid == start) {\n                    if ((int)path.size() < 8) continue;\n\n                    if (in_dir != -1 && !feasible_pair[cur][in_dir][d]) continue;\n\n                    int first = path[1];\n                    int fi = first / N, fj = first % N;\n                    int out_start = dir_between(si, sj, fi, fj);\n                    int in_start = dir_between(si, sj, ci, cj);\n                    if (out_start == -1 || in_start == -1) continue;\n                    if (!feasible_pair[start][in_start][out_start]) continue;\n\n                    Candidate tmp;\n                    if (make_candidate_from_cycle(path, tmp)) {\n                        cand = std::move(tmp);\n                        return true;\n                    }\n                    continue;\n                }\n\n                if (banned[nid]) continue;\n                if (used[nid] == mark) continue;\n                if ((int)path.size() >= target_len) continue;\n\n                if (in_dir != -1 && !feasible_pair[cur][in_dir][d]) continue;\n\n                int dist_now = abs(ci - si) + abs(cj - sj);\n                int dist_next = abs(ni - si) + abs(nj - sj);\n\n                int score = rng.next_int(100);\n\n                if ((int)path.size() > target_len * 2 / 3) {\n                    score -= (dist_now - dist_next) * 45;\n                } else {\n                    score += dist_next * 2;\n                }\n\n                // Mildly prefer cells with more continuation options.\n                int deg = 0;\n                for (int nd = 0; nd < 4; nd++) {\n                    int xi = ni + di[nd], xj = nj + dj[nd];\n                    if (xi < 0 || xi >= N || xj < 0 || xj >= N) continue;\n                    if (!banned[xi * N + xj]) deg++;\n                }\n                score -= deg * 3;\n\n                cand_dirs.push_back({score, d});\n            }\n\n            if (cand_dirs.empty()) break;\n\n            sort(cand_dirs.begin(), cand_dirs.end());\n\n            int pick_lim = min<int>(3, cand_dirs.size());\n            int pick = rng.next_int(pick_lim);\n            int d = cand_dirs[pick].second;\n\n            int ni = ci + di[d], nj = cj + dj[d];\n            int nid = ni * N + nj;\n\n            used[nid] = mark;\n            path.push_back(nid);\n            ci = ni;\n            cj = nj;\n        }\n\n        return false;\n    }\n\n    void generate_candidates(vector<Candidate>& cands, const Timer& timer, double until) {\n        while (timer.elapsed() < until) {\n            Candidate cand;\n            int target;\n            int r = rng.next_int(100);\n            if (r < 40) target = 30 + rng.next_int(70);\n            else if (r < 85) target = 80 + rng.next_int(120);\n            else target = 160 + rng.next_int(220);\n\n            if (feasible_random_cycle(cand, target)) {\n                cands.push_back(std::move(cand));\n            }\n        }\n    }\n\n    void sort_filter(vector<Candidate>& cands, int limit) {\n        sort(cands.begin(), cands.end(), [](const Candidate& a, const Candidate& b) {\n            return a.len > b.len;\n        });\n\n        vector<Candidate> filtered;\n        filtered.reserve(min<int>(limit, cands.size()));\n\n        for (auto &c : cands) {\n            bool duplicate = false;\n            int start = max(0, (int)filtered.size() - 200);\n            for (int i = start; i < (int)filtered.size(); i++) {\n                bool same = true;\n                for (int k = 0; k < 15; k++) {\n                    if (filtered[i].mask[k] != c.mask[k]) {\n                        same = false;\n                        break;\n                    }\n                }\n                if (same) {\n                    duplicate = true;\n                    break;\n                }\n            }\n            if (!duplicate) filtered.push_back(std::move(c));\n            if ((int)filtered.size() >= limit) break;\n        }\n\n        cands.swap(filtered);\n    }\n\n    pair<int,int> best_pair_indices(const vector<Candidate>& cands) const {\n        long long best_prod = -1;\n        int bi = -1, bj = -1;\n\n        for (int i = 0; i < (int)cands.size(); i++) {\n            if (1LL * cands[i].len * cands[i].len < best_prod) break;\n            for (int j = i + 1; j < (int)cands.size(); j++) {\n                long long prod = 1LL * cands[i].len * cands[j].len;\n                if (prod <= best_prod) break;\n                if (disjoint(cands[i], cands[j])) {\n                    best_prod = prod;\n                    bi = i;\n                    bj = j;\n                    break;\n                }\n            }\n        }\n        return {bi, bj};\n    }\n\n    void apply_candidate(const Candidate& cand) {\n        for (int k = 0; k < (int)cand.cells.size(); k++) {\n            int cell = cand.cells[k];\n            int a = cand.req_a[k];\n            int b = cand.req_b[k];\n\n            int r = rotation_for_pair(base[cell], a, b);\n            if (r >= 0) {\n                rot[cell] = r;\n                fixed_cell[cell] = 1;\n            }\n        }\n    }\n\n    void fill_random_free() {\n        for (int i = 0; i < N * N; i++) {\n            if (fixed_cell[i]) continue;\n            int maxr = (base[i] <= 3 ? 4 : 2);\n            rot[i] = rng.next_int(maxr);\n        }\n        rebuild_tile();\n    }\n\n    void construct_solution(const Timer& timer) {\n        vector<Candidate> base_cands;\n        memset(banned, 0, sizeof(banned));\n\n        add_rect_candidates(base_cands);\n        generate_candidates(base_cands, timer, 0.75);\n        sort_filter(base_cands, 4500);\n\n        Candidate bestA, bestB;\n        long long best_prod = -1;\n\n        auto [pi, pj] = best_pair_indices(base_cands);\n        if (pi != -1) {\n            bestA = base_cands[pi];\n            bestB = base_cands[pj];\n            best_prod = 1LL * bestA.len * bestB.len;\n        }\n\n        int trials = min<int>(16, base_cands.size());\n        double start_time = timer.elapsed();\n\n        for (int t = 0; t < trials && timer.elapsed() < 1.05; t++) {\n            const Candidate& first = base_cands[t];\n\n            memset(banned, 0, sizeof(banned));\n            for (int cell : first.cells) banned[cell] = 1;\n\n            vector<Candidate> second_cands;\n            generate_candidates(second_cands, timer, start_time + (t + 1) * (0.30 / max(1, trials)));\n            sort_filter(second_cands, 1000);\n\n            for (auto &sec : second_cands) {\n                long long prod = 1LL * first.len * sec.len;\n                if (prod > best_prod) {\n                    best_prod = prod;\n                    bestA = first;\n                    bestB = sec;\n                    break;\n                }\n            }\n        }\n\n        memset(banned, 0, sizeof(banned));\n\n        fixed_cell.fill(0);\n        rot.fill(0);\n\n        if (best_prod > 0) {\n            apply_candidate(bestA);\n            apply_candidate(bestB);\n        }\n\n        fill_random_free();\n    }\n\n    void improve_free_cells(double until_sec, const Timer& timer) {\n        long long cur = evaluate();\n        long long best = cur;\n        best_rot = rot;\n\n        while (timer.elapsed() < until_sec) {\n            int p = rng.next_int(N * N);\n            if (fixed_cell[p]) continue;\n\n            int oldr = rot[p];\n            int oldt = tile[p];\n\n            int maxr = (base[p] <= 3 ? 4 : 2);\n            int nr = rng.next_int(maxr);\n            if (nr == oldr) nr = (nr + 1) % maxr;\n\n            rot[p] = nr;\n            tile[p] = rotate_state(base[p], nr);\n\n            long long ns = evaluate();\n            long long diff = ns - cur;\n\n            double progress = timer.elapsed() / until_sec;\n            double temp = 1000.0 * (1.0 - progress) + 2.0;\n\n            bool accept = false;\n            if (diff >= 0) accept = true;\n            else if (rng.next_double() < exp((double)diff / temp)) accept = true;\n\n            if (accept) {\n                cur = ns;\n                if (cur > best) {\n                    best = cur;\n                    best_rot = rot;\n                }\n            } else {\n                rot[p] = oldr;\n                tile[p] = oldt;\n            }\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n    }\n\n    void solve() {\n        s.resize(N);\n        for (int i = 0; i < N; i++) cin >> s[i];\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                base[i * N + j] = s[i][j] - '0';\n            }\n        }\n\n        for (int cell = 0; cell < N * N; cell++) {\n            for (int a = 0; a < 4; a++) {\n                for (int b = 0; b < 4; b++) {\n                    feasible_pair[cell][a][b] = (a != b && rotation_for_pair(base[cell], a, b) != -1);\n                }\n            }\n        }\n\n        Timer timer;\n\n        construct_solution(timer);\n\n        long long best_score = evaluate();\n        best_rot = rot;\n\n        while (timer.elapsed() < 1.18) {\n            fill_random_free();\n            long long sc = evaluate();\n            if (sc > best_score) {\n                best_score = sc;\n                best_rot = rot;\n            }\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n\n        improve_free_cells(1.90, timer);\n\n        string ans;\n        ans.reserve(N * N);\n        for (int i = 0; i < N * N; i++) {\n            ans.push_back(char('0' + rot[i]));\n        }\n        cout << ans << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer{ chrono::steady_clock::time_point s=chrono::steady_clock::now(); double elapsed(){return chrono::duration<double>(chrono::steady_clock::now()-s).count();}};\nint N,Tlim,M;\nvector<unsigned char> initb;\nmt19937 rng(1234567);\n\nint hv(char c){return c<='9'?c-'0':c-'a'+10;}\nstruct DSU{ vector<int> p,z; DSU(int n=0){init(n);} void init(int n){p.resize(n);z.assign(n,1);iota(p.begin(),p.end(),0);} int f(int x){while(p[x]!=x){p[x]=p[p[x]];x=p[x];}return x;} bool uni(int a,int b){a=f(a);b=f(b); if(a==b)return false; if(z[a]<z[b])swap(a,b); p[b]=a; z[a]+=z[b]; return true;}};\nstruct Ev{int lt,lc,e,cy,tc,co,iso;};\n\nEv evalb(const vector<unsigned char>& b){\n    DSU d(M); int edges=0,cy=0; bool act[105];\n    for(int i=0;i<M;i++) act[i]=b[i]!=0;\n    for(int r=0;r<N;r++)for(int c=0;c<N;c++){\n        int id=r*N+c; if(!act[id])continue; int v=b[id];\n        if(c+1<N){int ni=id+1; if(act[ni]&&(v&4)&&(b[ni]&1)){edges++; if(!d.uni(id,ni))cy++;}}\n        if(r+1<N){int ni=id+N; if(act[ni]&&(v&8)&&(b[ni]&2)){edges++; if(!d.uni(id,ni))cy++;}}\n    }\n    int vc[105]={},ec[105]={};\n    for(int i=0;i<M;i++) if(act[i]) vc[d.f(i)]++;\n    for(int r=0;r<N;r++)for(int c=0;c<N;c++){\n        int id=r*N+c; if(!act[id])continue; int v=b[id];\n        if(c+1<N){int ni=id+1; if(act[ni]&&(v&4)&&(b[ni]&1)) ec[d.f(id)]++;}\n        if(r+1<N){int ni=id+N; if(act[ni]&&(v&8)&&(b[ni]&2)) ec[d.f(id)]++;}\n    }\n    Ev e{0,0,edges,cy,0,0,0};\n    for(int i=0;i<M;i++)if(vc[i]){\n        e.co++; e.lc=max(e.lc,vc[i]); if(vc[i]==1)e.iso++;\n        if(ec[i]==vc[i]-1){e.tc++; e.lt=max(e.lt,vc[i]);}\n    }\n    return e;\n}\nint offscore(const vector<unsigned char>& b,int k){ Ev e=evalb(b); if(e.lt==M-1)return 1000000000-k*1000; return e.lt*1000000; }\nchar opp(char c){ if(c=='U')return'D'; if(c=='D')return'U'; if(c=='L')return'R'; if(c=='R')return'L'; return'?';}\nbool apply(vector<unsigned char>& b,int& emp,char m){\n    int r=emp/N,c=emp%N,nr=r,nc=c;\n    if(m=='U')nr--; if(m=='D')nr++; if(m=='L')nc--; if(m=='R')nc++;\n    if(nr<0||nr>=N||nc<0||nc>=N)return false;\n    int np=nr*N+nc; swap(b[emp],b[np]); emp=np; return true;\n}\nstring keyb(const vector<unsigned char>& b,int emp){\n    string s; s.resize(M+1); for(int i=0;i<M;i++)s[i]=char(b[i]); s[M]=char(emp); return s;\n}\nstruct State{vector<unsigned char>b; int emp; string p; char last; int sc;};\nstruct Res{vector<unsigned char>b; int emp; string ans; int score;};\n\nint hscore(const Ev& e,int emp,int plen,int d,int mode){\n    int sc=e.lt*1000000;\n    if(mode==0){\n        sc+=e.lc*18000+e.e*4500-e.cy*45000-e.co*1800-e.iso*1200+e.tc*1200;\n    }else if(mode==1){\n        sc+=e.lc*26000+e.e*3000-e.cy*70000-e.co*1200-e.iso*800+e.tc*2500;\n    }else{\n        sc+=e.lc*10000+e.e*8000-e.cy*25000-e.co*2500-e.iso*1800+e.tc*800;\n    }\n    if(e.lt==M-1) sc+=500000000-(plen+d)*8000;\n    else sc-=d*20;\n    int r=emp/N,c=emp%N;\n    sc-=(abs(r-(N-1))+abs(c-(N-1)))*100;\n    return sc;\n}\nRes beam(const vector<unsigned char>& sb,int se,const string& pref,double endt,Timer& tim,int mode,int bwscale){\n    Res best{sb,se,pref,offscore(sb,pref.size())};\n    State st{sb,se,\"\",'?',0}; st.sc=hscore(evalb(sb),se,pref.size(),0,mode);\n    vector<State> beam{move(st)};\n    int base = (N==6?1500:N==7?1050:N==8?700:N==9?450:310);\n    int BW=max(70,base*bwscale/100);\n    if(!pref.empty()) BW=max(60,BW*2/3);\n    char mv[4]={'U','D','L','R'}; int dr[4]={-1,1,0,0},dc[4]={0,0,-1,1};\n    int maxD=Tlim-(int)pref.size();\n    for(int dep=0;dep<maxD;dep++){\n        if(tim.elapsed()>endt)break;\n        vector<State> cand; cand.reserve(beam.size()*4);\n        for(auto &s:beam){\n            int r=s.emp/N,c=s.emp%N;\n            for(int k=0;k<4;k++){\n                char m=mv[k];\n                if(s.last!='?'&&opp(s.last)==m) continue;\n                int nr=r+dr[k],nc=c+dc[k]; if(nr<0||nr>=N||nc<0||nc>=N)continue;\n                int np=nr*N+nc;\n                State ns; ns.b=s.b; swap(ns.b[s.emp],ns.b[np]); ns.emp=np; ns.p=s.p; ns.p.push_back(m); ns.last=m;\n                Ev e=evalb(ns.b); ns.sc=hscore(e,ns.emp,pref.size(),ns.p.size(),mode);\n                int os = (e.lt==M-1?1000000000-(int)(pref.size()+ns.p.size())*1000:e.lt*1000000);\n                if(os>best.score){best.score=os; best.b=ns.b; best.emp=ns.emp; best.ans=pref+ns.p;}\n                cand.push_back(move(ns));\n            }\n        }\n        if(cand.empty())break;\n        int keep=min(BW,(int)cand.size());\n        nth_element(cand.begin(),cand.begin()+keep,cand.end(),[](auto&a,auto&b){return a.sc>b.sc;});\n        cand.resize(keep);\n        sort(cand.begin(),cand.end(),[](auto&a,auto&b){return a.sc>b.sc;});\n        unordered_set<string> seen; seen.reserve(keep*3);\n        vector<State> nb; nb.reserve(keep);\n        for(auto &s:cand){ string k=keyb(s.b,s.emp); if(seen.insert(k).second){nb.push_back(move(s)); if((int)nb.size()>=keep)break;}}\n        beam.swap(nb);\n    }\n    return best;\n}\nstring rw(vector<unsigned char>& b,int& e,int len){\n    string p; char last='?'; char mv[4]={'U','D','L','R'};\n    for(int i=0;i<len;i++){\n        vector<char> le; int r=e/N,c=e%N;\n        for(char m:mv){ if(last!='?'&&opp(last)==m)continue; int nr=r,nc=c; if(m=='U')nr--; if(m=='D')nr++; if(m=='L')nc--; if(m=='R')nc++; if(0<=nr&&nr<N&&0<=nc&&nc<N)le.push_back(m);}\n        if(le.empty())break;\n        char m=le[uniform_int_distribution<int>(0,(int)le.size()-1)(rng)];\n        apply(b,e,m); p.push_back(m); last=m;\n    }\n    return p;\n}\n\nint main(){\n    ios::sync_with_stdio(false); cin.tie(nullptr);\n    cin>>N>>Tlim; M=N*N; initb.assign(M,0); int emp=0;\n    for(int i=0;i<N;i++){string s;cin>>s;for(int j=0;j<N;j++){initb[i*N+j]=hv(s[j]); if(initb[i*N+j]==0)emp=i*N+j;}}\n    Timer tim;\n    Res gb{initb,emp,\"\",offscore(initb,0)};\n    vector<tuple<vector<unsigned char>,int,string,int,int>> starts;\n    starts.push_back({initb,emp,\"\",0,120});\n    int rest=(N<=6?8:N==7?7:N==8?5:4);\n    for(int i=0;i<rest;i++){\n        vector<unsigned char>b=initb; int e=emp;\n        int len=(i%4+1)*N/1;\n        string p=rw(b,e,len);\n        starts.push_back({b,e,p,i%3,90});\n    }\n    int idx=0;\n    for(auto &tu:starts){\n        if(tim.elapsed()>2.82)break;\n        auto [b,e,p,mode,sc]=tu;\n        double remain=2.86;\n        Res r=beam(b,e,p,remain,tim,mode,sc);\n        if(r.score>gb.score) gb=r;\n        idx++;\n    }\n    if((int)gb.ans.size()>Tlim) gb.ans.resize(Tlim);\n    cout<<gb.ans<<\"\\n\";\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\nstruct CutSet {\n    vector<int> cuts;\n    vector<unsigned short> bin;\n};\n\nstruct RotCand {\n    int approxScore;\n    int c1, c2;\n    double theta;\n    vector<double> cut1, cut2;\n};\n\nstatic const long long LIM = 1000000000LL;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\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    int N, K;\n    cin >> N >> K;\n\n    vector<int> a(11);\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n\n    vector<Point> pts(N);\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) {\n        cin >> pts[i].x >> pts[i].y;\n        xs[i] = pts[i].x;\n        ys[i] = pts[i].y;\n    }\n\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    auto score_from_cells = [&](const vector<unsigned short>& cell) {\n        int b[11] = {};\n        for (unsigned short v : cell) {\n            if (1 <= v && v <= 10) b[v]++;\n        }\n        int score = 0;\n        for (int d = 1; d <= 10; d++) score += min(a[d], b[d]);\n        return score;\n    };\n\n    auto make_cuts = [&](const vector<int>& sorted_coord, int c, double off) {\n        vector<int> cuts;\n        cuts.reserve(c);\n\n        for (int i = 1; i <= c; i++) {\n            double pos = (i + off) / (c + 1.0);\n            if (pos <= 0.0 || pos >= 1.0) continue;\n\n            int idx = (int)(pos * N);\n            idx = max(1, min(N - 1, idx));\n\n            int v1 = sorted_coord[idx - 1];\n            int v2 = sorted_coord[idx];\n\n            int cut;\n            if (v1 == v2) cut = v1 + 1;\n            else cut = (v1 + v2) / 2;\n\n            if (cuts.empty() || cuts.back() != cut) cuts.push_back(cut);\n        }\n\n        return cuts;\n    };\n\n    auto make_cutset = [&](const vector<int>& sorted_coord, int c, double off, bool isX) {\n        CutSet cs;\n        cs.cuts = make_cuts(sorted_coord, c, off);\n        cs.bin.resize(N);\n\n        for (int i = 0; i < N; i++) {\n            int v = isX ? pts[i].x : pts[i].y;\n            cs.bin[i] = upper_bound(cs.cuts.begin(), cs.cuts.end(), v) - cs.cuts.begin();\n        }\n\n        return cs;\n    };\n\n    int attendees = 0;\n    for (int d = 1; d <= 10; d++) attendees += a[d];\n\n    vector<pair<int,int>> shapes;\n\n    for (int vx = 20; vx <= 80; vx++) shapes.push_back({vx, 100 - vx});\n\n    for (int total : {50, 60, 70, 80, 90, 96, 100}) {\n        int mid = total / 2;\n        for (int vx = mid - 22; vx <= mid + 22; vx += 2) {\n            int hy = total - vx;\n            if (vx >= 1 && hy >= 1) shapes.push_back({vx, hy});\n        }\n    }\n\n    int estV = 50, estH = 50;\n    double bestCost = 1e100;\n    for (int vx = 0; vx <= K; vx++) {\n        for (int hy = 0; hy + vx <= K; hy++) {\n            int cells = (vx + 1) * (hy + 1);\n            double cost = abs(cells - attendees) + 0.05 * abs(vx - hy);\n            if (cost < bestCost) {\n                bestCost = cost;\n                estV = vx;\n                estH = hy;\n            }\n        }\n    }\n    for (int dv = -20; dv <= 20; dv++) {\n        int vx = estV + dv;\n        int hy = estH - dv;\n        if (vx >= 1 && hy >= 1 && vx + hy <= K) shapes.push_back({vx, hy});\n    }\n\n    sort(shapes.begin(), shapes.end());\n    shapes.erase(unique(shapes.begin(), shapes.end()), shapes.end());\n\n    vector<double> offs = {0.0, -0.4, -0.25, -0.1, 0.1, 0.25, 0.4};\n\n    set<pair<int,int>> xParams, yParams;\n    for (auto [vx, hy] : shapes) {\n        for (int oi = 0; oi < (int)offs.size(); oi++) {\n            xParams.insert({vx, oi});\n            yParams.insert({hy, oi});\n        }\n    }\n\n    vector<CutSet> xsets, ysets;\n    for (auto [c, oi] : xParams) xsets.push_back(make_cutset(xs, c, offs[oi], true));\n    for (auto [c, oi] : yParams) ysets.push_back(make_cutset(ys, c, offs[oi], false));\n\n    auto eval_axis_pair = [&](const CutSet& X, const CutSet& Y) {\n        int cx = (int)X.cuts.size();\n        int cy = (int)Y.cuts.size();\n        int W = cy + 1;\n        vector<unsigned short> cell((cx + 1) * W, 0);\n\n        for (int i = 0; i < N; i++) {\n            cell[X.bin[i] * W + Y.bin[i]]++;\n        }\n\n        return score_from_cells(cell);\n    };\n\n    int bestScore = -1;\n    vector<Line> bestLines;\n\n    for (const auto &X : xsets) {\n        int cx = (int)X.cuts.size();\n        for (const auto &Y : ysets) {\n            int cy = (int)Y.cuts.size();\n            if (cx + cy > K) continue;\n            if (abs(cx - cy) > 60) continue;\n\n            int sc = eval_axis_pair(X, Y);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestLines.clear();\n                for (int x : X.cuts) bestLines.push_back({x, -LIM, x, LIM});\n                for (int y : Y.cuts) bestLines.push_back({-LIM, y, LIM, y});\n            }\n        }\n    }\n\n    auto make_proj_line = [&](double ux, double uy, double t) -> Line {\n        double vx = -uy;\n        double vy = ux;\n\n        long long px = llround(ux * t + vx * LIM);\n        long long py = llround(uy * t + vy * LIM);\n        long long qx = llround(ux * t - vx * LIM);\n        long long qy = llround(uy * t - vy * LIM);\n\n        px = max(-LIM, min(LIM, px));\n        py = max(-LIM, min(LIM, py));\n        qx = max(-LIM, min(LIM, qx));\n        qy = max(-LIM, min(LIM, qy));\n\n        if (px == qx && py == qy) {\n            if (qx < LIM) qx++;\n            else qx--;\n        }\n        return {px, py, qx, qy};\n    };\n\n    auto build_rot_lines_from_cuts = [&](const RotCand& rc) {\n        double u1x = cos(rc.theta), u1y = sin(rc.theta);\n        double u2x = -sin(rc.theta), u2y = cos(rc.theta);\n\n        vector<Line> lines;\n        lines.reserve(rc.cut1.size() + rc.cut2.size());\n\n        for (double t : rc.cut1) lines.push_back(make_proj_line(u1x, u1y, t));\n        for (double t : rc.cut2) lines.push_back(make_proj_line(u2x, u2y, t));\n\n        if ((int)lines.size() > K) lines.resize(K);\n        return lines;\n    };\n\n    auto eval_lines_exact = [&](const vector<Line>& lines) {\n        int m = (int)lines.size();\n\n        vector<pair<unsigned long long, unsigned long long>> key(N, {0ULL, 0ULL});\n        vector<char> cut(N, 0);\n\n        for (int j = 0; j < m; j++) {\n            const Line &ln = lines[j];\n            long long dx = ln.qx - ln.px;\n            long long dy = ln.qy - ln.py;\n\n            for (int i = 0; i < N; i++) {\n                long long vx = pts[i].x - ln.px;\n                long long vy = pts[i].y - ln.py;\n                __int128 cross = (__int128)dx * vy - (__int128)dy * vx;\n\n                if (cross == 0) {\n                    cut[i] = 1;\n                } else if (cross > 0) {\n                    if (j < 64) key[i].first |= (1ULL << j);\n                    else key[i].second |= (1ULL << (j - 64));\n                }\n            }\n        }\n\n        vector<pair<unsigned long long, unsigned long long>> alive;\n        alive.reserve(N);\n        for (int i = 0; i < N; i++) {\n            if (!cut[i]) alive.push_back(key[i]);\n        }\n\n        sort(alive.begin(), alive.end());\n\n        int b[11] = {};\n        int cnt = 1;\n        for (int i = 1; i <= (int)alive.size(); i++) {\n            if (i < (int)alive.size() && alive[i] == alive[i - 1]) {\n                cnt++;\n            } else {\n                if (1 <= cnt && cnt <= 10) b[cnt]++;\n                cnt = 1;\n            }\n        }\n\n        int score = 0;\n        for (int d = 1; d <= 10; d++) score += min(a[d], b[d]);\n        return score;\n    };\n\n    auto approx_rotated = [&](int c1, int c2, double theta) -> RotCand {\n        double u1x = cos(theta), u1y = sin(theta);\n        double u2x = -sin(theta), u2y = cos(theta);\n\n        vector<double> s1(N), s2(N);\n        for (int i = 0; i < N; i++) {\n            s1[i] = u1x * pts[i].x + u1y * pts[i].y;\n            s2[i] = u2x * pts[i].x + u2y * pts[i].y;\n        }\n\n        vector<double> sorted1 = s1, sorted2 = s2;\n        sort(sorted1.begin(), sorted1.end());\n        sort(sorted2.begin(), sorted2.end());\n\n        vector<double> cut1, cut2;\n        cut1.reserve(c1);\n        cut2.reserve(c2);\n\n        for (int i = 1; i <= c1; i++) {\n            int idx = (long long)N * i / (c1 + 1);\n            if (idx <= 0 || idx >= N) continue;\n            cut1.push_back((sorted1[idx - 1] + sorted1[idx]) * 0.5);\n        }\n        for (int i = 1; i <= c2; i++) {\n            int idx = (long long)N * i / (c2 + 1);\n            if (idx <= 0 || idx >= N) continue;\n            cut2.push_back((sorted2[idx - 1] + sorted2[idx]) * 0.5);\n        }\n\n        int W = (int)cut2.size() + 1;\n        vector<unsigned short> cell(((int)cut1.size() + 1) * W, 0);\n\n        for (int i = 0; i < N; i++) {\n            int id1 = upper_bound(cut1.begin(), cut1.end(), s1[i]) - cut1.begin();\n            int id2 = upper_bound(cut2.begin(), cut2.end(), s2[i]) - cut2.begin();\n            cell[id1 * W + id2]++;\n        }\n\n        int sc = score_from_cells(cell);\n        return {sc, c1, c2, theta, move(cut1), move(cut2)};\n    };\n\n    // Rotated approximate search.\n    vector<RotCand> rotPool;\n    auto push_rot = [&](RotCand rc) {\n        rotPool.push_back(move(rc));\n        sort(rotPool.begin(), rotPool.end(), [](const RotCand& l, const RotCand& r) {\n            return l.approxScore > r.approxScore;\n        });\n        if ((int)rotPool.size() > 20) rotPool.pop_back();\n    };\n\n    vector<double> rAngles;\n    for (int i = 1; i < 16; i++) {\n        rAngles.push_back((M_PI / 2.0) * i / 16.0);\n    }\n\n    vector<pair<int,int>> rShapes = {\n        {50,50}, {45,55}, {55,45}, {40,60}, {60,40},\n        {35,65}, {65,35}, {48,48}, {42,48}, {48,42},\n        {44,52}, {52,44}\n    };\n\n    for (double th : rAngles) {\n        if (elapsed() > 2.35) break;\n        for (auto [c1, c2] : rShapes) {\n            if (c1 + c2 <= K) push_rot(approx_rotated(c1, c2, th));\n        }\n    }\n\n    // Exact-check only the promising rotated grids.\n    for (const auto &rc : rotPool) {\n        if (elapsed() > 2.75) break;\n        vector<Line> lines = build_rot_lines_from_cuts(rc);\n        int sc = eval_lines_exact(lines);\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestLines = move(lines);\n        }\n    }\n\n    if ((int)bestLines.size() > K) bestLines.resize(K);\n\n    cout << bestLines.size() << '\\n';\n    for (auto &ln : bestLines) {\n        cout << ln.px << ' ' << ln.py << ' ' << ln.qx << ' ' << ln.qy << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    int score;\n    int lenSum;\n};\n\nint N, M;\nvector<vector<unsigned char>> dotGrid;\nvector<vector<array<unsigned char, 4>>> usedSeg;\nvector<Move> answerMoves;\nvector<vector<int>> W;\n\nchrono::steady_clock::time_point startTime;\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\nint gcdAbs(int a, int b) {\n    return std::gcd(abs(a), abs(b));\n}\n\n// dir:\n// 0 : horizontal segment from (x,y) to (x+1,y)\n// 1 : vertical   segment from (x,y) to (x,y+1)\n// 2 : diag up    segment from (x,y) to (x+1,y+1)\n// 3 : diag down  segment from (x,y) to (x+1,y-1)\nbool getSegUsed(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n\n    if (dx == -1 || (dx == 0 && dy == -1)) {\n        swap(x1, x2);\n        swap(y1, y2);\n        dx = -dx;\n        dy = -dy;\n    }\n\n    if (dx == 1 && dy == 0) {\n        return usedSeg[x1][y1][0];\n    }\n    if (dx == 0 && dy == 1) {\n        return usedSeg[x1][y1][1];\n    }\n    if (dx == 1 && dy == 1) {\n        return usedSeg[x1][y1][2];\n    }\n    if (dx == -1 && dy == -1) {\n        return usedSeg[x2][y2][2];\n    }\n    if (dx == 1 && dy == -1) {\n        return usedSeg[x1][y1][3];\n    }\n    if (dx == -1 && dy == 1) {\n        return usedSeg[x2][y2][3];\n    }\n\n    return false;\n}\n\nvoid setSegUsed(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n\n    if (dx == -1 || (dx == 0 && dy == -1)) {\n        swap(x1, x2);\n        swap(y1, y2);\n        dx = -dx;\n        dy = -dy;\n    }\n\n    if (dx == 1 && dy == 0) {\n        usedSeg[x1][y1][0] = 1;\n    } else if (dx == 0 && dy == 1) {\n        usedSeg[x1][y1][1] = 1;\n    } else if (dx == 1 && dy == 1) {\n        usedSeg[x1][y1][2] = 1;\n    } else if (dx == -1 && dy == -1) {\n        usedSeg[x2][y2][2] = 1;\n    } else if (dx == 1 && dy == -1) {\n        usedSeg[x1][y1][3] = 1;\n    } else if (dx == -1 && dy == 1) {\n        usedSeg[x2][y2][3] = 1;\n    }\n}\n\nbool checkSideNoDotAndNoSeg(int ax, int ay, int bx, int by,\n                            int ex1, int ey1,\n                            int ex2, int ey2,\n                            int ex3, int ey3) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n        if (getSegUsed(x, y, nx, ny)) return false;\n    }\n\n    for (int i = 1; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n\n        if ((x == ex1 && y == ey1) ||\n            (x == ex2 && y == ey2) ||\n            (x == ex3 && y == ey3)) {\n            continue;\n        }\n\n        if (dotGrid[x][y]) return false;\n    }\n\n    return true;\n}\n\nvoid addSideSegments(int ax, int ay, int bx, int by) {\n    int dx = bx - ax;\n    int dy = by - ay;\n    int g = gcdAbs(dx, dy);\n    int sx = dx / g;\n    int sy = dy / g;\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n        setSegUsed(x, y, nx, ny);\n    }\n}\n\nbool legalMove(const Move& mv) {\n    int x1 = mv.x1, y1 = mv.y1;\n    int x2 = mv.x2, y2 = mv.y2;\n    int x3 = mv.x3, y3 = mv.y3;\n    int x4 = mv.x4, y4 = mv.y4;\n\n    if (!inside(x1, y1) || !inside(x2, y2) || !inside(x3, y3) || !inside(x4, y4)) return false;\n    if (dotGrid[x1][y1]) return false;\n    if (!dotGrid[x2][y2] || !dotGrid[x3][y3] || !dotGrid[x4][y4]) return false;\n\n    if (!checkSideNoDotAndNoSeg(x1, y1, x2, y2, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x2, y2, x3, y3, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x3, y3, x4, y4, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x4, y4, x1, y1, x2, y2, x3, y3, x4, y4)) return false;\n\n    return true;\n}\n\nvoid applyMove(const Move& mv) {\n    dotGrid[mv.x1][mv.y1] = 1;\n\n    addSideSegments(mv.x1, mv.y1, mv.x2, mv.y2);\n    addSideSegments(mv.x2, mv.y2, mv.x3, mv.y3);\n    addSideSegments(mv.x3, mv.y3, mv.x4, mv.y4);\n    addSideSegments(mv.x4, mv.y4, mv.x1, mv.y1);\n\n    answerMoves.push_back(mv);\n}\n\nvector<pair<int,int>> dirs = {\n    {1, 0}, {0, 1}, {-1, 0}, {0, -1},\n    {1, 1}, {-1, 1}, {-1, -1}, {1, -1}\n};\n\nlong long moveValue(const Move& mv) {\n    return 10000LL * mv.score - 120LL * mv.lenSum;\n}\n\nbool findBestMove(Move& best) {\n    bool found = false;\n    long long bestVal = LLONG_MIN;\n\n    vector<pair<int,int>> dots;\n    dots.reserve(N * N);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            if (dotGrid[x][y]) dots.push_back({x, y});\n        }\n    }\n\n    for (auto [x3, y3] : dots) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (elapsed > 4.85) return found;\n\n        for (auto [dx, dy] : dirs) {\n            int rdx = -dy;\n            int rdy = dx;\n\n            for (int sign : {-1, 1}) {\n                int bx = rdx * sign;\n                int by = rdy * sign;\n\n                for (int l1 = 1; l1 < N; l1++) {\n                    int x2 = x3 + dx * l1;\n                    int y2 = y3 + dy * l1;\n                    if (!inside(x2, y2)) break;\n                    if (!dotGrid[x2][y2]) continue;\n\n                    for (int l2 = 1; l2 < N; l2++) {\n                        int x4 = x3 + bx * l2;\n                        int y4 = y3 + by * l2;\n                        if (!inside(x4, y4)) break;\n                        if (!dotGrid[x4][y4]) continue;\n\n                        int x1 = x2 + bx * l2;\n                        int y1 = y2 + by * l2;\n                        if (!inside(x1, y1)) break;\n                        if (dotGrid[x1][y1]) continue;\n\n                        Move mv;\n                        mv.x1 = x1; mv.y1 = y1;\n                        mv.x2 = x2; mv.y2 = y2;\n                        mv.x3 = x3; mv.y3 = y3;\n                        mv.x4 = x4; mv.y4 = y4;\n                        mv.score = W[x1][y1];\n                        mv.lenSum = l1 + l2;\n\n                        if (!legalMove(mv)) continue;\n\n                        long long val = moveValue(mv);\n\n                        if (!found ||\n                            val > bestVal ||\n                            (val == bestVal && mv.lenSum < best.lenSum)) {\n                            found = true;\n                            bestVal = val;\n                            best = mv;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return found;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    dotGrid.assign(N, vector<unsigned char>(N, 0));\n    usedSeg.assign(N, vector<array<unsigned char, 4>>(N));\n    W.assign(N, vector<int>(N, 0));\n\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            int dx = x - c;\n            int dy = y - c;\n            W[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        dotGrid[x][y] = 1;\n    }\n\n    startTime = chrono::steady_clock::now();\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n        if (elapsed > 4.85) break;\n\n        Move best;\n        if (!findBestMove(best)) break;\n        applyMove(best);\n    }\n\n    cout << answerMoves.size() << '\\n';\n    for (auto &mv : answerMoves) {\n        cout << mv.x1 << ' ' << mv.y1 << ' '\n             << mv.x2 << ' ' << mv.y2 << ' '\n             << mv.x3 << ' ' << mv.y3 << ' '\n             << mv.x4 << ' ' << mv.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int T = 100;\n\nint f[T];\nint cntFlavor[4];\nint targetColor[100];\nint rank_of_flavor[4];\n\nconst char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    inline uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n};\n\nRNG global_rng(246813579);\n\nstruct Board {\n    unsigned char a[100];\n};\n\ninline void clear_board(Board& b) {\n    memset(b.a, 0, sizeof(b.a));\n}\n\nvoid tilt_board(const Board& src, Board& dst, int dir) {\n    memset(dst.a, 0, sizeof(dst.a));\n\n    if (dir == 0) { // F\n        for (int c = 0; c < N; c++) {\n            int w = 0;\n            for (int r = 0; r < N; r++) {\n                int v = src.a[r * 10 + c];\n                if (v) dst.a[w++ * 10 + c] = (unsigned char)v;\n            }\n        }\n    } else if (dir == 1) { // B\n        for (int c = 0; c < N; c++) {\n            int w = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                int v = src.a[r * 10 + c];\n                if (v) dst.a[w-- * 10 + c] = (unsigned char)v;\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < N; r++) {\n            int w = 0;\n            int base = r * 10;\n            for (int c = 0; c < N; c++) {\n                int v = src.a[base + c];\n                if (v) dst.a[base + w++] = (unsigned char)v;\n            }\n        }\n    } else { // R\n        for (int r = 0; r < N; r++) {\n            int w = N - 1;\n            int base = r * 10;\n            for (int c = N - 1; c >= 0; c--) {\n                int v = src.a[base + c];\n                if (v) dst.a[base + w--] = (unsigned char)v;\n            }\n        }\n    }\n}\n\nvoid place_by_index(Board& b, int p, int flavor) {\n    int cnt = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b.a[i] == 0) {\n            cnt++;\n            if (cnt == p) {\n                b.a[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\ninline int empty_count(const Board& b) {\n    int e = 0;\n    for (int i = 0; i < 100; i++) if (b.a[i] == 0) e++;\n    return e;\n}\n\nvoid place_random(Board& b, int flavor, RNG& rng) {\n    int e = empty_count(b);\n    int p = rng.next_int(1, e);\n    place_by_index(b, p, flavor);\n}\n\nint component_score(const Board& b) {\n    bool vis[100] = {};\n    int q[100];\n    int score = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b.a[s] == 0 || vis[s]) continue;\n\n        int col = b.a[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            int r = v / 10;\n            int c = v % 10;\n\n            if (r > 0) {\n                int nv = v - 10;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (r < 9) {\n                int nv = v + 10;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (c > 0) {\n                int nv = v - 1;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (c < 9) {\n                int nv = v + 1;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n        }\n\n        score += sz * sz;\n    }\n\n    return score;\n}\n\ninline int edge_score(const Board& b) {\n    int s = 0;\n\n    for (int r = 0; r < N; r++) {\n        int base = r * 10;\n        for (int c = 0; c < N; c++) {\n            int idx = base + c;\n            int x = b.a[idx];\n            if (!x) continue;\n            if (r + 1 < N && b.a[idx + 10] == x) s++;\n            if (c + 1 < N && b.a[idx + 1] == x) s++;\n        }\n    }\n\n    return s;\n}\n\ninline int target_match_score(const Board& b) {\n    int s = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b.a[i] && b.a[i] == targetColor[i]) s++;\n    }\n    return s;\n}\n\ndouble target_neighbor_score(const Board& b) {\n    double s = 0.0;\n\n    for (int i = 0; i < 100; i++) {\n        int x = b.a[i];\n        if (!x) continue;\n\n        int r = i / 10;\n        int c = i % 10;\n\n        for (int j = 0; j < 100; j++) {\n            if (targetColor[j] != x) continue;\n            int rr = j / 10;\n            int cc = j % 10;\n            int d = abs(r - rr) + abs(c - cc);\n            if (d <= 3) s += 4 - d;\n        }\n    }\n\n    return s;\n}\n\ndouble eval_target(const Board& b, int turn) {\n    double progress = turn * 0.01;\n\n    int comp = component_score(b);\n    int edge = edge_score(b);\n    int match = target_match_score(b);\n    double nearTarget = target_neighbor_score(b);\n\n    return comp * (10.0 + 38.0 * progress)\n         + edge * 18.0\n         + match * (90.0 * (1.0 - 0.3 * progress))\n         + nearTarget * (7.0 * (1.0 - 0.5 * progress));\n}\n\ndouble region_score(const Board& b) {\n    double s = 0.0;\n\n    for (int idx = 0; idx < 100; idx++) {\n        int x = b.a[idx];\n        if (!x) continue;\n\n        int r = idx / 10;\n        int c = idx % 10;\n        int rk = rank_of_flavor[x];\n\n        int tr, tc;\n        if (rk == 0) {\n            tr = 1; tc = 1;\n        } else if (rk == 1) {\n            tr = 8; tc = 8;\n        } else {\n            tr = 1; tc = 8;\n        }\n\n        int d = abs(r - tr) + abs(c - tc);\n        s += 18 - d;\n\n        if (rk == 0) s += (N - r) * 0.25 + (N - c) * 0.15;\n        else if (rk == 1) s += r * 0.25 + c * 0.15;\n        else s += (N - r) * 0.25 + c * 0.15;\n    }\n\n    return s;\n}\n\ndouble eval_region(const Board& b, int turn) {\n    double progress = turn * 0.01;\n\n    int comp = component_score(b);\n    int edge = edge_score(b);\n    double reg = region_score(b);\n\n    return comp * (12.0 + 35.0 * progress)\n         + edge * 20.0\n         + reg * (2.0 * (1.0 - progress) + 0.2);\n}\n\ndouble eval_component(const Board& b, int turn) {\n    double progress = turn * 0.01;\n    int comp = component_score(b);\n    int edge = edge_score(b);\n\n    return comp * (22.0 + 45.0 * progress)\n         + edge * (28.0 + 10.0 * progress);\n}\n\ndouble eval_mixed(const Board& b, int turn) {\n    double progress = turn * 0.01;\n\n    double wt = 0.55 - 0.15 * progress;\n    double wr = 0.30;\n    double wc = 0.15 + 0.15 * progress;\n\n    return eval_target(b, turn) * wt\n         + eval_region(b, turn) * wr\n         + eval_component(b, turn) * wc;\n}\n\nint greedy_dir_policy(const Board& b, int turn, int policy) {\n    int best = 0;\n    double bestVal = -1e100;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb;\n        tilt_board(b, nb, d);\n\n        double val;\n        if (policy == 0) val = eval_target(nb, turn);\n        else if (policy == 1) val = eval_region(nb, turn);\n        else if (policy == 2) val = eval_component(nb, turn);\n        else val = eval_mixed(nb, turn);\n\n        if (d == 0) val += 0.003;\n        if (d == 2) val += 0.002;\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\ndouble rollout_limited(Board b, int nextTurn, int horizon, RNG rng, int policy) {\n    int endTurn = min(T, nextTurn + horizon - 1);\n\n    for (int turn = nextTurn; turn <= endTurn; turn++) {\n        place_random(b, f[turn - 1], rng);\n\n        int gd = greedy_dir_policy(b, turn, policy);\n        Board nb;\n        tilt_board(b, nb, gd);\n        b = nb;\n    }\n\n    if (endTurn >= 88) {\n        return component_score(b) * 1000.0 + edge_score(b) * 10.0;\n    }\n\n    return eval_mixed(b, endTurn);\n}\n\nint choose_dir(const Board& current, int turn) {\n    int rolloutCalls;\n    int horizon;\n\n    // rolloutCalls means total rollout simulations per direction.\n    // Policies cycle among target / region / component.\n    if (turn <= 18) {\n        rolloutCalls = 8;\n        horizon = 30;\n    } else if (turn <= 38) {\n        rolloutCalls = 7;\n        horizon = 26;\n    } else if (turn <= 58) {\n        rolloutCalls = 6;\n        horizon = 22;\n    } else if (turn <= 76) {\n        rolloutCalls = 5;\n        horizon = 18;\n    } else if (turn <= 88) {\n        rolloutCalls = 4;\n        horizon = T - turn;\n    } else {\n        return greedy_dir_policy(current, turn, 3);\n    }\n\n    int bestDir = 0;\n    double bestVal = -1e100;\n\n    // Common random seeds for all directions make comparison less noisy.\n    uint64_t seeds[12];\n    for (int k = 0; k < rolloutCalls; k++) {\n        seeds[k] = global_rng.next_u64() ^ ((uint64_t)turn << 32) ^ (uint64_t)k;\n    }\n\n    for (int d = 0; d < 4; d++) {\n        Board after;\n        tilt_board(current, after, d);\n\n        double sum = eval_mixed(after, turn) * 0.45\n                   + component_score(after) * 20.0;\n\n        for (int k = 0; k < rolloutCalls; k++) {\n            int policy = k % 3;\n            uint64_t seed = seeds[k] ^ ((uint64_t)d * 0x9e3779b97f4a7c15ULL);\n            RNG rr(seed);\n\n            sum += rollout_limited(after, turn + 1, horizon, rr, policy);\n        }\n\n        double avg = sum / (rolloutCalls + 0.45);\n\n        if (d == 0) avg += 0.01;\n        if (d == 2) avg += 0.005;\n\n        if (avg > bestVal) {\n            bestVal = avg;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nvoid build_target_board() {\n    vector<int> flavors = {1, 2, 3};\n\n    sort(flavors.begin(), flavors.end(), [&](int a, int b) {\n        return cntFlavor[a] > cntFlavor[b];\n    });\n\n    for (int i = 0; i < 3; i++) {\n        rank_of_flavor[flavors[i]] = i;\n    }\n\n    vector<int> path;\n    path.reserve(100);\n\n    // Horizontal snake target.\n    for (int r = 0; r < N; r++) {\n        if (r % 2 == 0) {\n            for (int c = 0; c < N; c++) path.push_back(r * 10 + c);\n        } else {\n            for (int c = N - 1; c >= 0; c--) path.push_back(r * 10 + c);\n        }\n    }\n\n    int ptr = 0;\n    for (int fl : flavors) {\n        for (int k = 0; k < cntFlavor[fl]; k++) {\n            targetColor[path[ptr++]] = fl;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < T; i++) {\n        cin >> f[i];\n        cntFlavor[f[i]]++;\n    }\n\n    build_target_board();\n\n    Board cur;\n    clear_board(cur);\n\n    for (int turn = 1; turn <= T; turn++) {\n        int p;\n        if (!(cin >> p)) break;\n\n        place_by_index(cur, p, f[turn - 1]);\n\n        int dir = choose_dir(cur, turn);\n\n        Board nb;\n        tilt_board(cur, nb, dir);\n        cur = nb;\n\n        cout << DIR_CH[dir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint M, N;\ndouble EPS;\n\nstruct Code {\n    array<int, 3> sz{};       // sorted descending clique sizes\n    string graph;\n    vector<double> edeg;      // expected sorted degrees descending\n    vector<double> prefix;    // prefix sums of edeg\n    double eedges = 0;\n    double edeg2 = 0;\n};\n\nint choose_N(int M, double e) {\n    if (e < 1e-12) {\n        int n = 4;\n        while (n * (n - 1) / 2 < M) n++;\n        return n;\n    }\n\n    // Larger N is almost always worth it when noise is nontrivial.\n    // For tiny noise, save N for score.\n    if (e <= 0.01) return max(8, min(100, M / 2 + 10));\n    if (e <= 0.03) return max(18, min(100, M / 2 + 18));\n    if (e <= 0.06) return max(32, min(100, M / 2 + 32));\n    if (e <= 0.10) return max(50, min(100, M / 2 + 50));\n    if (e <= 0.15) return max(72, min(100, M / 2 + 65));\n    return 100;\n}\n\nstring make_multi_clique_graph(array<int, 3> s) {\n    string out;\n    out.reserve(N * (N - 1) / 2);\n\n    vector<int> belong(N, -1);\n    int pos = 0;\n    for (int g = 0; g < 3; g++) {\n        for (int i = 0; i < s[g] && pos < N; i++, pos++) {\n            belong[pos] = g;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = (belong[i] >= 0 && belong[i] == belong[j]);\n            out.push_back(e ? '1' : '0');\n        }\n    }\n    return out;\n}\n\nvector<int> parse_degrees_desc(const string& h) {\n    vector<int> d(N, 0);\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (h[p] == '1') {\n                d[i]++;\n                d[j]++;\n            }\n            p++;\n        }\n    }\n    sort(d.begin(), d.end(), greater<int>());\n    return d;\n}\n\nCode make_code(array<int, 3> s) {\n    sort(s.begin(), s.end(), greater<int>());\n\n    Code c;\n    c.sz = s;\n    c.graph = make_multi_clique_graph(s);\n\n    int E = N * (N - 1) / 2;\n    int origEdges = 0;\n    for (int x : s) origEdges += x * (x - 1) / 2;\n\n    c.eedges = (1.0 - EPS) * origEdges + EPS * (E - origEdges);\n\n    double base = EPS * (N - 1);\n    double coef = 1.0 - 2.0 * EPS;\n\n    c.edeg.clear();\n    for (int x : s) {\n        for (int i = 0; i < x; i++) {\n            c.edeg.push_back(base + coef * (x - 1));\n        }\n    }\n    int used = s[0] + s[1] + s[2];\n    for (int i = used; i < N; i++) c.edeg.push_back(base);\n\n    sort(c.edeg.begin(), c.edeg.end(), greater<double>());\n\n    c.prefix.assign(N + 1, 0.0);\n    for (int i = 0; i < N; i++) c.prefix[i + 1] = c.prefix[i] + c.edeg[i];\n\n    c.edeg2 = 0;\n    for (double x : c.edeg) c.edeg2 += x * x;\n\n    return c;\n}\n\nbool same_code(const Code& a, const Code& b) {\n    return a.sz == b.sz;\n}\n\ndouble profile_distance(const Code& x, const Code& y) {\n    double degreeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N - 1))) + 1.0;\n    double edgeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N * (N - 1) / 2.0))) + 1.0;\n\n    double s = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double d = (x.edeg[i] - y.edeg[i]) / degreeSigma;\n        s += d * d;\n    }\n    s /= N;\n\n    double e = (x.eedges - y.eedges) / edgeSigma;\n    s += 2.3 * e * e;\n\n    double d2scale = max(10.0, N * N * degreeSigma);\n    double d2 = (x.edeg2 - y.edeg2) / d2scale;\n    s += 0.25 * d2 * d2;\n\n    // Plateau-boundary prefix distances.\n    int px = 0;\n    for (int t = 0; t < 3; t++) {\n        px += x.sz[t];\n        if (px <= 0 || px > N) continue;\n\n        double dx = x.prefix[px] - y.prefix[px];\n        double scale = max(1.0, sqrt((double)px) * degreeSigma);\n        s += 0.25 * (dx / scale) * (dx / scale);\n    }\n\n    int py = 0;\n    for (int t = 0; t < 3; t++) {\n        py += y.sz[t];\n        if (py <= 0 || py > N) continue;\n\n        double dy = x.prefix[py] - y.prefix[py];\n        double scale = max(1.0, sqrt((double)py) * degreeSigma);\n        s += 0.25 * (dy / scale) * (dy / scale);\n    }\n\n    return s;\n}\n\ndouble obs_distance(const vector<int>& deg,\n                    const vector<double>& obsPrefix,\n                    int obsEdges,\n                    double obsDeg2,\n                    const Code& c) {\n    double degreeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N - 1))) + 1.0;\n    double edgeSigma = sqrt(max(1.0, EPS * (1.0 - EPS) * (N * (N - 1) / 2.0))) + 1.0;\n\n    double s = 0.0;\n\n    // Full sorted degree profile.\n    double prof = 0.0;\n    for (int i = 0; i < N; i++) {\n        double d = (deg[i] - c.edeg[i]) / degreeSigma;\n        prof += d * d;\n    }\n    s += prof / N;\n\n    // Edge count.\n    double e = (obsEdges - c.eedges) / edgeSigma;\n    s += 2.7 * e * e;\n\n    // Degree second moment.\n    double d2scale = max(10.0, N * N * degreeSigma);\n    double d2 = (obsDeg2 - c.edeg2) / d2scale;\n    s += 0.35 * d2 * d2;\n\n    // Plateau prefix sums.\n    int p = 0;\n    for (int t = 0; t < 3; t++) {\n        p += c.sz[t];\n        if (p <= 0 || p > N) continue;\n\n        double diff = obsPrefix[p] - c.prefix[p];\n        double scale = max(1.0, sqrt((double)p) * degreeSigma);\n        s += 0.85 * (diff / scale) * (diff / scale);\n    }\n\n    // Quantile checkpoints improve robustness when plateau boundaries are blurred.\n    static const double qs[] = {0.10, 0.20, 0.35, 0.50, 0.70, 0.85};\n    for (double q : qs) {\n        int idx = min(N - 1, max(0, (int)(q * (N - 1))));\n        double diff = deg[idx] - c.edeg[idx];\n        s += 0.10 * (diff / degreeSigma) * (diff / degreeSigma);\n    }\n\n    return s;\n}\n\nvector<Code> build_codebook() {\n    vector<Code> cand;\n\n    int minClique;\n    if (EPS <= 0.03) minClique = 0;\n    else if (EPS <= 0.08) minClique = 3;\n    else if (EPS <= 0.15) minClique = 5;\n    else if (EPS <= 0.25) minClique = 7;\n    else if (EPS <= 0.35) minClique = 9;\n    else minClique = 11;\n\n    // Candidate generation.\n    // Enumerating all triples up to N=100 is about 176k, acceptable.\n    for (int a = minClique; a <= N; a++) {\n        for (int b = 0; b <= a; b++) {\n            if (b > 0 && b < minClique) continue;\n            for (int c = 0; c <= b; c++) {\n                if (c > 0 && c < minClique) continue;\n                if (a + b + c > N) continue;\n                if (a == 0 && b == 0 && c == 0) continue;\n\n                int iso = N - a - b - c;\n                if (EPS >= 0.10 && iso < 2) continue;\n\n                cand.push_back(make_code({a, b, c}));\n            }\n        }\n    }\n\n    if (EPS <= 0.10) cand.push_back(make_code({0, 0, 0}));\n\n    // To keep greedy selection fast, prefilter candidates by edge count buckets\n    // when there are too many.\n    if ((int)cand.size() > 25000) {\n        sort(cand.begin(), cand.end(), [](const Code& x, const Code& y) {\n            if (x.eedges != y.eedges) return x.eedges < y.eedges;\n            return x.sz < y.sz;\n        });\n\n        vector<Code> filtered;\n        int B = 25000;\n        filtered.reserve(B);\n\n        for (int i = 0; i < B; i++) {\n            int idx = (long long)i * (cand.size() - 1) / max(1, B - 1);\n            filtered.push_back(cand[idx]);\n        }\n\n        // Add some balanced triple candidates explicitly.\n        for (int a = minClique; a <= N; a += max(1, N / 30)) {\n            for (int b = 0; b <= a; b += max(1, N / 30)) {\n                for (int c = 0; c <= b; c += max(1, N / 30)) {\n                    if (a + b + c <= N && !(a == 0 && b == 0 && c == 0)) {\n                        filtered.push_back(make_code({a, b, c}));\n                    }\n                }\n            }\n        }\n\n        sort(filtered.begin(), filtered.end(), [](const Code& x, const Code& y) {\n            if (x.sz != y.sz) return x.sz < y.sz;\n            return x.eedges < y.eedges;\n        });\n        filtered.erase(unique(filtered.begin(), filtered.end(), same_code), filtered.end());\n        cand.swap(filtered);\n    }\n\n    sort(cand.begin(), cand.end(), [](const Code& x, const Code& y) {\n        if (x.eedges != y.eedges) return x.eedges < y.eedges;\n        return x.sz < y.sz;\n    });\n\n    vector<Code> selected;\n    selected.reserve(M);\n\n    if (!cand.empty()) {\n        selected.push_back(cand.front());\n        if ((int)selected.size() < M) selected.push_back(cand.back());\n        if ((int)selected.size() < M) selected.push_back(cand[cand.size() / 2]);\n        if ((int)selected.size() < M) selected.push_back(cand[cand.size() / 4]);\n        if ((int)selected.size() < M) selected.push_back(cand[cand.size() * 3 / 4]);\n    }\n\n    sort(selected.begin(), selected.end(), [](const Code& x, const Code& y) {\n        return x.sz < y.sz;\n    });\n    selected.erase(unique(selected.begin(), selected.end(), same_code), selected.end());\n\n    vector<double> mind(cand.size(), 1e100);\n    for (int i = 0; i < (int)cand.size(); i++) {\n        for (auto &s : selected) {\n            if (same_code(cand[i], s)) {\n                mind[i] = -1;\n                break;\n            }\n            mind[i] = min(mind[i], profile_distance(cand[i], s));\n        }\n    }\n\n    while ((int)selected.size() < M) {\n        int best = -1;\n        double bestVal = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (mind[i] < 0) continue;\n\n            double val = mind[i];\n\n            int iso = N - cand[i].sz[0] - cand[i].sz[1] - cand[i].sz[2];\n            if (EPS >= 0.20 && iso < 5) val *= 0.97;\n\n            // Prefer candidates not having too many equal plateau sizes,\n            // because equal cliques collapse into one plateau.\n            if (cand[i].sz[1] > 0 && cand[i].sz[0] == cand[i].sz[1]) val *= 0.96;\n            if (cand[i].sz[2] > 0 && cand[i].sz[1] == cand[i].sz[2]) val *= 0.96;\n\n            if (val > bestVal) {\n                bestVal = val;\n                best = i;\n            }\n        }\n\n        if (best < 0) break;\n\n        selected.push_back(cand[best]);\n        mind[best] = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (mind[i] < 0) continue;\n            mind[i] = min(mind[i], profile_distance(cand[i], cand[best]));\n        }\n    }\n\n    // Fallback.\n    for (int r = 1; (int)selected.size() < M && r <= N; r++) {\n        selected.push_back(make_code({r, 0, 0}));\n    }\n\n    sort(selected.begin(), selected.end(), [](const Code& x, const Code& y) {\n        if (x.eedges != y.eedges) return x.eedges < y.eedges;\n        return x.sz < y.sz;\n    });\n\n    if ((int)selected.size() > M) selected.resize(M);\n    return selected;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> M >> EPS;\n    N = choose_N(M, EPS);\n    int E = N * (N - 1) / 2;\n\n    if (EPS < 1e-12) {\n        cout << N << '\\n';\n        for (int k = 0; k < M; k++) {\n            string s(E, '0');\n            for (int i = 0; i < k; i++) s[i] = '1';\n            cout << s << '\\n';\n        }\n        cout.flush();\n\n        for (int q = 0; q < 100; q++) {\n            string H;\n            cin >> H;\n            int ones = 0;\n            for (char c : H) ones += (c == '1');\n            cout << min(M - 1, ones) << '\\n';\n            cout.flush();\n        }\n        return 0;\n    }\n\n    vector<Code> codebook = build_codebook();\n\n    cout << N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << codebook[k].graph << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        vector<int> deg = parse_degrees_desc(H);\n        vector<double> pref(N + 1, 0.0);\n        for (int i = 0; i < N; i++) pref[i + 1] = pref[i] + deg[i];\n\n        int obsEdges = (int)(pref[N] / 2.0 + 0.5);\n\n        double obsDeg2 = 0;\n        for (int x : deg) obsDeg2 += 1.0 * x * x;\n\n        int best = 0;\n        double bestScore = 1e300;\n\n        for (int k = 0; k < M; k++) {\n            double sc = obs_distance(deg, pref, obsEdges, obsDeg2, codebook[k]);\n            if (sc < bestScore) {\n                bestScore = sc;\n                best = k;\n            }\n        }\n\n        cout << best << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    double mx, my;\n};\n\nstatic uint64_t rng_state = 88172645463325252ull;\n\nuint64_t xorshift64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\nint rnd_int(int l, int r) {\n    return l + (int)(xorshift64() % (uint64_t)(r - l + 1));\n}\n\ndouble rnd01() {\n    return (xorshift64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> adj(N);\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 = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n\n    vector<double> X(N), Y(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    for (int i = 0; i < M; i++) {\n        edges[i].mx = (X[edges[i].u] + X[edges[i].v]) * 0.5;\n        edges[i].my = (Y[edges[i].u] + Y[edges[i].v]) * 0.5;\n    }\n\n    const long long INF = (1LL << 60);\n\n    vector<int> banned(M, 0);\n    int banVersion = 1;\n\n    auto markRemoved = [&](const vector<int>* rem) {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n        if (rem) {\n            for (int e : *rem) {\n                if (0 <= e && e < M) banned[e] = banVersion;\n            }\n        }\n    };\n\n    auto dijkstra = [&](int s, const vector<int>* rem) -> vector<long long> {\n        markRemoved(rem);\n\n        vector<long long> dist(N, INF);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != dist[u]) continue;\n\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n                long long nd = du + edges[ei].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pq.push({nd, v});\n                }\n            }\n        }\n\n        return dist;\n    };\n\n    // ---------- Approximate edge importance ----------\n    vector<double> imp(M, 1.0);\n\n    vector<int> landmarks;\n    {\n        vector<pair<double,int>> vals;\n\n        auto addExtreme = [&](auto func) {\n            vals.clear();\n            for (int i = 0; i < N; i++) vals.push_back({func(i), i});\n            sort(vals.begin(), vals.end());\n            landmarks.push_back(vals.front().second);\n            landmarks.push_back(vals.back().second);\n        };\n\n        addExtreme([&](int i){ return X[i] + Y[i]; });\n        addExtreme([&](int i){ return X[i] - Y[i]; });\n        addExtreme([&](int i){ return X[i]; });\n        addExtreme([&](int i){ return Y[i]; });\n\n        int samples = min(N, 36);\n        while ((int)landmarks.size() < samples) landmarks.push_back(rnd_int(0, N - 1));\n\n        sort(landmarks.begin(), landmarks.end());\n        landmarks.erase(unique(landmarks.begin(), landmarks.end()), landmarks.end());\n    }\n\n    vector<long long> distTmp(N);\n    vector<int> parEdge(N);\n\n    for (int s : landmarks) {\n        fill(distTmp.begin(), distTmp.end(), INF);\n        fill(parEdge.begin(), parEdge.end(), -1);\n\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n\n        distTmp[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n\n            if (du != distTmp[u]) continue;\n\n            for (auto [v, ei] : adj[u]) {\n                long long nd = du + edges[ei].w;\n                if (nd < distTmp[v]) {\n                    distTmp[v] = nd;\n                    parEdge[v] = ei;\n                    pq.push({nd, v});\n                }\n            }\n        }\n\n        for (int v = 0; v < N; v++) {\n            if (parEdge[v] >= 0) imp[parEdge[v]] += 1.0;\n        }\n    }\n\n    double maxImp = *max_element(imp.begin(), imp.end());\n    double sumImp = 0.0;\n\n    for (int i = 0; i < M; i++) {\n        imp[i] = sqrt(imp[i] / maxImp);\n        imp[i] += 0.12 * sqrt((double)edges[i].w / 1000000.0);\n        sumImp += imp[i];\n    }\n\n    double targetImp = sumImp / D;\n\n    // ---------- Connectivity ----------\n    auto isConnectedDay = [&](const vector<int>& rem) -> bool {\n        markRemoved(&rem);\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n\n        vis[0] = 1;\n        q.push(0);\n\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n\n        return cnt == N;\n    };\n\n    auto isConnectedWithExtra = [&](const vector<int>& rem, int extra) -> bool {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n\n        for (int e : rem) {\n            if (0 <= e && e < M) banned[e] = banVersion;\n        }\n        if (0 <= extra && extra < M) banned[extra] = banVersion;\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n\n        vis[0] = 1;\n        q.push(0);\n\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n\n        return cnt == N;\n    };\n\n    // ---------- State ----------\n    vector<int> ans(M, -1);\n    vector<int> load(D, 0);\n    vector<double> dayImp(D, 0.0);\n    vector<vector<int>> dayEdges(D);\n    vector<vector<int>> dayVertCnt(D, vector<int>(N, 0));\n\n    auto pairCost = [&](int a, int b) -> double {\n        double dx = edges[a].mx - edges[b].mx;\n        double dy = edges[a].my - edges[b].my;\n        double d2 = dx * dx + dy * dy;\n\n        double c = 18000.0 / (d2 + 900.0);\n\n        if (edges[a].u == edges[b].u || edges[a].u == edges[b].v ||\n            edges[a].v == edges[b].u || edges[a].v == edges[b].v) {\n            c += 2.5;\n        }\n\n        return c * (0.7 + 0.9 * (imp[a] + imp[b]));\n    };\n\n    auto addCostToDay = [&](int e, int d) -> double {\n        double c = 0.0;\n\n        for (int f : dayEdges[d]) c += pairCost(e, f);\n\n        c += 2.5 * imp[e] * dayImp[d];\n\n        int u = edges[e].u;\n        int v = edges[e].v;\n\n        c += 8.0 * dayVertCnt[d][u];\n        c += 8.0 * dayVertCnt[d][v];\n\n        double targetLoad = (double)M / D;\n        c += 0.4 * max(0.0, load[d] + 1 - targetLoad);\n\n        double ni = dayImp[d] + imp[e];\n        if (ni > targetImp) {\n            c += 12.0 * (ni - targetImp) * (ni - targetImp);\n        }\n\n        return c;\n    };\n\n    auto assignEdge = [&](int e, int d) {\n        if (e < 0 || e >= M || d < 0 || d >= D) return;\n        ans[e] = d;\n        load[d]++;\n        dayImp[d] += imp[e];\n        dayEdges[d].push_back(e);\n        dayVertCnt[d][edges[e].u]++;\n        dayVertCnt[d][edges[e].v]++;\n    };\n\n    auto removeFromDayVec = [&](int e, int d) {\n        auto &vec = dayEdges[d];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i] == e) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n\n    auto removeEdge = [&](int e, int d) {\n        if (e < 0 || e >= M || d < 0 || d >= D) return;\n        if (ans[e] != d) return;\n\n        ans[e] = -1;\n        load[d]--;\n        dayImp[d] -= imp[e];\n\n        dayVertCnt[d][edges[e].u]--;\n        dayVertCnt[d][edges[e].v]--;\n\n        removeFromDayVec(e, d);\n    };\n\n    auto edgeContribution = [&](int e, int d) -> double {\n        double c = 0.0;\n\n        for (int f : dayEdges[d]) {\n            if (f != e) c += pairCost(e, f);\n        }\n\n        c += 2.5 * imp[e] * max(0.0, dayImp[d] - imp[e]);\n\n        int u = edges[e].u;\n        int v = edges[e].v;\n\n        c += 8.0 * max(0, dayVertCnt[d][u] - 1);\n        c += 8.0 * max(0, dayVertCnt[d][v] - 1);\n\n        return c;\n    };\n\n    // ---------- Initial construction ----------\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabs(imp[a] - imp[b]) > 1e-12) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    for (int e : ord) {\n        int bestD = -1;\n        double best = 1e100;\n\n        for (int d = 0; d < D; d++) {\n            if (load[d] >= K) continue;\n\n            if (!isConnectedWithExtra(dayEdges[d], e)) continue;\n\n            double c = addCostToDay(e, d);\n\n            if (c < best) {\n                best = c;\n                bestD = d;\n            }\n        }\n\n        if (bestD < 0) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= K) continue;\n\n                double c = addCostToDay(e, d) + 1e6;\n\n                if (c < best) {\n                    best = c;\n                    bestD = d;\n                }\n            }\n        }\n\n        if (bestD < 0) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] < K) {\n                    bestD = d;\n                    break;\n                }\n            }\n        }\n\n        if (bestD < 0) bestD = 0;\n\n        assignEdge(e, bestD);\n    }\n\n    auto repairDisconnected = [&]() {\n        bool changed = true;\n        int rounds = 0;\n\n        while (changed && rounds < 200) {\n            changed = false;\n            rounds++;\n\n            for (int d = 0; d < D; d++) {\n                while (!isConnectedDay(dayEdges[d])) {\n                    if (dayEdges[d].empty()) break;\n\n                    int chosen = -1;\n                    double worst = -1;\n\n                    for (int e : dayEdges[d]) {\n                        double c = edgeContribution(e, d) + 100.0 * imp[e];\n\n                        if (c > worst) {\n                            worst = c;\n                            chosen = e;\n                        }\n                    }\n\n                    if (chosen < 0) break;\n\n                    int src = d;\n                    removeEdge(chosen, src);\n\n                    int bestD = -1;\n                    double best = 1e100;\n\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd == src) continue;\n                        if (load[nd] >= K) continue;\n                        if (!isConnectedWithExtra(dayEdges[nd], chosen)) continue;\n\n                        double c = addCostToDay(chosen, nd);\n\n                        if (c < best) {\n                            best = c;\n                            bestD = nd;\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        for (int nd = 0; nd < D; nd++) {\n                            if (nd == src) continue;\n                            if (load[nd] >= K) continue;\n\n                            double c = addCostToDay(chosen, nd) + 1e6;\n\n                            if (c < best) {\n                                best = c;\n                                bestD = nd;\n                            }\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        assignEdge(chosen, src);\n                        break;\n                    } else {\n                        assignEdge(chosen, bestD);\n                        changed = true;\n                    }\n                }\n            }\n        }\n    };\n\n    repairDisconnected();\n\n    // ---------- Surrogate local search ----------\n    double phase1Limit = 3.0;\n\n    while (timer.elapsed() < phase1Limit) {\n        if ((xorshift64() & 3) != 0) {\n            int e = rnd_int(0, M - 1);\n            int a = ans[e];\n            int b = rnd_int(0, D - 1);\n\n            if (a == b || b < 0 || b >= D || load[b] >= K) continue;\n\n            double oldc = edgeContribution(e, a);\n\n            removeEdge(e, a);\n\n            if (!isConnectedDay(dayEdges[a]) || !isConnectedWithExtra(dayEdges[b], e)) {\n                assignEdge(e, a);\n                continue;\n            }\n\n            double newc = addCostToDay(e, b);\n\n            double t = max(0.001, 0.05 * (1.0 - timer.elapsed() / phase1Limit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) assignEdge(e, b);\n            else assignEdge(e, a);\n\n        } else {\n            int e1 = rnd_int(0, M - 1);\n            int e2 = rnd_int(0, M - 1);\n\n            if (e1 == e2) continue;\n\n            int d1 = ans[e1];\n            int d2 = ans[e2];\n\n            if (d1 == d2 || d1 < 0 || d2 < 0) continue;\n\n            double oldc = edgeContribution(e1, d1) + edgeContribution(e2, d2);\n\n            removeEdge(e1, d1);\n            removeEdge(e2, d2);\n\n            bool ok1 = isConnectedWithExtra(dayEdges[d1], e2);\n            bool ok2 = isConnectedWithExtra(dayEdges[d2], e1);\n\n            if (!ok1 || !ok2) {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n                continue;\n            }\n\n            double newc = addCostToDay(e1, d2) + addCostToDay(e2, d1);\n\n            double t = max(0.001, 0.05 * (1.0 - timer.elapsed() / phase1Limit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) {\n                assignEdge(e1, d2);\n                assignEdge(e2, d1);\n            } else {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n            }\n        }\n    }\n\n    repairDisconnected();\n\n    // ---------- Sampled true-score sources ----------\n    vector<int> scoreSources;\n    {\n        vector<pair<double,int>> vals;\n\n        auto addExtreme = [&](auto func) {\n            vals.clear();\n            for (int i = 0; i < N; i++) vals.push_back({func(i), i});\n            sort(vals.begin(), vals.end());\n            scoreSources.push_back(vals.front().second);\n            scoreSources.push_back(vals.back().second);\n        };\n\n        addExtreme([&](int i){ return X[i] + Y[i]; });\n        addExtreme([&](int i){ return X[i] - Y[i]; });\n        addExtreme([&](int i){ return X[i]; });\n        addExtreme([&](int i){ return Y[i]; });\n\n        int S0 = min(N, 24);\n\n        while ((int)scoreSources.size() < S0) {\n            scoreSources.push_back(rnd_int(0, N - 1));\n        }\n\n        sort(scoreSources.begin(), scoreSources.end());\n        scoreSources.erase(unique(scoreSources.begin(), scoreSources.end()), scoreSources.end());\n    }\n\n    int S = scoreSources.size();\n    vector<vector<long long>> origDist(S);\n\n    for (int i = 0; i < S; i++) {\n        origDist[i] = dijkstra(scoreSources[i], nullptr);\n    }\n\n    auto sampledDayScore = [&](const vector<int>& rem) -> double {\n        double total = 0.0;\n\n        for (int si = 0; si < S; si++) {\n            vector<long long> nd = dijkstra(scoreSources[si], &rem);\n            const auto &od = origDist[si];\n\n            for (int v = 0; v < N; v++) {\n                if (v == scoreSources[si]) continue;\n\n                if (nd[v] >= INF / 4) {\n                    total += 1e9;\n                } else {\n                    total += (double)(nd[v] - od[v]);\n                }\n            }\n        }\n\n        return total / max(1, S);\n    };\n\n    vector<double> dayScore(D);\n\n    auto recomputeDayScore = [&](int d) {\n        dayScore[d] = sampledDayScore(dayEdges[d]);\n    };\n\n    for (int d = 0; d < D; d++) recomputeDayScore(d);\n\n    auto totalSampleScore = [&]() {\n        double s = 0.0;\n        for (double x : dayScore) s += x;\n        return s;\n    };\n\n    // ---------- Direct sampled-score local search ----------\n    double phase2Limit = 5.72;\n\n    while (timer.elapsed() < phase2Limit) {\n        int worstDay = max_element(dayScore.begin(), dayScore.end()) - dayScore.begin();\n\n        bool improved = false;\n\n        vector<int> cand = dayEdges[worstDay];\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            return edgeContribution(a, worstDay) + 25.0 * imp[a] >\n                   edgeContribution(b, worstDay) + 25.0 * imp[b];\n        });\n\n        // Refined candidate ranking by actual sampled improvement from removing one edge.\n        vector<pair<double,int>> trueCand;\n        int evalCand = min((int)cand.size(), 8);\n\n        for (int i = 0; i < evalCand && timer.elapsed() < phase2Limit; i++) {\n            int e = cand[i];\n\n            removeEdge(e, worstDay);\n            bool ok = isConnectedDay(dayEdges[worstDay]);\n\n            double sc = 1e100;\n            if (ok) sc = sampledDayScore(dayEdges[worstDay]);\n\n            assignEdge(e, worstDay);\n\n            if (ok) {\n                double gain = dayScore[worstDay] - sc;\n                trueCand.push_back({gain, e});\n            }\n        }\n\n        if (!trueCand.empty()) {\n            sort(trueCand.rbegin(), trueCand.rend());\n            cand.clear();\n            for (auto [g, e] : trueCand) cand.push_back(e);\n        }\n\n        int tryEdges = min((int)cand.size(), 8);\n        double currentTotal = totalSampleScore();\n\n        for (int ii = 0; ii < tryEdges && timer.elapsed() < phase2Limit; ii++) {\n            int e = cand[ii];\n            int a = worstDay;\n\n            vector<int> ds(D);\n            iota(ds.begin(), ds.end(), 0);\n\n            sort(ds.begin(), ds.end(), [&](int x, int y) {\n                double cx = dayScore[x] + (load[x] >= K ? 1e100 : 0.0) + 0.05 * addCostToDay(e, x);\n                double cy = dayScore[y] + (load[y] >= K ? 1e100 : 0.0) + 0.05 * addCostToDay(e, y);\n                return cx < cy;\n            });\n\n            for (int b : ds) {\n                if (a == b || load[b] >= K) continue;\n\n                removeEdge(e, a);\n\n                if (!isConnectedDay(dayEdges[a]) || !isConnectedWithExtra(dayEdges[b], e)) {\n                    assignEdge(e, a);\n                    continue;\n                }\n\n                assignEdge(e, b);\n\n                double oldA = dayScore[a];\n                double oldB = dayScore[b];\n\n                double newA = sampledDayScore(dayEdges[a]);\n                double newB = sampledDayScore(dayEdges[b]);\n\n                double newTotal = currentTotal - oldA - oldB + newA + newB;\n\n                if (newTotal + 1e-7 < currentTotal) {\n                    dayScore[a] = newA;\n                    dayScore[b] = newB;\n                    improved = true;\n                    currentTotal = newTotal;\n                    break;\n                } else {\n                    removeEdge(e, b);\n                    assignEdge(e, a);\n                }\n            }\n\n            if (improved) break;\n        }\n\n        if (improved) continue;\n\n        int swapTrials = 18;\n\n        for (int tt = 0; tt < swapTrials && timer.elapsed() < phase2Limit; tt++) {\n            int lim = min((int)cand.size(), 8);\n            if (lim <= 0) break;\n\n            int e1 = cand[rnd_int(0, lim - 1)];\n            int d1 = worstDay;\n\n            int d2 = rnd_int(0, D - 1);\n\n            if (d1 == d2 || dayEdges[d2].empty()) continue;\n\n            // Prefer high-conflict edge in destination.\n            int e2 = dayEdges[d2][rnd_int(0, (int)dayEdges[d2].size() - 1)];\n            if ((int)dayEdges[d2].size() >= 4) {\n                for (int rep = 0; rep < 3; rep++) {\n                    int t = dayEdges[d2][rnd_int(0, (int)dayEdges[d2].size() - 1)];\n                    if (edgeContribution(t, d2) > edgeContribution(e2, d2)) e2 = t;\n                }\n            }\n\n            double currentTotal = totalSampleScore();\n\n            removeEdge(e1, d1);\n            removeEdge(e2, d2);\n\n            bool ok1 = isConnectedWithExtra(dayEdges[d1], e2);\n            bool ok2 = isConnectedWithExtra(dayEdges[d2], e1);\n\n            if (!ok1 || !ok2) {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n                continue;\n            }\n\n            assignEdge(e1, d2);\n            assignEdge(e2, d1);\n\n            double old1 = dayScore[d1];\n            double old2 = dayScore[d2];\n\n            double new1 = sampledDayScore(dayEdges[d1]);\n            double new2 = sampledDayScore(dayEdges[d2]);\n\n            double newTotal = currentTotal - old1 - old2 + new1 + new2;\n\n            if (newTotal + 1e-7 < currentTotal) {\n                dayScore[d1] = new1;\n                dayScore[d2] = new2;\n                improved = true;\n                break;\n            } else {\n                removeEdge(e1, d2);\n                removeEdge(e2, d1);\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n            }\n        }\n\n        if (!improved) {\n            dayScore[worstDay] *= 0.996;\n        }\n    }\n\n    repairDisconnected();\n\n    // ---------- Final legality check ----------\n    bool legal = true;\n    vector<int> cnt(D, 0);\n\n    for (int e = 0; e < M; e++) {\n        if (ans[e] < 0 || ans[e] >= D) {\n            legal = false;\n            break;\n        }\n        cnt[ans[e]]++;\n    }\n\n    for (int d = 0; d < D; d++) {\n        if (cnt[d] > K) legal = false;\n    }\n\n    if (!legal) {\n        vector<int> out(M);\n        vector<int> c(D, 0);\n\n        int d = 0;\n        for (int e = 0; e < M; e++) {\n            while (d < D && c[d] >= K) d++;\n            if (d >= D) d = D - 1;\n\n            out[e] = d + 1;\n            c[d]++;\n        }\n\n        for (int i = 0; i < M; i++) {\n            if (i) cout << ' ';\n            cout << out[i];\n        }\n        cout << '\\n';\n\n        return 0;\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << ans[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Seg {\n    int x, y, z, dir;\n    int run;\n};\n\nstruct Result {\n    vector<vector<int>> ans;\n    double eval;\n    int n;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for (int i = 0; i < 2; i++) {\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    const int N3 = D * D * D;\n\n    auto id = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    const int dx[3] = {1, 0, 0};\n    const int dy[3] = {0, 1, 0};\n    const int dz[3] = {0, 0, 1};\n\n    auto feasible = [&](int t, int x, int y, int z) {\n        return f[t][z][x] == '1' && r[t][z][y] == '1';\n    };\n\n    auto build_occ = [&](int seed) {\n        vector<vector<int>> occ(2, vector<int>(N3, 0));\n        mt19937 rng(1234567 + seed * 10007);\n\n        bool backward = (seed % 6 == 5);\n\n        for (int t = 0; t < 2; t++) {\n            vector<pair<int, int>> prev_pairs;\n\n            for (int zi = 0; zi < D; zi++) {\n                int z = backward ? (D - 1 - zi) : zi;\n\n                vector<int> xs, ys;\n                vector<int> hasX(D, 0), hasY(D, 0);\n\n                for (int x = 0; x < D; x++) {\n                    if (f[t][z][x] == '1') {\n                        xs.push_back(x);\n                        hasX[x] = 1;\n                    }\n                }\n                for (int y = 0; y < D; y++) {\n                    if (r[t][z][y] == '1') {\n                        ys.push_back(y);\n                        hasY[y] = 1;\n                    }\n                }\n\n                if (seed > 0) {\n                    if (seed % 2) shuffle(xs.begin(), xs.end(), rng);\n                    if (seed % 3) shuffle(ys.begin(), ys.end(), rng);\n                    if (seed % 5 == 0) reverse(xs.begin(), xs.end());\n                    if (seed % 7 == 0) reverse(ys.begin(), ys.end());\n                }\n\n                vector<int> coveredX(D, 0), coveredY(D, 0);\n                vector<pair<int, int>> cur_pairs;\n                set<pair<int, int>> used_pair;\n\n                auto add_pair = [&](int x, int y) {\n                    if (!used_pair.count({x, y})) {\n                        used_pair.insert({x, y});\n                        cur_pairs.push_back({x, y});\n                    }\n                    coveredX[x] = 1;\n                    coveredY[y] = 1;\n                };\n\n                vector<pair<int, int>> pp = prev_pairs;\n                if (seed > 0 && seed % 4) shuffle(pp.begin(), pp.end(), rng);\n\n                for (auto [x, y] : pp) {\n                    if (hasX[x] && hasY[y] && !coveredX[x] && !coveredY[y]) {\n                        add_pair(x, y);\n                    }\n                }\n\n                vector<int> remX, remY;\n                for (int x : xs) if (!coveredX[x]) remX.push_back(x);\n                for (int y : ys) if (!coveredY[y]) remY.push_back(y);\n\n                if (seed > 0) {\n                    shuffle(remX.begin(), remX.end(), rng);\n                    shuffle(remY.begin(), remY.end(), rng);\n                }\n\n                int p = 0;\n                while (p < (int)remX.size() && p < (int)remY.size()) {\n                    add_pair(remX[p], remY[p]);\n                    p++;\n                }\n\n                int fallbackY = ys[0];\n                for (int y : ys) {\n                    if (coveredY[y]) {\n                        fallbackY = y;\n                        break;\n                    }\n                }\n\n                while (p < (int)remX.size()) {\n                    add_pair(remX[p], fallbackY);\n                    p++;\n                }\n\n                int fallbackX = xs[0];\n                for (int x : xs) {\n                    if (coveredX[x]) {\n                        fallbackX = x;\n                        break;\n                    }\n                }\n\n                p = min((int)remX.size(), (int)remY.size());\n                while (p < (int)remY.size()) {\n                    add_pair(fallbackX, remY[p]);\n                    p++;\n                }\n\n                for (auto [x, y] : cur_pairs) {\n                    occ[t][id(x, y, z)] = 1;\n                }\n\n                prev_pairs = cur_pairs;\n            }\n        }\n\n        /*\n          Optional bridge filling.\n          Only for some seeds; actual evaluation decides whether beneficial.\n        */\n        if (seed % 4 == 2 || seed % 4 == 3) {\n            for (int t = 0; t < 2; t++) {\n                vector<int> add;\n                for (int x = 0; x < D; x++) {\n                    for (int y = 0; y < D; y++) {\n                        for (int z = 1; z + 1 < D; z++) {\n                            int q = id(x, y, z);\n                            if (occ[t][q]) continue;\n                            if (!feasible(t, x, y, z)) continue;\n                            if (occ[t][id(x, y, z - 1)] && occ[t][id(x, y, z + 1)]) {\n                                add.push_back(q);\n                            }\n                        }\n                    }\n                }\n\n                // Add at most a small number of bridges to avoid volume blow-up.\n                if (seed > 0) shuffle(add.begin(), add.end(), rng);\n\n                int limit = max(1, D / 2);\n                if (seed % 4 == 3) limit = D;\n\n                for (int i = 0; i < (int)add.size() && i < limit; i++) {\n                    occ[t][add[i]] = 1;\n                }\n            }\n        }\n\n        return occ;\n    };\n\n    auto solve_for_occ = [&](const vector<vector<int>>& occ, int seed) {\n        vector<vector<int>> ans(2, vector<int>(N3, 0));\n        int block_id = 0;\n        mt19937 rng(9876543 + seed * 101);\n\n        auto inside = [&](int x, int y, int z) {\n            return 0 <= x && x < D && 0 <= y && y < D && 0 <= z && z < D;\n        };\n\n        auto can_cell = [&](int t, int x, int y, int z) {\n            return inside(x, y, z) && occ[t][id(x, y, z)] && ans[t][id(x, y, z)] == 0;\n        };\n\n        auto can_segment = [&](int t, int x, int y, int z, int dir, int len) {\n            for (int k = 0; k < len; k++) {\n                int nx = x + dx[dir] * k;\n                int ny = y + dy[dir] * k;\n                int nz = z + dz[dir] * k;\n                if (!can_cell(t, nx, ny, nz)) return false;\n            }\n            return true;\n        };\n\n        auto run_length = [&](int t, int x, int y, int z, int dir) {\n            int len = 0;\n            while (true) {\n                int nx = x + dx[dir] * len;\n                int ny = y + dy[dir] * len;\n                int nz = z + dz[dir] * len;\n                if (!can_cell(t, nx, ny, nz)) break;\n                len++;\n            }\n            return len;\n        };\n\n        auto place_segment = [&](int t, int x, int y, int z, int dir, int len, int bid) {\n            for (int k = 0; k < len; k++) {\n                int nx = x + dx[dir] * k;\n                int ny = y + dy[dir] * k;\n                int nz = z + dz[dir] * k;\n                ans[t][id(nx, ny, nz)] = bid;\n            }\n        };\n\n        for (int len = D; len >= 2; len--) {\n            bool updated = true;\n\n            while (updated) {\n                updated = false;\n\n                vector<Seg> segs[2];\n\n                for (int t = 0; t < 2; t++) {\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                                for (int dir = 0; dir < 3; dir++) {\n                                    if (!can_segment(t, x, y, z, dir, len)) continue;\n\n                                    int px = x - dx[dir];\n                                    int py = y - dy[dir];\n                                    int pz = z - dz[dir];\n\n                                    bool is_start = !can_cell(t, px, py, pz);\n                                    int run = run_length(t, x, y, z, dir);\n\n                                    if (is_start || run == len) {\n                                        segs[t].push_back({x, y, z, dir, run});\n                                    } else if (seed % 3 == 0) {\n                                        segs[t].push_back({x, y, z, dir, run});\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n\n                if (segs[0].empty() || segs[1].empty()) continue;\n\n                shuffle(segs[0].begin(), segs[0].end(), rng);\n                shuffle(segs[1].begin(), segs[1].end(), rng);\n\n                for (int t = 0; t < 2; t++) {\n                    stable_sort(segs[t].begin(), segs[t].end(), [](const Seg& a, const Seg& b) {\n                        return a.run > b.run;\n                    });\n                }\n\n                size_t p0 = 0, p1 = 0;\n\n                while (p0 < segs[0].size() && p1 < segs[1].size()) {\n                    while (p0 < segs[0].size() &&\n                           !can_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z,\n                                        segs[0][p0].dir, len)) {\n                        p0++;\n                    }\n\n                    while (p1 < segs[1].size() &&\n                           !can_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z,\n                                        segs[1][p1].dir, len)) {\n                        p1++;\n                    }\n\n                    if (p0 >= segs[0].size() || p1 >= segs[1].size()) break;\n\n                    block_id++;\n                    place_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z,\n                                  segs[0][p0].dir, len, block_id);\n                    place_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z,\n                                  segs[1][p1].dir, len, block_id);\n\n                    updated = true;\n                    p0++;\n                    p1++;\n                }\n            }\n        }\n\n        vector<int> rem[2];\n\n        for (int t = 0; t < 2; t++) {\n            for (int q = 0; q < N3; q++) {\n                if (occ[t][q] && ans[t][q] == 0) {\n                    rem[t].push_back(q);\n                }\n            }\n        }\n\n        int common_units = min((int)rem[0].size(), (int)rem[1].size());\n\n        for (int i = 0; i < common_units; i++) {\n            block_id++;\n            ans[0][rem[0][i]] = block_id;\n            ans[1][rem[1][i]] = block_id;\n        }\n\n        for (int i = common_units; i < (int)rem[0].size(); i++) {\n            block_id++;\n            ans[0][rem[0][i]] = block_id;\n        }\n\n        for (int i = common_units; i < (int)rem[1].size(); i++) {\n            block_id++;\n            ans[1][rem[1][i]] = block_id;\n        }\n\n        vector<int> vol0(block_id + 1, 0), vol1(block_id + 1, 0);\n        vector<int> used0(block_id + 1, 0), used1(block_id + 1, 0);\n\n        for (int q = 0; q < N3; q++) {\n            int b0 = ans[0][q];\n            if (b0) {\n                vol0[b0]++;\n                used0[b0] = 1;\n            }\n            int b1 = ans[1][q];\n            if (b1) {\n                vol1[b1]++;\n                used1[b1] = 1;\n            }\n        }\n\n        double eval = 0.0;\n        for (int b = 1; b <= block_id; b++) {\n            int v = max(vol0[b], vol1[b]);\n            if (used0[b] && used1[b]) {\n                eval += 1.0 / v;\n            } else if (used0[b]) {\n                eval += v;\n            } else if (used1[b]) {\n                eval += v;\n            }\n        }\n\n        return Result{ans, eval, block_id};\n    };\n\n    auto start_time = chrono::steady_clock::now();\n\n    Result best;\n    best.eval = 1e100;\n    best.n = 0;\n\n    int seed = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n\n        if (seed > 0 && elapsed > 5.65) break;\n        if (seed >= 90) break;\n\n        auto occ = build_occ(seed);\n        auto res = solve_for_occ(occ, seed);\n\n        if (res.eval < best.eval) {\n            best = move(res);\n        }\n\n        seed++;\n    }\n\n    cout << best.n << '\\n';\n\n    for (int t = 0; t < 2; t++) {\n        for (int q = 0; q < N3; q++) {\n            if (q) cout << ' ';\n            cout << best.ans[t][q];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        sz.assign(n,1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[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(sz[a]<sz[b]) swap(a,b);\n        p[b]=a;\n        sz[a]+=sz[b];\n        return true;\n    }\n};\n\nstatic inline long long sqdist(long long x1,long long y1,long long x2,long long y2){\n    long long dx=x1-x2, dy=y1-y2;\n    return dx*dx+dy*dy;\n}\n\nstruct Solver {\n    int N, M, K;\n    vector<int> x, y, a, b;\n    vector<Edge> edges;\n    vector<vector<pair<int,int>>> g;\n\n    vector<vector<int>> d2;\n    vector<vector<pair<int,int>>> cand;\n\n    vector<vector<long long>> dist;\n    vector<vector<int>> prevEdge, prevNode;\n\n    vector<int> bestP, bestB;\n    long long bestCost = (1LL<<62);\n\n    chrono::steady_clock::time_point st;\n    double timeLimit = 1.93;\n\n    bool time_ok() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count() < timeLimit;\n    }\n\n    int ceil_sqrt_int(int val) const {\n        int r=(int)ceil(sqrt((double)val));\n        while(1LL*r*r < val) r++;\n        while(r>0 && 1LL*(r-1)*(r-1) >= val) r--;\n        return r;\n    }\n\n    long long calc_cost(const vector<int>& P, const vector<int>& B) const {\n        long long s=0;\n        for(int p:P) s += 1LL*p*p;\n        for(int i=0;i<M;i++) if(B[i]) s += edges[i].w;\n        return s;\n    }\n\n    void add_path(vector<int>& B, int s, int t) const {\n        int cur=t;\n        while(cur!=s){\n            int ei=prevEdge[s][cur];\n            if(ei<0) break;\n            B[ei]=1;\n            cur=prevNode[s][cur];\n        }\n    }\n\n    void prune_edges(const vector<int>& P, vector<int>& B) const {\n        vector<vector<pair<int,int>>> tg(N);\n        vector<int> deg(N,0);\n        for(int i=0;i<M;i++) if(B[i]){\n            int u=edges[i].u, v=edges[i].v;\n            tg[u].push_back({v,i});\n            tg[v].push_back({u,i});\n            deg[u]++; deg[v]++;\n        }\n\n        queue<int> q;\n        for(int i=1;i<N;i++){\n            if(P[i]==0 && deg[i]==1) q.push(i);\n        }\n\n        while(!q.empty()){\n            int v=q.front(); q.pop();\n            if(v==0 || P[v]>0 || deg[v]!=1) continue;\n\n            int rem=-1, to=-1;\n            for(auto [nv,ei]: tg[v]){\n                if(B[ei]){\n                    rem=ei;\n                    to=nv;\n                    break;\n                }\n            }\n            if(rem<0) continue;\n\n            B[rem]=0;\n            deg[v]--;\n            deg[to]--;\n            if(to!=0 && P[to]==0 && deg[to]==1) q.push(to);\n        }\n    }\n\n    vector<int> build_edges_root_union(const vector<int>& P) const {\n        vector<int> B(M,0);\n        for(int i=0;i<N;i++){\n            if(P[i]>0) add_path(B,0,i);\n        }\n        prune_edges(P,B);\n        return B;\n    }\n\n    vector<int> build_edges_metric_mst(const vector<int>& P) const {\n        vector<int> terminals;\n        terminals.push_back(0);\n        for(int i=1;i<N;i++) if(P[i]>0) terminals.push_back(i);\n\n        vector<int> B(M,0);\n        int T=terminals.size();\n        if(T<=1) return B;\n\n        struct ME {\n            long long w;\n            int i,j;\n            bool operator<(const ME& o) const { return w<o.w; }\n        };\n\n        vector<ME> es;\n        es.reserve(T*T/2);\n        for(int i=0;i<T;i++){\n            for(int j=i+1;j<T;j++){\n                es.push_back({dist[terminals[i]][terminals[j]], i, j});\n            }\n        }\n        sort(es.begin(),es.end());\n\n        DSU dsu(T);\n        int used=0;\n        for(auto &e: es){\n            if(dsu.unite(e.i,e.j)){\n                add_path(B,terminals[e.i],terminals[e.j]);\n                used++;\n                if(used==T-1) break;\n            }\n        }\n\n        prune_edges(P,B);\n        return B;\n    }\n\n    vector<int> best_edges_for_P(const vector<int>& P) const {\n        vector<int> b1=build_edges_metric_mst(P);\n        long long c1=calc_cost(P,b1);\n\n        vector<int> b2=build_edges_root_union(P);\n        long long c2=calc_cost(P,b2);\n\n        return (c2<c1 ? b2 : b1);\n    }\n\n    long long total_cost_for_P(const vector<int>& P) const {\n        vector<int> B=best_edges_for_P(P);\n        return calc_cost(P,B);\n    }\n\n    vector<int> recomputeP_from_assigned(const vector<vector<int>>& assigned) const {\n        vector<int> P(N,0);\n        for(int i=0;i<N;i++){\n            int md=0;\n            for(int k: assigned[i]) md=max(md,d2[i][k]);\n            P[i]=ceil_sqrt_int(md);\n            if(P[i]>5000) P[i]=5000;\n        }\n        return P;\n    }\n\n    bool all_covered(const vector<int>& P) const {\n        for(int k=0;k<K;k++){\n            bool ok=false;\n            for(int i=0;i<N;i++){\n                if(P[i]>0 && 1LL*P[i]*P[i]>=d2[i][k]){\n                    ok=true;\n                    break;\n                }\n            }\n            if(!ok) return false;\n        }\n        return true;\n    }\n\n    vector<int> coverage_count(const vector<int>& P) const {\n        vector<int> cnt(K,0);\n        for(int i=0;i<N;i++){\n            if(P[i]==0) continue;\n            long long rr=1LL*P[i]*P[i];\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=rr) cnt[k]++;\n            }\n        }\n        return cnt;\n    }\n\n    void global_reduce(vector<int>& P) const {\n        vector<int> covCnt=coverage_count(P);\n\n        vector<int> ord(N);\n        iota(ord.begin(),ord.end(),0);\n        sort(ord.begin(),ord.end(),[&](int p,int q){\n            return P[p]<P[q];\n        });\n\n        for(int i: ord){\n            if(P[i]==0) continue;\n            long long rr=1LL*P[i]*P[i];\n\n            bool ok=true;\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=rr && covCnt[k]<=1){\n                    ok=false;\n                    break;\n                }\n            }\n\n            if(ok){\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=rr) covCnt[k]--;\n                }\n                P[i]=0;\n            }\n        }\n\n        ord.clear();\n        for(int i=0;i<N;i++) if(P[i]>0) ord.push_back(i);\n        sort(ord.begin(),ord.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        for(int i: ord){\n            if(P[i]==0) continue;\n\n            vector<int> critical;\n            critical.push_back(0);\n            long long oldrr=1LL*P[i]*P[i];\n\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=oldrr) critical.push_back(ceil_sqrt_int(d2[i][k]));\n            }\n\n            sort(critical.begin(),critical.end());\n            critical.erase(unique(critical.begin(),critical.end()),critical.end());\n\n            int best=P[i];\n            for(int idx=(int)critical.size()-1; idx>=0; idx--){\n                int r=critical[idx];\n                long long nrr=1LL*r*r;\n\n                bool ok=true;\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=oldrr && d2[i][k]>nrr && covCnt[k]<=1){\n                        ok=false;\n                        break;\n                    }\n                }\n\n                if(ok) best=r;\n                else break;\n            }\n\n            if(best<P[i]){\n                long long nrr=1LL*best*best;\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=oldrr && d2[i][k]>nrr) covCnt[k]--;\n                }\n                P[i]=best;\n            }\n        }\n    }\n\n    void repair_uncovered(vector<int>& P, int maxCand=45) const {\n        while(true){\n            vector<int> uncovered;\n            uncovered.reserve(K);\n\n            for(int k=0;k<K;k++){\n                bool ok=false;\n                for(int i=0;i<N;i++){\n                    if(P[i]>0 && 1LL*P[i]*P[i]>=d2[i][k]){\n                        ok=true;\n                        break;\n                    }\n                }\n                if(!ok) uncovered.push_back(k);\n            }\n\n            if(uncovered.empty()) break;\n\n            long long bestVal=(1LL<<62);\n            int bestI=-1;\n            int bestNewR=0;\n\n            for(int i=0;i<N;i++){\n                vector<pair<int,int>> ds;\n                ds.reserve(uncovered.size());\n\n                for(int k: uncovered){\n                    if(d2[i][k] <= 5000LL*5000LL){\n                        ds.push_back({d2[i][k],k});\n                    }\n                }\n                if(ds.empty()) continue;\n\n                sort(ds.begin(),ds.end());\n\n                int gain=0;\n                for(int p=0;p<(int)ds.size();p++){\n                    gain++;\n                    int dd=ds[p].first;\n                    if(p+1<(int)ds.size() && ds[p+1].first==dd) continue;\n\n                    int nr=max(P[i],ceil_sqrt_int(dd));\n                    if(nr>5000) continue;\n\n                    long long inc=1LL*nr*nr - 1LL*P[i]*P[i];\n                    if(P[i]==0) inc += dist[0][i]/7;\n\n                    long long val = inc / max(1,gain) - 20LL*gain;\n\n                    if(val<bestVal){\n                        bestVal=val;\n                        bestI=i;\n                        bestNewR=nr;\n                    }\n                }\n            }\n\n            if(bestI<0){\n                int k=uncovered[0];\n                int bi=cand[k][0].second;\n                P[bi]=max(P[bi],ceil_sqrt_int(d2[bi][k]));\n                P[bi]=min(P[bi],5000);\n            }else{\n                P[bestI]=bestNewR;\n            }\n        }\n    }\n\n    bool distributed_repair_from_need(vector<int>& NP, const vector<int>& need, int removedA=-1, int removedB=-1) const {\n        vector<int> order=need;\n\n        sort(order.begin(),order.end(),[&](int p,int q){\n            return cand[p][0].first > cand[q][0].first;\n        });\n\n        for(int k: order){\n            bool already=false;\n            for(int i=0;i<N;i++){\n                if(NP[i]>0 && 1LL*NP[i]*NP[i]>=d2[i][k]){\n                    already=true;\n                    break;\n                }\n            }\n            if(already) continue;\n\n            long long bestInc=(1LL<<60);\n            int bestI=-1, bestR=0;\n\n            int lim=min(25,(int)cand[k].size());\n            for(int z=0; z<lim; z++){\n                int i=cand[k][z].second;\n                if(i==removedA || i==removedB) continue;\n\n                int nr=max(NP[i],ceil_sqrt_int(d2[i][k]));\n                if(nr>5000) continue;\n\n                long long inc=1LL*nr*nr-1LL*NP[i]*NP[i];\n                if(NP[i]==0) inc += dist[0][i]/6;\n\n                if(inc<bestInc){\n                    bestInc=inc;\n                    bestI=i;\n                    bestR=nr;\n                }\n            }\n\n            if(bestI<0) return false;\n            NP[bestI]=bestR;\n        }\n        return true;\n    }\n\n    void drop_repair_local_search(vector<int>& P){\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        for(int pass=0; pass<2 && time_ok(); pass++){\n            bool improved=false;\n\n            vector<int> active;\n            for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n            sort(active.begin(),active.end(),[&](int p,int q){\n                long long cp=1LL*P[p]*P[p]+dist[0][p]/5;\n                long long cq=1LL*P[q]*P[q]+dist[0][q]/5;\n                return cp>cq;\n            });\n\n            int trials=0;\n            for(int rem: active){\n                if(!time_ok()) return;\n                if(P[rem]==0) continue;\n                if(++trials>75) break;\n\n                vector<int> NP=P;\n                NP[rem]=0;\n                repair_uncovered(NP,50);\n                global_reduce(NP);\n\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    improved=true;\n                }\n            }\n\n            if(!improved) break;\n        }\n    }\n\n    void expand_to_remove(vector<int>& P){\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        int tested=0;\n        for(int rem: active){\n            if(!time_ok() || tested>70) break;\n            tested++;\n            if(P[rem]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> needResidents;\n            long long rrem=1LL*P[rem]*P[rem];\n\n            for(int k=0;k<K;k++){\n                if(d2[rem][k]<=rrem && covCnt[k]==1) needResidents.push_back(k);\n            }\n\n            if(needResidents.empty()){\n                P[rem]=0;\n                global_reduce(P);\n                base=total_cost_for_P(P);\n                continue;\n            }\n\n            vector<int> candidates;\n            for(int k: needResidents){\n                int lim=min(10,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int i=cand[k][z].second;\n                    if(i!=rem) candidates.push_back(i);\n                }\n            }\n\n            sort(candidates.begin(),candidates.end());\n            candidates.erase(unique(candidates.begin(),candidates.end()),candidates.end());\n\n            int cnt=0;\n            for(int add: candidates){\n                if(!time_ok() || cnt>30) break;\n                cnt++;\n\n                vector<int> NP=P;\n                NP[rem]=0;\n                int nr=NP[add];\n\n                bool ok=true;\n                for(int k: needResidents){\n                    nr=max(nr,ceil_sqrt_int(d2[add][k]));\n                    if(nr>5000){\n                        ok=false;\n                        break;\n                    }\n                }\n\n                if(!ok) continue;\n\n                NP[add]=nr;\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    break;\n                }\n            }\n        }\n    }\n\n    void try_station_relocation(vector<int>& P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        int tested=0;\n        for(int old: active){\n            if(!time_ok() || tested>60) break;\n            tested++;\n            if(P[old]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> uniqueResidents;\n            long long rr=1LL*P[old]*P[old];\n\n            for(int k=0;k<K;k++){\n                if(d2[old][k]<=rr && covCnt[k]==1) uniqueResidents.push_back(k);\n            }\n\n            if(uniqueResidents.empty()){\n                vector<int> NP=P;\n                NP[old]=0;\n                global_reduce(NP);\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                }\n                continue;\n            }\n\n            vector<int> candidateStations;\n            for(int k: uniqueResidents){\n                int lim=min(8,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni!=old) candidateStations.push_back(ni);\n                }\n            }\n\n            sort(candidateStations.begin(),candidateStations.end());\n            candidateStations.erase(unique(candidateStations.begin(),candidateStations.end()),candidateStations.end());\n\n            int cnt=0;\n            for(int ni: candidateStations){\n                if(!time_ok() || cnt>20) break;\n                cnt++;\n\n                vector<int> NP=P;\n                NP[old]=0;\n                int need=NP[ni];\n\n                bool ok=true;\n                for(int k: uniqueResidents){\n                    need=max(need,ceil_sqrt_int(d2[ni][k]));\n                    if(need>5000){\n                        ok=false;\n                        break;\n                    }\n                }\n\n                if(!ok) continue;\n\n                NP[ni]=need;\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    break;\n                }\n            }\n        }\n    }\n\n    void remove_station_distributed_repair(vector<int>& P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            long long cp=1LL*P[p]*P[p]+dist[0][p]/4;\n            long long cq=1LL*P[q]*P[q]+dist[0][q]/4;\n            return cp>cq;\n        });\n\n        int tried=0;\n        for(int rem: active){\n            if(!time_ok() || tried>50) break;\n            tried++;\n            if(P[rem]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> need;\n            long long rr=1LL*P[rem]*P[rem];\n\n            for(int k=0;k<K;k++){\n                if(d2[rem][k]<=rr && covCnt[k]==1) need.push_back(k);\n            }\n\n            if(need.empty()){\n                vector<int> NP=P;\n                NP[rem]=0;\n                global_reduce(NP);\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                }\n                continue;\n            }\n\n            vector<int> NP=P;\n            NP[rem]=0;\n\n            if(!distributed_repair_from_need(NP,need,rem,-1)) continue;\n\n            global_reduce(NP);\n            if(!all_covered(NP)) continue;\n\n            long long nc=total_cost_for_P(NP);\n            if(nc<base){\n                P=NP;\n                base=nc;\n            }\n        }\n    }\n\n    void remove_two_stations_repair(vector<int>& P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            long long cp=1LL*P[p]*P[p]+dist[0][p]/4;\n            long long cq=1LL*P[q]*P[q]+dist[0][q]/4;\n            return cp>cq;\n        });\n\n        int L=min(18,(int)active.size());\n        int tried=0;\n\n        for(int ai=0; ai<L && time_ok(); ai++){\n            int r1=active[ai];\n            if(P[r1]==0) continue;\n\n            for(int aj=ai+1; aj<L && time_ok(); aj++){\n                if(++tried>70) return;\n                int r2=active[aj];\n                if(P[r2]==0) continue;\n\n                vector<int> NP=P;\n                NP[r1]=0;\n                NP[r2]=0;\n\n                vector<int> need;\n                for(int k=0;k<K;k++){\n                    bool ok=false;\n                    for(int i=0;i<N;i++){\n                        if(i==r1 || i==r2) continue;\n                        if(NP[i]>0 && 1LL*NP[i]*NP[i]>=d2[i][k]){\n                            ok=true;\n                            break;\n                        }\n                    }\n                    if(!ok) need.push_back(k);\n                }\n\n                if(need.empty()){\n                    global_reduce(NP);\n                    long long nc=total_cost_for_P(NP);\n                    if(nc<base){\n                        P=NP;\n                        base=nc;\n                    }\n                    continue;\n                }\n\n                if((int)need.size()>350) continue;\n\n                if(!distributed_repair_from_need(NP,need,r1,r2)) continue;\n\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                }\n            }\n        }\n    }\n\n    void refine_assignment(vector<vector<int>>& assigned, vector<int>& assign){\n        for(int outer=0; outer<7 && time_ok(); outer++){\n            vector<int> curMax(N,0), secondMax(N,0), cntMax(N,0);\n\n            for(int i=0;i<N;i++){\n                for(int k: assigned[i]){\n                    int dd=d2[i][k];\n                    if(dd>curMax[i]){\n                        secondMax[i]=curMax[i];\n                        curMax[i]=dd;\n                        cntMax[i]=1;\n                    }else if(dd==curMax[i]){\n                        cntMax[i]++;\n                    }else if(dd>secondMax[i]){\n                        secondMax[i]=dd;\n                    }\n                }\n            }\n\n            bool changed=false;\n            vector<int> order(K);\n            iota(order.begin(),order.end(),0);\n            shuffle(order.begin(),order.end(),mt19937(1234567+outer));\n\n            for(int k: order){\n                int old=assign[k];\n                if(old<0) continue;\n\n                int oldAfter=curMax[old];\n                if(d2[old][k]==curMax[old] && cntMax[old]==1) oldAfter=secondMax[old];\n\n                int oldR=ceil_sqrt_int(curMax[old]);\n                int oldAfterR=ceil_sqrt_int(oldAfter);\n                long long deltaOld=1LL*oldAfterR*oldAfterR-1LL*oldR*oldR;\n\n                long long bestDelta=0;\n                int bestI=old;\n\n                int lim=min(45,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni==old) continue;\n\n                    int r0=ceil_sqrt_int(curMax[ni]);\n                    int r1=ceil_sqrt_int(max(curMax[ni],d2[ni][k]));\n                    long long delta=deltaOld+1LL*r1*r1-1LL*r0*r0;\n\n                    if(assigned[ni].empty()) delta += dist[0][ni]/7;\n                    if(assigned[old].size()==1) delta -= dist[0][old]/7;\n\n                    if(delta<bestDelta){\n                        bestDelta=delta;\n                        bestI=ni;\n                    }\n                }\n\n                if(bestI!=old){\n                    auto &v=assigned[old];\n                    auto it=find(v.begin(),v.end(),k);\n                    if(it!=v.end()) v.erase(it);\n                    assigned[bestI].push_back(k);\n                    assign[k]=bestI;\n                    changed=true;\n                }\n            }\n\n            try_delete_stations(assigned,assign);\n            if(!changed) break;\n        }\n    }\n\n    void try_delete_stations(vector<vector<int>>& assigned, vector<int>& assign){\n        vector<int> stations;\n        for(int i=0;i<N;i++) if(!assigned[i].empty()) stations.push_back(i);\n\n        sort(stations.begin(),stations.end(),[&](int p,int q){\n            return assigned[p].size()<assigned[q].size();\n        });\n\n        int tries=0;\n        for(int rem: stations){\n            if(!time_ok()) return;\n            if(assigned[rem].empty()) continue;\n            if((int)assigned[rem].size()>220) continue;\n            if(++tries>50) break;\n\n            auto backupA=assigned;\n            auto backupAssign=assign;\n\n            vector<int> oldP=recomputeP_from_assigned(assigned);\n            global_reduce(oldP);\n            long long oldCost=total_cost_for_P(oldP);\n\n            vector<int> residents=assigned[rem];\n            assigned[rem].clear();\n\n            bool ok=true;\n            for(int k: residents){\n                long long bestInc=(1LL<<60);\n                int bestI=-1;\n\n                int lim=min(60,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni==rem) continue;\n\n                    int md=0;\n                    for(int kk: assigned[ni]) md=max(md,d2[ni][kk]);\n\n                    int r0=ceil_sqrt_int(md);\n                    int r1=ceil_sqrt_int(max(md,d2[ni][k]));\n                    long long inc=1LL*r1*r1-1LL*r0*r0;\n                    if(assigned[ni].empty()) inc += dist[0][ni]/7;\n\n                    if(inc<bestInc){\n                        bestInc=inc;\n                        bestI=ni;\n                    }\n                }\n\n                if(bestI<0){\n                    ok=false;\n                    break;\n                }\n\n                assigned[bestI].push_back(k);\n                assign[k]=bestI;\n            }\n\n            if(ok){\n                vector<int> newP=recomputeP_from_assigned(assigned);\n                global_reduce(newP);\n                long long newCost=total_cost_for_P(newP);\n                if(newCost<oldCost) continue;\n            }\n\n            assigned=backupA;\n            assign=backupAssign;\n        }\n    }\n\n    void evaluate_P(vector<int> P){\n        for(int &p:P) p=max(0,min(5000,p));\n\n        repair_uncovered(P);\n        global_reduce(P);\n\n        if(time_ok()) expand_to_remove(P);\n        if(time_ok()) try_station_relocation(P);\n        if(time_ok()) drop_repair_local_search(P);\n        if(time_ok()) remove_station_distributed_repair(P);\n\n        global_reduce(P);\n\n        if(!all_covered(P)) repair_uncovered(P);\n        global_reduce(P);\n\n        vector<int> B=best_edges_for_P(P);\n        long long c=calc_cost(P,B);\n\n        if(c<bestCost){\n            bestCost=c;\n            bestP=P;\n            bestB=B;\n        }\n    }\n\n    void polish_best(){\n        if(!time_ok()) return;\n\n        vector<int> P=bestP;\n\n        for(int it=0; it<3 && time_ok(); it++){\n            global_reduce(P);\n\n            if(time_ok()) expand_to_remove(P);\n            if(time_ok()) try_station_relocation(P);\n            if(time_ok()) drop_repair_local_search(P);\n            if(time_ok()) remove_station_distributed_repair(P);\n            if(time_ok()) remove_two_stations_repair(P);\n\n            global_reduce(P);\n\n            if(!all_covered(P)) repair_uncovered(P);\n            global_reduce(P);\n\n            vector<int> B=best_edges_for_P(P);\n            long long c=calc_cost(P,B);\n\n            if(c<bestCost){\n                bestCost=c;\n                bestP=P;\n                bestB=B;\n            }else{\n                break;\n            }\n        }\n    }\n\n    void evaluate_assignment(vector<vector<int>> assigned){\n        vector<int> assign(K,-1);\n        for(int i=0;i<N;i++){\n            for(int k: assigned[i]) assign[k]=i;\n        }\n\n        refine_assignment(assigned,assign);\n\n        vector<int> P=recomputeP_from_assigned(assigned);\n        evaluate_P(P);\n    }\n\n    void build_initial_nearest(){\n        vector<vector<int>> assigned(N);\n        for(int k=0;k<K;k++){\n            assigned[cand[k][0].second].push_back(k);\n        }\n        evaluate_assignment(assigned);\n    }\n\n    void build_initial_marginal(int lim, long long connDiv, int orderMode){\n        vector<vector<int>> assigned(N);\n        vector<int> maxd(N,0);\n\n        vector<int> order(K);\n        iota(order.begin(),order.end(),0);\n\n        if(orderMode==0){\n            sort(order.begin(),order.end(),[&](int p,int q){\n                return cand[p][0].first>cand[q][0].first;\n            });\n        }else if(orderMode==1){\n            sort(order.begin(),order.end(),[&](int p,int q){\n                return cand[p][0].first<cand[q][0].first;\n            });\n        }else{\n            shuffle(order.begin(),order.end(),mt19937(777+orderMode));\n        }\n\n        for(int k: order){\n            long long best=(1LL<<60);\n            int bi=cand[k][0].second;\n\n            int L=min(lim,(int)cand[k].size());\n            for(int z=0;z<L;z++){\n                int i=cand[k][z].second;\n\n                int r0=ceil_sqrt_int(maxd[i]);\n                int r1=ceil_sqrt_int(max(maxd[i],d2[i][k]));\n                long long inc=1LL*r1*r1-1LL*r0*r0;\n\n                if(assigned[i].empty()) inc += dist[0][i]/connDiv;\n\n                if(inc<best){\n                    best=inc;\n                    bi=i;\n                }\n            }\n\n            assigned[bi].push_back(k);\n            maxd[bi]=max(maxd[bi],d2[bi][k]);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void build_initial_setcover(long long connDiv, int radiiStep, double powGain){\n        vector<char> covered(K,0);\n        int remaining=K;\n        vector<vector<int>> assigned(N);\n        vector<int> assign(K,-1);\n\n        vector<int> possibleR;\n        for(int r=250;r<=5000;r+=radiiStep) possibleR.push_back(r);\n        possibleR.push_back(5000);\n        sort(possibleR.begin(),possibleR.end());\n        possibleR.erase(unique(possibleR.begin(),possibleR.end()),possibleR.end());\n\n        for(int iter=0; remaining>0 && iter<180 && time_ok(); iter++){\n            double bestScore=-1;\n            int bestI=-1;\n            vector<int> bestList;\n\n            for(int i=0;i<N;i++){\n                vector<pair<int,int>> ds;\n                ds.reserve(remaining);\n\n                for(int k=0;k<K;k++){\n                    if(!covered[k] && d2[i][k]<=5000LL*5000LL){\n                        ds.push_back({d2[i][k],k});\n                    }\n                }\n\n                if(ds.empty()) continue;\n                sort(ds.begin(),ds.end());\n\n                vector<int> cur;\n                int ptr=0;\n\n                for(int r: possibleR){\n                    int rr=r*r;\n                    while(ptr<(int)ds.size() && ds[ptr].first<=rr){\n                        cur.push_back(ds[ptr].second);\n                        ptr++;\n                    }\n\n                    int gain=cur.size();\n                    if(gain==0) continue;\n\n                    long long cost=1LL*r*r + dist[0][i]/connDiv;\n                    double score=pow((double)gain,powGain)/(double)cost;\n\n                    if(score>bestScore){\n                        bestScore=score;\n                        bestI=i;\n                        bestList=cur;\n                    }\n                }\n            }\n\n            if(bestI<0) break;\n\n            for(int k: bestList){\n                if(!covered[k]){\n                    covered[k]=1;\n                    remaining--;\n                    assign[k]=bestI;\n                    assigned[bestI].push_back(k);\n                }\n            }\n        }\n\n        for(int k=0;k<K;k++){\n            if(assign[k]>=0) continue;\n\n            long long best=(1LL<<60);\n            int bi=cand[k][0].second;\n            int L=min(60,(int)cand[k].size());\n\n            for(int z=0;z<L;z++){\n                int i=cand[k][z].second;\n\n                int md=0;\n                for(int kk: assigned[i]) md=max(md,d2[i][kk]);\n\n                int r0=ceil_sqrt_int(md);\n                int r1=ceil_sqrt_int(max(md,d2[i][k]));\n                long long inc=1LL*r1*r1-1LL*r0*r0;\n\n                if(assigned[i].empty()) inc += dist[0][i]/connDiv;\n\n                if(inc<best){\n                    best=inc;\n                    bi=i;\n                }\n            }\n\n            assign[k]=bi;\n            assigned[bi].push_back(k);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void prepare(){\n        d2.assign(N,vector<int>(K));\n        for(int i=0;i<N;i++){\n            for(int k=0;k<K;k++){\n                d2[i][k]=(int)sqdist(x[i],y[i],a[k],b[k]);\n            }\n        }\n\n        cand.assign(K,{});\n        for(int k=0;k<K;k++){\n            cand[k].reserve(N);\n            for(int i=0;i<N;i++){\n                if(d2[i][k]<=5000LL*5000LL) cand[k].push_back({d2[i][k],i});\n            }\n\n            if(cand[k].empty()){\n                for(int i=0;i<N;i++) cand[k].push_back({d2[i][k],i});\n            }\n\n            sort(cand[k].begin(),cand[k].end());\n        }\n\n        const long long INF=(1LL<<60);\n        dist.assign(N,vector<long long>(N,INF));\n        prevEdge.assign(N,vector<int>(N,-1));\n        prevNode.assign(N,vector<int>(N,-1));\n\n        for(int s=0;s<N;s++){\n            priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>> pq;\n            dist[s][s]=0;\n            pq.push({0,s});\n\n            while(!pq.empty()){\n                auto [cd,v]=pq.top();\n                pq.pop();\n\n                if(cd!=dist[s][v]) continue;\n\n                for(auto [to,ei]: g[v]){\n                    long long nd=cd+edges[ei].w;\n                    if(nd<dist[s][to]){\n                        dist[s][to]=nd;\n                        prevEdge[s][to]=ei;\n                        prevNode[s][to]=v;\n                        pq.push({nd,to});\n                    }\n                }\n            }\n        }\n    }\n\n    void solve(){\n        st=chrono::steady_clock::now();\n        prepare();\n\n        bestP.assign(N,0);\n        bestB.assign(M,0);\n\n        build_initial_nearest();\n\n        if(time_ok()) build_initial_marginal(12,4,0);\n        if(time_ok()) build_initial_marginal(25,5,0);\n        if(time_ok()) build_initial_marginal(60,7,0);\n        if(time_ok()) build_initial_marginal(100,9,0);\n\n        if(time_ok()) build_initial_marginal(25,5,1);\n        if(time_ok()) build_initial_marginal(50,7,2);\n        if(time_ok()) build_initial_marginal(80,10,3);\n\n        if(time_ok()) build_initial_setcover(5,300,1.35);\n        if(time_ok()) build_initial_setcover(8,450,1.45);\n        if(time_ok()) build_initial_setcover(12,650,1.55);\n\n        polish_best();\n\n        for(int k=0;k<K;k++){\n            bool ok=false;\n            for(int i=0;i<N;i++){\n                if(bestP[i]>0 && 1LL*bestP[i]*bestP[i]>=d2[i][k]){\n                    ok=true;\n                    break;\n                }\n            }\n\n            if(!ok){\n                int bi=cand[k][0].second;\n                bestP[bi]=max(bestP[bi],ceil_sqrt_int(d2[bi][k]));\n                bestP[bi]=min(bestP[bi],5000);\n            }\n        }\n\n        global_reduce(bestP);\n        bestB=best_edges_for_P(bestP);\n    }\n};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    cin >> solver.N >> solver.M >> solver.K;\n\n    solver.x.resize(solver.N);\n    solver.y.resize(solver.N);\n\n    for(int i=0;i<solver.N;i++){\n        cin >> solver.x[i] >> solver.y[i];\n    }\n\n    solver.edges.resize(solver.M);\n    solver.g.assign(solver.N,{});\n\n    for(int i=0;i<solver.M;i++){\n        int u,v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n\n        solver.edges[i]={u,v,w};\n        solver.g[u].push_back({v,i});\n        solver.g[v].push_back({u,i});\n    }\n\n    solver.a.resize(solver.K);\n    solver.b.resize(solver.K);\n\n    for(int k=0;k<solver.K;k++){\n        cin >> solver.a[k] >> solver.b[k];\n    }\n\n    solver.solve();\n\n    for(int i=0;i<solver.N;i++){\n        if(i) cout << ' ';\n        cout << solver.bestP[i];\n    }\n    cout << '\\n';\n\n    for(int i=0;i<solver.M;i++){\n        if(i) cout << ' ';\n        cout << solver.bestB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int M = N * (N + 1) / 2;\nstatic constexpr int LIM = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nstruct Pos {\n    int x, y;\n};\n\nusing Board = array<array<int, N>, N>;\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y <= x;\n}\n\nint cell_violation(const Board& a, int x, int y) {\n    if (x < 0 || x >= N - 1 || y < 0 || y > x) return 0;\n    int c = 0;\n    if (a[x][y] > a[x + 1][y]) c++;\n    if (a[x][y] > a[x + 1][y + 1]) c++;\n    return c;\n}\n\nint cell_severity(const Board& a, int x, int y) {\n    if (x < 0 || x >= N - 1 || y < 0 || y > x) return 0;\n    int s = 0;\n    if (a[x][y] > a[x + 1][y]) s += a[x][y] - a[x + 1][y];\n    if (a[x][y] > a[x + 1][y + 1]) s += a[x][y] - a[x + 1][y + 1];\n    return s;\n}\n\nint total_violations(const Board& a) {\n    int e = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) {\n            e += cell_violation(a, x, y);\n        }\n    }\n    return e;\n}\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 123456789) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) { return int(next() % n); }\n    double uniform01() { return (next() & 0xffffff) / double(0x1000000); }\n};\n\nstruct Result {\n    bool ok = false;\n    Board board{};\n    vector<Op> ops;\n};\n\nvoid init_pos(const Board& a, array<Pos, M>& pos) {\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            pos[a[x][y]] = {x, y};\n        }\n    }\n}\n\nbool do_swap(Board& a, array<Pos, M>& pos, vector<Op>& ops,\n             int x1, int y1, int x2, int y2) {\n    if ((int)ops.size() >= LIM) return false;\n    int v1 = a[x1][y1], v2 = a[x2][y2];\n    swap(a[x1][y1], a[x2][y2]);\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n    ops.push_back({x1, y1, x2, y2});\n    return true;\n}\n\nvector<pair<int,int>> local_cells_around(int x, int y) {\n    vector<pair<int,int>> v;\n    for (int dx = -2; dx <= 1; dx++) {\n        for (int dy = -2; dy <= 2; dy++) {\n            int nx = x + dx, ny = y + dy;\n            if (inside(nx, ny) && nx < N - 1) {\n                if (abs(nx - x) + abs(ny - y) <= 3) v.push_back({nx, ny});\n            }\n        }\n    }\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nvector<pair<int,int>> affected_union(int x1, int y1, int x2, int y2) {\n    auto a = local_cells_around(x1, y1);\n    auto b = local_cells_around(x2, y2);\n    a.insert(a.end(), b.begin(), b.end());\n    sort(a.begin(), a.end());\n    a.erase(unique(a.begin(), a.end()), a.end());\n    return a;\n}\n\nstruct Policy {\n    int order_type;\n    double w_vio;\n    double w_sev;\n    double w_depth;\n    double w_small;\n    uint32_t seed;\n};\n\nResult repair_with_policy(const Board& start_board,\n                          const vector<Op>& prefix,\n                          const Policy& pol) {\n    Board a = start_board;\n    vector<Op> ops = prefix;\n    XorShift rng(pol.seed);\n\n    auto do_swap_simple = [&](int x1, int y1, int x2, int y2) -> bool {\n        if ((int)ops.size() >= LIM) return false;\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n        return true;\n    };\n\n    auto candidate_score = [&](int x1, int y1, int x2, int y2) {\n        auto aff = affected_union(x1, y1, x2, y2);\n\n        int vio_before = 0, sev_before = 0;\n        for (auto [x, y] : aff) {\n            vio_before += cell_violation(a, x, y);\n            sev_before += cell_severity(a, x, y);\n        }\n\n        swap(a[x1][y1], a[x2][y2]);\n\n        int vio_after = 0, sev_after = 0;\n        for (auto [x, y] : aff) {\n            vio_after += cell_violation(a, x, y);\n            sev_after += cell_severity(a, x, y);\n        }\n\n        int moved_up = a[x1][y1];\n        swap(a[x1][y1], a[x2][y2]);\n\n        double score = 0;\n        score += pol.w_vio * double(vio_before - vio_after);\n        score += pol.w_sev * double(sev_before - sev_after);\n        score += pol.w_depth * double(x1);\n        score += pol.w_small * double(464 - moved_up) / 464.0;\n        score += 1e-6 * rng.uniform01();\n        return score;\n    };\n\n    auto repair_cell = [&](int x, int y) -> bool {\n        if (x >= N - 1 || cell_violation(a, x, y) == 0) return false;\n\n        vector<pair<int,int>> cand;\n        if (a[x][y] > a[x + 1][y]) cand.push_back({x + 1, y});\n        if (a[x][y] > a[x + 1][y + 1]) cand.push_back({x + 1, y + 1});\n        if (cand.empty()) return false;\n\n        int bx = cand[0].first, by = cand[0].second;\n        double best_score = -1e100;\n\n        for (auto [cx, cy] : cand) {\n            double sc = candidate_score(x, y, cx, cy);\n            if (sc > best_score) {\n                best_score = sc;\n                bx = cx;\n                by = cy;\n            }\n        }\n\n        return do_swap_simple(x, y, bx, by);\n    };\n\n    int lastE = total_violations(a);\n    int stagnant = 0;\n\n    for (int pass = 0; pass < 600 && (int)ops.size() < LIM; pass++) {\n        int before_ops = ops.size();\n\n        int mode = pol.order_type;\n        if (mode == 2) mode = pass & 1;\n\n        if (mode == 0) {\n            for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (cell_violation(a, x, y)) repair_cell(x, y);\n                }\n            }\n        } else {\n            for (int x = 0; x < N - 1 && (int)ops.size() < LIM; x++) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (cell_violation(a, x, y)) repair_cell(x, y);\n                }\n            }\n        }\n\n        int E = total_violations(a);\n        if (E == 0) return {true, a, ops};\n\n        if ((int)ops.size() == before_ops) break;\n        if (E >= lastE) stagnant++;\n        else stagnant = 0;\n        lastE = E;\n        if (stagnant >= 40 && ops.size() > 3500) break;\n    }\n\n    return {total_violations(a) == 0, a, ops};\n}\n\nResult fallback_repair(const Board& start_board, const vector<Op>& prefix) {\n    Board a = start_board;\n    vector<Op> ops = prefix;\n\n    auto do_swap_simple = [&](int x1, int y1, int x2, int y2) -> bool {\n        if ((int)ops.size() >= LIM) return false;\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n        return true;\n    };\n\n    using Node = tuple<int,int,int,int>;\n    priority_queue<Node> pq;\n    vector<vector<int>> pushed(N);\n    for (int x = 0; x < N; x++) pushed[x].assign(x + 1, 0);\n    int timer = 0;\n\n    auto push_cell = [&](int x, int y) {\n        if (!inside(x, y) || x >= N - 1) return;\n        int s = cell_severity(a, x, y);\n        if (s <= 0) return;\n        pushed[x][y] = ++timer;\n        pq.emplace(s, pushed[x][y], x, y);\n    };\n\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) push_cell(x, y);\n    }\n\n    while (!pq.empty() && (int)ops.size() < LIM) {\n        auto [sold, id, x, y] = pq.top();\n        pq.pop();\n        if (id != pushed[x][y]) continue;\n\n        int snow = cell_severity(a, x, y);\n        if (snow <= 0) continue;\n        if (snow != sold) {\n            push_cell(x, y);\n            continue;\n        }\n\n        int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n        if (!(a[x][y] > a[x + 1][by])) continue;\n\n        do_swap_simple(x, y, x + 1, by);\n\n        for (int dx = -2; dx <= 2; dx++) {\n            for (int dy = -2; dy <= 2; dy++) {\n                push_cell(x + dx, y + dy);\n                push_cell(x + 1 + dx, by + dy);\n            }\n        }\n    }\n\n    for (int pass = 0; pass < 600 && total_violations(a) > 0 && (int)ops.size() < LIM; pass++) {\n        for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n            for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                if (cell_violation(a, x, y)) {\n                    int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n                    do_swap_simple(x, y, x + 1, by);\n                }\n            }\n        }\n    }\n\n    return {total_violations(a) == 0, a, ops};\n}\n\nvector<pair<int,int>> make_shape_cells(int H, int type) {\n    vector<pair<int,int>> cells;\n\n    if (type == 0) {\n        for (int x = 0; x < H; x++) {\n            for (int y = 0; y <= x; y++) cells.push_back({x, y});\n        }\n    } else if (type == 1) {\n        for (int x = 0; x < H; x++) {\n            int w = max(1, (x + 2) / 2);\n            for (int y = 0; y < w; y++) cells.push_back({x, y});\n        }\n    } else if (type == 2) {\n        for (int x = 0; x < H; x++) {\n            int w = max(1, (x + 2) / 2);\n            for (int y = x - w + 1; y <= x; y++) cells.push_back({x, y});\n        }\n    } else if (type == 3) {\n        for (int x = 0; x < H; x++) {\n            cells.push_back({x, 0});\n            if (x > 0) cells.push_back({x, x});\n            if (x >= 3) {\n                cells.push_back({x, 1});\n                cells.push_back({x, x - 1});\n            }\n        }\n    } else if (type == 4) {\n        for (int x = 0; x < H; x++) {\n            int w = max(1, (x + 2) / 2);\n            int l = (x - w + 1) / 2;\n            for (int y = l; y < l + w; y++) cells.push_back({x, y});\n        }\n    }\n\n    sort(cells.begin(), cells.end());\n    cells.erase(unique(cells.begin(), cells.end()), cells.end());\n    sort(cells.begin(), cells.end(), [](auto p, auto q) {\n        if (p.first != q.first) return p.first < q.first;\n        return p.second < q.second;\n    });\n    return cells;\n}\n\nint estimate_path_cost(Pos p, int tx, int ty) {\n    int cx = p.x, cy = p.y;\n    int cost = 0;\n\n    while (cx > tx) {\n        if (cy > ty) {\n            cx--;\n            cy--;\n        } else {\n            if (cy <= cx - 1) {\n                cx--;\n            } else {\n                cx--;\n                cy--;\n            }\n        }\n        cost++;\n    }\n    cost += abs(cy - ty);\n    return cost;\n}\n\nResult make_prefix_place_small_cells(const Board& init,\n                                     const vector<pair<int,int>>& targets,\n                                     int candLimit,\n                                     double valuePenalty) {\n    Board a = init;\n    array<Pos, M> pos;\n    init_pos(a, pos);\n\n    vector<Op> ops;\n    vector<vector<bool>> fixed(N);\n    for (int x = 0; x < N; x++) fixed[x].assign(x + 1, false);\n\n    auto swap_fixed = [&](int x1, int y1, int x2, int y2) -> bool {\n        return do_swap(a, pos, ops, x1, y1, x2, y2);\n    };\n\n    for (auto [tx, ty] : targets) {\n        vector<int> candidates;\n        for (int v = 0; v < M && (int)candidates.size() < candLimit; v++) {\n            Pos p = pos[v];\n            if (!fixed[p.x][p.y]) candidates.push_back(v);\n        }\n        if (candidates.empty()) break;\n\n        int chosen = candidates[0];\n        double bestScore = 1e100;\n\n        for (int rank = 0; rank < (int)candidates.size(); rank++) {\n            int v = candidates[rank];\n            Pos p = pos[v];\n            int dist = estimate_path_cost(p, tx, ty);\n            double sc = dist + valuePenalty * rank;\n            if (sc < bestScore) {\n                bestScore = sc;\n                chosen = v;\n            }\n        }\n\n        int cx = pos[chosen].x;\n        int cy = pos[chosen].y;\n\n        while (cx > tx && (int)ops.size() < LIM) {\n            vector<pair<int,int>> cand;\n            if (cy > 0) cand.push_back({cx - 1, cy - 1});\n            if (cy < cx) cand.push_back({cx - 1, cy});\n\n            pair<int,int> nxt = {-1, -1};\n            int bestd = INT_MAX;\n            for (auto [nx, ny] : cand) {\n                if (fixed[nx][ny]) continue;\n                int d = abs(nx - tx) + abs(ny - ty);\n                if (ny < ty) d += 100;\n                if (d < bestd) {\n                    bestd = d;\n                    nxt = {nx, ny};\n                }\n            }\n            if (nxt.first == -1) break;\n\n            swap_fixed(cx, cy, nxt.first, nxt.second);\n            cx = nxt.first;\n            cy = nxt.second;\n        }\n\n        while (cy > ty && (int)ops.size() < LIM) {\n            if (fixed[cx][cy - 1]) break;\n            swap_fixed(cx, cy, cx, cy - 1);\n            cy--;\n        }\n        while (cy < ty && (int)ops.size() < LIM) {\n            if (cy + 1 > cx || fixed[cx][cy + 1]) break;\n            swap_fixed(cx, cy, cx, cy + 1);\n            cy++;\n        }\n\n        fixed[tx][ty] = true;\n    }\n\n    return {false, a, ops};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::steady_clock::now();\n\n    Board init{};\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) cin >> init[x][y];\n    }\n\n    vector<Policy> policies;\n    uint32_t seed = 2463534242u;\n    for (int order = 0; order < 3; order++) {\n        policies.push_back({order, 1000.0, 1.0, 0.0, 0.0, seed += 101});\n        policies.push_back({order, 500.0, 2.0, 0.0, 0.2, seed += 101});\n        policies.push_back({order, 200.0, 5.0, 0.1, 0.0, seed += 101});\n        policies.push_back({order, 100.0, 10.0, 0.2, 0.5, seed += 101});\n        policies.push_back({order, 1000.0, 0.0, 0.0, 1.0, seed += 101});\n    }\n\n    Result best;\n    best.ok = false;\n\n    Result fb0 = fallback_repair(init, {});\n    if (fb0.ok) best = fb0;\n\n    for (int i = 0; i < (int)policies.size(); i++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 0.55) break;\n\n        Result r = repair_with_policy(init, {}, policies[i]);\n        if (r.ok && (!best.ok || r.ops.size() < best.ops.size())) best = move(r);\n    }\n\n    struct Job {\n        int H;\n        int type;\n        int candLimit;\n        double penalty;\n    };\n\n    vector<Job> jobs;\n\n    // Exact-small placement, known strong.\n    for (int H = 1; H <= 9; H++) jobs.push_back({H, 0, 1, 1000.0});\n\n    // Near-small placement: allow closer values among next few small values.\n    for (int H = 2; H <= 10; H++) {\n        jobs.push_back({H, 0, 3, 1.5});\n        jobs.push_back({H, 0, 5, 1.0});\n        jobs.push_back({H, 0, 8, 0.8});\n    }\n\n    // Shape variants.\n    for (int H = 3; H <= 12; H++) {\n        for (int type = 1; type <= 4; type++) {\n            jobs.push_back({H, type, 1, 1000.0});\n            jobs.push_back({H, type, 4, 1.0});\n        }\n    }\n\n    stable_sort(jobs.begin(), jobs.end(), [](const Job& a, const Job& b) {\n        if (a.type == 0 && b.type != 0) return true;\n        if (a.type != 0 && b.type == 0) return false;\n        if (a.candLimit == 1 && b.candLimit != 1) return true;\n        if (a.candLimit != 1 && b.candLimit == 1) return false;\n        return a.H < b.H;\n    });\n\n    for (const auto& job : jobs) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.88) break;\n\n        auto targets = make_shape_cells(job.H, job.type);\n        Result pref = make_prefix_place_small_cells(init, targets, job.candLimit, job.penalty);\n\n        if ((int)pref.ops.size() >= (best.ok ? (int)best.ops.size() : LIM)) continue;\n\n        Result r = fallback_repair(pref.board, pref.ops);\n        if (r.ok && (!best.ok || r.ops.size() < best.ops.size())) best = move(r);\n\n        now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.88) break;\n\n        if ((int)pref.ops.size() < (best.ok ? (int)best.ops.size() - 120 : LIM)) {\n            Result rp = repair_with_policy(pref.board, pref.ops, policies[0]);\n            if (rp.ok && (!best.ok || rp.ops.size() < best.ops.size())) best = move(rp);\n        }\n    }\n\n    if (!best.ok) best = fb0;\n\n    cout << best.ops.size() << '\\n';\n    for (auto &op : best.ops) {\n        cout << op.x1 << ' ' << op.y1 << ' ' << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c;\n};\n\nint D, N;\nconst int ENTR = 0;\nconst int ENTC = 4;\nconst int MAXM = 80;\n\nbool obstacle_[9][9];\nbool occupied_[9][9];\nint valAt[9][9];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nbool isEntrance(int r, int c) {\n    return r == ENTR && c == ENTC;\n}\n\nvector<vector<int>> reachableEmpty() {\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    queue<pair<int,int>> q;\n\n    if (!obstacle_[ENTR][ENTC] && !occupied_[ENTR][ENTC]) {\n        vis[ENTR][ENTC] = 1;\n        q.push({ENTR, ENTC});\n    }\n\n    while (!q.empty()) {\n        auto [r,c] = q.front();\n        q.pop();\n\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (vis[nr][nc]) continue;\n            if (obstacle_[nr][nc] || occupied_[nr][nc]) continue;\n            vis[nr][nc] = 1;\n            q.push({nr,nc});\n        }\n    }\n\n    return vis;\n}\n\nbool keepsConnectivity(int br, int bc, const vector<Cell>& allCells) {\n    occupied_[br][bc] = true;\n    auto vis = reachableEmpty();\n    occupied_[br][bc] = false;\n\n    for (auto cell : allCells) {\n        int r = cell.r, c = cell.c;\n        if (occupied_[r][c]) continue;\n        if (r == br && c == bc) continue;\n        if (!vis[r][c]) return false;\n    }\n\n    return true;\n}\n\nvector<vector<int>> baseDistance() {\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n\n    dist[ENTR][ENTC] = 0;\n    q.push({ENTR, ENTC});\n\n    while (!q.empty()) {\n        auto [r,c] = q.front();\n        q.pop();\n\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (obstacle_[nr][nc]) continue;\n            if (dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr,nc});\n        }\n    }\n\n    return dist;\n}\n\nbool removableContainer(int r, int c, const vector<vector<int>>& emptyReach) {\n    if (!occupied_[r][c]) return false;\n\n    for (int k=0;k<4;k++) {\n        int nr = r + dr[k], nc = c + dc[k];\n        if (!inside(nr,nc)) continue;\n        if (emptyReach[nr][nc]) return true;\n    }\n\n    return false;\n}\n\nint cellIdG[9][9];\nvector<Cell> cellsG;\nvector<int> labelG;\nint KG;\n\nvector<int> reachableEmptyMask(unsigned __int128 mask) {\n    vector<int> visFlat(D * D, 0);\n    queue<pair<int,int>> q;\n\n    visFlat[ENTR * D + ENTC] = 1;\n    q.push({ENTR, ENTC});\n\n    while (!q.empty()) {\n        auto [r,c] = q.front();\n        q.pop();\n\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n\n            int flat = nr * D + nc;\n            if (visFlat[flat]) continue;\n            if (obstacle_[nr][nc]) continue;\n\n            int id = cellIdG[nr][nc];\n            if (id >= 0 && ((mask >> id) & 1)) continue;\n\n            visFlat[flat] = 1;\n            q.push({nr,nc});\n        }\n    }\n\n    return visFlat;\n}\n\nvector<int> legalMovesMask(unsigned __int128 mask) {\n    vector<int> reach = reachableEmptyMask(mask);\n    vector<int> moves;\n\n    for (int id=0; id<KG; id++) {\n        if (((mask >> id) & 1) == 0) continue;\n\n        int r = cellsG[id].r;\n        int c = cellsG[id].c;\n\n        bool ok = false;\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (reach[nr * D + nc]) {\n                ok = true;\n                break;\n            }\n        }\n\n        if (ok) moves.push_back(id);\n    }\n\n    return moves;\n}\n\nint immediateCost(unsigned __int128 nmask, int id) {\n    int add = 0;\n    int lab = labelG[id];\n    for (int j=0;j<KG;j++) {\n        if (((nmask >> j) & 1) && labelG[j] < lab) add++;\n    }\n    return add;\n}\n\nint unlockScore(unsigned __int128 mask, int id) {\n    auto before = legalMovesMask(mask);\n    unsigned __int128 nmask = mask & ~((unsigned __int128)1 << id);\n    auto after = legalMovesMask(nmask);\n\n    // Count newly legal cells, weighted toward small labels.\n    vector<int> was(KG, 0);\n    for (int x : before) was[x] = 1;\n\n    int score = 0;\n    for (int x : after) {\n        if (!was[x]) {\n            score += 100;\n            score += max(0, 80 - labelG[x]);\n        }\n    }\n\n    return score;\n}\n\nlong long heuristicState(unsigned __int128 mask) {\n    // Cheap lower-ish estimate:\n    // encourage states where current accessible minimum is small.\n    auto moves = legalMovesMask(mask);\n    if (moves.empty()) return 1000000;\n\n    int mn = 1000000;\n    int sumSmall = 0;\n    for (int id : moves) {\n        mn = min(mn, labelG[id]);\n        if (labelG[id] < 20) sumSmall++;\n    }\n\n    return mn * 2LL - sumSmall * 10LL;\n}\n\nstruct BeamState {\n    unsigned __int128 mask;\n    int cost;\n    array<unsigned char, MAXM> seq;\n    unsigned char len;\n    int h;\n};\n\nstruct Key {\n    unsigned long long lo, hi;\n    bool operator==(const Key& o) const {\n        return lo == o.lo && hi == o.hi;\n    }\n};\n\nstruct Hasher {\n    size_t operator()(const Key& k) const {\n        return k.lo ^ (k.hi * 11995408973635179863ULL);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    memset(obstacle_, 0, sizeof(obstacle_));\n    memset(occupied_, 0, sizeof(occupied_));\n\n    for (int r=0;r<9;r++) {\n        for (int c=0;c<9;c++) {\n            valAt[r][c] = -1;\n            cellIdG[r][c] = -1;\n        }\n    }\n\n    for (int i=0;i<N;i++) {\n        int r,c;\n        cin >> r >> c;\n        obstacle_[r][c] = true;\n    }\n\n    int M = D * D - 1 - N;\n\n    auto dist = baseDistance();\n\n    vector<Cell> allCells;\n    for (int r=0;r<D;r++) {\n        for (int c=0;c<D;c++) {\n            if (isEntrance(r,c)) continue;\n            if (obstacle_[r][c]) continue;\n            allCells.push_back({r,c});\n        }\n    }\n\n    sort(allCells.begin(), allCells.end(), [&](const Cell& a, const Cell& b) {\n        int da = dist[a.r][a.c];\n        int db = dist[b.r][b.c];\n        if (da != db) return da < db;\n\n        int ca = abs(a.c - ENTC);\n        int cb = abs(b.c - ENTC);\n        if (ca != cb) return ca < cb;\n\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    int rankOf[9][9];\n    memset(rankOf, -1, sizeof(rankOf));\n\n    for (int i=0;i<(int)allCells.size();i++) {\n        rankOf[allCells[i].r][allCells[i].c] = i;\n    }\n\n    // Stable baseline placement.\n    for (int d=0; d<M; d++) {\n        int t;\n        cin >> t;\n\n        auto reach = reachableEmpty();\n\n        Cell best{-1,-1};\n        long long bestScore = LLONG_MAX;\n\n        for (auto cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (occupied_[r][c]) continue;\n            if (!reach[r][c]) continue;\n            if (!keepsConnectivity(r,c,allCells)) continue;\n\n            int rk = rankOf[r][c];\n\n            long long score = 0;\n            score += 1000LL * abs(rk - t);\n            score -= 20LL * dist[r][c];\n            if (c == ENTC) score += 100;\n            score -= 5LL * abs(c - ENTC);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = cell;\n            }\n        }\n\n        if (best.r == -1) {\n            bestScore = LLONG_MAX;\n            for (auto cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (occupied_[r][c]) continue;\n                if (!reach[r][c]) continue;\n\n                int rk = rankOf[r][c];\n                long long score = 1000LL * abs(rk - t) - 20LL * dist[r][c];\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = cell;\n                }\n            }\n        }\n\n        if (best.r == -1) {\n            for (auto cell : allCells) {\n                if (!occupied_[cell.r][cell.c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        occupied_[best.r][best.c] = true;\n        valAt[best.r][best.c] = t;\n\n        cout << best.r << \" \" << best.c << '\\n';\n        cout.flush();\n    }\n\n    // Prepare final removal data.\n    cellsG = allCells;\n    KG = (int)cellsG.size();\n\n    for (int i=0;i<KG;i++) {\n        cellIdG[cellsG[i].r][cellsG[i].c] = i;\n    }\n\n    labelG.assign(KG, -1);\n    for (int i=0;i<KG;i++) {\n        labelG[i] = valAt[cellsG[i].r][cellsG[i].c];\n    }\n\n    unsigned __int128 fullMask = 0;\n    for (int i=0;i<KG;i++) {\n        fullMask |= ((unsigned __int128)1 << i);\n    }\n\n    // Greedy fallback.\n    bool backupOcc[9][9];\n    int backupVal[9][9];\n\n    for (int r=0;r<D;r++) {\n        for (int c=0;c<D;c++) {\n            backupOcc[r][c] = occupied_[r][c];\n            backupVal[r][c] = valAt[r][c];\n        }\n    }\n\n    vector<Cell> greedyAns;\n    greedyAns.reserve(M);\n\n    for (int step=0; step<M; step++) {\n        auto emptyReach = reachableEmpty();\n\n        Cell best{-1,-1};\n        int bestVal = INT_MAX;\n\n        for (auto cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (!occupied_[r][c]) continue;\n            if (!removableContainer(r,c,emptyReach)) continue;\n\n            if (valAt[r][c] < bestVal) {\n                bestVal = valAt[r][c];\n                best = cell;\n            }\n        }\n\n        if (best.r == -1) {\n            for (auto cell : allCells) {\n                if (occupied_[cell.r][cell.c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        greedyAns.push_back(best);\n        occupied_[best.r][best.c] = false;\n        valAt[best.r][best.c] = -1;\n    }\n\n    for (int r=0;r<D;r++) {\n        for (int c=0;c<D;c++) {\n            occupied_[r][c] = backupOcc[r][c];\n            valAt[r][c] = backupVal[r][c];\n        }\n    }\n\n    // Beam search for removal.\n    int BEAM = 360;\n    if (M >= 78) BEAM = 300;\n    if (N >= 7) BEAM = 420;\n\n    vector<BeamState> beam;\n    BeamState init;\n    init.mask = fullMask;\n    init.cost = 0;\n    init.len = 0;\n    init.h = heuristicState(fullMask);\n    beam.push_back(init);\n\n    vector<unsigned char> bestSeq;\n\n    for (int step=0; step<M; step++) {\n        vector<BeamState> nxt;\n        nxt.reserve(BEAM * 12);\n\n        for (const auto& st : beam) {\n            vector<int> moves = legalMovesMask(st.mask);\n            if (moves.empty()) continue;\n\n            vector<int> selected;\n\n            // 1. Smallest labels.\n            vector<int> byLabel = moves;\n            sort(byLabel.begin(), byLabel.end(), [&](int a, int b) {\n                return labelG[a] < labelG[b];\n            });\n\n            int L1 = (step < 20 ? 12 : 9);\n            for (int i=0;i<(int)byLabel.size() && i<L1;i++) {\n                selected.push_back(byLabel[i]);\n            }\n\n            // 2. Best unlockers.\n            vector<pair<int,int>> byUnlock;\n            for (int id : moves) {\n                byUnlock.push_back({-unlockScore(st.mask, id), id});\n            }\n            sort(byUnlock.begin(), byUnlock.end());\n\n            int L2 = (step < 25 ? 5 : 3);\n            for (int i=0;i<(int)byUnlock.size() && i<L2;i++) {\n                selected.push_back(byUnlock[i].second);\n            }\n\n            // 3. Low immediate inversion cost.\n            vector<pair<int,int>> byCost;\n            for (int id : moves) {\n                unsigned __int128 nmask = st.mask & ~((unsigned __int128)1 << id);\n                byCost.push_back({immediateCost(nmask, id), id});\n            }\n            sort(byCost.begin(), byCost.end());\n\n            int L3 = 5;\n            for (int i=0;i<(int)byCost.size() && i<L3;i++) {\n                selected.push_back(byCost[i].second);\n            }\n\n            sort(selected.begin(), selected.end());\n            selected.erase(unique(selected.begin(), selected.end()), selected.end());\n\n            for (int id : selected) {\n                unsigned __int128 nmask = st.mask & ~((unsigned __int128)1 << id);\n\n                BeamState ns;\n                ns.mask = nmask;\n                ns.cost = st.cost + immediateCost(nmask, id);\n                ns.seq = st.seq;\n                ns.seq[st.len] = (unsigned char)id;\n                ns.len = st.len + 1;\n                ns.h = (int)heuristicState(nmask);\n\n                nxt.push_back(ns);\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [&](const BeamState& a, const BeamState& b) {\n            long long ea = a.cost * 1000LL + a.h;\n            long long eb = b.cost * 1000LL + b.h;\n            if (ea != eb) return ea < eb;\n            if (a.cost != b.cost) return a.cost < b.cost;\n            int la = a.len ? labelG[a.seq[a.len-1]] : -1;\n            int lb = b.len ? labelG[b.seq[b.len-1]] : -1;\n            return la < lb;\n        });\n\n        vector<BeamState> filtered;\n        filtered.reserve(BEAM);\n\n        unordered_set<Key, Hasher> seen;\n        seen.reserve(BEAM * 4);\n\n        for (auto& st : nxt) {\n            Key key{(unsigned long long)st.mask, (unsigned long long)(st.mask >> 64)};\n            if (seen.find(key) != seen.end()) continue;\n            seen.insert(key);\n\n            filtered.push_back(st);\n            if ((int)filtered.size() >= BEAM) break;\n        }\n\n        beam.swap(filtered);\n    }\n\n    if (!beam.empty()) {\n        auto bestIt = min_element(beam.begin(), beam.end(), [&](const BeamState& a, const BeamState& b) {\n            if (a.len != b.len) return a.len > b.len;\n            return a.cost < b.cost;\n        });\n\n        if (bestIt->len == M) {\n            bestSeq.assign(bestIt->seq.begin(), bestIt->seq.begin() + M);\n        }\n    }\n\n    if ((int)bestSeq.size() == M) {\n        for (unsigned char uc : bestSeq) {\n            int id = (int)uc;\n            Cell cell = cellsG[id];\n            cout << cell.r << \" \" << cell.c << '\\n';\n        }\n    } else {\n        for (auto cell : greedyAns) {\n            cout << cell.r << \" \" << cell.c << '\\n';\n        }\n    }\n\n    cout.flush();\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 50;\nstatic const int M = 100;\n\nint n, m;\narray<array<int, N>, N> g, bestG;\nbool targetAdj[M + 1][M + 1];\nint colorCnt[M + 1];\n\nchrono::steady_clock::time_point startTime;\nconst double TL = 1.92;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\ninline bool inside(int i, int j) {\n    return 0 <= i && i < n && 0 <= j && j < n;\n}\n\nvoid addAdj(bool adj[M + 1][M + 1], int a, int b) {\n    if (a == b) return;\n    adj[a][b] = adj[b][a] = true;\n}\n\nvoid computeAdj(const array<array<int, N>, N>& grid, bool adj[M + 1][M + 1]) {\n    for (int i = 0; i <= M; i++)\n        for (int j = 0; j <= M; j++)\n            adj[i][j] = false;\n\n    for (int i = 0; i < n; i++) {\n        addAdj(adj, 0, grid[i][0]);\n        addAdj(adj, 0, grid[i][n - 1]);\n    }\n    for (int j = 0; j < n; j++) {\n        addAdj(adj, 0, grid[0][j]);\n        addAdj(adj, 0, grid[n - 1][j]);\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i + 1 < n) addAdj(adj, grid[i][j], grid[i + 1][j]);\n            if (j + 1 < n) addAdj(adj, grid[i][j], grid[i][j + 1]);\n        }\n    }\n}\n\nvoid recount() {\n    memset(colorCnt, 0, sizeof(colorCnt));\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            colorCnt[g[i][j]]++;\n}\n\nbool checkZeroConnected() {\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n\n    for (int i = 0; i < n; i++) {\n        if (g[i][0] == 0 && !vis[i][0]) vis[i][0] = true, q.push({i, 0});\n        if (g[i][n - 1] == 0 && !vis[i][n - 1]) vis[i][n - 1] = true, q.push({i, n - 1});\n    }\n    for (int j = 0; j < n; j++) {\n        if (g[0][j] == 0 && !vis[0][j]) vis[0][j] = true, q.push({0, j});\n        if (g[n - 1][j] == 0 && !vis[n - 1][j]) vis[n - 1][j] = true, q.push({n - 1, j});\n    }\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (!inside(ni, nj) || vis[ni][nj] || g[ni][nj] != 0) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (g[i][j] == 0 && !vis[i][j])\n                return false;\n\n    return true;\n}\n\nbool checkColorConnected(int c) {\n    if (colorCnt[c] <= 0) return false;\n\n    int si = -1, sj = -1;\n    for (int i = 0; i < n && si < 0; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == c) {\n                si = i;\n                sj = j;\n                break;\n            }\n        }\n    }\n\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n    vis[si][sj] = true;\n    q.push({si, sj});\n    int cnt = 0;\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        cnt++;\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (!inside(ni, nj) || vis[ni][nj] || g[ni][nj] != c) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    return cnt == colorCnt[c];\n}\n\nbool fullCheck() {\n    recount();\n\n    if (!checkZeroConnected()) return false;\n\n    for (int c = 1; c <= m; c++)\n        if (!checkColorConnected(c))\n            return false;\n\n    bool curAdj[M + 1][M + 1];\n    computeAdj(g, curAdj);\n\n    for (int i = 0; i <= m; i++)\n        for (int j = 0; j <= m; j++)\n            if (curAdj[i][j] != targetAdj[i][j])\n                return false;\n\n    return true;\n}\n\nint zeroCount() {\n    int z = 0;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (g[i][j] == 0)\n                z++;\n    return z;\n}\n\nbool trySetCell(int i, int j, int nc) {\n    int oc = g[i][j];\n    if (oc == nc) return false;\n    if (oc != 0 && colorCnt[oc] <= 1) return false;\n\n    int oldZero = colorCnt[0];\n\n    g[i][j] = nc;\n    colorCnt[oc]--;\n    colorCnt[nc]++;\n\n    bool ok = fullCheck();\n    bool improveOrNeutral = colorCnt[0] >= oldZero;\n\n    if (!ok || !improveOrNeutral) {\n        g[i][j] = oc;\n        colorCnt[oc]++;\n        colorCnt[nc]--;\n        return false;\n    }\n\n    return true;\n}\n\nbool tryDelete(int i, int j) {\n    if (g[i][j] == 0) return false;\n    return trySetCell(i, j, 0);\n}\n\nvoid greedyDeletion(double untilTime, mt19937& rng) {\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.push_back({i, j});\n\n    int pass = 0;\n    while (elapsed() < untilTime) {\n        pass++;\n\n        if (pass % 4 == 1) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, 49 - a.first, 49 - a.second});\n                int db = min({b.first, b.second, 49 - b.first, 49 - b.second});\n                return da < db;\n            });\n        } else if (pass % 4 == 2) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, 49 - a.first, 49 - a.second});\n                int db = min({b.first, b.second, 49 - b.first, 49 - b.second});\n                return da > db;\n            });\n        } else {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n\n        bool changed = false;\n        for (auto [i, j] : cells) {\n            if (elapsed() >= untilTime) break;\n            if (tryDelete(i, j)) changed = true;\n        }\n\n        if (!changed && pass >= 4) break;\n    }\n}\n\nvector<pair<int,int>> collectBoundaryCells() {\n    vector<pair<int,int>> v;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = g[i][j];\n            bool boundary = false;\n            static const int di[4] = {1, -1, 0, 0};\n            static const int dj[4] = {0, 0, 1, -1};\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) {\n                    if (c != 0) boundary = true;\n                } else if (g[ni][nj] != c) {\n                    boundary = true;\n                }\n            }\n            if (boundary) v.push_back({i, j});\n        }\n    }\n    return v;\n}\n\nvoid reshapePhase(double untilTime, mt19937& rng) {\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    int bestZero = zeroCount();\n    bestG = g;\n\n    while (elapsed() < untilTime) {\n        auto cells = collectBoundaryCells();\n        shuffle(cells.begin(), cells.end(), rng);\n\n        bool changed = false;\n\n        for (auto [i, j] : cells) {\n            if (elapsed() >= untilTime) break;\n\n            int oc = g[i][j];\n            if (oc == 0) continue;\n            if (colorCnt[oc] <= 1) continue;\n\n            vector<int> cand;\n            cand.push_back(0);\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) continue;\n                int nc = g[ni][nj];\n                if (nc != oc) cand.push_back(nc);\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int nc : cand) {\n                if (elapsed() >= untilTime) break;\n                if (nc == oc) continue;\n\n                int beforeZero = colorCnt[0];\n                if (trySetCell(i, j, nc)) {\n                    changed = true;\n\n                    int z = colorCnt[0];\n                    if (z > bestZero) {\n                        bestZero = z;\n                        bestG = g;\n                    }\n\n                    // Prefer real deletion; after one accepted move, go to next cell.\n                    break;\n                } else {\n                    // trySetCell restores itself\n                    (void)beforeZero;\n                }\n            }\n        }\n\n        if (!changed) break;\n\n        // After neutral recolors, try to harvest deletions.\n        greedyDeletion(min(untilTime, elapsed() + 0.25), rng);\n\n        int z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        }\n    }\n\n    g = bestG;\n    recount();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    startTime = chrono::steady_clock::now();\n\n    cin >> n >> m;\n\n    for (int i = 0; i <= M; i++)\n        for (int j = 0; j <= M; j++)\n            targetAdj[i][j] = false;\n\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> g[i][j];\n\n    computeAdj(g, targetAdj);\n    recount();\n\n    mt19937 rng(123456789);\n\n    greedyDeletion(0.70, rng);\n\n    bestG = g;\n    int bestZero = zeroCount();\n\n    while (elapsed() < TL) {\n        reshapePhase(min(TL, elapsed() + 0.40), rng);\n\n        int z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        } else {\n            g = bestG;\n            recount();\n        }\n\n        greedyDeletion(min(TL, elapsed() + 0.25), rng);\n\n        z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        } else {\n            g = bestG;\n            recount();\n        }\n    }\n\n    g = bestG;\n\n    // Safety: if something unexpected happens, the current best is still expected valid\n    // because every accepted move was full-checked.\n    // assert(fullCheck());\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\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    vector<int> ord;              // light -> heavy estimated\n    vector<vector<int>> groups;\n    vector<int> ans;\n    vector<double> estW;\n    vector<double> estSum;\n\n    char query_vec(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        char c;\n        cin >> c;\n        used++;\n        return c;\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query_vec(L, R);\n    }\n\n    bool less_item(int a, int b) {\n        char c = query_single(a, b);\n        return c == '<';\n    }\n\n    void bounded_insertion_sort() {\n        ord.clear();\n        ord.push_back(0);\n\n        for (int i = 1; i < N; i++) {\n            if (used >= Q) {\n                ord.push_back(i);\n                continue;\n            }\n\n            int lo = 0, hi = (int)ord.size();\n            while (lo < hi && used < Q) {\n                int mid = (lo + hi) / 2;\n                bool lt = less_item(i, ord[mid]);\n                if (lt) hi = mid;\n                else lo = mid + 1;\n            }\n            ord.insert(ord.begin() + lo, i);\n        }\n\n        vector<int> seen(N, 0);\n        for (int x : ord) {\n            if (0 <= x && x < N) seen[x] = 1;\n        }\n        for (int i = 0; i < N; i++) {\n            if (!seen[i]) ord.push_back(i);\n        }\n    }\n\n    void build_est_weights() {\n        estW.assign(N, 1.0);\n\n        for (int r = 0; r < N; r++) {\n            int item = ord[r];\n            double p = (r + 0.5) / N;\n            double x = -log(max(1e-12, 1.0 - p));\n\n            // Slightly damp tail for safer fallback.\n            x = pow(x, 0.95);\n            estW[item] = x;\n        }\n\n        double sum = accumulate(estW.begin(), estW.end(), 0.0);\n        if (sum > 0) {\n            for (double &x : estW) x *= N / sum;\n        }\n    }\n\n    int compare_group(int a, int b) {\n        if (groups[a].empty() && groups[b].empty()) return 0;\n        if (groups[a].empty()) return -1;\n        if (groups[b].empty()) return 1;\n\n        char c = query_vec(groups[a], groups[b]);\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    int find_lightest_group_by_query() {\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (used >= Q) break;\n            int cmp = compare_group(g, best);\n            if (cmp == -1) best = g;\n        }\n        return best;\n    }\n\n    int find_lightest_group_est() {\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (estSum[g] < estSum[best]) best = g;\n        }\n        return best;\n    }\n\n    int find_smallest_group_size() {\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (groups[g].size() < groups[best].size()) best = g;\n        }\n        return best;\n    }\n\n    bool use_est_fallback_now(int placedCount) {\n        double ratio = (double)Q / N;\n\n        // Estimated fallback helped many medium cases.\n        // It is riskier for large D and very low query ratio.\n        if (D <= 8) return true;\n        if (ratio >= 10.0 && D <= 16) return true;\n        if (ratio >= 16.0) return true;\n\n        // If many items have already been placed by real group comparisons,\n        // estimated sums are anchored enough.\n        if (placedCount >= N / 2 && D <= 18) return true;\n\n        return false;\n    }\n\n    void add_item(int item, int g) {\n        groups[g].push_back(item);\n        ans[item] = g;\n        estSum[g] += estW[item];\n    }\n\n    void make_partition() {\n        groups.assign(D, {});\n        ans.assign(N, 0);\n        estSum.assign(D, 0.0);\n\n        vector<int> heavy_to_light = ord;\n        reverse(heavy_to_light.begin(), heavy_to_light.end());\n\n        int placed = 0;\n\n        for (int item : heavy_to_light) {\n            int g;\n\n            if (used + D - 1 <= Q) {\n                g = find_lightest_group_by_query();\n            } else {\n                if (use_est_fallback_now(placed)) {\n                    g = find_lightest_group_est();\n                } else {\n                    g = find_smallest_group_size();\n                }\n            }\n\n            add_item(item, g);\n            placed++;\n        }\n    }\n\n    vector<int> build_round_robin_ans() {\n        vector<int> cand(N, 0);\n        vector<int> items = ord;\n        reverse(items.begin(), items.end());\n\n        for (int i = 0; i < (int)items.size(); i++) {\n            cand[items[i]] = i % D;\n        }\n        return cand;\n    }\n\n    vector<int> build_est_greedy_ans() {\n        vector<int> cand(N, 0);\n        vector<double> sum(D, 0.0);\n\n        vector<int> items = ord;\n        reverse(items.begin(), items.end());\n\n        priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n        for (int g = 0; g < D; g++) pq.push({0.0, g});\n\n        for (int item : items) {\n            auto [s, g] = pq.top();\n            pq.pop();\n\n            cand[item] = g;\n            sum[g] += estW[item];\n\n            pq.push({sum[g], g});\n        }\n\n        return cand;\n    }\n\n    void set_ans_from_vector(const vector<int>& cand) {\n        ans = cand;\n        groups.assign(D, {});\n        estSum.assign(D, 0.0);\n\n        for (int i = 0; i < N; i++) {\n            int g = ans[i];\n            if (g < 0 || g >= D) g = 0;\n            ans[i] = g;\n            groups[g].push_back(i);\n            estSum[g] += estW[i];\n        }\n    }\n\n    void partition_no_query_left() {\n        double ratio = (double)Q / N;\n\n        // Original round-robin can be surprisingly good when D is large and\n        // estimates are unreliable. Otherwise estimated greedy is better.\n        bool useEst =\n            (D <= 10) ||\n            (ratio >= 8.0 && D <= 18) ||\n            (ratio >= 14.0);\n\n        if (useEst) {\n            set_ans_from_vector(build_est_greedy_ans());\n        } else {\n            set_ans_from_vector(build_round_robin_ans());\n        }\n    }\n\n    void spend_remaining_queries() {\n        while (used < Q) {\n            int a = used % N;\n            int b = (a + 1) % N;\n            query_single(a, b);\n        }\n    }\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        bounded_insertion_sort();\n        build_est_weights();\n\n        if (used < Q) {\n            make_partition();\n        } else {\n            partition_no_query_left();\n        }\n\n        spend_remaining_queries();\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << ans[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Config {\n    int mode; // 0 = rollout, 1 = bucket, 2 = beam, 3 = split\n    int rolloutHorizon;\n    double costW;\n    double emptyBonus;\n    double goodBoundaryBonus;\n    double badBoundaryPenalty;\n    double badBoundaryDiffW;\n    double heightW;\n    double nearDepthW;\n    double topSmallBonus;\n    double coverSmallPenalty;\n    double staticW;\n    double bucketW;\n    int bucketSize;\n    int beamWidth;\n    double splitPenalty;\n    int splitMaxCandidates;\n};\n\nstruct Result {\n    vector<pair<int,int>> ops;\n    int energy;\n};\n\nstruct BeamState {\n    vector<vector<int>> st;\n    int cur;\n    int energy;\n    int firstDst;\n    double score;\n};\n\nstruct FirstAction {\n    int type; // 0 normal, 1 split\n    int split;\n    int dst1;\n    int dst2;\n    double score;\n};\n\nstruct PortfolioSolver {\n    int n, m;\n    vector<vector<int>> init;\n\n    PortfolioSolver(int n_, int m_, vector<vector<int>> init_)\n        : n(n_), m(m_), init(std::move(init_)) {}\n\n    int find_stack(const vector<vector<int>>& a, int v) const {\n        for (int i = 0; i < m; i++) {\n            for (int x : a[i]) if (x == v) return i;\n        }\n        return -1;\n    }\n\n    int find_index(const vector<int>& s, int v) const {\n        for (int i = 0; i < (int)s.size(); i++) if (s[i] == v) return i;\n        return -1;\n    }\n\n    int bucket(int x, int bs) const {\n        return (x - 1) / bs;\n    }\n\n    int remove_greedy_sim(vector<vector<int>>& a, int cur, int limitCur) const {\n        bool changed = true;\n        while (cur <= limitCur && changed) {\n            changed = false;\n            for (int i = 0; i < m; i++) {\n                if (!a[i].empty() && a[i].back() == cur) {\n                    a[i].pop_back();\n                    cur++;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        return cur;\n    }\n\n    double bucket_eval_stack(const vector<int>& s, int cur, const Config& cfg) const {\n        if (s.empty()) return -cfg.emptyBonus * 0.2;\n\n        double sc = 0.0;\n        int h = (int)s.size();\n\n        for (int j = 0; j + 1 < h; j++) {\n            int lower = s[j];\n            int upper = s[j + 1];\n            int bl = bucket(lower, cfg.bucketSize);\n            int bu = bucket(upper, cfg.bucketSize);\n\n            if (bl < bu) {\n                sc += cfg.bucketW * (1 + bu - bl);\n                if (lower < cur + 50) sc += cfg.bucketW;\n            } else if (bl == bu) {\n                if (lower < upper) sc += cfg.bucketW * 0.6;\n                else sc -= cfg.bucketW * 0.15;\n            } else {\n                sc -= cfg.bucketW * 0.25;\n            }\n        }\n\n        for (int j = 0; j < h; j++) {\n            int v = s[j];\n            if (v >= cur && v < cur + 50) {\n                int above = h - 1 - j;\n                sc += above * (55 - (v - cur)) * 0.025 * cfg.bucketW;\n            }\n        }\n\n        return sc;\n    }\n\n    double static_eval(const vector<vector<int>>& a, int cur, const Config& cfg) const {\n        double score = 0.0;\n\n        for (int i = 0; i < m; i++) {\n            const auto& s = a[i];\n            int h = (int)s.size();\n\n            score += cfg.heightW * h;\n\n            for (int j = 0; j + 1 < h; j++) {\n                int lower = s[j];\n                int upper = s[j + 1];\n\n                if (lower < upper) {\n                    score += cfg.badBoundaryPenalty * 0.07;\n                    if (lower < cur + 45) score += cfg.badBoundaryPenalty * 0.07;\n                } else {\n                    score -= cfg.goodBoundaryBonus * 0.01;\n                }\n            }\n\n            for (int j = 0; j < h; j++) {\n                int v = s[j];\n                if (v >= cur && v < cur + 40) {\n                    int above = h - 1 - j;\n                    score += above * (42 - (v - cur)) * cfg.nearDepthW * 0.02;\n                }\n            }\n\n            if (!s.empty()) {\n                int top = s.back();\n                if (top >= cur && top < cur + 30) {\n                    score -= (32 - (top - cur)) * cfg.topSmallBonus * 0.03;\n                }\n            }\n\n            if (cfg.mode == 1 || cfg.mode == 3) {\n                score += bucket_eval_stack(s, cur, cfg);\n            }\n        }\n\n        return score;\n    }\n\n    double destination_score(\n        const vector<vector<int>>& a,\n        int dst,\n        int src,\n        const vector<int>& seg,\n        int cur,\n        const Config& cfg\n    ) const {\n        int bottom = seg.front();\n        int topSeg = seg.back();\n        int segMin = *min_element(seg.begin(), seg.end());\n        int k = (int)seg.size();\n\n        double sc = 0.0;\n\n        if (a[dst].empty()) {\n            sc -= cfg.emptyBonus;\n            sc += k * 1.5;\n        } else {\n            int top = a[dst].back();\n\n            if (top > bottom) {\n                sc -= cfg.goodBoundaryBonus;\n                sc += (top - bottom) * 0.7;\n            } else {\n                sc += cfg.badBoundaryPenalty;\n                sc += (bottom - top) * cfg.badBoundaryDiffW;\n            }\n\n            if (top < cur + 25) {\n                sc += cfg.coverSmallPenalty;\n                sc += (cur + 25 - top) * 3.0;\n            }\n\n            sc += abs(top - bottom) * 0.35;\n\n            if (cfg.mode == 1 || cfg.mode == 3) {\n                int bt = bucket(top, cfg.bucketSize);\n                int bb = bucket(bottom, cfg.bucketSize);\n                int bm = bucket(segMin, cfg.bucketSize);\n\n                if (bt > bb) {\n                    sc -= cfg.bucketW * (1 + bt - bb);\n                } else if (bt == bb) {\n                    if (top > bottom) sc -= cfg.bucketW * 0.4;\n                    else sc += cfg.bucketW * 0.8;\n                } else {\n                    sc += cfg.bucketW * (2 + bb - bt);\n                }\n\n                if (top < cur + cfg.bucketSize * 2) {\n                    sc += cfg.bucketW * 2.5;\n                }\n\n                if (segMin < cur + cfg.bucketSize * 2) {\n                    sc += (int)a[dst].size() * cfg.bucketW * 0.25;\n                }\n\n                if (bt >= bm) sc -= cfg.bucketW * 0.5;\n            }\n        }\n\n        sc += (int)a[dst].size() * cfg.heightW;\n\n        if (segMin < cur + 25) sc += (int)a[dst].size() * cfg.nearDepthW;\n        if (topSeg < cur + 20) sc += (int)a[dst].size() * cfg.nearDepthW * 0.8;\n\n        return sc;\n    }\n\n    int greedy_future_dst(\n        const vector<vector<int>>& a,\n        int src,\n        const vector<int>& seg,\n        int cur,\n        const Config& cfg\n    ) const {\n        int bd = -1;\n        double bs = 1e100;\n        for (int d = 0; d < m; d++) {\n            if (d == src) continue;\n            double ds = destination_score(a, d, src, seg, cur, cfg);\n            if (ds < bs) {\n                bs = ds;\n                bd = d;\n            }\n        }\n        if (bd == -1) bd = (src + 1) % m;\n        return bd;\n    }\n\n    double rollout_after_state(vector<vector<int>> a, int cur, double initialCost, const Config& cfg) const {\n        double futureCost = initialCost;\n        cur = remove_greedy_sim(a, cur, n);\n\n        int rolloutEnd = min(n, cur + cfg.rolloutHorizon);\n        int steps = 0;\n\n        while (cur <= rolloutEnd && steps < cfg.rolloutHorizon) {\n            int s = find_stack(a, cur);\n            if (s < 0) {\n                cur++;\n                continue;\n            }\n\n            int id = find_index(a[s], cur);\n            if (id == (int)a[s].size() - 1) {\n                cur = remove_greedy_sim(a, cur, rolloutEnd);\n                continue;\n            }\n\n            vector<int> sg;\n            for (int j = id + 1; j < (int)a[s].size(); j++) sg.push_back(a[s][j]);\n\n            int d = greedy_future_dst(a, s, sg, cur, cfg);\n            futureCost += (int)sg.size() + 1;\n\n            for (int x : sg) a[d].push_back(x);\n            a[s].resize(id + 1);\n\n            cur = remove_greedy_sim(a, cur, rolloutEnd);\n            steps++;\n        }\n\n        return cfg.costW * futureCost + cfg.staticW * static_eval(a, cur, cfg);\n    }\n\n    int choose_dst_rollout(\n        const vector<vector<int>>& st,\n        int src,\n        int idx,\n        int cur,\n        const Config& cfg\n    ) const {\n        vector<int> seg;\n        for (int j = idx + 1; j < (int)st[src].size(); j++) seg.push_back(st[src][j]);\n\n        int bestDst = -1;\n        double bestScore = 1e100;\n\n        for (int dst = 0; dst < m; dst++) {\n            if (dst == src) continue;\n\n            vector<vector<int>> a = st;\n            for (int x : seg) a[dst].push_back(x);\n            a[src].resize(idx + 1);\n\n            double score = rollout_after_state(a, cur, (int)seg.size() + 1, cfg)\n                         + destination_score(st, dst, src, seg, cur, cfg) * 0.15;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestDst = dst;\n            }\n        }\n\n        if (bestDst == -1) bestDst = (src + 1) % m;\n        return bestDst;\n    }\n\n    int choose_dst_beam(\n        const vector<vector<int>>& st,\n        int src,\n        int idx,\n        int cur,\n        const Config& cfg\n    ) const {\n        vector<BeamState> beam;\n\n        vector<int> firstSeg;\n        for (int j = idx + 1; j < (int)st[src].size(); j++) firstSeg.push_back(st[src][j]);\n        int firstK = (int)firstSeg.size();\n\n        for (int dst = 0; dst < m; dst++) {\n            if (dst == src) continue;\n\n            BeamState ns;\n            ns.st = st;\n            ns.cur = cur;\n            ns.energy = firstK + 1;\n            ns.firstDst = dst;\n\n            for (int x : firstSeg) ns.st[dst].push_back(x);\n            ns.st[src].resize(idx + 1);\n            ns.cur = remove_greedy_sim(ns.st, ns.cur, n);\n\n            ns.score = cfg.costW * ns.energy + cfg.staticW * static_eval(ns.st, ns.cur, cfg);\n            beam.push_back(std::move(ns));\n        }\n\n        int targetEnd = min(n, cur + cfg.rolloutHorizon);\n\n        for (int depth = 0; depth < cfg.rolloutHorizon; depth++) {\n            vector<BeamState> nxt;\n\n            for (const auto& state : beam) {\n                if (state.cur > targetEnd) {\n                    nxt.push_back(state);\n                    continue;\n                }\n\n                int s = find_stack(state.st, state.cur);\n                if (s < 0) {\n                    BeamState ns = state;\n                    ns.cur++;\n                    ns.cur = remove_greedy_sim(ns.st, ns.cur, targetEnd);\n                    ns.score = cfg.costW * ns.energy\n                             + cfg.staticW * static_eval(ns.st, ns.cur, cfg)\n                             - (ns.cur - cur) * 8.0;\n                    nxt.push_back(std::move(ns));\n                    continue;\n                }\n\n                int id = find_index(state.st[s], state.cur);\n                if (id == (int)state.st[s].size() - 1) {\n                    BeamState ns = state;\n                    ns.cur = remove_greedy_sim(ns.st, ns.cur, targetEnd);\n                    ns.score = cfg.costW * ns.energy\n                             + cfg.staticW * static_eval(ns.st, ns.cur, cfg)\n                             - (ns.cur - cur) * 8.0;\n                    nxt.push_back(std::move(ns));\n                    continue;\n                }\n\n                vector<int> seg;\n                for (int j = id + 1; j < (int)state.st[s].size(); j++) seg.push_back(state.st[s][j]);\n                int k = (int)seg.size();\n\n                vector<pair<double,int>> cand;\n                for (int d = 0; d < m; d++) {\n                    if (d == s) continue;\n                    cand.push_back({destination_score(state.st, d, s, seg, state.cur, cfg), d});\n                }\n                sort(cand.begin(), cand.end());\n\n                int branchLimit = min<int>((int)cand.size(), max(3, cfg.beamWidth));\n                for (int bi = 0; bi < branchLimit; bi++) {\n                    int d = cand[bi].second;\n\n                    BeamState ns = state;\n                    ns.energy += k + 1;\n\n                    for (int x : seg) ns.st[d].push_back(x);\n                    ns.st[s].resize(id + 1);\n\n                    ns.cur = remove_greedy_sim(ns.st, ns.cur, targetEnd);\n\n                    ns.score = cfg.costW * ns.energy\n                             + cfg.staticW * static_eval(ns.st, ns.cur, cfg)\n                             + cand[bi].first * 0.05\n                             - (ns.cur - cur) * 8.0;\n\n                    nxt.push_back(std::move(ns));\n                }\n            }\n\n            if (nxt.empty()) break;\n\n            sort(nxt.begin(), nxt.end(), [](const BeamState& a, const BeamState& b) {\n                return a.score < b.score;\n            });\n\n            if ((int)nxt.size() > cfg.beamWidth) nxt.resize(cfg.beamWidth);\n            beam.swap(nxt);\n        }\n\n        int bestDst = -1;\n        double bestScore = 1e100;\n\n        for (auto& state : beam) {\n            double sc = cfg.costW * state.energy\n                      + cfg.staticW * static_eval(state.st, state.cur, cfg)\n                      - (state.cur - cur) * 10.0;\n\n            if (sc < bestScore) {\n                bestScore = sc;\n                bestDst = state.firstDst;\n            }\n        }\n\n        if (bestDst == -1) bestDst = (src + 1) % m;\n        return bestDst;\n    }\n\n    vector<int> select_split_candidates(const vector<vector<int>>& st, int src, int idx, int cur, const Config& cfg) const {\n        vector<int> ret;\n        int h = (int)st[src].size();\n        int start = idx + 1;\n        int len = h - start;\n        if (len < 6) return ret;\n\n        auto add = [&](int sp) {\n            if (sp <= start + 1 || sp >= h - 1) return;\n            ret.push_back(sp);\n        };\n\n        // Heuristic candidates.\n        for (int sp = start + 2; sp <= h - 2; sp++) {\n            int lowerTop = st[src][sp - 1];\n            int upperBottom = st[src][sp];\n\n            bool good = false;\n\n            if (abs(lowerTop - upperBottom) >= 40) good = true;\n\n            int upperMin = 1000000, upperMax = -1;\n            int lowerMin = 1000000, lowerMax = -1;\n            for (int j = sp; j < h; j++) {\n                upperMin = min(upperMin, st[src][j]);\n                upperMax = max(upperMax, st[src][j]);\n            }\n            for (int j = start; j < sp; j++) {\n                lowerMin = min(lowerMin, st[src][j]);\n                lowerMax = max(lowerMax, st[src][j]);\n            }\n\n            if (upperMin < cur + 40) good = true;\n            if (upperMin + 35 < lowerMin) good = true;\n            if (lowerMax + 35 < upperMax) good = true;\n\n            if (good) add(sp);\n        }\n\n        // Split just below the minimum blocker if meaningful.\n        int minPos = -1, minVal = INT_MAX;\n        for (int j = start; j < h; j++) {\n            if (st[src][j] < minVal) {\n                minVal = st[src][j];\n                minPos = j;\n            }\n        }\n        add(minPos);\n        add(minPos + 1);\n\n        // Largest adjacent jump positions.\n        vector<pair<int,int>> jumps;\n        for (int sp = start + 2; sp <= h - 2; sp++) {\n            jumps.push_back({abs(st[src][sp] - st[src][sp - 1]), sp});\n        }\n        sort(jumps.rbegin(), jumps.rend());\n        for (int i = 0; i < (int)jumps.size() && i < 3; i++) add(jumps[i].second);\n\n        sort(ret.begin(), ret.end());\n        ret.erase(unique(ret.begin(), ret.end()), ret.end());\n\n        // Rank by upper minimum and jump size.\n        sort(ret.begin(), ret.end(), [&](int a, int b) {\n            auto key = [&](int sp) {\n                int upperMin = 1000000;\n                for (int j = sp; j < h; j++) upperMin = min(upperMin, st[src][j]);\n                int jump = abs(st[src][sp] - st[src][sp - 1]);\n                return pair<int,int>(upperMin, -jump);\n            };\n            return key(a) < key(b);\n        });\n\n        if ((int)ret.size() > cfg.splitMaxCandidates) ret.resize(cfg.splitMaxCandidates);\n        return ret;\n    }\n\n    FirstAction choose_action_split(\n        const vector<vector<int>>& st,\n        int src,\n        int idx,\n        int cur,\n        const Config& cfg\n    ) const {\n        vector<FirstAction> actions;\n\n        int h = (int)st[src].size();\n        int start = idx + 1;\n\n        vector<int> whole;\n        for (int j = start; j < h; j++) whole.push_back(st[src][j]);\n\n        // Normal actions.\n        for (int d = 0; d < m; d++) {\n            if (d == src) continue;\n\n            vector<vector<int>> a = st;\n            for (int x : whole) a[d].push_back(x);\n            a[src].resize(start);\n\n            double sc = rollout_after_state(a, cur, (int)whole.size() + 1, cfg)\n                      + destination_score(st, d, src, whole, cur, cfg) * 0.15;\n\n            actions.push_back({0, -1, d, -1, sc});\n        }\n\n        vector<int> candidateSplits = select_split_candidates(st, src, idx, cur, cfg);\n\n        for (int sp : candidateSplits) {\n            vector<int> lower, upper;\n            for (int j = start; j < sp; j++) lower.push_back(st[src][j]);\n            for (int j = sp; j < h; j++) upper.push_back(st[src][j]);\n\n            for (int d1 = 0; d1 < m; d1++) {\n                if (d1 == src) continue;\n\n                vector<vector<int>> a1 = st;\n                for (int x : upper) a1[d1].push_back(x);\n                a1[src].resize(sp);\n\n                vector<pair<double,int>> cand2;\n                for (int d2 = 0; d2 < m; d2++) {\n                    if (d2 == src) continue;\n                    cand2.push_back({destination_score(a1, d2, src, lower, cur, cfg), d2});\n                }\n                sort(cand2.begin(), cand2.end());\n\n                int lim2 = min<int>(4, cand2.size());\n                for (int ci = 0; ci < lim2; ci++) {\n                    int d2 = cand2[ci].second;\n\n                    vector<vector<int>> a = a1;\n                    for (int x : lower) a[d2].push_back(x);\n                    a[src].resize(start);\n\n                    double initCost = (int)upper.size() + 1 + (int)lower.size() + 1;\n                    double sc = rollout_after_state(a, cur, initCost, cfg)\n                              + destination_score(st, d1, src, upper, cur, cfg) * 0.10\n                              + destination_score(a1, d2, src, lower, cur, cfg) * 0.10\n                              + cfg.splitPenalty;\n\n                    actions.push_back({1, sp, d1, d2, sc});\n                }\n            }\n        }\n\n        return *min_element(actions.begin(), actions.end(), [](const FirstAction& a, const FirstAction& b) {\n            return a.score < b.score;\n        });\n    }\n\n    Result run_one(const Config& cfg) const {\n        vector<vector<int>> st = init;\n        vector<pair<int,int>> ops;\n        int energy = 0;\n        int cur = 1;\n\n        auto real_remove = [&]() {\n            bool changed = true;\n            while (cur <= n && changed) {\n                changed = false;\n                for (int i = 0; i < m; i++) {\n                    if (!st[i].empty() && st[i].back() == cur) {\n                        st[i].pop_back();\n                        ops.push_back({cur, 0});\n                        cur++;\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n        };\n\n        real_remove();\n\n        while (cur <= n && (int)ops.size() < 5000) {\n            int src = find_stack(st, cur);\n            if (src < 0) {\n                real_remove();\n                continue;\n            }\n\n            int idx = find_index(st[src], cur);\n            if (idx == (int)st[src].size() - 1) {\n                real_remove();\n                continue;\n            }\n\n            if (cfg.mode == 3) {\n                FirstAction act = choose_action_split(st, src, idx, cur, cfg);\n\n                int h = (int)st[src].size();\n                int start = idx + 1;\n\n                if (act.type == 0) {\n                    int d = act.dst1;\n                    int v = st[src][start];\n                    int k = h - start;\n\n                    ops.push_back({v, d + 1});\n                    energy += k + 1;\n\n                    for (int j = start; j < h; j++) st[d].push_back(st[src][j]);\n                    st[src].resize(start);\n                } else {\n                    int sp = act.split;\n                    int d1 = act.dst1;\n                    int d2 = act.dst2;\n\n                    int v1 = st[src][sp];\n                    int k1 = h - sp;\n                    ops.push_back({v1, d1 + 1});\n                    energy += k1 + 1;\n\n                    for (int j = sp; j < h; j++) st[d1].push_back(st[src][j]);\n                    st[src].resize(sp);\n\n                    int v2 = st[src][start];\n                    int k2 = sp - start;\n                    ops.push_back({v2, d2 + 1});\n                    energy += k2 + 1;\n\n                    for (int j = start; j < sp; j++) st[d2].push_back(st[src][j]);\n                    st[src].resize(start);\n                }\n            } else {\n                int dst;\n                if (cfg.mode == 2) dst = choose_dst_beam(st, src, idx, cur, cfg);\n                else dst = choose_dst_rollout(st, src, idx, cur, cfg);\n\n                int v = st[src][idx + 1];\n                int k = (int)st[src].size() - (idx + 1);\n\n                ops.push_back({v, dst + 1});\n                energy += k + 1;\n\n                for (int j = idx + 1; j < (int)st[src].size(); j++) {\n                    st[dst].push_back(st[src][j]);\n                }\n                st[src].resize(idx + 1);\n            }\n\n            real_remove();\n        }\n\n        return {ops, energy};\n    }\n\n    Result solve() const {\n        vector<Config> configs = {\n            // Rollout family.\n            {0,45,100,250,180,350,5,3,4,30,500,1,0,20,1,0,4},\n            {0,55,125,220,160,380,5.5,3,5,25,550,0.8,0,20,1,0,4},\n            {0,50,90,260,220,420,6,4,5.5,35,650,1.4,0,20,1,0,4},\n            {0,45,105,350,170,360,5,3.5,4.5,30,520,1,0,20,1,0,4},\n            {0,50,100,240,170,340,5,3,4.5,30,850,1,0,20,1,0,4},\n            {0,55,100,230,260,430,6,3,4.2,35,550,1.1,0,20,1,0,4},\n            {0,30,120,260,190,350,4.5,2.5,3.5,25,450,0.7,0,20,1,0,4},\n            {0,70,115,220,180,360,5,3.5,4.5,30,600,1,0,20,1,0,4},\n            {0,50,100,260,180,360,5,6,5,30,550,1,0,20,1,0,4},\n            {0,55,105,240,180,380,5.5,3,8,35,600,1.2,0,20,1,0,4},\n\n            // Bucket family.\n            {1,45,105,260,190,380,5,3,4.5,30,550,1,45,20,1,0,4},\n            {1,55,110,240,200,400,5.5,3,5,30,600,1.1,55,20,1,0,4},\n            {1,60,100,280,220,420,6,4,5.5,35,650,1.2,65,25,1,0,4},\n            {1,40,120,300,180,360,5,3,4,25,520,0.9,50,15,1,0,4},\n            {1,70,105,230,240,440,6,3.5,5,35,650,1.2,60,20,1,0,4},\n            {1,50,95,320,180,380,5,5,6,35,700,1.4,70,25,1,0,4},\n\n            // Beam family.\n            {2,18,100,250,180,350,5,3,4,30,500,1,0,20,6,0,4},\n            {2,22,105,240,200,390,5.5,3,5,30,600,1,0,20,7,0,4},\n            {2,26,95,260,220,420,6,4,5,35,650,1.2,0,20,7,0,4},\n            {2,20,115,300,170,360,5,3.5,4.5,30,520,0.9,0,20,6,0,4},\n\n            // Split family, conservative to aggressive.\n            {3,45,105,260,190,380,5,3,4.5,30,550,1,45,20,1,35,4},\n            {3,55,110,240,210,410,5.5,3.5,5,35,620,1.1,55,20,1,25,5},\n            {3,40,120,300,180,360,5,3,4,25,520,0.9,50,15,1,20,4},\n            {3,60,100,250,220,430,6,4,5.5,35,650,1.2,60,20,1,15,5},\n            {3,50,95,320,180,380,5,5,6,35,700,1.4,70,25,1,10,5},\n            {3,70,115,220,190,370,5,3.5,4.5,30,600,1,45,20,1,30,4},\n            {3,35,130,280,170,350,4,2.5,3.5,25,480,0.8,40,20,1,5,5},\n        };\n\n        Result best;\n        best.energy = INT_MAX;\n\n        for (const auto& cfg : configs) {\n            Result r = run_one(cfg);\n            if ((int)r.ops.size() <= 5000 && r.energy < best.energy) {\n                best = std::move(r);\n            }\n        }\n\n        return best;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> st(m);\n    int h = n / m;\n    for (int i = 0; i < m; i++) {\n        st[i].resize(h);\n        for (int j = 0; j < h; j++) cin >> st[i][j];\n    }\n\n    PortfolioSolver solver(n, m, st);\n    Result res = solver.solve();\n\n    for (auto [v, to] : res.ops) {\n        cout << v << ' ' << to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge { int to; char c; };\nstruct Cand { string route; long double score; };\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto t0=chrono::steady_clock::now();\n    auto elapsed=[&](){\n        return chrono::duration<double>(chrono::steady_clock::now()-t0).count();\n    };\n\n    int N;\n    cin>>N;\n\n    vector<string> h(N-1), v(N);\n    for(int i=0;i<N-1;i++) cin>>h[i];\n    for(int i=0;i<N;i++) cin>>v[i];\n\n    int V=N*N;\n    auto id=[&](int i,int j){return i*N+j;};\n    auto pos=[&](int x){return pair<int,int>{x/N,x%N};};\n\n    vector<int> dirt(V);\n    for(int i=0;i<N;i++) {\n        for(int j=0;j<N;j++) cin>>dirt[id(i,j)];\n    }\n\n    vector<vector<Edge>> g(V);\n    auto add=[&](int a,int b,char c){ g[a].push_back({b,c}); };\n\n    for(int i=0;i<N;i++) for(int j=0;j<N;j++){\n        int u=id(i,j);\n        if(i+1<N && h[i][j]=='0'){\n            add(u,id(i+1,j),'D');\n            add(id(i+1,j),u,'U');\n        }\n        if(j+1<N && v[i][j]=='0'){\n            add(u,id(i,j+1),'R');\n            add(id(i,j+1),u,'L');\n        }\n    }\n\n    auto opp=[&](char c){\n        if(c=='U') return 'D';\n        if(c=='D') return 'U';\n        if(c=='L') return 'R';\n        return 'L';\n    };\n\n    auto step=[&](int u,char c){\n        for(auto e:g[u]) if(e.c==c) return e.to;\n        return -1;\n    };\n\n    vector<vector<int>> dist(V, vector<int>(V,-1));\n    vector<vector<int>> par(V, vector<int>(V,-1));\n    vector<vector<char>> pm(V, vector<char>(V,'?'));\n\n    for(int s=0;s<V;s++){\n        queue<int> q;\n        dist[s][s]=0;\n        q.push(s);\n\n        while(!q.empty()){\n            int u=q.front();\n            q.pop();\n\n            vector<Edge> es=g[u];\n            sort(es.begin(), es.end(), [&](const Edge&a,const Edge&b){\n                return dirt[a.to]>dirt[b.to];\n            });\n\n            for(auto e:es){\n                if(dist[s][e.to]<0){\n                    dist[s][e.to]=dist[s][u]+1;\n                    par[s][e.to]=u;\n                    pm[s][e.to]=e.c;\n                    q.push(e.to);\n                }\n            }\n        }\n    }\n\n    auto path=[&](int s,int t){\n        string r;\n        int cur=t;\n        while(cur!=s){\n            r.push_back(pm[s][cur]);\n            cur=par[s][cur];\n        }\n        reverse(r.begin(), r.end());\n        return r;\n    };\n\n    auto revroute=[&](const string& s){\n        string r;\n        r.reserve(s.size());\n        for(int i=(int)s.size()-1;i>=0;i--) r.push_back(opp(s[i]));\n        return r;\n    };\n\n    auto eval=[&](const string& route)->long double{\n        int L=route.size();\n        if(L<=0 || L>100000) return 1e100L;\n\n        vector<vector<int>> vis(V);\n        int cur=0;\n\n        for(int t=1;t<=L;t++){\n            cur=step(cur,route[t-1]);\n            if(cur<0) return 1e100L;\n            vis[cur].push_back(t);\n        }\n\n        if(cur!=0) return 1e100L;\n\n        long double res=0;\n        for(int x=0;x<V;x++){\n            if(vis[x].empty()) return 1e100L;\n\n            long long tri=0;\n            int m=vis[x].size();\n\n            for(int k=0;k<m;k++){\n                int a=vis[x][k];\n                int b=vis[x][(k+1)%m];\n                int gap=(k+1<m ? b-a : b+L-a);\n                tri += 1LL*gap*(gap-1)/2;\n            }\n\n            res += (long double)dirt[x]*(long double)tri/(long double)L;\n        }\n\n        return res;\n    };\n\n    vector<Cand> cands;\n    unordered_set<string> seen;\n    seen.reserve(30000);\n\n    auto addcand=[&](const string& s){\n        if(s.empty() || (int)s.size()>100000) return;\n        if(seen.find(s)!=seen.end()) return;\n        seen.insert(s);\n\n        long double sc=eval(s);\n        if(sc<1e90L) cands.push_back({s,sc});\n    };\n\n    auto prio=[&](int x,int mode)->long double{\n        auto [i,j]=pos(x);\n        long double cen=fabsl(i-(N-1)/2.0L)+fabsl(j-(N-1)/2.0L);\n\n        if(mode==0) return dirt[x];\n        if(mode==1) return -dirt[x];\n        if(mode==2) return i*N+j;\n        if(mode==3) return -(i*N+j);\n        if(mode==4) return i+j;\n        if(mode==5) return -(i+j);\n        if(mode==6) return i-j;\n        if(mode==7) return j-i;\n        if(mode==8) return -cen;\n        if(mode==9) return cen;\n        if(mode==10) return dirt[x]-5*cen;\n        if(mode==11) return dirt[x]+5*cen;\n        if(mode==12) return dirt[x]+2*(i+j);\n        if(mode==13) return dirt[x]-2*(i+j);\n\n        return dirt[x];\n    };\n\n    auto make_dfs=[&](int bm,int om){\n        vector<int> vis(V), parent(V,-1);\n        vector<char> pc(V);\n        vector<vector<int>> tr(V);\n\n        function<void(int)> build=[&](int u){\n            vis[u]=1;\n            vector<Edge> es=g[u];\n\n            sort(es.begin(), es.end(), [&](const Edge&a,const Edge&b){\n                long double A=prio(a.to,bm), B=prio(b.to,bm);\n                if(A!=B) return A>B;\n                return a.to<b.to;\n            });\n\n            for(auto e:es){\n                if(!vis[e.to]){\n                    parent[e.to]=u;\n                    pc[e.to]=e.c;\n                    tr[u].push_back(e.to);\n                    build(e.to);\n                }\n            }\n        };\n\n        build(0);\n\n        vector<long long> subD(V);\n        vector<int> subS(V);\n\n        function<void(int)> calc=[&](int u){\n            subD[u]=dirt[u];\n            subS[u]=1;\n            for(int w:tr[u]){\n                calc(w);\n                subD[u]+=subD[w];\n                subS[u]+=subS[w];\n            }\n        };\n        calc(0);\n\n        for(int u=0;u<V;u++){\n            sort(tr[u].begin(), tr[u].end(), [&](int a,int b){\n                if(om==0) return subD[a]>subD[b];\n                if(om==1) return subD[a]<subD[b];\n                if(om==2) return dirt[a]>dirt[b];\n                if(om==3) return dirt[a]<dirt[b];\n                if(om==4) return subS[a]>subS[b];\n                if(om==5) return subS[a]<subS[b];\n\n                auto [ai,aj]=pos(a);\n                auto [bi,bj]=pos(b);\n\n                if(om==6) return ai+aj<bi+bj;\n                if(om==7) return ai+aj>bi+bj;\n                if(om==8) return ai-aj<bi-bj;\n                if(om==9) return ai-aj>bi-bj;\n                if(om==10) return (long double)subD[a]/subS[a] > (long double)subD[b]/subS[b];\n                return (long double)subD[a]/subS[a] < (long double)subD[b]/subS[b];\n            });\n        }\n\n        string ans;\n        ans.reserve(2*V);\n\n        function<void(int)> tour=[&](int u){\n            for(int w:tr[u]){\n                ans.push_back(pc[w]);\n                tour(w);\n                ans.push_back(opp(pc[w]));\n            }\n        };\n\n        tour(0);\n        return ans;\n    };\n\n    for(int bm=0;bm<14;bm++){\n        for(int om=0;om<12;om++){\n            if(elapsed()>0.88) break;\n\n            string s=make_dfs(bm,om);\n            addcand(s);\n            addcand(revroute(s));\n        }\n    }\n\n    auto route_from_order=[&](const vector<int>& ord, bool skipVisitedTarget){\n        vector<char> used(V,0);\n        string ans;\n        int cur=0;\n        used[0]=1;\n\n        for(int x:ord){\n            if(x==cur) continue;\n            if(skipVisitedTarget && used[x]) continue;\n\n            string p=path(cur,x);\n            for(char c:p){\n                ans.push_back(c);\n                cur=step(cur,c);\n                if(!used[cur]) used[cur]=1;\n            }\n        }\n\n        for(int x=0;x<V;x++){\n            if(!used[x]){\n                string p=path(cur,x);\n                for(char c:p){\n                    ans.push_back(c);\n                    cur=step(cur,c);\n                    if(!used[cur]) used[cur]=1;\n                }\n            }\n        }\n\n        ans += path(cur,0);\n        return ans;\n    };\n\n    vector<vector<int>> orders;\n\n    {\n        vector<int> o;\n        for(int i=0;i<N;i++) for(int j=0;j<N;j++) o.push_back(id(i,j));\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    {\n        vector<int> o;\n        for(int j=0;j<N;j++) for(int i=0;i<N;i++) o.push_back(id(i,j));\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    {\n        vector<int> o;\n        for(int i=0;i<N;i++){\n            if(i%2==0) for(int j=0;j<N;j++) o.push_back(id(i,j));\n            else for(int j=N-1;j>=0;j--) o.push_back(id(i,j));\n        }\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    {\n        vector<int> o;\n        for(int j=0;j<N;j++){\n            if(j%2==0) for(int i=0;i<N;i++) o.push_back(id(i,j));\n            else for(int i=N-1;i>=0;i--) o.push_back(id(i,j));\n        }\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    {\n        vector<int> o;\n        for(int s=0;s<=2*(N-1);s++){\n            vector<int> tmp;\n            for(int i=0;i<N;i++){\n                int j=s-i;\n                if(0<=j && j<N) tmp.push_back(id(i,j));\n            }\n            if(s%2) reverse(tmp.begin(),tmp.end());\n            for(int x:tmp) o.push_back(x);\n        }\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    // Morton/Z-order.\n    {\n        auto morton=[&](int x,int y){\n            int r=0;\n            for(int b=0;b<6;b++){\n                r |= ((x>>b)&1)<<(2*b+1);\n                r |= ((y>>b)&1)<<(2*b);\n            }\n            return r;\n        };\n\n        vector<int> o(V);\n        iota(o.begin(),o.end(),0);\n        sort(o.begin(),o.end(),[&](int a,int b){\n            auto [ai,aj]=pos(a);\n            auto [bi,bj]=pos(b);\n            return morton(ai,aj)<morton(bi,bj);\n        });\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    // Hilbert-like recursive order by quadrant.\n    function<void(int,int,int,int,int,vector<int>&)> hilbert_like =\n        [&](int r0,int r1,int c0,int c1,int type,vector<int>& out){\n            if(r0>r1 || c0>c1) return;\n            if(r1-r0<=2 && c1-c0<=2){\n                vector<int> tmp;\n                for(int i=r0;i<=r1;i++) for(int j=c0;j<=c1;j++) tmp.push_back(id(i,j));\n                sort(tmp.begin(),tmp.end(),[&](int a,int b){\n                    auto [ai,aj]=pos(a);\n                    auto [bi,bj]=pos(b);\n                    if(type%2==0) return ai+aj<bi+bj;\n                    return ai-aj<bi-bj;\n                });\n                for(int x:tmp) out.push_back(x);\n                return;\n            }\n\n            int rm=(r0+r1)/2;\n            int cm=(c0+c1)/2;\n\n            if(type==0){\n                hilbert_like(r0,rm,c0,cm,1,out);\n                hilbert_like(r0,rm,cm+1,c1,0,out);\n                hilbert_like(rm+1,r1,cm+1,c1,0,out);\n                hilbert_like(rm+1,r1,c0,cm,3,out);\n            }else if(type==1){\n                hilbert_like(r0,rm,c0,cm,0,out);\n                hilbert_like(rm+1,r1,c0,cm,1,out);\n                hilbert_like(rm+1,r1,cm+1,c1,1,out);\n                hilbert_like(r0,rm,cm+1,c1,2,out);\n            }else if(type==2){\n                hilbert_like(rm+1,r1,cm+1,c1,3,out);\n                hilbert_like(rm+1,r1,c0,cm,2,out);\n                hilbert_like(r0,rm,c0,cm,2,out);\n                hilbert_like(r0,rm,cm+1,c1,1,out);\n            }else{\n                hilbert_like(rm+1,r1,cm+1,c1,2,out);\n                hilbert_like(r0,rm,cm+1,c1,3,out);\n                hilbert_like(r0,rm,c0,cm,3,out);\n                hilbert_like(rm+1,r1,c0,cm,0,out);\n            }\n        };\n\n    for(int t=0;t<4;t++){\n        vector<int> o;\n        hilbert_like(0,N-1,0,N-1,t,o);\n        vector<char> seenCell(V,0);\n        vector<int> uniq;\n        for(int x:o) if(!seenCell[x]){\n            seenCell[x]=1;\n            uniq.push_back(x);\n        }\n        if((int)uniq.size()==V){\n            orders.push_back(uniq);\n            reverse(uniq.begin(),uniq.end());\n            orders.push_back(uniq);\n        }\n    }\n\n    // Block snake and dirt-block orders.\n    vector<int> blockSizes={2,3,4,5,6,8};\n    for(int B:blockSizes){\n        int RB=(N+B-1)/B, CB=(N+B-1)/B;\n\n        vector<pair<int,int>> blocks;\n        for(int br=0;br<RB;br++){\n            if(br%2==0){\n                for(int bc=0;bc<CB;bc++) blocks.push_back({br,bc});\n            }else{\n                for(int bc=CB-1;bc>=0;bc--) blocks.push_back({br,bc});\n            }\n        }\n\n        for(int variant=0;variant<2;variant++){\n            vector<int> o;\n            for(auto [br,bc]:blocks){\n                vector<int> tmp;\n                int r0=br*B, r1=min(N,(br+1)*B);\n                int c0=bc*B, c1=min(N,(bc+1)*B);\n\n                for(int i=r0;i<r1;i++){\n                    if(((i-r0)&1)==0){\n                        for(int j=c0;j<c1;j++) tmp.push_back(id(i,j));\n                    }else{\n                        for(int j=c1-1;j>=c0;j--) tmp.push_back(id(i,j));\n                    }\n                }\n\n                if(variant==1){\n                    sort(tmp.begin(),tmp.end(),[&](int a,int b){\n                        return dirt[a]>dirt[b];\n                    });\n                }\n\n                for(int x:tmp) o.push_back(x);\n            }\n\n            orders.push_back(o);\n            reverse(o.begin(),o.end());\n            orders.push_back(o);\n        }\n\n        // Dirt-sorted blocks.\n        vector<tuple<long long,int,int>> db;\n        for(int br=0;br<RB;br++){\n            for(int bc=0;bc<CB;bc++){\n                long long sum=0;\n                int r0=br*B, r1=min(N,(br+1)*B);\n                int c0=bc*B, c1=min(N,(bc+1)*B);\n                for(int i=r0;i<r1;i++) for(int j=c0;j<c1;j++) sum+=dirt[id(i,j)];\n                db.push_back({-sum,br,bc});\n            }\n        }\n        sort(db.begin(),db.end());\n\n        vector<int> o;\n        for(auto [neg,br,bc]:db){\n            vector<int> tmp;\n            int r0=br*B, r1=min(N,(br+1)*B);\n            int c0=bc*B, c1=min(N,(bc+1)*B);\n            for(int i=r0;i<r1;i++) for(int j=c0;j<c1;j++) tmp.push_back(id(i,j));\n            sort(tmp.begin(),tmp.end(),[&](int a,int b){return dirt[a]>dirt[b];});\n            for(int x:tmp) o.push_back(x);\n        }\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    for(int mode=0; mode<8; mode++){\n        vector<int> o(V);\n        iota(o.begin(),o.end(),0);\n\n        sort(o.begin(),o.end(),[&](int a,int b){\n            auto [ai,aj]=pos(a);\n            auto [bi,bj]=pos(b);\n\n            long double A=0,B=0;\n            if(mode==0){ A=dist[0][a]; B=dist[0][b]; }\n            else if(mode==1){ A=-dist[0][a]; B=-dist[0][b]; }\n            else if(mode==2){ A=dirt[a]; B=dirt[b]; }\n            else if(mode==3){ A=-dirt[a]; B=-dirt[b]; }\n            else if(mode==4){ A=ai+aj; B=bi+bj; }\n            else if(mode==5){ A=ai-aj; B=bi-bj; }\n            else if(mode==6){ A=(long double)dirt[a]/(dist[0][a]+1); B=(long double)dirt[b]/(dist[0][b]+1); }\n            else { A=(long double)dirt[a]-5*dist[0][a]; B=(long double)dirt[b]-5*dist[0][b]; }\n\n            if(A!=B) return A<B;\n            return a<b;\n        });\n\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    for(auto &o:orders){\n        if(elapsed()>1.12) break;\n\n        string s1=route_from_order(o,true);\n        addcand(s1);\n        addcand(revroute(s1));\n\n        if(elapsed()>1.12) break;\n\n        string s2=route_from_order(o,false);\n        addcand(s2);\n        addcand(revroute(s2));\n    }\n\n    mt19937 rng(712367);\n    uniform_real_distribution<double> ur(-1,1);\n\n    auto make_greedy=[&](int mode,double noise){\n        vector<char> un(V,1);\n        un[0]=0;\n        int rem=V-1, cur=0;\n        string ans;\n        ans.reserve(20000);\n\n        while(rem>0){\n            int best=-1;\n            long double bs=-1e100L;\n\n            for(int x=0;x<V;x++) if(un[x]){\n                int dd=max(1,dist[cur][x]);\n                auto [ci,cj]=pos(cur);\n                auto [xi,xj]=pos(x);\n\n                long double geo=abs(xi-ci)+abs(xj-cj);\n                long double cen=fabsl(xi-(N-1)/2.0L)+fabsl(xj-(N-1)/2.0L);\n                long double sc;\n\n                if(mode==0) sc=-dd;\n                else if(mode==1) sc=(long double)dirt[x]/dd;\n                else if(mode==2) sc=(long double)dirt[x]/sqrt((long double)dd);\n                else if(mode==3) sc=(long double)dirt[x]-10.0L*dd;\n                else if(mode==4) sc=sqrt((long double)dirt[x])-dd;\n                else if(mode==5) sc=-dd+0.05L*dirt[x]-0.1L*geo;\n                else if(mode==6) sc=-dd+0.02L*dirt[x]+0.5L*geo;\n                else if(mode==7) sc=(long double)dirt[x]/(dd+5);\n                else if(mode==8) sc=(long double)dirt[x]/pow((long double)dd,0.75L);\n                else if(mode==9) sc=-dd+0.01L*dirt[x];\n                else if(mode==10) sc=-dd+0.03L*dirt[x];\n                else if(mode==11) sc=-dd+0.08L*dirt[x];\n                else if(mode==12) sc=(long double)dirt[x]/(dd+1) - 0.03L*cen;\n                else if(mode==13) sc=-dd + 0.04L*dirt[x] + 0.02L*cen;\n                else if(mode==14) sc=-dd + 0.02L*dirt[x] - 0.25L*dist[0][x];\n                else sc=(long double)dirt[x]/pow((long double)(dd+1),0.55L) - 0.05L*dist[0][x];\n\n                sc += noise*ur(rng);\n\n                if(sc>bs){\n                    bs=sc;\n                    best=x;\n                }\n            }\n\n            string p=path(cur,best);\n            for(char c:p){\n                ans.push_back(c);\n                cur=step(cur,c);\n                if(un[cur]){\n                    un[cur]=0;\n                    rem--;\n                }\n            }\n\n            if((int)ans.size()>90000) break;\n        }\n\n        ans += path(cur,0);\n        return ans;\n    };\n\n    for(int m=0;m<16;m++){\n        if(elapsed()>1.26) break;\n        string s=make_greedy(m,0);\n        addcand(s);\n        addcand(revroute(s));\n    }\n\n    int trials=0;\n    while(elapsed()<1.43 && trials<65){\n        string s=make_greedy(trials%16, 0.4+(trials%10)*0.7);\n        addcand(s);\n        addcand(revroute(s));\n        trials++;\n    }\n\n    sort(cands.begin(), cands.end(), [](auto&a,auto&b){return a.score<b.score;});\n\n    // Internal-origin rotations.\n    {\n        vector<string> extra;\n        for(int bi=0;bi<min<int>(12,cands.size());bi++){\n            const string& s=cands[bi].route;\n            int cur=0;\n            vector<int> cuts;\n\n            for(int t=0;t<(int)s.size();t++){\n                cur=step(cur,s[t]);\n                if(cur==0 && t+1<(int)s.size()) cuts.push_back(t+1);\n            }\n\n            int stride=max(1,(int)cuts.size()/10);\n            for(int k=0;k<(int)cuts.size();k+=stride){\n                int cut=cuts[k];\n                extra.push_back(s.substr(cut)+s.substr(0,cut));\n            }\n        }\n\n        for(auto&s:extra){\n            if(elapsed()>1.52) break;\n            addcand(s);\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [](auto&a,auto&b){return a.score<b.score;});\n\n    // Multi-detour insertion.\n    vector<int> hi(V);\n    iota(hi.begin(),hi.end(),0);\n    sort(hi.begin(),hi.end(),[&](int a,int b){return dirt[a]>dirt[b];});\n    hi.resize(min(V,100));\n\n    auto route_positions=[&](const string& s){\n        vector<int> rp;\n        rp.reserve(s.size()+1);\n        int cur=0;\n        rp.push_back(cur);\n        for(char c:s){\n            cur=step(cur,c);\n            rp.push_back(cur);\n        }\n        return rp;\n    };\n\n    vector<string> dets;\n    int base=min<int>(6,cands.size());\n\n    for(int bi=0;bi<base;bi++){\n        string s=cands[bi].route;\n        long double bestSc=cands[bi].score;\n\n        for(int iter=0;iter<3;iter++){\n            if(elapsed()>1.70) break;\n\n            auto rp=route_positions(s);\n            int L=s.size();\n\n            vector<tuple<long double,int,int>> ops;\n            int stride=max(1,L/160);\n\n            for(int t=0;t<L;t+=stride){\n                int u=rp[t];\n\n                for(int x:hi){\n                    int dd=dist[u][x];\n                    if(dd<=0 || dd>8) continue;\n\n                    long double merit=(long double)dirt[x]/(2*dd+1);\n                    ops.push_back({merit,t,x});\n                }\n            }\n\n            sort(ops.begin(),ops.end(),greater<>());\n\n            bool improved=false;\n            int lim=min<int>(35,ops.size());\n\n            for(int k=0;k<lim;k++){\n                auto [mer,t,x]=ops[k];\n                int u=rp[t];\n\n                string go=path(u,x);\n                string ba=path(x,u);\n\n                if((int)s.size()+(int)go.size()+(int)ba.size()>100000) continue;\n\n                string ns;\n                ns.reserve(s.size()+go.size()+ba.size());\n                ns.append(s.begin(),s.begin()+t);\n                ns+=go;\n                ns+=ba;\n                ns.append(s.begin()+t,s.end());\n\n                long double sc=eval(ns);\n                if(sc+1e-9L<bestSc){\n                    s.swap(ns);\n                    bestSc=sc;\n                    improved=true;\n                    break;\n                }\n            }\n\n            if(!improved) break;\n        }\n\n        dets.push_back(s);\n    }\n\n    for(auto&s:dets){\n        if(elapsed()>1.78) break;\n        addcand(s);\n    }\n\n    sort(cands.begin(), cands.end(), [](auto&a,auto&b){return a.score<b.score;});\n\n    // Concatenate top routes.\n    {\n        vector<string> conc;\n        int bc=min<int>(7,cands.size());\n\n        for(int i=0;i<bc;i++){\n            for(int j=0;j<bc;j++){\n                if(i==j) continue;\n                if((int)cands[i].route.size()+(int)cands[j].route.size()<=100000){\n                    conc.push_back(cands[i].route+cands[j].route);\n                }\n            }\n        }\n\n        for(auto&s:conc){\n            if(elapsed()>1.92) break;\n            addcand(s);\n        }\n    }\n\n    int best=0;\n    for(int i=1;i<(int)cands.size();i++){\n        if(cands[i].score<cands[best].score) best=i;\n    }\n\n    cout<<cands[best].route<<\"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int r, c;\n};\n\nint mdist(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint overlap_len(const string& a, const string& b) {\n    int best = 0;\n    for (int k = 1; k <= 4; k++) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[5 - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) best = k;\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    Pos start;\n    cin >> start.r >> start.c;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> word(M);\n    for (int i = 0; i < M; i++) cin >> word[i];\n\n    vector<vector<Pos>> occ(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            occ[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) ov[i][j] = overlap_len(word[i], word[j]);\n        }\n    }\n\n    vector<vector<vector<vector<unsigned char>>>> cd(\n        26, vector<vector<vector<unsigned char>>>(26)\n    );\n\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            cd[a][b].assign(occ[a].size(), vector<unsigned char>(occ[b].size()));\n            for (int i = 0; i < (int)occ[a].size(); i++) {\n                for (int j = 0; j < (int)occ[b].size(); j++) {\n                    cd[a][b][i][j] = (unsigned char)(mdist(occ[a][i], occ[b][j]) + 1);\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> letter_cost(26, vector<int>(26, 1000000));\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            for (int i = 0; i < (int)occ[a].size(); i++) {\n                for (int j = 0; j < (int)occ[b].size(); j++) {\n                    letter_cost[a][b] = min<int>(letter_cost[a][b], cd[a][b][i][j]);\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> trans_cost(M, vector<int>(M, 0));\n    for (int a = 0; a < M; a++) {\n        for (int b = 0; b < M; b++) {\n            if (a == b) continue;\n\n            int k = ov[a][b];\n            int cost = 0;\n            char prev = word[a].back();\n\n            for (int p = k; p < 5; p++) {\n                char ch = word[b][p];\n                cost += letter_cost[prev - 'A'][ch - 'A'];\n                prev = ch;\n            }\n\n            trans_cost[a][b] = cost;\n        }\n    }\n\n    const int BIG = 10000;\n    const int START_PENALTY = 5 * BIG;\n\n    vector<int> weights = {0, 4, 8, 12, 16, 18, 22, 28, 36};\n    vector<vector<vector<int>>> edges;\n\n    for (int w : weights) {\n        vector<vector<int>> edge(M, vector<int>(M));\n        for (int a = 0; a < M; a++) {\n            for (int b = 0; b < M; b++) {\n                if (a == b) edge[a][b] = 0;\n                else edge[a][b] = (5 - ov[a][b]) * BIG + w * trans_cost[a][b];\n            }\n        }\n        edges.push_back(move(edge));\n    }\n\n    int base_edge_idx = 5;\n    const auto& base_edge = edges[base_edge_idx];\n\n    auto order_value = [&](const vector<int>& ord, const vector<vector<int>>& edge) {\n        int v = START_PENALTY;\n        for (int i = 1; i < (int)ord.size(); i++) {\n            v += edge[ord[i - 1]][ord[i]];\n        }\n        return v;\n    };\n\n    auto build_string = [&](const vector<int>& ord) {\n        string s = word[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            int k = ov[ord[i - 1]][ord[i]];\n            s += word[ord[i]].substr(k);\n        }\n        return s;\n    };\n\n    auto exact_cost_only = [&](const string& s) {\n        const int INF = 1e9;\n\n        int c0 = s[0] - 'A';\n        vector<int> dp(occ[c0].size(), INF);\n\n        for (int i = 0; i < (int)occ[c0].size(); i++) {\n            dp[i] = mdist(start, occ[c0][i]) + 1;\n        }\n\n        for (int p = 1; p < (int)s.size(); p++) {\n            int pc = s[p - 1] - 'A';\n            int cc = s[p] - 'A';\n\n            vector<int> ndp(occ[cc].size(), INF);\n\n            for (int i = 0; i < (int)occ[pc].size(); i++) {\n                int base = dp[i];\n                if (base >= INF) continue;\n\n                for (int j = 0; j < (int)occ[cc].size(); j++) {\n                    int val = base + cd[pc][cc][i][j];\n                    if (val < ndp[j]) ndp[j] = val;\n                }\n            }\n\n            dp.swap(ndp);\n        }\n\n        return *min_element(dp.begin(), dp.end());\n    };\n\n    mt19937 rng(987654321);\n    auto global_start = chrono::steady_clock::now();\n\n    auto make_append_greedy = [&](int st, double noise, double cw) {\n        vector<int> ord;\n        vector<char> used(M, false);\n        ord.reserve(M);\n\n        int cur = st;\n        ord.push_back(cur);\n        used[cur] = true;\n\n        for (int step = 1; step < M; step++) {\n            int best = -1;\n            double best_score = -1e100;\n\n            for (int nxt = 0; nxt < M; nxt++) {\n                if (used[nxt]) continue;\n\n                int mxout = 0;\n                for (int z = 0; z < M; z++) {\n                    if (!used[z] && z != nxt) {\n                        mxout = max(mxout, ov[nxt][z]);\n                    }\n                }\n\n                double score = 1260.0 * ov[cur][nxt]\n                             + 16.0 * mxout\n                             - cw * trans_cost[cur][nxt];\n\n                if (noise > 0) {\n                    score += uniform_real_distribution<double>(0.0, noise)(rng);\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best = nxt;\n                }\n            }\n\n            cur = best;\n            used[cur] = true;\n            ord.push_back(cur);\n        }\n\n        return ord;\n    };\n\n    auto make_insertion_greedy = [&](int st, double noise, const vector<vector<int>>& edge) {\n        vector<int> ord;\n        vector<char> used(M, false);\n\n        ord.push_back(st);\n        used[st] = true;\n\n        while ((int)ord.size() < M) {\n            int sz = ord.size();\n            int best_word = -1;\n            int best_pos = -1;\n            double best_gain = 1e100;\n\n            for (int x = 0; x < M; x++) {\n                if (used[x]) continue;\n\n                for (int pos = 0; pos <= sz; pos++) {\n                    int gain;\n                    if (pos == 0) {\n                        gain = edge[x][ord[0]];\n                    } else if (pos == sz) {\n                        gain = edge[ord[sz - 1]][x];\n                    } else {\n                        int a = ord[pos - 1];\n                        int b = ord[pos];\n                        gain = edge[a][x] + edge[x][b] - edge[a][b];\n                    }\n\n                    double g = gain;\n                    if (noise > 0) {\n                        g += uniform_real_distribution<double>(0.0, noise)(rng);\n                    }\n\n                    if (g < best_gain) {\n                        best_gain = g;\n                        best_word = x;\n                        best_pos = pos;\n                    }\n                }\n            }\n\n            ord.insert(ord.begin() + best_pos, best_word);\n            used[best_word] = true;\n        }\n\n        return ord;\n    };\n\n    auto improve_swap = [&](vector<int> ord, const vector<vector<int>>& edge,\n                            double limit_time) {\n        for (int round = 0; round < 2; round++) {\n            bool improved = false;\n\n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    vector<int> idxs;\n                    for (int x : {i - 1, i, j - 1, j}) {\n                        if (0 <= x && x + 1 < M) idxs.push_back(x);\n                    }\n                    sort(idxs.begin(), idxs.end());\n                    idxs.erase(unique(idxs.begin(), idxs.end()), idxs.end());\n\n                    int before = 0, after = 0;\n                    for (int x : idxs) before += edge[ord[x]][ord[x + 1]];\n\n                    swap(ord[i], ord[j]);\n\n                    for (int x : idxs) after += edge[ord[x]][ord[x + 1]];\n\n                    if (after < before) {\n                        improved = true;\n                    } else {\n                        swap(ord[i], ord[j]);\n                    }\n                }\n\n                double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n                if (elapsed > limit_time) return ord;\n            }\n\n            if (!improved) break;\n        }\n\n        return ord;\n    };\n\n    auto improve_reinsert_fast = [&](vector<int> ord, const vector<vector<int>>& edge,\n                                     double limit_time) {\n        auto e = [&](int a, int b) {\n            if (a < 0 || b < 0) return 0;\n            return edge[a][b];\n        };\n\n        for (int round = 0; round < 2; round++) {\n            bool any = false;\n\n            for (int i = 0; i < M; i++) {\n                int x = ord[i];\n\n                int left = (i > 0 ? ord[i - 1] : -1);\n                int right = (i + 1 < M ? ord[i + 1] : -1);\n\n                int remove_delta = -e(left, x) - e(x, right) + e(left, right);\n\n                int best_pos = -1;\n                int best_delta = 0;\n\n                for (int pos = 0; pos <= M - 1; pos++) {\n                    // position in sequence after removing x\n                    if (pos == i || pos == i + 1) continue;\n\n                    int a, b;\n\n                    if (pos == 0) {\n                        a = -1;\n                        b = ord[0];\n                    } else if (pos == M - 1) {\n                        a = ord[M - 1];\n                        b = -1;\n                    } else {\n                        a = ord[pos - 1];\n                        b = ord[pos];\n                    }\n\n                    if (a == x || b == x) continue;\n\n                    int insert_delta = -e(a, b) + e(a, x) + e(x, b);\n                    int delta = remove_delta + insert_delta;\n\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_pos = pos;\n                    }\n                }\n\n                if (best_pos != -1) {\n                    int val = x;\n                    ord.erase(ord.begin() + i);\n\n                    if (best_pos > i) best_pos--;\n\n                    ord.insert(ord.begin() + best_pos, val);\n                    any = true;\n                }\n\n                double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n                if (elapsed > limit_time) return ord;\n            }\n\n            if (!any) break;\n        }\n\n        return ord;\n    };\n\n    vector<vector<int>> candidates;\n\n    auto add_candidate = [&](vector<int> ord) {\n        candidates.push_back(move(ord));\n    };\n\n    for (int st = 0; st < M; st++) {\n        add_candidate(make_append_greedy(st, 0.0, 2.5));\n    }\n\n    // Deterministic insertion candidates with different edge weights.\n    for (int wi = 0; wi < (int)edges.size(); wi += 2) {\n        for (int st = wi; st < M; st += 23) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > 0.45) goto deterministic_insert_done;\n            add_candidate(make_insertion_greedy(st, 0.0, edges[wi]));\n        }\n    }\n\ndeterministic_insert_done:\n\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n        if (elapsed > 0.82) break;\n\n        int type = uniform_int_distribution<int>(0, 2)(rng);\n\n        if (type == 0) {\n            int st = uniform_int_distribution<int>(0, M - 1)(rng);\n            double noise = uniform_real_distribution<double>(50.0, 850.0)(rng);\n            double cw = uniform_real_distribution<double>(0.2, 7.5)(rng);\n            add_candidate(make_append_greedy(st, noise, cw));\n        } else {\n            int st = uniform_int_distribution<int>(0, M - 1)(rng);\n            double noise = uniform_real_distribution<double>(0.0, 800.0)(rng);\n            int wi = uniform_int_distribution<int>(0, (int)edges.size() - 1)(rng);\n            add_candidate(make_insertion_greedy(st, noise, edges[wi]));\n        }\n    }\n\n    sort(candidates.begin(), candidates.end(), [&](const vector<int>& a, const vector<int>& b) {\n        return order_value(a, base_edge) < order_value(b, base_edge);\n    });\n\n    if ((int)candidates.size() > 42) candidates.resize(42);\n\n    vector<vector<int>> pool = candidates;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n        if (elapsed > 1.32) break;\n\n        const auto& edge = edges[i % edges.size()];\n\n        vector<int> ord = candidates[i];\n\n        if (i % 3 == 0) {\n            ord = improve_reinsert_fast(ord, edge, 1.32);\n        } else {\n            ord = improve_swap(ord, edge, 1.32);\n        }\n\n        pool.push_back(move(ord));\n    }\n\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    sort(pool.begin(), pool.end(), [&](const vector<int>& a, const vector<int>& b) {\n        return order_value(a, base_edge) < order_value(b, base_edge);\n    });\n\n    if ((int)pool.size() > 70) pool.resize(70);\n\n    string best_s;\n    int best_exact = INT_MAX;\n\n    for (int i = 0; i < (int)pool.size(); i++) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n        if (elapsed > 1.70 && !best_s.empty()) break;\n\n        string s = build_string(pool[i]);\n        int cost = exact_cost_only(s);\n\n        if (cost < best_exact) {\n            best_exact = cost;\n            best_s = move(s);\n        }\n    }\n\n    if (best_s.empty()) best_s = build_string(pool[0]);\n\n    int L = best_s.size();\n    const int INF = 1e9;\n\n    vector<vector<int>> dp(L);\n    vector<vector<int>> pre(L);\n\n    int first_c = best_s[0] - 'A';\n    dp[0].assign(occ[first_c].size(), INF);\n    pre[0].assign(occ[first_c].size(), -1);\n\n    for (int i = 0; i < (int)occ[first_c].size(); i++) {\n        dp[0][i] = mdist(start, occ[first_c][i]) + 1;\n    }\n\n    for (int p = 1; p < L; p++) {\n        int pc = best_s[p - 1] - 'A';\n        int cc = best_s[p] - 'A';\n\n        dp[p].assign(occ[cc].size(), INF);\n        pre[p].assign(occ[cc].size(), -1);\n\n        for (int i = 0; i < (int)occ[pc].size(); i++) {\n            int base = dp[p - 1][i];\n            if (base >= INF) continue;\n\n            for (int j = 0; j < (int)occ[cc].size(); j++) {\n                int val = base + cd[pc][cc][i][j];\n                if (val < dp[p][j]) {\n                    dp[p][j] = val;\n                    pre[p][j] = i;\n                }\n            }\n        }\n    }\n\n    int last_c = best_s.back() - 'A';\n    int best_last = 0;\n\n    for (int i = 1; i < (int)occ[last_c].size(); i++) {\n        if (dp[L - 1][i] < dp[L - 1][best_last]) {\n            best_last = i;\n        }\n    }\n\n    vector<Pos> ans(L);\n    int idx = best_last;\n\n    for (int p = L - 1; p >= 0; p--) {\n        int ch = best_s[p] - 'A';\n        ans[p] = occ[ch][idx];\n        idx = pre[p][idx];\n    }\n\n    for (auto& p : ans) {\n        cout << p.r << ' ' << p.c << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<unsigned long long> bits;\n};\n\nstruct Constraint {\n    int id;\n    int val;\n};\n\nstatic uint64_t rng_state = 1234567891234567ULL;\n\nstatic inline uint64_t rng64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\nstatic inline int randint(int n) {\n    return (int)(rng64() % n);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n\n    const int V = N * N;\n    const int W = (V + 63) / 64;\n\n    vector<vector<pair<int,int>>> shape(M);\n    vector<int> h(M, 0), w(M, 0);\n\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        shape[k].resize(d);\n        for (int t = 0; t < d; t++) {\n            int i, j;\n            cin >> i >> j;\n            shape[k][t] = {i, j};\n            h[k] = max(h[k], i + 1);\n            w[k] = max(w[k], j + 1);\n        }\n    }\n\n    vector<vector<Placement>> cand(M);\n\n    for (int k = 0; k < M; k++) {\n        for (int si = 0; si + h[k] <= N; si++) {\n            for (int sj = 0; sj + w[k] <= N; sj++) {\n                Placement p;\n                p.bits.assign(W, 0);\n\n                for (auto [di, dj] : shape[k]) {\n                    int ni = si + di;\n                    int nj = sj + dj;\n                    int id = ni * N + nj;\n                    p.cells.push_back(id);\n                    p.bits[id >> 6] |= 1ULL << (id & 63);\n                }\n\n                cand[k].push_back(std::move(p));\n            }\n        }\n    }\n\n    vector<int> known(V, -1);\n    vector<int> positives;\n    vector<Constraint> constraints;\n\n    auto contains_cell = [&](const Placement& p, int id) -> bool {\n        return (p.bits[id >> 6] >> (id & 63)) & 1ULL;\n    };\n\n    auto propagate = [&]() {\n        for (int round = 0; round < 3; round++) {\n            bool changed = false;\n\n            for (auto &con : constraints) {\n                int id = con.id;\n                int target = con.val;\n\n                vector<char> someCover(M, 0), someAvoid(M, 0);\n\n                for (int k = 0; k < M; k++) {\n                    for (auto &p : cand[k]) {\n                        if (contains_cell(p, id)) someCover[k] = 1;\n                        else someAvoid[k] = 1;\n                        if (someCover[k] && someAvoid[k]) break;\n                    }\n                }\n\n                int globalMin = 0;\n                int globalMax = 0;\n\n                for (int k = 0; k < M; k++) {\n                    if (!someAvoid[k]) globalMin++;\n                    if (someCover[k]) globalMax++;\n                }\n\n                if (target < globalMin || target > globalMax) {\n                    continue;\n                }\n\n                for (int k = 0; k < M; k++) {\n                    vector<Placement> nxt;\n                    nxt.reserve(cand[k].size());\n\n                    int otherMin = globalMin - (!someAvoid[k] ? 1 : 0);\n                    int otherMax = globalMax - (someCover[k] ? 1 : 0);\n\n                    for (auto &p : cand[k]) {\n                        bool has = contains_cell(p, id);\n                        int lo = otherMin + (has ? 1 : 0);\n                        int hi = otherMax + (has ? 1 : 0);\n\n                        if (target < lo || target > hi) {\n                            changed = true;\n                        } else {\n                            nxt.push_back(std::move(p));\n                        }\n                    }\n\n                    cand[k].swap(nxt);\n                }\n            }\n\n            if (!changed) break;\n        }\n    };\n\n    auto output_answer = [&](const vector<int>& ans) -> bool {\n        cout << \"a \" << ans.size();\n        for (int id : ans) {\n            cout << ' ' << id / N << ' ' << id % N;\n        }\n        cout << endl;\n        cout.flush();\n\n        int res;\n        cin >> res;\n        return res == 1;\n    };\n\n    auto drill = [&](int id) -> int {\n        cout << \"q 1 \" << id / N << ' ' << id % N << endl;\n        cout.flush();\n\n        int val;\n        cin >> val;\n\n        known[id] = val;\n        constraints.push_back({id, val});\n        if (val > 0) positives.push_back(id);\n\n        propagate();\n\n        return val;\n    };\n\n    auto all_singleton = [&]() -> bool {\n        for (int k = 0; k < M; k++) {\n            if ((int)cand[k].size() != 1) return false;\n        }\n        return true;\n    };\n\n    auto build_union_from_choice = [&](const vector<int>& choice) -> vector<int> {\n        vector<int> mark(V, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (choice[k] < 0 || choice[k] >= (int)cand[k].size()) continue;\n            for (int id : cand[k][choice[k]].cells) mark[id] = 1;\n        }\n\n        for (int id : positives) mark[id] = 1;\n\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            if (mark[id]) ans.push_back(id);\n        }\n\n        return ans;\n    };\n\n    auto build_union_greedy = [&]() -> vector<int> {\n        vector<int> choice(M, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) {\n                choice[k] = -1;\n                continue;\n            }\n\n            int best = 0;\n            int bestScore = INT_MIN;\n\n            for (int idx = 0; idx < (int)cand[k].size(); idx++) {\n                int score = 0;\n\n                for (int id : cand[k][idx].cells) {\n                    if (known[id] > 0) score += 50;\n                    else if (known[id] == 0) score -= 100000;\n                }\n\n                for (int pid : positives) {\n                    int pi = pid / N;\n                    int pj = pid % N;\n                    for (int cid : cand[k][idx].cells) {\n                        int ci = cid / N;\n                        int cj = cid % N;\n                        int dist = abs(pi - ci) + abs(pj - cj);\n                        if (dist <= 2) score += 3 - dist;\n                    }\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = idx;\n                }\n            }\n\n            choice[k] = best;\n        }\n\n        return build_union_from_choice(choice);\n    };\n\n    auto eval_choice_error = [&](const vector<int>& ch) -> int {\n        int err = 0;\n\n        for (int ci = 0; ci < (int)constraints.size(); ci++) {\n            int sum = 0;\n            int id = constraints[ci].id;\n\n            for (int k = 0; k < M; k++) {\n                if (ch[k] >= 0 && contains_cell(cand[k][ch[k]], id)) sum++;\n            }\n\n            err += abs(sum - constraints[ci].val);\n        }\n\n        return err;\n    };\n\n    auto sample_feasible_consensus_answer = [&]() -> vector<int> {\n        long long totalCand = 0;\n        int maxCand = 0;\n        for (int k = 0; k < M; k++) {\n            totalCand += cand[k].size();\n            maxCand = max(maxCand, (int)cand[k].size());\n            if (cand[k].empty()) return {};\n        }\n\n        int trials;\n        if (totalCand <= 80) trials = 500;\n        else if (totalCand <= 150) trials = 350;\n        else if (totalCand <= 260) trials = 220;\n        else trials = 0;\n\n        if (trials == 0) return {};\n\n        vector<vector<int>> feasibleChoices;\n        feasibleChoices.reserve(32);\n\n        for (int t = 0; t < trials; t++) {\n            vector<int> ch(M);\n\n            for (int k = 0; k < M; k++) {\n                int sz = cand[k].size();\n\n                /*\n                   Biased random: among a few random candidates, choose one\n                   locally agreeing with known cells.\n                */\n                int best = randint(sz);\n                int bestScore = INT_MIN;\n\n                int samples = min(sz, 5);\n                for (int s = 0; s < samples; s++) {\n                    int idx = randint(sz);\n                    int sc = 0;\n\n                    for (int id : cand[k][idx].cells) {\n                        if (known[id] > 0) sc += 5;\n                        else if (known[id] == 0) sc -= 50;\n                    }\n\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = idx;\n                    }\n                }\n\n                ch[k] = best;\n            }\n\n            if (eval_choice_error(ch) == 0) {\n                feasibleChoices.push_back(ch);\n                if ((int)feasibleChoices.size() >= 24) break;\n            }\n        }\n\n        if (feasibleChoices.empty()) return {};\n\n        /*\n           Check union stability among feasible sampled assignments.\n        */\n        vector<int> freq(V, 0);\n        vector<int> firstUnionMark(V, 0);\n\n        for (int s = 0; s < (int)feasibleChoices.size(); s++) {\n            vector<int> mark(V, 0);\n\n            for (int k = 0; k < M; k++) {\n                for (int id : cand[k][feasibleChoices[s][k]].cells) {\n                    mark[id] = 1;\n                }\n            }\n            for (int id : positives) mark[id] = 1;\n\n            for (int id = 0; id < V; id++) {\n                if (mark[id]) freq[id]++;\n            }\n\n            if (s == 0) firstUnionMark = mark;\n        }\n\n        int uncertainCells = 0;\n        for (int id = 0; id < V; id++) {\n            if (known[id] != -1) continue;\n            if (freq[id] > 0 && freq[id] < (int)feasibleChoices.size()) {\n                uncertainCells++;\n            }\n        }\n\n        /*\n           If sampled feasible assignments disagree too much, don't guess.\n        */\n        int allowedUncertain = max(6, V / 25);\n        if (uncertainCells > allowedUncertain && (int)feasibleChoices.size() >= 5) {\n            return {};\n        }\n\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            if (firstUnionMark[id]) ans.push_back(id);\n        }\n\n        return ans;\n    };\n\n    auto choose_next_cell = [&]() -> int {\n        vector<double> cover(V, 0.0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n            double inv = 1.0 / cand[k].size();\n\n            for (auto &p : cand[k]) {\n                for (int id : p.cells) {\n                    cover[id] += inv;\n                }\n            }\n        }\n\n        int best = -1;\n        double bestScore = -1e100;\n\n        for (int id = 0; id < V; id++) {\n            if (known[id] != -1) continue;\n\n            double lambda = cover[id];\n            double pOil = 1.0 - exp(-lambda);\n            double uncertain = pOil * (1.0 - pOil);\n\n            double score = 12.0 * uncertain + 0.7 * pOil;\n\n            int i = id / N;\n            int j = id % N;\n\n            for (int pid : positives) {\n                int pi = pid / N;\n                int pj = pid % N;\n                int dist = abs(i - pi) + abs(j - pj);\n                if (dist <= 3) score += 0.25 * (4 - dist);\n            }\n\n            int zeroNear = 0;\n            for (int di = -1; di <= 1; di++) {\n                for (int dj = -1; dj <= 1; dj++) {\n                    int ni = i + di;\n                    int nj = j + dj;\n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                    if (known[ni * N + nj] == 0) zeroNear++;\n                }\n            }\n\n            score -= 0.03 * zeroNear;\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id = 0; id < V; id++) {\n                if (known[id] == -1) return id;\n            }\n        }\n\n        return best;\n    };\n\n    int op_count = 0;\n    const int op_limit = 2 * N * N;\n    int last_answer_op = -100000;\n\n    /*\n       Initial exact probing.\n    */\n    int step = max(2, N / 5);\n    vector<int> initial;\n\n    for (int i = step / 2; i < N; i += step) {\n        for (int j = step / 2; j < N; j += step) {\n            initial.push_back(i * N + j);\n        }\n    }\n\n    for (int id : initial) {\n        if (op_count + 1 >= op_limit) break;\n        if (known[id] == -1) {\n            drill(id);\n            op_count++;\n        }\n    }\n\n    while (op_count + 1 < op_limit) {\n        if (all_singleton()) {\n            vector<int> choice(M, 0);\n            vector<int> ans = build_union_from_choice(choice);\n            op_count++;\n            if (output_answer(ans)) return 0;\n            last_answer_op = op_count;\n        }\n\n        long long totalCand = 0;\n        int maxCand = 0;\n\n        for (int k = 0; k < M; k++) {\n            totalCand += cand[k].size();\n            maxCand = max(maxCand, (int)cand[k].size());\n        }\n\n        bool enoughNewDrills = (op_count - last_answer_op >= 4);\n\n        if (enoughNewDrills &&\n            ((op_count >= 14 && totalCand <= 80) ||\n             (op_count >= 28 && totalCand <= 160) ||\n             (op_count >= 45 && totalCand <= 260))) {\n            vector<int> ans = sample_feasible_consensus_answer();\n            if (!ans.empty()) {\n                op_count++;\n                if (output_answer(ans)) return 0;\n                last_answer_op = op_count;\n            }\n        }\n\n        if (enoughNewDrills &&\n            ((op_count >= 18 && totalCand <= 70) ||\n             (op_count >= 35 && totalCand <= 140))) {\n            vector<int> ans = build_union_greedy();\n            op_count++;\n            if (output_answer(ans)) return 0;\n            last_answer_op = op_count;\n        }\n\n        int id = choose_next_cell();\n        if (id < 0) break;\n\n        drill(id);\n        op_count++;\n    }\n\n    /*\n       Exact fallback.\n    */\n    for (int id = 0; id < V && op_count + 1 < op_limit; id++) {\n        if (known[id] == -1) {\n            drill(id);\n            op_count++;\n        }\n    }\n\n    vector<int> final_ans;\n    for (int id = 0; id < V; id++) {\n        if (known[id] > 0) final_ans.push_back(id);\n    }\n\n    op_count++;\n    output_answer(final_ans);\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n};\n\nint W, D, N;\nvector<vector<int>> A;\nvector<vector<int>> wid;\n\nlong long shortage_cost(int d, int k, int w) {\n    long long area = 1LL * W * w;\n    if (A[d][k] > area) return 100LL * (A[d][k] - area);\n    return 0;\n}\n\nlong long shortage_cost_day(int d) {\n    long long c = 0;\n    for (int k = 0; k < N; k++) c += shortage_cost(d, k, wid[d][k]);\n    return c;\n}\n\nvector<int> boundaries_from_widths(const vector<int>& w) {\n    vector<int> b;\n    int x = 0;\n    for (int k = 0; k + 1 < N; k++) {\n        x += w[k];\n        b.push_back(x);\n    }\n    return b;\n}\n\nlong long transition_cost_widths(const vector<int>& a, const vector<int>& b) {\n    vector<int> ba = boundaries_from_widths(a);\n    vector<int> bb = boundaries_from_widths(b);\n\n    int i = 0, j = 0, common = 0;\n    while (i < (int)ba.size() && j < (int)bb.size()) {\n        if (ba[i] == bb[j]) {\n            common++;\n            i++;\n            j++;\n        } else if (ba[i] < bb[j]) {\n            i++;\n        } else {\n            j++;\n        }\n    }\n\n    int diff = (int)ba.size() + (int)bb.size() - 2 * common;\n    return 1LL * W * diff;\n}\n\nlong long transition_cost_pair(int d) {\n    if (d <= 0) return 0;\n    return transition_cost_widths(wid[d - 1], wid[d]);\n}\n\nlong long total_cost() {\n    long long c = 0;\n    for (int d = 0; d < D; d++) c += shortage_cost_day(d);\n    for (int d = 1; d < D; d++) c += transition_cost_pair(d);\n    return c;\n}\n\nlong long local_part_cost(int d) {\n    long long c = shortage_cost_day(d);\n    if (d >= 1) c += transition_cost_pair(d);\n    if (d + 1 < D) c += transition_cost_pair(d + 1);\n    return c;\n}\n\nvoid normalize_day_initial(int d) {\n    wid[d].assign(N, 1);\n\n    vector<int> req(N);\n    long long sum = 0;\n    for (int k = 0; k < N; k++) {\n        req[k] = max(1, (A[d][k] + W - 1) / W);\n        wid[d][k] = req[k];\n        sum += wid[d][k];\n    }\n\n    if (sum < W) {\n        int rem = W - (int)sum;\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int x, int y) {\n            return A[d][x] > A[d][y];\n        });\n        int p = 0;\n        while (rem--) {\n            wid[d][ord[p]]++;\n            p++;\n            if (p == N) p = 0;\n        }\n    } else if (sum > W) {\n        int over = (int)(sum - W);\n        while (over > 0) {\n            int bestK = -1;\n            long long bestDamage = LLONG_MAX;\n\n            for (int k = 0; k < N; k++) {\n                if (wid[d][k] <= 1) continue;\n                long long before = shortage_cost(d, k, wid[d][k]);\n                long long after = shortage_cost(d, k, wid[d][k] - 1);\n                long long dmg = after - before;\n\n                // Tie-break: reduce larger widths first.\n                long long key = dmg * 10000 - wid[d][k];\n                if (key < bestDamage) {\n                    bestDamage = key;\n                    bestK = k;\n                }\n            }\n\n            if (bestK < 0) break;\n            wid[d][bestK]--;\n            over--;\n        }\n    }\n}\n\nvoid initialize_solution() {\n    wid.assign(D, vector<int>(N, 1));\n\n    // Candidate 1: original strong independent per-day layout.\n    vector<vector<int>> bestWid(D, vector<int>(N));\n    for (int d = 0; d < D; d++) normalize_day_initial(d);\n    bestWid = wid;\n    long long bestScore = total_cost();\n\n    // Candidate 2: original global fixed DP layout.\n    vector<vector<long long>> cost(N, vector<long long>(W + 1, 0));\n    for (int k = 0; k < N; k++) {\n        for (int w = 1; w <= W; w++) {\n            long long c = 0;\n            for (int d = 0; d < D; d++) c += shortage_cost(d, k, w);\n            cost[k][w] = c;\n        }\n    }\n\n    const long long INF = (1LL << 60);\n    vector<vector<long long>> dp(N + 1, vector<long long>(W + 1, INF));\n    vector<vector<int>> pre(N + 1, vector<int>(W + 1, -1));\n    dp[0][0] = 0;\n\n    for (int k = 0; k < N; k++) {\n        for (int used = 0; used <= W; used++) {\n            if (dp[k][used] >= INF) continue;\n            int remain = N - k - 1;\n            for (int ww = 1; used + ww + remain <= W; ww++) {\n                long long nv = dp[k][used] + cost[k][ww];\n                if (nv < dp[k + 1][used + ww]) {\n                    dp[k + 1][used + ww] = nv;\n                    pre[k + 1][used + ww] = ww;\n                }\n            }\n        }\n    }\n\n    int bu = N;\n    for (int u = N; u <= W; u++) {\n        if (dp[N][u] < dp[N][bu]) bu = u;\n    }\n\n    vector<int> fixed(N);\n    int cur = bu;\n    for (int k = N; k >= 1; k--) {\n        fixed[k - 1] = pre[k][cur];\n        cur -= fixed[k - 1];\n    }\n\n    int used = accumulate(fixed.begin(), fixed.end(), 0);\n    while (used < W) {\n        int bestK = 0;\n        long long bestGain = LLONG_MIN;\n        for (int k = 0; k < N; k++) {\n            long long gain = cost[k][fixed[k]] - cost[k][fixed[k] + 1];\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestK = k;\n            }\n        }\n        fixed[bestK]++;\n        used++;\n    }\n\n    wid.assign(D, fixed);\n    long long sc2 = total_cost();\n\n    if (sc2 < bestScore) {\n        bestScore = sc2;\n        bestWid = wid;\n    }\n\n    wid = bestWid;\n}\n\n// Try replacing an entire day's layout by a neighboring day's layout.\n// Accepted only by exact local cost.\nvoid copy_day_refinement(const Timer& timer) {\n    bool improved = true;\n    int pass = 0;\n\n    while (improved && pass < 10 && timer.elapsed() < 2.15) {\n        improved = false;\n        pass++;\n\n        for (int d = 0; d < D && timer.elapsed() < 2.15; d++) {\n            long long base = local_part_cost(d);\n            vector<int> old = wid[d];\n\n            vector<int> best = old;\n            long long bestCost = base;\n\n            if (d > 0) {\n                wid[d] = wid[d - 1];\n                long long c = local_part_cost(d);\n                if (c < bestCost) {\n                    bestCost = c;\n                    best = wid[d];\n                }\n            }\n\n            if (d + 1 < D) {\n                wid[d] = wid[d + 1];\n                long long c = local_part_cost(d);\n                if (c < bestCost) {\n                    bestCost = c;\n                    best = wid[d];\n                }\n            }\n\n            wid[d] = best;\n            if (bestCost < base) improved = true;\n        }\n    }\n}\n\nvoid deterministic_local_search(const Timer& timer) {\n    bool improved = true;\n    int pass = 0;\n\n    while (improved && pass < 30 && timer.elapsed() < 2.50) {\n        improved = false;\n        pass++;\n\n        for (int d = 0; d < D && timer.elapsed() < 2.50; d++) {\n            bool dayImp = true;\n            int inner = 0;\n\n            while (dayImp && inner < 200 && timer.elapsed() < 2.50) {\n                dayImp = false;\n                inner++;\n\n                long long base = local_part_cost(d);\n                int bestFrom = -1, bestTo = -1;\n                long long bestDelta = 0;\n\n                for (int from = 0; from < N; from++) {\n                    if (wid[d][from] <= 1) continue;\n\n                    for (int to = 0; to < N; to++) {\n                        if (from == to) continue;\n\n                        wid[d][from]--;\n                        wid[d][to]++;\n                        long long nc = local_part_cost(d);\n                        wid[d][from]++;\n                        wid[d][to]--;\n\n                        long long delta = nc - base;\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestFrom = from;\n                            bestTo = to;\n                        }\n                    }\n                }\n\n                if (bestDelta < 0) {\n                    wid[d][bestFrom]--;\n                    wid[d][bestTo]++;\n                    improved = true;\n                    dayImp = true;\n                }\n            }\n        }\n    }\n}\n\nvoid random_local_search(const Timer& timer) {\n    XorShift rng;\n    double TL = 2.86;\n\n    while (timer.elapsed() < TL) {\n        int d = rng.randint(0, D - 1);\n        int from = rng.randint(0, N - 1);\n        int to = rng.randint(0, N - 1);\n        if (from == to || wid[d][from] <= 1) continue;\n\n        int maxMove = min(wid[d][from] - 1, 10);\n        if (maxMove <= 0) continue;\n\n        int mv = 1;\n        if ((rng.next() & 7) == 0) mv = rng.randint(1, maxMove);\n\n        long long base = local_part_cost(d);\n        wid[d][from] -= mv;\n        wid[d][to] += mv;\n        long long nc = local_part_cost(d);\n\n        if (nc <= base) {\n            // accept\n        } else {\n            wid[d][from] += mv;\n            wid[d][to] -= mv;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> W >> D >> N;\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    initialize_solution();\n\n    copy_day_refinement(timer);\n    deterministic_local_search(timer);\n    random_local_search(timer);\n\n    // Output vertical full-height strips.\n    for (int d = 0; d < D; d++) {\n        int sum = accumulate(wid[d].begin(), wid[d].end(), 0);\n\n        // Safety repair, should not be needed.\n        while (sum < W) {\n            wid[d][N - 1]++;\n            sum++;\n        }\n        while (sum > W) {\n            for (int k = N - 1; k >= 0 && sum > W; k--) {\n                if (wid[d][k] > 1) {\n                    wid[d][k]--;\n                    sum--;\n                }\n            }\n        }\n\n        int x = 0;\n        for (int k = 0; k < N; k++) {\n            int x2 = x + wid[d][k];\n            if (k == N - 1) x2 = W;\n\n            cout << 0 << ' ' << x << ' ' << W << ' ' << x2 << '\\n';\n            x = x2;\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr long long MOD = 998244353LL;\nstatic constexpr int N = 9;\nstatic constexpr int M = 20;\nstatic constexpr int K = 81;\nstatic constexpr int POS = 7;\nstatic constexpr int ALL = M * POS * POS;\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct Move {\n    long long gain;\n    Op op;\n};\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n    inline double uniform() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nlong long stamp[M][3][3];\nOp all_ops[ALL];\nint all_cnt = 0;\n\narray<array<long long, N>, N> initial_board;\nlong long initial_score = 0;\n\nstruct Result {\n    long long score;\n    vector<Op> ops;\n};\n\ninline long long gain_of(const array<array<long long, N>, N>& b, const Op& op) {\n    const int m = op.m;\n    const int p = op.p;\n    const int q = op.q;\n\n    long long gain = 0;\n    long long oldv, nv;\n\n    oldv = b[p][q];\n    nv = oldv + stamp[m][0][0];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p][q + 1];\n    nv = oldv + stamp[m][0][1];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p][q + 2];\n    nv = oldv + stamp[m][0][2];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 1][q];\n    nv = oldv + stamp[m][1][0];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 1][q + 1];\n    nv = oldv + stamp[m][1][1];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 1][q + 2];\n    nv = oldv + stamp[m][1][2];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 2][q];\n    nv = oldv + stamp[m][2][0];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 2][q + 1];\n    nv = oldv + stamp[m][2][1];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 2][q + 2];\n    nv = oldv + stamp[m][2][2];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    return gain;\n}\n\ninline void apply_op(array<array<long long, N>, N>& b, const Op& op) {\n    const int m = op.m;\n    const int p = op.p;\n    const int q = op.q;\n\n    long long &v00 = b[p][q];\n    v00 += stamp[m][0][0];\n    if (v00 >= MOD) v00 -= MOD;\n\n    long long &v01 = b[p][q + 1];\n    v01 += stamp[m][0][1];\n    if (v01 >= MOD) v01 -= MOD;\n\n    long long &v02 = b[p][q + 2];\n    v02 += stamp[m][0][2];\n    if (v02 >= MOD) v02 -= MOD;\n\n    long long &v10 = b[p + 1][q];\n    v10 += stamp[m][1][0];\n    if (v10 >= MOD) v10 -= MOD;\n\n    long long &v11 = b[p + 1][q + 1];\n    v11 += stamp[m][1][1];\n    if (v11 >= MOD) v11 -= MOD;\n\n    long long &v12 = b[p + 1][q + 2];\n    v12 += stamp[m][1][2];\n    if (v12 >= MOD) v12 -= MOD;\n\n    long long &v20 = b[p + 2][q];\n    v20 += stamp[m][2][0];\n    if (v20 >= MOD) v20 -= MOD;\n\n    long long &v21 = b[p + 2][q + 1];\n    v21 += stamp[m][2][1];\n    if (v21 >= MOD) v21 -= MOD;\n\n    long long &v22 = b[p + 2][q + 2];\n    v22 += stamp[m][2][2];\n    if (v22 >= MOD) v22 -= MOD;\n}\n\ninline void insert_top(vector<Move>& top, const Move& mv, int TOP) {\n    if (mv.gain <= 0) return;\n\n    if ((int)top.size() < TOP) {\n        top.push_back(mv);\n        int i = (int)top.size() - 1;\n        while (i > 0 && top[i].gain > top[i - 1].gain) {\n            swap(top[i], top[i - 1]);\n            i--;\n        }\n    } else if (mv.gain > top.back().gain) {\n        top.back() = mv;\n        int i = TOP - 1;\n        while (i > 0 && top[i].gain > top[i - 1].gain) {\n            swap(top[i], top[i - 1]);\n            i--;\n        }\n    }\n}\n\nlong long eval_ops(const vector<Op>& ops) {\n    auto b = initial_board;\n    long long score = initial_score;\n\n    for (const Op& op : ops) {\n        long long g = gain_of(b, op);\n        apply_op(b, op);\n        score += g;\n    }\n    return score;\n}\n\nResult construct_original_like(XorShift& rng, bool deterministic) {\n    auto b = initial_board;\n\n    Result res;\n    res.score = initial_score;\n    res.ops.reserve(K);\n\n    constexpr int TOP = 12;\n\n    for (int step = 0; step < K; step++) {\n        vector<Move> top;\n        top.reserve(TOP);\n\n        for (int i = 0; i < all_cnt; i++) {\n            long long g = gain_of(b, all_ops[i]);\n            insert_top(top, {g, all_ops[i]}, TOP);\n        }\n\n        if (top.empty()) break;\n\n        int idx = 0;\n\n        if (!deterministic) {\n            double greedy_prob = 0.70 + 0.25 * (double(step) / K);\n            if (rng.uniform() >= greedy_prob) {\n                idx = rng.randint(0, (int)top.size() - 1);\n            }\n        }\n\n        Move chosen = top[idx];\n        apply_op(b, chosen.op);\n        res.score += chosen.gain;\n        res.ops.push_back(chosen.op);\n    }\n\n    return res;\n}\n\nResult construct_variant(XorShift& rng, int mode) {\n    auto b = initial_board;\n\n    Result res;\n    res.score = initial_score;\n    res.ops.reserve(K);\n\n    int TOP = (mode == 0 ? 8 : mode == 1 ? 16 : 20);\n\n    for (int step = 0; step < K; step++) {\n        vector<Move> top;\n        top.reserve(TOP);\n\n        for (int i = 0; i < all_cnt; i++) {\n            long long g = gain_of(b, all_ops[i]);\n            insert_top(top, {g, all_ops[i]}, TOP);\n        }\n\n        if (top.empty()) break;\n\n        int idx = 0;\n\n        double t = double(step) / K;\n        double greedy_prob;\n\n        if (mode == 0) greedy_prob = 0.80 + 0.16 * t;\n        else if (mode == 1) greedy_prob = 0.62 + 0.30 * t;\n        else greedy_prob = 0.55 + 0.35 * t;\n\n        if (rng.uniform() >= greedy_prob) {\n            double r = rng.uniform();\n            if (mode != 2) r *= r;\n            int lim = (int)top.size();\n            idx = int(r * lim);\n            if (idx >= lim) idx = lim - 1;\n        }\n\n        Move chosen = top[idx];\n        apply_op(b, chosen.op);\n        res.score += chosen.gain;\n        res.ops.push_back(chosen.op);\n    }\n\n    return res;\n}\n\nint biased_index(int L, XorShift& rng) {\n    if (L <= 1) return 0;\n\n    if (rng.randint(0, 99) < 60) {\n        return rng.randint(0, L - 1);\n    } else {\n        double r = rng.uniform();\n        int idx = int(r * r * L);\n        if (idx >= L) idx = L - 1;\n        return idx;\n    }\n}\n\nbool improve_replacement(Result& best, XorShift& rng) {\n    int L = (int)best.ops.size();\n    if (L == 0) return false;\n\n    int idx = biased_index(L, rng);\n\n    auto b = initial_board;\n    for (int i = 0; i < idx; i++) {\n        apply_op(b, best.ops[i]);\n    }\n\n    constexpr int TOP = 10;\n    vector<Move> top;\n    top.reserve(TOP);\n\n    for (int i = 0; i < all_cnt; i++) {\n        long long g = gain_of(b, all_ops[i]);\n        insert_top(top, {g, all_ops[i]}, TOP);\n    }\n\n    vector<Op> candidates;\n    candidates.reserve(TOP + 5);\n\n    for (auto &mv : top) candidates.push_back(mv.op);\n\n    for (int t = 0; t < 5; t++) {\n        candidates.push_back(all_ops[rng.randint(0, all_cnt - 1)]);\n    }\n\n    for (const Op& op : candidates) {\n        if (op.m == best.ops[idx].m && op.p == best.ops[idx].p && op.q == best.ops[idx].q) {\n            continue;\n        }\n\n        vector<Op> cand = best.ops;\n        cand[idx] = op;\n\n        long long sc = eval_ops(cand);\n        if (sc > best.score) {\n            best.score = sc;\n            best.ops.swap(cand);\n            return true;\n        }\n    }\n\n    return false;\n}\n\nbool improve_swap(Result& best, XorShift& rng) {\n    int L = (int)best.ops.size();\n    if (L < 2) return false;\n\n    int i = rng.randint(0, L - 2);\n    int j;\n\n    if (rng.randint(0, 99) < 75) {\n        j = i + 1;\n    } else {\n        j = rng.randint(0, L - 1);\n        if (i == j) return false;\n    }\n\n    vector<Op> cand = best.ops;\n    swap(cand[i], cand[j]);\n\n    long long sc = eval_ops(cand);\n    if (sc > best.score) {\n        best.score = sc;\n        best.ops.swap(cand);\n        return true;\n    }\n\n    return false;\n}\n\nbool improve_truncate(Result& best) {\n    int L = (int)best.ops.size();\n    if (L <= 1) return false;\n\n    auto b = initial_board;\n    long long score = initial_score;\n\n    long long best_pref_score = initial_score;\n    int best_len = 0;\n\n    for (int i = 0; i < L; i++) {\n        long long g = gain_of(b, best.ops[i]);\n        apply_op(b, best.ops[i]);\n        score += g;\n\n        if (score > best_pref_score) {\n            best_pref_score = score;\n            best_len = i + 1;\n        }\n    }\n\n    if (best_pref_score > best.score) {\n        best.score = best_pref_score;\n        best.ops.resize(best_len);\n        return true;\n    }\n\n    return false;\n}\n\nbool improve_suffix_regreedy(Result& best, XorShift& rng) {\n    int L = (int)best.ops.size();\n\n    if (L <= 3) return false;\n\n    int cut;\n\n    // Mostly repair later suffix, sometimes from earlier point.\n    if (rng.randint(0, 99) < 70) {\n        cut = rng.randint(L / 3, L - 1);\n    } else {\n        cut = rng.randint(0, L - 1);\n    }\n\n    vector<Op> cand;\n    cand.reserve(K);\n\n    auto b = initial_board;\n    long long score = initial_score;\n\n    for (int i = 0; i < cut; i++) {\n        cand.push_back(best.ops[i]);\n        long long g = gain_of(b, best.ops[i]);\n        apply_op(b, best.ops[i]);\n        score += g;\n    }\n\n    for (int step = cut; step < K; step++) {\n        constexpr int TOP = 12;\n        vector<Move> top;\n        top.reserve(TOP);\n\n        for (int i = 0; i < all_cnt; i++) {\n            long long g = gain_of(b, all_ops[i]);\n            insert_top(top, {g, all_ops[i]}, TOP);\n        }\n\n        if (top.empty()) break;\n\n        int idx = 0;\n\n        double greedy_prob = 0.68 + 0.27 * (double(step) / K);\n        if (rng.uniform() >= greedy_prob) {\n            idx = rng.randint(0, (int)top.size() - 1);\n        }\n\n        Move chosen = top[idx];\n        cand.push_back(chosen.op);\n        apply_op(b, chosen.op);\n        score += chosen.gain;\n    }\n\n    if (score > best.score) {\n        best.score = score;\n        best.ops.swap(cand);\n        return true;\n    }\n\n    return false;\n}\n\nbool improve_two_replacement(Result& best, XorShift& rng) {\n    int L = (int)best.ops.size();\n    if (L < 2) return false;\n\n    vector<Op> cand = best.ops;\n\n    int i = biased_index(L, rng);\n    int j;\n\n    if (rng.randint(0, 99) < 70) {\n        int d = rng.randint(1, 4);\n        j = min(L - 1, i + d);\n        if (j == i) j = max(0, i - d);\n    } else {\n        j = rng.randint(0, L - 1);\n    }\n\n    if (i == j) return false;\n\n    cand[i] = all_ops[rng.randint(0, all_cnt - 1)];\n    cand[j] = all_ops[rng.randint(0, all_cnt - 1)];\n\n    long long sc = eval_ops(cand);\n    if (sc > best.score) {\n        best.score = sc;\n        best.ops.swap(cand);\n        return true;\n    }\n\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, minput, kinput;\n    cin >> n >> minput >> kinput;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> initial_board[i][j];\n            initial_score += initial_board[i][j];\n        }\n    }\n\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamp[m][i][j];\n            }\n        }\n    }\n\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p < POS; p++) {\n            for (int q = 0; q < POS; q++) {\n                all_ops[all_cnt++] = {m, p, q};\n            }\n        }\n    }\n\n    auto start = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.88;\n\n    XorShift rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    Result best;\n    best.score = initial_score;\n\n    {\n        Result r = construct_original_like(rng, true);\n        if (r.score > best.score) best = std::move(r);\n    }\n\n    int trial = 0;\n\n    // Main randomized greedy phase.\n    while (true) {\n        double elapsed = chrono::duration<double>(\n            chrono::steady_clock::now() - start\n        ).count();\n\n        if (elapsed > 1.35) break;\n\n        Result r;\n\n        int x = trial % 14;\n        if (x < 10) {\n            r = construct_original_like(rng, false);\n        } else {\n            r = construct_variant(rng, x % 3);\n        }\n\n        if (r.score > best.score) {\n            best = std::move(r);\n        }\n\n        trial++;\n    }\n\n    // Safe local improvement phase.\n    while (true) {\n        double elapsed = chrono::duration<double>(\n            chrono::steady_clock::now() - start\n        ).count();\n\n        if (elapsed > TIME_LIMIT) break;\n\n        int r = rng.randint(0, 99);\n\n        if (r < 58) {\n            improve_replacement(best, rng);\n        } else if (r < 73) {\n            improve_suffix_regreedy(best, rng);\n        } else if (r < 88) {\n            improve_swap(best, rng);\n        } else if (r < 97) {\n            improve_two_replacement(best, rng);\n        } else {\n            improve_truncate(best);\n        }\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const Op& op : best.ops) {\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Params {\n    int nowW;\n    int laterW;\n    int rowPenaltyW;\n    int colPenaltyW;\n    int recvPenalty;\n};\n\nstruct Solver {\n    static constexpr int N = 5;\n\n    const vector<vector<int>>& A;\n    Params param;\n\n    int ptr[N];\n    int grid[N][N];\n    pair<int,int> pos[N * N];\n\n    string s0;\n\n    int cr = 0, cc = 0;\n    bool holding = false;\n    int hold = -1;\n\n    Solver(const vector<vector<int>>& A_, Params p) : A(A_), param(p) {\n        for (int i = 0; i < N; i++) ptr[i] = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) grid[i][j] = -1;\n        }\n        for (int x = 0; x < N * N; x++) pos[x] = {-1, -1};\n\n        for (int i = 0; i < N; i++) {\n            int x = A[i][0];\n            grid[i][0] = x;\n            pos[x] = {i, 0};\n            ptr[i] = 1;\n        }\n\n        s0.reserve(1000);\n    }\n\n    inline int dist(int r1, int c1, int r2, int c2) const {\n        return abs(r1 - r2) + abs(c1 - c2);\n    }\n\n    inline void do_receive() {\n        for (int i = 0; i < N; i++) {\n            if (ptr[i] < N && grid[i][0] == -1) {\n                if (holding && cr == i && cc == 0) continue;\n\n                int x = A[i][ptr[i]++];\n                grid[i][0] = x;\n                pos[x] = {i, 0};\n            }\n        }\n    }\n\n    inline void append_large(char c) {\n        s0.push_back(c);\n\n        if (c == 'U') cr--;\n        else if (c == 'D') cr++;\n        else if (c == 'L') cc--;\n        else if (c == 'R') cc++;\n    }\n\n    inline void move_one(char c) {\n        do_receive();\n        append_large(c);\n    }\n\n    void move_to(int tr, int tc) {\n        while (cr < tr) move_one('D');\n        while (cr > tr) move_one('U');\n        while (cc < tc) move_one('R');\n        while (cc > tc) move_one('L');\n    }\n\n    inline void pick() {\n        do_receive();\n\n        int x = grid[cr][cc];\n\n        if (x == -1) {\n            append_large('.');\n            return;\n        }\n\n        append_large('P');\n\n        holding = true;\n        hold = x;\n        grid[cr][cc] = -1;\n        pos[x] = {-1, -1};\n    }\n\n    inline void release() {\n        do_receive();\n\n        append_large('Q');\n\n        holding = false;\n\n        if (cc == N - 1) {\n            pos[hold] = {-2, -2};\n        } else {\n            grid[cr][cc] = hold;\n            pos[hold] = {cr, cc};\n        }\n\n        hold = -1;\n    }\n\n    inline bool target_on_grid(int target) const {\n        return pos[target].first >= 0;\n    }\n\n    inline bool usable_storage(int r, int c) const {\n        if (c == N - 1) return false;\n        if (grid[r][c] != -1) return false;\n        if (c == 0 && ptr[r] < N) return false;\n        return true;\n    }\n\n    pair<int,int> find_storage_for(int x) const {\n        int dest = x / N;\n\n        pair<int,int> best = {-1, -1};\n        int bestScore = INT_MAX;\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N - 1; c++) {\n                if (!usable_storage(r, c)) continue;\n\n                int nowCost = dist(cr, cc, r, c);\n                int laterCost = dist(r, c, dest, N - 1);\n                int rowPenalty = abs(r - dest);\n                int colPenalty = 3 - c;\n\n                int score = 0;\n                score += param.nowW * nowCost;\n                score += param.laterW * laterCost;\n                score += param.rowPenaltyW * rowPenalty;\n                score += param.colPenaltyW * colPenalty;\n                if (c == 0) score += param.recvPenalty;\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = {r, c};\n                }\n            }\n        }\n\n        return best;\n    }\n\n    void store_held() {\n        auto p = find_storage_for(hold);\n\n        if (p.first == -1) {\n            int dest = hold / N;\n            move_to(dest, N - 1);\n            release();\n            return;\n        }\n\n        move_to(p.first, p.second);\n        release();\n    }\n\n    bool row_hides_target(int r, int target) const {\n        for (int k = ptr[r]; k < N; k++) {\n            if (A[r][k] == target) return true;\n        }\n        return false;\n    }\n\n    int choose_revealing_row(int target) const {\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1) continue;\n            if (row_hides_target(r, target)) return r;\n        }\n\n        int best = -1;\n        int bestDist = INT_MAX;\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] != -1) {\n                int d = dist(cr, cc, r, 0);\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = r;\n                }\n            }\n        }\n\n        return best;\n    }\n\n    void deliver_held_to_correct_gate() {\n        int dest = hold / N;\n        move_to(dest, N - 1);\n        release();\n    }\n\n    void move_to_and_pick(pair<int,int> p) {\n        move_to(p.first, p.second);\n        pick();\n    }\n\n    void solve_exact_order() {\n        for (int target = 0; target < N * N; target++) {\n            while (true) {\n                if (target_on_grid(target)) {\n                    move_to_and_pick(pos[target]);\n                    deliver_held_to_correct_gate();\n                    break;\n                }\n\n                int row = choose_revealing_row(target);\n\n                if (row == -1) {\n                    move_one('.');\n                    continue;\n                }\n\n                move_to(row, 0);\n                pick();\n\n                if (hold == target) {\n                    deliver_held_to_correct_gate();\n                    break;\n                } else {\n                    store_held();\n                }\n            }\n        }\n    }\n\n    string run() {\n        solve_exact_order();\n        return s0;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    vector<Params> params = {\n        {3, 4, 4, 1, 8},\n        {2, 5, 5, 1, 10},\n        {5, 3, 3, 1, 8},\n        {3, 4, 8, 1, 10},\n        {3, 4, 4, 4, 10},\n        {4, 4, 4, 2, 8},\n        {2, 4, 6, 2, 12},\n        {4, 5, 3, 1, 8},\n        {3, 5, 6, 2, 12},\n        {5, 5, 5, 1, 10},\n\n        // Extra lightweight parameter variants.\n        {1, 6, 8, 1, 12},\n        {6, 2, 2, 1, 6},\n        {2, 6, 3, 4, 10},\n        {4, 3, 7, 2, 10},\n        {3, 6, 10, 1, 12},\n        {6, 4, 4, 3, 8},\n        {1, 5, 10, 1, 15},\n        {7, 2, 1, 1, 5},\n        {2, 7, 8, 2, 12},\n        {4, 6, 4, 4, 10},\n        {5, 4, 8, 2, 8},\n        {3, 7, 12, 1, 15},\n    };\n\n    string best;\n    int bestLen = INT_MAX;\n\n    for (auto p : params) {\n        Solver solver(A, p);\n        string s = solver.run();\n\n        if ((int)s.size() < bestLen) {\n            bestLen = (int)s.size();\n            best = std::move(s);\n        }\n    }\n\n    cout << best << '\\n';\n\n    for (int i = 1; i < N; i++) {\n        cout << 'B';\n        for (int k = 1; k < bestLen; k++) cout << '.';\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<vector<int>> H;\n\nstruct Result {\n    long long cost = (1LL << 60);\n    vector<string> ops;\n};\n\nstruct Cell {\n    int r, c;\n    int v;\n};\n\nstruct Params {\n    double emptyDistW;\n    double deliverDistW;\n    double amountBonus;\n    double sourceToSinkW;\n};\n\nint manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nvoid move_to(vector<string>& ops, long long& cost, long long load,\n             int& r, int& c, int nr, int nc) {\n    while (r < nr) {\n        ops.push_back(\"D\");\n        cost += 100 + load;\n        r++;\n    }\n    while (r > nr) {\n        ops.push_back(\"U\");\n        cost += 100 + load;\n        r--;\n    }\n    while (c < nc) {\n        ops.push_back(\"R\");\n        cost += 100 + load;\n        c++;\n    }\n    while (c > nc) {\n        ops.push_back(\"L\");\n        cost += 100 + load;\n        c--;\n    }\n}\n\nResult simulate_greedy(const Params& par) {\n    vector<Cell> pos, neg;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (H[i][j] > 0) pos.push_back({i, j, H[i][j]});\n            if (H[i][j] < 0) neg.push_back({i, j, -H[i][j]});\n        }\n    }\n\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n    int lastSrcR = 0, lastSrcC = 0;\n\n    int remainNeg = 0;\n    for (auto& x : neg) remainNeg += x.v;\n\n    while (remainNeg > 0) {\n        if (load == 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)pos.size(); i++) {\n                if (pos[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, pos[i].r, pos[i].c);\n                int nearestSink = 1000000;\n                for (auto& g : neg) {\n                    if (g.v <= 0) continue;\n                    nearestSink = min(nearestSink, manhattan(pos[i].r, pos[i].c, g.r, g.c));\n                }\n\n                double score =\n                    par.emptyDistW * dcur\n                    + par.sourceToSinkW * nearestSink\n                    - par.amountBonus * sqrt((double)pos[i].v);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, pos[best].r, pos[best].c);\n\n            int d = pos[best].v;\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            pos[best].v = 0;\n            lastSrcR = r;\n            lastSrcC = c;\n        }\n\n        while (load > 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)neg.size(); i++) {\n                if (neg[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, neg[i].r, neg[i].c);\n                int dsrc = manhattan(lastSrcR, lastSrcC, neg[i].r, neg[i].c);\n                int give = min<long long>(load, neg[i].v);\n\n                double score =\n                    par.deliverDistW * dcur\n                    + 0.25 * dsrc\n                    - par.amountBonus * sqrt((double)give);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, neg[best].r, neg[best].c);\n\n            int d = min<long long>(load, neg[best].v);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            neg[best].v -= d;\n            remainNeg -= d;\n        }\n    }\n\n    if ((int)ops.size() > 100000) return Result();\n    return {cost, ops};\n}\n\nResult simulate_path(const vector<pair<int,int>>& path) {\n    vector<vector<int>> h = H;\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n\n    auto process_cell = [&](int i, int j) {\n        if (h[i][j] > 0) {\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        } else if (h[i][j] < 0 && load > 0) {\n            int d = min<long long>(-h[i][j], load);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] += d;\n        }\n    };\n\n    for (auto [i,j] : path) {\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (int idx = (int)path.size() - 1; idx >= 0; idx--) {\n        auto [i,j] = path[idx];\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] > 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        }\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] < 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = -h[i][j];\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] = 0;\n        }\n    }\n\n    if ((int)ops.size() > 100000) return Result();\n    return {cost, ops};\n}\n\nResult simulate_cyclic_path(const vector<pair<int,int>>& base, int start) {\n    int M = base.size();\n\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n\n    for (int k = 0; k < M; k++) {\n        auto [i,j] = base[(start + k) % M];\n\n        move_to(ops, cost, load, r, c, i, j);\n\n        int v = H[i][j];\n        if (v > 0) {\n            ops.push_back(\"+\" + to_string(v));\n            cost += v;\n            load += v;\n        } else if (v < 0) {\n            int d = -v;\n            if (load < d) return Result();\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n        }\n    }\n\n    if (load != 0) return Result();\n    if ((int)ops.size() > 100000) return Result();\n    return {cost, ops};\n}\n\nvoid test_cyclic_candidates(const vector<pair<int,int>>& base, Result& best) {\n    int M = base.size();\n\n    vector<long long> pref(M + 1, 0);\n    for (int i = 0; i < M; i++) {\n        auto [r,c] = base[i];\n        pref[i + 1] = pref[i] + H[r][c];\n    }\n\n    long long mn = *min_element(pref.begin(), pref.end());\n\n    // Only starts after minimum prefix are guaranteed valid.\n    for (int i = 0; i < M; i++) {\n        if (pref[i] == mn) {\n            Result r = simulate_cyclic_path(base, i);\n            if (r.cost < best.cost) best = move(r);\n        }\n    }\n}\n\nvector<pair<int,int>> row_snake_from_order(const vector<int>& rows, bool revFirst) {\n    vector<pair<int,int>> p;\n    for (int idx = 0; idx < (int)rows.size(); idx++) {\n        int i = rows[idx];\n        bool rev = (idx % 2) ^ revFirst;\n        if (!rev) for (int j = 0; j < N; j++) p.push_back({i,j});\n        else for (int j = N - 1; j >= 0; j--) p.push_back({i,j});\n    }\n    return p;\n}\n\nvector<pair<int,int>> col_snake_from_order(const vector<int>& cols, bool revFirst) {\n    vector<pair<int,int>> p;\n    for (int idx = 0; idx < (int)cols.size(); idx++) {\n        int j = cols[idx];\n        bool rev = (idx % 2) ^ revFirst;\n        if (!rev) for (int i = 0; i < N; i++) p.push_back({i,j});\n        else for (int i = N - 1; i >= 0; i--) p.push_back({i,j});\n    }\n    return p;\n}\n\nvector<int> normal_order() {\n    vector<int> v(N);\n    iota(v.begin(), v.end(), 0);\n    return v;\n}\n\nvector<int> reverse_order_vec() {\n    vector<int> v = normal_order();\n    reverse(v.begin(), v.end());\n    return v;\n}\n\nvector<int> center_out_order() {\n    vector<int> v;\n    int a = (N - 1) / 2, b = N / 2;\n    for (int d = 0; d < N; d++) {\n        int x = a - d;\n        int y = b + d;\n        if (x >= 0) v.push_back(x);\n        if (y < N && y != x) v.push_back(y);\n    }\n    return v;\n}\n\nvector<int> outside_in_order() {\n    vector<int> v;\n    for (int d = 0; d < (N + 1) / 2; d++) {\n        v.push_back(d);\n        if (N - 1 - d != d) v.push_back(N - 1 - d);\n    }\n    return v;\n}\n\nvector<int> even_odd_order() {\n    vector<int> v;\n    for (int i = 0; i < N; i += 2) v.push_back(i);\n    for (int i = 1; i < N; i += 2) v.push_back(i);\n    return v;\n}\n\nvector<int> odd_even_order() {\n    vector<int> v;\n    for (int i = 1; i < N; i += 2) v.push_back(i);\n    for (int i = 0; i < N; i += 2) v.push_back(i);\n    return v;\n}\n\nvector<pair<int,int>> row_raster() {\n    vector<pair<int,int>> p;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> col_raster() {\n    vector<pair<int,int>> p;\n    for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> spiral_outside_in() {\n    vector<pair<int,int>> p;\n    int top = 0, bottom = N - 1, left = 0, right = N - 1;\n    while (top <= bottom && left <= right) {\n        for (int j = left; j <= right; j++) p.push_back({top,j});\n        top++;\n        for (int i = top; i <= bottom; i++) p.push_back({i,right});\n        right--;\n        if (top <= bottom) {\n            for (int j = right; j >= left; j--) p.push_back({bottom,j});\n            bottom--;\n        }\n        if (left <= right) {\n            for (int i = bottom; i >= top; i--) p.push_back({i,left});\n            left++;\n        }\n    }\n    return p;\n}\n\nvector<pair<int,int>> spiral_center_out() {\n    auto p = spiral_outside_in();\n    reverse(p.begin(), p.end());\n    return p;\n}\n\nvector<pair<int,int>> diagonal_order(bool anti, bool zigzag) {\n    vector<pair<int,int>> p;\n    for (int s = 0; s <= 2 * (N - 1); s++) {\n        vector<pair<int,int>> v;\n        for (int i = 0; i < N; i++) {\n            int j = s - i;\n            if (0 <= j && j < N) {\n                if (!anti) v.push_back({i,j});\n                else v.push_back({i,N-1-j});\n            }\n        }\n        if (zigzag && (s & 1)) reverse(v.begin(), v.end());\n        for (auto x : v) p.push_back(x);\n    }\n    return p;\n}\n\nint morton_code(int r, int c) {\n    int z = 0;\n    for (int b = 0; b < 5; b++) {\n        z |= ((c >> b) & 1) << (2 * b);\n        z |= ((r >> b) & 1) << (2 * b + 1);\n    }\n    return z;\n}\n\nvector<pair<int,int>> morton_order(bool swapRC, bool revBits) {\n    vector<tuple<int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = swapRC ? j : i;\n            int b = swapRC ? i : j;\n            int code = morton_code(a, b);\n            if (revBits) code = -code;\n            v.push_back({code, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [_, i, j] : v) p.push_back({i,j});\n    return p;\n}\n\nint hilbert_xy2d(int n, int x, int y) {\n    int rx, ry, s, d = 0;\n    for (s = n / 2; s > 0; s /= 2) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = n - 1 - x;\n                y = n - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\nvector<pair<int,int>> hilbert_order(int rot, bool rev) {\n    vector<tuple<int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x = i, y = j;\n            if (rot == 1) { x = j; y = N - 1 - i; }\n            if (rot == 2) { x = N - 1 - i; y = N - 1 - j; }\n            if (rot == 3) { x = N - 1 - j; y = i; }\n            if (rot == 4) { x = j; y = i; }\n            if (rot == 5) { x = N - 1 - i; y = j; }\n            if (rot == 6) { x = i; y = N - 1 - j; }\n            if (rot == 7) { x = N - 1 - j; y = N - 1 - i; }\n\n            int code = hilbert_xy2d(32, x, y);\n            if (rev) code = -code;\n            v.push_back({code, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [_, i, j] : v) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> projection_order(int a, int b, bool zigzagTie, bool rev) {\n    vector<tuple<int,int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int key = a * i + b * j;\n            int tie = -b * i + a * j;\n            if (zigzagTie && (key & 1)) tie = -tie;\n            if (rev) key = -key;\n            v.push_back({key, tie, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [k,t,i,j] : v) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> block_snake(int B, bool blockColMajor, bool revBlockFirst, bool revInnerFirst) {\n    vector<pair<int,int>> p;\n    int nb = (N + B - 1) / B;\n\n    if (!blockColMajor) {\n        for (int bi = 0; bi < nb; bi++) {\n            vector<int> bjList;\n            if (((bi & 1) ^ revBlockFirst) == 0) {\n                for (int bj = 0; bj < nb; bj++) bjList.push_back(bj);\n            } else {\n                for (int bj = nb - 1; bj >= 0; bj--) bjList.push_back(bj);\n            }\n\n            for (int bj : bjList) {\n                int r0 = bi * B, r1 = min(N, r0 + B);\n                int c0 = bj * B, c1 = min(N, c0 + B);\n\n                for (int ii = r0; ii < r1; ii++) {\n                    bool rev = ((ii - r0) & 1) ^ revInnerFirst;\n                    if (!rev) for (int jj = c0; jj < c1; jj++) p.push_back({ii,jj});\n                    else for (int jj = c1 - 1; jj >= c0; jj--) p.push_back({ii,jj});\n                }\n            }\n        }\n    } else {\n        for (int bj = 0; bj < nb; bj++) {\n            vector<int> biList;\n            if (((bj & 1) ^ revBlockFirst) == 0) {\n                for (int bi = 0; bi < nb; bi++) biList.push_back(bi);\n            } else {\n                for (int bi = nb - 1; bi >= 0; bi--) biList.push_back(bi);\n            }\n\n            for (int bi : biList) {\n                int r0 = bi * B, r1 = min(N, r0 + B);\n                int c0 = bj * B, c1 = min(N, c0 + B);\n\n                for (int jj = c0; jj < c1; jj++) {\n                    bool rev = ((jj - c0) & 1) ^ revInnerFirst;\n                    if (!rev) for (int ii = r0; ii < r1; ii++) p.push_back({ii,jj});\n                    else for (int ii = r1 - 1; ii >= r0; ii--) p.push_back({ii,jj});\n                }\n            }\n        }\n    }\n\n    return p;\n}\n\nint smooth_height(int r, int c) {\n    int sum = 0, cnt = 0;\n    for (int dr = -1; dr <= 1; dr++) {\n        for (int dc = -1; dc <= 1; dc++) {\n            int nr = r + dr, nc = c + dc;\n            if (0 <= nr && nr < N && 0 <= nc && nc < N) {\n                sum += H[nr][nc];\n                cnt++;\n            }\n        }\n    }\n    return sum / cnt;\n}\n\nvector<pair<int,int>> height_sorted_order(bool smooth, bool descending, int tieMode) {\n    vector<tuple<int,int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int hv = smooth ? smooth_height(i,j) : H[i][j];\n            int key = descending ? -hv : hv;\n            int tie;\n            if (tieMode == 0) tie = i * N + j;\n            else if (tieMode == 1) tie = j * N + i;\n            else if (tieMode == 2) tie = manhattan(i,j,N/2,N/2);\n            else tie = morton_code(i,j);\n            v.push_back({key, tie, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [a,b,i,j] : v) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> nearest_terrain_path(int sr, int sc, double distW, double signW, double magW) {\n    vector<pair<int,int>> p;\n    vector<vector<int>> used(N, vector<int>(N, 0));\n    int r = sr, c = sc;\n    long long balance = 0;\n\n    for (int step = 0; step < N * N; step++) {\n        p.push_back({r,c});\n        used[r][c] = 1;\n        balance += H[r][c];\n\n        if (step == N * N - 1) break;\n\n        int bestR = -1, bestC = -1;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (used[i][j]) continue;\n\n                int d = manhattan(r,c,i,j);\n                int hv = H[i][j];\n\n                // If current balance is low/negative, prefer positive cells.\n                // If high, prefer negative cells.\n                double signScore = 0;\n                if (balance < 0 && hv > 0) signScore -= signW * sqrt((double)abs(hv));\n                if (balance > 0 && hv < 0) signScore -= signW * sqrt((double)abs(hv));\n                if (balance < 0 && hv < 0) signScore += signW;\n                if (balance > 0 && hv > 0) signScore += signW * 0.3;\n\n                double score =\n                    distW * d\n                    + signScore\n                    - magW * sqrt((double)abs(hv));\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    bestR = i;\n                    bestC = j;\n                }\n            }\n        }\n\n        r = bestR;\n        c = bestC;\n    }\n\n    return p;\n}\n\nbool valid_order(const vector<pair<int,int>>& p) {\n    if ((int)p.size() != N * N) return false;\n    vector<vector<int>> seen(N, vector<int>(N, 0));\n    for (auto [r,c] : p) {\n        if (r < 0 || r >= N || c < 0 || c >= N) return false;\n        if (seen[r][c]) return false;\n        seen[r][c] = 1;\n    }\n    return true;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    H.assign(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> H[i][j];\n    }\n\n    Result best;\n\n    vector<Params> params = {\n        {1.0, 1.0, 0.0, 0.0},\n        {1.0, 1.0, 1.0, 0.2},\n        {1.0, 1.0, 2.0, 0.5},\n        {1.0, 1.3, 1.0, 0.5},\n        {1.3, 1.0, 1.0, 0.5},\n        {0.7, 1.2, 2.0, 0.8},\n        {1.5, 0.8, 1.5, 0.3},\n        {1.0, 2.0, 2.0, 1.0},\n        {2.0, 1.0, 2.0, 1.0},\n        {0.5, 1.5, 1.0, 1.0},\n    };\n\n    for (auto& p : params) {\n        Result res = simulate_greedy(p);\n        if (res.cost < best.cost) best = move(res);\n    }\n\n    vector<vector<pair<int,int>>> paths;\n\n    vector<vector<int>> orders = {\n        normal_order(),\n        reverse_order_vec(),\n        center_out_order(),\n        outside_in_order(),\n        even_odd_order(),\n        odd_even_order()\n    };\n\n    for (auto rows : orders) {\n        for (int rf = 0; rf < 2; rf++) {\n            paths.push_back(row_snake_from_order(rows, rf));\n            paths.push_back(col_snake_from_order(rows, rf));\n        }\n    }\n\n    paths.push_back(row_raster());\n    paths.push_back(col_raster());\n    paths.push_back(spiral_outside_in());\n    paths.push_back(spiral_center_out());\n\n    for (int anti = 0; anti < 2; anti++) {\n        for (int zig = 0; zig < 2; zig++) {\n            paths.push_back(diagonal_order(anti, zig));\n        }\n    }\n\n    for (int sw = 0; sw < 2; sw++) {\n        for (int rv = 0; rv < 2; rv++) {\n            paths.push_back(morton_order(sw, rv));\n        }\n    }\n\n    for (int rot = 0; rot < 8; rot++) {\n        for (int rv = 0; rv < 2; rv++) {\n            paths.push_back(hilbert_order(rot, rv));\n        }\n    }\n\n    vector<pair<int,int>> dirs = {\n        {1,1}, {1,-1}, {2,1}, {1,2}, {2,-1}, {1,-2},\n        {3,1}, {1,3}, {3,-1}, {1,-3}\n    };\n    for (auto [a,b] : dirs) {\n        for (int zig = 0; zig < 2; zig++) {\n            for (int rv = 0; rv < 2; rv++) {\n                paths.push_back(projection_order(a,b,zig,rv));\n            }\n        }\n    }\n\n    for (int B : {2, 4, 5, 10}) {\n        for (int cm = 0; cm < 2; cm++) {\n            for (int rb = 0; rb < 2; rb++) {\n                for (int ri = 0; ri < 2; ri++) {\n                    paths.push_back(block_snake(B, cm, rb, ri));\n                }\n            }\n        }\n    }\n\n    for (int sm = 0; sm < 2; sm++) {\n        for (int desc = 0; desc < 2; desc++) {\n            for (int tie = 0; tie < 4; tie++) {\n                paths.push_back(height_sorted_order(sm, desc, tie));\n            }\n        }\n    }\n\n    vector<pair<int,int>> starts = {\n        {0,0}, {0,N-1}, {N-1,0}, {N-1,N-1},\n        {N/2,N/2}, {0,N/2}, {N/2,0}, {N-1,N/2}, {N/2,N-1}\n    };\n\n    for (auto [sr,sc] : starts) {\n        for (double dw : {1.0, 1.5, 2.0}) {\n            for (double sw : {1.0, 2.0, 4.0}) {\n                paths.push_back(nearest_terrain_path(sr, sc, dw, sw, 0.2));\n                paths.push_back(nearest_terrain_path(sr, sc, dw, sw, 1.0));\n            }\n        }\n    }\n\n    int originalSize = paths.size();\n    for (int i = 0; i < originalSize; i++) {\n        auto q = paths[i];\n        reverse(q.begin(), q.end());\n        paths.push_back(q);\n    }\n\n    set<vector<pair<int,int>>> seen;\n    vector<vector<pair<int,int>>> uniq;\n    for (auto& p : paths) {\n        if (!valid_order(p)) continue;\n        if (seen.insert(p).second) uniq.push_back(p);\n    }\n\n    for (auto& path : uniq) {\n        Result res = simulate_path(path);\n        if (res.cost < best.cost) best = move(res);\n\n        test_cyclic_candidates(path, best);\n    }\n\n    for (auto& s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ull) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n    double rand01() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int S = 2 * N * (N - 1); // 60\n    const int C = N * N;           // 36\n\n    vector<vector<int>> X(S, vector<int>(M));\n    for (int i = 0; i < S; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    vector<int> target(M, 0);\n    for (int i = 0; i < S; i++) {\n        for (int l = 0; l < M; l++) target[l] = max(target[l], X[i][l]);\n    }\n    int targetSum = accumulate(target.begin(), target.end(), 0);\n\n    vector<pair<int,int>> edges;\n    vector<vector<int>> incident(C);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (j + 1 < N) {\n                int id2 = id + 1;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n            if (i + 1 < N) {\n                int id2 = id + N;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n        }\n    }\n\n    vector<int> deg(C, 0);\n    for (auto [a,b] : edges) {\n        deg[a]++;\n        deg[b]++;\n    }\n\n    vector<int> blackCells, whiteCells, allCells(C);\n    iota(allCells.begin(), allCells.end(), 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if ((i + j) & 1) whiteCells.push_back(id);\n            else blackCells.push_back(id);\n        }\n    }\n\n    auto sort_cells = [&](vector<int>& v) {\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n    };\n    sort_cells(blackCells);\n    sort_cells(whiteCells);\n    sort_cells(allCells);\n\n    auto start_time = chrono::steady_clock::now();\n    XorShift rng(246813579);\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> curMax(M, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) curMax[l] = max(curMax[l], X[i][l]);\n        }\n\n        vector<int> sumv(S, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) sumv[i] += X[i][l];\n        }\n\n        double phase = (double)turn / max(1, T - 1);\n        bool finalTurn = (turn == T - 1);\n\n        vector<double> seedScore(S, 0);\n        vector<double> valueScore(S, 0);\n        vector<double> targetFit(S, 0);\n        vector<double> curFit(S, 0);\n\n        for (int i = 0; i < S; i++) {\n            double tr = 0, trsq = 0;\n            double cr = 0, crsq = 0;\n            double elite = 0;\n            int nearTarget = 0;\n            int exactCur = 0;\n\n            for (int l = 0; l < M; l++) {\n                double rt = (double)X[i][l] / max(1, target[l]);\n                double rc = (double)X[i][l] / max(1, curMax[l]);\n                tr += 100.0 * rt;\n                trsq += 100.0 * rt * rt;\n                cr += 100.0 * rc;\n                crsq += 100.0 * rc * rc;\n\n                if (X[i][l] >= target[l] * 0.95) nearTarget++;\n                if (X[i][l] == curMax[l]) exactCur++;\n\n                if (X[i][l] == curMax[l]) elite += 70.0;\n                if (X[i][l] >= target[l] * 0.95) elite += 45.0;\n                else if (X[i][l] >= target[l] * 0.88) elite += 18.0;\n            }\n\n            targetFit[i] = tr + 0.45 * trsq + 32.0 * nearTarget;\n            curFit[i] = cr + 0.35 * crsq + 38.0 * exactCur;\n            valueScore[i] = sumv[i] + 0.55 * targetFit[i];\n\n            seedScore[i] =\n                (0.70 + 0.95 * phase) * sumv[i]\n                + 0.80 * targetFit[i]\n                + 0.38 * curFit[i]\n                + elite;\n        }\n\n        // Pair score.\n        vector<vector<double>> P(S, vector<double>(S, 0.0));\n\n        for (int a = 0; a < S; a++) {\n            for (int b = a + 1; b < S; b++) {\n                int maxsum = 0;\n                int minsum = 0;\n                int diff = 0;\n                int nearTarget = 0;\n                int nearCurrent = 0;\n                int exactCurrent = 0;\n                int bothMedium = 0;\n                double targetRatioSq = 0;\n\n                for (int l = 0; l < M; l++) {\n                    int ma = max(X[a][l], X[b][l]);\n                    int mi = min(X[a][l], X[b][l]);\n                    maxsum += ma;\n                    minsum += mi;\n                    diff += abs(X[a][l] - X[b][l]);\n\n                    double rt = (double)ma / max(1, target[l]);\n                    targetRatioSq += rt * rt;\n\n                    if (ma >= target[l] * 0.92) nearTarget++;\n                    if (ma >= curMax[l] * 0.92) nearCurrent++;\n                    if (ma == curMax[l]) exactCurrent++;\n                    if (X[a][l] >= target[l] * 0.70 && X[b][l] >= target[l] * 0.70) bothMedium++;\n                }\n\n                double expected = 0.5 * (sumv[a] + sumv[b]);\n                double closeToTarget = targetSum > 0 ? (double)maxsum / targetSum : 0.0;\n\n                double exploit = finalTurn ? 1.0 : phase;\n\n                double sc = 0;\n                sc += (1.70 + 0.55 * exploit) * maxsum;\n                sc += (0.18 + 1.10 * exploit) * expected;\n                sc += 0.16 * minsum;\n                sc += (0.24 - 0.13 * exploit) * diff;\n                sc += 34.0 * nearTarget;\n                sc += 18.0 * nearCurrent;\n                sc += 13.0 * exactCurrent;\n                sc += 7.0 * bothMedium;\n                sc += 18.0 * targetRatioSq;\n                sc += 300.0 * closeToTarget * closeToTarget;\n\n                P[a][b] = P[b][a] = sc;\n            }\n        }\n\n        auto make_selection = [&](int mode) {\n            vector<int> selected;\n            vector<int> used(S, 0);\n\n            auto add_seed = [&](int id) {\n                if (!used[id] && (int)selected.size() < C) {\n                    used[id] = 1;\n                    selected.push_back(id);\n                }\n            };\n\n            // Top 1 or top 2 coordinate champions.\n            int champDepth = (turn <= 6 ? 2 : 1);\n            if (mode == 3) champDepth = 2;\n\n            for (int l = 0; l < M; l++) {\n                vector<int> ids(S);\n                iota(ids.begin(), ids.end(), 0);\n                sort(ids.begin(), ids.end(), [&](int a, int b) {\n                    if (X[a][l] != X[b][l]) return X[a][l] > X[b][l];\n                    return seedScore[a] > seedScore[b];\n                });\n\n                for (int r = 0; r < champDepth; r++) add_seed(ids[r]);\n            }\n\n            vector<int> ord(S);\n            iota(ord.begin(), ord.end(), 0);\n\n            if (mode == 0) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n            } else if (mode == 1) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return targetFit[a] > targetFit[b];\n                });\n            } else if (mode == 2) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return valueScore[a] > valueScore[b];\n                });\n            } else {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return curFit[a] > curFit[b];\n                });\n            }\n\n            int mandatoryTop;\n            if (mode == 2) mandatoryTop = 14 + (int)(8 * phase);\n            else mandatoryTop = 10 + (int)(6 * phase);\n\n            for (int id : ord) {\n                if ((int)selected.size() >= mandatoryTop) break;\n                add_seed(id);\n            }\n\n            vector<int> cover(M, 0);\n            for (int id : selected) {\n                for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[id][l]);\n            }\n\n            while ((int)selected.size() < C) {\n                int best = -1;\n                double bestSc = -1e100;\n\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    double gain = 0;\n                    for (int l = 0; l < M; l++) {\n                        int d = max(0, X[i][l] - cover[l]);\n\n                        if (mode == 0) gain += 12.0 * d;\n                        if (mode == 1) gain += 15.0 * d;\n                        if (mode == 2) gain += 7.0 * d;\n                        if (mode == 3) gain += 13.0 * d;\n\n                        double rt = (double)X[i][l] / max(1, target[l]);\n                        double rc = (double)X[i][l] / max(1, curMax[l]);\n\n                        gain += 24.0 * rt + 12.0 * rc;\n                        if (X[i][l] >= target[l] * 0.92) gain += 18.0;\n                        if (X[i][l] == curMax[l]) gain += 22.0;\n                    }\n\n                    double bestPair = 0;\n                    double avgPair = 0;\n                    for (int id : selected) {\n                        bestPair = max(bestPair, P[i][id]);\n                        avgPair += P[i][id];\n                    }\n                    if (!selected.empty()) avgPair /= selected.size();\n\n                    double sc = gain\n                              + (0.32 + 0.55 * phase) * seedScore[i]\n                              + (mode == 2 ? 0.35 : 0.24) * bestPair\n                              + 0.08 * avgPair\n                              + rng.rand01() * 1e-5;\n\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n\n                add_seed(best);\n                for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[best][l]);\n            }\n\n            return selected;\n        };\n\n        auto layout_score = [&](const vector<int>& posSeed) {\n            double s = 0;\n            for (auto [u,v] : edges) s += P[posSeed[u]][posSeed[v]];\n            return s;\n        };\n\n        auto make_layouts = [&](const vector<int>& selected) {\n            vector<vector<int>> layouts;\n\n            // Layout A: complementary bipartite.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> gA, gB;\n                gA.push_back(rem[0]);\n\n                for (int idx = 1; idx < (int)rem.size(); idx++) {\n                    int id = rem[idx];\n\n                    if ((int)gA.size() >= 18) {\n                        gB.push_back(id);\n                        continue;\n                    }\n                    if ((int)gB.size() >= 18) {\n                        gA.push_back(id);\n                        continue;\n                    }\n\n                    double toA = 0, toB = 0;\n                    for (int x : gA) toB += P[id][x];\n                    for (int x : gB) toA += P[id][x];\n\n                    if (toA > toB) gA.push_back(id);\n                    else gB.push_back(id);\n                }\n\n                while ((int)gA.size() < 18) {\n                    gA.push_back(gB.back());\n                    gB.pop_back();\n                }\n                while ((int)gB.size() < 18) {\n                    gB.push_back(gA.back());\n                    gA.pop_back();\n                }\n\n                sort(gA.begin(), gA.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n                sort(gB.begin(), gB.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < 18; i++) {\n                    pos[blackCells[i]] = gA[i];\n                    pos[whiteCells[i]] = gB[i];\n                }\n                layouts.push_back(pos);\n            }\n\n            // Layout B: strength-degree.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < C; i++) pos[allCells[i]] = rem[i];\n                layouts.push_back(pos);\n            }\n\n            // Layout C: alternating target/value on bipartition.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return targetFit[a] > targetFit[b];\n                });\n\n                vector<int> gA, gB;\n                for (int i = 0; i < C; i++) {\n                    if (i % 2 == 0) gA.push_back(rem[i]);\n                    else gB.push_back(rem[i]);\n                }\n\n                sort(gA.begin(), gA.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n                sort(gB.begin(), gB.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < 18; i++) {\n                    pos[blackCells[i]] = gA[i];\n                    pos[whiteCells[i]] = gB[i];\n                }\n                layouts.push_back(pos);\n            }\n\n            return layouts;\n        };\n\n        auto improve_layout = [&](vector<int> posSeed, int iterations, double temp0) {\n            auto edgeScoreAt = [&](const vector<int>& ps, int eid) {\n                auto [u,v] = edges[eid];\n                return P[ps[u]][ps[v]];\n            };\n\n            double cur = layout_score(posSeed);\n\n            for (int it = 0; it < iterations; it++) {\n                int a = rng.randint(C);\n                int b = rng.randint(C);\n                if (a == b) continue;\n\n                vector<int> es;\n                for (int e : incident[a]) es.push_back(e);\n                for (int e : incident[b]) es.push_back(e);\n                sort(es.begin(), es.end());\n                es.erase(unique(es.begin(), es.end()), es.end());\n\n                double before = 0;\n                for (int e : es) before += edgeScoreAt(posSeed, e);\n\n                swap(posSeed[a], posSeed[b]);\n\n                double after = 0;\n                for (int e : es) after += edgeScoreAt(posSeed, e);\n\n                double delta = after - before;\n                double progress = (double)it / max(1, iterations);\n                double temp = temp0 * (1.0 - progress) + 1.0;\n\n                bool accept = false;\n                if (delta >= 0) accept = true;\n                else if (exp(delta / temp) > rng.rand01()) accept = true;\n\n                if (accept) {\n                    cur += delta;\n                } else {\n                    swap(posSeed[a], posSeed[b]);\n                }\n            }\n\n            return pair<double, vector<int>>(cur, posSeed);\n        };\n\n        vector<pair<double, vector<int>>> pool;\n\n        int modes = finalTurn ? 3 : 4;\n        for (int mode = 0; mode < modes; mode++) {\n            vector<int> sel = make_selection(mode);\n            vector<vector<int>> layouts = make_layouts(sel);\n\n            for (auto &lay : layouts) {\n                int shortIter = 2500;\n                auto res = improve_layout(lay, shortIter, 55.0);\n                pool.push_back(res);\n            }\n        }\n\n        sort(pool.begin(), pool.end(), [&](const auto& a, const auto& b) {\n            return a.first > b.first;\n        });\n\n        vector<int> posSeed = pool[0].second;\n\n        int longIter = 70000;\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.70) longIter = 20000;\n\n        auto finalRes = improve_layout(posSeed, longIter, 75.0);\n        posSeed = finalRes.second;\n\n        vector<vector<int>> A(N, vector<int>(N));\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                A[i][j] = posSeed[i * N + 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 << A[i][j];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        for (int i = 0; i < S; i++) {\n            for (int j = 0; j < M; j++) cin >> X[i][j];\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\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    vector<Pos> src, dst;\n    vector<vector<int>> src_id(N, vector<int>(N, -1));\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] == '0') {\n                src_id[i][j] = (int)src.size();\n                src.push_back({i, j});\n            }\n            if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    int K = (int)src.size();\n\n    int F = max(1, V - 1);\n    int Vp = F + 1;\n\n    /*\n        Star arm, but each finger has different length.\n\n        Length pattern:\n        1,2,3,4,5, then repeat.\n        Capped by N-1.\n\n        This keeps many short useful fingers while allowing wider reach.\n    */\n    vector<int> len(F);\n    for (int f = 0; f < F; f++) {\n        len[f] = min(N - 1, 1 + (f % 5));\n    }\n\n    vector<int> finger_dir(F, 0); // 0:R, 1:D, 2:L, 3:U\n    vector<int> holding(F, -1);\n\n    const int dx[4] = {0, 1, 0, -1};\n    const int dy[4] = {1, 0, -1, 0};\n\n    auto inside = [&](int x, int y) {\n        return 0 <= x && x < N && y >= 0 && y < N;\n    };\n\n    auto manhattan = [&](Pos a, Pos b) {\n        return abs(a.x - b.x) + abs(a.y - b.y);\n    };\n\n    int root_x = 0, root_y = 0;\n    vector<string> ops;\n\n    auto add_op = [&](char mv, const vector<char>& rot, const vector<char>& act) {\n        string op(2 * Vp, '.');\n        op[0] = mv;\n\n        for (int f = 0; f < F; f++) {\n            op[1 + f] = rot[f];\n            op[Vp + 1 + f] = act[f];\n        }\n\n        if (mv == 'U') root_x--;\n        if (mv == 'D') root_x++;\n        if (mv == 'L') root_y--;\n        if (mv == 'R') root_y++;\n\n        for (int f = 0; f < F; f++) {\n            if (rot[f] == 'L') finger_dir[f] = (finger_dir[f] + 3) % 4;\n            if (rot[f] == 'R') finger_dir[f] = (finger_dir[f] + 1) % 4;\n        }\n\n        ops.push_back(op);\n    };\n\n    auto blank_rot = [&]() { return vector<char>(F, '.'); };\n    auto blank_act = [&]() { return vector<char>(F, '.'); };\n\n    auto move_root_to = [&](int tx, int ty) {\n        while (root_x < tx) add_op('D', blank_rot(), blank_act());\n        while (root_x > tx) add_op('U', blank_rot(), blank_act());\n        while (root_y < ty) add_op('R', blank_rot(), blank_act());\n        while (root_y > ty) add_op('L', blank_rot(), blank_act());\n    };\n\n    auto rotate_fingers_to = [&](const vector<int>& target_dir) {\n        while (true) {\n            vector<char> rot(F, '.');\n            vector<char> act(F, '.');\n            bool changed = false;\n\n            for (int f = 0; f < F; f++) {\n                if (target_dir[f] < 0) continue;\n                if (finger_dir[f] == target_dir[f]) continue;\n\n                int diff = (target_dir[f] - finger_dir[f] + 4) % 4;\n                if (diff == 1 || diff == 2) rot[f] = 'R';\n                else rot[f] = 'L';\n\n                changed = true;\n            }\n\n            if (!changed) break;\n            add_op('.', rot, act);\n        }\n    };\n\n    struct Reach {\n        int f;\n        int d;\n        Pos r;\n    };\n\n    auto reaches_for_cell = [&](Pos p) {\n        vector<Reach> res;\n        for (int f = 0; f < F; f++) {\n            for (int d = 0; d < 4; d++) {\n                int rx = p.x - dx[d] * len[f];\n                int ry = p.y - dy[d] * len[f];\n                if (inside(rx, ry)) {\n                    res.push_back({f, d, {rx, ry}});\n                }\n            }\n        }\n        return res;\n    };\n\n    auto finger_can_reach_from_root = [&](int f, Pos root, Pos p, int &dir_out) {\n        for (int d = 0; d < 4; d++) {\n            if (root.x + dx[d] * len[f] == p.x &&\n                root.y + dy[d] * len[f] == p.y) {\n                dir_out = d;\n                return true;\n            }\n        }\n        return false;\n    };\n\n    // Greedy matching by sorted all-pair distances.\n    vector<int> pair_dst(K, -1);\n    {\n        struct Edge {\n            int dist, i, j;\n        };\n        vector<Edge> edges;\n        edges.reserve(K * K);\n\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < K; j++) {\n                edges.push_back({manhattan(src[i], dst[j]), i, j});\n            }\n        }\n\n        sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) {\n            if (a.dist != b.dist) return a.dist < b.dist;\n            if (a.i != b.i) return a.i < b.i;\n            return a.j < b.j;\n        });\n\n        vector<int> used_s(K, 0), used_d(K, 0);\n        int matched = 0;\n        for (const auto& e : edges) {\n            if (!used_s[e.i] && !used_d[e.j]) {\n                used_s[e.i] = used_d[e.j] = 1;\n                pair_dst[e.i] = e.j;\n                matched++;\n                if (matched == K) break;\n            }\n        }\n    }\n\n    vector<int> done(K, 0);\n    int remaining = K;\n\n    auto min_root_dist_to_cell = [&](Pos p) {\n        int best = INT_MAX;\n        for (auto rc : reaches_for_cell(p)) {\n            int c = abs(root_x - rc.r.x) + abs(root_y - rc.r.y);\n            best = min(best, c);\n        }\n        return best;\n    };\n\n    auto choose_seed = [&]() {\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n\n            int approach = min_root_dist_to_cell(src[i]);\n            int transport = manhattan(src[i], dst[pair_dst[i]]);\n\n            int cost = approach * 5 + transport;\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best = i;\n            }\n        }\n\n        return best;\n    };\n\n    while (remaining > 0) {\n        int seed = choose_seed();\n        if (seed < 0) break;\n\n        // Choose best root/finger/dir to pick seed.\n        Reach best_reach{-1, -1, {-1, -1}};\n        int best_cost = INT_MAX;\n\n        for (auto rc : reaches_for_cell(src[seed])) {\n            int move_cost = abs(root_x - rc.r.x) + abs(root_y - rc.r.y);\n            int diff = abs(finger_dir[rc.f] - rc.d);\n            int rot_cost = min(diff, 4 - diff);\n            int cost = move_cost * 3 + rot_cost;\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_reach = rc;\n            }\n        }\n\n        move_root_to(best_reach.r.x, best_reach.r.y);\n\n        /*\n            Pick phase.\n            Among all undone sources reachable from current root, choose at most one\n            per finger. Prefer destinations near seed destination.\n        */\n        struct Cand {\n            int score;\n            int id;\n            int f;\n            int d;\n        };\n\n        vector<Cand> cands;\n        Pos seed_dest = dst[pair_dst[seed]];\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n\n            for (int f = 0; f < F; f++) {\n                int d;\n                if (finger_can_reach_from_root(f, {root_x, root_y}, src[i], d)) {\n                    Pos di = dst[pair_dst[i]];\n                    int diff = abs(finger_dir[f] - d);\n                    int rot = min(diff, 4 - diff);\n                    int score = manhattan(di, seed_dest) * 4\n                              + manhattan(src[i], src[seed])\n                              + rot;\n                    cands.push_back({score, i, f, d});\n                }\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            if (a.score != b.score) return a.score < b.score;\n            return a.id < b.id;\n        });\n\n        vector<int> used_f(F, 0), used_item(K, 0);\n        vector<int> pick_pairs;\n        vector<int> pick_fingers;\n        vector<int> pick_dirs;\n\n        // Ensure seed is picked if possible.\n        {\n            int bestf = -1, bestd = -1, bestr = INT_MAX;\n            for (int f = 0; f < F; f++) {\n                int d;\n                if (finger_can_reach_from_root(f, {root_x, root_y}, src[seed], d)) {\n                    int diff = abs(finger_dir[f] - d);\n                    int r = min(diff, 4 - diff);\n                    if (r < bestr) {\n                        bestr = r;\n                        bestf = f;\n                        bestd = d;\n                    }\n                }\n            }\n            if (bestf >= 0) {\n                used_f[bestf] = 1;\n                used_item[seed] = 1;\n                pick_pairs.push_back(seed);\n                pick_fingers.push_back(bestf);\n                pick_dirs.push_back(bestd);\n            }\n        }\n\n        for (auto c : cands) {\n            if ((int)pick_pairs.size() >= F) break;\n            if (used_f[c.f]) continue;\n            if (used_item[c.id]) continue;\n\n            used_f[c.f] = 1;\n            used_item[c.id] = 1;\n            pick_pairs.push_back(c.id);\n            pick_fingers.push_back(c.f);\n            pick_dirs.push_back(c.d);\n        }\n\n        int cnt = (int)pick_pairs.size();\n\n        vector<int> target_dir(F, -1);\n        for (int k = 0; k < cnt; k++) {\n            target_dir[pick_fingers[k]] = pick_dirs[k];\n        }\n\n        rotate_fingers_to(target_dir);\n\n        {\n            vector<char> rot = blank_rot();\n            vector<char> act = blank_act();\n\n            for (int k = 0; k < cnt; k++) {\n                int f = pick_fingers[k];\n                int pid = pick_pairs[k];\n\n                act[f] = 'P';\n                holding[f] = pid;\n                s[src[pid].x][src[pid].y] = '0';\n            }\n\n            add_op('.', rot, act);\n        }\n\n        vector<int> carrying;\n        for (int f = 0; f < F; f++) {\n            if (holding[f] >= 0) carrying.push_back(f);\n        }\n\n        /*\n            Place phase.\n            Repeatedly choose a root position maximizing number of carried items\n            placeable from there.\n        */\n        while (!carrying.empty()) {\n            int best_count = -1;\n            int best_cost2 = INT_MAX;\n            Pos best_root{-1, -1};\n\n            for (int f0 : carrying) {\n                int pid0 = holding[f0];\n                Pos q0 = dst[pair_dst[pid0]];\n\n                for (auto rc : reaches_for_cell(q0)) {\n                    Pos r = rc.r;\n\n                    int cnt_place = 0;\n                    for (int f : carrying) {\n                        int pid = holding[f];\n                        Pos q = dst[pair_dst[pid]];\n                        int dd;\n                        if (finger_can_reach_from_root(f, r, q, dd)) {\n                            cnt_place++;\n                        }\n                    }\n\n                    int cost = abs(root_x - r.x) + abs(root_y - r.y);\n\n                    if (cnt_place > best_count ||\n                        (cnt_place == best_count && cost < best_cost2)) {\n                        best_count = cnt_place;\n                        best_cost2 = cost;\n                        best_root = r;\n                    }\n                }\n            }\n\n            move_root_to(best_root.x, best_root.y);\n\n            vector<int> place_fingers;\n            vector<int> place_dirs;\n\n            for (int f : carrying) {\n                int pid = holding[f];\n                Pos q = dst[pair_dst[pid]];\n                int d;\n                if (finger_can_reach_from_root(f, {root_x, root_y}, q, d)) {\n                    place_fingers.push_back(f);\n                    place_dirs.push_back(d);\n                }\n            }\n\n            vector<int> tdir(F, -1);\n            for (int i = 0; i < (int)place_fingers.size(); i++) {\n                tdir[place_fingers[i]] = place_dirs[i];\n            }\n\n            rotate_fingers_to(tdir);\n\n            {\n                vector<char> rot = blank_rot();\n                vector<char> act = blank_act();\n\n                for (int f : place_fingers) {\n                    int pid = holding[f];\n                    int did = pair_dst[pid];\n                    Pos q = dst[did];\n\n                    act[f] = 'P';\n                    holding[f] = -1;\n                    done[pid] = 1;\n                    remaining--;\n                    s[q.x][q.y] = '1';\n                }\n\n                add_op('.', rot, act);\n            }\n\n            carrying.clear();\n            for (int f = 0; f < F; f++) {\n                if (holding[f] >= 0) carrying.push_back(f);\n            }\n        }\n    }\n\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << len[i - 1] << '\\n';\n    }\n    cout << 0 << ' ' << 0 << '\\n';\n\n    for (const string& op : ops) {\n        cout << op << '\\n';\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n    bool operator==(const Pt& o) const { return x == o.x && y == o.y; }\n};\n\nstruct Fish {\n    int x, y, t;\n};\n\nstatic const int LIM = 100000;\n\nlong long perimeter_poly(const vector<Pt>& p) {\n    long long res = 0;\n    int m = (int)p.size();\n    for (int i = 0; i < m; i++) {\n        Pt a = p[i], b = p[(i + 1) % m];\n        res += abs(a.x - b.x) + abs(a.y - b.y);\n    }\n    return res;\n}\n\nvector<Pt> simplify_poly(vector<Pt> p) {\n    if (p.empty()) return p;\n\n    vector<Pt> q;\n    q.reserve(p.size());\n    for (auto v : p) {\n        if (q.empty() || !(q.back() == v)) q.push_back(v);\n    }\n    if (q.size() > 1 && q.front() == q.back()) q.pop_back();\n\n    bool changed = true;\n    while (changed && q.size() >= 4) {\n        changed = false;\n        vector<Pt> r;\n        r.reserve(q.size());\n        int m = q.size();\n        for (int i = 0; i < m; i++) {\n            Pt a = q[(i - 1 + m) % m], b = q[i], c = q[(i + 1) % m];\n            if ((a.x == b.x && b.x == c.x) || (a.y == b.y && b.y == c.y)) {\n                changed = true;\n            } else {\n                r.push_back(b);\n            }\n        }\n        q.swap(r);\n    }\n    return q;\n}\n\nbool inside_poly(const vector<Pt>& poly, int x, int y) {\n    bool in = false;\n    int m = poly.size();\n    for (int i = 0, j = m - 1; i < m; j = i++) {\n        Pt a = poly[j], b = poly[i];\n\n        if (a.x == b.x && x == a.x && min(a.y,b.y) <= y && y <= max(a.y,b.y)) return true;\n        if (a.y == b.y && y == a.y && min(a.x,b.x) <= x && x <= max(a.x,b.x)) return true;\n\n        if ((a.y > y) != (b.y > y)) {\n            long double xx = (long double)(b.x - a.x) * (y - a.y) / (long double)(b.y - a.y) + a.x;\n            if (xx >= x) in = !in;\n        }\n    }\n    return in;\n}\n\nint eval_exact(const vector<Pt>& poly, const vector<Fish>& fish) {\n    int s = 0;\n    for (auto &f : fish) {\n        if (inside_poly(poly, f.x, f.y)) s += f.t;\n    }\n    return s;\n}\n\nbool legal_basic(const vector<Pt>& p) {\n    if ((int)p.size() < 4 || (int)p.size() > 1000) return false;\n    if (perimeter_poly(p) > 400000) return false;\n\n    set<pair<int,int>> st;\n    for (auto &v : p) {\n        if (v.x < 0 || v.x > LIM || v.y < 0 || v.y > LIM) return false;\n        if (!st.insert({v.x, v.y}).second) return false;\n    }\n    for (int i = 0; i < (int)p.size(); i++) {\n        Pt a = p[i], b = p[(i + 1) % p.size()];\n        if (!(a.x == b.x || a.y == b.y)) return false;\n    }\n    return true;\n}\n\nvector<Pt> rect_poly(int x1, int y1, int x2, int y2) {\n    x1 = max(0, min(LIM, x1));\n    x2 = max(0, min(LIM, x2));\n    y1 = max(0, min(LIM, y1));\n    y2 = max(0, min(LIM, y2));\n    if (x1 > x2) swap(x1,x2);\n    if (y1 > y2) swap(y1,y2);\n    if (x1 == x2) x2 = min(LIM, x1 + 1);\n    if (y1 == y2) y2 = min(LIM, y1 + 1);\n    return {{x1,y1},{x2,y1},{x2,y2},{x1,y2}};\n}\n\nstruct CandComp {\n    int score = 0;\n    int per = 0;\n    int minx = 1e9, maxx = -1;\n    int miny = 1e9, maxy = -1;\n    vector<pair<int,int>> cells;\n};\n\npair<int,int> comp_center(const CandComp& c) {\n    long long sx = 0, sy = 0;\n    for (auto [x,y] : c.cells) {\n        sx += x;\n        sy += y;\n    }\n    if (c.cells.empty()) return {0,0};\n    return {(int)(sx / c.cells.size()), (int)(sy / c.cells.size())};\n}\n\nvector<CandComp> find_components(const vector<vector<unsigned char>>& sel,\n                                const vector<vector<int>>& diff) {\n    int W = sel.size(), H = sel[0].size();\n    vector<vector<unsigned char>> vis(W, vector<unsigned char>(H, 0));\n    vector<CandComp> comps;\n    int dx[4] = {1,-1,0,0};\n    int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n        if (!sel[i][j] || vis[i][j]) continue;\n\n        CandComp cc;\n        queue<pair<int,int>> q;\n        q.push({i,j});\n        vis[i][j] = 1;\n\n        while (!q.empty()) {\n            auto [x,y] = q.front();\n            q.pop();\n\n            cc.cells.push_back({x,y});\n            cc.score += diff[x][y];\n            cc.minx = min(cc.minx, x);\n            cc.maxx = max(cc.maxx, x);\n            cc.miny = min(cc.miny, y);\n            cc.maxy = max(cc.maxy, y);\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= W || ny < 0 || ny >= H || !sel[nx][ny]) {\n                    cc.per++;\n                } else if (!vis[nx][ny]) {\n                    vis[nx][ny] = 1;\n                    q.push({nx,ny});\n                }\n            }\n        }\n\n        comps.push_back(move(cc));\n    }\n\n    sort(comps.begin(), comps.end(), [](const CandComp& a, const CandComp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<Pt> boundary_from_selected(const vector<vector<unsigned char>>& occ, int G) {\n    int W = occ.size(), H = occ[0].size();\n\n    map<pair<int,int>, vector<pair<int,int>>> adj;\n\n    auto add = [&](int x1, int y1, int x2, int y2) {\n        adj[{x1,y1}].push_back({x2,y2});\n    };\n\n    for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n        if (!occ[i][j]) continue;\n\n        int x0 = i * G, x1 = min(LIM, (i + 1) * G);\n        int y0 = j * G, y1 = min(LIM, (j + 1) * G);\n\n        if (j == 0 || !occ[i][j - 1]) add(x0, y0, x1, y0);\n        if (i == W - 1 || !occ[i + 1][j]) add(x1, y0, x1, y1);\n        if (j == H - 1 || !occ[i][j + 1]) add(x1, y1, x0, y1);\n        if (i == 0 || !occ[i - 1][j]) add(x0, y1, x0, y0);\n    }\n\n    if (adj.empty()) return {};\n\n    pair<int,int> start = adj.begin()->first;\n    for (auto &kv : adj) {\n        if (kv.first.second < start.second ||\n            (kv.first.second == start.second && kv.first.first < start.first)) {\n            start = kv.first;\n        }\n    }\n\n    vector<Pt> poly;\n    pair<int,int> cur = start, prev = {-1,-1};\n\n    for (int iter = 0; iter < 30000; iter++) {\n        poly.push_back({cur.first, cur.second});\n\n        auto it = adj.find(cur);\n        if (it == adj.end() || it->second.empty()) break;\n\n        auto &v = it->second;\n        pair<int,int> nxt = v[0];\n        if (v.size() >= 2 && v[0] == prev) nxt = v[1];\n\n        for (int k = 0; k < (int)v.size(); k++) {\n            if (v[k] == nxt) {\n                v.erase(v.begin() + k);\n                break;\n            }\n        }\n\n        prev = cur;\n        cur = nxt;\n        if (cur == start) break;\n    }\n\n    return simplify_poly(poly);\n}\n\nvector<Pt> boundary_from_cells(const vector<pair<int,int>>& cells, int G, int W, int H) {\n    vector<vector<unsigned char>> occ(W, vector<unsigned char>(H, 0));\n    for (auto [i,j] : cells) occ[i][j] = 1;\n    return boundary_from_selected(occ, G);\n}\n\nint grid_perimeter(const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int per = 0;\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        if (i==0 || !occ[i-1][j]) per++;\n        if (i==W-1 || !occ[i+1][j]) per++;\n        if (j==0 || !occ[i][j-1]) per++;\n        if (j==H-1 || !occ[i][j+1]) per++;\n    }\n    return per;\n}\n\nvoid connect_point(vector<vector<unsigned char>>& occ, pair<int,int> a, pair<int,int> b) {\n    int x = a.first, y = a.second;\n    int tx = b.first, ty = b.second;\n\n    while (x != tx) {\n        occ[x][y] = 1;\n        x += (tx > x ? 1 : -1);\n    }\n    while (y != ty) {\n        occ[x][y] = 1;\n        y += (ty > y ? 1 : -1);\n    }\n    occ[x][y] = 1;\n}\n\nvoid add_component(vector<vector<unsigned char>>& occ, const CandComp& c) {\n    for (auto [x,y] : c.cells) occ[x][y] = 1;\n}\n\nvoid prune_leaves(vector<vector<unsigned char>>& occ, const vector<vector<int>>& diff) {\n    int W = occ.size(), H = occ[0].size();\n    queue<pair<int,int>> q;\n\n    auto deg = [&](int x, int y) {\n        int d = 0;\n        if (x > 0 && occ[x-1][y]) d++;\n        if (x+1 < W && occ[x+1][y]) d++;\n        if (y > 0 && occ[x][y-1]) d++;\n        if (y+1 < H && occ[x][y+1]) d++;\n        return d;\n    };\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n        if (occ[i][j] && diff[i][j] <= 0 && deg(i,j) <= 1) q.push({i,j});\n    }\n\n    while (!q.empty()) {\n        auto [x,y] = q.front();\n        q.pop();\n        if (!occ[x][y] || diff[x][y] > 0 || deg(x,y) > 1) continue;\n        occ[x][y] = 0;\n\n        for (auto [nx,ny] : {pair<int,int>{x-1,y}, {x+1,y}, {x,y-1}, {x,y+1}}) {\n            if (nx>=0 && nx<W && ny>=0 && ny<H && occ[nx][ny] && diff[nx][ny] <= 0 && deg(nx,ny) <= 1) {\n                q.push({nx,ny});\n            }\n        }\n    }\n}\n\nint manhattan_comp_to_occ(const CandComp& c, const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int best = 1e9;\n\n    // Fast approximation: compare center to occupied cells, limited scan is okay for ~100x100 grid.\n    auto cen = comp_center(c);\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        best = min(best, abs(cen.first - i) + abs(cen.second - j));\n    }\n    return best;\n}\n\npair<int,int> nearest_occ_cell(pair<int,int> p, const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int best = 1e9;\n    pair<int,int> bp = p;\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        int d = abs(p.first-i) + abs(p.second-j);\n        if (d < best) {\n            best = d;\n            bp = {i,j};\n        }\n    }\n    return bp;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n\n    vector<Fish> fish;\n    fish.reserve(2 * n);\n\n    for (int i = 0; i < 2 * n; i++) {\n        int x, y;\n        cin >> x >> y;\n        fish.push_back({x, y, i < n ? 1 : -1});\n    }\n\n    vector<Pt> best = rect_poly(0,0,1,1);\n    int bestScore = eval_exact(best, fish);\n\n    int exactEvalCount = 0;\n    const int MAX_EXACT_EVAL = 95;\n\n    vector<int> gridSizes = {700, 850, 1000, 1250, 1600, 2000};\n    vector<double> thresholds = {-0.25, -0.10, 0.0, 0.20, 0.45, 0.75};\n\n    for (int G : gridSizes) {\n        int W = (LIM + G) / G;\n        int H = (LIM + G) / G;\n\n        vector<vector<int>> diff(W, vector<int>(H, 0));\n        for (auto &f : fish) {\n            int ix = min(W - 1, f.x / G);\n            int iy = min(H - 1, f.y / G);\n            diff[ix][iy] += f.t;\n        }\n\n        vector<vector<double>> sm(W, vector<double>(H, 0.0));\n        for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n            double s = 0, w = 0;\n            for (int dx=-1; dx<=1; dx++) for (int dy=-1; dy<=1; dy++) {\n                int ni=i+dx, nj=j+dy;\n                if (ni<0 || ni>=W || nj<0 || nj>=H) continue;\n                double ww = (dx==0 && dy==0 ? 4.0 : (dx==0 || dy==0 ? 2.0 : 1.0));\n                s += ww * diff[ni][nj];\n                w += ww;\n            }\n            sm[i][j] = s / w;\n        }\n\n        for (double th : thresholds) {\n            vector<vector<unsigned char>> sel(W, vector<unsigned char>(H, 0));\n            for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n                if (sm[i][j] > th) sel[i][j] = 1;\n            }\n\n            auto comps = find_components(sel, diff);\n\n            int checked = 0;\n            for (auto &cc : comps) {\n                if (cc.score <= 0) break;\n                if (checked >= 4) break;\n                checked++;\n\n                if (1LL * cc.per * G > 400000) continue;\n                if ((int)cc.cells.size() > 3500) continue;\n\n                vector<Pt> poly = boundary_from_cells(cc.cells, G, W, H);\n                poly = simplify_poly(poly);\n                if (!legal_basic(poly)) continue;\n\n                if (cc.score + 50 < bestScore) continue;\n\n                int sc = eval_exact(poly, fish);\n                exactEvalCount++;\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    best = poly;\n                }\n\n                if (exactEvalCount >= MAX_EXACT_EVAL) break;\n            }\n\n            if (exactEvalCount >= MAX_EXACT_EVAL) break;\n\n            // Cost-aware greedy merged candidates.\n            int K = min(12, (int)comps.size());\n            vector<int> usable;\n            for (int i=0;i<K;i++) {\n                if (comps[i].score > 0) usable.push_back(i);\n            }\n\n            vector<double> penalties = {0.0, 0.6, 1.0, 1.5, 2.2};\n\n            for (double pen : penalties) {\n                if (usable.empty()) continue;\n\n                vector<vector<unsigned char>> occ(W, vector<unsigned char>(H, 0));\n                vector<unsigned char> used(comps.size(), 0);\n\n                int start = usable[0];\n                add_component(occ, comps[start]);\n                used[start] = 1;\n\n                for (int step=1; step<=6; step++) {\n                    int bestId = -1;\n                    double bestGain = -1e100;\n\n                    for (int id : usable) if (!used[id]) {\n                        int d = manhattan_comp_to_occ(comps[id], occ);\n                        double gain = comps[id].score - pen * d;\n                        if (gain > bestGain) {\n                            bestGain = gain;\n                            bestId = id;\n                        }\n                    }\n\n                    if (bestId == -1) break;\n                    if (bestGain < -5.0 && step >= 2) break;\n\n                    auto ccen = comp_center(comps[bestId]);\n                    auto nearp = nearest_occ_cell(ccen, occ);\n                    connect_point(occ, nearp, ccen);\n                    add_component(occ, comps[bestId]);\n                    used[bestId] = 1;\n\n                    prune_leaves(occ, diff);\n\n                    int gper = grid_perimeter(occ);\n                    if (1LL * gper * G > 400000) continue;\n\n                    vector<Pt> poly = boundary_from_selected(occ, G);\n                    poly = simplify_poly(poly);\n\n                    if (!legal_basic(poly)) continue;\n\n                    int sc = eval_exact(poly, fish);\n                    exactEvalCount++;\n\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = poly;\n                    }\n\n                    if (exactEvalCount >= MAX_EXACT_EVAL) break;\n                }\n\n                if (exactEvalCount >= MAX_EXACT_EVAL) break;\n            }\n\n            if (exactEvalCount >= MAX_EXACT_EVAL) break;\n        }\n\n        if (exactEvalCount >= MAX_EXACT_EVAL) break;\n    }\n\n    // Coarse prefix-sum rectangle candidates.\n    {\n        const int G = 2000;\n        int W = (LIM + G) / G;\n        int H = (LIM + G) / G;\n        vector<vector<int>> a(W, vector<int>(H, 0));\n        for (auto &f : fish) {\n            a[min(W-1, f.x/G)][min(H-1, f.y/G)] += f.t;\n        }\n\n        vector<vector<int>> ps(W+1, vector<int>(H+1, 0));\n        for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n            ps[i+1][j+1] = ps[i+1][j] + ps[i][j+1] - ps[i][j] + a[i][j];\n        }\n\n        auto sum_rect = [&](int x1,int y1,int x2,int y2) {\n            return ps[x2][y2] - ps[x1][y2] - ps[x2][y1] + ps[x1][y1];\n        };\n\n        vector<tuple<int,int,int,int,int>> cand;\n        cand.reserve(200000);\n\n        for (int x1=0;x1<W;x1++) for (int x2=x1+1;x2<=W;x2++) {\n            int width = (x2 - x1) * G;\n            if (2 * width > 400000) continue;\n            int maxh = 400000 / 2 - width;\n            int maxCellsH = maxh / G;\n            if (maxCellsH <= 0) continue;\n\n            for (int y1=0;y1<H;y1++) {\n                int yMax = min(H, y1 + maxCellsH);\n                for (int y2=y1+1;y2<=yMax;y2++) {\n                    int s = sum_rect(x1,y1,x2,y2);\n                    if (s > 0) cand.push_back({s,x1,y1,x2,y2});\n                }\n            }\n        }\n\n        sort(cand.rbegin(), cand.rend());\n        int lim = min(120, (int)cand.size());\n        for (int k=0;k<lim;k++) {\n            auto [s,x1,y1,x2,y2] = cand[k];\n            vector<Pt> p = rect_poly(x1*G, y1*G, min(LIM,x2*G), min(LIM,y2*G));\n            if (!legal_basic(p)) continue;\n            int sc = eval_exact(p, fish);\n            if (sc > bestScore) {\n                bestScore = sc;\n                best = p;\n            }\n        }\n    }\n\n    best = simplify_poly(best);\n    if (!legal_basic(best)) {\n        best = rect_poly(0,0,1,1);\n    }\n\n    cout << best.size() << '\\n';\n    for (auto &p : best) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Rect {\n    long long w, h;\n};\n\nstruct Op {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Placed {\n    long long x1, y1, x2, y2;\n};\n\nstruct Cand {\n    long long score;\n    vector<Op> ops;\n};\n\nstruct LocalChoice {\n    long double val;\n    Op op;\n    Placed p;\n};\n\nstatic inline bool overlap1d(long long l1, long long r1, long long l2, long long r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nlong long simulate_score(const vector<Op>& ops, const vector<Rect>& rects) {\n    int N = rects.size();\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n\n    long long W = 0, H = 0;\n\n    for (auto &op : ops) {\n        int i = op.p;\n        long long w = rects[i].w;\n        long long h = rects[i].h;\n        if (op.r) swap(w, h);\n\n        long long x = 0, y = 0;\n\n        if (op.d == 'U') {\n            x = (op.b == -1 ? 0 : pos[op.b].x2);\n            y = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(x, x + w, pos[j].x1, pos[j].x2)) {\n                    y = max(y, pos[j].y2);\n                }\n            }\n        } else {\n            y = (op.b == -1 ? 0 : pos[op.b].y2);\n            x = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(y, y + h, pos[j].y1, pos[j].y2)) {\n                    x = max(x, pos[j].x2);\n                }\n            }\n        }\n\n        pos[i] = {x, y, x + w, y + h};\n        used[i] = 1;\n        W = max(W, x + w);\n        H = max(H, y + h);\n    }\n\n    long long penalty = 0;\n    for (int i = 0; i < N; i++) if (!used[i]) {\n        penalty += rects[i].w + rects[i].h;\n    }\n\n    return W + H + penalty;\n}\n\nvector<int> make_rotation_policy(const vector<Rect>& a, int mode, int seed) {\n    int N = a.size();\n    vector<int> r(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        long long w = a[i].w, h = a[i].h;\n\n        if (mode == 0) {\n            r[i] = 0;\n        } else if (mode == 1) {\n            r[i] = (w > h);\n        } else if (mode == 2) {\n            r[i] = (w < h);\n        } else if (mode == 3) {\n            r[i] = ((i + seed) & 1);\n        } else if (mode == 4) {\n            r[i] = ((i / 2 + seed) & 1);\n        } else if (mode == 5) {\n            uint32_t x = (uint32_t)(i * 1103515245u + seed * 12345u + 998244353u);\n            r[i] = (x >> 30) & 1;\n        } else {\n            r[i] = ((i / 3 + seed) & 1);\n        }\n    }\n\n    return r;\n}\n\nPlaced calc_place(const vector<Placed>& pos, const vector<int>& used, const vector<Rect>& a,\n                  int i, int rot, char d, int b) {\n    int N = a.size();\n    long long w = a[i].w;\n    long long h = a[i].h;\n    if (rot) swap(w, h);\n\n    long long x = 0, y = 0;\n    if (d == 'U') {\n        x = (b == -1 ? 0 : pos[b].x2);\n        y = 0;\n        for (int j = 0; j < N; j++) if (used[j]) {\n            if (overlap1d(x, x + w, pos[j].x1, pos[j].x2)) {\n                y = max(y, pos[j].y2);\n            }\n        }\n    } else {\n        y = (b == -1 ? 0 : pos[b].y2);\n        x = 0;\n        for (int j = 0; j < N; j++) if (used[j]) {\n            if (overlap1d(y, y + h, pos[j].y1, pos[j].y2)) {\n                x = max(x, pos[j].x2);\n            }\n        }\n    }\n    return {x, y, x + w, y + h};\n}\n\nlong double eval_ld(long long W, long long H, long double placedArea, int mode) {\n    long double per = (long double)W + H;\n    long double balance = fabsl((long double)W - H);\n    long double boxArea = max((long double)1.0, (long double)W * (long double)H);\n    long double waste = max((long double)0.0, boxArea - placedArea);\n\n    if (mode == 0) {\n        return per;\n    } else if (mode == 1) {\n        return per + 0.25L * balance;\n    } else if (mode == 2) {\n        return max((long double)W, (long double)H) * 2.0L + min((long double)W, (long double)H);\n    } else if (mode == 3) {\n        return per + 0.0000010L * boxArea;\n    } else if (mode == 4) {\n        return per + 0.50L * balance;\n    } else if (mode == 5) {\n        return per + 0.0000006L * boxArea;\n    } else if (mode == 6) {\n        return per + 0.0000015L * waste;\n    } else {\n        return per + 0.15L * balance + 0.0000008L * waste;\n    }\n}\n\nlong long greedy_eval(long long W, long long H, int mode) {\n    return (long long)eval_ld(W, H, 0, mode);\n}\n\nvector<Op> make_vertical_shelves(const vector<Rect>& a, const vector<int>& r, long double targetH, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int last_col_first = -1;\n    int prev = -1;\n    long double curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newCol = false;\n\n        if (i == 0) {\n            newCol = true;\n        } else {\n            long double projected = curH + hh[i];\n\n            if (projected > targetH) {\n                long double before = fabsl(targetH - curH);\n                long double after = fabsl(targetH - projected);\n\n                if (variant == 0) {\n                    newCol = true;\n                } else if (variant == 1) {\n                    newCol = after > before * 0.85L;\n                } else if (variant == 2) {\n                    newCol = after > before * 0.65L;\n                } else {\n                    newCol = after > before;\n                }\n            }\n        }\n\n        if (newCol) {\n            if (last_col_first == -1) ops.push_back({i, r[i], 'U', -1});\n            else ops.push_back({i, r[i], 'U', last_col_first});\n            last_col_first = i;\n            curH = hh[i];\n        } else {\n            ops.push_back({i, r[i], 'L', prev});\n            curH += hh[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\nvector<Op> make_horizontal_shelves(const vector<Rect>& a, const vector<int>& r, long double targetW, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int first_row = -1;\n    int prev = -1;\n    long double curW = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newRow = false;\n\n        if (i == 0) {\n            newRow = true;\n        } else {\n            long double projected = curW + ww[i];\n\n            if (projected > targetW) {\n                long double before = fabsl(targetW - curW);\n                long double after = fabsl(targetW - projected);\n\n                if (variant == 0) {\n                    newRow = true;\n                } else if (variant == 1) {\n                    newRow = after > before * 0.85L;\n                } else if (variant == 2) {\n                    newRow = after > before * 0.65L;\n                } else {\n                    newRow = after > before;\n                }\n            }\n        }\n\n        if (newRow) {\n            if (first_row == -1) ops.push_back({i, r[i], 'L', -1});\n            else ops.push_back({i, r[i], 'L', first_row});\n            first_row = i;\n            curW = ww[i];\n        } else {\n            ops.push_back({i, r[i], 'U', prev});\n            curW += ww[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\nvector<Op> make_greedy_anchor_layout(const vector<Rect>& a, const vector<int>& r, int mode) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long double bestVal = 1e100;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n        for (int b = 0; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            Placed p = calc_place(pos, used, a, i, r[i], d, b);\n            long long nW = max(curW, p.x2);\n            long long nH = max(curH, p.y2);\n\n            long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n            val = val * 1000000.0L + p.x1 + p.y1;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = p;\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n        placedArea += (long double)wi * hi;\n    }\n\n    return ops;\n}\n\nvector<Op> make_free_rotation_greedy_layout(const vector<Rect>& a, int mode, int anchorStyle) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    for (int i = 0; i < N; i++) {\n        Op bestOp{i, 0, 'U', -1};\n        Placed bestP{0, 0, a[i].w, a[i].h};\n        long double bestVal = 1e100;\n\n        vector<int> anchors;\n        anchors.push_back(-1);\n\n        if (anchorStyle == 0) {\n            for (int b = 0; b < i; b++) anchors.push_back(b);\n        } else if (anchorStyle == 1) {\n            for (int b = max(0, i - 20); b < i; b++) anchors.push_back(b);\n            for (int b = 0; b < i; b += 8) anchors.push_back(b);\n        } else {\n            for (int b = max(0, i - 10); b < i; b++) anchors.push_back(b);\n            for (int b = 0; b < i; b += 5) anchors.push_back(b);\n        }\n\n        sort(anchors.begin(), anchors.end());\n        anchors.erase(unique(anchors.begin(), anchors.end()), anchors.end());\n\n        for (int rot = 0; rot < 2; rot++) {\n            long long wi = a[i].w, hi = a[i].h;\n            if (rot) swap(wi, hi);\n\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n                    val = val * 1000000.0L + p.x1 + p.y1;\n\n                    if (val < bestVal) {\n                        bestVal = val;\n                        bestOp = {i, rot, d, b};\n                        bestP = p;\n                    }\n                }\n            }\n        }\n\n        long long bw = a[i].w, bh = a[i].h;\n        if (bestOp.r) swap(bw, bh);\n        placedArea += (long double)bw * bh;\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_target_aspect_free_greedy(const vector<Rect>& a, long double targetAspect, int anchorStyle) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        Op bestOp{i, 0, 'U', -1};\n        Placed bestP{0, 0, a[i].w, a[i].h};\n        long double bestVal = 1e100;\n\n        vector<int> anchors;\n        anchors.push_back(-1);\n\n        if (anchorStyle == 0) {\n            for (int b = 0; b < i; b++) anchors.push_back(b);\n        } else if (anchorStyle == 1) {\n            for (int b = max(0, i - 18); b < i; b++) anchors.push_back(b);\n            for (int b = 0; b < i; b += 7) anchors.push_back(b);\n        } else {\n            for (int b = max(0, i - 9); b < i; b++) anchors.push_back(b);\n            for (int b = 0; b < i; b += 5) anchors.push_back(b);\n        }\n\n        sort(anchors.begin(), anchors.end());\n        anchors.erase(unique(anchors.begin(), anchors.end()), anchors.end());\n\n        for (int rot = 0; rot < 2; rot++) {\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double aspectPenalty = fabsl((long double)nW - targetAspect * (long double)nH);\n                    long double val = (long double)nW + nH + 0.22L * aspectPenalty;\n                    val = val * 1000000.0L + p.x1 + p.y1;\n\n                    if (val < bestVal) {\n                        bestVal = val;\n                        bestOp = {i, rot, d, b};\n                        bestP = p;\n                    }\n                }\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_topk_free_rotation_greedy(const vector<Rect>& a, int mode, int anchorStyle, int seed) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    uint32_t rng = 123456789u + seed * 1000003u;\n\n    auto next_rand = [&]() {\n        rng ^= rng << 13;\n        rng ^= rng >> 17;\n        rng ^= rng << 5;\n        return rng;\n    };\n\n    for (int i = 0; i < N; i++) {\n        vector<int> anchors;\n        anchors.push_back(-1);\n\n        if (anchorStyle == 0) {\n            for (int b = 0; b < i; b++) anchors.push_back(b);\n        } else if (anchorStyle == 1) {\n            for (int b = max(0, i - 18); b < i; b++) anchors.push_back(b);\n            for (int b = 0; b < i; b += 7) anchors.push_back(b);\n        } else {\n            for (int b = max(0, i - 9); b < i; b++) anchors.push_back(b);\n            for (int b = 0; b < i; b += 5) anchors.push_back(b);\n        }\n\n        sort(anchors.begin(), anchors.end());\n        anchors.erase(unique(anchors.begin(), anchors.end()), anchors.end());\n\n        vector<LocalChoice> choices;\n        choices.reserve(anchors.size() * 4);\n\n        for (int rot = 0; rot < 2; rot++) {\n            long long wi = a[i].w, hi = a[i].h;\n            if (rot) swap(wi, hi);\n\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n\n                    long double perturb = 0;\n                    if (seed & 1) perturb += (long double)(p.x1 + p.y1) / 20.0L;\n                    if (seed & 2) perturb += (long double)llabs(nW - nH) / 10.0L;\n                    if (seed & 4) perturb -= (long double)min(p.x1, p.y1) / 30.0L;\n                    if (seed & 8) perturb += 0.0000003L * (long double)nW * nH;\n\n                    val = (val + perturb) * 1000000.0L + p.x1 + p.y1;\n\n                    choices.push_back({val, {i, rot, d, b}, p});\n                }\n            }\n        }\n\n        sort(choices.begin(), choices.end(), [](const LocalChoice& x, const LocalChoice& y) {\n            return x.val < y.val;\n        });\n\n        int topK = min((int)choices.size(), 1 + (seed % 4));\n        int pick = 0;\n        if (topK > 1 && i > 1) {\n            uint32_t rv = next_rand();\n            if ((rv & 7) == 0) pick = min(topK - 1, 2);\n            else if ((rv & 3) == 0) pick = min(topK - 1, 1);\n            else pick = 0;\n        }\n\n        auto ch = choices[pick];\n\n        long long bw = a[i].w, bh = a[i].h;\n        if (ch.op.r) swap(bw, bh);\n        placedArea += (long double)bw * bh;\n\n        ops.push_back(ch.op);\n        pos[i] = ch.p;\n        used[i] = 1;\n        curW = max(curW, ch.p.x2);\n        curH = max(curH, ch.p.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_mixed_layout(const vector<Rect>& a, const vector<int>& r, int blockSize, int mode) {\n    int N = a.size();\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long double bestVal = 1e100;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n\n        int start = max(0, i - blockSize);\n        for (int b = start; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (int b = 0; b < i; b += max(1, blockSize / 2)) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            Placed p = calc_place(pos, used, a, i, r[i], d, b);\n            long long nW = max(curW, p.x2);\n            long long nH = max(curH, p.y2);\n\n            long double val = eval_ld(nW, nH, 0, mode);\n            val = val * 1000000.0L + p.x1 + p.y1;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = p;\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n\n    vector<Rect> a(N);\n    for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n    long double area = 0;\n    for (auto &e : a) area += (long double)e.w * (long double)e.h;\n    long double root = sqrt(area);\n\n    vector<Cand> cands;\n    cands.reserve(9000);\n\n    auto add_candidate = [&](const vector<Op>& ops) {\n        long long sc = simulate_score(ops, a);\n        cands.push_back({sc, ops});\n    };\n\n    // Shelf candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 8; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n\n            for (int k = 0; k < 45; k++) {\n                long double factor = 0.45L + 0.035L * k;\n                for (int var = 0; var < 4; var++) {\n                    add_candidate(make_vertical_shelves(a, r, root * factor, var));\n                    add_candidate(make_horizontal_shelves(a, r, root * factor, var));\n                }\n            }\n        }\n    }\n\n    // Fixed-rotation greedy candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 12; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bm = 0; bm < 6; bm++) {\n                add_candidate(make_greedy_anchor_layout(a, r, bm));\n            }\n        }\n    }\n\n    // Free-rotation greedy candidates.\n    for (int bm = 0; bm < 8; bm++) {\n        for (int style = 0; style < 3; style++) {\n            add_candidate(make_free_rotation_greedy_layout(a, bm, style));\n        }\n    }\n\n    // Target-aspect free-rotation greedy.\n    vector<long double> aspects = {0.70L, 0.82L, 0.92L, 1.0L, 1.08L, 1.22L, 1.42L};\n    for (long double asp : aspects) {\n        for (int style = 0; style < 3; style++) {\n            add_candidate(make_target_aspect_free_greedy(a, asp, style));\n        }\n    }\n\n    // Top-k perturbed free-rotation greedy candidates.\n    for (int seed = 0; seed < 24; seed++) {\n        int bm = seed % 8;\n        int style = (seed / 2) % 3;\n        add_candidate(make_topk_free_rotation_greedy(a, bm, style, seed));\n    }\n\n    // Mixed restricted-anchor candidates.\n    vector<int> blockSizes = {4, 6, 8, 10, 12, 15, 20, 30};\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 6; seed++) {\n            if (timer.elapsed() > 2.45) break;\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bs : blockSizes) {\n                for (int bm = 0; bm < 4; bm++) {\n                    add_candidate(make_mixed_layout(a, r, bs, bm));\n                }\n            }\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& x, const Cand& y) {\n        return x.score < y.score;\n    });\n\n    vector<Cand> uniq;\n    uniq.reserve(cands.size());\n\n    auto signature = [](const vector<Op>& ops) {\n        string s;\n        s.reserve(ops.size() * 8);\n        for (auto &op : ops) {\n            s += char(op.r + '0');\n            s += op.d;\n            int b = op.b + 1;\n            s += char(33 + (b % 90));\n            s += char(33 + ((b / 90) % 90));\n            s += ',';\n        }\n        return s;\n    };\n\n    unordered_set<string> seen;\n    for (auto &c : cands) {\n        string sig = signature(c.ops);\n        if (seen.insert(sig).second) {\n            uniq.push_back(std::move(c));\n            if ((int)uniq.size() >= max(T * 4, 500)) break;\n        }\n    }\n\n    if (uniq.empty()) {\n        vector<int> r(N, 0);\n        vector<Op> ops = make_vertical_shelves(a, r, root, 0);\n        uniq.push_back({simulate_score(ops, a), ops});\n    }\n\n    for (int t = 0; t < T; t++) {\n        const vector<Op>& ops = uniq[t % uniq.size()].ops;\n\n        cout << ops.size() << '\\n';\n        for (auto &op : ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        if (!cin) return 0;\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>> g;\n    vector<pair<int,int>> xy;\n\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n    const double TL = 1.92;\n\n    Solver() : rng(123456789) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    double rnd(double l, double r) {\n        return uniform_real_distribution<double>(l, r)(rng);\n    }\n\n    long long calcScore(const vector<int>& par) {\n        vector<vector<int>> ch(n);\n        vector<int> roots;\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -1) {\n                roots.push_back(v);\n            } else {\n                ch[par[v]].push_back(v);\n            }\n        }\n\n        long long score = 1;\n        vector<int> dep(n, -1);\n        queue<int> q;\n\n        for (int r : roots) {\n            dep[r] = 0;\n            q.push(r);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            score += 1LL * (dep[v] + 1) * A[v];\n\n            for (int to : ch[v]) {\n                dep[to] = dep[v] + 1;\n                q.push(to);\n            }\n        }\n\n        return score;\n    }\n\n    vector<int> bfsConstruct(double lowBias, double noise, bool randomOrder) {\n        vector<vector<int>> reach(n);\n\n        for (int s = 0; s < n; s++) {\n            vector<int> d(n, -1);\n            queue<int> q;\n            d[s] = 0;\n            q.push(s);\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                reach[s].push_back(v);\n\n                if (d[v] == h) continue;\n\n                for (int to : g[v]) {\n                    if (d[to] == -1) {\n                        d[to] = d[v] + 1;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        vector<char> covered(n, 0), isRoot(n, 0);\n        vector<int> roots;\n        int coveredCnt = 0;\n\n        while (coveredCnt < n) {\n            int best = -1;\n            double bestVal = -1e100;\n\n            vector<int> cand(n);\n            iota(cand.begin(), cand.end(), 0);\n            if (randomOrder) shuffle(cand.begin(), cand.end(), rng);\n\n            for (int v : cand) {\n                if (isRoot[v]) continue;\n\n                int gain = 0;\n                int gainW = 0;\n\n                for (int u : reach[v]) {\n                    if (!covered[u]) {\n                        gain++;\n                        gainW += A[u];\n                    }\n                }\n\n                if (gain == 0) continue;\n\n                double val =\n                    gain * 1000.0\n                    - lowBias * A[v]\n                    + 0.04 * gainW\n                    + rnd(-noise, noise);\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = v;\n                }\n            }\n\n            if (best == -1) {\n                for (int v = 0; v < n; v++) {\n                    if (!covered[v]) {\n                        best = v;\n                        break;\n                    }\n                }\n            }\n\n            roots.push_back(best);\n            isRoot[best] = 1;\n\n            for (int u : reach[best]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        vector<int> dist(n, INT_MAX), par(n, -2);\n\n        struct Node {\n            double key;\n            int v;\n            bool operator<(const Node& other) const {\n                return key > other.key;\n            }\n        };\n\n        priority_queue<Node> pq;\n\n        for (int r : roots) {\n            dist[r] = 0;\n            par[r] = -1;\n            pq.push({0.003 * A[r], r});\n        }\n\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n\n            int v = cur.v;\n            if (dist[v] == h) continue;\n\n            vector<int> ns = g[v];\n            shuffle(ns.begin(), ns.end(), rng);\n\n            for (int to : ns) {\n                if (dist[to] == INT_MAX) {\n                    dist[to] = dist[v] + 1;\n                    par[to] = v;\n\n                    double key =\n                        dist[to]\n                        + 0.014 * (100 - A[to])\n                        + rnd(0.0, 0.04);\n\n                    pq.push({key, to});\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    vector<int> deepDfsConstruct(double rootBias, double childBias, double randomness) {\n        vector<int> par(n, -2), dep(n, -1);\n        vector<char> used(n, 0);\n        int usedCnt = 0;\n\n        vector<pair<double,int>> key;\n        key.reserve(n);\n\n        for (int v = 0; v < n; v++) {\n            key.push_back({A[v] * rootBias + rnd(0.0, randomness), v});\n        }\n\n        sort(key.begin(), key.end());\n\n        vector<int> order;\n        order.reserve(n);\n        for (auto [_, v] : key) order.push_back(v);\n\n        int ptr = 0;\n\n        while (usedCnt < n) {\n            int root = -1;\n\n            while (ptr < n && used[order[ptr]]) ptr++;\n            if (ptr < n) root = order[ptr];\n\n            if (root == -1) {\n                for (int v = 0; v < n; v++) {\n                    if (!used[v]) {\n                        root = v;\n                        break;\n                    }\n                }\n            }\n\n            used[root] = 1;\n            usedCnt++;\n            par[root] = -1;\n            dep[root] = 0;\n\n            vector<int> stk;\n            stk.push_back(root);\n\n            while (!stk.empty()) {\n                int v = stk.back();\n\n                if (dep[v] >= h) {\n                    stk.pop_back();\n                    continue;\n                }\n\n                vector<int> cand;\n                for (int to : g[v]) {\n                    if (!used[to]) cand.push_back(to);\n                }\n\n                if (cand.empty()) {\n                    stk.pop_back();\n                    continue;\n                }\n\n                int best = -1;\n                double bestScore = -1e100;\n\n                for (int to : cand) {\n                    int freeNei = 0;\n                    for (int w : g[to]) {\n                        if (!used[w]) freeNei++;\n                    }\n\n                    double sc =\n                        childBias * A[to]\n                        + 4.0 * freeNei\n                        + 12.0 * dep[v]\n                        + rnd(0.0, randomness);\n\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = to;\n                    }\n                }\n\n                used[best] = 1;\n                usedCnt++;\n                par[best] = v;\n                dep[best] = dep[v] + 1;\n                stk.push_back(best);\n\n                // Safe occasional branch.\n                if (dep[v] + 1 <= h && rnd(0.0, 1.0) < 0.15) {\n                    vector<int> cand2;\n                    for (int to : g[v]) {\n                        if (!used[to]) cand2.push_back(to);\n                    }\n\n                    if (!cand2.empty()) {\n                        int b2 = -1;\n                        double bs2 = -1e100;\n\n                        for (int to : cand2) {\n                            double sc =\n                                0.7 * childBias * A[to]\n                                + rnd(0.0, randomness);\n\n                            if (sc > bs2) {\n                                bs2 = sc;\n                                b2 = to;\n                            }\n                        }\n\n                        used[b2] = 1;\n                        usedCnt++;\n                        par[b2] = v;\n                        dep[b2] = dep[v] + 1;\n                        stk.push_back(b2);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    vector<int> greedyLayerConstruct(double randomness) {\n        vector<int> par(n, -2), dep(n, -1);\n        vector<char> used(n, 0);\n        int usedCnt = 0;\n\n        while (usedCnt < n) {\n            int root = -1;\n            double bestRootScore = 1e100;\n\n            for (int v = 0; v < n; v++) {\n                if (used[v]) continue;\n\n                int un = 0;\n                for (int to : g[v]) {\n                    if (!used[to]) un++;\n                }\n\n                double sc =\n                    A[v] * 5.0\n                    - un * 8.0\n                    + rnd(0.0, randomness);\n\n                if (sc < bestRootScore) {\n                    bestRootScore = sc;\n                    root = v;\n                }\n            }\n\n            used[root] = 1;\n            usedCnt++;\n            par[root] = -1;\n            dep[root] = 0;\n\n            vector<int> frontier = {root};\n\n            for (int d = 0; d < h && !frontier.empty(); d++) {\n                vector<pair<double, pair<int,int>>> cand;\n\n                for (int v : frontier) {\n                    for (int to : g[v]) {\n                        if (!used[to]) {\n                            int un = 0;\n                            for (int w : g[to]) {\n                                if (!used[w]) un++;\n                            }\n\n                            double sc =\n                                A[to] * (1.0 + 0.25 * d)\n                                + 2.5 * un\n                                + rnd(0.0, randomness);\n\n                            cand.push_back({-sc, {v, to}});\n                        }\n                    }\n                }\n\n                if (cand.empty()) break;\n\n                sort(cand.begin(), cand.end());\n\n                vector<int> next;\n\n                for (auto &e : cand) {\n                    int p = e.second.first;\n                    int v = e.second.second;\n\n                    if (used[v]) continue;\n\n                    used[v] = 1;\n                    usedCnt++;\n                    par[v] = p;\n                    dep[v] = d + 1;\n                    next.push_back(v);\n                }\n\n                frontier.swap(next);\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    vector<int> rerootTrees(const vector<int>& par0) {\n        vector<vector<int>> treeAdj(n);\n\n        for (int v = 0; v < n; v++) {\n            if (par0[v] != -1) {\n                treeAdj[v].push_back(par0[v]);\n                treeAdj[par0[v]].push_back(v);\n            }\n        }\n\n        vector<int> compId(n, -1);\n        vector<vector<int>> comps;\n\n        for (int s = 0; s < n; s++) {\n            if (compId[s] != -1) continue;\n\n            int id = (int)comps.size();\n            comps.push_back({});\n\n            queue<int> q;\n            q.push(s);\n            compId[s] = id;\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                comps.back().push_back(v);\n\n                for (int to : treeAdj[v]) {\n                    if (compId[to] == -1) {\n                        compId[to] = id;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        vector<int> newPar(n, -2);\n        vector<int> d(n);\n\n        for (auto &comp : comps) {\n            int bestRoot = comp[0];\n            long long bestVal = LLONG_MIN;\n\n            for (int r : comp) {\n                fill(d.begin(), d.end(), -1);\n\n                queue<int> q;\n                d[r] = 0;\n                q.push(r);\n\n                int mx = 0;\n                long long val = 0;\n\n                while (!q.empty()) {\n                    int v = q.front();\n                    q.pop();\n\n                    mx = max(mx, d[v]);\n                    val += 1LL * (d[v] + 1) * A[v];\n\n                    for (int to : treeAdj[v]) {\n                        if (d[to] == -1) {\n                            d[to] = d[v] + 1;\n                            q.push(to);\n                        }\n                    }\n                }\n\n                if (mx <= h && val > bestVal) {\n                    bestVal = val;\n                    bestRoot = r;\n                }\n            }\n\n            vector<char> seen(n, 0);\n            queue<int> q;\n\n            newPar[bestRoot] = -1;\n            seen[bestRoot] = 1;\n            q.push(bestRoot);\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                for (int to : treeAdj[v]) {\n                    if (!seen[to]) {\n                        seen[to] = 1;\n                        newPar[to] = v;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (newPar[v] == -2) newPar[v] = -1;\n        }\n\n        return newPar;\n    }\n\n    void solve() {\n        cin >> n >> m >> h;\n\n        A.resize(n);\n        for (int i = 0; i < n; i++) cin >> A[i];\n\n        g.assign(n, {});\n        for (int i = 0; i < m; i++) {\n            int u, v;\n            cin >> u >> v;\n            g[u].push_back(v);\n            g[v].push_back(u);\n        }\n\n        xy.resize(n);\n        for (int i = 0; i < n; i++) {\n            cin >> xy[i].first >> xy[i].second;\n        }\n\n        st = chrono::steady_clock::now();\n\n        vector<int> bestPar(n, -1);\n        long long bestScore = -1;\n\n        int iter = 0;\n\n        while (elapsed() < TL) {\n            vector<int> par;\n\n            int mode = iter % 6;\n\n            if (mode == 0 || mode == 1) {\n                double lowBias = 8.0 + (iter % 11) * 7.0;\n                double noise = 100.0 + (iter % 9) * 250.0;\n                par = bfsConstruct(lowBias, noise, iter & 1);\n            } else if (mode == 2 || mode == 3 || mode == 4) {\n                double rootBias = 2.0 + (iter % 7);\n                double childBias = 8.0 + (iter % 13) * 2.0;\n                double randomness = 20.0 + (iter % 17) * 12.0;\n                par = deepDfsConstruct(rootBias, childBias, randomness);\n            } else {\n                double randomness = 20.0 + (iter % 19) * 15.0;\n                par = greedyLayerConstruct(randomness);\n            }\n\n            par = rerootTrees(par);\n\n            long long sc = calcScore(par);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPar = par;\n            }\n\n            iter++;\n        }\n\n        for (int i = 0; i < n; i++) {\n            if (i) cout << ' ';\n            cout << bestPar[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char d;\n    int p;\n};\n\nstruct Cycle {\n    char d;\n    int p;\n    int k;\n    int cost;\n    unsigned long long mask;\n};\n\nint N;\nvector<string> initial_board;\nvector<pair<int,int>> oni;\nint oid[20][20];\n\nchar rev_dir(char d) {\n    if (d == 'U') return 'D';\n    if (d == 'D') return 'U';\n    if (d == 'L') return 'R';\n    return 'L';\n}\n\nint popcnt(unsigned long long x) {\n    return __builtin_popcountll(x);\n}\n\nvector<Operation> cycles_to_ops(const vector<Cycle>& selected) {\n    vector<Operation> ops;\n    for (const Cycle& c : selected) {\n        char r = rev_dir(c.d);\n        for (int t = 0; t < c.k; t++) ops.push_back({c.d, c.p});\n        for (int t = 0; t < c.k; t++) ops.push_back({r, c.p});\n    }\n    return ops;\n}\n\nvector<Cycle> enumerate_cycles_from_board(const vector<string>& board) {\n    vector<Cycle> cycles;\n\n    auto add = [&](char d, int p, int k, unsigned long long mask) {\n        if (mask == 0) return;\n        cycles.push_back({d, p, k, 2 * k, mask});\n    };\n\n    // Up\n    for (int j = 0; j < N; j++) {\n        bool block = false;\n        unsigned long long mask = 0;\n        for (int i = 0; i < N; i++) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('U', j, i + 1, mask);\n        }\n    }\n\n    // Down\n    for (int j = 0; j < N; j++) {\n        bool block = false;\n        unsigned long long mask = 0;\n        for (int i = N - 1; i >= 0; i--) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('D', j, N - i, mask);\n        }\n    }\n\n    // Left\n    for (int i = 0; i < N; i++) {\n        bool block = false;\n        unsigned long long mask = 0;\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('L', i, j + 1, mask);\n        }\n    }\n\n    // Right\n    for (int i = 0; i < N; i++) {\n        bool block = false;\n        unsigned long long mask = 0;\n        for (int j = N - 1; j >= 0; j--) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('R', i, N - j, mask);\n        }\n    }\n\n    return cycles;\n}\n\nvector<Operation> dynamic_greedy() {\n    vector<string> board = initial_board;\n    vector<Operation> ops;\n\n    auto count_oni = [&]() {\n        int c = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (board[i][j] == 'x') c++;\n            }\n        }\n        return c;\n    };\n\n    auto erase_mask = [&](unsigned long long mask) {\n        for (int id = 0; id < (int)oni.size(); id++) {\n            if ((mask >> id) & 1ULL) {\n                auto [i, j] = oni[id];\n                board[i][j] = '.';\n            }\n        }\n    };\n\n    while (count_oni() > 0) {\n        vector<Cycle> cycles = enumerate_cycles_from_board(board);\n\n        int best = -1;\n\n        for (int i = 0; i < (int)cycles.size(); i++) {\n            int gain = popcnt(cycles[i].mask);\n            if (gain == 0) continue;\n\n            if (best == -1) {\n                best = i;\n            } else {\n                int bgain = popcnt(cycles[best].mask);\n\n                long long lhs = 1LL * gain * cycles[best].cost;\n                long long rhs = 1LL * bgain * cycles[i].cost;\n\n                if (lhs > rhs ||\n                    (lhs == rhs && gain > bgain) ||\n                    (lhs == rhs && gain == bgain && cycles[i].cost < cycles[best].cost)) {\n                    best = i;\n                }\n            }\n        }\n\n        if (best == -1) break;\n\n        Cycle c = cycles[best];\n        erase_mask(c.mask);\n\n        char r = rev_dir(c.d);\n        for (int t = 0; t < c.k; t++) ops.push_back({c.d, c.p});\n        for (int t = 0; t < c.k; t++) ops.push_back({r, c.p});\n    }\n\n    return ops;\n}\n\nvector<Cycle> remove_redundant(vector<Cycle> selected, unsigned long long ALL) {\n    bool changed = true;\n\n    while (changed) {\n        changed = false;\n\n        for (int i = 0; i < (int)selected.size(); i++) {\n            unsigned long long cov = 0;\n            for (int j = 0; j < (int)selected.size(); j++) {\n                if (i == j) continue;\n                cov |= selected[j].mask;\n            }\n\n            if (cov == ALL) {\n                selected.erase(selected.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    return selected;\n}\n\nint total_cost(const vector<Cycle>& v) {\n    int s = 0;\n    for (auto& c : v) s += c.cost;\n    return s;\n}\n\nvector<Operation> randomized_set_cover(const vector<Operation>& baseline_ops) {\n    vector<Cycle> cycles = enumerate_cycles_from_board(initial_board);\n\n    // Dominance filtering: safe for set cover.\n    vector<char> bad(cycles.size(), false);\n    for (int i = 0; i < (int)cycles.size(); i++) {\n        for (int j = 0; j < (int)cycles.size(); j++) {\n            if (i == j) continue;\n            if ((cycles[i].mask & ~cycles[j].mask) == 0 &&\n                cycles[i].cost >= cycles[j].cost) {\n                bad[i] = true;\n                break;\n            }\n        }\n    }\n\n    vector<Cycle> filtered;\n    for (int i = 0; i < (int)cycles.size(); i++) {\n        if (!bad[i]) filtered.push_back(cycles[i]);\n    }\n    cycles.swap(filtered);\n\n    int M = oni.size();\n    unsigned long long ALL = (M == 64 ? ~0ULL : ((1ULL << M) - 1));\n\n    mt19937 rng(1234567);\n\n    vector<Cycle> best_sel;\n    int best_cost = (int)baseline_ops.size();\n\n    auto greedy_trial = [&](double noise) {\n        unsigned long long covered = 0;\n        vector<Cycle> sel;\n\n        while (covered != ALL) {\n            vector<pair<double,int>> cand;\n\n            for (int i = 0; i < (int)cycles.size(); i++) {\n                unsigned long long gainMask = cycles[i].mask & ~covered;\n                int gain = popcnt(gainMask);\n                if (gain == 0) continue;\n\n                double value = (double)gain / cycles[i].cost;\n                if (noise > 0) {\n                    double r = uniform_real_distribution<double>(0.0, 1.0)(rng);\n                    value *= 1.0 + noise * (r - 0.5);\n                }\n\n                cand.push_back({value, i});\n            }\n\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), greater<pair<double,int>>());\n\n            int chooseRank = 0;\n            if (noise > 0 && cand.size() >= 3) {\n                int lim = min<int>(5, cand.size());\n                chooseRank = uniform_int_distribution<int>(0, lim - 1)(rng);\n            }\n\n            int idx = cand[chooseRank].second;\n            sel.push_back(cycles[idx]);\n            covered |= cycles[idx].mask;\n        }\n\n        if (covered != ALL) return;\n\n        sel = remove_redundant(sel, ALL);\n\n        int cst = total_cost(sel);\n        if (cst < best_cost) {\n            best_cost = cst;\n            best_sel = sel;\n        }\n    };\n\n    // Deterministic greedy.\n    greedy_trial(0.0);\n\n    // Randomized trials; small but enough for 2 sec and 150 cases.\n    for (int t = 0; t < 700; t++) {\n        double noise = 0.25 + 0.75 * (t % 10) / 9.0;\n        greedy_trial(noise);\n    }\n\n    if (best_sel.empty()) return baseline_ops;\n\n    vector<Operation> ops = cycles_to_ops(best_sel);\n\n    if ((int)ops.size() < (int)baseline_ops.size() && (int)ops.size() <= 4 * N * N) {\n        return ops;\n    }\n    return baseline_ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    initial_board.resize(N);\n\n    memset(oid, -1, sizeof(oid));\n\n    for (int i = 0; i < N; i++) cin >> initial_board[i];\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (initial_board[i][j] == 'x') {\n                oid[i][j] = (int)oni.size();\n                oni.push_back({i, j});\n            }\n        }\n    }\n\n    vector<Operation> baseline = dynamic_greedy();\n    vector<Operation> answer = randomized_set_cover(baseline);\n\n    if ((int)answer.size() > 4 * N * N) {\n        answer = baseline;\n    }\n\n    for (auto [d, p] : answer) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 100;\nstatic constexpr int L = 500000;\nstatic constexpr int SHORT_L = 100000;\n\nstruct Plan {\n    int a[N];\n    int b[N];\n};\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 1234567891234567ULL) : x(seed) {}\n\n    inline uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n\n    inline double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\ninline int eval_plan_full(const Plan& p, const int T[N]) {\n    static int cnt[N];\n    memset(cnt, 0, sizeof(cnt));\n\n    int x = 0;\n\n    for (int week = 0; week < L; week++) {\n        int c = ++cnt[x];\n        x = (c & 1) ? p.a[x] : p.b[x];\n    }\n\n    int err = 0;\n    for (int i = 0; i < N; i++) {\n        err += abs(cnt[i] - T[i]);\n    }\n\n    return err;\n}\n\ninline int eval_plan_short(const Plan& p, const int Tshort[N]) {\n    static int cnt[N];\n    memset(cnt, 0, sizeof(cnt));\n\n    int x = 0;\n\n    for (int week = 0; week < SHORT_L; week++) {\n        int c = ++cnt[x];\n        x = (c & 1) ? p.a[x] : p.b[x];\n    }\n\n    int err = 0;\n    for (int i = 0; i < N; i++) {\n        err += abs(cnt[i] - Tshort[i]);\n    }\n\n    return err;\n}\n\nint sample_weighted(const int pref[N], RNG& rng) {\n    int v = rng.next_int(1, L);\n\n    int lo = 0;\n    int hi = N - 1;\n\n    while (lo < hi) {\n        int mid = (lo + hi) >> 1;\n        if (pref[mid] >= v) hi = mid;\n        else lo = mid + 1;\n    }\n\n    return lo;\n}\n\nPlan random_plan(const int pref[N], RNG& rng) {\n    Plan p;\n\n    for (int i = 0; i < N; i++) {\n        p.a[i] = sample_weighted(pref, rng);\n        p.b[i] = sample_weighted(pref, rng);\n    }\n\n    return p;\n}\n\nPlan weighted_balance_plan(const int T[N], RNG& rng, double noise) {\n    struct Item {\n        int src;\n        double w;\n        double key;\n    };\n\n    Item items[200];\n    int ptr = 0;\n\n    for (int i = 0; i < N; i++) {\n        double w = T[i] * 0.5;\n\n        double r1 = 1.0 + noise * (rng.next_double() - 0.5);\n        double r2 = 1.0 + noise * (rng.next_double() - 0.5);\n\n        items[ptr++] = {i, w, w * r1};\n        items[ptr++] = {i, w, w * r2};\n    }\n\n    sort(items, items + 200, [](const Item& x, const Item& y) {\n        return x.key > y.key;\n    });\n\n    double load[N];\n    int outs[N][2];\n    int deg[N];\n\n    for (int i = 0; i < N; i++) {\n        load[i] = 0.0;\n        deg[i] = 0;\n        outs[i][0] = outs[i][1] = 0;\n    }\n\n    for (int idx = 0; idx < 200; idx++) {\n        const auto& it = items[idx];\n\n        int best = 0;\n        double best_score = -1e100;\n\n        for (int j = 0; j < N; j++) {\n            double rem = T[j] - load[j];\n            double score = rem + noise * 2500.0 * (rng.next_double() - 0.5);\n\n            if (score > best_score) {\n                best_score = score;\n                best = j;\n            }\n        }\n\n        load[best] += it.w;\n\n        int s = it.src;\n        if (deg[s] < 2) {\n            outs[s][deg[s]++] = best;\n        }\n    }\n\n    Plan p;\n\n    for (int i = 0; i < N; i++) {\n        while (deg[i] < 2) {\n            outs[i][deg[i]++] = rng.next_int(0, N - 1);\n        }\n\n        if (rng.next_int(0, 1)) {\n            swap(outs[i][0], outs[i][1]);\n        }\n\n        p.a[i] = outs[i][0];\n        p.b[i] = outs[i][1];\n    }\n\n    return p;\n}\n\nPlan swap_mutate_plan(const Plan& base, RNG& rng, int changes) {\n    Plan p = base;\n\n    for (int k = 0; k < changes; k++) {\n        int i1 = rng.next_int(0, N - 1);\n        int i2 = rng.next_int(0, N - 1);\n        int s1 = rng.next_int(0, 1);\n        int s2 = rng.next_int(0, 1);\n\n        int* e1 = (s1 == 0 ? &p.a[i1] : &p.b[i1]);\n        int* e2 = (s2 == 0 ? &p.a[i2] : &p.b[i2]);\n\n        swap(*e1, *e2);\n    }\n\n    return p;\n}\n\nPlan flip_mutate_plan(const Plan& base, RNG& rng, int changes) {\n    Plan p = base;\n\n    for (int k = 0; k < changes; k++) {\n        int i = rng.next_int(0, N - 1);\n        swap(p.a[i], p.b[i]);\n    }\n\n    return p;\n}\n\nPlan random_edge_mutate_plan(const Plan& base, const int pref[N], RNG& rng, int changes) {\n    Plan p = base;\n\n    for (int k = 0; k < changes; k++) {\n        int i = rng.next_int(0, N - 1);\n        int side = rng.next_int(0, 1);\n        int to = sample_weighted(pref, rng);\n\n        if (side == 0) p.a[i] = to;\n        else p.b[i] = to;\n    }\n\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n\n    int T[N];\n    int pref[N];\n    int Tshort[N];\n\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n    }\n\n    for (int i = 0; i < N; i++) {\n        pref[i] = T[i] + (i ? pref[i - 1] : 0);\n        Tshort[i] = (int)llround((long long)T[i] * SHORT_L / (double)L);\n    }\n\n    RNG rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    Plan best;\n    for (int i = 0; i < N; i++) {\n        best.a[i] = best.b[i] = 0;\n    }\n\n    int best_err = eval_plan_full(best, T);\n    int best_short = eval_plan_short(best, Tshort);\n\n    auto start = chrono::steady_clock::now();\n\n    int iter = 0;\n    int full_evals = 1;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n\n        if (elapsed > 1.88) break;\n\n        Plan cand;\n\n        int mode = iter % 18;\n\n        if (mode <= 13) {\n            double noise;\n\n            switch (mode) {\n                case 0: noise = 0.00; break;\n                case 1: noise = 0.01; break;\n                case 2: noise = 0.02; break;\n                case 3: noise = 0.035; break;\n                case 4: noise = 0.05; break;\n                case 5: noise = 0.075; break;\n                case 6: noise = 0.10; break;\n                case 7: noise = 0.14; break;\n                case 8: noise = 0.20; break;\n                case 9: noise = 0.28; break;\n                case 10: noise = 0.38; break;\n                case 11: noise = 0.52; break;\n                case 12: noise = 0.75; break;\n                default: noise = 1.00; break;\n            }\n\n            cand = weighted_balance_plan(T, rng, noise);\n        } else if (mode == 14) {\n            cand = flip_mutate_plan(best, rng, 1 + rng.next_int(0, 4));\n        } else if (mode == 15) {\n            cand = swap_mutate_plan(best, rng, 1 + rng.next_int(0, 3));\n        } else if (mode == 16) {\n            cand = random_edge_mutate_plan(best, pref, rng, 1);\n        } else {\n            cand = random_plan(pref, rng);\n        }\n\n        int se = eval_plan_short(cand, Tshort);\n\n        bool do_full = false;\n\n        if (iter < 25) {\n            do_full = true;\n        } else if (se <= best_short + 1800) {\n            do_full = true;\n        } else if ((iter & 15) == 0 && se <= best_short + 4500) {\n            do_full = true;\n        }\n\n        if (do_full) {\n            int err = eval_plan_full(cand, T);\n            full_evals++;\n\n            if (err < best_err) {\n                best_err = err;\n                best = cand;\n                best_short = se;\n            }\n        }\n\n        iter++;\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    bool operator<(const Edge& o) const {\n        if (w != o.w) return w < o.w;\n        if (u != o.u) return u < o.u;\n        return v < o.v;\n    }\n};\n\nstatic uint64_t rng_state = 3141592653589793ULL;\n\nuint64_t rng64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\nint rnd_int(int l, int r) {\n    return l + (int)(rng64() % (uint64_t)(r - l + 1));\n}\ndouble rnd01() {\n    return (rng64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<double> x(N), y(N), rad(N), side(N);\n\n    double avgSide = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n        x[i] = 0.5 * (lx[i] + rx[i]);\n        y[i] = 0.5 * (ly[i] + ry[i]);\n\n        double wx = rx[i] - lx[i];\n        double wy = ry[i] - ly[i];\n\n        side[i] = max(wx, wy);\n        rad[i] = 0.5 * sqrt(wx * wx + wy * wy);\n        avgSide += side[i];\n    }\n\n    avgSide /= N;\n\n    double uncertainRatio = min(1.0, max(0.0, avgSide / 1800.0));\n    double centerWeight = 0.82 - 0.18 * uncertainRatio;\n    double minWeight = 1.0 - centerWeight;\n    double uncertaintyCoef = 0.045 + 0.075 * uncertainRatio;\n\n    vector<vector<double>> cd(N, vector<double>(N, 0.0));\n    vector<vector<double>> wd(N, vector<double>(N, 0.0));\n    vector<vector<int>> iw(N, vector<int>(N, 0));\n    vector<vector<int>> nearest(N);\n\n    for (int i = 0; i < N; i++) {\n        nearest[i].reserve(N - 1);\n        for (int j = 0; j < N; j++) if (i != j) nearest[i].push_back(j);\n    }\n\n    auto rectMinDist = [&](int a, int b) -> double {\n        double dx = 0.0;\n        if (rx[a] < lx[b]) dx = lx[b] - rx[a];\n        else if (rx[b] < lx[a]) dx = lx[a] - rx[b];\n\n        double dy = 0.0;\n        if (ry[a] < ly[b]) dy = ly[b] - ry[a];\n        else if (ry[b] < ly[a]) dy = ly[a] - ry[b];\n\n        return sqrt(dx * dx + dy * dy);\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            double dx = x[i] - x[j];\n            double dy = y[i] - y[j];\n            double d = sqrt(dx * dx + dy * dy);\n            cd[i][j] = cd[j][i] = d;\n\n            double md = rectMinDist(i, j);\n            double uncertainty = uncertaintyCoef * (rad[i] + rad[j]);\n\n            double robust = centerWeight * d + minWeight * md + uncertainty;\n\n            if (md < 1e-9) {\n                robust = min(robust, d * (0.86 - 0.08 * uncertainRatio) + uncertainty * 0.45);\n            }\n\n            wd[i][j] = wd[j][i] = robust;\n            iw[i][j] = iw[j][i] = max(0, (int)robust);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        sort(nearest[i].begin(), nearest[i].end(), [&](int a, int b) {\n            return wd[i][a] < wd[i][b];\n        });\n    }\n\n    auto mstCostMat = [&](const vector<int>& v, const vector<vector<double>>& mat) -> double {\n        int n = (int)v.size();\n        if (n <= 1) return 0.0;\n\n        vector<double> mn(n, 1e100);\n        vector<char> used(n, 0);\n        mn[0] = 0;\n\n        double cost = 0;\n\n        for (int it = 0; it < n; it++) {\n            int bi = -1;\n\n            for (int i = 0; i < n; i++) {\n                if (!used[i] && (bi == -1 || mn[i] < mn[bi])) bi = i;\n            }\n\n            used[bi] = 1;\n            cost += mn[bi];\n\n            int a = v[bi];\n\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                double d = mat[a][v[j]];\n                if (d < mn[j]) mn[j] = d;\n            }\n        }\n\n        return cost;\n    };\n\n    double robustScoreWeight = 0.55 + 0.30 * uncertainRatio;\n\n    auto mstCost = [&](const vector<int>& v) -> double {\n        return robustScoreWeight * mstCostMat(v, wd)\n             + (1.0 - robustScoreWeight) * mstCostMat(v, cd);\n    };\n\n    auto totalMSTCost = [&](const vector<vector<int>>& groups) -> double {\n        double s = 0;\n        for (const auto &g : groups) s += mstCost(g);\n        return s;\n    };\n\n    auto makeByOrder = [&](const vector<int>& order) {\n        vector<vector<int>> groups(M);\n        int p = 0;\n\n        for (int k = 0; k < M; k++) {\n            groups[k].assign(order.begin() + p, order.begin() + p + G[k]);\n            p += G[k];\n        }\n\n        return groups;\n    };\n\n    vector<vector<vector<int>>> candidates;\n\n    auto addCandidate = [&](vector<vector<int>> g) {\n        bool ok = true;\n        vector<int> cnt(N, 0);\n\n        for (int k = 0; k < M; k++) {\n            if ((int)g[k].size() != G[k]) ok = false;\n\n            for (int v : g[k]) {\n                if (0 <= v && v < N) cnt[v]++;\n                else ok = false;\n            }\n        }\n\n        for (int i = 0; i < N; i++) if (cnt[i] != 1) ok = false;\n\n        if (ok) candidates.push_back(std::move(g));\n    };\n\n    auto mortonKey = [&](int i, bool swapxy, bool revx, bool revy) -> long long {\n        int xi = max(0, min(10000, (int)x[i]));\n        int yi = max(0, min(10000, (int)y[i]));\n\n        if (revx) xi = 10000 - xi;\n        if (revy) yi = 10000 - yi;\n        if (swapxy) swap(xi, yi);\n\n        long long key = 0;\n\n        for (int b = 0; b < 14; b++) {\n            key |= ((long long)((xi >> b) & 1)) << (2 * b);\n            key |= ((long long)((yi >> b) & 1)) << (2 * b + 1);\n        }\n\n        return key;\n    };\n\n    // Basic geometric candidates.\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (x[a] != x[b]) return x[a] < x[b];\n            return y[a] < y[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (y[a] != y[b]) return y[a] < y[b];\n            return x[a] < x[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka = x[a] + y[a];\n            double kb = x[b] + y[b];\n            if (ka != kb) return ka < kb;\n            return x[a] < x[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka = x[a] - y[a];\n            double kb = x[b] - y[b];\n            if (ka != kb) return ka < kb;\n            return x[a] < x[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        for (int sw = 0; sw < 2; sw++) {\n            for (int rxv = 0; rxv < 2; rxv++) {\n                for (int ryv = 0; ryv < 2; ryv++) {\n                    iota(ord.begin(), ord.end(), 0);\n\n                    sort(ord.begin(), ord.end(), [&](int a, int b) {\n                        long long ka = mortonKey(a, sw, rxv, ryv);\n                        long long kb = mortonKey(b, sw, rxv, ryv);\n                        if (ka != kb) return ka < kb;\n                        return a < b;\n                    });\n\n                    addCandidate(makeByOrder(ord));\n                }\n            }\n        }\n\n        for (int B : {4, 5, 7, 8, 10, 12, 16, 20, 25}) {\n            for (int mode = 0; mode < 2; mode++) {\n                iota(ord.begin(), ord.end(), 0);\n\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int ca = min(B - 1, max(0, (int)(x[a] * B / 10001.0)));\n                    int cb = min(B - 1, max(0, (int)(x[b] * B / 10001.0)));\n                    int ra = min(B - 1, max(0, (int)(y[a] * B / 10001.0)));\n                    int rb = min(B - 1, max(0, (int)(y[b] * B / 10001.0)));\n\n                    long long ka, kb;\n\n                    if (mode == 0) {\n                        ka = (long long)ra * B + ((ra & 1) ? (B - 1 - ca) : ca);\n                        kb = (long long)rb * B + ((rb & 1) ? (B - 1 - cb) : cb);\n                    } else {\n                        ka = (long long)ca * B + ((ca & 1) ? (B - 1 - ra) : ra);\n                        kb = (long long)cb * B + ((cb & 1) ? (B - 1 - rb) : rb);\n                    }\n\n                    if (ka != kb) return ka < kb;\n                    return mode == 0 ? x[a] < x[b] : y[a] < y[b];\n                });\n\n                addCandidate(makeByOrder(ord));\n            }\n        }\n    }\n\n    // Global MST traversal candidates.\n    {\n        vector<Edge> allEdges;\n        allEdges.reserve(N * (N - 1) / 2);\n\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                allEdges.push_back({i, j, (long long)(wd[i][j] * 1000)});\n            }\n        }\n\n        sort(allEdges.begin(), allEdges.end());\n\n        DSU dsu(N);\n        vector<vector<int>> tree(N);\n\n        for (auto &e : allEdges) {\n            if (dsu.unite(e.u, e.v)) {\n                tree[e.u].push_back(e.v);\n                tree[e.v].push_back(e.u);\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            sort(tree[i].begin(), tree[i].end(), [&](int a, int b) {\n                return atan2(y[a] - y[i], x[a] - x[i]) < atan2(y[b] - y[i], x[b] - x[i]);\n            });\n        }\n\n        vector<int> roots;\n        {\n            vector<int> tmp(N);\n            iota(tmp.begin(), tmp.end(), 0);\n\n            sort(tmp.begin(), tmp.end(), [&](int a, int b) {\n                return x[a] + y[a] < x[b] + y[b];\n            });\n            roots.push_back(tmp.front());\n            roots.push_back(tmp.back());\n\n            sort(tmp.begin(), tmp.end(), [&](int a, int b) {\n                return x[a] - y[a] < x[b] - y[b];\n            });\n            roots.push_back(tmp.front());\n            roots.push_back(tmp.back());\n\n            for (int t = 0; t < 6; t++) roots.push_back(rnd_int(0, N - 1));\n        }\n\n        for (int root : roots) {\n            vector<int> ord;\n            ord.reserve(N);\n\n            function<void(int,int)> dfs = [&](int v, int p) {\n                ord.push_back(v);\n                for (int to : tree[v]) if (to != p) dfs(to, v);\n            };\n\n            dfs(root, -1);\n\n            if ((int)ord.size() == N) {\n                addCandidate(makeByOrder(ord));\n                reverse(ord.begin(), ord.end());\n                addCandidate(makeByOrder(ord));\n            }\n\n            vector<int> bord;\n            bord.reserve(N);\n            vector<int> vis(N, 0);\n            queue<int> qu;\n            qu.push(root);\n            vis[root] = 1;\n\n            while (!qu.empty()) {\n                int v = qu.front();\n                qu.pop();\n\n                bord.push_back(v);\n\n                vector<int> ch = tree[v];\n                sort(ch.begin(), ch.end(), [&](int a, int b) {\n                    return wd[v][a] < wd[v][b];\n                });\n\n                for (int to : ch) if (!vis[to]) {\n                    vis[to] = 1;\n                    qu.push(to);\n                }\n            }\n\n            if ((int)bord.size() == N) addCandidate(makeByOrder(bord));\n        }\n    }\n\n    // Recursive bisection candidates.\n    function<void(vector<int>&, vector<int>&, vector<vector<int>>&, int)> recBuild =\n        [&](vector<int>& pts, vector<int>& gids, vector<vector<int>>& groups, int depth) {\n            if (gids.empty()) return;\n\n            if ((int)gids.size() == 1) {\n                groups[gids[0]] = pts;\n                return;\n            }\n\n            double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n\n            for (int p : pts) {\n                minx = min(minx, x[p]);\n                maxx = max(maxx, x[p]);\n                miny = min(miny, y[p]);\n                maxy = max(maxy, y[p]);\n            }\n\n            vector<int> order = gids;\n\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                if (G[a] != G[b]) return G[a] > G[b];\n                return a < b;\n            });\n\n            for (int i = 0; i < (int)order.size(); i++) {\n                if (rnd01() < 0.25) {\n                    int j = rnd_int(i, (int)order.size() - 1);\n                    swap(order[i], order[j]);\n                }\n            }\n\n            int total = (int)pts.size();\n            int target = total / 2;\n\n            vector<int> leftG, rightG;\n            int sumL = 0;\n\n            for (int id : order) {\n                if (sumL < target) {\n                    leftG.push_back(id);\n                    sumL += G[id];\n                } else {\n                    rightG.push_back(id);\n                }\n            }\n\n            bool improved = true;\n\n            while (improved) {\n                improved = false;\n                int cur = abs(sumL - (total - sumL));\n\n                for (int i = 0; i < (int)leftG.size(); i++) {\n                    int ns = sumL - G[leftG[i]];\n                    int nd = abs(ns - (total - ns));\n\n                    if (!rightG.empty() && nd < cur) {\n                        rightG.push_back(leftG[i]);\n                        leftG.erase(leftG.begin() + i);\n                        sumL = ns;\n                        improved = true;\n                        break;\n                    }\n                }\n\n                if (improved) continue;\n\n                for (int i = 0; i < (int)rightG.size(); i++) {\n                    int ns = sumL + G[rightG[i]];\n                    int nd = abs(ns - (total - ns));\n\n                    if (nd < cur) {\n                        leftG.push_back(rightG[i]);\n                        rightG.erase(rightG.begin() + i);\n                        sumL = ns;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n\n            if (leftG.empty() || rightG.empty()) {\n                leftG.clear();\n                rightG.clear();\n                sumL = 0;\n\n                for (int i = 0; i < (int)order.size(); i++) {\n                    if (i < (int)order.size() / 2) {\n                        leftG.push_back(order[i]);\n                        sumL += G[order[i]];\n                    } else {\n                        rightG.push_back(order[i]);\n                    }\n                }\n            }\n\n            bool splitX = (maxx - minx) >= (maxy - miny);\n            if (rnd01() < 0.15) splitX = !splitX;\n\n            sort(pts.begin(), pts.end(), [&](int a, int b) {\n                double va = splitX ? x[a] : y[a];\n                double vb = splitX ? x[b] : y[b];\n\n                if (va != vb) return va < vb;\n                return (splitX ? y[a] : x[a]) < (splitX ? y[b] : x[b]);\n            });\n\n            vector<int> lpts(pts.begin(), pts.begin() + sumL);\n            vector<int> rpts(pts.begin() + sumL, pts.end());\n\n            recBuild(lpts, leftG, groups, depth + 1);\n            recBuild(rpts, rightG, groups, depth + 1);\n        };\n\n    int recAttempts = 60;\n    if (M <= 20) recAttempts = 100;\n    if (M >= 180) recAttempts = 30;\n\n    for (int at = 0; at < recAttempts && timer.sec() < 0.85; at++) {\n        vector<int> pts(N), gids(M);\n        iota(pts.begin(), pts.end(), 0);\n        iota(gids.begin(), gids.end(), 0);\n\n        vector<vector<int>> g(M);\n        recBuild(pts, gids, g, 0);\n        addCandidate(g);\n    }\n\n    // Capacity-constrained seed clustering.\n    auto buildSeedCluster = [&](int variant) {\n        vector<vector<int>> groups(M);\n\n        vector<int> gids(M);\n        iota(gids.begin(), gids.end(), 0);\n\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n\n        vector<int> seeds(M, -1);\n        vector<int> all(N);\n        iota(all.begin(), all.end(), 0);\n\n        int firstSeed;\n\n        if (variant % 6 == 0) {\n            firstSeed = min_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] + y[a] < x[b] + y[b];\n            })[0];\n        } else if (variant % 6 == 1) {\n            firstSeed = max_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] + y[a] < x[b] + y[b];\n            })[0];\n        } else if (variant % 6 == 2) {\n            firstSeed = min_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] - y[a] < x[b] - y[b];\n            })[0];\n        } else {\n            firstSeed = rnd_int(0, N - 1);\n        }\n\n        seeds[gids[0]] = firstSeed;\n\n        vector<int> chosen;\n        chosen.push_back(firstSeed);\n\n        for (int idx = 1; idx < M; idx++) {\n            int gid = gids[idx];\n\n            int bestCity = -1;\n            double bestVal = -1;\n\n            int trials = (variant < 8 ? N : min(N, 180));\n\n            for (int tt = 0; tt < trials; tt++) {\n                int c = (trials == N ? tt : rnd_int(0, N - 1));\n\n                double md = 1e100;\n                for (int s : chosen) md = min(md, wd[c][s]);\n\n                double val = md * (1.0 + 0.12 * (rnd01() - 0.5));\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    bestCity = c;\n                }\n            }\n\n            seeds[gid] = bestCity;\n            chosen.push_back(bestCity);\n        }\n\n        vector<int> rem = G;\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            double ba = 1e100, sa = 1e100;\n            double bb = 1e100, sb = 1e100;\n\n            for (int k = 0; k < M; k++) {\n                double da = wd[a][seeds[k]];\n                if (da < ba) {\n                    sa = ba;\n                    ba = da;\n                } else if (da < sa) {\n                    sa = da;\n                }\n\n                double db = wd[b][seeds[k]];\n                if (db < bb) {\n                    sb = bb;\n                    bb = db;\n                } else if (db < sb) {\n                    sb = db;\n                }\n            }\n\n            return (sa - ba) > (sb - bb);\n        });\n\n        for (int c : order) {\n            int bestK = -1;\n            double bestD = 1e100;\n\n            for (int k = 0; k < M; k++) {\n                if (rem[k] <= 0) continue;\n\n                double d = wd[c][seeds[k]] * (1.0 + 0.05 * (rnd01() - 0.5));\n\n                if (d < bestD) {\n                    bestD = d;\n                    bestK = k;\n                }\n            }\n\n            if (bestK < 0) {\n                for (int k = 0; k < M; k++) if (rem[k] > 0) {\n                    bestK = k;\n                    break;\n                }\n            }\n\n            groups[bestK].push_back(c);\n            rem[bestK]--;\n        }\n\n        return groups;\n    };\n\n    int seedAttempts = 30;\n    if (M <= 30) seedAttempts = 65;\n    if (M >= 180) seedAttempts = 12;\n\n    for (int at = 0; at < seedAttempts && timer.sec() < 1.05; at++) {\n        addCandidate(buildSeedCluster(at));\n    }\n\n    vector<vector<int>> groups;\n    double bestScore = 1e100;\n\n    for (auto &cand : candidates) {\n        double sc = totalMSTCost(cand);\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = cand;\n        }\n    }\n\n    vector<int> belong(N), posInGroup(N);\n\n    auto rebuildBelong = [&]() {\n        for (int k = 0; k < M; k++) {\n            for (int i = 0; i < (int)groups[k].size(); i++) {\n                belong[groups[k][i]] = k;\n                posInGroup[groups[k][i]] = i;\n            }\n        }\n    };\n\n    rebuildBelong();\n\n    vector<double> gCost(M);\n    for (int k = 0; k < M; k++) gCost[k] = mstCost(groups[k]);\n\n    // Local swap improvement.\n    for (int iter = 0; iter < 8500 && timer.sec() < 1.32; iter++) {\n        int aCity = rnd_int(0, N - 1);\n        int ga = belong[aCity];\n\n        int bCity = -1;\n        int scan = min(45, N - 1);\n        int offset = rnd_int(0, max(0, scan - 1));\n\n        for (int t = 0; t < scan; t++) {\n            int cand = nearest[aCity][(t + offset) % scan];\n\n            if (belong[cand] != ga) {\n                bCity = cand;\n                break;\n            }\n        }\n\n        if (bCity < 0) continue;\n\n        int gb = belong[bCity];\n        if (ga == gb) continue;\n\n        int ia = posInGroup[aCity];\n        int ib = posInGroup[bCity];\n\n        double old = gCost[ga] + gCost[gb];\n\n        swap(groups[ga][ia], groups[gb][ib]);\n\n        double na = mstCost(groups[ga]);\n        double nb = mstCost(groups[gb]);\n        double nw = na + nb;\n\n        if (nw + 1e-9 < old) {\n            gCost[ga] = na;\n            gCost[gb] = nb;\n\n            belong[aCity] = gb;\n            belong[bCity] = ga;\n            posInGroup[aCity] = ib;\n            posInGroup[bCity] = ia;\n        } else {\n            swap(groups[ga][ia], groups[gb][ib]);\n        }\n    }\n\n    // Sort inside groups by long axis.\n    for (int k = 0; k < M; k++) {\n        double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n\n        for (int p : groups[k]) {\n            minx = min(minx, x[p]);\n            maxx = max(maxx, x[p]);\n            miny = min(miny, y[p]);\n            maxy = max(maxy, y[p]);\n        }\n\n        bool sx = (maxx - minx) >= (maxy - miny);\n\n        sort(groups[k].begin(), groups[k].end(), [&](int a, int b) {\n            double va = sx ? x[a] : y[a];\n            double vb = sx ? x[b] : y[b];\n\n            if (va != vb) return va < vb;\n            return (sx ? y[a] : x[a]) < (sx ? y[b] : x[b]);\n        });\n    }\n\n    vector<vector<pair<int,int>>> queriedEdges(M);\n    vector<int> exactWhole(M, 0);\n\n    int qcnt = 0;\n\n    auto query = [&](const vector<int>& c) -> vector<pair<int,int>> {\n        cout << \"? \" << c.size();\n\n        for (int v : c) cout << ' ' << v;\n\n        cout << endl;\n        cout.flush();\n\n        vector<pair<int,int>> ret;\n\n        for (int i = 0; i < (int)c.size() - 1; i++) {\n            int a, b;\n            cin >> a >> b;\n\n            if (a > b) swap(a, b);\n\n            ret.push_back({a, b});\n        }\n\n        return ret;\n    };\n\n    // Exact small groups first.\n    vector<int> qorder(M);\n    iota(qorder.begin(), qorder.end(), 0);\n\n    sort(qorder.begin(), qorder.end(), [&](int a, int b) {\n        bool aa = (G[a] >= 2 && G[a] <= L);\n        bool bb = (G[b] >= 2 && G[b] <= L);\n\n        if (aa != bb) return aa > bb;\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n\n    for (int k : qorder) {\n        if (qcnt >= Q) break;\n\n        if (G[k] >= 2 && G[k] <= L) {\n            auto ret = query(groups[k]);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            exactWhole[k] = 1;\n        }\n    }\n\n    // Important larger groups.\n    vector<int> imp(M);\n    iota(imp.begin(), imp.end(), 0);\n\n    sort(imp.begin(), imp.end(), [&](int a, int b) {\n        double va = gCost[a] / max(1, G[a] - 1);\n        double vb = gCost[b] / max(1, G[b] - 1);\n        return va > vb;\n    });\n\n    for (int k : imp) {\n        if (qcnt >= Q) break;\n\n        int s = groups[k].size();\n\n        if (s < 2 || exactWhole[k]) continue;\n\n        int tq = 1;\n\n        if (s >= 120) tq = 10;\n        else if (s >= 80) tq = 8;\n        else if (s >= 50) tq = 5;\n        else if (s >= 25) tq = 3;\n        else if (s >= 10) tq = 2;\n\n        tq = min(tq, Q - qcnt);\n\n        for (int t = 0; t < tq && qcnt < Q; t++) {\n            int anchor = groups[k][(long long)t * (s - 1) / max(1, tq - 1)];\n\n            vector<pair<double,int>> nb;\n            nb.reserve(s);\n\n            for (int p : groups[k]) nb.push_back({wd[anchor][p], p});\n\n            sort(nb.begin(), nb.end());\n\n            vector<int> c;\n\n            for (int i = 0; i < min(L, (int)nb.size()); i++) c.push_back(nb[i].second);\n\n            if ((int)c.size() >= 2) {\n                auto ret = query(c);\n                qcnt++;\n                queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n            }\n        }\n    }\n\n    // Remaining queries: local windows.\n    for (int k : imp) {\n        if (qcnt >= Q) break;\n        if (exactWhole[k]) continue;\n\n        int s = groups[k].size();\n        if (s < 2) continue;\n\n        int step = max(2, L - 1);\n\n        for (int st = 0; st < s && qcnt < Q; st += step) {\n            int en = min(s, st + L);\n\n            if (en - st < 2) break;\n\n            vector<int> c(groups[k].begin() + st, groups[k].begin() + en);\n\n            auto ret = query(c);\n            qcnt++;\n            queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n\n            if (en == s) break;\n        }\n    }\n\n    vector<vector<pair<int,int>>> ansEdges(M);\n\n    auto ekey = [](int a, int b) -> long long {\n        if (a > b) swap(a, b);\n        return ((long long)a << 32) ^ (unsigned int)b;\n    };\n\n    for (int k = 0; k < M; k++) {\n        int s = groups[k].size();\n\n        if (s <= 1) continue;\n\n        // If whole group was queried, returned edges are its exact true MST.\n        if (exactWhole[k]) {\n            ansEdges[k] = queriedEdges[k];\n            continue;\n        }\n\n        unordered_set<long long> qset;\n        qset.reserve(queriedEdges[k].size() * 2 + 10);\n\n        for (auto [a, b] : queriedEdges[k]) qset.insert(ekey(a, b));\n\n        vector<Edge> edges;\n        edges.reserve(s * (s - 1) / 2);\n\n        for (int i = 0; i < s; i++) {\n            for (int j = i + 1; j < s; j++) {\n                int a = groups[k][i];\n                int b = groups[k][j];\n\n                long long w = iw[a][b];\n\n                if (qset.count(ekey(a, b))) w -= 450;\n\n                edges.push_back({a, b, w});\n            }\n        }\n\n        sort(edges.begin(), edges.end());\n\n        DSU dsu(N);\n\n        for (auto &e : edges) {\n            if ((int)ansEdges[k].size() == s - 1) break;\n\n            if (dsu.unite(e.u, e.v)) {\n                ansEdges[k].push_back({e.u, e.v});\n            }\n        }\n\n        for (int i = 0; i + 1 < s && (int)ansEdges[k].size() < s - 1; i++) {\n            if (dsu.unite(groups[k][i], groups[k][i + 1])) {\n                ansEdges[k].push_back({groups[k][i], groups[k][i + 1]});\n            }\n        }\n    }\n\n    cout << \"!\" << '\\n';\n\n    for (int k = 0; k < M; k++) {\n        for (int i = 0; i < (int)groups[k].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[k][i];\n        }\n\n        cout << '\\n';\n\n        for (auto [a, b] : ansEdges[k]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Action {\n    char a, d;\n};\n\nstruct Prev {\n    int pi = -1;\n    int pj = -1;\n    Action act;\n};\n\nint N, M;\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'};\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nbool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nint dir_id(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\npair<int,int> slide_dest(int i, int j, int dir, const vector<vector<int>>& block) {\n    while (true) {\n        int ni = i + di[dir];\n        int nj = j + dj[dir];\n\n        if (!inside(ni, nj)) break;\n        if (block[ni][nj]) break;\n\n        i = ni;\n        j = nj;\n    }\n\n    return {i, j};\n}\n\nvector<Action> bfs_path(\n    pair<int,int> start,\n    pair<int,int> goal,\n    const vector<vector<int>>& block\n) {\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<Prev>> prv(N, vector<Prev>(N));\n\n    queue<pair<int,int>> q;\n    dist[start.first][start.second] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        if (i == goal.first && j == goal.second) break;\n\n        for (int dir = 0; dir < 4; dir++) {\n            // Move\n            {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n\n                if (inside(ni, nj) && !block[ni][nj] && dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    prv[ni][nj] = {i, j, {'M', dc[dir]}};\n                    q.push({ni, nj});\n                }\n            }\n\n            // Slide\n            {\n                auto [ni, nj] = slide_dest(i, j, dir, block);\n\n                if ((ni != i || nj != j) && dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    prv[ni][nj] = {i, j, {'S', dc[dir]}};\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n\n    vector<Action> path;\n\n    if (dist[goal.first][goal.second] == -1) {\n        return path;\n    }\n\n    int ci = goal.first;\n    int cj = goal.second;\n\n    while (!(ci == start.first && cj == start.second)) {\n        Prev pr = prv[ci][cj];\n        path.push_back(pr.act);\n        ci = pr.pi;\n        cj = pr.pj;\n    }\n\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nbool apply_action(\n    pair<int,int>& pos,\n    vector<vector<int>>& block,\n    Action act\n) {\n    int dir = dir_id(act.d);\n\n    if (act.a == 'M') {\n        int ni = pos.first + di[dir];\n        int nj = pos.second + dj[dir];\n\n        if (!inside(ni, nj)) return false;\n        if (block[ni][nj]) return false;\n\n        pos = {ni, nj};\n        return true;\n    }\n\n    if (act.a == 'S') {\n        pos = slide_dest(pos.first, pos.second, dir, block);\n        return true;\n    }\n\n    if (act.a == 'A') {\n        int ni = pos.first + di[dir];\n        int nj = pos.second + dj[dir];\n\n        if (!inside(ni, nj)) return false;\n\n        block[ni][nj] ^= 1;\n        return true;\n    }\n\n    return false;\n}\n\nbool is_target_cell(const vector<pair<int,int>>& p, int i, int j) {\n    for (auto [x, y] : p) {\n        if (x == i && y == j) return true;\n    }\n    return false;\n}\n\nbool simulate_full(\n    const vector<pair<int,int>>& p,\n    const vector<Action>& ans\n) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    pair<int,int> pos = p[0];\n    int next_target = 1;\n\n    for (auto act : ans) {\n        if (!apply_action(pos, block, act)) {\n            return false;\n        }\n\n        if (next_target < M && pos == p[next_target]) {\n            next_target++;\n        }\n    }\n\n    return next_target == M;\n}\n\nvector<Action> baseline_solution(const vector<pair<int,int>>& p) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    vector<Action> ans;\n    pair<int,int> cur = p[0];\n\n    for (int t = 1; t < M; t++) {\n        auto path = bfs_path(cur, p[t], block);\n\n        for (auto a : path) {\n            ans.push_back(a);\n            apply_action(cur, block, a);\n        }\n    }\n\n    return ans;\n}\n\nvector<Action> construct_blocks(\n    pair<int,int>& cur,\n    vector<vector<int>>& block,\n    const vector<pair<int,int>>& wanted,\n    const vector<pair<int,int>>& p\n) {\n    vector<Action> res;\n\n    for (auto [bi, bj] : wanted) {\n        if (elapsed_sec() > 1.88) return {};\n        if (!inside(bi, bj)) continue;\n        if (block[bi][bj]) continue;\n        if (is_target_cell(p, bi, bj)) continue;\n\n        vector<Action> best;\n        bool found = false;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int si = bi - di[dir];\n            int sj = bj - dj[dir];\n\n            if (!inside(si, sj)) continue;\n            if (block[si][sj]) continue;\n\n            auto path = bfs_path(cur, {si, sj}, block);\n\n            if (path.empty() && cur != make_pair(si, sj)) continue;\n\n            vector<Action> cand = path;\n            cand.push_back({'A', dc[dir]});\n\n            if (!found || cand.size() < best.size()) {\n                found = true;\n                best = cand;\n            }\n        }\n\n        if (!found) continue;\n\n        for (auto a : best) {\n            res.push_back(a);\n            bool ok = apply_action(cur, block, a);\n            if (!ok) return {};\n        }\n    }\n\n    return res;\n}\n\nvector<Action> solve_with_initial_blocks(\n    const vector<pair<int,int>>& p,\n    const vector<pair<int,int>>& wanted_blocks\n) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    pair<int,int> cur = p[0];\n    vector<Action> ans;\n\n    auto build = construct_blocks(cur, block, wanted_blocks, p);\n\n    if (!wanted_blocks.empty() && build.empty()) {\n        return {};\n    }\n\n    ans.insert(ans.end(), build.begin(), build.end());\n\n    for (int t = 1; t < M; t++) {\n        if (elapsed_sec() > 1.88) return {};\n\n        auto goal = p[t];\n\n        if (block[goal.first][goal.second]) {\n            return {};\n        }\n\n        auto path = bfs_path(cur, goal, block);\n\n        if (path.empty() && cur != goal) {\n            return {};\n        }\n\n        for (auto a : path) {\n            ans.push_back(a);\n            bool ok = apply_action(cur, block, a);\n            if (!ok) return {};\n        }\n    }\n\n    return ans;\n}\n\nvector<pair<int,int>> unique_cells(vector<pair<int,int>> v) {\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nvoid add_candidate(\n    vector<vector<pair<int,int>>>& candidates,\n    vector<pair<int,int>> cells,\n    const vector<pair<int,int>>& p,\n    int max_size = 18\n) {\n    vector<pair<int,int>> filtered;\n\n    for (auto [i, j] : cells) {\n        if (!inside(i, j)) continue;\n        if (is_target_cell(p, i, j)) continue;\n        filtered.push_back({i, j});\n    }\n\n    filtered = unique_cells(filtered);\n\n    if (!filtered.empty() && (int)filtered.size() <= max_size) {\n        candidates.push_back(filtered);\n    }\n}\n\nint main() {\n    START_TIME = chrono::steady_clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    vector<pair<int,int>> p(M);\n    for (int i = 0; i < M; i++) {\n        cin >> p[i].first >> p[i].second;\n    }\n\n    vector<Action> best = baseline_solution(p);\n\n    vector<vector<pair<int,int>>> candidates;\n    candidates.push_back({});\n\n    // Sparse lattice candidates.\n    for (int step : {5, 6, 7}) {\n        for (int oi = 1; oi < step; oi++) {\n            for (int oj = 1; oj < step; oj++) {\n                vector<pair<int,int>> cells;\n\n                for (int i = oi; i < N; i += step) {\n                    for (int j = oj; j < N; j += step) {\n                        cells.push_back({i, j});\n                    }\n                }\n\n                add_candidate(candidates, cells, p, 12);\n            }\n        }\n    }\n\n    vector<pair<int,int>> top;\n\n    // Route-aware target stopper scoring.\n    {\n        map<pair<int,int>, int> score;\n\n        for (int t = 1; t < M; t++) {\n            auto [gi, gj] = p[t];\n            auto [pi0, pj0] = p[t - 1];\n\n            for (int dir = 0; dir < 4; dir++) {\n                int bi = gi + di[dir];\n                int bj = gj + dj[dir];\n\n                if (!inside(bi, bj)) continue;\n                if (is_target_cell(p, bi, bj)) continue;\n\n                int val = 5;\n\n                int opp = dir ^ 1;\n                int len = 0;\n                int ci = gi + di[opp];\n                int cj = gj + dj[opp];\n\n                while (inside(ci, cj)) {\n                    len++;\n                    ci += di[opp];\n                    cj += dj[opp];\n                }\n\n                val += len;\n\n                if (dir <= 1) {\n                    if (pj0 == gj) val += 8;\n                    val += max(0, 5 - abs(pj0 - gj));\n                } else {\n                    if (pi0 == gi) val += 8;\n                    val += max(0, 5 - abs(pi0 - gi));\n                }\n\n                if (gi == 0 || gi == N - 1 || gj == 0 || gj == N - 1) {\n                    val -= 3;\n                }\n\n                // Extra bonus if this blocker can serve several targets in row/column.\n                for (int u = 1; u < M; u++) {\n                    if (u == t) continue;\n                    if (dir <= 1 && p[u].second == gj) val++;\n                    if (dir >= 2 && p[u].first == gi) val++;\n                }\n\n                score[{bi, bj}] += val;\n            }\n        }\n\n        vector<pair<int,pair<int,int>>> ord;\n\n        for (auto [cell, sc] : score) {\n            ord.push_back({-sc, cell});\n        }\n\n        sort(ord.begin(), ord.end());\n\n        for (int k = 0; k < (int)ord.size() && k < 30; k++) {\n            top.push_back(ord[k].second);\n        }\n\n        // Prefixes.\n        for (int lim : {3, 4, 5, 6, 7, 8, 10, 12, 14, 16}) {\n            vector<pair<int,int>> cells;\n            for (int k = 0; k < (int)top.size() && k < lim; k++) {\n                cells.push_back(top[k]);\n            }\n            add_candidate(candidates, cells, p, 18);\n        }\n\n        // Shifted windows.\n        for (int start : {1, 2, 3, 5, 8, 11}) {\n            for (int lim : {5, 7, 9, 11}) {\n                vector<pair<int,int>> cells;\n                for (int k = start; k < (int)top.size() && k < start + lim; k++) {\n                    cells.push_back(top[k]);\n                }\n                add_candidate(candidates, cells, p, 16);\n            }\n        }\n\n        // Even / odd / modulo subsets.\n        for (int mod : {2, 3, 4}) {\n            for (int rem = 0; rem < mod; rem++) {\n                vector<pair<int,int>> cells;\n                for (int k = 0; k < (int)top.size() && k < 24; k++) {\n                    if (k % mod == rem) cells.push_back(top[k]);\n                }\n                add_candidate(candidates, cells, p, 14);\n            }\n        }\n\n        // Prefix minus one variants.\n        for (int lim : {8, 10, 12, 14}) {\n            for (int skip = 0; skip < min(lim, (int)top.size()); skip++) {\n                vector<pair<int,int>> cells;\n                for (int k = 0; k < (int)top.size() && k < lim; k++) {\n                    if (k != skip) cells.push_back(top[k]);\n                }\n                add_candidate(candidates, cells, p, 16);\n            }\n        }\n    }\n\n    // Row/column rail candidates from target frequencies.\n    {\n        vector<int> rowcnt(N, 0), colcnt(N, 0);\n\n        for (int t = 1; t < M; t++) {\n            rowcnt[p[t].first]++;\n            colcnt[p[t].second]++;\n        }\n\n        vector<int> rows(N), cols(N);\n        iota(rows.begin(), rows.end(), 0);\n        iota(cols.begin(), cols.end(), 0);\n\n        sort(rows.begin(), rows.end(), [&](int a, int b) {\n            return rowcnt[a] > rowcnt[b];\n        });\n\n        sort(cols.begin(), cols.end(), [&](int a, int b) {\n            return colcnt[a] > colcnt[b];\n        });\n\n        for (int rcnt : {1, 2, 3}) {\n            for (int off = 2; off <= 5; off++) {\n                vector<pair<int,int>> cells;\n\n                for (int a = 0; a < rcnt; a++) {\n                    int r = rows[a];\n                    for (int c = off; c < N; c += 5) {\n                        cells.push_back({r, c});\n                    }\n                }\n\n                add_candidate(candidates, cells, p, 14);\n            }\n        }\n\n        for (int ccnt : {1, 2, 3}) {\n            for (int off = 2; off <= 5; off++) {\n                vector<pair<int,int>> cells;\n\n                for (int b = 0; b < ccnt; b++) {\n                    int c = cols[b];\n                    for (int r = off; r < N; r += 5) {\n                        cells.push_back({r, c});\n                    }\n                }\n\n                add_candidate(candidates, cells, p, 14);\n            }\n        }\n\n        for (int rcnt : {1, 2}) {\n            for (int ccnt : {1, 2}) {\n                for (int off = 2; off <= 5; off++) {\n                    vector<pair<int,int>> cells;\n\n                    for (int a = 0; a < rcnt; a++) {\n                        int r = rows[a];\n                        for (int c = off; c < N; c += 5) {\n                            cells.push_back({r, c});\n                        }\n                    }\n\n                    for (int b = 0; b < ccnt; b++) {\n                        int c = cols[b];\n                        for (int r = off; r < N; r += 5) {\n                            cells.push_back({r, c});\n                        }\n                    }\n\n                    add_candidate(candidates, cells, p, 16);\n                }\n            }\n        }\n    }\n\n    // Mixed lattice + top blockers.\n    if (!top.empty()) {\n        for (int step : {6, 7}) {\n            for (int oi = 1; oi < step; oi += 2) {\n                for (int oj = 1; oj < step; oj += 2) {\n                    vector<pair<int,int>> cells;\n\n                    for (int i = oi; i < N; i += step) {\n                        for (int j = oj; j < N; j += step) {\n                            cells.push_back({i, j});\n                        }\n                    }\n\n                    for (int k = 0; k < (int)top.size() && k < 4; k++) {\n                        cells.push_back(top[k]);\n                    }\n\n                    add_candidate(candidates, cells, p, 16);\n                }\n            }\n        }\n    }\n\n    // Remove duplicate candidates.\n    for (auto& c : candidates) {\n        c = unique_cells(c);\n    }\n\n    sort(candidates.begin(), candidates.end());\n    candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n    for (auto cells : candidates) {\n        if (elapsed_sec() > 1.82) break;\n\n        auto ans = solve_with_initial_blocks(p, cells);\n\n        if (ans.empty()) continue;\n        if ((int)ans.size() > 2 * N * M) continue;\n        if (!simulate_full(p, ans)) continue;\n\n        if (ans.size() < best.size()) {\n            best = ans;\n        }\n    }\n\n    if ((int)best.size() > 2 * N * M || !simulate_full(p, best)) {\n        best = baseline_solution(p);\n    }\n\n    for (auto [a, d] : best) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Input {\n    int n;\n    vector<int> x, y;\n    vector<long long> r;\n};\n\nstatic constexpr int W = 10000;\nstatic constexpr double TIME_LIMIT = 4.82;\n\nchrono::steady_clock::time_point start_time;\n\ndouble elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - start_time).count();\n}\n\nlong long area(const Rect& e) {\n    return 1LL * (e.c - e.a) * (e.d - e.b);\n}\n\nint width(const Rect& r) {\n    return r.c - r.a;\n}\n\nint height(const Rect& r) {\n    return r.d - r.b;\n}\n\nbool overlap_interval(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nbool overlap_rect(const Rect& p, const Rect& q) {\n    return overlap_interval(p.a, p.c, q.a, q.c)\n        && overlap_interval(p.b, p.d, q.b, q.d);\n}\n\ndouble rect_score(long long s, long long r) {\n    double mn = (double)min(s, r);\n    double mx = (double)max(s, r);\n    double q = mn / mx;\n    return 1.0 - (1.0 - q) * (1.0 - q);\n}\n\ndouble total_score(const vector<Rect>& rects, const Input& in) {\n    double res = 0;\n    for (int i = 0; i < in.n; i++) {\n        res += rect_score(area(rects[i]), in.r[i]);\n    }\n    return res;\n}\n\nbool valid_rect_for_point(const Rect& r, int x, int y) {\n    return r.a <= x && x < r.c && r.b <= y && y < r.d && r.a < r.c && r.b < r.d;\n}\n\nbool validate_solution(const vector<Rect>& rects, const Input& in) {\n    int n = in.n;\n    if ((int)rects.size() != n) return false;\n\n    for (int i = 0; i < n; i++) {\n        const Rect& r = rects[i];\n\n        if (r.a < 0 || r.b < 0 || r.c > W || r.d > W) return false;\n        if (r.a >= r.c || r.b >= r.d) return false;\n        if (!valid_rect_for_point(r, in.x[i], in.y[i])) return false;\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = i + 1; j < n; j++) {\n            if (overlap_rect(rects[i], rects[j])) return false;\n        }\n    }\n\n    return true;\n}\n\nint max_expand_dir(const vector<Rect>& rects, int idx, int dir) {\n    const Rect& cur = rects[idx];\n    int n = rects.size();\n\n    if (dir == 0) {\n        int lim = cur.a;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.c <= cur.a) {\n                lim = min(lim, cur.a - o.c);\n            }\n        }\n        return lim;\n    } else if (dir == 1) {\n        int lim = W - cur.c;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.b, cur.d, o.b, o.d) && o.a >= cur.c) {\n                lim = min(lim, o.a - cur.c);\n            }\n        }\n        return lim;\n    } else if (dir == 2) {\n        int lim = cur.b;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.d <= cur.b) {\n                lim = min(lim, cur.b - o.d);\n            }\n        }\n        return lim;\n    } else {\n        int lim = W - cur.d;\n        for (int j = 0; j < n; j++) if (j != idx) {\n            const Rect& o = rects[j];\n            if (overlap_interval(cur.a, cur.c, o.a, o.c) && o.b >= cur.d) {\n                lim = min(lim, o.b - cur.d);\n            }\n        }\n        return lim;\n    }\n}\n\nRect expanded(Rect r, int dir, int delta) {\n    if (dir == 0) r.a -= delta;\n    else if (dir == 1) r.c += delta;\n    else if (dir == 2) r.b -= delta;\n    else r.d += delta;\n    return r;\n}\n\nRect shrunk(Rect r, int dir, int delta) {\n    if (dir == 0) r.a += delta;\n    else if (dir == 1) r.c -= delta;\n    else if (dir == 2) r.b += delta;\n    else r.d -= delta;\n    return r;\n}\n\nvector<int> candidate_deltas(int mx, long long cur_area, long long target, int len) {\n    vector<int> cand;\n    if (mx <= 0) return cand;\n\n    cand.push_back(1);\n    cand.push_back(mx);\n\n    long long need = target - cur_area;\n\n    if (need != 0) {\n        long long ab = llabs(need);\n        long long f = ab / len;\n        long long c = (ab + len - 1) / len;\n\n        for (long long v : {f - 2, f - 1, f, f + 1, f + 2,\n                            c - 2, c - 1, c, c + 1, c + 2}) {\n            if (1 <= v && v <= mx) cand.push_back((int)v);\n        }\n    }\n\n    sort(cand.begin(), cand.end());\n    cand.erase(unique(cand.begin(), cand.end()), cand.end());\n    return cand;\n}\n\nvoid local_refine(vector<Rect>& rects, const Input& in, mt19937& rng, int max_loop = 120) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int loop = 0;\n\n    while (elapsed() < TIME_LIMIT && loop < max_loop) {\n        loop++;\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_type = -1;\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-14;\n\n            // Expansion\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1) ? height(rects[id]) : width(rects[id]);\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 0;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            // Shrink\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = 0;\n\n                if (dir == 0) {\n                    mx = in.x[id] - rects[id].a;\n                } else if (dir == 1) {\n                    mx = rects[id].c - (in.x[id] + 1);\n                } else if (dir == 2) {\n                    mx = in.y[id] - rects[id].b;\n                } else {\n                    mx = rects[id].d - (in.y[id] + 1);\n                }\n\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1) ? height(rects[id]) : width(rects[id]);\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = shrunk(rects[id], dir, delta);\n                    if (!valid_rect_for_point(nr, in.x[id], in.y[id])) continue;\n\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_type = 1;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_type != -1) {\n                if (best_type == 0) {\n                    rects[id] = expanded(rects[id], best_dir, best_delta);\n                } else {\n                    rects[id] = shrunk(rects[id], best_dir, best_delta);\n                }\n                changed = true;\n            }\n        }\n\n        if (!changed) break;\n    }\n}\n\nvoid greedy_expand(vector<Rect>& rects, const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<int> ord(n);\n    iota(ord.begin(), ord.end(), 0);\n\n    int stagnate = 0;\n\n    while (elapsed() < TIME_LIMIT && stagnate < 35) {\n        shuffle(ord.begin(), ord.end(), rng);\n        bool changed = false;\n\n        for (int id : ord) {\n            if (elapsed() >= TIME_LIMIT) break;\n\n            long long cur_area = area(rects[id]);\n            double cur_score = rect_score(cur_area, in.r[id]);\n\n            int best_dir = -1;\n            int best_delta = 0;\n            double best_gain = 1e-15;\n\n            for (int dir = 0; dir < 4; dir++) {\n                int mx = max_expand_dir(rects, id, dir);\n                if (mx <= 0) continue;\n\n                int len = (dir <= 1) ? height(rects[id]) : width(rects[id]);\n                auto cand = candidate_deltas(mx, cur_area, in.r[id], len);\n\n                for (int delta : cand) {\n                    Rect nr = expanded(rects[id], dir, delta);\n                    long long na = area(nr);\n                    double ns = rect_score(na, in.r[id]);\n                    double gain = ns - cur_score;\n\n                    gain += 1e-13 * delta;\n\n                    if (gain > best_gain) {\n                        best_gain = gain;\n                        best_dir = dir;\n                        best_delta = delta;\n                    }\n                }\n            }\n\n            if (best_dir != -1) {\n                rects[id] = expanded(rects[id], best_dir, best_delta);\n                changed = true;\n            }\n        }\n\n        if (changed) stagnate = 0;\n        else stagnate++;\n    }\n}\n\nvector<Rect> solve_greedy_once(const Input& in, mt19937& rng) {\n    int n = in.n;\n    vector<Rect> rects(n);\n\n    for (int i = 0; i < n; i++) {\n        rects[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n    }\n\n    greedy_expand(rects, in, rng);\n    local_refine(rects, in, rng, 250);\n\n    return rects;\n}\n\nlong long sum_r(const Input& in, const vector<int>& ids) {\n    long long s = 0;\n    for (int id : ids) s += in.r[id];\n    return s;\n}\n\nstruct SplitCandidate {\n    bool split_x;\n    int k;\n    int cut;\n    double err;\n};\n\nvector<SplitCandidate> all_split_candidates_axis(\n    const Input& in,\n    const vector<int>& ids,\n    const Rect& box,\n    bool split_x\n) {\n    vector<SplitCandidate> res;\n\n    int m = ids.size();\n    if (m <= 1) return res;\n\n    vector<int> sorted = ids;\n    sort(sorted.begin(), sorted.end(), [&](int p, int q) {\n        if (split_x) return in.x[p] < in.x[q];\n        else return in.y[p] < in.y[q];\n    });\n\n    long long total = sum_r(in, sorted);\n\n    vector<long long> pref(m + 1, 0);\n    for (int i = 0; i < m; i++) {\n        pref[i + 1] = pref[i] + in.r[sorted[i]];\n    }\n\n    for (int k = 1; k < m; k++) {\n        int coord_l = split_x ? in.x[sorted[k - 1]] : in.y[sorted[k - 1]];\n        int coord_r = split_x ? in.x[sorted[k]] : in.y[sorted[k]];\n\n        if (coord_l == coord_r) continue;\n\n        double ratio = (double)pref[k] / (double)total;\n\n        int cut = split_x\n            ? box.a + (int)round(width(box) * ratio)\n            : box.b + (int)round(height(box) * ratio);\n\n        int low = coord_l + 1;\n        int high = coord_r;\n\n        if (split_x) {\n            cut = max(box.a + 1, min(box.c - 1, cut));\n            cut = max(low, min(high, cut));\n            if (!(box.a < cut && cut < box.c)) continue;\n        } else {\n            cut = max(box.b + 1, min(box.d - 1, cut));\n            cut = max(low, min(high, cut));\n            if (!(box.b < cut && cut < box.d)) continue;\n        }\n\n        double actual_ratio = split_x\n            ? (double)(cut - box.a) / width(box)\n            : (double)(cut - box.b) / height(box);\n\n        double err = fabs(actual_ratio - ratio);\n\n        res.push_back({split_x, k, cut, err});\n    }\n\n    return res;\n}\n\nvoid build_slice_rec(\n    const Input& in,\n    const vector<int>& ids,\n    const Rect& box,\n    vector<Rect>& out,\n    int mode,\n    int depth,\n    mt19937& rng\n) {\n    if (ids.empty()) return;\n\n    if (ids.size() == 1) {\n        out[ids[0]] = box;\n        return;\n    }\n\n    vector<SplitCandidate> cand;\n\n    auto cx = all_split_candidates_axis(in, ids, box, true);\n    auto cy = all_split_candidates_axis(in, ids, box, false);\n\n    if (mode == 0) {\n        cand = (width(box) >= height(box)) ? cx : cy;\n        if (cand.empty()) cand = (width(box) >= height(box)) ? cy : cx;\n    } else if (mode == 1) {\n        cand = (width(box) < height(box)) ? cx : cy;\n        if (cand.empty()) cand = (width(box) < height(box)) ? cy : cx;\n    } else if (mode == 2) {\n        cand = (depth % 2 == 0) ? cx : cy;\n        if (cand.empty()) cand = (depth % 2 == 0) ? cy : cx;\n    } else if (mode == 3) {\n        cand = cx;\n        cand.insert(cand.end(), cy.begin(), cy.end());\n    } else {\n        cand = cx;\n        cand.insert(cand.end(), cy.begin(), cy.end());\n    }\n\n    if (cand.empty()) {\n        // Extremely rare fallback.\n        vector<int> sorted = ids;\n        bool split_x = width(box) >= height(box);\n        sort(sorted.begin(), sorted.end(), [&](int p, int q) {\n            return split_x ? in.x[p] < in.x[q] : in.y[p] < in.y[q];\n        });\n\n        int k = sorted.size() / 2;\n        k = max(1, min(k, (int)sorted.size() - 1));\n\n        int coord_l = split_x ? in.x[sorted[k - 1]] : in.y[sorted[k]];\n        int coord_r = split_x ? in.x[sorted[k]] : in.y[sorted[k]];\n        int cut = (coord_l + coord_r + 1) / 2;\n\n        cand.push_back({split_x, k, cut, 0});\n    }\n\n    sort(cand.begin(), cand.end(), [](const SplitCandidate& p, const SplitCandidate& q) {\n        return p.err < q.err;\n    });\n\n    SplitCandidate chosen = cand[0];\n\n    if (mode >= 4) {\n        int ktop = min<int>((mode <= 7 ? 3 : 7), cand.size());\n        uniform_int_distribution<int> dist(0, ktop - 1);\n        chosen = cand[dist(rng)];\n    }\n\n    vector<int> sorted = ids;\n    sort(sorted.begin(), sorted.end(), [&](int p, int q) {\n        if (chosen.split_x) return in.x[p] < in.x[q];\n        else return in.y[p] < in.y[q];\n    });\n\n    vector<int> left(sorted.begin(), sorted.begin() + chosen.k);\n    vector<int> right(sorted.begin() + chosen.k, sorted.end());\n\n    if (chosen.split_x) {\n        Rect lbox = {box.a, box.b, chosen.cut, box.d};\n        Rect rbox = {chosen.cut, box.b, box.c, box.d};\n\n        build_slice_rec(in, left, lbox, out, mode, depth + 1, rng);\n        build_slice_rec(in, right, rbox, out, mode, depth + 1, rng);\n    } else {\n        Rect lbox = {box.a, box.b, box.c, chosen.cut};\n        Rect rbox = {box.a, chosen.cut, box.c, box.d};\n\n        build_slice_rec(in, left, lbox, out, mode, depth + 1, rng);\n        build_slice_rec(in, right, rbox, out, mode, depth + 1, rng);\n    }\n}\n\nvector<Rect> solve_slice(const Input& in, mt19937& rng, int mode) {\n    int n = in.n;\n    vector<Rect> rects(n);\n    vector<int> ids(n);\n    iota(ids.begin(), ids.end(), 0);\n\n    build_slice_rec(in, ids, {0, 0, W, W}, rects, mode, 0, rng);\n\n    if (validate_solution(rects, in)) {\n        local_refine(rects, in, rng, 100);\n    }\n\n    return rects;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    start_time = chrono::steady_clock::now();\n\n    Input in;\n    cin >> in.n;\n    in.x.resize(in.n);\n    in.y.resize(in.n);\n    in.r.resize(in.n);\n\n    for (int i = 0; i < in.n; i++) {\n        cin >> in.x[i] >> in.y[i] >> in.r[i];\n    }\n\n    mt19937 rng(1234567);\n\n    vector<Rect> best;\n    double best_score = -1.0;\n\n    int mode = 0;\n\n    // Prioritize slicing.\n    while (elapsed() < TIME_LIMIT * 0.88) {\n        auto rects = solve_slice(in, rng, mode);\n\n        if (validate_solution(rects, in)) {\n            double sc = total_score(rects, in);\n            if (sc > best_score) {\n                best_score = sc;\n                best = rects;\n            }\n        }\n\n        mode++;\n        if (mode > 12) mode = 4;\n    }\n\n    // Greedy backup.\n    while (elapsed() < TIME_LIMIT) {\n        auto rects = solve_greedy_once(in, rng);\n\n        double sc = total_score(rects, in);\n\n        if (sc > best_score) {\n            best_score = sc;\n            best = rects;\n        }\n    }\n\n    if (best.empty()) {\n        best.resize(in.n);\n        for (int i = 0; i < in.n; i++) {\n            best[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n        }\n    }\n\n    if (!validate_solution(best, in)) {\n        for (int i = 0; i < in.n; i++) {\n            best[i] = {in.x[i], in.y[i], in.x[i] + 1, in.y[i] + 1};\n        }\n    }\n\n    for (int i = 0; i < in.n; i++) {\n        cout << best[i].a << ' ' << best[i].b << ' '\n             << best[i].c << ' ' << best[i].d << '\\n';\n    }\n\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXT = 2500;\nstatic constexpr double TIME_LIMIT = 1.995;\n\nint si, sj;\nint tile_id[N][N];\nint pval[N][N];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\ninline bool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() {\n        st = chrono::high_resolution_clock::now();\n    }\n    double elapsed() const {\n        auto now = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(now - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 11995408973635179863ULL;\n\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int next_int(int n) {\n        return (int)(next() % n);\n    }\n};\n\nstruct Candidate {\n    int dir;\n    int ni, nj;\n    int eval;\n};\n\nstruct Params {\n    int w_score;\n    int w_deg;\n    int w_near;\n    int w_best2;\n    int w_sum2;\n    int w_best3;\n    int noise;\n    int deg1_penalty;\n    int dead_penalty;\n    int random_pick_rate;\n};\n\nint visited_stamp[MAXT + 5];\nint cur_stamp = 1;\n\ninline bool visited(int tid) {\n    return visited_stamp[tid] == cur_stamp;\n}\n\ninline void set_visited(int tid) {\n    visited_stamp[tid] = cur_stamp;\n}\n\ninline void unset_visited(int tid) {\n    visited_stamp[tid] = 0;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n\n    int max_tile = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> tile_id[i][j];\n            max_tile = max(max_tile, tile_id[i][j]);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> pval[i][j];\n        }\n    }\n\n    const Params params[] = {\n        {100, 18, 3, 35, 1, 12, 150, 250, 2500, 17},\n        {120, 12, 2, 25, 1, 10, 220, 150, 2200, 20},\n        { 90, 45, 4, 30, 1, 10, 120, 400, 3000, 14},\n        {105,-20, 3, 20, 1,  8, 150,   0, 2000, 18},\n        {135,  5, 2, 15, 0,  5, 280,  80, 1800, 24},\n        { 95, 30, 7, 35, 1, 12, 180, 250, 2600, 18},\n        {110, 25, 1, 45, 0, 15, 170, 250, 2600, 16},\n        {100, 60, 2, 20, 0,  8, 100, 500, 3500, 12},\n        {150,  0, 1, 10, 0,  3, 350,  50, 1500, 28},\n        { 80, 70, 5, 25, 1,  8, 100, 600, 3800, 10},\n        {115,-35, 3, 25, 0,  7, 160,-100, 1700, 18},\n        {105, 20, 5, 40, 1, 14, 260, 200, 2400, 22},\n\n        {125, 18, 4, 32, 1, 12, 200, 200, 2300, 20},\n        { 85, 80, 3, 18, 0,  6,  80, 700, 4200,  8},\n        {160,-10, 1,  8, 0,  2, 400,   0, 1200, 30},\n        {100,-55, 2, 35, 0, 10, 180,-150, 1600, 20},\n        {115, 35, 6, 30, 1, 10, 150, 350, 3000, 15},\n        {130,  8, 5, 25, 1,  8, 250, 150, 2100, 24},\n        { 95, 55, 1, 40, 0, 16, 130, 450, 3300, 13},\n        {140, 15, 0, 20, 0,  6, 320, 100, 1800, 26}\n    };\n\n    constexpr int PARAM_COUNT = sizeof(params) / sizeof(params[0]);\n\n    Timer timer;\n    XorShift rng;\n\n    string best_path;\n    int best_score = pval[si][sj];\n\n    char path_buf[2600];\n\n    int iter = 0;\n\n    while (timer.elapsed() < TIME_LIMIT) {\n        iter++;\n\n        cur_stamp++;\n        if (cur_stamp > INT_MAX - 10) {\n            memset(visited_stamp, 0, sizeof(visited_stamp));\n            cur_stamp = 1;\n        }\n\n        int ci = si;\n        int cj = sj;\n        int score = pval[ci][cj];\n        int path_len = 0;\n\n        set_visited(tile_id[ci][cj]);\n\n        const Params& par = params[(iter + rng.next_int(PARAM_COUNT)) % PARAM_COUNT];\n\n        while (true) {\n            Candidate cand[4];\n            int cn = 0;\n\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d];\n                int nj = cj + dj[d];\n\n                if (!inside(ni, nj)) continue;\n\n                int tid = tile_id[ni][nj];\n                if (visited(tid)) continue;\n\n                set_visited(tid);\n\n                int deg = 0;\n                int near_score = 0;\n                int best2 = 0;\n                int sum2 = 0;\n                int best3 = 0;\n\n                for (int e = 0; e < 4; e++) {\n                    int xi = ni + di[e];\n                    int xj = nj + dj[e];\n\n                    if (!inside(xi, xj)) continue;\n\n                    int nt = tile_id[xi][xj];\n                    if (visited(nt)) continue;\n\n                    deg++;\n                    near_score += pval[xi][xj];\n\n                    set_visited(nt);\n\n                    int local_best2 = 0;\n                    int local_best3 = 0;\n\n                    for (int f = 0; f < 4; f++) {\n                        int yi = xi + di[f];\n                        int yj = xj + dj[f];\n\n                        if (!inside(yi, yj)) continue;\n\n                        int yt = tile_id[yi][yj];\n                        if (visited(yt)) continue;\n\n                        local_best2 = max(local_best2, pval[yi][yj]);\n\n                        set_visited(yt);\n\n                        int local3 = 0;\n\n                        for (int g = 0; g < 4; g++) {\n                            int zi = yi + di[g];\n                            int zj = yj + dj[g];\n\n                            if (!inside(zi, zj)) continue;\n\n                            int zt = tile_id[zi][zj];\n                            if (visited(zt)) continue;\n\n                            local3 = max(local3, pval[zi][zj]);\n                        }\n\n                        unset_visited(yt);\n\n                        local_best3 = max(local_best3, pval[yi][yj] + local3);\n                    }\n\n                    unset_visited(nt);\n\n                    best2 = max(best2, pval[xi][xj] + local_best2);\n                    best3 = max(best3, pval[xi][xj] + local_best3);\n                    sum2 += pval[xi][xj];\n                }\n\n                unset_visited(tid);\n\n                int eval = 0;\n                eval += par.w_score * pval[ni][nj];\n                eval += par.w_deg * deg;\n                eval += par.w_near * near_score;\n                eval += par.w_best2 * best2;\n                eval += par.w_sum2 * sum2;\n                eval += par.w_best3 * best3;\n                eval += rng.next_int(par.noise + 1);\n\n                if (deg == 0) eval -= par.dead_penalty;\n                else if (deg == 1) eval -= par.deg1_penalty;\n\n                cand[cn++] = {d, ni, nj, eval};\n            }\n\n            if (cn == 0) break;\n\n            sort(cand, cand + cn, [](const Candidate& a, const Candidate& b) {\n                return a.eval > b.eval;\n            });\n\n            int choose = 0;\n            int r = rng.next_int(100);\n\n            if (r < par.random_pick_rate) {\n                if (cn >= 4 && rng.next_int(100) < 8) {\n                    choose = 3;\n                } else if (cn >= 3 && rng.next_int(100) < 25) {\n                    choose = 2;\n                } else if (cn >= 2) {\n                    choose = 1;\n                }\n            }\n\n            Candidate c = cand[choose];\n\n            path_buf[path_len++] = dc[c.dir];\n\n            ci = c.ni;\n            cj = c.nj;\n\n            set_visited(tile_id[ci][cj]);\n            score += pval[ci][cj];\n        }\n\n        if (score > best_score) {\n            best_score = score;\n            best_path.assign(path_buf, path_buf + path_len);\n        }\n    }\n\n    cout << best_path << '\\n';\n\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N;\nstatic constexpr int Q = 1000;\n\nstruct UsedEdge {\n    int type; // 0: horizontal, 1: vertical\n    int a, b;\n};\n\nstruct Obs {\n    array<unsigned char, N> row{};\n    array<unsigned char, N> col{};\n    int measured = 0;\n};\n\ndouble h_edge[N][N - 1];\ndouble v_edge[N - 1][N];\nint h_cnt[N][N - 1];\nint v_cnt[N - 1][N];\n\ndouble row_cost[N];\ndouble col_cost[N];\n\nvector<UsedEdge> prev_edges;\nvector<Obs> observations;\n\nmt19937 rng(1234567);\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\npair<int,int> pos(int x) {\n    return {x / N, x % N};\n}\n\ndouble clamp_cost(double x) {\n    return max(100.0, min(10000.0, x));\n}\n\ndouble get_h_cost(int i, int j, int turn) {\n    double coarse = row_cost[i];\n    double local = h_edge[i][j];\n\n    double local_w = min(0.45, h_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\ndouble get_v_cost(int i, int j, int turn) {\n    double coarse = col_cost[j];\n    double local = v_edge[i][j];\n\n    double local_w = min(0.45, v_cnt[i][j] / 8.0);\n    if (turn < 80) local_w *= 0.4;\n    else if (turn < 250) local_w *= 0.7;\n\n    return clamp_cost((1.0 - local_w) * coarse + local_w * local);\n}\n\ndouble mono_h_cost(int i, int j, int turn) {\n    double local_w = min(0.20, h_cnt[i][j] / 20.0);\n    if (turn < 300) local_w *= 0.5;\n\n    return clamp_cost((1.0 - local_w) * row_cost[i] + local_w * h_edge[i][j]);\n}\n\ndouble mono_v_cost(int i, int j, int turn) {\n    double local_w = min(0.20, v_cnt[i][j] / 20.0);\n    if (turn < 300) local_w *= 0.5;\n\n    return clamp_cost((1.0 - local_w) * col_cost[j] + local_w * v_edge[i][j]);\n}\n\nvector<UsedEdge> path_edges(int si, int sj, const string& path) {\n    vector<UsedEdge> edges;\n    int i = si, j = sj;\n\n    for (char c : path) {\n        if (c == 'U') {\n            edges.push_back({1, i - 1, j});\n            --i;\n        } else if (c == 'D') {\n            edges.push_back({1, i, j});\n            ++i;\n        } else if (c == 'L') {\n            edges.push_back({0, i, j - 1});\n            --j;\n        } else if (c == 'R') {\n            edges.push_back({0, i, j});\n            ++j;\n        }\n    }\n\n    return edges;\n}\n\nObs make_obs(const vector<UsedEdge>& edges, int measured) {\n    Obs o;\n    o.measured = measured;\n\n    for (auto &e : edges) {\n        if (e.type == 0) o.row[e.a]++;\n        else o.col[e.b]++;\n    }\n\n    return o;\n}\n\nstring manhattan_path(int si, int sj, int ti, int tj, bool vertical_first) {\n    string s;\n\n    if (vertical_first) {\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n    } else {\n        while (sj < tj) s.push_back('R'), ++sj;\n        while (sj > tj) s.push_back('L'), --sj;\n        while (si < ti) s.push_back('D'), ++si;\n        while (si > ti) s.push_back('U'), --si;\n    }\n\n    return s;\n}\n\nstring randomized_manhattan(int si, int sj, int ti, int tj) {\n    string s;\n    int i = si, j = sj;\n\n    while (i != ti || j != tj) {\n        vector<char> cand;\n        if (i < ti) cand.push_back('D');\n        if (i > ti) cand.push_back('U');\n        if (j < tj) cand.push_back('R');\n        if (j > tj) cand.push_back('L');\n\n        char c = cand[rng() % cand.size()];\n        s.push_back(c);\n\n        if (c == 'D') ++i;\n        else if (c == 'U') --i;\n        else if (c == 'R') ++j;\n        else --j;\n    }\n\n    return s;\n}\n\nstring monotone_dp_path(int si, int sj, int ti, int tj, int turn) {\n    int di = (ti >= si ? 1 : -1);\n    int dj = (tj >= sj ? 1 : -1);\n\n    int H = abs(ti - si);\n    int W = abs(tj - sj);\n\n    vector<vector<double>> dp(H + 1, vector<double>(W + 1, 1e100));\n    vector<vector<char>> par(H + 1, vector<char>(W + 1, '?'));\n\n    dp[0][0] = 0.0;\n\n    for (int a = 0; a <= H; a++) {\n        for (int b = 0; b <= W; b++) {\n            int i = si + di * a;\n            int j = sj + dj * b;\n\n            if (a < H) {\n                double w;\n                char c;\n\n                if (di == 1) {\n                    w = mono_v_cost(i, j, turn);\n                    c = 'D';\n                } else {\n                    w = mono_v_cost(i - 1, j, turn);\n                    c = 'U';\n                }\n\n                if (dp[a + 1][b] > dp[a][b] + w) {\n                    dp[a + 1][b] = dp[a][b] + w;\n                    par[a + 1][b] = c;\n                }\n            }\n\n            if (b < W) {\n                double w;\n                char c;\n\n                if (dj == 1) {\n                    w = mono_h_cost(i, j, turn);\n                    c = 'R';\n                } else {\n                    w = mono_h_cost(i, j - 1, turn);\n                    c = 'L';\n                }\n\n                if (dp[a][b + 1] > dp[a][b] + w) {\n                    dp[a][b + 1] = dp[a][b] + w;\n                    par[a][b + 1] = c;\n                }\n            }\n        }\n    }\n\n    string res;\n    int a = H, b = W;\n\n    while (a > 0 || b > 0) {\n        char c = par[a][b];\n        res.push_back(c);\n\n        if (c == 'D' || c == 'U') --a;\n        else --b;\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nstring dijkstra_path(int si, int sj, int ti, int tj, int turn) {\n    vector<double> dist(V, 1e100);\n    vector<int> par(V, -1);\n    vector<char> pch(V, '?');\n\n    priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n\n    int S0 = id(si, sj);\n    int T0 = id(ti, tj);\n\n    dist[S0] = 0.0;\n    pq.push({0.0, S0});\n\n    while (!pq.empty()) {\n        auto [d, x] = pq.top();\n        pq.pop();\n\n        if (d != dist[x]) continue;\n        if (x == T0) break;\n\n        auto [i, j] = pos(x);\n\n        auto relax = [&](int ni, int nj, double w, char c) {\n            int y = id(ni, nj);\n            if (dist[y] > d + w) {\n                dist[y] = d + w;\n                par[y] = x;\n                pch[y] = c;\n                pq.push({dist[y], y});\n            }\n        };\n\n        if (i > 0) relax(i - 1, j, get_v_cost(i - 1, j, turn), 'U');\n        if (i + 1 < N) relax(i + 1, j, get_v_cost(i, j, turn), 'D');\n        if (j > 0) relax(i, j - 1, get_h_cost(i, j - 1, turn), 'L');\n        if (j + 1 < N) relax(i, j + 1, get_h_cost(i, j, turn), 'R');\n    }\n\n    string res;\n    int cur = T0;\n\n    while (cur != S0) {\n        if (cur < 0 || pch[cur] == '?') {\n            return manhattan_path(si, sj, ti, tj, true);\n        }\n\n        res.push_back(pch[cur]);\n        cur = par[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nbool valid_simple_path(int si, int sj, int ti, int tj, const string& s) {\n    bool seen[N][N] = {};\n    int i = si, j = sj;\n    seen[i][j] = true;\n\n    for (char c : s) {\n        if (c == 'U') --i;\n        else if (c == 'D') ++i;\n        else if (c == 'L') --j;\n        else if (c == 'R') ++j;\n        else return false;\n\n        if (i < 0 || i >= N || j < 0 || j >= N) return false;\n        if (seen[i][j]) return false;\n        seen[i][j] = true;\n    }\n\n    return i == ti && j == tj;\n}\n\nvoid replay_fit_rowcol(int turn) {\n    if (observations.size() < 30) return;\n\n    int epochs = (turn > 300 ? 3 : 2);\n\n    double lr = 0.017;\n    if (turn > 300) lr = 0.010;\n    if (turn > 700) lr = 0.007;\n\n    for (int ep = 0; ep < epochs; ep++) {\n        for (const auto &o : observations) {\n            double pred = 0.0;\n            double norm = 1e-9;\n\n            for (int i = 0; i < N; i++) {\n                pred += row_cost[i] * o.row[i];\n                norm += int(o.row[i]) * int(o.row[i]);\n            }\n            for (int j = 0; j < N; j++) {\n                pred += col_cost[j] * o.col[j];\n                norm += int(o.col[j]) * int(o.col[j]);\n            }\n\n            double ratio = o.measured / max(1.0, pred);\n            ratio = max(0.85, min(1.15, ratio));\n            double err = pred * ratio - pred;\n\n            for (int i = 0; i < N; i++) {\n                if (o.row[i]) {\n                    row_cost[i] += lr * err * o.row[i] / norm;\n                    row_cost[i] = clamp_cost(row_cost[i]);\n                }\n            }\n            for (int j = 0; j < N; j++) {\n                if (o.col[j]) {\n                    col_cost[j] += lr * err * o.col[j] / norm;\n                    col_cost[j] = clamp_cost(col_cost[j]);\n                }\n            }\n        }\n    }\n}\n\nvoid update_from_result(int measured, int turn) {\n    if (prev_edges.empty()) return;\n\n    observations.push_back(make_obs(prev_edges, measured));\n\n    int row_use[N] = {};\n    int col_use[N] = {};\n\n    double pred_coarse = 0.0;\n    double pred_edge = 0.0;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            row_use[e.a]++;\n            pred_coarse += row_cost[e.a];\n            pred_edge += h_edge[e.a][e.b];\n        } else {\n            col_use[e.b]++;\n            pred_coarse += col_cost[e.b];\n            pred_edge += v_edge[e.a][e.b];\n        }\n    }\n\n    double pred = 0.75 * pred_coarse + 0.25 * pred_edge;\n    if (pred <= 1.0) return;\n\n    double ratio = measured / pred;\n    ratio = max(0.75, min(1.25, ratio));\n    double target = pred * ratio;\n    double err = target - pred;\n\n    double norm = 1e-9;\n    for (int i = 0; i < N; i++) norm += row_use[i] * row_use[i];\n    for (int j = 0; j < N; j++) norm += col_use[j] * col_use[j];\n\n    double lr = 0.55;\n    if (turn > 100) lr = 0.42;\n    if (turn > 300) lr = 0.32;\n    if (turn > 600) lr = 0.24;\n\n    for (int i = 0; i < N; i++) {\n        if (row_use[i]) {\n            row_cost[i] += lr * err * row_use[i] / norm;\n            row_cost[i] = clamp_cost(row_cost[i]);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        if (col_use[j]) {\n            col_cost[j] += lr * err * col_use[j] / norm;\n            col_cost[j] = clamp_cost(col_cost[j]);\n        }\n    }\n\n    double edge_norm = max(1, (int)prev_edges.size());\n    double edge_lr = 0.20;\n    if (turn > 200) edge_lr = 0.16;\n    if (turn > 600) edge_lr = 0.11;\n\n    double per_edge_delta = edge_lr * err / edge_norm;\n\n    for (auto &e : prev_edges) {\n        if (e.type == 0) {\n            int i = e.a, j = e.b;\n            h_edge[i][j] += per_edge_delta;\n            h_edge[i][j] = clamp_cost(h_edge[i][j]);\n            h_cnt[i][j]++;\n\n            h_edge[i][j] = 0.985 * h_edge[i][j] + 0.015 * row_cost[i];\n        } else {\n            int i = e.a, j = e.b;\n            v_edge[i][j] += per_edge_delta;\n            v_edge[i][j] = clamp_cost(v_edge[i][j]);\n            v_cnt[i][j]++;\n\n            v_edge[i][j] = 0.985 * v_edge[i][j] + 0.015 * col_cost[j];\n        }\n    }\n\n    if (turn % 20 == 0) {\n        replay_fit_rowcol(turn);\n    }\n}\n\nstring choose_path(int si, int sj, int ti, int tj, int turn) {\n    if (turn < 20) {\n        if (turn % 3 == 0) return manhattan_path(si, sj, ti, tj, true);\n        if (turn % 3 == 1) return manhattan_path(si, sj, ti, tj, false);\n        return randomized_manhattan(si, sj, ti, tj);\n    }\n\n    if (turn < 90) {\n        return monotone_dp_path(si, sj, ti, tj, turn);\n    }\n\n    string best = dijkstra_path(si, sj, ti, tj, turn);\n\n    int manhattan = abs(si - ti) + abs(sj - tj);\n    if ((int)best.size() > manhattan + 16 && turn < 300) {\n        best = monotone_dp_path(si, sj, ti, tj, turn);\n    }\n\n    if (turn < 260 && turn % 17 == 0) {\n        string alt = monotone_dp_path(si, sj, ti, tj, turn);\n        if ((int)alt.size() <= (int)best.size() + 4) {\n            best = alt;\n        }\n    }\n\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < N; i++) {\n        row_cost[i] = 5000.0;\n        for (int j = 0; j < N - 1; j++) {\n            h_edge[i][j] = 5000.0;\n            h_cnt[i][j] = 0;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        col_cost[j] = 5000.0;\n    }\n\n    for (int i = 0; i < N - 1; i++) {\n        for (int j = 0; j < N; j++) {\n            v_edge[i][j] = 5000.0;\n            v_cnt[i][j] = 0;\n        }\n    }\n\n    int measured = -1;\n\n    for (int turn = 0; turn < Q; turn++) {\n        int si, sj, ti, tj;\n        if (!(cin >> si >> sj >> ti >> tj)) return 0;\n\n        if (turn > 0) {\n            update_from_result(measured, turn);\n        }\n\n        string ans = choose_path(si, sj, ti, tj, turn);\n\n        if (!valid_simple_path(si, sj, ti, tj, ans)) {\n            ans = manhattan_path(si, sj, ti, tj, true);\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        prev_edges = path_edges(si, sj, ans);\n\n        cin >> measured;\n    }\n\n    return 0;\n}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 20;\nstatic const int MAXM = 800;\nstatic const string ALPHA = \"ABCDEFGH\";\n\nint M;\nvector<string> S;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nbool cyclic_contains(const string& line, const string& pat) {\n    int L = (int)line.size();\n    int K = (int)pat.size();\n\n    for (int st = 0; st < L; ++st) {\n        bool ok = true;\n        for (int p = 0; p < K; ++p) {\n            if (line[(st + p) % L] != pat[p]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n\n    return false;\n}\n\nint overlap_suffix_prefix(const string& a, const string& b) {\n    int la = (int)a.size();\n    int lb = (int)b.size();\n    int lim = min(la, lb);\n\n    for (int k = lim; k >= 1; --k) {\n        bool ok = true;\n        for (int i = 0; i < k; ++i) {\n            if (a[la - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n\n    return 0;\n}\n\nstring rotate_str(const string& s, int sh) {\n    sh %= N;\n    if (sh < 0) sh += N;\n    return s.substr(sh) + s.substr(0, sh);\n}\n\nstring canonical_rotation(const string& s) {\n    string best = s;\n    for (int sh = 1; sh < (int)s.size(); ++sh) {\n        string t = s.substr(sh) + s.substr(0, sh);\n        if (t < best) best = t;\n    }\n    return best;\n}\n\nstruct Cand {\n    string line;\n    bitset<MAXM> cover;\n    int cnt;\n};\n\nbitset<MAXM> calc_cover(const string& line) {\n    bitset<MAXM> bs;\n    for (int i = 0; i < M; ++i) {\n        if (cyclic_contains(line, S[i])) bs.set(i);\n    }\n    return bs;\n}\n\nint gain_count(const bitset<MAXM>& cover, const bitset<MAXM>& used) {\n    return (int)(cover & (~used)).count();\n}\n\nstring extend_random_to_20(string t, mt19937& rng, char fillChar) {\n    while ((int)t.size() < N) {\n        if ((rng() % 100) < 75) t += ALPHA[rng() % 8];\n        else t += fillChar;\n    }\n\n    if ((int)t.size() > N) t.resize(N);\n    return t;\n}\n\nstring complete_sampled(string cur, mt19937& rng, int mode) {\n    for (int step = 0; step < 8 && (int)cur.size() < N; ++step) {\n        int bestId = -1;\n        int bestOv = -1;\n        string bestMerge;\n\n        for (int rep = 0; rep < 48; ++rep) {\n            int id = rng() % M;\n            const string& b = S[id];\n\n            if (cur.find(b) != string::npos) continue;\n\n            if (mode != 2) {\n                int ov1 = overlap_suffix_prefix(cur, b);\n                int len1 = (int)cur.size() + (int)b.size() - ov1;\n\n                if (len1 <= N) {\n                    int score = ov1 * 10 + ((mode == 1) ? 2 : 0);\n                    if (score > bestOv) {\n                        bestOv = score;\n                        bestId = id;\n                        bestMerge = cur + b.substr(ov1);\n                    }\n                }\n            }\n\n            if (mode != 1) {\n                int ov2 = overlap_suffix_prefix(b, cur);\n                int len2 = (int)cur.size() + (int)b.size() - ov2;\n\n                if (len2 <= N) {\n                    int score = ov2 * 10 + ((mode == 2) ? 2 : 0);\n                    if (score > bestOv) {\n                        bestOv = score;\n                        bestId = id;\n                        bestMerge = b + cur.substr(ov2);\n                    }\n                }\n            }\n        }\n\n        if (bestId == -1 || bestOv < 20) break;\n        cur = bestMerge;\n    }\n\n    return cur;\n}\n\nvoid add_candidate_line(\n    vector<Cand>& cands,\n    unordered_set<string>& seen,\n    const string& t\n) {\n    if ((int)t.size() != N) return;\n\n    string can = canonical_rotation(t);\n    if (!seen.insert(can).second) return;\n\n    bitset<MAXM> cov = calc_cover(t);\n    int cnt = (int)cov.count();\n\n    if (cnt > 0) {\n        cands.push_back({t, cov, cnt});\n    }\n}\n\nvoid add_candidate(\n    vector<Cand>& cands,\n    unordered_set<string>& seen,\n    string t,\n    mt19937& rng,\n    char fillChar,\n    bool variants\n) {\n    if ((int)t.size() > N) return;\n\n    if ((int)t.size() == N) {\n        add_candidate_line(cands, seen, t);\n        return;\n    }\n\n    string base = t;\n\n    if (variants && (rng() % 100) < 35) {\n        for (int mode = 0; mode < 3; ++mode) {\n            string u = complete_sampled(base, rng, mode);\n            u = extend_random_to_20(u, rng, fillChar);\n            add_candidate_line(cands, seen, u);\n        }\n    } else {\n        if ((rng() % 100) < 55) {\n            t = complete_sampled(t, rng, 0);\n        }\n        t = extend_random_to_20(t, rng, fillChar);\n        add_candidate_line(cands, seen, t);\n    }\n}\n\nvector<Cand> generate_candidates(mt19937& rng, Timer& timer) {\n    vector<int> freq(8, 0);\n    for (const string& s : S) {\n        for (char c : s) freq[c - 'A']++;\n    }\n\n    int bestCharId = max_element(freq.begin(), freq.end()) - freq.begin();\n    char fillChar = ALPHA[bestCharId];\n\n    vector<Cand> cands;\n    unordered_set<string> seen;\n    seen.reserve(18000);\n\n    for (const string& s : S) {\n        add_candidate(cands, seen, s, rng, fillChar, true);\n    }\n\n    int trials = 0;\n\n    while (timer.elapsed() < 1.02 && trials < 6200) {\n        trials++;\n\n        string cur = S[rng() % M];\n\n        for (int step = 0; step < 8; ++step) {\n            int bestId = -1;\n            int bestOvScore = -1;\n            string bestMerge;\n\n            for (int rep = 0; rep < 36; ++rep) {\n                int id = rng() % M;\n                const string& b = S[id];\n\n                if (cur.find(b) != string::npos) {\n                    bestId = id;\n                    bestOvScore = 10000;\n                    bestMerge = cur;\n                    break;\n                }\n\n                int ov1 = overlap_suffix_prefix(cur, b);\n                int len1 = (int)cur.size() + (int)b.size() - ov1;\n\n                if (len1 <= N) {\n                    int score = ov1 * 10 + (int)b.size();\n                    if (score > bestOvScore) {\n                        bestOvScore = score;\n                        bestId = id;\n                        bestMerge = cur + b.substr(ov1);\n                    }\n                }\n\n                int ov2 = overlap_suffix_prefix(b, cur);\n                int len2 = (int)cur.size() + (int)b.size() - ov2;\n\n                if (len2 <= N) {\n                    int score = ov2 * 10 + (int)b.size();\n                    if (score > bestOvScore) {\n                        bestOvScore = score;\n                        bestId = id;\n                        bestMerge = b + cur.substr(ov2);\n                    }\n                }\n            }\n\n            if (bestId == -1 || bestOvScore < 20) break;\n\n            cur = bestMerge;\n            add_candidate(cands, seen, cur, rng, fillChar, false);\n        }\n\n        add_candidate(cands, seen, cur, rng, fillChar, true);\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n        if (a.cnt != b.cnt) return a.cnt > b.cnt;\n        return a.line < b.line;\n    });\n\n    if ((int)cands.size() > 2100) {\n        vector<Cand> kept;\n        int strong = 1700;\n        for (int i = 0; i < strong; ++i) kept.push_back(cands[i]);\n\n        vector<Cand> rest;\n        for (int i = strong; i < (int)cands.size(); ++i) rest.push_back(cands[i]);\n        shuffle(rest.begin(), rest.end(), rng);\n\n        int extra = min(400, (int)rest.size());\n        for (int i = 0; i < extra; ++i) kept.push_back(rest[i]);\n\n        cands.swap(kept);\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n        if (a.cnt != b.cnt) return a.cnt > b.cnt;\n        return a.line < b.line;\n    });\n\n    return cands;\n}\n\nvector<string> greedy_select_rows(const vector<Cand>& cands, mt19937& rng, bitset<MAXM>& usedOut) {\n    bitset<MAXM> used;\n    vector<string> rows;\n\n    for (int step = 0; step < N; ++step) {\n        int best = -1;\n        int bestGain = -1;\n\n        for (int i = 0; i < (int)cands.size(); ++i) {\n            int gain = gain_count(cands[i].cover, used);\n            if (gain > bestGain) {\n                bestGain = gain;\n                best = i;\n            }\n        }\n\n        if (best == -1 || bestGain <= 0) break;\n\n        rows.push_back(cands[best].line);\n        used |= cands[best].cover;\n    }\n\n    while ((int)rows.size() < N) {\n        rows.push_back(string(N, ALPHA[rng() % 8]));\n    }\n\n    usedOut = used;\n    return rows;\n}\n\nvector<string> local_replace_rows(\n    vector<string> rows,\n    const vector<Cand>& cands,\n    Timer& timer\n) {\n    vector<bitset<MAXM>> rowCov(N);\n\n    for (int i = 0; i < N; ++i) rowCov[i] = calc_cover(rows[i]);\n\n    bitset<MAXM> used;\n    for (int i = 0; i < N; ++i) used |= rowCov[i];\n\n    int curScore = (int)used.count();\n    int candLim = min((int)cands.size(), 1100);\n\n    bool improved = true;\n\n    while (improved && timer.elapsed() < 2.42) {\n        improved = false;\n\n        for (int r = 0; r < N && timer.elapsed() < 2.42; ++r) {\n            bitset<MAXM> without;\n            for (int i = 0; i < N; ++i) {\n                if (i != r) without |= rowCov[i];\n            }\n\n            int bestScore = curScore;\n            int bestCand = -1;\n\n            for (int ci = 0; ci < candLim; ++ci) {\n                bitset<MAXM> tmp = without | cands[ci].cover;\n                int sc = (int)tmp.count();\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestCand = ci;\n                }\n            }\n\n            if (bestCand != -1) {\n                rows[r] = cands[bestCand].line;\n                rowCov[r] = cands[bestCand].cover;\n                used = without | rowCov[r];\n                curScore = bestScore;\n                improved = true;\n            }\n        }\n    }\n\n    return rows;\n}\n\nvector<string> local_replace_two_rows(\n    vector<string> rows,\n    const vector<Cand>& cands,\n    Timer& timer\n) {\n    vector<bitset<MAXM>> rowCov(N);\n    for (int i = 0; i < N; ++i) rowCov[i] = calc_cover(rows[i]);\n\n    bitset<MAXM> used;\n    for (int i = 0; i < N; ++i) used |= rowCov[i];\n    int curScore = (int)used.count();\n\n    int candLim = min((int)cands.size(), 700);\n\n    bool improved = true;\n\n    while (improved && timer.elapsed() < 2.52) {\n        improved = false;\n\n        for (int r1 = 0; r1 < N && timer.elapsed() < 2.52; ++r1) {\n            for (int r2 = r1 + 1; r2 < N && timer.elapsed() < 2.52; ++r2) {\n                bitset<MAXM> base;\n                for (int i = 0; i < N; ++i) {\n                    if (i != r1 && i != r2) base |= rowCov[i];\n                }\n\n                int bestA = -1;\n                int bestB = -1;\n                int bestScore = curScore;\n\n                int firstBest = -1;\n                int firstBestScore = -1;\n\n                for (int a = 0; a < candLim; ++a) {\n                    int sc = (int)(base | cands[a].cover).count();\n                    if (sc > firstBestScore) {\n                        firstBestScore = sc;\n                        firstBest = a;\n                    }\n                }\n\n                if (firstBest == -1) continue;\n\n                bitset<MAXM> base2 = base | cands[firstBest].cover;\n\n                for (int b = 0; b < candLim; ++b) {\n                    if (b == firstBest) continue;\n                    int sc = (int)(base2 | cands[b].cover).count();\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestA = firstBest;\n                        bestB = b;\n                    }\n                }\n\n                if (bestA != -1 && bestB != -1 && bestScore > curScore) {\n                    rows[r1] = cands[bestA].line;\n                    rows[r2] = cands[bestB].line;\n                    rowCov[r1] = cands[bestA].cover;\n                    rowCov[r2] = cands[bestB].cover;\n\n                    used = base | rowCov[r1] | rowCov[r2];\n                    curScore = bestScore;\n                    improved = true;\n                    goto NEXT_PASS;\n                }\n            }\n        }\n\nNEXT_PASS:\n        ;\n    }\n\n    return rows;\n}\n\nvector<string> randomized_select_rows(\n    const vector<Cand>& cands,\n    mt19937& rng,\n    Timer& timer,\n    bitset<MAXM>& bestUsedOut\n) {\n    vector<string> bestRows = greedy_select_rows(cands, rng, bestUsedOut);\n    int bestScore = (int)bestUsedOut.count();\n\n    int C = (int)cands.size();\n\n    while (timer.elapsed() < 2.16) {\n        bitset<MAXM> used;\n        vector<string> rows;\n\n        for (int step = 0; step < N; ++step) {\n            vector<pair<int, int>> top;\n            top.reserve(10);\n\n            int lim = min(C, 1100);\n\n            for (int i = 0; i < lim; ++i) {\n                int gain = gain_count(cands[i].cover, used);\n                if (gain <= 0) continue;\n\n                if ((int)top.size() < 10) {\n                    top.push_back({gain, i});\n                    sort(top.rbegin(), top.rend());\n                } else if (gain > top.back().first) {\n                    top.back() = {gain, i};\n                    sort(top.rbegin(), top.rend());\n                }\n            }\n\n            if (top.empty()) break;\n\n            int chooseRange = min((int)top.size(), 4);\n            int pick = rng() % chooseRange;\n\n            int id = top[pick].second;\n            rows.push_back(cands[id].line);\n            used |= cands[id].cover;\n        }\n\n        while ((int)rows.size() < N) {\n            rows.push_back(string(N, ALPHA[rng() % 8]));\n        }\n\n        int sc = (int)used.count();\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            bestRows = rows;\n            bestUsedOut = used;\n        }\n    }\n\n    bestRows = local_replace_rows(bestRows, cands, timer);\n\n    if (timer.elapsed() < 2.45) {\n        bestRows = local_replace_two_rows(bestRows, cands, timer);\n    }\n\n    bestUsedOut.reset();\n    for (const string& row : bestRows) {\n        bestUsedOut |= calc_cover(row);\n    }\n\n    return bestRows;\n}\n\nbitset<MAXM> vertical_cover_bitset(const vector<string>& grid) {\n    vector<string> cols(N, string(N, 'A'));\n\n    for (int j = 0; j < N; ++j) {\n        for (int i = 0; i < N; ++i) cols[j][i] = grid[i][j];\n    }\n\n    bitset<MAXM> bs;\n\n    for (int idx = 0; idx < M; ++idx) {\n        for (int j = 0; j < N; ++j) {\n            if (cyclic_contains(cols[j], S[idx])) {\n                bs.set(idx);\n                break;\n            }\n        }\n    }\n\n    return bs;\n}\n\nbitset<MAXM> grid_cover_bitset(const vector<string>& grid) {\n    bitset<MAXM> bs;\n\n    for (int i = 0; i < N; ++i) {\n        bs |= calc_cover(grid[i]);\n    }\n\n    bs |= vertical_cover_bitset(grid);\n    return bs;\n}\n\nvector<string> optimize_row_order_and_shifts(\n    vector<string> grid,\n    const bitset<MAXM>& rowCoverFixed,\n    mt19937& rng,\n    Timer& timer\n) {\n    auto score_grid = [&](const vector<string>& g) -> int {\n        bitset<MAXM> bs = rowCoverFixed | vertical_cover_bitset(g);\n        return (int)bs.count();\n    };\n\n    int bestScore = score_grid(grid);\n    vector<string> bestGrid = grid;\n\n    while (timer.elapsed() < 2.73) {\n        vector<string> cur = bestGrid;\n\n        if ((rng() % 100) < 65) {\n            shuffle(cur.begin(), cur.end(), rng);\n        }\n\n        for (int i = 0; i < N; ++i) {\n            if ((rng() % 100) < 60) {\n                cur[i] = rotate_str(cur[i], rng() % N);\n            }\n        }\n\n        int curScore = score_grid(cur);\n\n        if (curScore > bestScore) {\n            bestScore = curScore;\n            bestGrid = cur;\n        }\n\n        int stagnant = 0;\n\n        while (timer.elapsed() < 2.73 && stagnant < 220) {\n            vector<string> nxt = cur;\n\n            int op = rng() % 100;\n\n            if (op < 45) {\n                int a = rng() % N;\n                int b = rng() % N;\n                if (a == b) continue;\n                swap(nxt[a], nxt[b]);\n            } else {\n                int r = rng() % N;\n                int sh = 1 + (rng() % (N - 1));\n                nxt[r] = rotate_str(nxt[r], sh);\n            }\n\n            int sc = score_grid(nxt);\n\n            if (sc >= curScore) {\n                cur.swap(nxt);\n                curScore = sc;\n                stagnant = 0;\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestGrid = cur;\n                }\n            } else {\n                stagnant++;\n            }\n        }\n    }\n\n    return bestGrid;\n}\n\nvector<string> improve_columns_tiny(\n    vector<string> grid,\n    const vector<Cand>& cands,\n    mt19937& rng,\n    Timer& timer\n) {\n    bitset<MAXM> curCover = grid_cover_bitset(grid);\n    int curScore = (int)curCover.count();\n\n    vector<int> colOrder(N);\n    iota(colOrder.begin(), colOrder.end(), 0);\n    shuffle(colOrder.begin(), colOrder.end(), rng);\n\n    int candLim = min((int)cands.size(), 25);\n\n    for (int col : colOrder) {\n        if (timer.elapsed() > 2.84) break;\n\n        int bestScore = curScore;\n        string bestCol;\n        bool improved = false;\n\n        for (int ci = 0; ci < candLim; ++ci) {\n            if (timer.elapsed() > 2.84) break;\n\n            const string& line = cands[ci].line;\n\n            for (int sh = 0; sh < N; sh += 2) {\n                vector<string> tmp = grid;\n\n                for (int i = 0; i < N; ++i) tmp[i][col] = line[(i + sh) % N];\n\n                int sc = (int)grid_cover_bitset(tmp).count();\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestCol.clear();\n                    for (int i = 0; i < N; ++i) bestCol.push_back(line[(i + sh) % N]);\n                    improved = true;\n                }\n            }\n        }\n\n        if (improved) {\n            for (int i = 0; i < N; ++i) grid[i][col] = bestCol[i];\n            curScore = bestScore;\n        }\n    }\n\n    return grid;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int inputN;\n    cin >> inputN >> M;\n\n    S.resize(M);\n    for (int i = 0; i < M; ++i) cin >> S[i];\n\n    Timer timer;\n    mt19937 rng(123456789);\n\n    vector<Cand> cands = generate_candidates(rng, timer);\n\n    if (cands.empty()) {\n        for (int i = 0; i < N; ++i) {\n            cout << string(N, 'A') << '\\n';\n        }\n        return 0;\n    }\n\n    bitset<MAXM> rowUsed;\n    vector<string> rows = randomized_select_rows(cands, rng, timer, rowUsed);\n\n    vector<string> grid = rows;\n\n    bitset<MAXM> rowCoverFixed;\n    for (const string& r : rows) {\n        rowCoverFixed |= calc_cover(r);\n    }\n\n    if (timer.elapsed() < 2.55) {\n        grid = optimize_row_order_and_shifts(grid, rowCoverFixed, rng, timer);\n    }\n\n    if (timer.elapsed() < 2.76) {\n        grid = improve_columns_tiny(grid, cands, rng, timer);\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << grid[i] << '\\n';\n    }\n\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct PQNode {\n    int d, v;\n    bool operator<(const PQNode& other) const {\n        return d > other.d;\n    }\n};\n\nstruct DijkstraResult {\n    vector<int> dist;\n    vector<int> par;\n    vector<int> parDir;\n};\n\nstruct CandidateSolution {\n    long long cost = (1LL << 60);\n    vector<int> nodes;\n    vector<int> route;\n    vector<vector<int>> distMat;\n    vector<DijkstraResult> dijs;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, si, sj;\n    cin >> N >> si >> sj;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    const int V = N * N;\n    const int INF = 1e9;\n\n    auto id = [&](int i, int j) {\n        return i * N + j;\n    };\n\n    auto pos = [&](int v) {\n        return pair<int,int>{v / N, v % N};\n    };\n\n    auto inside = [&](int i, int j) {\n        return 0 <= i && i < N && 0 <= j && j < N;\n    };\n\n    vector<int> isroad(V, 0), weight(V, 0), road_ids;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (grid[i][j] != '#') {\n                int v = id(i, j);\n                isroad[v] = 1;\n                weight[v] = grid[i][j] - '0';\n                road_ids.push_back(v);\n            }\n        }\n    }\n\n    int R = (int)road_ids.size();\n    int start = id(si, sj);\n\n    vector<vector<int>> visible(V);\n\n    vector<int> hid(V, -1), vid(V, -1);\n    vector<vector<int>> hsegCells, vsegCells;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (grid[i][j] == '#') {\n                j++;\n                continue;\n            }\n\n            vector<int> seg;\n            int k = j;\n            while (k < N && grid[i][k] != '#') {\n                int v = id(i, k);\n                hid[v] = (int)hsegCells.size();\n                seg.push_back(v);\n                k++;\n            }\n\n            hsegCells.push_back(seg);\n\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n\n            j = k;\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (grid[i][j] == '#') {\n                i++;\n                continue;\n            }\n\n            vector<int> seg;\n            int k = i;\n            while (k < N && grid[k][j] != '#') {\n                int v = id(k, j);\n                vid[v] = (int)vsegCells.size();\n                seg.push_back(v);\n                k++;\n            }\n\n            vsegCells.push_back(seg);\n\n            for (int v : seg) {\n                visible[v].insert(visible[v].end(), seg.begin(), seg.end());\n            }\n\n            i = k;\n        }\n    }\n\n    for (int v : road_ids) {\n        auto &a = visible[v];\n        sort(a.begin(), a.end());\n        a.erase(unique(a.begin(), a.end()), a.end());\n    }\n\n    int H = (int)hsegCells.size();\n    int W = (int)vsegCells.size();\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    auto dijkstra = [&](int s) {\n        DijkstraResult res;\n        res.dist.assign(V, INF);\n        res.par.assign(V, -1);\n        res.parDir.assign(V, -1);\n\n        priority_queue<PQNode> pq;\n        res.dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, v] = pq.top();\n            pq.pop();\n\n            if (d != res.dist[v]) continue;\n\n            auto [i, j] = pos(v);\n\n            for (int z = 0; z < 4; z++) {\n                int ni = i + di[z];\n                int nj = j + dj[z];\n\n                if (!inside(ni, nj)) continue;\n                if (grid[ni][nj] == '#') continue;\n\n                int nv = id(ni, nj);\n                int nd = d + weight[nv];\n\n                if (nd < res.dist[nv]) {\n                    res.dist[nv] = nd;\n                    res.par[nv] = v;\n                    res.parDir[nv] = z;\n                    pq.push({nd, nv});\n                }\n            }\n        }\n\n        return res;\n    };\n\n    auto restore_path = [&](int s, int t, const vector<int>& par,\n                            const vector<int>& parDir) {\n        string path;\n        int cur = t;\n\n        while (cur != s) {\n            int z = parDir[cur];\n            path.push_back(dc[z]);\n            cur = par[cur];\n        }\n\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    DijkstraResult dijStart = dijkstra(start);\n\n    auto coverage_complete = [&](const vector<int>& target_cells) {\n        vector<char> cov(V, 0);\n        int cnt = 0;\n\n        auto add = [&](int v) {\n            for (int u : visible[v]) {\n                if (!cov[u]) {\n                    cov[u] = 1;\n                    cnt++;\n                }\n            }\n        };\n\n        add(start);\n        for (int v : target_cells) add(v);\n\n        return cnt == R;\n    };\n\n    auto solution_cells = [&](const CandidateSolution& sol) {\n        vector<int> cells;\n        for (int idx : sol.route) cells.push_back(sol.nodes[idx]);\n        return cells;\n    };\n\n    auto build_target_set_cell = [&](double distPow, double interBonus, double noiseCoef) {\n        vector<char> covered(V, 0);\n        int covered_count = 0;\n\n        auto apply_cover = [&](int v) {\n            for (int u : visible[v]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    covered_count++;\n                }\n            }\n        };\n\n        vector<int> targets;\n        apply_cover(start);\n\n        int step = 0;\n\n        while (covered_count < R) {\n            int best = -1;\n            double bestScore = -1.0;\n\n            for (int v : road_ids) {\n                int gain = 0;\n                for (int u : visible[v]) {\n                    if (!covered[u]) gain++;\n                }\n                if (gain == 0) continue;\n\n                double score = (double)gain;\n                score /= pow((double)dijStart.dist[v] + 20.0, distPow);\n\n                auto [i, j] = pos(v);\n                int deg = 0;\n                for (int z = 0; z < 4; z++) {\n                    int ni = i + di[z];\n                    int nj = j + dj[z];\n                    if (inside(ni, nj) && grid[ni][nj] != '#') deg++;\n                }\n                if (deg >= 3) score *= interBonus;\n\n                unsigned h = (unsigned)(v * 1103515245u + step * 12345u);\n                double rnd = ((h >> 8) & 1023) / 1023.0;\n                score *= 1.0 + noiseCoef * (rnd - 0.5);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = v;\n                }\n            }\n\n            if (best == -1) break;\n\n            targets.push_back(best);\n            apply_cover(best);\n            step++;\n        }\n\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n        return targets;\n    };\n\n    auto build_target_set_segment = [&](double distPow, double lengthBonus, double noiseCoef) {\n        vector<char> hSeen(H, 0), vSeen(W, 0);\n\n        auto covered_count_now = [&]() {\n            int cnt = 0;\n            for (int v : road_ids) {\n                if (hSeen[hid[v]] || vSeen[vid[v]]) cnt++;\n            }\n            return cnt;\n        };\n\n        auto apply = [&](int v) {\n            hSeen[hid[v]] = 1;\n            vSeen[vid[v]] = 1;\n        };\n\n        vector<int> targets;\n        apply(start);\n\n        int covered_count = covered_count_now();\n        int step = 0;\n\n        while (covered_count < R) {\n            int best = -1;\n            double bestScore = -1.0;\n\n            for (int v : road_ids) {\n                int h = hid[v];\n                int w = vid[v];\n\n                if (hSeen[h] && vSeen[w]) continue;\n\n                int gain = 0;\n\n                for (int u : hsegCells[h]) {\n                    if (!(hSeen[hid[u]] || vSeen[vid[u]])) gain++;\n                }\n\n                for (int u : vsegCells[w]) {\n                    if (!(hSeen[hid[u]] || vSeen[vid[u]])) gain++;\n                }\n\n                if (!(hSeen[h] || vSeen[w])) gain--;\n\n                if (gain <= 0) continue;\n\n                double score = (double)gain;\n                score /= pow((double)dijStart.dist[v] + 20.0, distPow);\n\n                int lenSum = (int)hsegCells[h].size() + (int)vsegCells[w].size();\n                score *= 1.0 + lengthBonus * sqrt((double)lenSum);\n\n                unsigned hh = (unsigned)(v * 2654435761u + step * 97u);\n                double rnd = ((hh >> 7) & 1023) / 1023.0;\n                score *= 1.0 + noiseCoef * (rnd - 0.5);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = v;\n                }\n            }\n\n            if (best == -1) break;\n\n            targets.push_back(best);\n            apply(best);\n            covered_count = covered_count_now();\n            step++;\n        }\n\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n        return targets;\n    };\n\n    auto remove_redundant_targets = [&](vector<int> targets) {\n        vector<int> result;\n        for (int v : targets) {\n            if (v != start) result.push_back(v);\n        }\n\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n\n            vector<int> coverCount(V, 0);\n            auto add = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            add(start);\n            for (int v : result) add(v);\n\n            vector<pair<int,int>> ord;\n            for (int idx = 0; idx < (int)result.size(); idx++) {\n                ord.push_back({(int)visible[result[idx]].size(), idx});\n            }\n\n            sort(ord.begin(), ord.end());\n\n            vector<char> removed(result.size(), 0);\n\n            for (auto [sz, idx] : ord) {\n                if (removed[idx]) continue;\n                int v = result[idx];\n\n                bool ok = true;\n                for (int u : visible[v]) {\n                    if (coverCount[u] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n\n                if (ok) {\n                    removed[idx] = 1;\n                    changed = true;\n                    for (int u : visible[v]) coverCount[u]--;\n                }\n            }\n\n            if (changed) {\n                vector<int> nxt;\n                for (int i = 0; i < (int)result.size(); i++) {\n                    if (!removed[i]) nxt.push_back(result[i]);\n                }\n                result.swap(nxt);\n            }\n        }\n\n        return result;\n    };\n\n    auto route_cost_from_order = [&](const vector<vector<int>>& distMat,\n                                     const vector<int>& route) {\n        long long cost = 0;\n        int prev = 0;\n        for (int x : route) {\n            cost += distMat[prev][x];\n            prev = x;\n        }\n        cost += distMat[prev][0];\n        return cost;\n    };\n\n    auto two_opt = [&](vector<int>& route, const vector<vector<int>>& distMat) {\n        int L = (int)route.size();\n\n        bool improved = true;\n        int iter = 0;\n\n        while (improved && iter < 500) {\n            improved = false;\n            iter++;\n\n            for (int l = 0; l < L && !improved; l++) {\n                for (int r = l + 1; r < L && !improved; r++) {\n                    int a = (l == 0 ? 0 : route[l - 1]);\n                    int b = route[l];\n                    int c = route[r];\n                    int d = (r + 1 == L ? 0 : route[r + 1]);\n\n                    int before = distMat[a][b] + distMat[c][d];\n                    int after  = distMat[a][c] + distMat[b][d];\n\n                    if (after < before) {\n                        reverse(route.begin() + l, route.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    };\n\n    auto solve_tsp_for_targets = [&](const vector<int>& target_cells) {\n        CandidateSolution sol;\n\n        vector<int> nodes;\n        nodes.push_back(start);\n        for (int v : target_cells) {\n            if (v != start) nodes.push_back(v);\n        }\n\n        sort(nodes.begin() + 1, nodes.end());\n        nodes.erase(unique(nodes.begin() + 1, nodes.end()), nodes.end());\n\n        int M = (int)nodes.size();\n\n        vector<DijkstraResult> dijs(M);\n        vector<vector<int>> distMat(M, vector<int>(M, INF));\n\n        for (int a = 0; a < M; a++) {\n            dijs[a] = dijkstra(nodes[a]);\n            for (int b = 0; b < M; b++) {\n                distMat[a][b] = dijs[a].dist[nodes[b]];\n            }\n        }\n\n        vector<int> remaining;\n        for (int i = 1; i < M; i++) remaining.push_back(i);\n\n        vector<int> route;\n\n        if (!remaining.empty()) {\n            int first = remaining[0];\n            for (int x : remaining) {\n                if (distMat[0][x] + distMat[x][0] <\n                    distMat[0][first] + distMat[first][0]) {\n                    first = x;\n                }\n            }\n\n            route.push_back(first);\n            remaining.erase(find(remaining.begin(), remaining.end(), first));\n        }\n\n        while (!remaining.empty()) {\n            int bestNode = -1;\n            int bestPos = -1;\n            int bestInc = INF;\n\n            for (int x : remaining) {\n                int L = (int)route.size();\n\n                for (int p = 0; p <= L; p++) {\n                    int a = (p == 0 ? 0 : route[p - 1]);\n                    int b = (p == L ? 0 : route[p]);\n\n                    int inc = distMat[a][x] + distMat[x][b] - distMat[a][b];\n\n                    if (inc < bestInc) {\n                        bestInc = inc;\n                        bestNode = x;\n                        bestPos = p;\n                    }\n                }\n            }\n\n            route.insert(route.begin() + bestPos, bestNode);\n            remaining.erase(find(remaining.begin(), remaining.end(), bestNode));\n        }\n\n        two_opt(route, distMat);\n\n        sol.cost = route_cost_from_order(distMat, route);\n        sol.nodes = move(nodes);\n        sol.route = move(route);\n        sol.distMat = move(distMat);\n        sol.dijs = move(dijs);\n\n        return sol;\n    };\n\n    auto route_aware_delete = [&](CandidateSolution& sol) {\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n\n            vector<int> target_cells;\n            for (int idx : sol.route) target_cells.push_back(sol.nodes[idx]);\n\n            vector<int> coverCount(V, 0);\n            auto addCount = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            addCount(start);\n            for (int v : target_cells) addCount(v);\n\n            int L = (int)sol.route.size();\n            int bestRemovePos = -1;\n            int bestGain = 0;\n\n            for (int p = 0; p < L; p++) {\n                int idx = sol.route[p];\n                int v = sol.nodes[idx];\n\n                bool ok = true;\n                for (int u : visible[v]) {\n                    if (coverCount[u] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n\n                int a = (p == 0 ? 0 : sol.route[p - 1]);\n                int b = idx;\n                int c = (p + 1 == L ? 0 : sol.route[p + 1]);\n\n                int gain = sol.distMat[a][b] + sol.distMat[b][c] - sol.distMat[a][c];\n\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    bestRemovePos = p;\n                }\n            }\n\n            if (bestRemovePos != -1) {\n                sol.route.erase(sol.route.begin() + bestRemovePos);\n                sol.cost -= bestGain;\n                changed = true;\n            }\n        }\n    };\n\n    auto build_solution_from_route_cells = [&](const vector<int>& cells) {\n        vector<int> cleaned;\n        for (int v : cells) {\n            if (v != start) cleaned.push_back(v);\n        }\n        sort(cleaned.begin(), cleaned.end());\n        cleaned.erase(unique(cleaned.begin(), cleaned.end()), cleaned.end());\n        return solve_tsp_for_targets(cleaned);\n    };\n\n    auto improve_by_relocation = [&](CandidateSolution base) {\n        vector<int> cells;\n        for (int idx : base.route) cells.push_back(base.nodes[idx]);\n\n        CandidateSolution bestLocal = base;\n\n        bool improvedReloc = true;\n        int relocIter = 0;\n\n        while (improvedReloc && relocIter < 3) {\n            improvedReloc = false;\n            relocIter++;\n\n            CandidateSolution curSol = build_solution_from_route_cells(cells);\n            route_aware_delete(curSol);\n            two_opt(curSol.route, curSol.distMat);\n            curSol.cost = route_cost_from_order(curSol.distMat, curSol.route);\n\n            if (curSol.cost < bestLocal.cost) bestLocal = curSol;\n\n            cells.clear();\n            for (int idx : curSol.route) cells.push_back(curSol.nodes[idx]);\n\n            vector<int> coverCount(V, 0);\n            auto addCount = [&](int v) {\n                for (int u : visible[v]) coverCount[u]++;\n            };\n\n            addCount(start);\n            for (int v : cells) addCount(v);\n\n            int L = (int)cells.size();\n\n            for (int p = 0; p < L; p++) {\n                int oldv = cells[p];\n\n                int prevv = (p == 0 ? start : cells[p - 1]);\n                int nextv = (p + 1 == L ? start : cells[p + 1]);\n\n                DijkstraResult dijPrev = dijkstra(prevv);\n                DijkstraResult dijOld = dijkstra(oldv);\n\n                int oldLocal = dijPrev.dist[oldv] + dijOld.dist[nextv];\n\n                vector<int> mustRemain;\n                for (int u : visible[oldv]) {\n                    if (coverCount[u] <= 1) mustRemain.push_back(u);\n                }\n\n                auto [oi, oj] = pos(oldv);\n\n                int bestNew = oldv;\n                int bestLocalCost = oldLocal;\n\n                for (int cand : road_ids) {\n                    auto [ci, cj] = pos(cand);\n                    int man = abs(ci - oi) + abs(cj - oj);\n                    if (man > 9) continue;\n\n                    if (cand == oldv) continue;\n\n                    bool coversMust = true;\n                    for (int u : mustRemain) {\n                        if (!binary_search(visible[cand].begin(), visible[cand].end(), u)) {\n                            coversMust = false;\n                            break;\n                        }\n                    }\n                    if (!coversMust) continue;\n\n                    int local1 = dijPrev.dist[cand];\n                    if (local1 >= INF) continue;\n\n                    DijkstraResult dijCand = dijkstra(cand);\n                    int local2 = dijCand.dist[nextv];\n                    if (local2 >= INF) continue;\n\n                    int local = local1 + local2;\n                    if (local < bestLocalCost) {\n                        bestLocalCost = local;\n                        bestNew = cand;\n                    }\n                }\n\n                if (bestNew != oldv) {\n                    for (int u : visible[oldv]) coverCount[u]--;\n                    cells[p] = bestNew;\n                    for (int u : visible[bestNew]) coverCount[u]++;\n                    improvedReloc = true;\n                }\n            }\n        }\n\n        CandidateSolution relocSol = build_solution_from_route_cells(cells);\n        route_aware_delete(relocSol);\n        two_opt(relocSol.route, relocSol.distMat);\n        relocSol.cost = route_cost_from_order(relocSol.distMat, relocSol.route);\n\n        if (coverage_complete(cells) && relocSol.cost < bestLocal.cost) {\n            bestLocal = relocSol;\n        }\n\n        return bestLocal;\n    };\n\n    auto build_target_set_insertion = [&](double gainPow, double costPow, double noiseCoef) {\n        vector<int> nodes;\n        nodes.push_back(start);\n\n        vector<DijkstraResult> dijs;\n        dijs.push_back(dijStart);\n\n        vector<vector<int>> distMat(1, vector<int>(1, 0));\n        vector<int> route;\n\n        vector<char> covered(V, 0);\n        int covered_count = 0;\n\n        auto apply_cover = [&](int v) {\n            for (int u : visible[v]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    covered_count++;\n                }\n            }\n        };\n\n        apply_cover(start);\n\n        int step = 0;\n\n        while (covered_count < R) {\n            int bestCell = -1;\n            double bestScore = -1.0;\n\n            for (int v : road_ids) {\n                int gain = 0;\n                for (int u : visible[v]) {\n                    if (!covered[u]) gain++;\n                }\n                if (gain <= 0) continue;\n\n                int bestInc = INF;\n\n                int L = (int)route.size();\n\n                for (int p = 0; p <= L; p++) {\n                    int aidx = (p == 0 ? 0 : route[p - 1]);\n                    int bidx = (p == L ? 0 : route[p]);\n\n                    int b = nodes[bidx];\n\n                    int dab = distMat[aidx][bidx];\n                    int dav = dijs[aidx].dist[v];\n\n                    if (dav >= INF) continue;\n\n                    auto [vi, vj] = pos(v);\n                    auto [bi, bj] = pos(b);\n\n                    int estvb = (abs(vi - bi) + abs(vj - bj)) * 5;\n\n                    int inc = dav + estvb - dab;\n                    if (inc < bestInc) bestInc = inc;\n                }\n\n                if (bestInc < 1) bestInc = 1;\n\n                double score = pow((double)gain, gainPow) / pow((double)bestInc + 10.0, costPow);\n\n                unsigned h = (unsigned)(v * 747796405u + step * 2891336453u);\n                double rnd = ((h >> 9) & 1023) / 1023.0;\n                score *= 1.0 + noiseCoef * (rnd - 0.5);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestCell = v;\n                }\n            }\n\n            if (bestCell == -1) break;\n\n            int newIdx = (int)nodes.size();\n            nodes.push_back(bestCell);\n\n            DijkstraResult dijNew = dijkstra(bestCell);\n            dijs.push_back(move(dijNew));\n\n            int oldM = (int)distMat.size();\n            for (auto &row : distMat) row.push_back(INF);\n            distMat.push_back(vector<int>(oldM + 1, INF));\n\n            for (int i = 0; i <= oldM; i++) {\n                if (i < oldM) {\n                    distMat[i][newIdx] = dijs[i].dist[bestCell];\n                    distMat[newIdx][i] = dijs[newIdx].dist[nodes[i]];\n                }\n            }\n            distMat[newIdx][newIdx] = 0;\n\n            int L = (int)route.size();\n            int bestInc = INF;\n            int bestPos = 0;\n\n            for (int p = 0; p <= L; p++) {\n                int a = (p == 0 ? 0 : route[p - 1]);\n                int b = (p == L ? 0 : route[p]);\n\n                int inc = distMat[a][newIdx] + distMat[newIdx][b] - distMat[a][b];\n\n                if (inc < bestInc) {\n                    bestInc = inc;\n                    bestPos = p;\n                }\n            }\n\n            route.insert(route.begin() + bestPos, newIdx);\n            apply_cover(bestCell);\n            step++;\n        }\n\n        vector<int> targets;\n        for (int idx : route) targets.push_back(nodes[idx]);\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n        return targets;\n    };\n\n    vector<CandidateSolution> pool;\n\n    auto add_solution_to_pool = [&](CandidateSolution sol) {\n        if (sol.cost >= (1LL << 50)) return;\n        if (!coverage_complete(solution_cells(sol))) return;\n\n        pool.push_back(move(sol));\n\n        sort(pool.begin(), pool.end(), [](const CandidateSolution& a, const CandidateSolution& b) {\n            return a.cost < b.cost;\n        });\n\n        if ((int)pool.size() > 10) pool.resize(10);\n    };\n\n    auto process_targets = [&](vector<int> targets) {\n        targets = remove_redundant_targets(targets);\n        if (!coverage_complete(targets)) return;\n\n        CandidateSolution raw = solve_tsp_for_targets(targets);\n        raw.cost = route_cost_from_order(raw.distMat, raw.route);\n        add_solution_to_pool(raw);\n\n        CandidateSolution imp = raw;\n        route_aware_delete(imp);\n        two_opt(imp.route, imp.distMat);\n        imp.cost = route_cost_from_order(imp.distMat, imp.route);\n        add_solution_to_pool(imp);\n    };\n\n    vector<tuple<double,double,double>> cellParams = {\n        {0.04, 1.00, 0.00},\n        {0.06, 1.00, 0.00},\n        {0.10, 1.02, 0.00},\n        {0.15, 1.05, 0.00},\n        {0.18, 1.08, 0.00},\n        {0.22, 1.10, 0.00},\n        {0.28, 1.12, 0.00},\n        {0.34, 1.15, 0.00},\n        {0.18, 1.08, 0.04},\n        {0.18, 1.08, 0.08},\n        {0.24, 1.12, 0.06},\n        {0.30, 1.15, 0.08}\n    };\n\n    for (auto [distPow, interBonus, noiseCoef] : cellParams) {\n        process_targets(build_target_set_cell(distPow, interBonus, noiseCoef));\n    }\n\n    vector<tuple<double,double,double>> segParams = {\n        {0.00, 0.000, 0.00},\n        {0.08, 0.010, 0.00},\n        {0.14, 0.015, 0.00},\n        {0.20, 0.020, 0.00},\n        {0.28, 0.025, 0.00},\n        {0.18, 0.015, 0.05},\n        {0.24, 0.020, 0.08}\n    };\n\n    for (auto [distPow, lengthBonus, noiseCoef] : segParams) {\n        process_targets(build_target_set_segment(distPow, lengthBonus, noiseCoef));\n    }\n\n    vector<tuple<double,double,double>> insParams = {\n        {1.00, 0.80, 0.00},\n        {1.00, 1.00, 0.00},\n        {1.10, 1.00, 0.00},\n        {1.20, 1.10, 0.00},\n        {1.00, 1.00, 0.06},\n        {1.15, 1.05, 0.08}\n    };\n\n    for (auto [gainPow, costPow, noiseCoef] : insParams) {\n        process_targets(build_target_set_insertion(gainPow, costPow, noiseCoef));\n    }\n\n    int initialPoolSize = (int)pool.size();\n    for (int i = 0; i < min(initialPoolSize, 4); i++) {\n        CandidateSolution rel = improve_by_relocation(pool[i]);\n        rel.cost = route_cost_from_order(rel.distMat, rel.route);\n        add_solution_to_pool(rel);\n    }\n\n    auto get_add_candidates = [&](const CandidateSolution& base, int LIMIT) {\n        vector<int> baseCells = solution_cells(base);\n        unordered_set<int> used(baseCells.begin(), baseCells.end());\n        used.insert(start);\n\n        vector<int> coverCount(V, 0);\n        auto addCount = [&](int v) {\n            for (int u : visible[v]) coverCount[u]++;\n        };\n\n        addCount(start);\n        for (int v : baseCells) addCount(v);\n\n        vector<pair<double,int>> candScores;\n\n        for (int v : road_ids) {\n            if (used.count(v)) continue;\n\n            int bestMan = 1e9;\n            auto [vi, vj] = pos(v);\n\n            for (int u : baseCells) {\n                auto [ui, uj] = pos(u);\n                bestMan = min(bestMan, abs(vi - ui) + abs(vj - uj));\n            }\n\n            auto [si0, sj0] = pos(start);\n            bestMan = min(bestMan, abs(vi - si0) + abs(vj - sj0));\n\n            int deg = 0;\n            for (int z = 0; z < 4; z++) {\n                int ni = vi + di[z];\n                int nj = vj + dj[z];\n                if (inside(ni, nj) && grid[ni][nj] != '#') deg++;\n            }\n\n            int lenSum = (int)hsegCells[hid[v]].size() + (int)vsegCells[vid[v]].size();\n\n            int uniqueGain = 0;\n            for (int u : visible[v]) {\n                if (coverCount[u] == 1) uniqueGain++;\n            }\n\n            double score = 0.0;\n            score += 3.5 * uniqueGain;\n            score += 0.45 * (double)visible[v].size();\n            score += 0.8 * sqrt((double)lenSum);\n\n            if (deg >= 3) score *= 1.15;\n\n            score /= (double)(bestMan + 3);\n\n            candScores.push_back({-score, v});\n        }\n\n        sort(candScores.begin(), candScores.end());\n\n        vector<int> res;\n        for (int i = 0; i < min(LIMIT, (int)candScores.size()); i++) {\n            res.push_back(candScores[i].second);\n        }\n        return res;\n    };\n\n    auto improve_by_add_delete_limited = [&](const CandidateSolution& base, int limit) {\n        CandidateSolution best = base;\n        vector<int> baseCells = solution_cells(base);\n\n        vector<int> cand = get_add_candidates(base, limit);\n\n        for (int addv : cand) {\n            vector<int> cells = baseCells;\n            cells.push_back(addv);\n\n            CandidateSolution sol = build_solution_from_route_cells(cells);\n            route_aware_delete(sol);\n            two_opt(sol.route, sol.distMat);\n            sol.cost = route_cost_from_order(sol.distMat, sol.route);\n\n            if (sol.cost < best.cost && coverage_complete(solution_cells(sol))) {\n                best = move(sol);\n            }\n        }\n\n        return best;\n    };\n\n    int poolSizeBeforeAdd = (int)pool.size();\n    for (int i = 0; i < min(poolSizeBeforeAdd, 4); i++) {\n        CandidateSolution improved = improve_by_add_delete_limited(pool[i], 24);\n        add_solution_to_pool(improved);\n    }\n\n    sort(pool.begin(), pool.end(), [](const CandidateSolution& a, const CandidateSolution& b) {\n        return a.cost < b.cost;\n    });\n\n    // A small second one-add pass only for the current best solution.\n    if (!pool.empty()) {\n        CandidateSolution second = improve_by_add_delete_limited(pool[0], 12);\n        add_solution_to_pool(second);\n    }\n\n    sort(pool.begin(), pool.end(), [](const CandidateSolution& a, const CandidateSolution& b) {\n        return a.cost < b.cost;\n    });\n\n    CandidateSolution bestSol = pool[0];\n\n    route_aware_delete(bestSol);\n    two_opt(bestSol.route, bestSol.distMat);\n    bestSol.cost = route_cost_from_order(bestSol.distMat, bestSol.route);\n\n    add_solution_to_pool(bestSol);\n\n    sort(pool.begin(), pool.end(), [](const CandidateSolution& a, const CandidateSolution& b) {\n        return a.cost < b.cost;\n    });\n\n    bestSol = pool[0];\n\n    string answer;\n    int prev = 0;\n\n    for (int x : bestSol.route) {\n        answer += restore_path(\n            bestSol.nodes[prev],\n            bestSol.nodes[x],\n            bestSol.dijs[prev].par,\n            bestSol.dijs[prev].parDir\n        );\n        prev = x;\n    }\n\n    answer += restore_path(\n        bestSol.nodes[prev],\n        bestSol.nodes[0],\n        bestSol.dijs[prev].par,\n        bestSol.dijs[prev].parDir\n    );\n\n    cout << answer << '\\n';\n\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Task {\n    vector<int> d;\n    vector<int> pre;\n    vector<int> nxt;\n};\n\nstruct Obs {\n    int task;\n    int dur;\n};\n\nstruct Edge {\n    int to, rev, cap;\n    int cost;\n};\n\nstruct MinCostFlow {\n    int n;\n    vector<vector<Edge>> g;\n\n    MinCostFlow(int n = 0) : n(n), g(n) {}\n\n    void addEdge(int fr, int to, int cap, int cost) {\n        Edge a{to, (int)g[to].size(), cap, cost};\n        Edge b{fr, (int)g[fr].size(), 0, -cost};\n        g[fr].push_back(a);\n        g[to].push_back(b);\n    }\n\n    pair<int,int> flow(int s, int t, int maxf) {\n        int flow = 0, cost = 0;\n        const int INF = 1e9;\n        vector<int> h(n, 0), dist(n), pv(n), pe(n);\n\n        while (flow < maxf) {\n            fill(dist.begin(), dist.end(), INF);\n            dist[s] = 0;\n\n            priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n            pq.push({0, s});\n\n            while (!pq.empty()) {\n                auto [d, v] = pq.top();\n                pq.pop();\n                if (dist[v] != d) continue;\n\n                for (int i = 0; i < (int)g[v].size(); i++) {\n                    Edge &e = g[v][i];\n                    if (e.cap <= 0) continue;\n                    int nd = d + e.cost + h[v] - h[e.to];\n                    if (nd < dist[e.to]) {\n                        dist[e.to] = nd;\n                        pv[e.to] = v;\n                        pe[e.to] = i;\n                        pq.push({nd, e.to});\n                    }\n                }\n            }\n\n            if (dist[t] == INF) break;\n\n            for (int v = 0; v < n; v++) {\n                if (dist[v] < INF) h[v] += dist[v];\n            }\n\n            int add = maxf - flow;\n            for (int v = t; v != s; v = pv[v]) {\n                add = min(add, g[pv[v]][pe[v]].cap);\n            }\n\n            for (int v = t; v != s; v = pv[v]) {\n                Edge &e = g[pv[v]][pe[v]];\n                e.cap -= add;\n                g[v][e.rev].cap += add;\n                cost += add * e.cost;\n            }\n\n            flow += add;\n        }\n\n        return {flow, cost};\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, K, R;\n    cin >> N >> M >> K >> R;\n\n    vector<Task> tasks(N);\n    vector<double> dsum(N, 0.0), dmaxv(N, 0.0), avgD(K, 0.0);\n\n    for (int i = 0; i < N; i++) {\n        tasks[i].d.resize(K);\n        for (int k = 0; k < K; k++) {\n            cin >> tasks[i].d[k];\n            dsum[i] += tasks[i].d[k];\n            dmaxv[i] = max(dmaxv[i], (double)tasks[i].d[k]);\n            avgD[k] += tasks[i].d[k];\n        }\n    }\n    for (int k = 0; k < K; k++) avgD[k] /= N;\n\n    vector<int> indeg0(N, 0);\n    for (int i = 0; i < R; i++) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        tasks[u].nxt.push_back(v);\n        tasks[v].pre.push_back(u);\n        indeg0[v]++;\n    }\n\n    vector<double> crit(N, 1.0), unlock(N, 0.0), nearUnlock(N, 0.0);\n\n    for (int i = N - 1; i >= 0; i--) {\n        double bestCrit = 0.0;\n        double sumUnlock = 0.0;\n        double near = tasks[i].nxt.size();\n\n        for (int v : tasks[i].nxt) {\n            bestCrit = max(bestCrit, crit[v]);\n            sumUnlock += 1.0 + 0.17 * unlock[v];\n            near += 0.22 * tasks[v].nxt.size();\n        }\n\n        double ownHard = dsum[i] / max(1, K);\n        crit[i] = 1.0 + bestCrit + 0.018 * ownHard;\n        unlock[i] = min(2500.0, sumUnlock);\n        nearUnlock[i] = near;\n    }\n\n    vector<double> basePriority(N);\n    for (int i = 0; i < N; i++) {\n        basePriority[i] =\n            35.5 * crit[i]\n            + 4.8 * nearUnlock[i]\n            + 0.13 * unlock[i]\n            + 0.028 * dsum[i]\n            + 0.028 * dmaxv[i]\n            - 0.001 * i;\n    }\n\n    vector<int> status(N, -1);\n    vector<int> remPre = indeg0;\n    vector<int> readySince(N, -1);\n\n    vector<int> readyList;\n    vector<char> inReady(N, 0);\n    for (int i = 0; i < N; i++) {\n        if (remPre[i] == 0) {\n            readyList.push_back(i);\n            inReady[i] = 1;\n            readySince[i] = 1;\n        }\n    }\n\n    vector<int> memberTask(M, -1);\n    vector<int> startDay(M, -1);\n\n    vector<vector<double>> skill(M, vector<double>(K, 0.0));\n    for (int j = 0; j < M; j++) {\n        double scale = 0.96 + 0.10 * ((j % 5) - 2);\n        if (scale < 0.75) scale = 0.75;\n\n        for (int k = 0; k < K; k++) {\n            double spec = 0.0;\n            if (k % M == j) spec += 3.0;\n            if ((k + j) % 7 == 0) spec += 2.0;\n            if ((2 * k + j) % 11 == 0) spec += 1.5;\n            skill[j][k] = max(0.0, avgD[k] * scale + spec);\n        }\n    }\n\n    vector<vector<Obs>> observations(M);\n    vector<double> speed(M, 1.0);\n\n    auto raw_shortage = [&](int task, int member) {\n        double w = 0.0;\n        for (int k = 0; k < K; k++) {\n            w += max(0.0, (double)tasks[task].d[k] - skill[member][k]);\n        }\n        return w;\n    };\n\n    auto estimate_duration = [&](int task, int member) {\n        double w = raw_shortage(task, member);\n        double e = max(1.0, w);\n        e *= speed[member];\n        if (e < 1.0) e = 1.0;\n        return e;\n    };\n\n    auto refit_member = [&](int j) {\n        int nobs = (int)observations[j].size();\n        if (nobs == 0) return;\n\n        int passes = 6;\n        if (nobs > 20) passes = 4;\n        if (nobs > 60) passes = 3;\n\n        double baseLR = 0.038 / sqrt(1.0 + 0.04 * nobs);\n\n        for (int pass = 0; pass < passes; pass++) {\n            for (const Obs &ob : observations[j]) {\n                int t = ob.task;\n                int dur = ob.dur;\n\n                double pred = 0.0;\n                vector<int> active;\n                active.reserve(K);\n\n                for (int k = 0; k < K; k++) {\n                    double gap = (double)tasks[t].d[k] - skill[j][k];\n                    if (gap > 0.0) {\n                        pred += gap;\n                        active.push_back(k);\n                    }\n                }\n\n                double lo, hi;\n                if (dur <= 1) {\n                    lo = 0.0;\n                    hi = 3.0;\n                } else {\n                    lo = max(0.0, (double)dur - 3.0);\n                    hi = (double)dur + 3.0;\n                }\n\n                double err = 0.0;\n                if (pred < lo) err = pred - lo;\n                else if (pred > hi) err = pred - hi;\n\n                if (fabs(err) > 1e-9) {\n                    if (!active.empty()) {\n                        double delta = baseLR * err / sqrt((double)active.size());\n                        for (int k : active) skill[j][k] += delta;\n                    } else if (err < 0.0) {\n                        double dec = baseLR * (-err) / max(1.0, dsum[t]);\n                        for (int k = 0; k < K; k++) skill[j][k] -= dec * tasks[t].d[k];\n                    }\n                }\n\n                if (dur == 1) {\n                    double lr = 0.018 / sqrt(1.0 + 0.03 * nobs);\n                    for (int k = 0; k < K; k++) {\n                        if (skill[j][k] < tasks[t].d[k]) {\n                            skill[j][k] += lr * ((double)tasks[t].d[k] - skill[j][k]);\n                        }\n                    }\n                }\n\n                for (int k = 0; k < K; k++) {\n                    if (skill[j][k] < 0.0) skill[j][k] = 0.0;\n                    if (skill[j][k] > 80.0) skill[j][k] = 80.0;\n                }\n            }\n        }\n    };\n\n    auto update_speed = [&](int j) {\n        int nobs = observations[j].size();\n        if (nobs == 0) return;\n\n        int use = min(nobs, 20);\n        double sumLog = 0.0;\n        int cnt = 0;\n\n        for (int idx = nobs - use; idx < nobs; idx++) {\n            const Obs &ob = observations[j][idx];\n            double pred = max(1.0, raw_shortage(ob.task, j));\n            double ratio = (double)ob.dur / pred;\n            ratio = min(3.0, max(0.35, ratio));\n            sumLog += log(ratio);\n            cnt++;\n        }\n\n        if (cnt > 0) {\n            double target = exp(sumLog / cnt);\n            double alpha = min(0.35, 0.08 + 0.015 * nobs);\n            speed[j] = speed[j] * (1.0 - alpha) + target * alpha;\n            if (speed[j] < 0.55) speed[j] = 0.55;\n            if (speed[j] > 1.80) speed[j] = 1.80;\n        }\n    };\n\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        vector<int> readyTasks;\n        readyTasks.reserve(readyList.size());\n        for (int t : readyList) {\n            if (status[t] == -1 && remPre[t] == 0) readyTasks.push_back(t);\n        }\n\n        vector<double> dynPriority(N, 0.0);\n        vector<double> immediateUnlock(N, 0.0);\n\n        for (int t : readyTasks) {\n            double almost = 0.0;\n            for (int v : tasks[t].nxt) {\n                if (status[v] == -1 && remPre[v] == 1) {\n                    almost += 1.0 + 0.08 * nearUnlock[v] + 0.04 * crit[v];\n                }\n            }\n            immediateUnlock[t] = almost;\n\n            double waitBonus = 0.0;\n            if (readySince[t] > 0) {\n                int wait = day - readySince[t];\n                waitBonus = min(25.0, 0.35 * wait);\n            }\n\n            dynPriority[t] =\n                basePriority[t]\n                + 7.0 * almost\n                + waitBonus;\n        }\n\n        sort(readyTasks.begin(), readyTasks.end(), [&](int a, int b) {\n            if (dynPriority[a] != dynPriority[b]) return dynPriority[a] > dynPriority[b];\n            return a < b;\n        });\n\n        vector<int> freeMembers;\n        for (int j = 0; j < M; j++) {\n            if (memberTask[j] == -1) freeMembers.push_back(j);\n        }\n\n        vector<pair<int,int>> assignments;\n\n        if (!freeMembers.empty() && !readyTasks.empty()) {\n            int F = (int)freeMembers.size();\n\n            vector<int> candTasks;\n            vector<char> selected(N, 0);\n\n            auto addTask = [&](int t) {\n                if (!selected[t]) {\n                    selected[t] = 1;\n                    candTasks.push_back(t);\n                }\n            };\n\n            int topByPriority = min((int)readyTasks.size(), max(45, F * 9));\n            for (int i = 0; i < topByPriority; i++) addTask(readyTasks[i]);\n\n            // Add tasks that seem quickly finishable by some free member.\n            vector<pair<double,int>> easy;\n            easy.reserve(readyTasks.size());\n            int scanEasy = min((int)readyTasks.size(), 180);\n            for (int idx = 0; idx < scanEasy; idx++) {\n                int t = readyTasks[idx];\n                double bestEst = 1e100;\n                for (int j : freeMembers) {\n                    bestEst = min(bestEst, estimate_duration(t, j));\n                }\n                double key = bestEst - 0.08 * immediateUnlock[t] - 0.01 * basePriority[t];\n                easy.push_back({key, t});\n            }\n            sort(easy.begin(), easy.end());\n            int addEasy = min((int)easy.size(), max(20, F * 4));\n            for (int i = 0; i < addEasy; i++) addTask(easy[i].second);\n\n            // Keep graph bounded.\n            if ((int)candTasks.size() > 130) {\n                sort(candTasks.begin(), candTasks.end(), [&](int a, int b) {\n                    return dynPriority[a] > dynPriority[b];\n                });\n                candTasks.resize(130);\n            }\n\n            int C = (int)candTasks.size();\n\n            int S = 0;\n            int memberOffset = 1;\n            int taskOffset = memberOffset + F;\n            int T = taskOffset + C;\n            int V = T + 1;\n\n            MinCostFlow mf(V);\n\n            for (int a = 0; a < F; a++) {\n                mf.addEdge(S, memberOffset + a, 1, 0);\n            }\n            for (int b = 0; b < C; b++) {\n                mf.addEdge(taskOffset + b, T, 1, 0);\n            }\n\n            const int SCALE = 1000;\n            const int OFFSET = 1000000;\n\n            double expPow = 0.91;\n            if (day < 120) expPow = 0.82;\n            else if (day < 300) expPow = 0.87;\n\n            for (int a = 0; a < F; a++) {\n                int j = freeMembers[a];\n\n                for (int b = 0; b < C; b++) {\n                    int t = candTasks[b];\n\n                    double est = estimate_duration(t, j);\n                    int cnt = observations[j].size();\n\n                    double uncertaintyPenalty = 0.0;\n                    if (cnt < 2) uncertaintyPenalty = 0.06 * est + 1.5;\n                    else if (cnt < 6) uncertaintyPenalty = 0.020 * est;\n\n                    double exploreBonus = 0.0;\n                    if (cnt < 5 && est <= 10.0) exploreBonus = 1.2;\n\n                    double throughputBonus = 0.0;\n                    if ((int)readyTasks.size() > 35) {\n                        throughputBonus = 2.5 / sqrt(est + 0.5);\n                    }\n\n                    double util =\n                        dynPriority[t] / pow(est + 1.0, expPow)\n                        - uncertaintyPenalty\n                        + exploreBonus\n                        + throughputBonus\n                        + 0.22 * crit[t]\n                        + 1.3 * immediateUnlock[t];\n\n                    int cost = OFFSET - (int)round(util * SCALE);\n                    if (cost < 0) cost = 0;\n\n                    mf.addEdge(memberOffset + a, taskOffset + b, 1, cost);\n                }\n            }\n\n            mf.flow(S, T, F);\n\n            for (int a = 0; a < F; a++) {\n                int node = memberOffset + a;\n                for (Edge &e : mf.g[node]) {\n                    if (e.to >= taskOffset && e.to < taskOffset + C && e.cap == 0) {\n                        int b = e.to - taskOffset;\n                        int j = freeMembers[a];\n                        int t = candTasks[b];\n                        assignments.push_back({j, t});\n                    }\n                }\n            }\n        }\n\n        for (auto [j, t] : assignments) {\n            status[t] = 0;\n            inReady[t] = 0;\n            memberTask[j] = t;\n            startDay[j] = day;\n        }\n\n        cout << assignments.size();\n        for (auto [j, t] : assignments) {\n            cout << ' ' << (j + 1) << ' ' << (t + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        string line;\n        if (!getline(cin >> ws, line)) return 0;\n\n        stringstream ss(line);\n        int nfin;\n        ss >> nfin;\n\n        if (nfin == -1) {\n            return 0;\n        }\n\n        for (int z = 0; z < nfin; z++) {\n            int memberInput;\n            ss >> memberInput;\n            int j = memberInput - 1;\n\n            int t = memberTask[j];\n            if (t < 0) continue;\n\n            int duration = day - startDay[j] + 1;\n\n            status[t] = 1;\n            memberTask[j] = -1;\n            startDay[j] = -1;\n\n            observations[j].push_back({t, duration});\n            refit_member(j);\n            update_speed(j);\n\n            for (int v : tasks[t].nxt) {\n                remPre[v]--;\n                if (remPre[v] == 0 && status[v] == -1 && !inReady[v]) {\n                    readyList.push_back(v);\n                    inReady[v] = 1;\n                    readySince[v] = day + 1;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Order {\n    int a, b, c, d;\n};\n\nstruct Point {\n    int x, y;\n};\n\nconst Point OFFICE{400, 400};\nvector<Order> ords(1000);\n\nstatic inline int mdist(const Point& p, const Point& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstatic inline Point pickup_point(int id) {\n    return {ords[id].a, ords[id].b};\n}\n\nstatic inline Point delivery_point(int id) {\n    return {ords[id].c, ords[id].d};\n}\n\nint path_length_points(const vector<Point>& pts) {\n    int s = 0;\n    for (int i = 0; i + 1 < (int)pts.size(); i++) {\n        s += mdist(pts[i], pts[i + 1]);\n    }\n    return s;\n}\n\nvector<int> nearest_path(const vector<int>& ids, bool pickup, Point start) {\n    int n = ids.size();\n    vector<int> path;\n    path.reserve(n);\n    vector<char> used(n, false);\n\n    Point cur = start;\n\n    for (int step = 0; step < n; step++) {\n        int best = -1;\n        int bestd = INT_MAX;\n\n        for (int i = 0; i < n; i++) {\n            if (used[i]) continue;\n\n            Point p = pickup ? pickup_point(ids[i]) : delivery_point(ids[i]);\n            int d = mdist(cur, p);\n\n            if (d < bestd) {\n                bestd = d;\n                best = i;\n            }\n        }\n\n        used[best] = true;\n        path.push_back(ids[best]);\n        cur = pickup ? pickup_point(ids[best]) : delivery_point(ids[best]);\n    }\n\n    return path;\n}\n\nvoid two_opt(vector<int>& path, bool pickup, Point start, Point goal) {\n    int n = path.size();\n    if (n <= 2) return;\n\n    auto getp = [&](int idx) -> Point {\n        if (idx == -1) return start;\n        if (idx == n) return goal;\n        return pickup ? pickup_point(path[idx]) : delivery_point(path[idx]);\n    };\n\n    bool improved = true;\n    int loop = 0;\n\n    while (improved && loop < 30) {\n        improved = false;\n        loop++;\n\n        for (int i = 0; i < n - 1; i++) {\n            Point A = getp(i - 1);\n            Point B = getp(i);\n\n            for (int k = i + 1; k < n; k++) {\n                Point C = getp(k);\n                Point D = getp(k + 1);\n\n                int before = mdist(A, B) + mdist(C, D);\n                int after = mdist(A, C) + mdist(B, D);\n\n                if (after < before) {\n                    reverse(path.begin() + i, path.begin() + k + 1);\n                    improved = true;\n                }\n            }\n        }\n    }\n}\n\nstruct Solution {\n    vector<int> ids;\n    vector<int> pickups;\n    vector<int> deliveries;\n    vector<Point> route;\n    int cost;\n};\n\nSolution build_solution(vector<int> ids) {\n    Solution sol;\n    sol.ids = ids;\n\n    sol.pickups = nearest_path(ids, true, OFFICE);\n\n    Point after_pickups = OFFICE;\n    if (!sol.pickups.empty()) {\n        after_pickups = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_path(ids, false, after_pickups);\n\n    Point first_del = sol.deliveries.empty() ? OFFICE : delivery_point(sol.deliveries.front());\n\n    two_opt(sol.pickups, true, OFFICE, first_del);\n\n    after_pickups = OFFICE;\n    if (!sol.pickups.empty()) {\n        after_pickups = pickup_point(sol.pickups.back());\n    }\n\n    sol.deliveries = nearest_path(ids, false, after_pickups);\n    two_opt(sol.deliveries, false, after_pickups, OFFICE);\n\n    sol.route.clear();\n    sol.route.reserve(102);\n    sol.route.push_back(OFFICE);\n\n    for (int id : sol.pickups) sol.route.push_back(pickup_point(id));\n    for (int id : sol.deliveries) sol.route.push_back(delivery_point(id));\n\n    sol.route.push_back(OFFICE);\n    sol.cost = path_length_points(sol.route);\n\n    return sol;\n}\n\nvector<pair<int, int>> ranking(function<int(int)> scorer) {\n    vector<pair<int, int>> v;\n    v.reserve(1000);\n    for (int i = 0; i < 1000; i++) v.push_back({scorer(i), i});\n    sort(v.begin(), v.end());\n    return v;\n}\n\nvector<int> top50_by(function<int(int)> scorer) {\n    auto v = ranking(scorer);\n    vector<int> ids;\n    ids.reserve(50);\n    for (int i = 0; i < 50; i++) ids.push_back(v[i].second);\n    return ids;\n}\n\nvector<int> topK_by(function<int(int)> scorer, int K) {\n    auto v = ranking(scorer);\n    vector<int> ids;\n    ids.reserve(K);\n    for (int i = 0; i < K; i++) ids.push_back(v[i].second);\n    return ids;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < 1000; i++) {\n        cin >> ords[i].a >> ords[i].b >> ords[i].c >> ords[i].d;\n    }\n\n    auto start_time = chrono::steady_clock::now();\n\n    vector<int> dPick(1000), dDel(1000), dDirect(1000), dRound(1000), dCenter(1000), dMax(1000);\n\n    for (int i = 0; i < 1000; i++) {\n        Point A = pickup_point(i);\n        Point B = delivery_point(i);\n\n        dPick[i] = mdist(OFFICE, A);\n        dDel[i] = mdist(OFFICE, B);\n        dDirect[i] = mdist(A, B);\n        dRound[i] = dPick[i] + dDirect[i] + dDel[i];\n        dCenter[i] = dPick[i] + dDel[i];\n        dMax[i] = max(dPick[i], dDel[i]);\n    }\n\n    auto score_round = [&](int i) {\n        return dRound[i];\n    };\n\n    auto score_center = [&](int i) {\n        return dCenter[i];\n    };\n\n    auto score_pick = [&](int i) {\n        return dPick[i];\n    };\n\n    auto score_del = [&](int i) {\n        return dDel[i];\n    };\n\n    auto score_max_direct = [&](int i) {\n        return dMax[i] * 2 + dDirect[i];\n    };\n\n    vector<vector<int>> initials;\n    initials.push_back(top50_by(score_round));\n    initials.push_back(top50_by(score_center));\n    initials.push_back(top50_by(score_pick));\n    initials.push_back(top50_by(score_del));\n    initials.push_back(top50_by(score_max_direct));\n\n    Solution best;\n    best.cost = INT_MAX;\n\n    for (auto ids : initials) {\n        Solution sol = build_solution(ids);\n        if (sol.cost < best.cost) best = sol;\n    }\n\n    vector<int> pool;\n    vector<char> in_pool(1000, false);\n\n    auto add_pool = [&](vector<int> v) {\n        for (int id : v) {\n            if (!in_pool[id]) {\n                in_pool[id] = true;\n                pool.push_back(id);\n            }\n        }\n    };\n\n    add_pool(topK_by(score_round, 180));\n    add_pool(topK_by(score_center, 180));\n    add_pool(topK_by(score_max_direct, 180));\n\n    sort(pool.begin(), pool.end(), [&](int x, int y) {\n        if (dRound[x] != dRound[y]) return dRound[x] < dRound[y];\n        return x < y;\n    });\n\n    if ((int)pool.size() > 260) pool.resize(260);\n\n    mt19937 rng(1234567);\n\n    Solution cur = best;\n    vector<int> cur_ids = cur.ids;\n\n    // Main search: restored best-performing single SA chain.\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.72) break;\n\n        vector<int> next_ids = cur_ids;\n        unordered_set<int> selected(next_ids.begin(), next_ids.end());\n\n        int remove_pos = uniform_int_distribution<int>(0, 49)(rng);\n\n        vector<int> candidates;\n        candidates.reserve(pool.size());\n        for (int id : pool) {\n            if (!selected.count(id)) candidates.push_back(id);\n        }\n        if (candidates.empty()) continue;\n\n        int add_id = candidates[uniform_int_distribution<int>(0, (int)candidates.size() - 1)(rng)];\n        next_ids[remove_pos] = add_id;\n\n        sort(next_ids.begin(), next_ids.end());\n        next_ids.erase(unique(next_ids.begin(), next_ids.end()), next_ids.end());\n        if ((int)next_ids.size() != 50) continue;\n\n        Solution nxt = build_solution(next_ids);\n\n        int diff = nxt.cost - cur.cost;\n        double temp = 40.0 * (1.72 - elapsed) / 1.72 + 1.0;\n\n        bool accept = false;\n        if (diff < 0) accept = true;\n        else {\n            double prob = exp(-diff / temp);\n            if (uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) accept = true;\n        }\n\n        if (accept) {\n            cur = nxt;\n            cur_ids = next_ids;\n        }\n\n        if (nxt.cost < best.cost) {\n            best = nxt;\n        }\n    }\n\n    // Small final strict-improvement scan.\n    vector<int> best_ids = best.ids;\n\n    for (int rem = 0; rem < 50; rem++) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n        if (elapsed > 1.90) break;\n\n        vector<char> selected(1000, false);\n        for (int id : best_ids) selected[id] = true;\n\n        for (int pi = 0; pi < min((int)pool.size(), 100); pi++) {\n            now = chrono::steady_clock::now();\n            elapsed = chrono::duration<double>(now - start_time).count();\n            if (elapsed > 1.90) break;\n\n            int add = pool[pi];\n            if (selected[add]) continue;\n\n            vector<int> ids = best_ids;\n            ids[rem] = add;\n\n            sort(ids.begin(), ids.end());\n            ids.erase(unique(ids.begin(), ids.end()), ids.end());\n            if ((int)ids.size() != 50) continue;\n\n            Solution sol = build_solution(ids);\n            if (sol.cost < best.cost) {\n                best = sol;\n                best_ids = ids;\n                break;\n            }\n        }\n    }\n\n    cout << 50;\n    for (int id : best.ids) {\n        cout << ' ' << id + 1;\n    }\n    cout << '\\n';\n\n    cout << best.route.size();\n    for (auto& p : best.route) {\n        cout << ' ' << p.x << ' ' << p.y;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n\n    DSU(int n = 0) {\n        init(n);\n    }\n\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int d;\n};\n\nstruct KEdge {\n    int w;\n    int id;\n\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return id < other.id;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    constexpr int N = 400;\n    constexpr int M = 1995;\n\n    vector<int> x(N), y(N);\n    for (int i = 0; i < N; i++) {\n        cin >> x[i] >> y[i];\n    }\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        cin >> edges[i].u >> edges[i].v;\n\n        long long dx = x[edges[i].u] - x[edges[i].v];\n        long long dy = y[edges[i].u] - y[edges[i].v];\n\n        edges[i].d = (int)llround(sqrt((double)(dx * dx + dy * dy)));\n        edges[i].d = max(edges[i].d, 1);\n    }\n\n    DSU accepted(N);\n    vector<int> actual(M, -1);\n\n    double coef = 1.92;\n\n    auto in_predicted_mst = [&](int cur, double base_coef) -> bool {\n        vector<KEdge> order;\n        order.reserve(M);\n\n        double progress = (double)cur / M;\n\n        for (int j = 0; j < M; j++) {\n            int w;\n\n            if (j <= cur) {\n                w = actual[j];\n            } else {\n                double t = (double)(j - cur) / max(1, M - cur);\n\n                double c = base_coef;\n                c += 0.08 * t;\n                c += 0.05 * max(0.0, progress - 0.75);\n\n                w = max(1, (int)round(c * edges[j].d));\n            }\n\n            order.push_back({w, j});\n        }\n\n        sort(order.begin(), order.end());\n\n        DSU tmp(N);\n\n        for (auto [w, id] : order) {\n            if (tmp.unite(edges[id].u, edges[id].v)) {\n                if (id == cur) return true;\n            }\n        }\n\n        return false;\n    };\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n        actual[i] = l;\n\n        bool take = false;\n\n        int ru = accepted.find(edges[i].u);\n        int rv = accepted.find(edges[i].v);\n\n        if (ru != rv) {\n            int comps = 0;\n            for (int v = 0; v < N; v++) {\n                if (accepted.find(v) == v) comps++;\n            }\n\n            // Safety check: current edge is a bridge among accepted-components\n            // using only current/future edges.\n            {\n                unordered_map<int, int> mp;\n                mp.reserve(N * 2);\n\n                for (int v = 0; v < N; v++) {\n                    int r = accepted.find(v);\n                    if (!mp.count(r)) {\n                        int id = (int)mp.size();\n                        mp[r] = id;\n                    }\n                }\n\n                int C = (int)mp.size();\n                vector<vector<pair<int, int>>> g(C);\n\n                for (int j = i; j < M; j++) {\n                    int a = mp[accepted.find(edges[j].u)];\n                    int b = mp[accepted.find(edges[j].v)];\n                    if (a == b) continue;\n\n                    g[a].push_back({b, j});\n                    g[b].push_back({a, j});\n                }\n\n                vector<int> tin(C, -1), low(C, -1);\n                int timer = 0;\n                bool is_bridge = false;\n\n                function<void(int, int)> dfs = [&](int v, int pe) {\n                    tin[v] = low[v] = timer++;\n\n                    for (auto [to, eid] : g[v]) {\n                        if (eid == pe) continue;\n\n                        if (tin[to] != -1) {\n                            low[v] = min(low[v], tin[to]);\n                        } else {\n                            dfs(to, eid);\n                            low[v] = min(low[v], low[to]);\n\n                            if (eid == i && low[to] > tin[v]) {\n                                is_bridge = true;\n                            }\n                        }\n                    }\n                };\n\n                for (int v = 0; v < C; v++) {\n                    if (tin[v] == -1) {\n                        dfs(v, -1);\n                    }\n                }\n\n                if (is_bridge) {\n                    take = true;\n                }\n            }\n\n            if (!take) {\n                double ratio = (double)l / edges[i].d;\n                double progress = (double)i / M;\n\n                int hit = 0;\n                int trials = 0;\n\n                auto test = [&](double c) {\n                    trials++;\n                    if (in_predicted_mst(i, c)) hit++;\n                };\n\n                test(coef - 0.06);\n                test(coef);\n                test(coef + 0.06);\n\n                // Small extra robustness late in the stream.\n                if (progress > 0.50) {\n                    test(coef - 0.10);\n                    test(coef + 0.10);\n                }\n\n                if (hit > 0) {\n                    double limit = 2.18 - 0.28 * progress;\n\n                    if (comps > 80) limit += 0.10;\n                    if (comps < 30) limit -= 0.10;\n\n                    // Normalize hit bonus by number of trials.\n                    double hrate = (double)hit / trials;\n                    if (hrate >= 0.80) limit += 0.05;\n                    else if (hrate <= 0.34) limit -= 0.03;\n\n                    if (progress > 0.80) limit -= 0.03;\n\n                    if (ratio <= limit || i > M - 420) {\n                        take = true;\n                    }\n                }\n            }\n\n            // Endgame fallback.\n            if (!take) {\n                int remaining = M - i;\n                if (remaining <= comps * 2) {\n                    take = true;\n                }\n            }\n        }\n\n        if (take) {\n            accepted.unite(edges[i].u, edges[i].v);\n            cout << 1 << '\\n';\n        } else {\n            cout << 0 << '\\n';\n        }\n\n        cout.flush();\n\n        if (i > 0 && i % 100 == 0) {\n            double sum = 0.0;\n\n            for (int j = 0; j <= i; j++) {\n                sum += (double)actual[j] / edges[j].d;\n            }\n\n            double avg = sum / (i + 1);\n            coef = 0.75 * coef + 0.25 * avg;\n            coef = min(2.08, max(1.78, coef));\n        }\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstruct Task {\n    int bx, by;\n    int hx, hy;\n    char build;\n};\n\nstruct Room {\n    int id;\n    int sz;\n    int x1, x2, y1, y2;\n    vector<Task> tasks;\n    vector<Pos> standby;\n};\n\nconst int H = 30, W = 30, TURNS = 300;\nint N, M;\nvector<Pos> pet, human_pos;\nvector<int> pet_type;\nbool wall[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar mvC[4] = {'U', 'D', 'L', 'R'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= H && 1 <= y && y <= W;\n}\n\nint dirIndex(char c) {\n    if (c == 'U') return 0;\n    if (c == 'D') return 1;\n    if (c == 'L') return 2;\n    if (c == 'R') return 3;\n    return -1;\n}\n\nint buildDirIndex(char c) {\n    if (c == 'u') return 0;\n    if (c == 'd') return 1;\n    if (c == 'l') return 2;\n    if (c == 'r') return 3;\n    return -1;\n}\n\nbool hasPet(int x, int y) {\n    for (auto &p : pet) {\n        if (p.x == x && p.y == y) return true;\n    }\n    return false;\n}\n\nbool hasHuman(int x, int y) {\n    for (auto &h : human_pos) {\n        if (h.x == x && h.y == y) return true;\n    }\n    return false;\n}\n\nbool canBuildCell(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (wall[x][y]) return true;\n    if (hasPet(x, y) || hasHuman(x, y)) return false;\n\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d];\n        int ny = y + dy[d];\n        if (inside(nx, ny) && hasPet(nx, ny)) return false;\n    }\n\n    return true;\n}\n\nbool inRect(Pos p, int x1, int x2, int y1, int y2) {\n    return x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2;\n}\n\nint manhattan(Pos a, Pos b) {\n    return abs(a.x - b.x) + abs(a.y - b.y);\n}\n\nchar stepToward(Pos cur, Pos goal, const bool reserved[31][31]) {\n    int bestd = INT_MAX;\n    char best = '.';\n\n    for (int d = 0; d < 4; d++) {\n        int nx = cur.x + dx[d];\n        int ny = cur.y + dy[d];\n\n        if (!inside(nx, ny)) continue;\n        if (wall[nx][ny]) continue;\n        if (reserved[nx][ny]) continue;\n\n        int md = abs(nx - goal.x) + abs(ny - goal.y);\n\n        if (md < bestd) {\n            bestd = md;\n            best = mvC[d];\n        }\n    }\n\n    return best;\n}\n\nvoid applyHumanActions(const string &ans) {\n    vector<Pos> newh = human_pos;\n    vector<pair<int, int>> builds;\n\n    for (int i = 0; i < M; i++) {\n        int d = buildDirIndex(ans[i]);\n\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d];\n            int ny = human_pos[i].y + dy[d];\n\n            if (inside(nx, ny) && canBuildCell(nx, ny)) {\n                builds.push_back({nx, ny});\n            }\n        }\n    }\n\n    for (auto &b : builds) {\n        wall[b.first][b.second] = true;\n    }\n\n    for (int i = 0; i < M; i++) {\n        int d = dirIndex(ans[i]);\n\n        if (d >= 0) {\n            int nx = human_pos[i].x + dx[d];\n            int ny = human_pos[i].y + dy[d];\n\n            if (inside(nx, ny) && !wall[nx][ny]) {\n                newh[i] = {nx, ny};\n            }\n        }\n    }\n\n    human_pos = newh;\n}\n\nvoid applyPetMoves(const vector<string> &moves) {\n    for (int i = 0; i < N; i++) {\n        for (char c : moves[i]) {\n            int d = dirIndex(c);\n\n            if (d >= 0) {\n                int nx = pet[i].x + dx[d];\n                int ny = pet[i].y + dy[d];\n\n                if (inside(nx, ny) && !wall[nx][ny]) {\n                    pet[i] = {nx, ny};\n                }\n            }\n        }\n    }\n}\n\nRoom makeRoom(int id, int sz) {\n    Room r;\n    r.id = id;\n    r.sz = sz;\n\n    if (id == 0) {\n        r.x1 = 1; r.x2 = sz; r.y1 = 1; r.y2 = sz;\n\n        for (int y = 1; y <= sz; y++) r.tasks.push_back({sz + 1, y, sz, y, 'd'});\n        for (int x = 1; x <= sz; x++) r.tasks.push_back({x, sz + 1, x, sz, 'r'});\n\n        for (int x = 2; x <= sz - 1; x++) {\n            for (int y = 2; y <= sz - 1; y++) r.standby.push_back({x, y});\n        }\n    } else if (id == 1) {\n        r.x1 = 1; r.x2 = sz; r.y1 = 31 - sz; r.y2 = 30;\n\n        for (int y = 31 - sz; y <= 30; y++) r.tasks.push_back({sz + 1, y, sz, y, 'd'});\n        for (int x = 1; x <= sz; x++) r.tasks.push_back({x, 30 - sz, x, 31 - sz, 'l'});\n\n        for (int x = 2; x <= sz - 1; x++) {\n            for (int y = 32 - sz; y <= 29; y++) r.standby.push_back({x, y});\n        }\n    } else if (id == 2) {\n        r.x1 = 31 - sz; r.x2 = 30; r.y1 = 1; r.y2 = sz;\n\n        for (int y = 1; y <= sz; y++) r.tasks.push_back({30 - sz, y, 31 - sz, y, 'u'});\n        for (int x = 31 - sz; x <= 30; x++) r.tasks.push_back({x, sz + 1, x, sz, 'r'});\n\n        for (int x = 32 - sz; x <= 29; x++) {\n            for (int y = 2; y <= sz - 1; y++) r.standby.push_back({x, y});\n        }\n    } else {\n        r.x1 = 31 - sz; r.x2 = 30; r.y1 = 31 - sz; r.y2 = 30;\n\n        for (int y = 31 - sz; y <= 30; y++) r.tasks.push_back({30 - sz, y, 31 - sz, y, 'u'});\n        for (int x = 31 - sz; x <= 30; x++) r.tasks.push_back({x, 30 - sz, x, 31 - sz, 'l'});\n\n        for (int x = 32 - sz; x <= 29; x++) {\n            for (int y = 32 - sz; y <= 29; y++) r.standby.push_back({x, y});\n        }\n    }\n\n    if (r.standby.empty()) {\n        r.standby.push_back({(r.x1 + r.x2) / 2, (r.y1 + r.y2) / 2});\n    }\n\n    return r;\n}\n\nstruct Eval {\n    long long risk;\n    int petsInside;\n    int petsNear;\n    int petsBoundaryNear;\n    long long travel;\n};\n\nEval evalRoom(const Room &r) {\n    int petsInside = 0;\n    int petsNear = 0;\n    int petsBoundaryNear = 0;\n\n    for (auto &p : pet) {\n        if (inRect(p, r.x1, r.x2, r.y1, r.y2)) petsInside++;\n\n        if (r.x1 - 2 <= p.x && p.x <= r.x2 + 2 &&\n            r.y1 - 2 <= p.y && p.y <= r.y2 + 2) {\n            petsNear++;\n        }\n\n        for (auto &t : r.tasks) {\n            if (manhattan(p, {t.bx, t.by}) <= 2) {\n                petsBoundaryNear++;\n                break;\n            }\n        }\n    }\n\n    Pos center{(r.x1 + r.x2) / 2, (r.y1 + r.y2) / 2};\n    long long travel = 0;\n\n    for (auto &h : human_pos) {\n        travel += manhattan(h, center);\n    }\n\n    long long risk = 0;\n    risk += 10000000LL * petsInside;\n    risk += 700000LL * petsNear;\n    risk += 350000LL * petsBoundaryNear;\n    risk += 20000LL * travel;\n\n    return {risk, petsInside, petsNear, petsBoundaryNear, travel};\n}\n\nbool actionLegalNow(int i, char c, const bool reserved[31][31]) {\n    if (c == '.') return true;\n\n    int md = dirIndex(c);\n    if (md >= 0) {\n        int nx = human_pos[i].x + dx[md];\n        int ny = human_pos[i].y + dy[md];\n\n        return inside(nx, ny) && !wall[nx][ny] && !reserved[nx][ny];\n    }\n\n    int bd = buildDirIndex(c);\n    if (bd >= 0) {\n        int bx = human_pos[i].x + dx[bd];\n        int by = human_pos[i].y + dy[bd];\n\n        return inside(bx, by) && canBuildCell(bx, by);\n    }\n\n    return false;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pet.resize(N);\n    pet_type.resize(N);\n\n    for (int i = 0; i < N; i++) {\n        cin >> pet[i].x >> pet[i].y >> pet_type[i];\n    }\n\n    cin >> M;\n    human_pos.resize(M);\n\n    for (int i = 0; i < M; i++) {\n        cin >> human_pos[i].x >> human_pos[i].y;\n    }\n\n    memset(wall, 0, sizeof(wall));\n\n    vector<Room> rooms8, rooms9, rooms10;\n\n    for (int id = 0; id < 4; id++) {\n        rooms8.push_back(makeRoom(id, 8));\n        rooms9.push_back(makeRoom(id, 9));\n        rooms10.push_back(makeRoom(id, 10));\n    }\n\n    Room best8 = rooms8[0];\n    Eval best8Eval = evalRoom(best8);\n\n    for (auto &r : rooms8) {\n        Eval e = evalRoom(r);\n        if (e.risk < best8Eval.risk) {\n            best8Eval = e;\n            best8 = r;\n        }\n    }\n\n    Room best9 = rooms9[0];\n    Eval best9Eval = evalRoom(best9);\n\n    for (auto &r : rooms9) {\n        Eval e = evalRoom(r);\n        if (e.risk < best9Eval.risk) {\n            best9Eval = e;\n            best9 = r;\n        }\n    }\n\n    Room best10 = rooms10[0];\n    Eval best10Eval = evalRoom(best10);\n\n    for (auto &r : rooms10) {\n        Eval e = evalRoom(r);\n        if (e.risk < best10Eval.risk) {\n            best10Eval = e;\n            best10 = r;\n        }\n    }\n\n    Room room = best8;\n\n    if (best9Eval.petsInside == 0 &&\n        best9Eval.petsNear <= best8Eval.petsNear &&\n        best9Eval.risk <= best8Eval.risk + 500000LL) {\n        room = best9;\n    }\n\n    // Rare, very conservative 10x10 upgrade.\n    // It is allowed only when construction and pet risk look exceptionally clean.\n    if (M >= 8 &&\n        best10Eval.petsInside == 0 &&\n        best10Eval.petsNear == 0 &&\n        best10Eval.petsBoundaryNear == 0 &&\n        best10Eval.travel <= best8Eval.travel + 10 &&\n        best10Eval.risk <= best8Eval.risk + 200000LL) {\n        room = best10;\n    }\n\n    vector<Pos> home(M);\n\n    for (int i = 0; i < M; i++) {\n        home[i] = room.standby[i % room.standby.size()];\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        string ans(M, '.');\n\n        bool reserved[31][31];\n        memset(reserved, 0, sizeof(reserved));\n\n        vector<int> usedTask(room.tasks.size(), 0);\n\n        // Build phase.\n        for (int i = 0; i < M; i++) {\n            Pos cur = human_pos[i];\n\n            int best = -1;\n\n            for (int k = 0; k < (int)room.tasks.size(); k++) {\n                if (usedTask[k]) continue;\n\n                Task &t = room.tasks[k];\n\n                if (wall[t.bx][t.by]) continue;\n                if (reserved[t.bx][t.by]) continue;\n\n                if (cur.x == t.hx && cur.y == t.hy && canBuildCell(t.bx, t.by)) {\n                    best = k;\n                    break;\n                }\n            }\n\n            if (best != -1) {\n                Task &t = room.tasks[best];\n                ans[i] = t.build;\n                usedTask[best] = 1;\n                reserved[t.bx][t.by] = true;\n            }\n        }\n\n        // Move phase.\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n\n            Pos cur = human_pos[i];\n\n            int best = -1;\n            int bestDist = INT_MAX;\n\n            for (int k = 0; k < (int)room.tasks.size(); k++) {\n                Task &t = room.tasks[k];\n\n                if (wall[t.bx][t.by]) continue;\n                if (reserved[t.hx][t.hy]) continue;\n\n                int d = manhattan(cur, {t.hx, t.hy});\n\n                if (!canBuildCell(t.bx, t.by)) d += 4;\n\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = k;\n                }\n            }\n\n            Pos goal;\n\n            if (best != -1) {\n                goal = {room.tasks[best].hx, room.tasks[best].hy};\n            } else {\n                goal = home[i];\n            }\n\n            if (cur.x != goal.x || cur.y != goal.y) {\n                char c = stepToward(cur, goal, reserved);\n                if (c != '.') ans[i] = c;\n            }\n        }\n\n        // Final legality filter.\n        for (int i = 0; i < M; i++) {\n            if (!actionLegalNow(i, ans[i], reserved)) {\n                ans[i] = '.';\n            }\n        }\n\n        cout << ans << endl;\n        cout.flush();\n\n        applyHumanActions(ans);\n\n        vector<string> pm(N);\n\n        for (int i = 0; i < N; i++) {\n            cin >> pm[i];\n        }\n\n        applyPetMoves(pm);\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int V = 400;\nstatic constexpr int MAXL = 200;\n\nint si_, sj_, ti_, tj_;\ndouble pforget;\n\nstring hwall[N];\nstring vwall[N - 1];\n\nint di[4] = {-1, 1, 0, 0};\nint dj[4] = {0, 0, -1, 1};\nchar dc[4] = {'U', 'D', 'L', 'R'};\n\nint nxt[V][4];\nint distT[V];\nint distS[V];\n\nmt19937 rng;\n\nint id(int i, int j) {\n    return i * N + j;\n}\n\nint dirId(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\nbool canMove(int i, int j, int d) {\n    if (d == 0) {\n        if (i == 0) return false;\n        return vwall[i - 1][j] == '0';\n    }\n    if (d == 1) {\n        if (i == N - 1) return false;\n        return vwall[i][j] == '0';\n    }\n    if (d == 2) {\n        if (j == 0) return false;\n        return hwall[i][j - 1] == '0';\n    }\n    if (d == 3) {\n        if (j == N - 1) return false;\n        return hwall[i][j] == '0';\n    }\n    return false;\n}\n\nvoid buildGraph() {\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int v = id(i, j);\n            for (int d = 0; d < 4; d++) {\n                if (canMove(i, j, d)) nxt[v][d] = id(i + di[d], j + dj[d]);\n                else nxt[v][d] = v;\n            }\n        }\n    }\n}\n\nvoid bfsFrom(int src, int dist[V]) {\n    fill(dist, dist + V, 1e9);\n    queue<int> q;\n    dist[src] = 0;\n    q.push(src);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n            if (dist[u] > dist[v] + 1) {\n                dist[u] = dist[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n}\n\nstring shortestPath(int s, int t, bool randomTie = false) {\n    vector<int> pre(V, -1), pred(V, -1);\n    queue<int> q;\n    pre[s] = s;\n    q.push(s);\n\n    while (!q.empty()) {\n        int v = q.front();\n        q.pop();\n\n        if (v == t) break;\n\n        array<int, 4> ord = {0, 1, 2, 3};\n        if (randomTie) shuffle(ord.begin(), ord.end(), rng);\n\n        for (int d : ord) {\n            int u = nxt[v][d];\n            if (u == v) continue;\n\n            if (pre[u] == -1) {\n                pre[u] = v;\n                pred[u] = d;\n                q.push(u);\n            }\n        }\n    }\n\n    if (pre[t] == -1) return \"\";\n\n    string res;\n    int cur = t;\n\n    while (cur != s) {\n        int d = pred[cur];\n        res.push_back(dc[d]);\n        cur = pre[cur];\n    }\n\n    reverse(res.begin(), res.end());\n    return res;\n}\n\ndouble evaluate(const string& route) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    static double prob[V], np[V];\n    fill(prob, prob + V, 0.0);\n    prob[s] = 1.0;\n\n    double expected = 0.0;\n    const double q = 1.0 - pforget;\n\n    for (int step = 0; step < (int)route.size(); step++) {\n        int d = dirId(route[step]);\n\n        fill(np, np + V, 0.0);\n\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * q;\n        }\n\n        double reach = np[t];\n\n        if (reach > 0.0) {\n            expected += reach * (401.0 - (step + 1));\n            np[t] = 0.0;\n        }\n\n        memcpy(prob, np, sizeof(prob));\n    }\n\n    return expected;\n}\n\narray<double, V> finalDistribution(const string& route) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    array<double, V> prob{}, np{};\n    prob.fill(0.0);\n    prob[s] = 1.0;\n\n    const double q = 1.0 - pforget;\n\n    for (char c : route) {\n        int d = dirId(c);\n        np.fill(0.0);\n\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * q;\n        }\n\n        np[t] = 0.0;\n        prob = np;\n    }\n\n    return prob;\n}\n\nstring repeatChars(const string& base, int r) {\n    string res;\n\n    for (char c : base) {\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring repeatWhole(const string& base) {\n    string res;\n    if (base.empty()) return res;\n\n    while ((int)res.size() < MAXL) {\n        for (char c : base) {\n            if ((int)res.size() >= MAXL) break;\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring noisyRepeatPath(const string& base) {\n    string res;\n    if (base.empty()) return res;\n\n    double mean = 1.0 / (1.0 - pforget);\n\n    for (char c : base) {\n        double noise = uniform_real_distribution<double>(-0.8, 1.8)(rng);\n        int r = max(1, (int)round(mean + noise));\n        r = min(r, 8);\n\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring stochasticExpandedPath(const string& base) {\n    string res;\n    if (base.empty()) return res;\n\n    double mean = 1.0 / (1.0 - pforget);\n    int ceilMean = max(1, (int)ceil(mean));\n\n    for (char c : base) {\n        int r;\n        int x = rng() % 100;\n\n        if (x < 20) r = 1;\n        else if (x < 70) r = ceilMean;\n        else if (x < 92) r = ceilMean + 1;\n        else r = ceilMean + 2;\n\n        r = min(r, 8);\n\n        for (int k = 0; k < r && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring deterministicDistRoute(int repeatBias, int lenLimit = MAXL) {\n    int cur = id(si_, sj_);\n    int t = id(ti_, tj_);\n    string route;\n\n    while ((int)route.size() < lenLimit && cur != t) {\n        int bd = -1;\n        int best = 1e9;\n\n        for (int d = 0; d < 4; d++) {\n            int u = nxt[cur][d];\n\n            if (u != cur && distT[u] < best) {\n                best = distT[u];\n                bd = d;\n            }\n        }\n\n        if (bd == -1) break;\n\n        for (int k = 0; k < repeatBias && (int)route.size() < lenLimit; k++) {\n            route.push_back(dc[bd]);\n        }\n\n        cur = nxt[cur][bd];\n    }\n\n    return route;\n}\n\nstring greedyDistribution(double temperature, double stayPenalty, double reachBonus, int lenLimit = MAXL) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<double> prob(V, 0.0), np(V, 0.0);\n    prob[s] = 1.0;\n\n    string route;\n\n    for (int step = 0; step < lenLimit; step++) {\n        double bestScore = 1e100;\n        vector<int> bestDirs;\n\n        for (int d = 0; d < 4; d++) {\n            fill(np.begin(), np.end(), 0.0);\n\n            for (int v = 0; v < V; v++) {\n                double pr = prob[v];\n                if (pr == 0.0) continue;\n\n                np[v] += pr * pforget;\n                np[nxt[v][d]] += pr * (1.0 - pforget);\n            }\n\n            double score = 0.0;\n\n            for (int v = 0; v < V; v++) {\n                double pr = np[v];\n                if (pr == 0.0) continue;\n\n                if (v == t) {\n                    score -= reachBonus * pr * (MAXL - step);\n                    continue;\n                }\n\n                score += pr * distT[v];\n\n                if (nxt[v][d] == v) {\n                    score += stayPenalty * pr;\n                }\n            }\n\n            if (temperature > 0.0) {\n                score += uniform_real_distribution<double>(-temperature, temperature)(rng);\n            }\n\n            if (score + 1e-12 < bestScore) {\n                bestScore = score;\n                bestDirs.clear();\n                bestDirs.push_back(d);\n            } else if (abs(score - bestScore) < 1e-12) {\n                bestDirs.push_back(d);\n            }\n        }\n\n        int d = bestDirs[rng() % bestDirs.size()];\n        route.push_back(dc[d]);\n\n        fill(np.begin(), np.end(), 0.0);\n\n        for (int v = 0; v < V; v++) {\n            double pr = prob[v];\n            if (pr == 0.0) continue;\n\n            np[v] += pr * pforget;\n            np[nxt[v][d]] += pr * (1.0 - pforget);\n        }\n\n        np[t] = 0.0;\n        prob.swap(np);\n\n        double alive = accumulate(prob.begin(), prob.end(), 0.0);\n        if (alive < 1e-12) break;\n    }\n\n    return route;\n}\n\nstruct BeamNode {\n    string route;\n    array<double, V> prob;\n    double heuristic;\n};\n\nstring beamSearchRoute(int beamWidth, int lenLimit, double reachWeight, double distWeight) {\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    vector<BeamNode> beam;\n    BeamNode init;\n    init.route.clear();\n    init.prob.fill(0.0);\n    init.prob[s] = 1.0;\n    init.heuristic = 0.0;\n    beam.push_back(init);\n\n    for (int step = 0; step < lenLimit; step++) {\n        vector<BeamNode> nb;\n        nb.reserve(beam.size() * 4);\n\n        for (const auto& node : beam) {\n            for (int d = 0; d < 4; d++) {\n                BeamNode x;\n                x.route = node.route;\n                x.route.push_back(dc[d]);\n                x.prob.fill(0.0);\n\n                for (int v = 0; v < V; v++) {\n                    double pr = node.prob[v];\n                    if (pr == 0.0) continue;\n\n                    x.prob[v] += pr * pforget;\n                    x.prob[nxt[v][d]] += pr * (1.0 - pforget);\n                }\n\n                double reached = x.prob[t];\n                x.prob[t] = 0.0;\n\n                double alive = 0.0;\n                double dsum = 0.0;\n\n                for (int v = 0; v < V; v++) {\n                    alive += x.prob[v];\n                    dsum += x.prob[v] * distT[v];\n                }\n\n                x.heuristic = node.heuristic\n                            + reached * reachWeight * (401.0 - (step + 1))\n                            - dsum * distWeight\n                            - alive * 0.02;\n\n                nb.push_back(move(x));\n            }\n        }\n\n        sort(nb.begin(), nb.end(), [](const BeamNode& a, const BeamNode& b) {\n            return a.heuristic > b.heuristic;\n        });\n\n        if ((int)nb.size() > beamWidth) nb.resize(beamWidth);\n        beam.swap(nb);\n    }\n\n    string best;\n    double bestVal = -1.0;\n\n    for (auto& node : beam) {\n        double val = evaluate(node.route);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = node.route;\n        }\n    }\n\n    return best;\n}\n\nchar randomBiasedChar() {\n    int x = rng() % 100;\n    if (x < 38) return 'D';\n    if (x < 76) return 'R';\n    if (x < 88) return 'U';\n    return 'L';\n}\n\nstring suffixAppendRepair(const string& base) {\n    if (base.empty()) return base;\n    if ((int)base.size() >= MAXL) return base;\n\n    auto prob = finalDistribution(base);\n\n    int bestCell = -1;\n    double bestPr = 0.0;\n\n    for (int v = 0; v < V; v++) {\n        if (prob[v] > bestPr) {\n            bestPr = prob[v];\n            bestCell = v;\n        }\n    }\n\n    if (bestCell == -1 || bestPr < 1e-12) return base;\n\n    string tail = shortestPath(bestCell, id(ti_, tj_), true);\n    string res = base;\n\n    for (char c : tail) {\n        if ((int)res.size() >= MAXL) break;\n        int rep = 1 + rng() % 3;\n        for (int k = 0; k < rep && (int)res.size() < MAXL; k++) {\n            res.push_back(c);\n        }\n    }\n\n    return res;\n}\n\nstring mutateString(string s, int strength) {\n    if (s.empty()) s = string(1, randomBiasedChar());\n    if ((int)s.size() > MAXL) s.resize(MAXL);\n\n    int ops = 1 + (rng() % max(1, strength));\n\n    for (int op = 0; op < ops; op++) {\n        if (s.empty()) {\n            s.push_back(randomBiasedChar());\n            continue;\n        }\n\n        int n = (int)s.size();\n        int type = rng() % 7;\n\n        if (type == 0) {\n            int pos = rng() % n;\n            s[pos] = dc[rng() % 4];\n        } else if (type == 1) {\n            if ((int)s.size() < MAXL) {\n                int pos = rng() % ((int)s.size() + 1);\n                s.insert(s.begin() + pos, randomBiasedChar());\n            }\n        } else if (type == 2) {\n            if ((int)s.size() > 1) {\n                int pos = rng() % (int)s.size();\n                s.erase(s.begin() + pos);\n            }\n        } else if (type == 3) {\n            int pos = rng() % (int)s.size();\n            int avail = (int)s.size() - pos;\n            if (avail > 0) {\n                int len = 1 + rng() % min(8, avail);\n                for (int k = 0; k < len; k++) {\n                    s[pos + k] = randomBiasedChar();\n                }\n            }\n        } else if (type == 4) {\n            if ((int)s.size() < MAXL) {\n                int pos = rng() % (int)s.size();\n                int avail = (int)s.size() - pos;\n                if (avail > 0) {\n                    int len = 1 + rng() % min(6, avail);\n                    string seg = s.substr(pos, len);\n                    int ipos = rng() % ((int)s.size() + 1);\n                    s.insert(ipos, seg);\n                    if ((int)s.size() > MAXL) s.resize(MAXL);\n                }\n            }\n        } else if (type == 5) {\n            if ((int)s.size() >= 2) {\n                int l = rng() % (int)s.size();\n                int maxLen = min(8, (int)s.size() - l);\n                if (maxLen >= 2) {\n                    int len = 2 + rng() % (maxLen - 1);\n                    reverse(s.begin() + l, s.begin() + l + len);\n                }\n            }\n        } else {\n            if ((int)s.size() >= 2) {\n                int pos = rng() % ((int)s.size() - 1);\n                swap(s[pos], s[pos + 1]);\n            }\n        }\n\n        if ((int)s.size() > MAXL) s.resize(MAXL);\n        if (s.empty()) s.push_back(randomBiasedChar());\n    }\n\n    return s;\n}\n\nbool tryOneCharNeighbor(string& best, double& bestVal) {\n    if (best.empty()) return false;\n\n    int pos = rng() % best.size();\n    char old = best[pos];\n\n    array<char, 4> ord = {'U', 'D', 'L', 'R'};\n    shuffle(ord.begin(), ord.end(), rng);\n\n    for (char c : ord) {\n        if (c == old) continue;\n\n        string cand = best;\n        cand[pos] = c;\n        double val = evaluate(cand);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n            return true;\n        }\n    }\n\n    return false;\n}\n\nbool tryOneSwapNeighbor(string& best, double& bestVal) {\n    if (best.size() < 2) return false;\n\n    int pos = rng() % (best.size() - 1);\n    if (best[pos] == best[pos + 1]) return false;\n\n    string cand = best;\n    swap(cand[pos], cand[pos + 1]);\n\n    double val = evaluate(cand);\n\n    if (val > bestVal) {\n        bestVal = val;\n        best = cand;\n        return true;\n    }\n\n    return false;\n}\n\nvoid deterministicSingleCharImprove(string& best, double& bestVal, chrono::steady_clock::time_point endTime) {\n    bool improved = true;\n\n    while (improved && chrono::steady_clock::now() < endTime) {\n        improved = false;\n\n        vector<int> positions(best.size());\n        iota(positions.begin(), positions.end(), 0);\n        shuffle(positions.begin(), positions.end(), rng);\n\n        for (int pos : positions) {\n            if (chrono::steady_clock::now() >= endTime) break;\n\n            char old = best[pos];\n            char bestChar = old;\n            double localBest = bestVal;\n\n            for (char c : {'U', 'D', 'L', 'R'}) {\n                if (c == old) continue;\n\n                string cand = best;\n                cand[pos] = c;\n\n                double val = evaluate(cand);\n\n                if (val > localBest) {\n                    localBest = val;\n                    bestChar = c;\n                }\n            }\n\n            if (bestChar != old) {\n                best[pos] = bestChar;\n                bestVal = localBest;\n                improved = true;\n            }\n        }\n    }\n}\n\nvoid deterministicSwapImprove(string& best, double& bestVal, chrono::steady_clock::time_point endTime) {\n    if (best.size() < 2) return;\n\n    bool improved = true;\n\n    while (improved && chrono::steady_clock::now() < endTime) {\n        improved = false;\n\n        vector<int> positions(best.size() - 1);\n        iota(positions.begin(), positions.end(), 0);\n        shuffle(positions.begin(), positions.end(), rng);\n\n        for (int pos : positions) {\n            if (chrono::steady_clock::now() >= endTime) break;\n            if (best[pos] == best[pos + 1]) continue;\n\n            string cand = best;\n            swap(cand[pos], cand[pos + 1]);\n\n            double val = evaluate(cand);\n\n            if (val > bestVal) {\n                bestVal = val;\n                best = cand;\n                improved = true;\n            }\n        }\n    }\n}\n\nvoid addCandidate(vector<string>& cands, const string& s) {\n    if (s.empty()) return;\n    string x = s;\n    if ((int)x.size() > MAXL) x.resize(MAXL);\n    cands.push_back(x);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto startTime = chrono::steady_clock::now();\n    auto endTime = startTime + chrono::milliseconds(1850);\n\n    cin >> si_ >> sj_ >> ti_ >> tj_ >> pforget;\n    for (int i = 0; i < N; i++) cin >> hwall[i];\n    for (int i = 0; i < N - 1; i++) cin >> vwall[i];\n\n    uint32_t seed = 1234567u;\n    seed ^= si_ * 1000003u;\n    seed ^= sj_ * 9176u;\n    seed ^= ti_ * 19260817u;\n    seed ^= tj_ * 998244353u;\n    seed ^= (uint32_t)(pforget * 1000);\n    rng.seed(seed);\n\n    buildGraph();\n\n    int s = id(si_, sj_);\n    int t = id(ti_, tj_);\n\n    bfsFrom(t, distT);\n    bfsFrom(s, distS);\n\n    vector<string> candidates;\n\n    string sp = shortestPath(s, t);\n    addCandidate(candidates, sp);\n\n    if (!sp.empty()) {\n        addCandidate(candidates, repeatWhole(sp));\n\n        for (int r = 2; r <= 10; r++) {\n            addCandidate(candidates, repeatChars(sp, r));\n        }\n\n        for (int trial = 0; trial < 80; trial++) {\n            string rsp = shortestPath(s, t, true);\n            addCandidate(candidates, rsp);\n            addCandidate(candidates, repeatChars(rsp, 2 + rng() % 6));\n            addCandidate(candidates, repeatWhole(rsp));\n            addCandidate(candidates, noisyRepeatPath(rsp));\n            addCandidate(candidates, stochasticExpandedPath(rsp));\n        }\n    }\n\n    for (int r = 1; r <= 10; r++) {\n        addCandidate(candidates, deterministicDistRoute(r));\n    }\n\n    vector<double> temps = {0.0, 0.02, 0.05, 0.1, 0.2, 0.4, 0.8, 1.5, 3.0};\n    vector<double> penalties = {0.0, 0.05, 0.15, 0.3, 0.7, 1.5, 3.0};\n    vector<double> bonuses = {0.2, 0.5, 1.0, 2.0, 4.0};\n\n    for (double temp : temps) {\n        for (double pen : penalties) {\n            for (double bonus : bonuses) {\n                addCandidate(candidates, greedyDistribution(temp, pen, bonus));\n            }\n        }\n    }\n\n    addCandidate(candidates, beamSearchRoute(8, 120, 1.0, 0.03));\n    addCandidate(candidates, beamSearchRoute(10, 150, 1.0, 0.02));\n    addCandidate(candidates, beamSearchRoute(12, 200, 1.0, 0.015));\n\n    vector<int> cells(V);\n    iota(cells.begin(), cells.end(), 0);\n\n    sort(cells.begin(), cells.end(), [&](int a, int b) {\n        int ai = a / N, aj = a % N;\n        int bi = b / N, bj = b % N;\n\n        int ascore = distS[a] + distT[a] + abs(ai - 10) + abs(aj - 10);\n        int bscore = distS[b] + distT[b] + abs(bi - 10) + abs(bj - 10);\n\n        return ascore < bscore;\n    });\n\n    for (int idx = 0; idx < min(V, 80); idx++) {\n        int mid = cells[idx];\n\n        string a = shortestPath(s, mid, true);\n        string b = shortestPath(mid, t, true);\n\n        if (a.empty() || b.empty()) continue;\n\n        string path = a + b;\n        if ((int)path.size() > MAXL) path.resize(MAXL);\n\n        addCandidate(candidates, path);\n        addCandidate(candidates, repeatWhole(path));\n        addCandidate(candidates, noisyRepeatPath(path));\n        addCandidate(candidates, stochasticExpandedPath(path));\n\n        for (int r = 2; r <= 5; r++) {\n            addCandidate(candidates, repeatChars(path, r));\n        }\n    }\n\n    for (int trial = 0; trial < 120; trial++) {\n        string r;\n        int len = 80 + rng() % 121;\n        for (int i = 0; i < len; i++) {\n            r.push_back(randomBiasedChar());\n        }\n        addCandidate(candidates, r);\n    }\n\n    string best = sp.empty() ? string(\"D\") : sp;\n    double bestVal = evaluate(best);\n\n    vector<pair<double, string>> elite;\n    elite.push_back({bestVal, best});\n\n    for (string cand : candidates) {\n        if (chrono::steady_clock::now() >= endTime) break;\n\n        if (cand.empty()) continue;\n        if ((int)cand.size() > MAXL) cand.resize(MAXL);\n\n        double val = evaluate(cand);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n\n        elite.push_back({val, cand});\n    }\n\n    sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    if ((int)elite.size() > 30) elite.resize(30);\n\n    int repairN = min(8, (int)elite.size());\n\n    for (int i = 0; i < repairN; i++) {\n        if (chrono::steady_clock::now() >= endTime) break;\n\n        string r = suffixAppendRepair(elite[i].second);\n        double val = evaluate(r);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = r;\n        }\n\n        elite.push_back({val, r});\n    }\n\n    sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n        return a.first > b.first;\n    });\n\n    if ((int)elite.size() > 30) elite.resize(30);\n\n    auto charImproveEnd = startTime + chrono::milliseconds(1400);\n    deterministicSingleCharImprove(best, bestVal, charImproveEnd);\n\n    auto swapImproveEnd = startTime + chrono::milliseconds(1480);\n    deterministicSwapImprove(best, bestVal, swapImproveEnd);\n\n    int stagnant = 0;\n\n    while (chrono::steady_clock::now() < endTime) {\n        string base;\n\n        int mode = rng() % 100;\n\n        if (mode < 80) {\n            base = best;\n        } else {\n            int top = max(1, min(10, (int)elite.size()));\n            base = elite[rng() % top].second;\n        }\n\n        int strength = 1 + min(18, stagnant / 25);\n        string cand = mutateString(base, strength);\n\n        double val = evaluate(cand);\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n            stagnant = 0;\n        } else {\n            stagnant++;\n\n            if ((stagnant & 7) == 0 && chrono::steady_clock::now() < endTime) {\n                if (rng() & 1) tryOneCharNeighbor(best, bestVal);\n                else tryOneSwapNeighbor(best, bestVal);\n            }\n        }\n\n        if (val > elite.back().first) {\n            elite.push_back({val, cand});\n            sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n                return a.first > b.first;\n            });\n            if ((int)elite.size() > 30) elite.resize(30);\n        }\n\n        if (stagnant % 180 == 179 && !sp.empty()) {\n            string base2;\n            int m = rng() % 4;\n\n            if (m == 0) base2 = repeatChars(sp, 2 + rng() % 8);\n            else if (m == 1) base2 = repeatWhole(sp);\n            else if (m == 2) base2 = stochasticExpandedPath(shortestPath(s, t, true));\n            else base2 = greedyDistribution(0.5, 0.5, 1.0);\n\n            string cand2 = mutateString(base2, 8);\n            double val2 = evaluate(cand2);\n\n            if (val2 > bestVal) {\n                bestVal = val2;\n                best = cand2;\n                stagnant = 0;\n            }\n\n            if (val2 > elite.back().first) {\n                elite.push_back({val2, cand2});\n                sort(elite.begin(), elite.end(), [](const auto& a, const auto& b) {\n                    return a.first > b.first;\n                });\n                if ((int)elite.size() > 30) elite.resize(30);\n            }\n        }\n    }\n\n    if (best.empty()) best = \"D\";\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n\n    cout << best << '\\n';\n\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int V = N * N * 4;\n\nint to_dir[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\nint di[4] = {0, -1, 0, 1};\nint dj[4] = {-1, 0, 1, 0};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int n) {\n        return (int)(next_u64() % n);\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint rotate_state(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (0 <= t && t <= 3) t = (t + 1) & 3;\n        else if (t == 4) t = 5;\n        else if (t == 5) t = 4;\n        else if (t == 6) t = 7;\n        else if (t == 7) t = 6;\n    }\n    return t;\n}\n\nbool state_has_pair(int t, int a, int b) {\n    if (a > b) swap(a, b);\n    int p = a * 4 + b;\n    for (int d = 0; d < 4; d++) {\n        if (to_dir[t][d] != -1) {\n            int x = d, y = to_dir[t][d];\n            if (x > y) swap(x, y);\n            if (x * 4 + y == p) return true;\n        }\n    }\n    return false;\n}\n\nint rotation_for_pair(int base, int a, int b) {\n    for (int r = 0; r < 4; r++) {\n        if (state_has_pair(rotate_state(base, r), a, b)) return r;\n    }\n    return -1;\n}\n\nint dir_between(int from_i, int from_j, int to_i, int to_j) {\n    if (to_i == from_i && to_j == from_j - 1) return 0;\n    if (to_i == from_i - 1 && to_j == from_j) return 1;\n    if (to_i == from_i && to_j == from_j + 1) return 2;\n    if (to_i == from_i + 1 && to_j == from_j) return 3;\n    return -1;\n}\n\nstruct Candidate {\n    vector<int> cells;\n    vector<unsigned char> req_a;\n    vector<unsigned char> req_b;\n    int len = 0;\n    int ci = 0, cj = 0;\n    uint64_t mask[15]{};\n};\n\nstruct Solver {\n    vector<string> s;\n    array<int, N * N> base{};\n    array<int, N * N> rot{};\n    array<int, N * N> tile{};\n    array<int, N * N> best_rot{};\n    array<int, N * N> fixed_cell{};\n    XorShift rng;\n\n    int feasible_pair[900][4][4]{};\n    int banned[900]{};\n\n    int id(int i, int j, int d) const {\n        return ((i * N + j) << 2) | d;\n    }\n\n    tuple<int,int,int> decode(int x) const {\n        int d = x & 3;\n        x >>= 2;\n        return {x / N, x % N, d};\n    }\n\n    int nxt(int x) const {\n        auto [i, j, d] = decode(x);\n        int t = tile[i * N + j];\n        int d2 = to_dir[t][d];\n        if (d2 == -1) return -1;\n        int ni = i + di[d2], nj = j + dj[d2];\n        if (ni < 0 || ni >= N || nj < 0 || nj >= N) return -1;\n        return id(ni, nj, (d2 + 2) & 3);\n    }\n\n    long long evaluate() const {\n        static int state[V], seen[V], dep[V];\n\n        for (int i = 0; i < V; i++) {\n            state[i] = 0;\n            seen[i] = -1;\n            dep[i] = 0;\n        }\n\n        int best1 = 0, best2 = 0;\n\n        for (int st = 0; st < V; st++) {\n            if (state[st]) continue;\n\n            int cur = st;\n            vector<int> path;\n            path.reserve(256);\n\n            while (true) {\n                if (cur == -1) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 2) {\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n                if (state[cur] == 1) {\n                    if (seen[cur] == st) {\n                        int len = (int)path.size() - dep[cur];\n                        if (len >= best1) {\n                            best2 = best1;\n                            best1 = len;\n                        } else if (len > best2) {\n                            best2 = len;\n                        }\n                    }\n                    for (int v : path) state[v] = 2;\n                    break;\n                }\n\n                state[cur] = 1;\n                seen[cur] = st;\n                dep[cur] = (int)path.size();\n                path.push_back(cur);\n                cur = nxt(cur);\n            }\n        }\n\n        if (best2 == 0) return 0;\n        return 1LL * best1 * best2;\n    }\n\n    void rebuild_tile() {\n        for (int i = 0; i < N * N; i++) {\n            tile[i] = rotate_state(base[i], rot[i]);\n        }\n    }\n\n    bool disjoint(const Candidate& a, const Candidate& b) const {\n        for (int k = 0; k < 15; k++) {\n            if (a.mask[k] & b.mask[k]) return false;\n        }\n        return true;\n    }\n\n    bool make_candidate_from_cycle(const vector<int>& cyc, Candidate& cand) const {\n        int m = (int)cyc.size();\n        if (m < 8) return false;\n\n        cand.cells.clear();\n        cand.req_a.clear();\n        cand.req_b.clear();\n        cand.len = m;\n        cand.ci = cand.cj = 0;\n        memset(cand.mask, 0, sizeof(cand.mask));\n\n        static int used[N * N];\n        static int mark = 100000;\n        mark++;\n        if (mark == INT_MAX) {\n            memset(used, 0, sizeof(used));\n            mark = 100000;\n        }\n\n        int sumi = 0, sumj = 0;\n\n        for (int x : cyc) {\n            if (x < 0 || x >= N * N) return false;\n            if (banned[x]) return false;\n            if (used[x] == mark) return false;\n            used[x] = mark;\n            sumi += x / N;\n            sumj += x % N;\n        }\n\n        cand.ci = sumi / m;\n        cand.cj = sumj / m;\n\n        for (int k = 0; k < m; k++) {\n            int prev = cyc[(k - 1 + m) % m];\n            int cur = cyc[k];\n            int nxtc = cyc[(k + 1) % m];\n\n            int ci = cur / N, cj = cur % N;\n            int pi = prev / N, pj = prev % N;\n            int ni = nxtc / N, nj = nxtc % N;\n\n            int dprev = dir_between(ci, cj, pi, pj);\n            int dnxt = dir_between(ci, cj, ni, nj);\n            if (dprev == -1 || dnxt == -1 || dprev == dnxt) return false;\n\n            if (!feasible_pair[cur][dprev][dnxt]) return false;\n\n            cand.cells.push_back(cur);\n            cand.req_a.push_back((unsigned char)dprev);\n            cand.req_b.push_back((unsigned char)dnxt);\n            cand.mask[cur >> 6] |= 1ULL << (cur & 63);\n        }\n\n        return true;\n    }\n\n    void try_add_cycle(vector<Candidate>& cands, const vector<int>& cyc) const {\n        Candidate cand;\n        if (make_candidate_from_cycle(cyc, cand)) {\n            cands.push_back(std::move(cand));\n        }\n    }\n\n    void add_rect_candidates(vector<Candidate>& cands) const {\n        for (int r1 = 0; r1 < N; r1++) {\n            for (int r2 = r1 + 1; r2 < N; r2++) {\n                for (int c1 = 0; c1 < N; c1++) {\n                    for (int c2 = c1 + 1; c2 < N; c2++) {\n                        int len = 2 * ((r2 - r1) + (c2 - c1));\n                        if (len < 20) continue;\n\n                        vector<int> cyc;\n                        cyc.reserve(len);\n\n                        for (int j = c1; j < c2; j++) cyc.push_back(r1 * N + j);\n                        for (int i = r1; i < r2; i++) cyc.push_back(i * N + c2);\n                        for (int j = c2; j > c1; j--) cyc.push_back(r2 * N + j);\n                        for (int i = r2; i > r1; i--) cyc.push_back(i * N + c1);\n\n                        try_add_cycle(cands, cyc);\n                    }\n                }\n            }\n        }\n    }\n\n    bool feasible_random_cycle(Candidate& cand, int target_len) {\n        int si = rng.next_int(N);\n        int sj = rng.next_int(N);\n        int start = si * N + sj;\n        if (banned[start]) return false;\n\n        static int used[N * N];\n        static int mark = 1;\n        mark++;\n        if (mark == INT_MAX) {\n            memset(used, 0, sizeof(used));\n            mark = 1;\n        }\n\n        vector<int> path;\n        path.reserve(target_len + 8);\n        path.push_back(start);\n        used[start] = mark;\n\n        int ci = si, cj = sj;\n\n        for (int step = 0; step < target_len + 100; step++) {\n            vector<pair<int,int>> cand_dirs;\n            cand_dirs.reserve(4);\n\n            int cur = ci * N + cj;\n            int in_dir = -1;\n            if ((int)path.size() >= 2) {\n                int prev = path[path.size() - 2];\n                int pi = prev / N, pj = prev % N;\n                in_dir = dir_between(ci, cj, pi, pj);\n            }\n\n            for (int d = 0; d < 4; d++) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                int nid = ni * N + nj;\n\n                if (nid == start) {\n                    if ((int)path.size() < 8) continue;\n                    if (in_dir != -1 && !feasible_pair[cur][in_dir][d]) continue;\n\n                    int first = path[1];\n                    int fi = first / N, fj = first % N;\n                    int out_start = dir_between(si, sj, fi, fj);\n                    int in_start = dir_between(si, sj, ci, cj);\n                    if (out_start == -1 || in_start == -1) continue;\n                    if (!feasible_pair[start][in_start][out_start]) continue;\n\n                    Candidate tmp;\n                    if (make_candidate_from_cycle(path, tmp)) {\n                        cand = std::move(tmp);\n                        return true;\n                    }\n                    continue;\n                }\n\n                if (banned[nid]) continue;\n                if (used[nid] == mark) continue;\n                if ((int)path.size() >= target_len) continue;\n                if (in_dir != -1 && !feasible_pair[cur][in_dir][d]) continue;\n\n                int dist_now = abs(ci - si) + abs(cj - sj);\n                int dist_next = abs(ni - si) + abs(nj - sj);\n\n                int score = rng.next_int(100);\n\n                if ((int)path.size() > target_len * 2 / 3) {\n                    score -= (dist_now - dist_next) * 50;\n                } else {\n                    score += dist_next * 2;\n                }\n\n                int deg = 0;\n                for (int nd = 0; nd < 4; nd++) {\n                    int xi = ni + di[nd], xj = nj + dj[nd];\n                    if (xi < 0 || xi >= N || xj < 0 || xj >= N) continue;\n                    if (!banned[xi * N + xj]) deg++;\n                }\n                score -= deg * 3;\n\n                cand_dirs.push_back({score, d});\n            }\n\n            if (cand_dirs.empty()) break;\n\n            sort(cand_dirs.begin(), cand_dirs.end());\n\n            int pick_lim = min<int>(3, cand_dirs.size());\n            int pick = rng.next_int(pick_lim);\n            int d = cand_dirs[pick].second;\n\n            int ni = ci + di[d], nj = cj + dj[d];\n            int nid = ni * N + nj;\n\n            used[nid] = mark;\n            path.push_back(nid);\n            ci = ni;\n            cj = nj;\n        }\n\n        return false;\n    }\n\n    void generate_candidates(vector<Candidate>& cands, const Timer& timer, double until) {\n        while (timer.elapsed() < until) {\n            Candidate cand;\n            int target;\n            int r = rng.next_int(100);\n            if (r < 30) target = 40 + rng.next_int(70);\n            else if (r < 82) target = 90 + rng.next_int(130);\n            else target = 180 + rng.next_int(220);\n\n            if (feasible_random_cycle(cand, target)) {\n                cands.push_back(std::move(cand));\n            }\n        }\n    }\n\n    void sort_filter(vector<Candidate>& cands, int limit) {\n        sort(cands.begin(), cands.end(), [](const Candidate& a, const Candidate& b) {\n            return a.len > b.len;\n        });\n\n        vector<Candidate> filtered;\n        filtered.reserve(min<int>(limit, cands.size()));\n\n        for (auto &c : cands) {\n            bool duplicate = false;\n            int start = max(0, (int)filtered.size() - 250);\n            for (int i = start; i < (int)filtered.size(); i++) {\n                bool same = true;\n                for (int k = 0; k < 15; k++) {\n                    if (filtered[i].mask[k] != c.mask[k]) {\n                        same = false;\n                        break;\n                    }\n                }\n                if (same) {\n                    duplicate = true;\n                    break;\n                }\n            }\n            if (!duplicate) filtered.push_back(std::move(c));\n            if ((int)filtered.size() >= limit) break;\n        }\n\n        cands.swap(filtered);\n    }\n\n    pair<int,int> best_pair_indices(const vector<Candidate>& cands) const {\n        long long best_prod = -1;\n        int bi = -1, bj = -1;\n\n        for (int i = 0; i < (int)cands.size(); i++) {\n            if (1LL * cands[i].len * cands[i].len < best_prod) break;\n            for (int j = i + 1; j < (int)cands.size(); j++) {\n                long long prod = 1LL * cands[i].len * cands[j].len;\n                if (prod <= best_prod) break;\n                if (disjoint(cands[i], cands[j])) {\n                    best_prod = prod;\n                    bi = i;\n                    bj = j;\n                    break;\n                }\n            }\n        }\n        return {bi, bj};\n    }\n\n    void apply_candidate(const Candidate& cand) {\n        for (int k = 0; k < (int)cand.cells.size(); k++) {\n            int cell = cand.cells[k];\n            int a = cand.req_a[k];\n            int b = cand.req_b[k];\n\n            int r = rotation_for_pair(base[cell], a, b);\n            if (r >= 0) {\n                rot[cell] = r;\n                fixed_cell[cell] = 1;\n            }\n        }\n    }\n\n    void fill_random_free() {\n        for (int i = 0; i < N * N; i++) {\n            if (fixed_cell[i]) continue;\n            int maxr = (base[i] <= 3 ? 4 : 2);\n            rot[i] = rng.next_int(maxr);\n        }\n        rebuild_tile();\n    }\n\n    long long eval_candidate_pair(const Candidate& a, const Candidate& b) {\n        auto save_rot = rot;\n        auto save_fixed = fixed_cell;\n\n        fixed_cell.fill(0);\n        rot.fill(0);\n        apply_candidate(a);\n        apply_candidate(b);\n        fill_random_free();\n\n        long long sc = evaluate();\n\n        rot = save_rot;\n        fixed_cell = save_fixed;\n        rebuild_tile();\n\n        return sc;\n    }\n\n    vector<int> select_first_trials(const vector<Candidate>& cands) {\n        vector<int> ids;\n        int m = (int)cands.size();\n        if (m == 0) return ids;\n\n        for (int i = 0; i < min(12, m); i++) ids.push_back(i);\n\n        vector<int> best_quad(9, -1);\n        for (int i = 0; i < min(m, 1500); i++) {\n            int qi = min(2, cands[i].ci / 10);\n            int qj = min(2, cands[i].cj / 10);\n            int q = qi * 3 + qj;\n            if (best_quad[q] == -1) best_quad[q] = i;\n        }\n        for (int x : best_quad) if (x != -1) ids.push_back(x);\n\n        for (int k = 0; k < 12 && m > 0; k++) {\n            ids.push_back(rng.next_int(min(m, 800)));\n        }\n\n        sort(ids.begin(), ids.end());\n        ids.erase(unique(ids.begin(), ids.end()), ids.end());\n        return ids;\n    }\n\n    void construct_solution(const Timer& timer) {\n        vector<Candidate> base_cands;\n        memset(banned, 0, sizeof(banned));\n\n        add_rect_candidates(base_cands);\n        generate_candidates(base_cands, timer, 0.82);\n        sort_filter(base_cands, 5500);\n\n        Candidate bestA, bestB;\n        long long best_prod = -1;\n        long long best_eval = -1;\n\n        auto [pi, pj] = best_pair_indices(base_cands);\n        if (pi != -1) {\n            bestA = base_cands[pi];\n            bestB = base_cands[pj];\n            best_prod = 1LL * bestA.len * bestB.len;\n            best_eval = best_prod;\n        }\n\n        vector<int> trials = select_first_trials(base_cands);\n        double phase_start = timer.elapsed();\n        double phase_budget = 0.34;\n\n        for (int ti = 0; ti < (int)trials.size() && timer.elapsed() < 1.18; ti++) {\n            const Candidate& first = base_cands[trials[ti]];\n\n            memset(banned, 0, sizeof(banned));\n            for (int cell : first.cells) banned[cell] = 1;\n\n            vector<Candidate> second_cands;\n            double until = phase_start + phase_budget * (ti + 1) / max(1, (int)trials.size());\n            generate_candidates(second_cands, timer, until);\n            sort_filter(second_cands, 1200);\n\n            int checked = 0;\n            for (auto &sec : second_cands) {\n                long long prod = 1LL * first.len * sec.len;\n                if (prod < best_prod * 95 / 100) break;\n\n                long long eval_sc = prod;\n                if (checked < 2 && timer.elapsed() < 1.18) {\n                    eval_sc = eval_candidate_pair(first, sec);\n                    checked++;\n                }\n\n                if (prod > best_prod || eval_sc > best_eval) {\n                    best_prod = max(best_prod, prod);\n                    best_eval = max(best_eval, eval_sc);\n                    bestA = first;\n                    bestB = sec;\n                }\n\n                if (prod <= best_prod) break;\n            }\n        }\n\n        memset(banned, 0, sizeof(banned));\n\n        fixed_cell.fill(0);\n        rot.fill(0);\n\n        if (best_prod > 0) {\n            apply_candidate(bestA);\n            apply_candidate(bestB);\n        }\n\n        fill_random_free();\n    }\n\n    void improve_free_cells(double until_sec, const Timer& timer) {\n        long long cur = evaluate();\n        long long best = cur;\n        best_rot = rot;\n\n        while (timer.elapsed() < until_sec) {\n            int p = rng.next_int(N * N);\n            if (fixed_cell[p]) continue;\n\n            int oldr = rot[p];\n            int oldt = tile[p];\n\n            int maxr = (base[p] <= 3 ? 4 : 2);\n            int nr = rng.next_int(maxr);\n            if (nr == oldr) nr = (nr + 1) % maxr;\n\n            rot[p] = nr;\n            tile[p] = rotate_state(base[p], nr);\n\n            long long ns = evaluate();\n            long long diff = ns - cur;\n\n            double progress = timer.elapsed() / until_sec;\n            double temp = 800.0 * (1.0 - progress) + 2.0;\n\n            bool accept = false;\n            if (diff >= 0) accept = true;\n            else if (rng.next_double() < exp((double)diff / temp)) accept = true;\n\n            if (accept) {\n                cur = ns;\n                if (cur > best) {\n                    best = cur;\n                    best_rot = rot;\n                }\n            } else {\n                rot[p] = oldr;\n                tile[p] = oldt;\n            }\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n    }\n\n    void solve() {\n        s.resize(N);\n        for (int i = 0; i < N; i++) cin >> s[i];\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                base[i * N + j] = s[i][j] - '0';\n            }\n        }\n\n        for (int cell = 0; cell < N * N; cell++) {\n            for (int a = 0; a < 4; a++) {\n                for (int b = 0; b < 4; b++) {\n                    feasible_pair[cell][a][b] = (a != b && rotation_for_pair(base[cell], a, b) != -1);\n                }\n            }\n        }\n\n        Timer timer;\n\n        construct_solution(timer);\n\n        long long best_score = evaluate();\n        best_rot = rot;\n\n        while (timer.elapsed() < 1.25) {\n            fill_random_free();\n            long long sc = evaluate();\n            if (sc > best_score) {\n                best_score = sc;\n                best_rot = rot;\n            }\n        }\n\n        rot = best_rot;\n        rebuild_tile();\n\n        improve_free_cells(1.90, timer);\n\n        string ans;\n        ans.reserve(N * N);\n        for (int i = 0; i < N * N; i++) {\n            ans.push_back(char('0' + rot[i]));\n        }\n        cout << ans << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc011":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point s = chrono::steady_clock::now();\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - s).count();\n    }\n};\n\nint N, Tlim, M;\nvector<unsigned char> initb;\nmt19937 rng(1234567);\n\nint hv(char c) {\n    return c <= '9' ? c - '0' : c - 'a' + 10;\n}\n\nstruct DSU {\n    int p[105], z[105];\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        for(int i=0;i<n;i++){\n            p[i]=i;\n            z[i]=1;\n        }\n    }\n    int f(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[x];\n        }\n        return x;\n    }\n    bool uni(int a,int b){\n        a=f(a);\n        b=f(b);\n        if(a==b) return false;\n        if(z[a]<z[b]) swap(a,b);\n        p[b]=a;\n        z[a]+=z[b];\n        return true;\n    }\n};\n\nstruct Ev {\n    int lt, lc, e, cy, tc, co, iso;\n};\n\nEv evalb(const vector<unsigned char>& b){\n    DSU d(M);\n    bool act[105];\n    for(int i=0;i<M;i++) act[i]=(b[i]!=0);\n\n    int edges=0, cy=0;\n\n    for(int r=0;r<N;r++){\n        for(int c=0;c<N;c++){\n            int id=r*N+c;\n            if(!act[id]) continue;\n            int v=b[id];\n\n            if(c+1<N){\n                int ni=id+1;\n                if(act[ni] && (v&4) && (b[ni]&1)){\n                    edges++;\n                    if(!d.uni(id,ni)) cy++;\n                }\n            }\n            if(r+1<N){\n                int ni=id+N;\n                if(act[ni] && (v&8) && (b[ni]&2)){\n                    edges++;\n                    if(!d.uni(id,ni)) cy++;\n                }\n            }\n        }\n    }\n\n    int vc[105]={}, ec[105]={};\n\n    for(int i=0;i<M;i++){\n        if(act[i]) vc[d.f(i)]++;\n    }\n\n    for(int r=0;r<N;r++){\n        for(int c=0;c<N;c++){\n            int id=r*N+c;\n            if(!act[id]) continue;\n            int v=b[id];\n\n            if(c+1<N){\n                int ni=id+1;\n                if(act[ni] && (v&4) && (b[ni]&1)){\n                    ec[d.f(id)]++;\n                }\n            }\n            if(r+1<N){\n                int ni=id+N;\n                if(act[ni] && (v&8) && (b[ni]&2)){\n                    ec[d.f(id)]++;\n                }\n            }\n        }\n    }\n\n    Ev e{0,0,edges,cy,0,0,0};\n\n    for(int i=0;i<M;i++){\n        if(vc[i]){\n            e.co++;\n            e.lc=max(e.lc,vc[i]);\n            if(vc[i]==1) e.iso++;\n            if(ec[i]==vc[i]-1){\n                e.tc++;\n                e.lt=max(e.lt,vc[i]);\n            }\n        }\n    }\n\n    return e;\n}\n\nint offscore_ev(const Ev& e,int k){\n    if(e.lt==M-1) return 1000000000-k*1000;\n    return e.lt*1000000;\n}\n\nchar opp(char c){\n    if(c=='U') return 'D';\n    if(c=='D') return 'U';\n    if(c=='L') return 'R';\n    if(c=='R') return 'L';\n    return '?';\n}\n\nbool apply(vector<unsigned char>& b,int& emp,char m){\n    int r=emp/N,c=emp%N,nr=r,nc=c;\n\n    if(m=='U') nr--;\n    if(m=='D') nr++;\n    if(m=='L') nc--;\n    if(m=='R') nc++;\n\n    if(nr<0 || nr>=N || nc<0 || nc>=N) return false;\n\n    int np=nr*N+nc;\n    swap(b[emp],b[np]);\n    emp=np;\n    return true;\n}\n\nstring keyb(const vector<unsigned char>& b,int emp){\n    string s;\n    s.resize(M+1);\n    for(int i=0;i<M;i++) s[i]=char(b[i]);\n    s[M]=char(emp);\n    return s;\n}\n\nstruct State {\n    vector<unsigned char> b;\n    int emp;\n    string p;\n    char last;\n    int sc;\n};\n\nstruct Res {\n    vector<unsigned char> b;\n    int emp;\n    string ans;\n    int score;\n};\n\nint hscore(const Ev& e,int emp,int plen,int d,int mode){\n    int sc=e.lt*1000000;\n\n    if(mode==0){\n        sc += e.lc*18000 + e.e*4500 - e.cy*45000\n            - e.co*1800 - e.iso*1200 + e.tc*1200;\n    }else if(mode==1){\n        sc += e.lc*26000 + e.e*3000 - e.cy*70000\n            - e.co*1200 - e.iso*800 + e.tc*2500;\n    }else{\n        sc += e.lc*10000 + e.e*8000 - e.cy*25000\n            - e.co*2500 - e.iso*1800 + e.tc*800;\n    }\n\n    if(e.lt==M-1){\n        sc += 500000000;\n        sc -= (plen+d)*8000;\n    }else{\n        sc -= d*20;\n    }\n\n    int r=emp/N,c=emp%N;\n    int distBR=abs(r-(N-1))+abs(c-(N-1));\n    sc -= distBR*100;\n\n    return sc;\n}\n\ntemplate<class T, class Comp>\nvoid keep_top(vector<T>& v,int keep,Comp comp){\n    if((int)v.size()<=keep){\n        sort(v.begin(),v.end(),comp);\n        return;\n    }\n    nth_element(v.begin(),v.begin()+keep,v.end(),comp);\n    v.resize(keep);\n    sort(v.begin(),v.end(),comp);\n}\n\nRes beam(\n    const vector<unsigned char>& sb,\n    int se,\n    const string& pref,\n    double endt,\n    const Timer& tim,\n    int mode,\n    int bwscale\n){\n    Ev sev=evalb(sb);\n    Res best{sb,se,pref,offscore_ev(sev,(int)pref.size())};\n\n    State st;\n    st.b=sb;\n    st.emp=se;\n    st.p=\"\";\n    st.last='?';\n    st.sc=hscore(sev,se,(int)pref.size(),0,mode);\n\n    vector<State> beam;\n    beam.push_back(st);\n\n    int base;\n    if(N==6) base=1500;\n    else if(N==7) base=1050;\n    else if(N==8) base=700;\n    else if(N==9) base=450;\n    else base=310;\n\n    int BW=max(70,base*bwscale/100);\n    if(!pref.empty()) BW=max(60,BW*2/3);\n\n    const char mv[4]={'U','D','L','R'};\n    const int dr[4]={-1,1,0,0};\n    const int dc[4]={0,0,-1,1};\n\n    int maxD=Tlim-(int)pref.size();\n\n    for(int dep=0; dep<maxD; dep++){\n        if(tim.elapsed()>endt) break;\n\n        vector<State> cand;\n        cand.reserve(beam.size()*3);\n\n        for(const auto& s:beam){\n            int r=s.emp/N,c=s.emp%N;\n\n            for(int k=0;k<4;k++){\n                char m=mv[k];\n\n                if(s.last!='?' && opp(s.last)==m) continue;\n\n                int nr=r+dr[k],nc=c+dc[k];\n                if(nr<0 || nr>=N || nc<0 || nc>=N) continue;\n\n                int np=nr*N+nc;\n\n                State ns;\n                ns.b=s.b;\n                swap(ns.b[s.emp],ns.b[np]);\n                ns.emp=np;\n                ns.p=s.p;\n                ns.p.push_back(m);\n                ns.last=m;\n\n                Ev e=evalb(ns.b);\n                ns.sc=hscore(e,ns.emp,(int)pref.size(),(int)ns.p.size(),mode);\n\n                int os=offscore_ev(e,(int)pref.size()+(int)ns.p.size());\n                if(os>best.score){\n                    best.score=os;\n                    best.b=ns.b;\n                    best.emp=ns.emp;\n                    best.ans=pref+ns.p;\n                }\n\n                cand.push_back(ns);\n            }\n        }\n\n        if(cand.empty()) break;\n\n        int keep=min(BW,(int)cand.size());\n\n        keep_top(cand,keep,[](const State& a,const State& b){\n            return a.sc>b.sc;\n        });\n\n        unordered_set<string> seen;\n        seen.reserve(keep*3);\n\n        vector<State> nb;\n        nb.reserve(keep);\n\n        for(const auto& s:cand){\n            string k=keyb(s.b,s.emp);\n            if(seen.insert(k).second){\n                nb.push_back(s);\n                if((int)nb.size()>=keep) break;\n            }\n        }\n\n        beam.swap(nb);\n    }\n\n    return best;\n}\n\nstring random_walk(vector<unsigned char>& b,int& e,int len){\n    string p;\n    char last='?';\n    const char mv[4]={'U','D','L','R'};\n\n    for(int i=0;i<len;i++){\n        vector<char> legal;\n        int r=e/N,c=e%N;\n\n        for(char m:mv){\n            if(last!='?' && opp(last)==m) continue;\n\n            int nr=r,nc=c;\n            if(m=='U') nr--;\n            if(m=='D') nr++;\n            if(m=='L') nc--;\n            if(m=='R') nc++;\n\n            if(0<=nr && nr<N && 0<=nc && nc<N){\n                legal.push_back(m);\n            }\n        }\n\n        if(legal.empty()) break;\n\n        char m=legal[uniform_int_distribution<int>(0,(int)legal.size()-1)(rng)];\n        apply(b,e,m);\n        p.push_back(m);\n        last=m;\n    }\n\n    return p;\n}\n\nstring greedy_walk(vector<unsigned char>& b,int& e,int len,int mode){\n    string p;\n    char last='?';\n    const char mv[4]={'U','D','L','R'};\n\n    for(int step=0; step<len; step++){\n        vector<pair<int,char>> cand;\n        int r=e/N,c=e%N;\n\n        for(char m:mv){\n            if(last!='?' && opp(last)==m) continue;\n\n            int nr=r,nc=c;\n            if(m=='U') nr--;\n            if(m=='D') nr++;\n            if(m=='L') nc--;\n            if(m=='R') nc++;\n\n            if(nr<0 || nr>=N || nc<0 || nc>=N) continue;\n\n            vector<unsigned char> nb=b;\n            int ne=e;\n            apply(nb,ne,m);\n\n            Ev ev=evalb(nb);\n            int sc=hscore(ev,ne,0,step+1,mode);\n            sc += uniform_int_distribution<int>(0,8000)(rng);\n\n            cand.push_back({sc,m});\n        }\n\n        if(cand.empty()) break;\n\n        sort(cand.begin(),cand.end(),greater<pair<int,char>>());\n\n        int pick=0;\n        int roll=uniform_int_distribution<int>(0,99)(rng);\n        if((int)cand.size()>=3 && roll<12) pick=2;\n        else if((int)cand.size()>=2 && roll<35) pick=1;\n\n        char m=cand[pick].second;\n        apply(b,e,m);\n        p.push_back(m);\n        last=m;\n    }\n\n    return p;\n}\n\nstring sanitize(const string& ans,int emp0){\n    vector<unsigned char> b=initb;\n    int e=emp0;\n    string res;\n    res.reserve(min((int)ans.size(),Tlim));\n\n    for(char c:ans){\n        if((int)res.size()>=Tlim) break;\n        if(c!='U' && c!='D' && c!='L' && c!='R') break;\n        if(!apply(b,e,c)) break;\n        res.push_back(c);\n    }\n\n    return res;\n}\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    M=N*N;\n    initb.assign(M,0);\n\n    int emp=0;\n    for(int i=0;i<N;i++){\n        string s;\n        cin >> s;\n        for(int j=0;j<N;j++){\n            initb[i*N+j]=hv(s[j]);\n            if(initb[i*N+j]==0) emp=i*N+j;\n        }\n    }\n\n    Timer tim;\n\n    Ev iev=evalb(initb);\n    Res gb{initb,emp,\"\",offscore_ev(iev,0)};\n\n    // Main search from original board.\n    {\n        Res r=beam(initb,emp,\"\",1.72,tim,0,120);\n        if(r.score>gb.score) gb=r;\n    }\n\n    int rest;\n    if(N<=6) rest=9;\n    else if(N==7) rest=7;\n    else if(N==8) rest=5;\n    else rest=4;\n\n    vector<int> lens = {N, 2*N, 3*N, 4*N};\n\n    // Random restarts.\n    for(int i=0;i<rest;i++){\n        if(tim.elapsed()>2.60) break;\n\n        vector<unsigned char> b=initb;\n        int e=emp;\n\n        int len=lens[i%(int)lens.size()];\n        string pref=random_walk(b,e,len);\n\n        int mode=i%3;\n        Res r=beam(b,e,pref,2.70,tim,mode,88);\n\n        if(r.score>gb.score){\n            gb=r;\n        }\n    }\n\n    // Short stochastic greedy-prefix restarts.\n    vector<int> glens = {max(1,N/2), N, 2*N};\n\n    int grest;\n    if(N<=7) grest=4;\n    else grest=3;\n\n    for(int i=0;i<grest;i++){\n        if(tim.elapsed()>2.80) break;\n\n        vector<unsigned char> b=initb;\n        int e=emp;\n\n        int len=glens[i%(int)glens.size()];\n        int mode=i%3;\n\n        string pref=greedy_walk(b,e,len,mode);\n\n        Res r=beam(b,e,pref,2.88,tim,mode,78);\n\n        if(r.score>gb.score){\n            gb=r;\n        }\n    }\n\n    string ans=sanitize(gb.ans,emp);\n    cout << ans << \"\\n\";\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Line {\n    long long px, py, qx, qy;\n};\n\nstruct CutSet {\n    vector<int> cuts;\n    vector<unsigned short> bin;\n};\n\nstruct AxisCand {\n    int score;\n    vector<int> cx, cy;\n};\n\nstatic const long long LIM = 1000000000LL;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\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    int N, K;\n    cin >> N >> K;\n\n    vector<int> a(11);\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n\n    vector<Point> pts(N);\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) {\n        cin >> pts[i].x >> pts[i].y;\n        xs[i] = pts[i].x;\n        ys[i] = pts[i].y;\n    }\n\n    sort(xs.begin(), xs.end());\n    sort(ys.begin(), ys.end());\n\n    auto score_from_cells = [&](const vector<unsigned short>& cell) {\n        int b[11] = {};\n        for (unsigned short v : cell) {\n            if (1 <= v && v <= 10) b[v]++;\n        }\n        int score = 0;\n        for (int d = 1; d <= 10; d++) score += min(a[d], b[d]);\n        return score;\n    };\n\n    auto make_cuts = [&](const vector<int>& sorted_coord, int c, double off) {\n        vector<int> cuts;\n        cuts.reserve(c);\n\n        for (int i = 1; i <= c; i++) {\n            double pos = (i + off) / (c + 1.0);\n            if (pos <= 0.0 || pos >= 1.0) continue;\n\n            int idx = (int)(pos * N);\n            idx = max(1, min(N - 1, idx));\n\n            int v1 = sorted_coord[idx - 1];\n            int v2 = sorted_coord[idx];\n\n            int cut = (v1 == v2 ? v1 + 1 : (v1 + v2) / 2);\n            if (cuts.empty() || cuts.back() != cut) cuts.push_back(cut);\n        }\n        return cuts;\n    };\n\n    auto build_bin = [&](const vector<int>& cuts, bool isX) {\n        vector<unsigned short> bin(N);\n        for (int i = 0; i < N; i++) {\n            int v = isX ? pts[i].x : pts[i].y;\n            bin[i] = upper_bound(cuts.begin(), cuts.end(), v) - cuts.begin();\n        }\n        return bin;\n    };\n\n    auto make_cutset = [&](const vector<int>& sorted_coord, int c, double off, bool isX) {\n        CutSet cs;\n        cs.cuts = make_cuts(sorted_coord, c, off);\n        cs.bin = build_bin(cs.cuts, isX);\n        return cs;\n    };\n\n    auto eval_axis_pair_bins = [&](const vector<unsigned short>& xb, int cx,\n                                   const vector<unsigned short>& yb, int cy) {\n        int W = cy + 1;\n        vector<unsigned short> cell((cx + 1) * W, 0);\n        for (int i = 0; i < N; i++) {\n            cell[xb[i] * W + yb[i]]++;\n        }\n        return score_from_cells(cell);\n    };\n\n    int attendees = 0;\n    for (int d = 1; d <= 10; d++) attendees += a[d];\n\n    vector<pair<int,int>> shapes;\n    for (int vx = 15; vx <= 85; vx++) shapes.push_back({vx, 100 - vx});\n\n    for (int total : {40, 45, 50, 60, 70, 80, 90, 96, 100}) {\n        int mid = total / 2;\n        for (int vx = mid - 26; vx <= mid + 26; vx += 2) {\n            int hy = total - vx;\n            if (vx >= 1 && hy >= 1) shapes.push_back({vx, hy});\n        }\n    }\n\n    int estV = 50, estH = 50;\n    double bestCost = 1e100;\n    for (int vx = 0; vx <= K; vx++) {\n        for (int hy = 0; hy + vx <= K; hy++) {\n            int cells = (vx + 1) * (hy + 1);\n            double cost = abs(cells - attendees) + 0.05 * abs(vx - hy);\n            if (cost < bestCost) {\n                bestCost = cost;\n                estV = vx;\n                estH = hy;\n            }\n        }\n    }\n\n    for (int dv = -28; dv <= 28; dv++) {\n        int vx = estV + dv;\n        int hy = estH - dv;\n        if (vx >= 1 && hy >= 1 && vx + hy <= K) shapes.push_back({vx, hy});\n    }\n\n    sort(shapes.begin(), shapes.end());\n    shapes.erase(unique(shapes.begin(), shapes.end()), shapes.end());\n\n    vector<double> offs = {0.0, -0.45, -0.35, -0.25, -0.1, 0.1, 0.25, 0.35, 0.45};\n\n    set<pair<int,int>> xParams, yParams;\n    for (auto [vx, hy] : shapes) {\n        for (int oi = 0; oi < (int)offs.size(); oi++) {\n            xParams.insert({vx, oi});\n            yParams.insert({hy, oi});\n        }\n    }\n\n    vector<CutSet> xsets, ysets;\n    xsets.reserve(xParams.size());\n    ysets.reserve(yParams.size());\n\n    for (auto [c, oi] : xParams) xsets.push_back(make_cutset(xs, c, offs[oi], true));\n    for (auto [c, oi] : yParams) ysets.push_back(make_cutset(ys, c, offs[oi], false));\n\n    auto eval_axis_pair = [&](const CutSet& X, const CutSet& Y) {\n        return eval_axis_pair_bins(X.bin, (int)X.cuts.size(), Y.bin, (int)Y.cuts.size());\n    };\n\n    vector<AxisCand> topAxis;\n\n    auto similar_shape_exists = [&](const AxisCand& cand) {\n        int cx = cand.cx.size();\n        int cy = cand.cy.size();\n        for (const auto &e : topAxis) {\n            int ex = e.cx.size();\n            int ey = e.cy.size();\n            if (abs(cx - ex) <= 2 && abs(cy - ey) <= 2 && cand.score <= e.score + 5) {\n                return true;\n            }\n        }\n        return false;\n    };\n\n    auto push_axis = [&](AxisCand cand) {\n        for (const auto &e : topAxis) {\n            if (e.cx == cand.cx && e.cy == cand.cy) return;\n        }\n\n        // Keep both high-score and shape-diverse starts.\n        if ((int)topAxis.size() >= 14 && similar_shape_exists(cand)) {\n            if (cand.score < topAxis.back().score + 10) return;\n        }\n\n        topAxis.push_back(move(cand));\n        sort(topAxis.begin(), topAxis.end(), [](const AxisCand& l, const AxisCand& r) {\n            return l.score > r.score;\n        });\n\n        if ((int)topAxis.size() > 16) {\n            // Remove the lowest-scoring candidate, preferring to remove one\n            // from an overrepresented shape neighborhood.\n            int rem = (int)topAxis.size() - 1;\n            for (int i = (int)topAxis.size() - 1; i >= 0; i--) {\n                int closeCnt = 0;\n                for (int j = 0; j < (int)topAxis.size(); j++) if (i != j) {\n                    if (abs((int)topAxis[i].cx.size() - (int)topAxis[j].cx.size()) <= 2 &&\n                        abs((int)topAxis[i].cy.size() - (int)topAxis[j].cy.size()) <= 2) {\n                        closeCnt++;\n                    }\n                }\n                if (closeCnt >= 2) {\n                    rem = i;\n                    break;\n                }\n            }\n            topAxis.erase(topAxis.begin() + rem);\n            sort(topAxis.begin(), topAxis.end(), [](const AxisCand& l, const AxisCand& r) {\n                return l.score > r.score;\n            });\n        }\n    };\n\n    for (const auto &X : xsets) {\n        int cx = (int)X.cuts.size();\n        for (const auto &Y : ysets) {\n            int cy = (int)Y.cuts.size();\n            if (cx + cy > K) continue;\n            if (abs(cx - cy) > 70) continue;\n\n            int sc = eval_axis_pair(X, Y);\n            push_axis({sc, X.cuts, Y.cuts});\n        }\n    }\n\n    auto candidate_value = [&](const vector<int>& sorted_coord, int rank) {\n        rank = max(1, min(N - 1, rank));\n        int v1 = sorted_coord[rank - 1];\n        int v2 = sorted_coord[rank];\n        return (v1 == v2 ? v1 + 1 : (v1 + v2) / 2);\n    };\n\n    auto local_search_axis = [&](AxisCand init, double timeLimit, int maxPass, bool fineOnly) {\n        vector<int> cx = init.cx, cy = init.cy;\n        vector<unsigned short> xb = build_bin(cx, true);\n        vector<unsigned short> yb = build_bin(cy, false);\n        int cur = eval_axis_pair_bins(xb, (int)cx.size(), yb, (int)cy.size());\n\n        auto try_one_cut = [&](bool doX, int idx, const vector<int>& steps) {\n            vector<int>& cuts = doX ? cx : cy;\n            const vector<int>& sortedCoord = doX ? xs : ys;\n            int C = cuts.size();\n\n            int old = cuts[idx];\n            int approxRank = lower_bound(sortedCoord.begin(), sortedCoord.end(), old) - sortedCoord.begin();\n\n            int bestLocal = cur;\n            int bestVal = old;\n\n            for (int st : steps) {\n                for (int sgn : {-1, 1}) {\n                    int val = candidate_value(sortedCoord, approxRank + sgn * st);\n                    if ((idx > 0 && val <= cuts[idx - 1]) ||\n                        (idx + 1 < C && val >= cuts[idx + 1])) continue;\n                    if (val == old) continue;\n\n                    cuts[idx] = val;\n                    int sc;\n                    if (doX) {\n                        auto nxb = build_bin(cx, true);\n                        sc = eval_axis_pair_bins(nxb, (int)cx.size(), yb, (int)cy.size());\n                    } else {\n                        auto nyb = build_bin(cy, false);\n                        sc = eval_axis_pair_bins(xb, (int)cx.size(), nyb, (int)cy.size());\n                    }\n\n                    if (sc > bestLocal) {\n                        bestLocal = sc;\n                        bestVal = val;\n                    }\n                }\n            }\n\n            cuts[idx] = old;\n            if (bestLocal > cur) {\n                cuts[idx] = bestVal;\n                if (doX) xb = build_bin(cx, true);\n                else yb = build_bin(cy, false);\n                cur = bestLocal;\n                return true;\n            }\n            return false;\n        };\n\n        for (int pass = 0; pass < maxPass; pass++) {\n            if (elapsed() > timeLimit) break;\n            bool improvedPass = false;\n\n            int Cx = cx.size(), Cy = cy.size();\n            int ux = max(1, N / (Cx + 1) / 10);\n            int uy = max(1, N / (Cy + 1) / 10);\n\n            vector<int> coarseX = {ux, 2 * ux, 4 * ux, 8 * ux, 12 * ux};\n            vector<int> coarseY = {uy, 2 * uy, 4 * uy, 8 * uy, 12 * uy};\n            vector<int> mediumX = {max(1, ux / 2), ux, 2 * ux, 3 * ux, 5 * ux};\n            vector<int> mediumY = {max(1, uy / 2), uy, 2 * uy, 3 * uy, 5 * uy};\n            vector<int> fine = {1, 2, 3, 5, 8, 13, 21};\n\n            bool xFirst = (pass % 2 == 0);\n\n            for (int phase = 0; phase < 2; phase++) {\n                bool doX = (phase == 0 ? xFirst : !xFirst);\n                int C = doX ? Cx : Cy;\n\n                vector<int> steps;\n                if (fineOnly) steps = fine;\n                else if (pass < 2) steps = doX ? coarseX : coarseY;\n                else if (pass < 4) steps = doX ? mediumX : mediumY;\n                else steps = fine;\n\n                vector<int> order(C);\n                iota(order.begin(), order.end(), 0);\n                int shift = (pass * 17 + (doX ? 5 : 11)) % max(1, C);\n                rotate(order.begin(), order.begin() + shift, order.end());\n\n                for (int idx : order) {\n                    if (elapsed() > timeLimit) break;\n                    if (try_one_cut(doX, idx, steps)) improvedPass = true;\n                }\n            }\n\n            if (!improvedPass && (fineOnly || pass >= 4)) break;\n        }\n\n        return AxisCand{cur, cx, cy};\n    };\n\n    AxisCand bestAxis = topAxis[0];\n\n    // Refine diverse starts. Allocate most time to local search.\n    for (int i = 0; i < (int)topAxis.size(); i++) {\n        if (elapsed() > 2.62) break;\n\n        double limit;\n        int passes;\n\n        if (i == 0) {\n            limit = 1.65;\n            passes = 7;\n        } else if (i <= 4) {\n            limit = 2.25;\n            passes = 5;\n        } else if (i <= 9) {\n            limit = 2.50;\n            passes = 3;\n        } else {\n            limit = 2.62;\n            passes = 2;\n        }\n\n        AxisCand loc = local_search_axis(topAxis[i], limit, passes, false);\n        if (loc.score > bestAxis.score) bestAxis = loc;\n    }\n\n    // Final fine polish if time remains.\n    if (elapsed() < 2.80) {\n        AxisCand polished = local_search_axis(bestAxis, 2.80, 3, true);\n        if (polished.score > bestAxis.score) bestAxis = polished;\n    }\n\n    vector<Line> bestLines;\n    for (int x : bestAxis.cx) bestLines.push_back({x, -LIM, x, LIM});\n    for (int y : bestAxis.cy) bestLines.push_back({-LIM, y, LIM, y});\n\n    if ((int)bestLines.size() > K) bestLines.resize(K);\n\n    cout << bestLines.size() << '\\n';\n    for (auto &ln : bestLines) {\n        cout << ln.px << ' ' << ln.py << ' ' << ln.qx << ' ' << ln.qy << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Move {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n    int score;\n    int lenSum;\n};\n\nint N, M;\nvector<vector<unsigned char>> dotGrid;\nvector<vector<array<unsigned char, 4>>> usedSeg;\nvector<Move> answerMoves;\nvector<vector<int>> W;\n\nint maxLenDir[65][65][8];\nint dirX[8] = {1, 0, -1, 0, 1, -1, -1, 1};\nint dirY[8] = {0, 1, 0, -1, 1, 1, -1, -1};\nint perpDir[8][2];\n\nchrono::steady_clock::time_point startTime;\n\ninline double elapsedTime() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\ninline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y < N;\n}\n\ninline int sgn(int v) {\n    return (v > 0) - (v < 0);\n}\n\n// dir:\n// 0 : horizontal segment from (x,y) to (x+1,y)\n// 1 : vertical   segment from (x,y) to (x,y+1)\n// 2 : diag up    segment from (x,y) to (x+1,y+1)\n// 3 : diag down  segment from (x,y) to (x+1,y-1)\ninline bool getSegUsed(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n\n    if (dy == 0) {\n        if (dx == 1) return usedSeg[x1][y1][0];\n        else return usedSeg[x2][y2][0];\n    }\n\n    if (dx == 0) {\n        if (dy == 1) return usedSeg[x1][y1][1];\n        else return usedSeg[x2][y2][1];\n    }\n\n    if (dx == dy) {\n        if (dx == 1) return usedSeg[x1][y1][2];\n        else return usedSeg[x2][y2][2];\n    }\n\n    if (dx == 1) return usedSeg[x1][y1][3];\n    else return usedSeg[x2][y2][3];\n}\n\ninline void setSegUsed(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n\n    if (dy == 0) {\n        if (dx == 1) usedSeg[x1][y1][0] = 1;\n        else usedSeg[x2][y2][0] = 1;\n        return;\n    }\n\n    if (dx == 0) {\n        if (dy == 1) usedSeg[x1][y1][1] = 1;\n        else usedSeg[x2][y2][1] = 1;\n        return;\n    }\n\n    if (dx == dy) {\n        if (dx == 1) usedSeg[x1][y1][2] = 1;\n        else usedSeg[x2][y2][2] = 1;\n        return;\n    }\n\n    if (dx == 1) usedSeg[x1][y1][3] = 1;\n    else usedSeg[x2][y2][3] = 1;\n}\n\nbool checkSideNoDotAndNoSeg(int ax, int ay, int bx, int by,\n                            int ex1, int ey1,\n                            int ex2, int ey2,\n                            int ex3, int ey3) {\n    int dx = bx - ax;\n    int dy = by - ay;\n\n    int sx = sgn(dx);\n    int sy = sgn(dy);\n    int g = max(abs(dx), abs(dy));\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n\n        if (getSegUsed(x, y, nx, ny)) return false;\n    }\n\n    for (int i = 1; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n\n        if ((x == ex1 && y == ey1) ||\n            (x == ex2 && y == ey2) ||\n            (x == ex3 && y == ey3)) {\n            continue;\n        }\n\n        if (dotGrid[x][y]) return false;\n    }\n\n    return true;\n}\n\nvoid addSideSegments(int ax, int ay, int bx, int by) {\n    int dx = bx - ax;\n    int dy = by - ay;\n\n    int sx = sgn(dx);\n    int sy = sgn(dy);\n    int g = max(abs(dx), abs(dy));\n\n    for (int i = 0; i < g; i++) {\n        int x = ax + sx * i;\n        int y = ay + sy * i;\n        int nx = x + sx;\n        int ny = y + sy;\n        setSegUsed(x, y, nx, ny);\n    }\n}\n\nbool legalMove(const Move& mv) {\n    int x1 = mv.x1, y1 = mv.y1;\n    int x2 = mv.x2, y2 = mv.y2;\n    int x3 = mv.x3, y3 = mv.y3;\n    int x4 = mv.x4, y4 = mv.y4;\n\n    if (dotGrid[x1][y1]) return false;\n    if (!dotGrid[x2][y2] || !dotGrid[x3][y3] || !dotGrid[x4][y4]) return false;\n\n    if (!checkSideNoDotAndNoSeg(x1, y1, x2, y2, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x2, y2, x3, y3, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x3, y3, x4, y4, x2, y2, x3, y3, x4, y4)) return false;\n    if (!checkSideNoDotAndNoSeg(x4, y4, x1, y1, x2, y2, x3, y3, x4, y4)) return false;\n\n    return true;\n}\n\nvoid applyMove(const Move& mv) {\n    dotGrid[mv.x1][mv.y1] = 1;\n\n    addSideSegments(mv.x1, mv.y1, mv.x2, mv.y2);\n    addSideSegments(mv.x2, mv.y2, mv.x3, mv.y3);\n    addSideSegments(mv.x3, mv.y3, mv.x4, mv.y4);\n    addSideSegments(mv.x4, mv.y4, mv.x1, mv.y1);\n\n    answerMoves.push_back(mv);\n}\n\ninline long long moveValueRaw(int x1, int y1, int lenSum) {\n    return 10000LL * W[x1][y1] - 120LL * lenSum;\n}\n\nbool findBestMove(Move& best) {\n    bool found = false;\n    long long bestVal = LLONG_MIN;\n\n    vector<pair<int,int>> dots;\n    dots.reserve(N * N);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            if (dotGrid[x][y]) dots.push_back({x, y});\n        }\n    }\n\n    for (auto [x3, y3] : dots) {\n        if (elapsedTime() > 4.88) return found;\n\n        for (int di = 0; di < 8; di++) {\n            int dx = dirX[di];\n            int dy = dirY[di];\n\n            for (int si = 0; si < 2; si++) {\n                int bdi = perpDir[di][si];\n                int bx = dirX[bdi];\n                int by = dirY[bdi];\n\n                int max1 = maxLenDir[x3][y3][di];\n                int max2 = maxLenDir[x3][y3][bdi];\n\n                for (int l1 = 1; l1 <= max1; l1++) {\n                    int x2 = x3 + dx * l1;\n                    int y2 = y3 + dy * l1;\n                    if (!dotGrid[x2][y2]) continue;\n\n                    for (int l2 = 1; l2 <= max2; l2++) {\n                        int x4 = x3 + bx * l2;\n                        int y4 = y3 + by * l2;\n                        if (!dotGrid[x4][y4]) continue;\n\n                        int x1 = x2 + bx * l2;\n                        int y1 = y2 + by * l2;\n\n                        if (!inside(x1, y1)) continue;\n                        if (dotGrid[x1][y1]) continue;\n\n                        int lenSum = l1 + l2;\n                        long long val = moveValueRaw(x1, y1, lenSum);\n\n                        if (found && val < bestVal) continue;\n\n                        Move mv;\n                        mv.x1 = x1; mv.y1 = y1;\n                        mv.x2 = x2; mv.y2 = y2;\n                        mv.x3 = x3; mv.y3 = y3;\n                        mv.x4 = x4; mv.y4 = y4;\n                        mv.score = W[x1][y1];\n                        mv.lenSum = lenSum;\n\n                        if (!legalMove(mv)) continue;\n\n                        if (!found ||\n                            val > bestVal ||\n                            (val == bestVal && mv.lenSum < best.lenSum)) {\n                            found = true;\n                            bestVal = val;\n                            best = mv;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    return found;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    dotGrid.assign(N, vector<unsigned char>(N, 0));\n    usedSeg.assign(N, vector<array<unsigned char, 4>>(N));\n    W.assign(N, vector<int>(N, 0));\n\n    int c = (N - 1) / 2;\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            int dx = x - c;\n            int dy = y - c;\n            W[x][y] = dx * dx + dy * dy + 1;\n        }\n    }\n\n    for (int d = 0; d < 8; d++) {\n        int rdx = -dirY[d];\n        int rdy = dirX[d];\n\n        for (int si = 0; si < 2; si++) {\n            int bx = rdx * (si == 0 ? -1 : 1);\n            int by = rdy * (si == 0 ? -1 : 1);\n\n            for (int t = 0; t < 8; t++) {\n                if (dirX[t] == bx && dirY[t] == by) {\n                    perpDir[d][si] = t;\n                    break;\n                }\n            }\n        }\n    }\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y < N; y++) {\n            for (int d = 0; d < 8; d++) {\n                int dx = dirX[d];\n                int dy = dirY[d];\n                int len = 0;\n                int nx = x + dx;\n                int ny = y + dy;\n                while (inside(nx, ny)) {\n                    len++;\n                    nx += dx;\n                    ny += dy;\n                }\n                maxLenDir[x][y][d] = len;\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        dotGrid[x][y] = 1;\n    }\n\n    startTime = chrono::steady_clock::now();\n\n    while (true) {\n        if (elapsedTime() > 4.88) break;\n\n        Move best;\n        if (!findBestMove(best)) break;\n        applyMove(best);\n    }\n\n    cout << answerMoves.size() << '\\n';\n    for (auto &mv : answerMoves) {\n        cout << mv.x1 << ' ' << mv.y1 << ' '\n             << mv.x2 << ' ' << mv.y2 << ' '\n             << mv.x3 << ' ' << mv.y3 << ' '\n             << mv.x4 << ' ' << mv.y4 << '\\n';\n    }\n\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int T = 100;\n\nint f[T];\nint cntFlavor[4];\nint targetColor[100];\nint rank_of_flavor[4];\n\nconst char DIR_CH[4] = {'F', 'B', 'L', 'R'};\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    inline uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n};\n\nRNG global_rng(246813579);\n\nstruct Board {\n    unsigned char a[100];\n};\n\ninline void clear_board(Board& b) {\n    memset(b.a, 0, sizeof(b.a));\n}\n\nvoid tilt_board(const Board& src, Board& dst, int dir) {\n    memset(dst.a, 0, sizeof(dst.a));\n\n    if (dir == 0) { // F\n        for (int c = 0; c < N; c++) {\n            int w = 0;\n            for (int r = 0; r < N; r++) {\n                int v = src.a[r * 10 + c];\n                if (v) dst.a[w++ * 10 + c] = (unsigned char)v;\n            }\n        }\n    } else if (dir == 1) { // B\n        for (int c = 0; c < N; c++) {\n            int w = N - 1;\n            for (int r = N - 1; r >= 0; r--) {\n                int v = src.a[r * 10 + c];\n                if (v) dst.a[w-- * 10 + c] = (unsigned char)v;\n            }\n        }\n    } else if (dir == 2) { // L\n        for (int r = 0; r < N; r++) {\n            int w = 0;\n            int base = r * 10;\n            for (int c = 0; c < N; c++) {\n                int v = src.a[base + c];\n                if (v) dst.a[base + w++] = (unsigned char)v;\n            }\n        }\n    } else { // R\n        for (int r = 0; r < N; r++) {\n            int w = N - 1;\n            int base = r * 10;\n            for (int c = N - 1; c >= 0; c--) {\n                int v = src.a[base + c];\n                if (v) dst.a[base + w--] = (unsigned char)v;\n            }\n        }\n    }\n}\n\nvoid place_by_index(Board& b, int p, int flavor) {\n    int cnt = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b.a[i] == 0) {\n            cnt++;\n            if (cnt == p) {\n                b.a[i] = (unsigned char)flavor;\n                return;\n            }\n        }\n    }\n}\n\ninline int empty_count(const Board& b) {\n    int e = 0;\n    for (int i = 0; i < 100; i++) if (b.a[i] == 0) e++;\n    return e;\n}\n\nvoid place_random(Board& b, int flavor, RNG& rng) {\n    int e = empty_count(b);\n    int p = rng.next_int(1, e);\n    place_by_index(b, p, flavor);\n}\n\nint component_score(const Board& b) {\n    bool vis[100] = {};\n    int q[100];\n    int score = 0;\n\n    for (int s = 0; s < 100; s++) {\n        if (b.a[s] == 0 || vis[s]) continue;\n\n        int col = b.a[s];\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = true;\n        int sz = 0;\n\n        while (head < tail) {\n            int v = q[head++];\n            sz++;\n\n            int r = v / 10;\n            int c = v % 10;\n\n            if (r > 0) {\n                int nv = v - 10;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (r < 9) {\n                int nv = v + 10;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (c > 0) {\n                int nv = v - 1;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n            if (c < 9) {\n                int nv = v + 1;\n                if (!vis[nv] && b.a[nv] == col) {\n                    vis[nv] = true;\n                    q[tail++] = nv;\n                }\n            }\n        }\n\n        score += sz * sz;\n    }\n\n    return score;\n}\n\ninline int edge_score(const Board& b) {\n    int s = 0;\n\n    for (int r = 0; r < N; r++) {\n        int base = r * 10;\n        for (int c = 0; c < N; c++) {\n            int idx = base + c;\n            int x = b.a[idx];\n            if (!x) continue;\n            if (r + 1 < N && b.a[idx + 10] == x) s++;\n            if (c + 1 < N && b.a[idx + 1] == x) s++;\n        }\n    }\n\n    return s;\n}\n\ninline int target_match_score(const Board& b) {\n    int s = 0;\n    for (int i = 0; i < 100; i++) {\n        if (b.a[i] && b.a[i] == targetColor[i]) s++;\n    }\n    return s;\n}\n\ndouble target_neighbor_score(const Board& b) {\n    double s = 0.0;\n\n    for (int i = 0; i < 100; i++) {\n        int x = b.a[i];\n        if (!x) continue;\n\n        int r = i / 10;\n        int c = i % 10;\n\n        for (int j = 0; j < 100; j++) {\n            if (targetColor[j] != x) continue;\n            int rr = j / 10;\n            int cc = j % 10;\n            int d = abs(r - rr) + abs(c - cc);\n            if (d <= 3) s += 4 - d;\n        }\n    }\n\n    return s;\n}\n\ndouble eval_target(const Board& b, int turn) {\n    double progress = turn * 0.01;\n\n    int comp = component_score(b);\n    int edge = edge_score(b);\n    int match = target_match_score(b);\n    double nearTarget = target_neighbor_score(b);\n\n    return comp * (10.0 + 38.0 * progress)\n         + edge * 18.0\n         + match * (90.0 * (1.0 - 0.3 * progress))\n         + nearTarget * (7.0 * (1.0 - 0.5 * progress));\n}\n\ndouble region_score(const Board& b) {\n    double s = 0.0;\n\n    for (int idx = 0; idx < 100; idx++) {\n        int x = b.a[idx];\n        if (!x) continue;\n\n        int r = idx / 10;\n        int c = idx % 10;\n        int rk = rank_of_flavor[x];\n\n        int tr, tc;\n        if (rk == 0) {\n            tr = 1; tc = 1;\n        } else if (rk == 1) {\n            tr = 8; tc = 8;\n        } else {\n            tr = 1; tc = 8;\n        }\n\n        int d = abs(r - tr) + abs(c - tc);\n        s += 18 - d;\n\n        if (rk == 0) s += (N - r) * 0.25 + (N - c) * 0.15;\n        else if (rk == 1) s += r * 0.25 + c * 0.15;\n        else s += (N - r) * 0.25 + c * 0.15;\n    }\n\n    return s;\n}\n\ndouble eval_region(const Board& b, int turn) {\n    double progress = turn * 0.01;\n\n    int comp = component_score(b);\n    int edge = edge_score(b);\n    double reg = region_score(b);\n\n    return comp * (12.0 + 35.0 * progress)\n         + edge * 20.0\n         + reg * (2.0 * (1.0 - progress) + 0.2);\n}\n\ndouble eval_component(const Board& b, int turn) {\n    double progress = turn * 0.01;\n    int comp = component_score(b);\n    int edge = edge_score(b);\n\n    return comp * (22.0 + 45.0 * progress)\n         + edge * (28.0 + 10.0 * progress);\n}\n\ndouble eval_mixed(const Board& b, int turn) {\n    double progress = turn * 0.01;\n\n    double wt = 0.55 - 0.15 * progress;\n    double wr = 0.30;\n    double wc = 0.15 + 0.15 * progress;\n\n    return eval_target(b, turn) * wt\n         + eval_region(b, turn) * wr\n         + eval_component(b, turn) * wc;\n}\n\nint greedy_dir_policy(const Board& b, int turn, int policy) {\n    int best = 0;\n    double bestVal = -1e100;\n\n    for (int d = 0; d < 4; d++) {\n        Board nb;\n        tilt_board(b, nb, d);\n\n        double val;\n        if (policy == 0) val = eval_target(nb, turn);\n        else if (policy == 1) val = eval_region(nb, turn);\n        else if (policy == 2) val = eval_component(nb, turn);\n        else val = eval_mixed(nb, turn);\n\n        if (d == 0) val += 0.003;\n        if (d == 2) val += 0.002;\n\n        if (val > bestVal) {\n            bestVal = val;\n            best = d;\n        }\n    }\n\n    return best;\n}\n\ndouble rollout_limited(Board b, int nextTurn, int horizon, RNG rng, int policy) {\n    int endTurn = min(T, nextTurn + horizon - 1);\n\n    for (int turn = nextTurn; turn <= endTurn; turn++) {\n        place_random(b, f[turn - 1], rng);\n\n        int gd = greedy_dir_policy(b, turn, policy);\n        Board nb;\n        tilt_board(b, nb, gd);\n        b = nb;\n    }\n\n    if (endTurn >= 88) {\n        return component_score(b) * 1000.0 + edge_score(b) * 10.0;\n    }\n\n    return eval_mixed(b, endTurn);\n}\n\nint choose_dir(const Board& current, int turn) {\n    int rolloutCalls;\n    int horizon;\n\n    // rolloutCalls means total rollout simulations per direction.\n    // Policies cycle among target / region / component.\n    if (turn <= 18) {\n        rolloutCalls = 8;\n        horizon = 30;\n    } else if (turn <= 38) {\n        rolloutCalls = 7;\n        horizon = 26;\n    } else if (turn <= 58) {\n        rolloutCalls = 6;\n        horizon = 22;\n    } else if (turn <= 76) {\n        rolloutCalls = 5;\n        horizon = 18;\n    } else if (turn <= 88) {\n        rolloutCalls = 4;\n        horizon = T - turn;\n    } else {\n        return greedy_dir_policy(current, turn, 3);\n    }\n\n    int bestDir = 0;\n    double bestVal = -1e100;\n\n    // Common random seeds for all directions make comparison less noisy.\n    uint64_t seeds[12];\n    for (int k = 0; k < rolloutCalls; k++) {\n        seeds[k] = global_rng.next_u64() ^ ((uint64_t)turn << 32) ^ (uint64_t)k;\n    }\n\n    for (int d = 0; d < 4; d++) {\n        Board after;\n        tilt_board(current, after, d);\n\n        double sum = eval_mixed(after, turn) * 0.45\n                   + component_score(after) * 20.0;\n\n        for (int k = 0; k < rolloutCalls; k++) {\n            int policy = k % 3;\n            uint64_t seed = seeds[k] ^ ((uint64_t)d * 0x9e3779b97f4a7c15ULL);\n            RNG rr(seed);\n\n            sum += rollout_limited(after, turn + 1, horizon, rr, policy);\n        }\n\n        double avg = sum / (rolloutCalls + 0.45);\n\n        if (d == 0) avg += 0.01;\n        if (d == 2) avg += 0.005;\n\n        if (avg > bestVal) {\n            bestVal = avg;\n            bestDir = d;\n        }\n    }\n\n    return bestDir;\n}\n\nvoid build_target_board() {\n    vector<int> flavors = {1, 2, 3};\n\n    sort(flavors.begin(), flavors.end(), [&](int a, int b) {\n        return cntFlavor[a] > cntFlavor[b];\n    });\n\n    for (int i = 0; i < 3; i++) {\n        rank_of_flavor[flavors[i]] = i;\n    }\n\n    vector<int> path;\n    path.reserve(100);\n\n    // Horizontal snake target.\n    for (int r = 0; r < N; r++) {\n        if (r % 2 == 0) {\n            for (int c = 0; c < N; c++) path.push_back(r * 10 + c);\n        } else {\n            for (int c = N - 1; c >= 0; c--) path.push_back(r * 10 + c);\n        }\n    }\n\n    int ptr = 0;\n    for (int fl : flavors) {\n        for (int k = 0; k < cntFlavor[fl]; k++) {\n            targetColor[path[ptr++]] = fl;\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    for (int i = 0; i < T; i++) {\n        cin >> f[i];\n        cntFlavor[f[i]]++;\n    }\n\n    build_target_board();\n\n    Board cur;\n    clear_board(cur);\n\n    for (int turn = 1; turn <= T; turn++) {\n        int p;\n        if (!(cin >> p)) break;\n\n        place_by_index(cur, p, f[turn - 1]);\n\n        int dir = choose_dir(cur, turn);\n\n        Board nb;\n        tilt_board(cur, nb, dir);\n        cur = nb;\n\n        cout << DIR_CH[dir] << '\\n' << flush;\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nint M, N;\ndouble EPS;\n\nstatic const int KMAX = 3;\n\nstruct Code {\n    array<int, KMAX> sz{};\n    string graph;\n    vector<double> edeg;\n    vector<double> prefix;\n    double eedges = 0;\n    double edeg2 = 0;\n};\n\nint choose_N(int M, double e) {\n    if (e < 1e-12) {\n        int n = 4;\n        while (n * (n - 1) / 2 < M) n++;\n        return n;\n    }\n\n    // Continue conservative N reduction in low-noise regimes.\n    if (e <= 0.01) return max(8, min(100, M / 2 + 4));\n    if (e <= 0.03) return max(16, min(100, M / 2 + 12));\n    if (e <= 0.06) return max(30, min(100, M / 2 + 26));\n    if (e <= 0.10) return max(50, min(100, M / 2 + 50));\n    if (e <= 0.15) return max(72, min(100, M / 2 + 65));\n    return 100;\n}\n\nstring make_multi_clique_graph(array<int, KMAX> s) {\n    string out;\n    out.reserve(N * (N - 1) / 2);\n\n    vector<int> belong(N, -1);\n    int pos = 0;\n    for (int g = 0; g < KMAX; g++) {\n        for (int i = 0; i < s[g] && pos < N; i++, pos++) {\n            belong[pos] = g;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = (belong[i] >= 0 && belong[i] == belong[j]);\n            out.push_back(e ? '1' : '0');\n        }\n    }\n    return out;\n}\n\nvector<int> parse_degrees_desc(const string& h) {\n    vector<int> d(N, 0);\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (h[p] == '1') {\n                d[i]++;\n                d[j]++;\n            }\n            p++;\n        }\n    }\n    sort(d.begin(), d.end(), greater<int>());\n    return d;\n}\n\nCode make_code(array<int, KMAX> s) {\n    sort(s.begin(), s.end(), greater<int>());\n\n    Code c;\n    c.sz = s;\n    c.graph = make_multi_clique_graph(s);\n\n    int E = N * (N - 1) / 2;\n    int origEdges = 0;\n    for (int x : s) origEdges += x * (x - 1) / 2;\n\n    c.eedges = (1.0 - EPS) * origEdges + EPS * (E - origEdges);\n\n    double base = EPS * (N - 1);\n    double coef = 1.0 - 2.0 * EPS;\n\n    c.edeg.clear();\n    c.edeg.reserve(N);\n\n    int used = 0;\n    for (int x : s) {\n        used += x;\n        for (int i = 0; i < x; i++) {\n            c.edeg.push_back(base + coef * (x - 1));\n        }\n    }\n    for (int i = used; i < N; i++) c.edeg.push_back(base);\n\n    sort(c.edeg.begin(), c.edeg.end(), greater<double>());\n\n    c.prefix.assign(N + 1, 0.0);\n    for (int i = 0; i < N; i++) c.prefix[i + 1] = c.prefix[i] + c.edeg[i];\n\n    c.edeg2 = 0;\n    for (double x : c.edeg) c.edeg2 += x * x;\n\n    return c;\n}\n\nbool same_code(const Code& a, const Code& b) {\n    return a.sz == b.sz;\n}\n\ndouble degree_sigma() {\n    return sqrt(max(1.0, EPS * (1.0 - EPS) * (N - 1))) + 1.0;\n}\n\ndouble edge_sigma() {\n    return sqrt(max(1.0, EPS * (1.0 - EPS) * (N * (N - 1) / 2.0))) + 1.0;\n}\n\ndouble profile_distance(const Code& x, const Code& y) {\n    double ds = degree_sigma();\n    double es = edge_sigma();\n\n    double s = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        double d = (x.edeg[i] - y.edeg[i]) / ds;\n        s += d * d;\n    }\n    s /= N;\n\n    double e = (x.eedges - y.eedges) / es;\n    s += 2.3 * e * e;\n\n    double d2scale = max(10.0, N * N * ds);\n    double d2 = (x.edeg2 - y.edeg2) / d2scale;\n    s += 0.25 * d2 * d2;\n\n    int px = 0;\n    for (int t = 0; t < KMAX; t++) {\n        px += x.sz[t];\n        if (px <= 0 || px > N) continue;\n\n        double diff = x.prefix[px] - y.prefix[px];\n        double scale = max(1.0, sqrt((double)px) * ds);\n        s += 0.25 * (diff / scale) * (diff / scale);\n    }\n\n    int py = 0;\n    for (int t = 0; t < KMAX; t++) {\n        py += y.sz[t];\n        if (py <= 0 || py > N) continue;\n\n        double diff = x.prefix[py] - y.prefix[py];\n        double scale = max(1.0, sqrt((double)py) * ds);\n        s += 0.25 * (diff / scale) * (diff / scale);\n    }\n\n    return s;\n}\n\ndouble obs_distance(const vector<int>& deg,\n                    const vector<double>& obsPrefix,\n                    int obsEdges,\n                    double obsDeg2,\n                    const Code& c) {\n    double ds = degree_sigma();\n    double es = edge_sigma();\n\n    double s = 0.0;\n\n    double prof = 0.0;\n    for (int i = 0; i < N; i++) {\n        double d = (deg[i] - c.edeg[i]) / ds;\n        prof += d * d;\n    }\n    s += prof / N;\n\n    double e = (obsEdges - c.eedges) / es;\n    s += 2.7 * e * e;\n\n    double d2scale = max(10.0, N * N * ds);\n    double d2 = (obsDeg2 - c.edeg2) / d2scale;\n    s += 0.35 * d2 * d2;\n\n    int p = 0;\n    for (int t = 0; t < KMAX; t++) {\n        p += c.sz[t];\n        if (p <= 0 || p > N) continue;\n\n        double diff = obsPrefix[p] - c.prefix[p];\n        double scale = max(1.0, sqrt((double)p) * ds);\n        s += 0.85 * (diff / scale) * (diff / scale);\n    }\n\n    static const double qs[] = {0.10, 0.20, 0.35, 0.50, 0.70, 0.85};\n    for (double q : qs) {\n        int idx = min(N - 1, max(0, (int)(q * (N - 1))));\n        double diff = deg[idx] - c.edeg[idx];\n        s += 0.10 * (diff / ds) * (diff / ds);\n    }\n\n    return s;\n}\n\nvector<Code> build_codebook() {\n    vector<Code> cand;\n\n    int minClique;\n    if (EPS <= 0.03) minClique = 0;\n    else if (EPS <= 0.08) minClique = 3;\n    else if (EPS <= 0.15) minClique = 5;\n    else if (EPS <= 0.25) minClique = 7;\n    else if (EPS <= 0.35) minClique = 9;\n    else minClique = 11;\n\n    for (int a = minClique; a <= N; a++) {\n        for (int b = 0; b <= a; b++) {\n            if (b > 0 && b < minClique) continue;\n            for (int c = 0; c <= b; c++) {\n                if (c > 0 && c < minClique) continue;\n                if (a + b + c > N) continue;\n                if (a == 0 && b == 0 && c == 0) continue;\n\n                int iso = N - a - b - c;\n                if (EPS >= 0.10 && iso < 2) continue;\n\n                cand.push_back(make_code({a, b, c}));\n            }\n        }\n    }\n\n    if (EPS <= 0.10) cand.push_back(make_code({0, 0, 0}));\n\n    if ((int)cand.size() > 36000) {\n        sort(cand.begin(), cand.end(), [](const Code& x, const Code& y) {\n            if (x.eedges != y.eedges) return x.eedges < y.eedges;\n            return x.sz < y.sz;\n        });\n\n        vector<Code> filtered;\n        int B = 36000;\n        filtered.reserve(B + 2000);\n\n        for (int i = 0; i < B; i++) {\n            int idx = (long long)i * ((int)cand.size() - 1) / max(1, B - 1);\n            filtered.push_back(cand[idx]);\n        }\n\n        for (const Code& c : cand) {\n            int nonzero = 0;\n            for (int x : c.sz) if (x > 0) nonzero++;\n            if (nonzero <= 2 && (int)filtered.size() < B + 2000) {\n                filtered.push_back(c);\n            }\n        }\n\n        sort(filtered.begin(), filtered.end(), [](const Code& x, const Code& y) {\n            return x.sz < y.sz;\n        });\n        filtered.erase(unique(filtered.begin(), filtered.end(), same_code), filtered.end());\n        cand.swap(filtered);\n    }\n\n    sort(cand.begin(), cand.end(), [](const Code& x, const Code& y) {\n        if (x.eedges != y.eedges) return x.eedges < y.eedges;\n        return x.sz < y.sz;\n    });\n\n    vector<Code> selected;\n    selected.reserve(M);\n\n    if (!cand.empty()) {\n        vector<int> anchors = {\n            0,\n            (int)cand.size() - 1,\n            (int)cand.size() / 2,\n            (int)cand.size() / 4,\n            (int)cand.size() * 3 / 4\n        };\n        for (int idx : anchors) {\n            if ((int)selected.size() >= M) break;\n            if (idx < 0 || idx >= (int)cand.size()) continue;\n\n            bool dup = false;\n            for (auto &s : selected) if (same_code(s, cand[idx])) dup = true;\n            if (!dup) selected.push_back(cand[idx]);\n        }\n    }\n\n    vector<double> mind(cand.size(), 1e100);\n    for (int i = 0; i < (int)cand.size(); i++) {\n        for (auto &s : selected) {\n            if (same_code(cand[i], s)) {\n                mind[i] = -1;\n                break;\n            }\n            mind[i] = min(mind[i], profile_distance(cand[i], s));\n        }\n    }\n\n    while ((int)selected.size() < M) {\n        int best = -1;\n        double bestVal = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (mind[i] < 0) continue;\n\n            double val = mind[i];\n\n            int iso = N - cand[i].sz[0] - cand[i].sz[1] - cand[i].sz[2];\n            if (EPS >= 0.20 && iso < 5) val *= 0.97;\n\n            if (cand[i].sz[1] > 0 && cand[i].sz[0] == cand[i].sz[1]) val *= 0.96;\n            if (cand[i].sz[2] > 0 && cand[i].sz[1] == cand[i].sz[2]) val *= 0.96;\n\n            if (val > bestVal) {\n                bestVal = val;\n                best = i;\n            }\n        }\n\n        if (best < 0) break;\n\n        selected.push_back(cand[best]);\n        mind[best] = -1;\n\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (mind[i] < 0) continue;\n            mind[i] = min(mind[i], profile_distance(cand[i], cand[best]));\n        }\n    }\n\n    for (int r = 1; (int)selected.size() < M && r <= N; r++) {\n        selected.push_back(make_code({r, 0, 0}));\n    }\n\n    sort(selected.begin(), selected.end(), [](const Code& x, const Code& y) {\n        if (x.eedges != y.eedges) return x.eedges < y.eedges;\n        return x.sz < y.sz;\n    });\n\n    if ((int)selected.size() > M) selected.resize(M);\n    return selected;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> M >> EPS;\n    N = choose_N(M, EPS);\n    int E = N * (N - 1) / 2;\n\n    if (EPS < 1e-12) {\n        cout << N << '\\n';\n        for (int k = 0; k < M; k++) {\n            string s(E, '0');\n            for (int i = 0; i < k; i++) s[i] = '1';\n            cout << s << '\\n';\n        }\n        cout.flush();\n\n        for (int q = 0; q < 100; q++) {\n            string H;\n            cin >> H;\n            int ones = 0;\n            for (char c : H) ones += (c == '1');\n            cout << min(M - 1, ones) << '\\n';\n            cout.flush();\n        }\n        return 0;\n    }\n\n    vector<Code> codebook = build_codebook();\n\n    cout << N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << codebook[k].graph << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        vector<int> deg = parse_degrees_desc(H);\n        vector<double> pref(N + 1, 0.0);\n        for (int i = 0; i < N; i++) pref[i + 1] = pref[i] + deg[i];\n\n        int obsEdges = (int)(pref[N] / 2.0 + 0.5);\n\n        double obsDeg2 = 0;\n        for (int x : deg) obsDeg2 += 1.0 * x * x;\n\n        int best = 0;\n        double bestScore = 1e300;\n\n        for (int k = 0; k < M; k++) {\n            double sc = obs_distance(deg, pref, obsEdges, obsDeg2, codebook[k]);\n            if (sc < bestScore) {\n                bestScore = sc;\n                best = k;\n            }\n        }\n\n        cout << best << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc017":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Edge {\n    int u, v;\n    int w;\n    double mx, my;\n};\n\nstatic uint64_t rng_state = 88172645463325252ull;\n\nuint64_t xorshift64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\nint rnd_int(int l, int r) {\n    return l + (int)(xorshift64() % (uint64_t)(r - l + 1));\n}\n\ndouble rnd01() {\n    return (xorshift64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, D, K;\n    cin >> N >> M >> D >> K;\n\n    vector<Edge> edges(M);\n    vector<vector<pair<int,int>>> adj(N);\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 = u;\n        edges[i].v = v;\n        edges[i].w = w;\n        adj[u].push_back({v, i});\n        adj[v].push_back({u, i});\n    }\n\n    vector<double> X(N), Y(N);\n    for (int i = 0; i < N; i++) cin >> X[i] >> Y[i];\n\n    for (int i = 0; i < M; i++) {\n        edges[i].mx = (X[edges[i].u] + X[edges[i].v]) * 0.5;\n        edges[i].my = (Y[edges[i].u] + Y[edges[i].v]) * 0.5;\n    }\n\n    const long long INF = (1LL << 60);\n\n    vector<int> banned(M, 0);\n    int banVersion = 1;\n\n    auto markRemoved = [&](const vector<int>* rem) {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n        if (rem) {\n            for (int e : *rem) {\n                if (0 <= e && e < M) banned[e] = banVersion;\n            }\n        }\n    };\n\n    auto dijkstra = [&](int s, const vector<int>* rem) -> vector<long long> {\n        markRemoved(rem);\n\n        vector<long long> dist(N, INF);\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n            if (du != dist[u]) continue;\n\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n                long long nd = du + edges[ei].w;\n                if (nd < dist[v]) {\n                    dist[v] = nd;\n                    pq.push({nd, v});\n                }\n            }\n        }\n\n        return dist;\n    };\n\n    // ---------- Approximate edge importance ----------\n    vector<double> imp(M, 1.0);\n\n    vector<int> landmarks;\n    {\n        vector<pair<double,int>> vals;\n\n        auto addExtreme = [&](auto func) {\n            vals.clear();\n            for (int i = 0; i < N; i++) vals.push_back({func(i), i});\n            sort(vals.begin(), vals.end());\n            landmarks.push_back(vals.front().second);\n            landmarks.push_back(vals.back().second);\n        };\n\n        addExtreme([&](int i){ return X[i] + Y[i]; });\n        addExtreme([&](int i){ return X[i] - Y[i]; });\n        addExtreme([&](int i){ return X[i]; });\n        addExtreme([&](int i){ return Y[i]; });\n\n        int samples = min(N, 36);\n        while ((int)landmarks.size() < samples) landmarks.push_back(rnd_int(0, N - 1));\n\n        sort(landmarks.begin(), landmarks.end());\n        landmarks.erase(unique(landmarks.begin(), landmarks.end()), landmarks.end());\n    }\n\n    vector<long long> distTmp(N);\n    vector<int> parEdge(N);\n\n    for (int s : landmarks) {\n        fill(distTmp.begin(), distTmp.end(), INF);\n        fill(parEdge.begin(), parEdge.end(), -1);\n\n        priority_queue<pair<long long,int>, vector<pair<long long,int>>, greater<pair<long long,int>>> pq;\n\n        distTmp[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [du, u] = pq.top();\n            pq.pop();\n\n            if (du != distTmp[u]) continue;\n\n            for (auto [v, ei] : adj[u]) {\n                long long nd = du + edges[ei].w;\n                if (nd < distTmp[v]) {\n                    distTmp[v] = nd;\n                    parEdge[v] = ei;\n                    pq.push({nd, v});\n                }\n            }\n        }\n\n        for (int v = 0; v < N; v++) {\n            if (parEdge[v] >= 0) imp[parEdge[v]] += 1.0;\n        }\n    }\n\n    double maxImp = *max_element(imp.begin(), imp.end());\n    double sumImp = 0.0;\n\n    for (int i = 0; i < M; i++) {\n        imp[i] = sqrt(imp[i] / maxImp);\n        imp[i] += 0.12 * sqrt((double)edges[i].w / 1000000.0);\n        sumImp += imp[i];\n    }\n\n    double targetImp = sumImp / D;\n\n    // ---------- Connectivity ----------\n    auto isConnectedDay = [&](const vector<int>& rem) -> bool {\n        markRemoved(&rem);\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n\n        vis[0] = 1;\n        q.push(0);\n\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n\n        return cnt == N;\n    };\n\n    auto isConnectedWithExtra = [&](const vector<int>& rem, int extra) -> bool {\n        banVersion++;\n        if (banVersion == INT_MAX) {\n            fill(banned.begin(), banned.end(), 0);\n            banVersion = 1;\n        }\n\n        for (int e : rem) {\n            if (0 <= e && e < M) banned[e] = banVersion;\n        }\n        if (0 <= extra && extra < M) banned[extra] = banVersion;\n\n        vector<char> vis(N, 0);\n        queue<int> q;\n\n        vis[0] = 1;\n        q.push(0);\n\n        int cnt = 1;\n\n        while (!q.empty()) {\n            int u = q.front();\n            q.pop();\n\n            for (auto [v, ei] : adj[u]) {\n                if (banned[ei] == banVersion) continue;\n\n                if (!vis[v]) {\n                    vis[v] = 1;\n                    cnt++;\n                    q.push(v);\n                }\n            }\n        }\n\n        return cnt == N;\n    };\n\n    // ---------- State ----------\n    vector<int> ans(M, -1);\n    vector<int> load(D, 0);\n    vector<double> dayImp(D, 0.0);\n    vector<vector<int>> dayEdges(D);\n    vector<vector<int>> dayVertCnt(D, vector<int>(N, 0));\n\n    auto pairCost = [&](int a, int b) -> double {\n        double dx = edges[a].mx - edges[b].mx;\n        double dy = edges[a].my - edges[b].my;\n        double d2 = dx * dx + dy * dy;\n\n        double c = 18000.0 / (d2 + 900.0);\n\n        if (edges[a].u == edges[b].u || edges[a].u == edges[b].v ||\n            edges[a].v == edges[b].u || edges[a].v == edges[b].v) {\n            c += 2.5;\n        }\n\n        return c * (0.7 + 0.9 * (imp[a] + imp[b]));\n    };\n\n    auto addCostToDay = [&](int e, int d) -> double {\n        double c = 0.0;\n\n        for (int f : dayEdges[d]) c += pairCost(e, f);\n\n        c += 2.5 * imp[e] * dayImp[d];\n\n        int u = edges[e].u;\n        int v = edges[e].v;\n\n        c += 8.0 * dayVertCnt[d][u];\n        c += 8.0 * dayVertCnt[d][v];\n\n        double targetLoad = (double)M / D;\n        c += 0.65 * max(0.0, load[d] + 1 - targetLoad);\n        c -= 0.08 * max(0.0, targetLoad - load[d]);\n\n        double ni = dayImp[d] + imp[e];\n        if (ni > targetImp) {\n            c += 12.0 * (ni - targetImp) * (ni - targetImp);\n        }\n\n        return c;\n    };\n\n    auto assignEdge = [&](int e, int d) {\n        if (e < 0 || e >= M || d < 0 || d >= D) return;\n        ans[e] = d;\n        load[d]++;\n        dayImp[d] += imp[e];\n        dayEdges[d].push_back(e);\n        dayVertCnt[d][edges[e].u]++;\n        dayVertCnt[d][edges[e].v]++;\n    };\n\n    auto removeFromDayVec = [&](int e, int d) {\n        auto &vec = dayEdges[d];\n        for (int i = 0; i < (int)vec.size(); i++) {\n            if (vec[i] == e) {\n                vec[i] = vec.back();\n                vec.pop_back();\n                return;\n            }\n        }\n    };\n\n    auto removeEdge = [&](int e, int d) {\n        if (e < 0 || e >= M || d < 0 || d >= D) return;\n        if (ans[e] != d) return;\n\n        ans[e] = -1;\n        load[d]--;\n        dayImp[d] -= imp[e];\n\n        dayVertCnt[d][edges[e].u]--;\n        dayVertCnt[d][edges[e].v]--;\n\n        removeFromDayVec(e, d);\n    };\n\n    auto edgeContribution = [&](int e, int d) -> double {\n        double c = 0.0;\n\n        for (int f : dayEdges[d]) {\n            if (f != e) c += pairCost(e, f);\n        }\n\n        c += 2.5 * imp[e] * max(0.0, dayImp[d] - imp[e]);\n\n        int u = edges[e].u;\n        int v = edges[e].v;\n\n        c += 8.0 * max(0, dayVertCnt[d][u] - 1);\n        c += 8.0 * max(0, dayVertCnt[d][v] - 1);\n\n        return c;\n    };\n\n    auto sharedEndpoint = [&](int a, int b) -> int {\n        return edges[a].u == edges[b].u || edges[a].u == edges[b].v ||\n               edges[a].v == edges[b].u || edges[a].v == edges[b].v;\n    };\n\n    // ---------- Initial construction ----------\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (fabs(imp[a] - imp[b]) > 1e-12) return imp[a] > imp[b];\n        return edges[a].w > edges[b].w;\n    });\n\n    for (int e : ord) {\n        int bestD = -1;\n        double best = 1e100;\n\n        for (int d = 0; d < D; d++) {\n            if (load[d] >= K) continue;\n\n            if (!isConnectedWithExtra(dayEdges[d], e)) continue;\n\n            double c = addCostToDay(e, d);\n\n            if (c < best) {\n                best = c;\n                bestD = d;\n            }\n        }\n\n        if (bestD < 0) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= K) continue;\n\n                double c = addCostToDay(e, d) + 1e6;\n\n                if (c < best) {\n                    best = c;\n                    bestD = d;\n                }\n            }\n        }\n\n        if (bestD < 0) {\n            for (int d = 0; d < D; d++) {\n                if (load[d] < K) {\n                    bestD = d;\n                    break;\n                }\n            }\n        }\n\n        if (bestD < 0) bestD = 0;\n\n        assignEdge(e, bestD);\n    }\n\n    auto repairDisconnected = [&]() {\n        bool changed = true;\n        int rounds = 0;\n\n        while (changed && rounds < 200) {\n            changed = false;\n            rounds++;\n\n            for (int d = 0; d < D; d++) {\n                while (!isConnectedDay(dayEdges[d])) {\n                    if (dayEdges[d].empty()) break;\n\n                    int chosen = -1;\n                    double worst = -1;\n\n                    for (int e : dayEdges[d]) {\n                        double c = edgeContribution(e, d) + 100.0 * imp[e];\n\n                        if (c > worst) {\n                            worst = c;\n                            chosen = e;\n                        }\n                    }\n\n                    if (chosen < 0) break;\n\n                    int src = d;\n                    removeEdge(chosen, src);\n\n                    int bestD = -1;\n                    double best = 1e100;\n\n                    for (int nd = 0; nd < D; nd++) {\n                        if (nd == src) continue;\n                        if (load[nd] >= K) continue;\n                        if (!isConnectedWithExtra(dayEdges[nd], chosen)) continue;\n\n                        double c = addCostToDay(chosen, nd);\n\n                        if (c < best) {\n                            best = c;\n                            bestD = nd;\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        for (int nd = 0; nd < D; nd++) {\n                            if (nd == src) continue;\n                            if (load[nd] >= K) continue;\n\n                            double c = addCostToDay(chosen, nd) + 1e6;\n\n                            if (c < best) {\n                                best = c;\n                                bestD = nd;\n                            }\n                        }\n                    }\n\n                    if (bestD < 0) {\n                        assignEdge(chosen, src);\n                        break;\n                    } else {\n                        assignEdge(chosen, bestD);\n                        changed = true;\n                    }\n                }\n            }\n        }\n    };\n\n    repairDisconnected();\n\n    // ---------- Surrogate local search ----------\n    double phase1Limit = 2.7;\n\n    while (timer.elapsed() < phase1Limit) {\n        if ((xorshift64() & 3) != 0) {\n            int e = rnd_int(0, M - 1);\n            int a = ans[e];\n            int b = rnd_int(0, D - 1);\n\n            if (a == b || b < 0 || b >= D || load[b] >= K) continue;\n\n            double oldc = edgeContribution(e, a);\n\n            removeEdge(e, a);\n\n            if (!isConnectedDay(dayEdges[a]) || !isConnectedWithExtra(dayEdges[b], e)) {\n                assignEdge(e, a);\n                continue;\n            }\n\n            double newc = addCostToDay(e, b);\n\n            double t = max(0.001, 0.05 * (1.0 - timer.elapsed() / phase1Limit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) assignEdge(e, b);\n            else assignEdge(e, a);\n\n        } else {\n            int e1 = rnd_int(0, M - 1);\n            int e2 = rnd_int(0, M - 1);\n\n            if (e1 == e2) continue;\n\n            int d1 = ans[e1];\n            int d2 = ans[e2];\n\n            if (d1 == d2 || d1 < 0 || d2 < 0) continue;\n\n            double oldc = edgeContribution(e1, d1) + edgeContribution(e2, d2);\n\n            removeEdge(e1, d1);\n            removeEdge(e2, d2);\n\n            bool ok1 = isConnectedWithExtra(dayEdges[d1], e2);\n            bool ok2 = isConnectedWithExtra(dayEdges[d2], e1);\n\n            if (!ok1 || !ok2) {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n                continue;\n            }\n\n            double newc = addCostToDay(e1, d2) + addCostToDay(e2, d1);\n\n            double t = max(0.001, 0.05 * (1.0 - timer.elapsed() / phase1Limit));\n            bool accept = (newc <= oldc) || (rnd01() < exp((oldc - newc) / t));\n\n            if (accept) {\n                assignEdge(e1, d2);\n                assignEdge(e2, d1);\n            } else {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n            }\n        }\n    }\n\n    repairDisconnected();\n\n    // ---------- Sampled true-score sources ----------\n    vector<int> scoreSources;\n    vector<char> usedSource(N, 0);\n    auto addSource = [&](int v) {\n        if (0 <= v && v < N && !usedSource[v]) {\n            usedSource[v] = 1;\n            scoreSources.push_back(v);\n        }\n    };\n\n    {\n        vector<pair<double,int>> vals;\n\n        auto addExtreme = [&](auto func) {\n            vals.clear();\n            for (int i = 0; i < N; i++) vals.push_back({func(i), i});\n            sort(vals.begin(), vals.end());\n            addSource(vals.front().second);\n            addSource(vals.back().second);\n        };\n\n        addExtreme([&](int i){ return X[i] + Y[i]; });\n        addExtreme([&](int i){ return X[i] - Y[i]; });\n        addExtreme([&](int i){ return X[i]; });\n        addExtreme([&](int i){ return Y[i]; });\n\n        vals.clear();\n        for (int i = 0; i < N; i++) vals.push_back({(double)adj[i].size(), i});\n        sort(vals.begin(), vals.end());\n        for (int i = 0; i < min(6, N); i++) addSource(vals[i].second);\n\n        vals.clear();\n        for (int i = 0; i < N; i++) {\n            double dx = X[i] - 500.0;\n            double dy = Y[i] - 500.0;\n            vals.push_back({dx * dx + dy * dy, i});\n        }\n        sort(vals.begin(), vals.end());\n        for (int i = 0; i < min(3, N); i++) addSource(vals[i].second);\n        for (int i = 0; i < min(3, N); i++) addSource(vals[N - 1 - i].second);\n\n        int S0 = min(N, 24);\n        while ((int)scoreSources.size() < S0) addSource(rnd_int(0, N - 1));\n        while ((int)scoreSources.size() > S0) scoreSources.pop_back();\n    }\n\n    int S = scoreSources.size();\n    vector<vector<long long>> origDist(S);\n\n    for (int i = 0; i < S; i++) {\n        origDist[i] = dijkstra(scoreSources[i], nullptr);\n    }\n\n    auto sampledDayScore = [&](const vector<int>& rem) -> double {\n        double total = 0.0;\n\n        for (int si = 0; si < S; si++) {\n            vector<long long> nd = dijkstra(scoreSources[si], &rem);\n            const auto &od = origDist[si];\n\n            for (int v = 0; v < N; v++) {\n                if (v == scoreSources[si]) continue;\n\n                if (nd[v] >= INF / 4) {\n                    total += 1e9;\n                } else {\n                    total += (double)(nd[v] - od[v]);\n                }\n            }\n        }\n\n        return total / max(1, S);\n    };\n\n    vector<double> dayScore(D);\n\n    auto recomputeDayScore = [&](int d) {\n        dayScore[d] = sampledDayScore(dayEdges[d]);\n    };\n\n    for (int d = 0; d < D; d++) recomputeDayScore(d);\n\n    auto totalSampleScore = [&]() {\n        double s = 0.0;\n        for (double x : dayScore) s += x;\n        return s;\n    };\n\n    vector<int> bestAns = ans;\n    double bestSample = totalSampleScore();\n\n    auto rebuildFromAns = [&](const vector<int>& src) {\n        fill(ans.begin(), ans.end(), -1);\n        fill(load.begin(), load.end(), 0);\n        fill(dayImp.begin(), dayImp.end(), 0.0);\n        for (auto &v : dayEdges) v.clear();\n        for (auto &v : dayVertCnt) fill(v.begin(), v.end(), 0);\n\n        for (int e = 0; e < M; e++) {\n            int d = src[e];\n            if (d < 0 || d >= D) d = 0;\n            assignEdge(e, d);\n        }\n    };\n\n    // ---------- Direct sampled-score local search ----------\n    double phase2Limit = 5.75;\n    vector<int> skip(D, 0);\n\n    while (timer.elapsed() < phase2Limit) {\n        for (int d = 0; d < D; d++) if (skip[d] > 0) skip[d]--;\n\n        vector<int> orderDays(D);\n        iota(orderDays.begin(), orderDays.end(), 0);\n        sort(orderDays.begin(), orderDays.end(), [&](int a, int b) {\n            double va = (skip[a] > 0 ? -1.0 : dayScore[a]);\n            double vb = (skip[b] > 0 ? -1.0 : dayScore[b]);\n            return va > vb;\n        });\n\n        int worstDay = -1;\n        int pickRange = min(D, 3);\n        if (rnd01() < 0.78) {\n            worstDay = orderDays[0];\n        } else {\n            int r = rnd_int(0, pickRange - 1);\n            worstDay = orderDays[r];\n        }\n\n        if (skip[worstDay] > 0 || dayScore[worstDay] < 0) {\n            fill(skip.begin(), skip.end(), 0);\n            continue;\n        }\n\n        bool improved = false;\n\n        vector<int> cand = dayEdges[worstDay];\n        if (cand.empty()) {\n            skip[worstDay] = 2;\n            continue;\n        }\n\n        sort(cand.begin(), cand.end(), [&](int a, int b) {\n            return edgeContribution(a, worstDay) + 25.0 * imp[a] >\n                   edgeContribution(b, worstDay) + 25.0 * imp[b];\n        });\n\n        vector<int> candPool;\n        vector<char> usedEdge(M, 0);\n        auto addCand = [&](int e) {\n            if (0 <= e && e < M && !usedEdge[e]) {\n                usedEdge[e] = 1;\n                candPool.push_back(e);\n            }\n        };\n\n        for (int i = 0; i < min((int)cand.size(), 8); i++) addCand(cand[i]);\n\n        vector<int> byImp = dayEdges[worstDay];\n        sort(byImp.begin(), byImp.end(), [&](int a, int b) {\n            return imp[a] > imp[b];\n        });\n        for (int i = 0; i < min((int)byImp.size(), 5); i++) addCand(byImp[i]);\n\n        while ((int)candPool.size() > 13) candPool.pop_back();\n\n        // Refined candidate ranking by actual sampled improvement from removing one edge.\n        vector<pair<double,int>> trueCand;\n\n        for (int e : candPool) {\n            if (timer.elapsed() >= phase2Limit) break;\n\n            removeEdge(e, worstDay);\n            bool ok = isConnectedDay(dayEdges[worstDay]);\n\n            double sc = 1e100;\n            if (ok) sc = sampledDayScore(dayEdges[worstDay]);\n\n            assignEdge(e, worstDay);\n\n            if (ok) {\n                double gain = dayScore[worstDay] - sc;\n                trueCand.push_back({gain, e});\n            }\n        }\n\n        if (!trueCand.empty()) {\n            sort(trueCand.rbegin(), trueCand.rend());\n            cand.clear();\n            for (auto [g, e] : trueCand) cand.push_back(e);\n        }\n\n        int tryEdges = min((int)cand.size(), 8);\n        double currentTotal = totalSampleScore();\n\n        for (int ii = 0; ii < tryEdges && timer.elapsed() < phase2Limit; ii++) {\n            int e = cand[ii];\n            int a = worstDay;\n\n            int eu = edges[e].u;\n            int ev = edges[e].v;\n\n            vector<int> ds(D);\n            iota(ds.begin(), ds.end(), 0);\n\n            sort(ds.begin(), ds.end(), [&](int x, int y) {\n                double cx = dayScore[x]\n                          + (load[x] >= K ? 1e100 : 0.0)\n                          + 0.05 * addCostToDay(e, x)\n                          + 0.07 * load[x]\n                          + 0.6 * (dayVertCnt[x][eu] + dayVertCnt[x][ev]);\n                double cy = dayScore[y]\n                          + (load[y] >= K ? 1e100 : 0.0)\n                          + 0.05 * addCostToDay(e, y)\n                          + 0.07 * load[y]\n                          + 0.6 * (dayVertCnt[y][eu] + dayVertCnt[y][ev]);\n                return cx < cy;\n            });\n\n            for (int b : ds) {\n                if (a == b || load[b] >= K) continue;\n\n                removeEdge(e, a);\n\n                if (!isConnectedDay(dayEdges[a]) || !isConnectedWithExtra(dayEdges[b], e)) {\n                    assignEdge(e, a);\n                    continue;\n                }\n\n                assignEdge(e, b);\n\n                double oldA = dayScore[a];\n                double oldB = dayScore[b];\n\n                double newA = sampledDayScore(dayEdges[a]);\n                double newB = sampledDayScore(dayEdges[b]);\n\n                double newTotal = currentTotal - oldA - oldB + newA + newB;\n\n                if (newTotal + 1e-7 < currentTotal) {\n                    dayScore[a] = newA;\n                    dayScore[b] = newB;\n                    improved = true;\n                    currentTotal = newTotal;\n\n                    if (currentTotal < bestSample) {\n                        bestSample = currentTotal;\n                        bestAns = ans;\n                    }\n\n                    break;\n                } else {\n                    removeEdge(e, b);\n                    assignEdge(e, a);\n                }\n            }\n\n            if (improved) break;\n        }\n\n        if (improved) continue;\n\n        int swapTrials = (timer.elapsed() < 5.35 ? 22 : 12);\n\n        vector<int> lowDays(D);\n        iota(lowDays.begin(), lowDays.end(), 0);\n        sort(lowDays.begin(), lowDays.end(), [&](int a, int b) {\n            return dayScore[a] < dayScore[b];\n        });\n\n        for (int tt = 0; tt < swapTrials && timer.elapsed() < phase2Limit; tt++) {\n            int lim = min((int)cand.size(), 8);\n            if (lim <= 0) break;\n\n            int e1 = cand[rnd_int(0, lim - 1)];\n            int d1 = worstDay;\n\n            int d2;\n            if (rnd01() < 0.55) {\n                d2 = lowDays[rnd_int(0, min(D, 8) - 1)];\n            } else {\n                d2 = rnd_int(0, D - 1);\n            }\n\n            if (d1 == d2 || dayEdges[d2].empty()) continue;\n\n            int e2 = dayEdges[d2][rnd_int(0, (int)dayEdges[d2].size() - 1)];\n\n            int trialsPick = min(5, (int)dayEdges[d2].size());\n            double bestPick = -1e100;\n            for (int rep = 0; rep < trialsPick; rep++) {\n                int t = dayEdges[d2][rnd_int(0, (int)dayEdges[d2].size() - 1)];\n                double sc = edgeContribution(t, d2) + 10.0 * sharedEndpoint(e1, t) + 2.0 * imp[t];\n                if (sc > bestPick) {\n                    bestPick = sc;\n                    e2 = t;\n                }\n            }\n\n            double currentTotal2 = totalSampleScore();\n\n            removeEdge(e1, d1);\n            removeEdge(e2, d2);\n\n            bool ok1 = isConnectedWithExtra(dayEdges[d1], e2);\n            bool ok2 = isConnectedWithExtra(dayEdges[d2], e1);\n\n            if (!ok1 || !ok2) {\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n                continue;\n            }\n\n            assignEdge(e1, d2);\n            assignEdge(e2, d1);\n\n            double old1 = dayScore[d1];\n            double old2 = dayScore[d2];\n\n            double new1 = sampledDayScore(dayEdges[d1]);\n            double new2 = sampledDayScore(dayEdges[d2]);\n\n            double newTotal = currentTotal2 - old1 - old2 + new1 + new2;\n\n            if (newTotal + 1e-7 < currentTotal2) {\n                dayScore[d1] = new1;\n                dayScore[d2] = new2;\n                improved = true;\n\n                if (newTotal < bestSample) {\n                    bestSample = newTotal;\n                    bestAns = ans;\n                }\n\n                break;\n            } else {\n                removeEdge(e1, d2);\n                removeEdge(e2, d1);\n                assignEdge(e1, d1);\n                assignEdge(e2, d2);\n            }\n        }\n\n        if (!improved) {\n            skip[worstDay] = 3;\n        }\n    }\n\n    rebuildFromAns(bestAns);\n    repairDisconnected();\n\n    // ---------- Final legality check ----------\n    bool legal = true;\n    vector<int> cnt(D, 0);\n\n    for (int e = 0; e < M; e++) {\n        if (ans[e] < 0 || ans[e] >= D) {\n            legal = false;\n            break;\n        }\n        cnt[ans[e]]++;\n    }\n\n    for (int d = 0; d < D; d++) {\n        if (cnt[d] > K) legal = false;\n    }\n\n    if (!legal) {\n        vector<int> out(M);\n        vector<int> c(D, 0);\n\n        int d = 0;\n        for (int e = 0; e < M; e++) {\n            while (d < D && c[d] >= K) d++;\n            if (d >= D) d = D - 1;\n\n            out[e] = d + 1;\n            c[d]++;\n        }\n\n        for (int i = 0; i < M; i++) {\n            if (i) cout << ' ';\n            cout << out[i];\n        }\n        cout << '\\n';\n\n        return 0;\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << ans[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Seg {\n    int x, y, z, dir;\n    int run;\n};\n\nstruct Square {\n    int q[4];\n};\n\nstruct Result {\n    vector<vector<int>> ans;\n    double eval;\n    int n;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n\n    vector<vector<string>> f(2, vector<string>(D));\n    vector<vector<string>> r(2, vector<string>(D));\n\n    for (int i = 0; i < 2; i++) {\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    const int N3 = D * D * D;\n\n    auto id = [&](int x, int y, int z) {\n        return x * D * D + y * D + z;\n    };\n\n    const int dx[3] = {1, 0, 0};\n    const int dy[3] = {0, 1, 0};\n    const int dz[3] = {0, 0, 1};\n\n    auto feasible = [&](int t, int x, int y, int z) {\n        return f[t][z][x] == '1' && r[t][z][y] == '1';\n    };\n\n    auto reorder = [&](vector<int>& v, int mode, mt19937& rng) {\n        if (mode == 0) {\n            sort(v.begin(), v.end());\n        } else if (mode == 1) {\n            sort(v.rbegin(), v.rend());\n        } else if (mode == 2) {\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return abs(a - D / 2) < abs(b - D / 2);\n            });\n        } else if (mode == 3) {\n            sort(v.begin(), v.end(), [&](int a, int b) {\n                return abs(a - D / 2) > abs(b - D / 2);\n            });\n        } else {\n            shuffle(v.begin(), v.end(), rng);\n        }\n    };\n\n    auto fill_layer_independent = [&](vector<int>& occ_t,\n                                      int t,\n                                      int z,\n                                      vector<pair<int,int>>& prev_pairs,\n                                      int seed,\n                                      mt19937& rng) {\n        vector<int> xs, ys;\n        vector<int> hasX(D, 0), hasY(D, 0);\n\n        for (int x = 0; x < D; x++) {\n            if (f[t][z][x] == '1') {\n                xs.push_back(x);\n                hasX[x] = 1;\n            }\n        }\n        for (int y = 0; y < D; y++) {\n            if (r[t][z][y] == '1') {\n                ys.push_back(y);\n                hasY[y] = 1;\n            }\n        }\n\n        int modeX = seed % 5;\n        int modeY = (seed / 5) % 5;\n\n        reorder(xs, modeX, rng);\n        reorder(ys, modeY, rng);\n\n        vector<int> coveredX(D, 0), coveredY(D, 0);\n        vector<pair<int, int>> cur_pairs;\n        set<pair<int, int>> used_pair;\n\n        auto add_pair = [&](int x, int y) {\n            if (!used_pair.count({x, y})) {\n                used_pair.insert({x, y});\n                cur_pairs.push_back({x, y});\n                occ_t[id(x, y, z)] = 1;\n            }\n            coveredX[x] = 1;\n            coveredY[y] = 1;\n        };\n\n        for (int x = 0; x < D; x++) {\n            for (int y = 0; y < D; y++) {\n                if (occ_t[id(x, y, z)]) {\n                    add_pair(x, y);\n                }\n            }\n        }\n\n        vector<pair<int, int>> pp = prev_pairs;\n        if (seed > 0 && seed % 4) shuffle(pp.begin(), pp.end(), rng);\n\n        bool aggressive = (seed % 13 == 7 || seed % 13 == 8 || seed % 17 == 4);\n\n        int extra_cap;\n        if (seed % 17 == 4) extra_cap = D;\n        else if (seed % 13 == 8) extra_cap = max(1, D / 2);\n        else extra_cap = max(1, D / 3);\n\n        int extra_used = 0;\n\n        for (auto [x, y] : pp) {\n            if (!(hasX[x] && hasY[y])) continue;\n\n            if (!coveredX[x] && !coveredY[y]) {\n                add_pair(x, y);\n            } else if (aggressive && extra_used < extra_cap) {\n                if (!used_pair.count({x, y})) {\n                    add_pair(x, y);\n                    extra_used++;\n                }\n            }\n        }\n\n        vector<int> remX, remY;\n        for (int x : xs) if (!coveredX[x]) remX.push_back(x);\n        for (int y : ys) if (!coveredY[y]) remY.push_back(y);\n\n        reorder(remX, (seed / 7) % 5, rng);\n        reorder(remY, (seed / 11) % 5, rng);\n\n        int p = 0;\n        while (p < (int)remX.size() && p < (int)remY.size()) {\n            add_pair(remX[p], remY[p]);\n            p++;\n        }\n\n        int fallbackY = ys[0];\n        if (seed % 2 == 0) {\n            for (int y : ys) if (coveredY[y]) { fallbackY = y; break; }\n        } else {\n            for (int i = (int)ys.size() - 1; i >= 0; i--) if (coveredY[ys[i]]) { fallbackY = ys[i]; break; }\n        }\n\n        while (p < (int)remX.size()) {\n            add_pair(remX[p], fallbackY);\n            p++;\n        }\n\n        int fallbackX = xs[0];\n        if (seed % 2 == 0) {\n            for (int x : xs) if (coveredX[x]) { fallbackX = x; break; }\n        } else {\n            for (int i = (int)xs.size() - 1; i >= 0; i--) if (coveredX[xs[i]]) { fallbackX = xs[i]; break; }\n        }\n\n        p = min((int)remX.size(), (int)remY.size());\n        while (p < (int)remY.size()) {\n            add_pair(fallbackX, remY[p]);\n            p++;\n        }\n\n        prev_pairs = cur_pairs;\n    };\n\n    auto add_vertical_extensions = [&](vector<vector<int>>& occ, int seed, mt19937& rng) {\n        if (!(seed % 19 == 6 || seed % 19 == 7 || seed % 23 == 5)) return;\n\n        for (int t = 0; t < 2; t++) {\n            vector<int> cand;\n\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 q = id(x, y, z);\n                        if (occ[t][q]) continue;\n                        if (!feasible(t, x, y, z)) continue;\n\n                        bool near = false;\n                        if (z > 0 && occ[t][id(x, y, z - 1)]) near = true;\n                        if (z + 1 < D && occ[t][id(x, y, z + 1)]) near = true;\n\n                        if (near) cand.push_back(q);\n                    }\n                }\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            int limit = D;\n            if (seed % 19 == 7) limit = 2 * D;\n            if (seed % 23 == 5) limit = max(1, D / 2);\n\n            for (int i = 0; i < (int)cand.size() && i < limit; i++) {\n                occ[t][cand[i]] = 1;\n            }\n        }\n    };\n\n    auto add_gap_bridges = [&](vector<vector<int>>& occ, int seed, mt19937& rng) {\n        if (!(seed % 4 == 2 || seed % 4 == 3)) return;\n\n        for (int t = 0; t < 2; t++) {\n            vector<int> add;\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    for (int z = 1; z + 1 < D; z++) {\n                        int q = id(x, y, z);\n                        if (occ[t][q]) continue;\n                        if (!feasible(t, x, y, z)) continue;\n                        if (occ[t][id(x, y, z - 1)] && occ[t][id(x, y, z + 1)]) {\n                            add.push_back(q);\n                        }\n                    }\n                }\n            }\n\n            if (seed > 0) shuffle(add.begin(), add.end(), rng);\n\n            int limit = max(1, D / 2);\n            if (seed % 4 == 3) limit = D;\n\n            for (int i = 0; i < (int)add.size() && i < limit; i++) {\n                occ[t][add[i]] = 1;\n            }\n        }\n    };\n\n    auto build_occ_independent = [&](int seed) {\n        vector<vector<int>> occ(2, vector<int>(N3, 0));\n        mt19937 rng(1234567 + seed * 10007);\n\n        bool backward = (seed % 6 == 5);\n\n        for (int t = 0; t < 2; t++) {\n            vector<pair<int, int>> prev_pairs;\n\n            for (int zi = 0; zi < D; zi++) {\n                int z = backward ? (D - 1 - zi) : zi;\n                fill_layer_independent(occ[t], t, z, prev_pairs, seed + t * 31, rng);\n            }\n        }\n\n        add_gap_bridges(occ, seed, rng);\n        add_vertical_extensions(occ, seed, rng);\n\n        return occ;\n    };\n\n    auto build_occ_coordinated = [&](int seed) {\n        vector<vector<int>> occ(2, vector<int>(N3, 0));\n        mt19937 rng(7654321 + seed * 20011);\n\n        bool backward = (seed % 2);\n\n        vector<pair<int,int>> prev_common;\n        vector<pair<int,int>> prev_pairs[2];\n\n        for (int zi = 0; zi < D; zi++) {\n            int z = backward ? (D - 1 - zi) : zi;\n\n            vector<int> hasX[2], hasY[2], coveredX[2], coveredY[2];\n            for (int t = 0; t < 2; t++) {\n                hasX[t].assign(D, 0);\n                hasY[t].assign(D, 0);\n                coveredX[t].assign(D, 0);\n                coveredY[t].assign(D, 0);\n\n                for (int x = 0; x < D; x++) if (f[t][z][x] == '1') hasX[t][x] = 1;\n                for (int y = 0; y < D; y++) if (r[t][z][y] == '1') hasY[t][y] = 1;\n            }\n\n            vector<pair<int,int>> cur_common;\n\n            auto add_common = [&](int x, int y) {\n                bool ok = true;\n                for (int t = 0; t < 2; t++) {\n                    if (!(hasX[t][x] && hasY[t][y])) ok = false;\n                }\n                if (!ok) return false;\n\n                for (int t = 0; t < 2; t++) {\n                    occ[t][id(x, y, z)] = 1;\n                    coveredX[t][x] = 1;\n                    coveredY[t][y] = 1;\n                }\n                cur_common.push_back({x, y});\n                return true;\n            };\n\n            vector<pair<int,int>> pp = prev_common;\n            if (seed % 3) shuffle(pp.begin(), pp.end(), rng);\n\n            set<pair<int,int>> used_common;\n\n            for (auto [x, y] : pp) {\n                if (used_common.count({x,y})) continue;\n                bool useful = false;\n                for (int t = 0; t < 2; t++) {\n                    if (!coveredX[t][x] && !coveredY[t][y]) useful = true;\n                }\n                if (useful && add_common(x, y)) used_common.insert({x,y});\n            }\n\n            vector<pair<int,int>> cand;\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    if (hasX[0][x] && hasY[0][y] && hasX[1][x] && hasY[1][y]) {\n                        cand.push_back({x, y});\n                    }\n                }\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n\n            sort(cand.begin(), cand.end(), [&](auto a, auto b) {\n                auto gain = [&](pair<int,int> p) {\n                    int x = p.first, y = p.second;\n                    int g = 0;\n                    for (int t = 0; t < 2; t++) {\n                        if (!coveredX[t][x]) g++;\n                        if (!coveredY[t][y]) g++;\n                    }\n                    return g;\n                };\n                return gain(a) > gain(b);\n            });\n\n            for (auto [x, y] : cand) {\n                if (used_common.count({x,y})) continue;\n                int gain = 0;\n                for (int t = 0; t < 2; t++) {\n                    if (!coveredX[t][x]) gain++;\n                    if (!coveredY[t][y]) gain++;\n                }\n                if (gain >= 3 || (gain >= 2 && seed % 2 == 0)) {\n                    if (add_common(x, y)) used_common.insert({x,y});\n                }\n            }\n\n            for (int t = 0; t < 2; t++) {\n                fill_layer_independent(occ[t], t, z, prev_pairs[t], seed + 17 + t * 31, rng);\n            }\n\n            cur_common.clear();\n            for (int x = 0; x < D; x++) {\n                for (int y = 0; y < D; y++) {\n                    if (occ[0][id(x,y,z)] && occ[1][id(x,y,z)]) {\n                        cur_common.push_back({x,y});\n                    }\n                }\n            }\n            prev_common = cur_common;\n        }\n\n        add_gap_bridges(occ, seed, rng);\n        add_vertical_extensions(occ, seed, rng);\n\n        return occ;\n    };\n\n    auto solve_for_occ = [&](const vector<vector<int>>& occ, int seed, int variant) {\n        vector<vector<int>> ans(2, vector<int>(N3, 0));\n        int block_id = 0;\n        mt19937 rng(9876543 + seed * 101 + variant * 1000003);\n\n        auto inside = [&](int x, int y, int z) {\n            return 0 <= x && x < D && 0 <= y && y < D && 0 <= z && z < D;\n        };\n\n        auto can_cell = [&](int t, int x, int y, int z) {\n            return inside(x, y, z) && occ[t][id(x, y, z)] && ans[t][id(x, y, z)] == 0;\n        };\n\n        auto can_segment = [&](int t, int x, int y, int z, int dir, int len) {\n            for (int k = 0; k < len; k++) {\n                int nx = x + dx[dir] * k;\n                int ny = y + dy[dir] * k;\n                int nz = z + dz[dir] * k;\n                if (!can_cell(t, nx, ny, nz)) return false;\n            }\n            return true;\n        };\n\n        auto run_length = [&](int t, int x, int y, int z, int dir) {\n            int len = 0;\n            while (true) {\n                int nx = x + dx[dir] * len;\n                int ny = y + dy[dir] * len;\n                int nz = z + dz[dir] * len;\n                if (!can_cell(t, nx, ny, nz)) break;\n                len++;\n            }\n            return len;\n        };\n\n        auto place_segment = [&](int t, int x, int y, int z, int dir, int len, int bid) {\n            for (int k = 0; k < len; k++) {\n                int nx = x + dx[dir] * k;\n                int ny = y + dy[dir] * k;\n                int nz = z + dz[dir] * k;\n                ans[t][id(nx, ny, nz)] = bid;\n            }\n        };\n\n        auto extract_segments_range = [&](int max_len, int min_len) {\n            for (int len = max_len; len >= min_len; len--) {\n                bool updated = true;\n\n                while (updated) {\n                    updated = false;\n\n                    vector<Seg> segs[2];\n\n                    for (int t = 0; t < 2; t++) {\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                                    for (int dir = 0; dir < 3; dir++) {\n                                        if (!can_segment(t, x, y, z, dir, len)) continue;\n\n                                        int px = x - dx[dir];\n                                        int py = y - dy[dir];\n                                        int pz = z - dz[dir];\n\n                                        bool is_start = !can_cell(t, px, py, pz);\n                                        int run = run_length(t, x, y, z, dir);\n\n                                        if (is_start || run == len) {\n                                            segs[t].push_back({x, y, z, dir, run});\n                                        } else if (seed % 3 == 0) {\n                                            segs[t].push_back({x, y, z, dir, run});\n                                        }\n                                    }\n                                }\n                            }\n                        }\n                    }\n\n                    if (segs[0].empty() || segs[1].empty()) continue;\n\n                    shuffle(segs[0].begin(), segs[0].end(), rng);\n                    shuffle(segs[1].begin(), segs[1].end(), rng);\n\n                    for (int t = 0; t < 2; t++) {\n                        stable_sort(segs[t].begin(), segs[t].end(), [](const Seg& a, const Seg& b) {\n                            return a.run > b.run;\n                        });\n                    }\n\n                    size_t p0 = 0, p1 = 0;\n\n                    while (p0 < segs[0].size() && p1 < segs[1].size()) {\n                        while (p0 < segs[0].size() &&\n                               !can_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z,\n                                            segs[0][p0].dir, len)) {\n                            p0++;\n                        }\n\n                        while (p1 < segs[1].size() &&\n                               !can_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z,\n                                            segs[1][p1].dir, len)) {\n                            p1++;\n                        }\n\n                        if (p0 >= segs[0].size() || p1 >= segs[1].size()) break;\n\n                        block_id++;\n                        place_segment(0, segs[0][p0].x, segs[0][p0].y, segs[0][p0].z,\n                                      segs[0][p0].dir, len, block_id);\n                        place_segment(1, segs[1][p1].x, segs[1][p1].y, segs[1][p1].z,\n                                      segs[1][p1].dir, len, block_id);\n\n                        updated = true;\n                        p0++;\n                        p1++;\n                    }\n                }\n            }\n        };\n\n        auto match_squares = [&]() {\n            auto find_squares = [&](int t) {\n                vector<Square> sqs;\n\n                for (int x = 0; x + 1 < D; x++) {\n                    for (int y = 0; y + 1 < D; y++) {\n                        for (int z = 0; z < D; z++) {\n                            int q0 = id(x, y, z);\n                            int q1 = id(x + 1, y, z);\n                            int q2 = id(x, y + 1, z);\n                            int q3 = id(x + 1, y + 1, z);\n                            if (ans[t][q0] == 0 && ans[t][q1] == 0 && ans[t][q2] == 0 && ans[t][q3] == 0 &&\n                                occ[t][q0] && occ[t][q1] && occ[t][q2] && occ[t][q3]) {\n                                sqs.push_back({q0, q1, q2, q3});\n                            }\n                        }\n                    }\n                }\n\n                for (int x = 0; x + 1 < D; x++) {\n                    for (int y = 0; y < D; y++) {\n                        for (int z = 0; z + 1 < D; z++) {\n                            int q0 = id(x, y, z);\n                            int q1 = id(x + 1, y, z);\n                            int q2 = id(x, y, z + 1);\n                            int q3 = id(x + 1, y, z + 1);\n                            if (ans[t][q0] == 0 && ans[t][q1] == 0 && ans[t][q2] == 0 && ans[t][q3] == 0 &&\n                                occ[t][q0] && occ[t][q1] && occ[t][q2] && occ[t][q3]) {\n                                sqs.push_back({q0, q1, q2, q3});\n                            }\n                        }\n                    }\n                }\n\n                for (int x = 0; x < D; x++) {\n                    for (int y = 0; y + 1 < D; y++) {\n                        for (int z = 0; z + 1 < D; z++) {\n                            int q0 = id(x, y, z);\n                            int q1 = id(x, y + 1, z);\n                            int q2 = id(x, y, z + 1);\n                            int q3 = id(x, y + 1, z + 1);\n                            if (ans[t][q0] == 0 && ans[t][q1] == 0 && ans[t][q2] == 0 && ans[t][q3] == 0 &&\n                                occ[t][q0] && occ[t][q1] && occ[t][q2] && occ[t][q3]) {\n                                sqs.push_back({q0, q1, q2, q3});\n                            }\n                        }\n                    }\n                }\n\n                shuffle(sqs.begin(), sqs.end(), rng);\n                return sqs;\n            };\n\n            auto square_free = [&](int t, const Square& s) {\n                for (int i = 0; i < 4; i++) {\n                    if (ans[t][s.q[i]] != 0) return false;\n                }\n                return true;\n            };\n\n            vector<Square> sq0 = find_squares(0);\n            vector<Square> sq1 = find_squares(1);\n\n            size_t s0 = 0, s1 = 0;\n\n            while (s0 < sq0.size() && s1 < sq1.size()) {\n                while (s0 < sq0.size() && !square_free(0, sq0[s0])) s0++;\n                while (s1 < sq1.size() && !square_free(1, sq1[s1])) s1++;\n\n                if (s0 >= sq0.size() || s1 >= sq1.size()) break;\n\n                block_id++;\n                for (int i = 0; i < 4; i++) {\n                    ans[0][sq0[s0].q[i]] = block_id;\n                    ans[1][sq1[s1].q[i]] = block_id;\n                }\n\n                s0++;\n                s1++;\n            }\n        };\n\n        if (variant == 0) {\n            extract_segments_range(D, 3);\n            match_squares();\n            extract_segments_range(2, 2);\n        } else if (variant == 1) {\n            extract_segments_range(D, 2);\n            match_squares();\n        } else {\n            match_squares();\n            extract_segments_range(D, 2);\n        }\n\n        vector<int> rem[2];\n\n        for (int t = 0; t < 2; t++) {\n            for (int q = 0; q < N3; q++) {\n                if (occ[t][q] && ans[t][q] == 0) {\n                    rem[t].push_back(q);\n                }\n            }\n        }\n\n        int common_units = min((int)rem[0].size(), (int)rem[1].size());\n\n        for (int i = 0; i < common_units; i++) {\n            block_id++;\n            ans[0][rem[0][i]] = block_id;\n            ans[1][rem[1][i]] = block_id;\n        }\n\n        for (int i = common_units; i < (int)rem[0].size(); i++) {\n            block_id++;\n            ans[0][rem[0][i]] = block_id;\n        }\n\n        for (int i = common_units; i < (int)rem[1].size(); i++) {\n            block_id++;\n            ans[1][rem[1][i]] = block_id;\n        }\n\n        vector<int> vol0(block_id + 1, 0), vol1(block_id + 1, 0);\n        vector<int> used0(block_id + 1, 0), used1(block_id + 1, 0);\n\n        for (int q = 0; q < N3; q++) {\n            int b0 = ans[0][q];\n            if (b0) {\n                vol0[b0]++;\n                used0[b0] = 1;\n            }\n            int b1 = ans[1][q];\n            if (b1) {\n                vol1[b1]++;\n                used1[b1] = 1;\n            }\n        }\n\n        double eval = 0.0;\n        for (int b = 1; b <= block_id; b++) {\n            int v = max(vol0[b], vol1[b]);\n            if (used0[b] && used1[b]) {\n                eval += 1.0 / v;\n            } else if (used0[b]) {\n                eval += v;\n            } else if (used1[b]) {\n                eval += v;\n            }\n        }\n\n        return Result{ans, eval, block_id};\n    };\n\n    auto start_time = chrono::steady_clock::now();\n\n    Result best;\n    best.eval = 1e100;\n    best.n = 0;\n\n    int seed = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n\n        if (seed > 0 && elapsed > 5.65) break;\n        if (seed >= 145) break;\n\n        vector<vector<int>> occ;\n\n        if (seed % 3 == 2) {\n            occ = build_occ_coordinated(seed);\n        } else {\n            occ = build_occ_independent(seed);\n        }\n\n        auto res0 = solve_for_occ(occ, seed, 0);\n        if (res0.eval < best.eval) best = move(res0);\n\n        now = chrono::steady_clock::now();\n        elapsed = chrono::duration<double>(now - start_time).count();\n\n        if (elapsed < 5.20 && seed < 30) {\n            auto res1 = solve_for_occ(occ, seed, 1);\n            if (res1.eval < best.eval) best = move(res1);\n\n            auto res2 = solve_for_occ(occ, seed, 2);\n            if (res2.eval < best.eval) best = move(res2);\n        }\n\n        seed++;\n    }\n\n    cout << best.n << '\\n';\n\n    for (int t = 0; t < 2; t++) {\n        for (int q = 0; q < N3; q++) {\n            if (q) cout << ' ';\n            cout << best.ans[t][q];\n        }\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int u, v;\n    long long w;\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n=0){ init(n); }\n    void init(int n){\n        p.resize(n);\n        sz.assign(n,1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x){\n        while(p[x]!=x){\n            p[x]=p[p[x]];\n            x=p[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(sz[a]<sz[b]) swap(a,b);\n        p[b]=a;\n        sz[a]+=sz[b];\n        return true;\n    }\n};\n\nstatic inline long long sqdist(long long x1,long long y1,long long x2,long long y2){\n    long long dx=x1-x2, dy=y1-y2;\n    return dx*dx+dy*dy;\n}\n\nstruct Solver {\n    int N, M, K;\n    vector<int> x, y, a, b;\n    vector<Edge> edges;\n    vector<vector<pair<int,int>>> g;\n\n    vector<vector<int>> d2;\n    vector<vector<pair<int,int>>> cand;\n\n    vector<vector<long long>> dist;\n    vector<vector<int>> prevEdge, prevNode;\n\n    vector<int> bestP, bestB;\n    long long bestCost = (1LL<<62);\n\n    chrono::steady_clock::time_point st;\n    double timeLimit = 1.93;\n\n    bool time_ok() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count() < timeLimit;\n    }\n\n    int ceil_sqrt_int(int val) const {\n        int r=(int)ceil(sqrt((double)val));\n        while(1LL*r*r < val) r++;\n        while(r>0 && 1LL*(r-1)*(r-1) >= val) r--;\n        return r;\n    }\n\n    long long calc_cost(const vector<int>& P, const vector<int>& B) const {\n        long long s=0;\n        for(int p:P) s += 1LL*p*p;\n        for(int i=0;i<M;i++) if(B[i]) s += edges[i].w;\n        return s;\n    }\n\n    void add_path(vector<int>& B, int s, int t) const {\n        int cur=t;\n        while(cur!=s){\n            int ei=prevEdge[s][cur];\n            if(ei<0) break;\n            B[ei]=1;\n            cur=prevNode[s][cur];\n        }\n    }\n\n    void prune_edges(const vector<int>& P, vector<int>& B) const {\n        vector<vector<pair<int,int>>> tg(N);\n        vector<int> deg(N,0);\n        for(int i=0;i<M;i++) if(B[i]){\n            int u=edges[i].u, v=edges[i].v;\n            tg[u].push_back({v,i});\n            tg[v].push_back({u,i});\n            deg[u]++; deg[v]++;\n        }\n\n        queue<int> q;\n        for(int i=1;i<N;i++){\n            if(P[i]==0 && deg[i]==1) q.push(i);\n        }\n\n        while(!q.empty()){\n            int v=q.front(); q.pop();\n            if(v==0 || P[v]>0 || deg[v]!=1) continue;\n\n            int rem=-1, to=-1;\n            for(auto [nv,ei]: tg[v]){\n                if(B[ei]){\n                    rem=ei;\n                    to=nv;\n                    break;\n                }\n            }\n            if(rem<0) continue;\n\n            B[rem]=0;\n            deg[v]--;\n            deg[to]--;\n            if(to!=0 && P[to]==0 && deg[to]==1) q.push(to);\n        }\n    }\n\n    vector<int> build_edges_root_union(const vector<int>& P) const {\n        vector<int> B(M,0);\n        for(int i=0;i<N;i++){\n            if(P[i]>0) add_path(B,0,i);\n        }\n        prune_edges(P,B);\n        return B;\n    }\n\n    vector<int> build_edges_metric_mst(const vector<int>& P) const {\n        vector<int> terminals;\n        terminals.push_back(0);\n        for(int i=1;i<N;i++) if(P[i]>0) terminals.push_back(i);\n\n        vector<int> B(M,0);\n        int T=terminals.size();\n        if(T<=1) return B;\n\n        struct ME {\n            long long w;\n            int i,j;\n            bool operator<(const ME& o) const { return w<o.w; }\n        };\n\n        vector<ME> es;\n        es.reserve(T*T/2);\n        for(int i=0;i<T;i++){\n            for(int j=i+1;j<T;j++){\n                es.push_back({dist[terminals[i]][terminals[j]], i, j});\n            }\n        }\n        sort(es.begin(),es.end());\n\n        DSU dsu(T);\n        int used=0;\n        for(auto &e: es){\n            if(dsu.unite(e.i,e.j)){\n                add_path(B,terminals[e.i],terminals[e.j]);\n                used++;\n                if(used==T-1) break;\n            }\n        }\n\n        prune_edges(P,B);\n        return B;\n    }\n\n    vector<int> best_edges_for_P(const vector<int>& P) const {\n        vector<int> b1=build_edges_metric_mst(P);\n        long long c1=calc_cost(P,b1);\n\n        vector<int> b2=build_edges_root_union(P);\n        long long c2=calc_cost(P,b2);\n\n        return (c2<c1 ? b2 : b1);\n    }\n\n    long long total_cost_for_P(const vector<int>& P) const {\n        vector<int> B=best_edges_for_P(P);\n        return calc_cost(P,B);\n    }\n\n    vector<int> recomputeP_from_assigned(const vector<vector<int>>& assigned) const {\n        vector<int> P(N,0);\n        for(int i=0;i<N;i++){\n            int md=0;\n            for(int k: assigned[i]) md=max(md,d2[i][k]);\n            P[i]=ceil_sqrt_int(md);\n            if(P[i]>5000) P[i]=5000;\n        }\n        return P;\n    }\n\n    bool all_covered(const vector<int>& P) const {\n        for(int k=0;k<K;k++){\n            bool ok=false;\n            for(int i=0;i<N;i++){\n                if(P[i]>0 && 1LL*P[i]*P[i]>=d2[i][k]){\n                    ok=true;\n                    break;\n                }\n            }\n            if(!ok) return false;\n        }\n        return true;\n    }\n\n    vector<int> coverage_count(const vector<int>& P) const {\n        vector<int> cnt(K,0);\n        for(int i=0;i<N;i++){\n            if(P[i]==0) continue;\n            long long rr=1LL*P[i]*P[i];\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=rr) cnt[k]++;\n            }\n        }\n        return cnt;\n    }\n\n    void global_reduce(vector<int>& P) const {\n        vector<int> covCnt=coverage_count(P);\n\n        vector<int> ord(N);\n        iota(ord.begin(),ord.end(),0);\n        sort(ord.begin(),ord.end(),[&](int p,int q){\n            return P[p]<P[q];\n        });\n\n        for(int i: ord){\n            if(P[i]==0) continue;\n            long long rr=1LL*P[i]*P[i];\n\n            bool ok=true;\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=rr && covCnt[k]<=1){\n                    ok=false;\n                    break;\n                }\n            }\n\n            if(ok){\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=rr) covCnt[k]--;\n                }\n                P[i]=0;\n            }\n        }\n\n        ord.clear();\n        for(int i=0;i<N;i++) if(P[i]>0) ord.push_back(i);\n        sort(ord.begin(),ord.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        for(int i: ord){\n            if(P[i]==0) continue;\n\n            vector<int> critical;\n            critical.push_back(0);\n            long long oldrr=1LL*P[i]*P[i];\n\n            for(int k=0;k<K;k++){\n                if(d2[i][k]<=oldrr) critical.push_back(ceil_sqrt_int(d2[i][k]));\n            }\n\n            sort(critical.begin(),critical.end());\n            critical.erase(unique(critical.begin(),critical.end()),critical.end());\n\n            int best=P[i];\n            for(int idx=(int)critical.size()-1; idx>=0; idx--){\n                int r=critical[idx];\n                long long nrr=1LL*r*r;\n\n                bool ok=true;\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=oldrr && d2[i][k]>nrr && covCnt[k]<=1){\n                        ok=false;\n                        break;\n                    }\n                }\n\n                if(ok) best=r;\n                else break;\n            }\n\n            if(best<P[i]){\n                long long nrr=1LL*best*best;\n                for(int k=0;k<K;k++){\n                    if(d2[i][k]<=oldrr && d2[i][k]>nrr) covCnt[k]--;\n                }\n                P[i]=best;\n            }\n        }\n    }\n\n    void repair_uncovered(vector<int>& P, int maxCand=45) const {\n        (void)maxCand;\n\n        while(true){\n            vector<int> uncovered;\n            uncovered.reserve(K);\n\n            for(int k=0;k<K;k++){\n                bool ok=false;\n                for(int i=0;i<N;i++){\n                    if(P[i]>0 && 1LL*P[i]*P[i]>=d2[i][k]){\n                        ok=true;\n                        break;\n                    }\n                }\n                if(!ok) uncovered.push_back(k);\n            }\n\n            if(uncovered.empty()) break;\n\n            long long bestVal=(1LL<<62);\n            int bestI=-1;\n            int bestNewR=0;\n\n            for(int i=0;i<N;i++){\n                vector<pair<int,int>> ds;\n                ds.reserve(uncovered.size());\n\n                for(int k: uncovered){\n                    if(d2[i][k] <= 5000LL*5000LL){\n                        ds.push_back({d2[i][k],k});\n                    }\n                }\n                if(ds.empty()) continue;\n\n                sort(ds.begin(),ds.end());\n\n                int gain=0;\n                for(int p=0;p<(int)ds.size();p++){\n                    gain++;\n                    int dd=ds[p].first;\n                    if(p+1<(int)ds.size() && ds[p+1].first==dd) continue;\n\n                    int nr=max(P[i],ceil_sqrt_int(dd));\n                    if(nr>5000) continue;\n\n                    long long inc=1LL*nr*nr - 1LL*P[i]*P[i];\n                    if(P[i]==0) inc += dist[0][i]/7;\n\n                    long long val = inc / max(1,gain) - 20LL*gain;\n\n                    if(val<bestVal){\n                        bestVal=val;\n                        bestI=i;\n                        bestNewR=nr;\n                    }\n                }\n            }\n\n            if(bestI<0){\n                int k=uncovered[0];\n                int bi=cand[k][0].second;\n                P[bi]=max(P[bi],ceil_sqrt_int(d2[bi][k]));\n                P[bi]=min(P[bi],5000);\n            }else{\n                P[bestI]=bestNewR;\n            }\n        }\n    }\n\n    bool distributed_repair_from_need(vector<int>& NP, const vector<int>& need, int removedA=-1, int removedB=-1) const {\n        vector<int> order=need;\n\n        sort(order.begin(),order.end(),[&](int p,int q){\n            return cand[p][0].first > cand[q][0].first;\n        });\n\n        for(int k: order){\n            bool already=false;\n            for(int i=0;i<N;i++){\n                if(NP[i]>0 && 1LL*NP[i]*NP[i]>=d2[i][k]){\n                    already=true;\n                    break;\n                }\n            }\n            if(already) continue;\n\n            long long bestInc=(1LL<<60);\n            int bestI=-1, bestR=0;\n\n            int lim=min(25,(int)cand[k].size());\n            for(int z=0; z<lim; z++){\n                int i=cand[k][z].second;\n                if(i==removedA || i==removedB) continue;\n\n                int nr=max(NP[i],ceil_sqrt_int(d2[i][k]));\n                if(nr>5000) continue;\n\n                long long inc=1LL*nr*nr-1LL*NP[i]*NP[i];\n                if(NP[i]==0) inc += dist[0][i]/6;\n\n                if(inc<bestInc){\n                    bestInc=inc;\n                    bestI=i;\n                    bestR=nr;\n                }\n            }\n\n            if(bestI<0) return false;\n            NP[bestI]=bestR;\n        }\n        return true;\n    }\n\n    void drop_repair_local_search(vector<int>& P){\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        for(int pass=0; pass<2 && time_ok(); pass++){\n            bool improved=false;\n\n            vector<int> active;\n            for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n            sort(active.begin(),active.end(),[&](int p,int q){\n                long long cp=1LL*P[p]*P[p]+dist[0][p]/5;\n                long long cq=1LL*P[q]*P[q]+dist[0][q]/5;\n                return cp>cq;\n            });\n\n            int trials=0;\n            for(int rem: active){\n                if(!time_ok()) return;\n                if(P[rem]==0) continue;\n                if(++trials>75) break;\n\n                vector<int> NP=P;\n                NP[rem]=0;\n                repair_uncovered(NP,50);\n                global_reduce(NP);\n\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    improved=true;\n                }\n            }\n\n            if(!improved) break;\n        }\n    }\n\n    void expand_to_remove(vector<int>& P){\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        int tested=0;\n        for(int rem: active){\n            if(!time_ok() || tested>70) break;\n            tested++;\n            if(P[rem]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> needResidents;\n            long long rrem=1LL*P[rem]*P[rem];\n\n            for(int k=0;k<K;k++){\n                if(d2[rem][k]<=rrem && covCnt[k]==1) needResidents.push_back(k);\n            }\n\n            if(needResidents.empty()){\n                P[rem]=0;\n                global_reduce(P);\n                base=total_cost_for_P(P);\n                continue;\n            }\n\n            vector<int> candidates;\n            for(int k: needResidents){\n                int lim=min(10,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int i=cand[k][z].second;\n                    if(i!=rem) candidates.push_back(i);\n                }\n            }\n\n            sort(candidates.begin(),candidates.end());\n            candidates.erase(unique(candidates.begin(),candidates.end()),candidates.end());\n\n            int cnt=0;\n            for(int add: candidates){\n                if(!time_ok() || cnt>30) break;\n                cnt++;\n\n                vector<int> NP=P;\n                NP[rem]=0;\n                int nr=NP[add];\n\n                bool ok=true;\n                for(int k: needResidents){\n                    nr=max(nr,ceil_sqrt_int(d2[add][k]));\n                    if(nr>5000){\n                        ok=false;\n                        break;\n                    }\n                }\n\n                if(!ok) continue;\n\n                NP[add]=nr;\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    break;\n                }\n            }\n        }\n    }\n\n    void try_station_relocation(vector<int>& P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            return P[p]>P[q];\n        });\n\n        int tested=0;\n        for(int old: active){\n            if(!time_ok() || tested>60) break;\n            tested++;\n            if(P[old]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> uniqueResidents;\n            long long rr=1LL*P[old]*P[old];\n\n            for(int k=0;k<K;k++){\n                if(d2[old][k]<=rr && covCnt[k]==1) uniqueResidents.push_back(k);\n            }\n\n            if(uniqueResidents.empty()){\n                vector<int> NP=P;\n                NP[old]=0;\n                global_reduce(NP);\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                }\n                continue;\n            }\n\n            vector<int> candidateStations;\n            for(int k: uniqueResidents){\n                int lim=min(8,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni!=old) candidateStations.push_back(ni);\n                }\n            }\n\n            sort(candidateStations.begin(),candidateStations.end());\n            candidateStations.erase(unique(candidateStations.begin(),candidateStations.end()),candidateStations.end());\n\n            int cnt=0;\n            for(int ni: candidateStations){\n                if(!time_ok() || cnt>20) break;\n                cnt++;\n\n                vector<int> NP=P;\n                NP[old]=0;\n                int need=NP[ni];\n\n                bool ok=true;\n                for(int k: uniqueResidents){\n                    need=max(need,ceil_sqrt_int(d2[ni][k]));\n                    if(need>5000){\n                        ok=false;\n                        break;\n                    }\n                }\n\n                if(!ok) continue;\n\n                NP[ni]=need;\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                    break;\n                }\n            }\n        }\n    }\n\n    void remove_station_distributed_repair(vector<int>& P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            long long cp=1LL*P[p]*P[p]+dist[0][p]/4;\n            long long cq=1LL*P[q]*P[q]+dist[0][q]/4;\n            return cp>cq;\n        });\n\n        int tried=0;\n        for(int rem: active){\n            if(!time_ok() || tried>50) break;\n            tried++;\n            if(P[rem]==0) continue;\n\n            vector<int> covCnt=coverage_count(P);\n            vector<int> need;\n            long long rr=1LL*P[rem]*P[rem];\n\n            for(int k=0;k<K;k++){\n                if(d2[rem][k]<=rr && covCnt[k]==1) need.push_back(k);\n            }\n\n            if(need.empty()){\n                vector<int> NP=P;\n                NP[rem]=0;\n                global_reduce(NP);\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                }\n                continue;\n            }\n\n            vector<int> NP=P;\n            NP[rem]=0;\n\n            if(!distributed_repair_from_need(NP,need,rem,-1)) continue;\n\n            global_reduce(NP);\n            if(!all_covered(NP)) continue;\n\n            long long nc=total_cost_for_P(NP);\n            if(nc<base){\n                P=NP;\n                base=nc;\n            }\n        }\n    }\n\n    void remove_two_stations_repair(vector<int>& P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        long long base=total_cost_for_P(P);\n\n        vector<int> active;\n        for(int i=0;i<N;i++) if(P[i]>0) active.push_back(i);\n\n        sort(active.begin(),active.end(),[&](int p,int q){\n            long long cp=1LL*P[p]*P[p]+dist[0][p]/4;\n            long long cq=1LL*P[q]*P[q]+dist[0][q]/4;\n            return cp>cq;\n        });\n\n        int L=min(18,(int)active.size());\n        int tried=0;\n\n        for(int ai=0; ai<L && time_ok(); ai++){\n            int r1=active[ai];\n            if(P[r1]==0) continue;\n\n            for(int aj=ai+1; aj<L && time_ok(); aj++){\n                if(++tried>70) return;\n                int r2=active[aj];\n                if(P[r2]==0) continue;\n\n                vector<int> NP=P;\n                NP[r1]=0;\n                NP[r2]=0;\n\n                vector<int> need;\n                for(int k=0;k<K;k++){\n                    bool ok=false;\n                    for(int i=0;i<N;i++){\n                        if(i==r1 || i==r2) continue;\n                        if(NP[i]>0 && 1LL*NP[i]*NP[i]>=d2[i][k]){\n                            ok=true;\n                            break;\n                        }\n                    }\n                    if(!ok) need.push_back(k);\n                }\n\n                if(need.empty()){\n                    global_reduce(NP);\n                    long long nc=total_cost_for_P(NP);\n                    if(nc<base){\n                        P=NP;\n                        base=nc;\n                    }\n                    continue;\n                }\n\n                if((int)need.size()>350) continue;\n\n                if(!distributed_repair_from_need(NP,need,r1,r2)) continue;\n\n                global_reduce(NP);\n                if(!all_covered(NP)) continue;\n\n                long long nc=total_cost_for_P(NP);\n                if(nc<base){\n                    P=NP;\n                    base=nc;\n                }\n            }\n        }\n    }\n\n    void refine_assignment(vector<vector<int>>& assigned, vector<int>& assign){\n        for(int outer=0; outer<7 && time_ok(); outer++){\n            vector<int> curMax(N,0), secondMax(N,0), cntMax(N,0);\n\n            for(int i=0;i<N;i++){\n                for(int k: assigned[i]){\n                    int dd=d2[i][k];\n                    if(dd>curMax[i]){\n                        secondMax[i]=curMax[i];\n                        curMax[i]=dd;\n                        cntMax[i]=1;\n                    }else if(dd==curMax[i]){\n                        cntMax[i]++;\n                    }else if(dd>secondMax[i]){\n                        secondMax[i]=dd;\n                    }\n                }\n            }\n\n            bool changed=false;\n            vector<int> order(K);\n            iota(order.begin(),order.end(),0);\n            shuffle(order.begin(),order.end(),mt19937(1234567+outer));\n\n            for(int k: order){\n                int old=assign[k];\n                if(old<0) continue;\n\n                int oldAfter=curMax[old];\n                if(d2[old][k]==curMax[old] && cntMax[old]==1) oldAfter=secondMax[old];\n\n                int oldR=ceil_sqrt_int(curMax[old]);\n                int oldAfterR=ceil_sqrt_int(oldAfter);\n                long long deltaOld=1LL*oldAfterR*oldAfterR-1LL*oldR*oldR;\n\n                long long bestDelta=0;\n                int bestI=old;\n\n                int lim=min(45,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni==old) continue;\n\n                    int r0=ceil_sqrt_int(curMax[ni]);\n                    int r1=ceil_sqrt_int(max(curMax[ni],d2[ni][k]));\n                    long long delta=deltaOld+1LL*r1*r1-1LL*r0*r0;\n\n                    if(assigned[ni].empty()) delta += dist[0][ni]/7;\n                    if(assigned[old].size()==1) delta -= dist[0][old]/7;\n\n                    if(delta<bestDelta){\n                        bestDelta=delta;\n                        bestI=ni;\n                    }\n                }\n\n                if(bestI!=old){\n                    auto &v=assigned[old];\n                    auto it=find(v.begin(),v.end(),k);\n                    if(it!=v.end()) v.erase(it);\n                    assigned[bestI].push_back(k);\n                    assign[k]=bestI;\n                    changed=true;\n                }\n            }\n\n            try_delete_stations(assigned,assign);\n            if(!changed) break;\n        }\n    }\n\n    void try_delete_stations(vector<vector<int>>& assigned, vector<int>& assign){\n        vector<int> stations;\n        for(int i=0;i<N;i++) if(!assigned[i].empty()) stations.push_back(i);\n\n        sort(stations.begin(),stations.end(),[&](int p,int q){\n            return assigned[p].size()<assigned[q].size();\n        });\n\n        int tries=0;\n        for(int rem: stations){\n            if(!time_ok()) return;\n            if(assigned[rem].empty()) continue;\n            if((int)assigned[rem].size()>220) continue;\n            if(++tries>50) break;\n\n            auto backupA=assigned;\n            auto backupAssign=assign;\n\n            vector<int> oldP=recomputeP_from_assigned(assigned);\n            global_reduce(oldP);\n            long long oldCost=total_cost_for_P(oldP);\n\n            vector<int> residents=assigned[rem];\n            assigned[rem].clear();\n\n            bool ok=true;\n            for(int k: residents){\n                long long bestInc=(1LL<<60);\n                int bestI=-1;\n\n                int lim=min(60,(int)cand[k].size());\n                for(int z=0;z<lim;z++){\n                    int ni=cand[k][z].second;\n                    if(ni==rem) continue;\n\n                    int md=0;\n                    for(int kk: assigned[ni]) md=max(md,d2[ni][kk]);\n\n                    int r0=ceil_sqrt_int(md);\n                    int r1=ceil_sqrt_int(max(md,d2[ni][k]));\n                    long long inc=1LL*r1*r1-1LL*r0*r0;\n\n                    if(assigned[ni].empty()) inc += dist[0][ni]/7;\n\n                    if(inc<bestInc){\n                        bestInc=inc;\n                        bestI=ni;\n                    }\n                }\n\n                if(bestI<0){\n                    ok=false;\n                    break;\n                }\n\n                assigned[bestI].push_back(k);\n                assign[k]=bestI;\n            }\n\n            if(ok){\n                vector<int> newP=recomputeP_from_assigned(assigned);\n                global_reduce(newP);\n                long long newCost=total_cost_for_P(newP);\n\n                if(newCost<oldCost) continue;\n            }\n\n            assigned=backupA;\n            assign=backupAssign;\n        }\n    }\n\n    void evaluate_P(vector<int> P){\n        for(int &p:P) p=max(0,min(5000,p));\n\n        repair_uncovered(P);\n        global_reduce(P);\n\n        if(time_ok()) expand_to_remove(P);\n        if(time_ok()) try_station_relocation(P);\n        if(time_ok()) drop_repair_local_search(P);\n        if(time_ok()) remove_station_distributed_repair(P);\n\n        global_reduce(P);\n\n        if(!all_covered(P)) repair_uncovered(P);\n        global_reduce(P);\n\n        vector<int> B=best_edges_for_P(P);\n        long long c=calc_cost(P,B);\n\n        if(c<bestCost){\n            bestCost=c;\n            bestP=P;\n            bestB=B;\n        }\n    }\n\n    void try_final_candidate(vector<int> P){\n        if(!time_ok()) return;\n\n        global_reduce(P);\n        if(!all_covered(P)) repair_uncovered(P);\n        global_reduce(P);\n\n        vector<int> B=best_edges_for_P(P);\n        long long c=calc_cost(P,B);\n\n        if(c<bestCost){\n            bestCost=c;\n            bestP=P;\n            bestB=B;\n        }\n    }\n\n    void final_independent_polish(){\n        if(!time_ok()) return;\n\n        vector<int> base=bestP;\n\n        if(time_ok()){\n            vector<int> P=base;\n            remove_station_distributed_repair(P);\n            try_final_candidate(P);\n        }\n\n        if(time_ok()){\n            vector<int> P=base;\n            remove_two_stations_repair(P);\n            try_final_candidate(P);\n        }\n\n        if(time_ok()){\n            vector<int> P=base;\n            remove_station_distributed_repair(P);\n            if(time_ok()) remove_two_stations_repair(P);\n            try_final_candidate(P);\n        }\n\n        if(time_ok()){\n            vector<int> P=base;\n            remove_two_stations_repair(P);\n            if(time_ok()) remove_station_distributed_repair(P);\n            try_final_candidate(P);\n        }\n    }\n\n    void polish_best(){\n        if(!time_ok()) return;\n\n        vector<int> P=bestP;\n\n        for(int it=0; it<3 && time_ok(); it++){\n            global_reduce(P);\n\n            if(time_ok()) expand_to_remove(P);\n            if(time_ok()) try_station_relocation(P);\n            if(time_ok()) drop_repair_local_search(P);\n            if(time_ok()) remove_station_distributed_repair(P);\n            if(time_ok()) remove_two_stations_repair(P);\n\n            global_reduce(P);\n\n            if(!all_covered(P)) repair_uncovered(P);\n            global_reduce(P);\n\n            vector<int> B=best_edges_for_P(P);\n            long long c=calc_cost(P,B);\n\n            if(c<bestCost){\n                bestCost=c;\n                bestP=P;\n                bestB=B;\n            }else{\n                break;\n            }\n        }\n\n        final_independent_polish();\n    }\n\n    void evaluate_assignment(vector<vector<int>> assigned){\n        vector<int> assign(K,-1);\n        for(int i=0;i<N;i++){\n            for(int k: assigned[i]) assign[k]=i;\n        }\n\n        refine_assignment(assigned,assign);\n\n        vector<int> P=recomputeP_from_assigned(assigned);\n        evaluate_P(P);\n    }\n\n    void build_initial_nearest(){\n        vector<vector<int>> assigned(N);\n        for(int k=0;k<K;k++){\n            assigned[cand[k][0].second].push_back(k);\n        }\n        evaluate_assignment(assigned);\n    }\n\n    void build_initial_marginal(int lim, long long connDiv, int orderMode){\n        vector<vector<int>> assigned(N);\n        vector<int> maxd(N,0);\n\n        vector<int> order(K);\n        iota(order.begin(),order.end(),0);\n\n        if(orderMode==0){\n            sort(order.begin(),order.end(),[&](int p,int q){\n                return cand[p][0].first>cand[q][0].first;\n            });\n        }else if(orderMode==1){\n            sort(order.begin(),order.end(),[&](int p,int q){\n                return cand[p][0].first<cand[q][0].first;\n            });\n        }else{\n            shuffle(order.begin(),order.end(),mt19937(777+orderMode));\n        }\n\n        for(int k: order){\n            long long best=(1LL<<60);\n            int bi=cand[k][0].second;\n\n            int L=min(lim,(int)cand[k].size());\n            for(int z=0;z<L;z++){\n                int i=cand[k][z].second;\n\n                int r0=ceil_sqrt_int(maxd[i]);\n                int r1=ceil_sqrt_int(max(maxd[i],d2[i][k]));\n                long long inc=1LL*r1*r1-1LL*r0*r0;\n\n                if(assigned[i].empty()) inc += dist[0][i]/connDiv;\n\n                if(inc<best){\n                    best=inc;\n                    bi=i;\n                }\n            }\n\n            assigned[bi].push_back(k);\n            maxd[bi]=max(maxd[bi],d2[bi][k]);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void build_initial_setcover(long long connDiv, int radiiStep, double powGain){\n        vector<char> covered(K,0);\n        int remaining=K;\n        vector<vector<int>> assigned(N);\n        vector<int> assign(K,-1);\n\n        vector<int> possibleR;\n        for(int r=250;r<=5000;r+=radiiStep) possibleR.push_back(r);\n        possibleR.push_back(5000);\n        sort(possibleR.begin(),possibleR.end());\n        possibleR.erase(unique(possibleR.begin(),possibleR.end()),possibleR.end());\n\n        for(int iter=0; remaining>0 && iter<180 && time_ok(); iter++){\n            double bestScore=-1;\n            int bestI=-1;\n            vector<int> bestList;\n\n            for(int i=0;i<N;i++){\n                vector<pair<int,int>> ds;\n                ds.reserve(remaining);\n\n                for(int k=0;k<K;k++){\n                    if(!covered[k] && d2[i][k]<=5000LL*5000LL){\n                        ds.push_back({d2[i][k],k});\n                    }\n                }\n\n                if(ds.empty()) continue;\n                sort(ds.begin(),ds.end());\n\n                vector<int> cur;\n                int ptr=0;\n\n                for(int r: possibleR){\n                    int rr=r*r;\n                    while(ptr<(int)ds.size() && ds[ptr].first<=rr){\n                        cur.push_back(ds[ptr].second);\n                        ptr++;\n                    }\n\n                    int gain=cur.size();\n                    if(gain==0) continue;\n\n                    long long cost=1LL*r*r + dist[0][i]/connDiv;\n                    double score=pow((double)gain,powGain)/(double)cost;\n\n                    if(score>bestScore){\n                        bestScore=score;\n                        bestI=i;\n                        bestList=cur;\n                    }\n                }\n            }\n\n            if(bestI<0) break;\n\n            for(int k: bestList){\n                if(!covered[k]){\n                    covered[k]=1;\n                    remaining--;\n                    assign[k]=bestI;\n                    assigned[bestI].push_back(k);\n                }\n            }\n        }\n\n        for(int k=0;k<K;k++){\n            if(assign[k]>=0) continue;\n\n            long long best=(1LL<<60);\n            int bi=cand[k][0].second;\n            int L=min(60,(int)cand[k].size());\n\n            for(int z=0;z<L;z++){\n                int i=cand[k][z].second;\n\n                int md=0;\n                for(int kk: assigned[i]) md=max(md,d2[i][kk]);\n\n                int r0=ceil_sqrt_int(md);\n                int r1=ceil_sqrt_int(max(md,d2[i][k]));\n                long long inc=1LL*r1*r1-1LL*r0*r0;\n\n                if(assigned[i].empty()) inc += dist[0][i]/connDiv;\n\n                if(inc<best){\n                    best=inc;\n                    bi=i;\n                }\n            }\n\n            assign[k]=bi;\n            assigned[bi].push_back(k);\n        }\n\n        evaluate_assignment(assigned);\n    }\n\n    void prepare(){\n        d2.assign(N,vector<int>(K));\n        for(int i=0;i<N;i++){\n            for(int k=0;k<K;k++){\n                d2[i][k]=(int)sqdist(x[i],y[i],a[k],b[k]);\n            }\n        }\n\n        cand.assign(K,{});\n        for(int k=0;k<K;k++){\n            cand[k].reserve(N);\n            for(int i=0;i<N;i++){\n                if(d2[i][k]<=5000LL*5000LL) cand[k].push_back({d2[i][k],i});\n            }\n\n            if(cand[k].empty()){\n                for(int i=0;i<N;i++) cand[k].push_back({d2[i][k],i});\n            }\n\n            sort(cand[k].begin(),cand[k].end());\n        }\n\n        const long long INF=(1LL<<60);\n        dist.assign(N,vector<long long>(N,INF));\n        prevEdge.assign(N,vector<int>(N,-1));\n        prevNode.assign(N,vector<int>(N,-1));\n\n        for(int s=0;s<N;s++){\n            priority_queue<pair<long long,int>,vector<pair<long long,int>>,greater<pair<long long,int>>> pq;\n            dist[s][s]=0;\n            pq.push({0,s});\n\n            while(!pq.empty()){\n                auto [cd,v]=pq.top();\n                pq.pop();\n\n                if(cd!=dist[s][v]) continue;\n\n                for(auto [to,ei]: g[v]){\n                    long long nd=cd+edges[ei].w;\n                    if(nd<dist[s][to]){\n                        dist[s][to]=nd;\n                        prevEdge[s][to]=ei;\n                        prevNode[s][to]=v;\n                        pq.push({nd,to});\n                    }\n                }\n            }\n        }\n    }\n\n    void solve(){\n        st=chrono::steady_clock::now();\n        prepare();\n\n        bestP.assign(N,0);\n        bestB.assign(M,0);\n\n        build_initial_nearest();\n\n        if(time_ok()) build_initial_marginal(12,4,0);\n        if(time_ok()) build_initial_marginal(25,5,0);\n        if(time_ok()) build_initial_marginal(60,7,0);\n        if(time_ok()) build_initial_marginal(100,9,0);\n\n        if(time_ok()) build_initial_marginal(25,5,1);\n        if(time_ok()) build_initial_marginal(50,7,2);\n        if(time_ok()) build_initial_marginal(80,10,3);\n\n        if(time_ok()) build_initial_setcover(5,300,1.35);\n        if(time_ok()) build_initial_setcover(8,450,1.45);\n        if(time_ok()) build_initial_setcover(12,650,1.55);\n\n        polish_best();\n\n        for(int k=0;k<K;k++){\n            bool ok=false;\n            for(int i=0;i<N;i++){\n                if(bestP[i]>0 && 1LL*bestP[i]*bestP[i]>=d2[i][k]){\n                    ok=true;\n                    break;\n                }\n            }\n\n            if(!ok){\n                int bi=cand[k][0].second;\n                bestP[bi]=max(bestP[bi],ceil_sqrt_int(d2[bi][k]));\n                bestP[bi]=min(bestP[bi],5000);\n            }\n        }\n\n        global_reduce(bestP);\n        bestB=best_edges_for_P(bestP);\n    }\n};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    cin >> solver.N >> solver.M >> solver.K;\n\n    solver.x.resize(solver.N);\n    solver.y.resize(solver.N);\n\n    for(int i=0;i<solver.N;i++){\n        cin >> solver.x[i] >> solver.y[i];\n    }\n\n    solver.edges.resize(solver.M);\n    solver.g.assign(solver.N,{});\n\n    for(int i=0;i<solver.M;i++){\n        int u,v;\n        long long w;\n        cin >> u >> v >> w;\n        --u; --v;\n\n        solver.edges[i]={u,v,w};\n        solver.g[u].push_back({v,i});\n        solver.g[v].push_back({u,i});\n    }\n\n    solver.a.resize(solver.K);\n    solver.b.resize(solver.K);\n\n    for(int k=0;k<solver.K;k++){\n        cin >> solver.a[k] >> solver.b[k];\n    }\n\n    solver.solve();\n\n    for(int i=0;i<solver.N;i++){\n        if(i) cout << ' ';\n        cout << solver.bestP[i];\n    }\n    cout << '\\n';\n\n    for(int i=0;i<solver.M;i++){\n        if(i) cout << ' ';\n        cout << solver.bestB[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int M = N * (N + 1) / 2;\nstatic constexpr int LIM = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nbool same_swap(const Op& a, const Op& b) {\n    return a.x1 == b.x1 && a.y1 == b.y1 && a.x2 == b.x2 && a.y2 == b.y2;\n}\n\nstruct Pos {\n    int x, y;\n};\n\nusing Board = array<array<int, N>, N>;\n\nbool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y <= x;\n}\n\nint cell_violation(const Board& a, int x, int y) {\n    if (x < 0 || x >= N - 1 || y < 0 || y > x) return 0;\n    int c = 0;\n    if (a[x][y] > a[x + 1][y]) c++;\n    if (a[x][y] > a[x + 1][y + 1]) c++;\n    return c;\n}\n\nint cell_severity(const Board& a, int x, int y) {\n    if (x < 0 || x >= N - 1 || y < 0 || y > x) return 0;\n    int s = 0;\n    if (a[x][y] > a[x + 1][y]) s += a[x][y] - a[x + 1][y];\n    if (a[x][y] > a[x + 1][y + 1]) s += a[x][y] - a[x + 1][y + 1];\n    return s;\n}\n\nint total_violations(const Board& a) {\n    int e = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) e += cell_violation(a, x, y);\n    }\n    return e;\n}\n\nint total_severity(const Board& a) {\n    int s = 0;\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) s += cell_severity(a, x, y);\n    }\n    return s;\n}\n\nstruct XorShift {\n    uint32_t x;\n    XorShift(uint32_t seed = 123456789) : x(seed) {}\n    uint32_t next() {\n        x ^= x << 13;\n        x ^= x >> 17;\n        x ^= x << 5;\n        return x;\n    }\n    int randint(int n) { return int(next() % n); }\n    double uniform01() { return (next() & 0xffffff) / double(0x1000000); }\n};\n\nstruct Result {\n    bool ok = false;\n    Board board{};\n    vector<Op> ops;\n};\n\nvoid init_pos(const Board& a, array<Pos, M>& pos) {\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) pos[a[x][y]] = {x, y};\n    }\n}\n\nbool do_swap(Board& a, array<Pos, M>& pos, vector<Op>& ops,\n             int x1, int y1, int x2, int y2) {\n    if ((int)ops.size() >= LIM) return false;\n    int v1 = a[x1][y1], v2 = a[x2][y2];\n    swap(a[x1][y1], a[x2][y2]);\n    pos[v1] = {x2, y2};\n    pos[v2] = {x1, y1};\n    ops.push_back({x1, y1, x2, y2});\n    return true;\n}\n\nvector<pair<int,int>> local_cells_around(int x, int y) {\n    vector<pair<int,int>> v;\n    for (int dx = -2; dx <= 1; dx++) {\n        for (int dy = -2; dy <= 2; dy++) {\n            int nx = x + dx, ny = y + dy;\n            if (inside(nx, ny) && nx < N - 1) {\n                if (abs(nx - x) + abs(ny - y) <= 3) v.push_back({nx, ny});\n            }\n        }\n    }\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nvector<pair<int,int>> affected_union(int x1, int y1, int x2, int y2) {\n    auto a = local_cells_around(x1, y1);\n    auto b = local_cells_around(x2, y2);\n    a.insert(a.end(), b.begin(), b.end());\n    sort(a.begin(), a.end());\n    a.erase(unique(a.begin(), a.end()), a.end());\n    return a;\n}\n\nstruct Policy {\n    int order_type;\n    double w_vio;\n    double w_sev;\n    double w_depth;\n    double w_small;\n    uint32_t seed;\n};\n\nResult repair_with_policy(const Board& start_board,\n                          const vector<Op>& prefix,\n                          const Policy& pol) {\n    Board a = start_board;\n    vector<Op> ops = prefix;\n    XorShift rng(pol.seed);\n\n    auto do_swap_simple = [&](int x1, int y1, int x2, int y2) -> bool {\n        if ((int)ops.size() >= LIM) return false;\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n        return true;\n    };\n\n    auto candidate_score = [&](int x1, int y1, int x2, int y2) {\n        auto aff = affected_union(x1, y1, x2, y2);\n\n        int vio_before = 0, sev_before = 0;\n        for (auto [x, y] : aff) {\n            vio_before += cell_violation(a, x, y);\n            sev_before += cell_severity(a, x, y);\n        }\n\n        swap(a[x1][y1], a[x2][y2]);\n\n        int vio_after = 0, sev_after = 0;\n        for (auto [x, y] : aff) {\n            vio_after += cell_violation(a, x, y);\n            sev_after += cell_severity(a, x, y);\n        }\n\n        int moved_up = a[x1][y1];\n        swap(a[x1][y1], a[x2][y2]);\n\n        double score = 0;\n        score += pol.w_vio * double(vio_before - vio_after);\n        score += pol.w_sev * double(sev_before - sev_after);\n        score += pol.w_depth * double(x1);\n        score += pol.w_small * double(464 - moved_up) / 464.0;\n        score += 1e-6 * rng.uniform01();\n        return score;\n    };\n\n    auto repair_cell = [&](int x, int y) -> bool {\n        if (x >= N - 1 || cell_violation(a, x, y) == 0) return false;\n\n        vector<pair<int,int>> cand;\n        if (a[x][y] > a[x + 1][y]) cand.push_back({x + 1, y});\n        if (a[x][y] > a[x + 1][y + 1]) cand.push_back({x + 1, y + 1});\n        if (cand.empty()) return false;\n\n        int bx = cand[0].first, by = cand[0].second;\n        double best_score = -1e100;\n\n        for (auto [cx, cy] : cand) {\n            double sc = candidate_score(x, y, cx, cy);\n            if (sc > best_score) {\n                best_score = sc;\n                bx = cx;\n                by = cy;\n            }\n        }\n\n        return do_swap_simple(x, y, bx, by);\n    };\n\n    int lastE = total_violations(a);\n    int stagnant = 0;\n\n    for (int pass = 0; pass < 600 && (int)ops.size() < LIM; pass++) {\n        int before_ops = ops.size();\n\n        int mode = pol.order_type;\n        if (mode == 2) mode = pass & 1;\n\n        if (mode == 0) {\n            for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (cell_violation(a, x, y)) repair_cell(x, y);\n                }\n            }\n        } else {\n            for (int x = 0; x < N - 1 && (int)ops.size() < LIM; x++) {\n                for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                    if (cell_violation(a, x, y)) repair_cell(x, y);\n                }\n            }\n        }\n\n        int E = total_violations(a);\n        if (E == 0) return {true, a, ops};\n\n        if ((int)ops.size() == before_ops) break;\n        if (E >= lastE) stagnant++;\n        else stagnant = 0;\n        lastE = E;\n        if (stagnant >= 40 && ops.size() > 3500) break;\n    }\n\n    return {total_violations(a) == 0, a, ops};\n}\n\nResult fallback_repair(const Board& start_board, const vector<Op>& prefix) {\n    Board a = start_board;\n    vector<Op> ops = prefix;\n\n    auto do_swap_simple = [&](int x1, int y1, int x2, int y2) -> bool {\n        if ((int)ops.size() >= LIM) return false;\n        swap(a[x1][y1], a[x2][y2]);\n        ops.push_back({x1, y1, x2, y2});\n        return true;\n    };\n\n    using Node = tuple<int,int,int,int>;\n    priority_queue<Node> pq;\n    vector<vector<int>> pushed(N);\n    for (int x = 0; x < N; x++) pushed[x].assign(x + 1, 0);\n    int timer = 0;\n\n    auto push_cell = [&](int x, int y) {\n        if (!inside(x, y) || x >= N - 1) return;\n        int s = cell_severity(a, x, y);\n        if (s <= 0) return;\n        pushed[x][y] = ++timer;\n        pq.emplace(s, pushed[x][y], x, y);\n    };\n\n    for (int x = 0; x < N - 1; x++) {\n        for (int y = 0; y <= x; y++) push_cell(x, y);\n    }\n\n    while (!pq.empty() && (int)ops.size() < LIM) {\n        auto [sold, id, x, y] = pq.top();\n        pq.pop();\n\n        if (id != pushed[x][y]) continue;\n\n        int snow = cell_severity(a, x, y);\n        if (snow <= 0) continue;\n        if (snow != sold) {\n            push_cell(x, y);\n            continue;\n        }\n\n        int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n        if (!(a[x][y] > a[x + 1][by])) continue;\n\n        do_swap_simple(x, y, x + 1, by);\n\n        for (int dx = -2; dx <= 2; dx++) {\n            for (int dy = -2; dy <= 2; dy++) {\n                push_cell(x + dx, y + dy);\n                push_cell(x + 1 + dx, by + dy);\n            }\n        }\n    }\n\n    for (int pass = 0; pass < 600 && total_violations(a) > 0 && (int)ops.size() < LIM; pass++) {\n        for (int x = N - 2; x >= 0 && (int)ops.size() < LIM; x--) {\n            for (int y = 0; y <= x && (int)ops.size() < LIM; y++) {\n                if (cell_violation(a, x, y)) {\n                    int by = (a[x + 1][y] < a[x + 1][y + 1] ? y : y + 1);\n                    do_swap_simple(x, y, x + 1, by);\n                }\n            }\n        }\n    }\n\n    return {total_violations(a) == 0, a, ops};\n}\n\nvector<pair<int,int>> make_shape_cells(int H, int type) {\n    vector<pair<int,int>> cells;\n\n    if (type == 0) {\n        for (int x = 0; x < H; x++) {\n            for (int y = 0; y <= x; y++) cells.push_back({x, y});\n        }\n    } else if (type == 1) {\n        for (int x = 0; x < H; x++) {\n            int w = max(1, (x + 2) / 2);\n            for (int y = 0; y < w; y++) cells.push_back({x, y});\n        }\n    } else if (type == 2) {\n        for (int x = 0; x < H; x++) {\n            int w = max(1, (x + 2) / 2);\n            for (int y = x - w + 1; y <= x; y++) cells.push_back({x, y});\n        }\n    } else if (type == 3) {\n        for (int x = 0; x < H; x++) {\n            cells.push_back({x, 0});\n            if (x > 0) cells.push_back({x, x});\n            if (x >= 3) {\n                cells.push_back({x, 1});\n                cells.push_back({x, x - 1});\n            }\n        }\n    } else if (type == 4) {\n        for (int x = 0; x < H; x++) {\n            int w = max(1, (x + 2) / 2);\n            int l = (x - w + 1) / 2;\n            for (int y = l; y < l + w; y++) cells.push_back({x, y});\n        }\n    } else if (type == 5) {\n        // Alternating parity cells, spread across upper rows.\n        for (int x = 0; x < H; x++) {\n            for (int y = 0; y <= x; y++) {\n                if ((x + y) % 2 == 0) cells.push_back({x, y});\n            }\n        }\n    } else if (type == 6) {\n        // Central spine with near-spine neighbors.\n        for (int x = 0; x < H; x++) {\n            int c = x / 2;\n            cells.push_back({x, c});\n            if (c - 1 >= 0) cells.push_back({x, c - 1});\n            if (c + 1 <= x) cells.push_back({x, c + 1});\n        }\n    } else if (type == 7) {\n        // Sparse every-third spread.\n        for (int x = 0; x < H; x++) {\n            for (int y = 0; y <= x; y++) {\n                if ((y % 3) == (x % 3)) cells.push_back({x, y});\n            }\n        }\n    } else if (type == 8) {\n        // Top few rows full, then sparse alternating.\n        int full = min(H, 4);\n        for (int x = 0; x < H; x++) {\n            for (int y = 0; y <= x; y++) {\n                if (x < full || ((x + y) % 2 == 0)) cells.push_back({x, y});\n            }\n        }\n    }\n\n    sort(cells.begin(), cells.end());\n    cells.erase(unique(cells.begin(), cells.end()), cells.end());\n    sort(cells.begin(), cells.end(), [](auto p, auto q) {\n        if (p.first != q.first) return p.first < q.first;\n        return p.second < q.second;\n    });\n    return cells;\n}\n\nint estimate_path_cost(Pos p, int tx, int ty) {\n    int dx = p.x - tx;\n    if (dx < 0) return abs(p.x - tx) + abs(p.y - ty);\n    int low = p.y - dx;\n    int high = p.y;\n    int extra = 0;\n    if (ty < low) extra = low - ty;\n    else if (ty > high) extra = ty - high;\n    return dx + extra;\n}\n\nResult make_prefix_place_small_cells(const Board& init,\n                                     const vector<pair<int,int>>& targets,\n                                     int candLimit,\n                                     double valuePenalty) {\n    Board a = init;\n    array<Pos, M> pos;\n    init_pos(a, pos);\n\n    vector<Op> ops;\n    vector<vector<bool>> fixed(N);\n    for (int x = 0; x < N; x++) fixed[x].assign(x + 1, false);\n\n    auto swap_fixed = [&](int x1, int y1, int x2, int y2) -> bool {\n        return do_swap(a, pos, ops, x1, y1, x2, y2);\n    };\n\n    for (auto [tx, ty] : targets) {\n        vector<int> candidates;\n        for (int v = 0; v < M && (int)candidates.size() < candLimit; v++) {\n            Pos p = pos[v];\n            if (!fixed[p.x][p.y]) candidates.push_back(v);\n        }\n        if (candidates.empty()) break;\n\n        int chosen = candidates[0];\n        double bestScore = 1e100;\n\n        for (int rank = 0; rank < (int)candidates.size(); rank++) {\n            int v = candidates[rank];\n            Pos p = pos[v];\n            int dist = estimate_path_cost(p, tx, ty);\n            double sc = dist + valuePenalty * rank;\n            if (sc < bestScore) {\n                bestScore = sc;\n                chosen = v;\n            }\n        }\n\n        int cx = pos[chosen].x;\n        int cy = pos[chosen].y;\n\n        while (cx > tx && (int)ops.size() < LIM) {\n            vector<pair<int,int>> cand;\n            if (cy > 0) cand.push_back({cx - 1, cy - 1});\n            if (cy < cx) cand.push_back({cx - 1, cy});\n\n            pair<int,int> nxt = {-1, -1};\n            int bestd = INT_MAX;\n            for (auto [nx, ny] : cand) {\n                if (fixed[nx][ny]) continue;\n                int d = estimate_path_cost({nx, ny}, tx, ty);\n                if (d < bestd) {\n                    bestd = d;\n                    nxt = {nx, ny};\n                }\n            }\n            if (nxt.first == -1) break;\n\n            swap_fixed(cx, cy, nxt.first, nxt.second);\n            cx = nxt.first;\n            cy = nxt.second;\n        }\n\n        while (cy > ty && (int)ops.size() < LIM) {\n            if (fixed[cx][cy - 1]) break;\n            swap_fixed(cx, cy, cx, cy - 1);\n            cy--;\n        }\n        while (cy < ty && (int)ops.size() < LIM) {\n            if (cy + 1 > cx || fixed[cx][cy + 1]) break;\n            swap_fixed(cx, cy, cx, cy + 1);\n            cy++;\n        }\n\n        fixed[tx][ty] = true;\n    }\n\n    return {false, a, ops};\n}\n\nstruct Job {\n    int H;\n    int type;\n    int candLimit;\n    double penalty;\n};\n\nstruct PrefixCand {\n    double rough;\n    Result pref;\n};\n\nvector<Op> cancel_consecutive_pairs(const vector<Op>& ops) {\n    vector<Op> st;\n    st.reserve(ops.size());\n    for (const auto& op : ops) {\n        if (!st.empty() && same_swap(st.back(), op)) st.pop_back();\n        else st.push_back(op);\n    }\n    return st;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto start_time = chrono::steady_clock::now();\n\n    Board init{};\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) cin >> init[x][y];\n    }\n\n    vector<Policy> policies;\n    uint32_t seed = 2463534242u;\n    for (int order = 0; order < 3; order++) {\n        policies.push_back({order, 1000.0, 1.0, 0.0, 0.0, seed += 101});\n        policies.push_back({order, 500.0, 2.0, 0.0, 0.2, seed += 101});\n        policies.push_back({order, 200.0, 5.0, 0.1, 0.0, seed += 101});\n        policies.push_back({order, 100.0, 10.0, 0.2, 0.5, seed += 101});\n        policies.push_back({order, 1000.0, 0.0, 0.0, 1.0, seed += 101});\n    }\n\n    Result best;\n    best.ok = false;\n\n    Result fb0 = fallback_repair(init, {});\n    if (fb0.ok) best = fb0;\n\n    for (int i = 0; i < (int)policies.size(); i++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 0.48) break;\n\n        Result r = repair_with_policy(init, {}, policies[i]);\n        if (r.ok && (!best.ok || r.ops.size() < best.ops.size())) best = move(r);\n    }\n\n    vector<Job> jobs;\n\n    for (int H = 1; H <= 10; H++) jobs.push_back({H, 0, 1, 1000.0});\n\n    for (int H = 2; H <= 11; H++) {\n        jobs.push_back({H, 0, 3, 1.5});\n        jobs.push_back({H, 0, 5, 1.0});\n        jobs.push_back({H, 0, 8, 0.8});\n        jobs.push_back({H, 0, 12, 0.6});\n    }\n\n    for (int H = 3; H <= 13; H++) {\n        for (int type = 1; type <= 4; type++) {\n            jobs.push_back({H, type, 1, 1000.0});\n            jobs.push_back({H, type, 4, 1.0});\n            jobs.push_back({H, type, 8, 0.8});\n        }\n    }\n\n    // New sparse/diverse shapes.\n    for (int H = 5; H <= 15; H++) {\n        for (int type = 5; type <= 8; type++) {\n            jobs.push_back({H, type, 1, 1000.0});\n            jobs.push_back({H, type, 5, 1.0});\n            jobs.push_back({H, type, 10, 0.7});\n        }\n    }\n\n    vector<PrefixCand> prefs;\n    prefs.reserve(jobs.size());\n\n    for (const auto& job : jobs) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.08) break;\n\n        auto targets = make_shape_cells(job.H, job.type);\n        Result pref = make_prefix_place_small_cells(init, targets, job.candLimit, job.penalty);\n\n        if ((int)pref.ops.size() >= (best.ok ? (int)best.ops.size() : LIM)) continue;\n\n        int E = total_violations(pref.board);\n        int S = total_severity(pref.board);\n        double rough = pref.ops.size() + 2.0 * E + 0.002 * S;\n\n        if (job.type == 0) rough -= 20.0;\n        if (job.candLimit == 1) rough -= 5.0;\n        if (job.type >= 5) rough -= 3.0; // slight exploration boost\n\n        prefs.push_back({rough, move(pref)});\n    }\n\n    sort(prefs.begin(), prefs.end(), [](const PrefixCand& a, const PrefixCand& b) {\n        return a.rough < b.rough;\n    });\n\n    for (int idx = 0; idx < (int)prefs.size(); idx++) {\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.88) break;\n\n        Result& pref = prefs[idx].pref;\n        if ((int)pref.ops.size() >= (best.ok ? (int)best.ops.size() : LIM)) continue;\n\n        Result r = fallback_repair(pref.board, pref.ops);\n        if (r.ok && (!best.ok || r.ops.size() < best.ops.size())) best = move(r);\n\n        now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start_time).count() > 1.88) break;\n\n        if (idx < 12 && (int)pref.ops.size() < (best.ok ? (int)best.ops.size() - 120 : LIM)) {\n            Result rp = repair_with_policy(pref.board, pref.ops, policies[0]);\n            if (rp.ok && (!best.ok || rp.ops.size() < best.ops.size())) best = move(rp);\n        }\n    }\n\n    if (!best.ok) best = fb0;\n\n    best.ops = cancel_consecutive_pairs(best.ops);\n\n    cout << best.ops.size() << '\\n';\n    for (auto &op : best.ops) {\n        cout << op.x1 << ' ' << op.y1 << ' ' << op.x2 << ' ' << op.y2 << '\\n';\n    }\n\n    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Cell {\n    int r, c;\n};\n\nint D, N;\nconst int ENTR = 0;\nconst int ENTC = 4;\nconst int MAXM = 80;\n\nbool obstacle_[9][9];\nbool occupied_[9][9];\nint valAt[9][9];\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\n\nchrono::steady_clock::time_point startTime;\n\nbool timeAlmostUp() {\n    auto now = chrono::steady_clock::now();\n    double elapsed = chrono::duration<double>(now - startTime).count();\n    return elapsed > 1.85;\n}\n\nbool inside(int r, int c) {\n    return 0 <= r && r < D && 0 <= c && c < D;\n}\n\nbool isEntrance(int r, int c) {\n    return r == ENTR && c == ENTC;\n}\n\nint popcount128(unsigned __int128 x) {\n    return __builtin_popcountll((unsigned long long)x)\n         + __builtin_popcountll((unsigned long long)(x >> 64));\n}\n\nstruct Key {\n    unsigned long long lo, hi;\n    bool operator==(const Key& o) const {\n        return lo == o.lo && hi == o.hi;\n    }\n};\n\nstruct Hasher {\n    size_t operator()(const Key& k) const {\n        return k.lo ^ (k.hi * 11995408973635179863ULL);\n    }\n};\n\nKey makeKey(unsigned __int128 x) {\n    return Key{(unsigned long long)x, (unsigned long long)(x >> 64)};\n}\n\nvector<vector<int>> reachableEmpty() {\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    queue<pair<int,int>> q;\n\n    if (!obstacle_[ENTR][ENTC] && !occupied_[ENTR][ENTC]) {\n        vis[ENTR][ENTC] = 1;\n        q.push({ENTR, ENTC});\n    }\n\n    while (!q.empty()) {\n        auto [r,c] = q.front();\n        q.pop();\n\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (vis[nr][nc]) continue;\n            if (obstacle_[nr][nc] || occupied_[nr][nc]) continue;\n            vis[nr][nc] = 1;\n            q.push({nr,nc});\n        }\n    }\n\n    return vis;\n}\n\nbool keepsConnectivity(int br, int bc, const vector<Cell>& allCells) {\n    occupied_[br][bc] = true;\n    auto vis = reachableEmpty();\n    occupied_[br][bc] = false;\n\n    for (auto cell : allCells) {\n        int r = cell.r, c = cell.c;\n        if (occupied_[r][c]) continue;\n        if (r == br && c == bc) continue;\n        if (!vis[r][c]) return false;\n    }\n\n    return true;\n}\n\nvector<vector<int>> baseDistance() {\n    vector<vector<int>> dist(D, vector<int>(D, -1));\n    queue<pair<int,int>> q;\n\n    dist[ENTR][ENTC] = 0;\n    q.push({ENTR, ENTC});\n\n    while (!q.empty()) {\n        auto [r,c] = q.front();\n        q.pop();\n\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (obstacle_[nr][nc]) continue;\n            if (dist[nr][nc] != -1) continue;\n            dist[nr][nc] = dist[r][c] + 1;\n            q.push({nr,nc});\n        }\n    }\n\n    return dist;\n}\n\nbool removableContainer(int r, int c, const vector<vector<int>>& emptyReach) {\n    if (!occupied_[r][c]) return false;\n\n    for (int k=0;k<4;k++) {\n        int nr = r + dr[k], nc = c + dc[k];\n        if (!inside(nr,nc)) continue;\n        if (emptyReach[nr][nc]) return true;\n    }\n\n    return false;\n}\n\nint cellIdG[9][9];\nvector<Cell> cellsG;\nvector<int> labelG;\nvector<unsigned __int128> smallerMaskG;\nint KG;\n\nvector<int> reachableEmptyMaskRaw(unsigned __int128 mask) {\n    vector<int> visFlat(D * D, 0);\n    queue<pair<int,int>> q;\n\n    visFlat[ENTR * D + ENTC] = 1;\n    q.push({ENTR, ENTC});\n\n    while (!q.empty()) {\n        auto [r,c] = q.front();\n        q.pop();\n\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n\n            int flat = nr * D + nc;\n            if (visFlat[flat]) continue;\n            if (obstacle_[nr][nc]) continue;\n\n            int id = cellIdG[nr][nc];\n            if (id >= 0 && ((mask >> id) & 1)) continue;\n\n            visFlat[flat] = 1;\n            q.push({nr,nc});\n        }\n    }\n\n    return visFlat;\n}\n\nvector<int> legalMovesMaskRaw(unsigned __int128 mask) {\n    vector<int> reach = reachableEmptyMaskRaw(mask);\n    vector<int> moves;\n\n    for (int id=0; id<KG; id++) {\n        if (((mask >> id) & 1) == 0) continue;\n\n        int r = cellsG[id].r;\n        int c = cellsG[id].c;\n\n        bool ok = false;\n        for (int k=0;k<4;k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!inside(nr,nc)) continue;\n            if (reach[nr * D + nc]) {\n                ok = true;\n                break;\n            }\n        }\n\n        if (ok) moves.push_back(id);\n    }\n\n    return moves;\n}\n\nunordered_map<Key, vector<int>, Hasher> legalCache;\nunordered_map<Key, int, Hasher> heuristicCache;\n\nconst vector<int>& legalMovesCached(unsigned __int128 mask) {\n    Key key = makeKey(mask);\n    auto it = legalCache.find(key);\n    if (it != legalCache.end()) return it->second;\n\n    auto moves = legalMovesMaskRaw(mask);\n    auto res = legalCache.emplace(key, std::move(moves));\n    return res.first->second;\n}\n\ninline int immediateCost(unsigned __int128 nmask, int id) {\n    return popcount128(nmask & smallerMaskG[id]);\n}\n\nint unlockScore(unsigned __int128 mask, int id) {\n    const auto& before = legalMovesCached(mask);\n    unsigned __int128 nmask = mask & ~((unsigned __int128)1 << id);\n    const auto& after = legalMovesCached(nmask);\n\n    bool was[MAXM] = {};\n    for (int x : before) was[x] = true;\n\n    int score = 0;\n    for (int x : after) {\n        if (!was[x]) {\n            score += 100;\n            score += max(0, 80 - labelG[x]);\n        }\n    }\n\n    return score;\n}\n\nint heuristicStateCached(unsigned __int128 mask) {\n    Key key = makeKey(mask);\n    auto it = heuristicCache.find(key);\n    if (it != heuristicCache.end()) return it->second;\n\n    const auto& moves = legalMovesCached(mask);\n    if (moves.empty()) {\n        heuristicCache[key] = 1000000;\n        return 1000000;\n    }\n\n    int mn = 1000000;\n    int sumSmall = 0;\n\n    for (int id : moves) {\n        mn = min(mn, labelG[id]);\n        if (labelG[id] < 20) sumSmall++;\n    }\n\n    int h = mn * 2 - sumSmall * 10;\n    heuristicCache[key] = h;\n    return h;\n}\n\nstruct BeamState {\n    unsigned __int128 mask;\n    int cost;\n    array<unsigned char, MAXM> seq;\n    unsigned char len;\n    int h;\n};\n\nint main() {\n    startTime = chrono::steady_clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> D >> N;\n\n    memset(obstacle_, 0, sizeof(obstacle_));\n    memset(occupied_, 0, sizeof(occupied_));\n\n    for (int r=0;r<9;r++) {\n        for (int c=0;c<9;c++) {\n            valAt[r][c] = -1;\n            cellIdG[r][c] = -1;\n        }\n    }\n\n    for (int i=0;i<N;i++) {\n        int r,c;\n        cin >> r >> c;\n        obstacle_[r][c] = true;\n    }\n\n    int M = D * D - 1 - N;\n\n    auto dist = baseDistance();\n\n    vector<Cell> allCells;\n    for (int r=0;r<D;r++) {\n        for (int c=0;c<D;c++) {\n            if (isEntrance(r,c)) continue;\n            if (obstacle_[r][c]) continue;\n            allCells.push_back({r,c});\n        }\n    }\n\n    sort(allCells.begin(), allCells.end(), [&](const Cell& a, const Cell& b) {\n        int da = dist[a.r][a.c];\n        int db = dist[b.r][b.c];\n        if (da != db) return da < db;\n\n        int ca = abs(a.c - ENTC);\n        int cb = abs(b.c - ENTC);\n        if (ca != cb) return ca < cb;\n\n        if (a.r != b.r) return a.r < b.r;\n        return a.c < b.c;\n    });\n\n    int rankOf[9][9];\n    memset(rankOf, -1, sizeof(rankOf));\n\n    for (int i=0;i<(int)allCells.size();i++) {\n        rankOf[allCells[i].r][allCells[i].c] = i;\n    }\n\n    // Best observed placement refinement.\n    for (int d=0; d<M; d++) {\n        int t;\n        cin >> t;\n\n        auto reach = reachableEmpty();\n\n        Cell best{-1,-1};\n        long long bestScore = LLONG_MAX;\n\n        for (auto cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (occupied_[r][c]) continue;\n            if (!reach[r][c]) continue;\n            if (!keepsConnectivity(r,c,allCells)) continue;\n\n            int rk = rankOf[r][c];\n\n            int emptyNbr = 0;\n            int nearEntrance = 0;\n\n            for (int k=0;k<4;k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (!inside(nr,nc)) continue;\n                if (isEntrance(nr,nc)) nearEntrance = 1;\n                if (reach[nr][nc]) emptyNbr++;\n            }\n\n            long long score = 0;\n            score += 1000LL * abs(rk - t);\n            score -= 20LL * dist[r][c];\n            if (c == ENTC) score += 100;\n            score -= 5LL * abs(c - ENTC);\n\n            score += 18LL * emptyNbr;\n\n            if (nearEntrance && t > M / 5) score += 160;\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = cell;\n            }\n        }\n\n        if (best.r == -1) {\n            bestScore = LLONG_MAX;\n\n            for (auto cell : allCells) {\n                int r = cell.r, c = cell.c;\n                if (occupied_[r][c]) continue;\n                if (!reach[r][c]) continue;\n\n                int rk = rankOf[r][c];\n                long long score = 1000LL * abs(rk - t) - 20LL * dist[r][c];\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = cell;\n                }\n            }\n        }\n\n        if (best.r == -1) {\n            for (auto cell : allCells) {\n                if (!occupied_[cell.r][cell.c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        occupied_[best.r][best.c] = true;\n        valAt[best.r][best.c] = t;\n\n        cout << best.r << \" \" << best.c << '\\n';\n        cout.flush();\n    }\n\n    // Prepare final removal data.\n    cellsG = allCells;\n    KG = (int)cellsG.size();\n\n    for (int i=0;i<KG;i++) {\n        cellIdG[cellsG[i].r][cellsG[i].c] = i;\n    }\n\n    labelG.assign(KG, -1);\n    for (int i=0;i<KG;i++) {\n        labelG[i] = valAt[cellsG[i].r][cellsG[i].c];\n    }\n\n    smallerMaskG.assign(KG, 0);\n    for (int i=0;i<KG;i++) {\n        unsigned __int128 m = 0;\n        for (int j=0;j<KG;j++) {\n            if (labelG[j] < labelG[i]) {\n                m |= ((unsigned __int128)1 << j);\n            }\n        }\n        smallerMaskG[i] = m;\n    }\n\n    unsigned __int128 fullMask = 0;\n    for (int i=0;i<KG;i++) {\n        fullMask |= ((unsigned __int128)1 << i);\n    }\n\n    // Greedy fallback.\n    bool backupOcc[9][9];\n    int backupVal[9][9];\n\n    for (int r=0;r<D;r++) {\n        for (int c=0;c<D;c++) {\n            backupOcc[r][c] = occupied_[r][c];\n            backupVal[r][c] = valAt[r][c];\n        }\n    }\n\n    vector<Cell> greedyAns;\n    greedyAns.reserve(M);\n\n    for (int step=0; step<M; step++) {\n        auto emptyReach = reachableEmpty();\n\n        Cell best{-1,-1};\n        int bestVal = INT_MAX;\n\n        for (auto cell : allCells) {\n            int r = cell.r, c = cell.c;\n            if (!occupied_[r][c]) continue;\n            if (!removableContainer(r,c,emptyReach)) continue;\n\n            if (valAt[r][c] < bestVal) {\n                bestVal = valAt[r][c];\n                best = cell;\n            }\n        }\n\n        if (best.r == -1) {\n            for (auto cell : allCells) {\n                if (occupied_[cell.r][cell.c]) {\n                    best = cell;\n                    break;\n                }\n            }\n        }\n\n        greedyAns.push_back(best);\n        occupied_[best.r][best.c] = false;\n        valAt[best.r][best.c] = -1;\n    }\n\n    for (int r=0;r<D;r++) {\n        for (int c=0;c<D;c++) {\n            occupied_[r][c] = backupOcc[r][c];\n            valAt[r][c] = backupVal[r][c];\n        }\n    }\n\n    legalCache.reserve(240000);\n    heuristicCache.reserve(240000);\n\n    int BEAM = 460;\n    if (M >= 78) BEAM = 390;\n    if (N >= 7) BEAM = 510;\n\n    vector<BeamState> beam;\n\n    BeamState init;\n    init.mask = fullMask;\n    init.cost = 0;\n    init.len = 0;\n    init.h = heuristicStateCached(fullMask);\n    beam.push_back(init);\n\n    vector<unsigned char> bestSeq;\n\n    for (int step=0; step<M; step++) {\n        if (timeAlmostUp()) break;\n\n        vector<BeamState> nxt;\n        nxt.reserve(BEAM * 12);\n\n        for (const auto& st : beam) {\n            if (timeAlmostUp()) break;\n\n            const auto& moves = legalMovesCached(st.mask);\n            if (moves.empty()) continue;\n\n            vector<int> selected;\n\n            vector<int> byLabel = moves;\n            sort(byLabel.begin(), byLabel.end(), [&](int a, int b) {\n                return labelG[a] < labelG[b];\n            });\n\n            int L1 = (step < 20 ? 12 : 9);\n            for (int i=0;i<(int)byLabel.size() && i<L1;i++) {\n                selected.push_back(byLabel[i]);\n            }\n\n            vector<pair<int,int>> byUnlock;\n            byUnlock.reserve(moves.size());\n\n            for (int id : moves) {\n                byUnlock.push_back({-unlockScore(st.mask, id), id});\n            }\n\n            sort(byUnlock.begin(), byUnlock.end());\n\n            int L2 = (step < 25 ? 5 : 3);\n            for (int i=0;i<(int)byUnlock.size() && i<L2;i++) {\n                selected.push_back(byUnlock[i].second);\n            }\n\n            vector<pair<int,int>> byCost;\n            byCost.reserve(moves.size());\n\n            for (int id : moves) {\n                unsigned __int128 nmask = st.mask & ~((unsigned __int128)1 << id);\n                byCost.push_back({immediateCost(nmask, id), id});\n            }\n\n            sort(byCost.begin(), byCost.end());\n\n            int L3 = 5;\n            for (int i=0;i<(int)byCost.size() && i<L3;i++) {\n                selected.push_back(byCost[i].second);\n            }\n\n            sort(selected.begin(), selected.end());\n            selected.erase(unique(selected.begin(), selected.end()), selected.end());\n\n            for (int id : selected) {\n                unsigned __int128 nmask = st.mask & ~((unsigned __int128)1 << id);\n\n                BeamState ns;\n                ns.mask = nmask;\n                ns.cost = st.cost + immediateCost(nmask, id);\n                ns.seq = st.seq;\n                ns.seq[st.len] = (unsigned char)id;\n                ns.len = st.len + 1;\n                ns.h = heuristicStateCached(nmask);\n\n                nxt.push_back(ns);\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        sort(nxt.begin(), nxt.end(), [&](const BeamState& a, const BeamState& b) {\n            long long ea = a.cost * 1000LL + a.h;\n            long long eb = b.cost * 1000LL + b.h;\n            if (ea != eb) return ea < eb;\n            if (a.cost != b.cost) return a.cost < b.cost;\n            int la = a.len ? labelG[a.seq[a.len-1]] : -1;\n            int lb = b.len ? labelG[b.seq[b.len-1]] : -1;\n            return la < lb;\n        });\n\n        vector<BeamState> filtered;\n        filtered.reserve(BEAM);\n\n        unordered_set<Key, Hasher> seen;\n        seen.reserve(BEAM * 4);\n\n        for (auto& st : nxt) {\n            Key key = makeKey(st.mask);\n            if (seen.find(key) != seen.end()) continue;\n            seen.insert(key);\n\n            filtered.push_back(st);\n            if ((int)filtered.size() >= BEAM) break;\n        }\n\n        beam.swap(filtered);\n    }\n\n    if (!beam.empty()) {\n        auto bestIt = max_element(beam.begin(), beam.end(), [&](const BeamState& a, const BeamState& b) {\n            if (a.len != b.len) return a.len < b.len;\n            return a.cost > b.cost;\n        });\n\n        if (bestIt->len == M) {\n            bestSeq.assign(bestIt->seq.begin(), bestIt->seq.begin() + M);\n        }\n    }\n\n    if ((int)bestSeq.size() == M) {\n        for (unsigned char uc : bestSeq) {\n            int id = (int)uc;\n            Cell cell = cellsG[id];\n            cout << cell.r << \" \" << cell.c << '\\n';\n        }\n    } else {\n        for (auto cell : greedyAns) {\n            cout << cell.r << \" \" << cell.c << '\\n';\n        }\n    }\n\n    cout.flush();\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int N = 50;\nstatic const int M = 100;\n\nint n, m;\narray<array<int, N>, N> g, bestG;\nbool targetAdj[M + 1][M + 1];\nint colorCnt[M + 1];\n\nchrono::steady_clock::time_point startTime;\nconst double TL = 1.92;\n\ninline double elapsed() {\n    return chrono::duration<double>(chrono::steady_clock::now() - startTime).count();\n}\n\ninline bool inside(int i, int j) {\n    return 0 <= i && i < n && 0 <= j && j < n;\n}\n\nvoid addAdj(bool adj[M + 1][M + 1], int a, int b) {\n    if (a == b) return;\n    adj[a][b] = adj[b][a] = true;\n}\n\nvoid computeAdj(const array<array<int, N>, N>& grid, bool adj[M + 1][M + 1]) {\n    for (int i = 0; i <= M; i++)\n        for (int j = 0; j <= M; j++)\n            adj[i][j] = false;\n\n    for (int i = 0; i < n; i++) {\n        addAdj(adj, 0, grid[i][0]);\n        addAdj(adj, 0, grid[i][n - 1]);\n    }\n    for (int j = 0; j < n; j++) {\n        addAdj(adj, 0, grid[0][j]);\n        addAdj(adj, 0, grid[n - 1][j]);\n    }\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (i + 1 < n) addAdj(adj, grid[i][j], grid[i + 1][j]);\n            if (j + 1 < n) addAdj(adj, grid[i][j], grid[i][j + 1]);\n        }\n    }\n}\n\nvoid recount() {\n    memset(colorCnt, 0, sizeof(colorCnt));\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            colorCnt[g[i][j]]++;\n}\n\nbool checkZeroConnected() {\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n\n    for (int i = 0; i < n; i++) {\n        if (g[i][0] == 0 && !vis[i][0]) vis[i][0] = true, q.push({i, 0});\n        if (g[i][n - 1] == 0 && !vis[i][n - 1]) vis[i][n - 1] = true, q.push({i, n - 1});\n    }\n    for (int j = 0; j < n; j++) {\n        if (g[0][j] == 0 && !vis[0][j]) vis[0][j] = true, q.push({0, j});\n        if (g[n - 1][j] == 0 && !vis[n - 1][j]) vis[n - 1][j] = true, q.push({n - 1, j});\n    }\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (!inside(ni, nj) || vis[ni][nj] || g[ni][nj] != 0) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (g[i][j] == 0 && !vis[i][j])\n                return false;\n\n    return true;\n}\n\nbool checkColorConnected(int c) {\n    if (colorCnt[c] <= 0) return false;\n\n    int si = -1, sj = -1;\n    for (int i = 0; i < n && si < 0; i++) {\n        for (int j = 0; j < n; j++) {\n            if (g[i][j] == c) {\n                si = i;\n                sj = j;\n                break;\n            }\n        }\n    }\n\n    bool vis[N][N] = {};\n    queue<pair<int,int>> q;\n    vis[si][sj] = true;\n    q.push({si, sj});\n    int cnt = 0;\n\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n        cnt++;\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            if (!inside(ni, nj) || vis[ni][nj] || g[ni][nj] != c) continue;\n            vis[ni][nj] = true;\n            q.push({ni, nj});\n        }\n    }\n\n    return cnt == colorCnt[c];\n}\n\nbool fullCheck() {\n    recount();\n\n    if (!checkZeroConnected()) return false;\n\n    for (int c = 1; c <= m; c++)\n        if (!checkColorConnected(c))\n            return false;\n\n    bool curAdj[M + 1][M + 1];\n    computeAdj(g, curAdj);\n\n    for (int i = 0; i <= m; i++)\n        for (int j = 0; j <= m; j++)\n            if (curAdj[i][j] != targetAdj[i][j])\n                return false;\n\n    return true;\n}\n\nint zeroCount() {\n    int z = 0;\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            if (g[i][j] == 0)\n                z++;\n    return z;\n}\n\nbool trySetCell(int i, int j, int nc) {\n    int oc = g[i][j];\n    if (oc == nc) return false;\n    if (oc != 0 && colorCnt[oc] <= 1) return false;\n\n    int oldZero = colorCnt[0];\n\n    g[i][j] = nc;\n    colorCnt[oc]--;\n    colorCnt[nc]++;\n\n    bool ok = fullCheck();\n    bool improveOrNeutral = colorCnt[0] >= oldZero;\n\n    if (!ok || !improveOrNeutral) {\n        g[i][j] = oc;\n        colorCnt[oc]++;\n        colorCnt[nc]--;\n        return false;\n    }\n\n    return true;\n}\n\nbool tryDelete(int i, int j) {\n    if (g[i][j] == 0) return false;\n    return trySetCell(i, j, 0);\n}\n\nvoid greedyDeletion(double untilTime, mt19937& rng) {\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.push_back({i, j});\n\n    int pass = 0;\n    while (elapsed() < untilTime) {\n        pass++;\n\n        if (pass % 4 == 1) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, 49 - a.first, 49 - a.second});\n                int db = min({b.first, b.second, 49 - b.first, 49 - b.second});\n                return da < db;\n            });\n        } else if (pass % 4 == 2) {\n            sort(cells.begin(), cells.end(), [](auto a, auto b) {\n                int da = min({a.first, a.second, 49 - a.first, 49 - a.second});\n                int db = min({b.first, b.second, 49 - b.first, 49 - b.second});\n                return da > db;\n            });\n        } else {\n            shuffle(cells.begin(), cells.end(), rng);\n        }\n\n        bool changed = false;\n        for (auto [i, j] : cells) {\n            if (elapsed() >= untilTime) break;\n            if (tryDelete(i, j)) changed = true;\n        }\n\n        if (!changed && pass >= 4) break;\n    }\n}\n\nvector<pair<int,int>> collectBoundaryCells() {\n    vector<pair<int,int>> v;\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            int c = g[i][j];\n            bool boundary = false;\n            static const int di[4] = {1, -1, 0, 0};\n            static const int dj[4] = {0, 0, 1, -1};\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) {\n                    if (c != 0) boundary = true;\n                } else if (g[ni][nj] != c) {\n                    boundary = true;\n                }\n            }\n            if (boundary) v.push_back({i, j});\n        }\n    }\n    return v;\n}\n\nvoid reshapePhase(double untilTime, mt19937& rng) {\n    static const int di[4] = {1, -1, 0, 0};\n    static const int dj[4] = {0, 0, 1, -1};\n\n    int bestZero = zeroCount();\n    bestG = g;\n\n    while (elapsed() < untilTime) {\n        auto cells = collectBoundaryCells();\n        shuffle(cells.begin(), cells.end(), rng);\n\n        bool changed = false;\n\n        for (auto [i, j] : cells) {\n            if (elapsed() >= untilTime) break;\n\n            int oc = g[i][j];\n            if (oc == 0) continue;\n            if (colorCnt[oc] <= 1) continue;\n\n            vector<int> cand;\n            cand.push_back(0);\n\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) continue;\n                int nc = g[ni][nj];\n                if (nc != oc) cand.push_back(nc);\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            shuffle(cand.begin(), cand.end(), rng);\n\n            for (int nc : cand) {\n                if (elapsed() >= untilTime) break;\n                if (nc == oc) continue;\n\n                int beforeZero = colorCnt[0];\n                if (trySetCell(i, j, nc)) {\n                    changed = true;\n\n                    int z = colorCnt[0];\n                    if (z > bestZero) {\n                        bestZero = z;\n                        bestG = g;\n                    }\n\n                    // Prefer real deletion; after one accepted move, go to next cell.\n                    break;\n                } else {\n                    // trySetCell restores itself\n                    (void)beforeZero;\n                }\n            }\n        }\n\n        if (!changed) break;\n\n        // After neutral recolors, try to harvest deletions.\n        greedyDeletion(min(untilTime, elapsed() + 0.25), rng);\n\n        int z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        }\n    }\n\n    g = bestG;\n    recount();\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    startTime = chrono::steady_clock::now();\n\n    cin >> n >> m;\n\n    for (int i = 0; i <= M; i++)\n        for (int j = 0; j <= M; j++)\n            targetAdj[i][j] = false;\n\n    for (int i = 0; i < n; i++)\n        for (int j = 0; j < n; j++)\n            cin >> g[i][j];\n\n    computeAdj(g, targetAdj);\n    recount();\n\n    mt19937 rng(123456789);\n\n    greedyDeletion(0.70, rng);\n\n    bestG = g;\n    int bestZero = zeroCount();\n\n    while (elapsed() < TL) {\n        reshapePhase(min(TL, elapsed() + 0.40), rng);\n\n        int z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        } else {\n            g = bestG;\n            recount();\n        }\n\n        greedyDeletion(min(TL, elapsed() + 0.25), rng);\n\n        z = zeroCount();\n        if (z > bestZero) {\n            bestZero = z;\n            bestG = g;\n        } else {\n            g = bestG;\n            recount();\n        }\n    }\n\n    g = bestG;\n\n    // Safety: if something unexpected happens, the current best is still expected valid\n    // because every accepted move was full-checked.\n    // assert(fullCheck());\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\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    vector<int> ord;              // light -> heavy estimated\n    vector<vector<int>> groups;\n    vector<int> ans;\n    vector<double> estW;\n    vector<double> estSum;\n\n    char query_vec(const vector<int>& L, const vector<int>& R) {\n        cout << L.size() << ' ' << R.size();\n        for (int x : L) cout << ' ' << x;\n        for (int x : R) cout << ' ' << x;\n        cout << endl;\n        cout.flush();\n\n        char c;\n        cin >> c;\n        used++;\n        return c;\n    }\n\n    char query_single(int a, int b) {\n        vector<int> L{a}, R{b};\n        return query_vec(L, R);\n    }\n\n    bool less_item(int a, int b) {\n        char c = query_single(a, b);\n        return c == '<';\n    }\n\n    void bounded_insertion_sort() {\n        ord.clear();\n        ord.push_back(0);\n\n        for (int i = 1; i < N; i++) {\n            if (used >= Q) {\n                ord.push_back(i);\n                continue;\n            }\n\n            int lo = 0, hi = (int)ord.size();\n            while (lo < hi && used < Q) {\n                int mid = (lo + hi) / 2;\n                bool lt = less_item(i, ord[mid]);\n                if (lt) hi = mid;\n                else lo = mid + 1;\n            }\n            ord.insert(ord.begin() + lo, i);\n        }\n\n        vector<int> seen(N, 0);\n        for (int x : ord) {\n            if (0 <= x && x < N) seen[x] = 1;\n        }\n        for (int i = 0; i < N; i++) {\n            if (!seen[i]) ord.push_back(i);\n        }\n    }\n\n    void build_est_weights() {\n        estW.assign(N, 1.0);\n\n        for (int r = 0; r < N; r++) {\n            int item = ord[r];\n            double p = (r + 0.5) / N;\n            double x = -log(max(1e-12, 1.0 - p));\n            x = pow(x, 0.95);\n            estW[item] = x;\n        }\n\n        double sum = accumulate(estW.begin(), estW.end(), 0.0);\n        if (sum > 0) {\n            for (double &x : estW) x *= N / sum;\n        }\n    }\n\n    int compare_group(int a, int b) {\n        if (groups[a].empty() && groups[b].empty()) return 0;\n        if (groups[a].empty()) return -1;\n        if (groups[b].empty()) return 1;\n\n        char c = query_vec(groups[a], groups[b]);\n        if (c == '<') return -1;\n        if (c == '>') return 1;\n        return 0;\n    }\n\n    int find_lightest_group_by_query() {\n        for (int g = 0; g < D; g++) {\n            if (groups[g].empty()) return g;\n        }\n\n        int best = 0;\n        for (int g = 1; g < D; g++) {\n            if (used >= Q) break;\n            int cmp = compare_group(g, best);\n            if (cmp == -1) best = g;\n        }\n        return best;\n    }\n\n    double fallback_alpha(int placedCount) {\n        double ratio = (double)Q / N;\n\n        double a = 0.45;\n\n        if (D <= 6) a += 0.30;\n        else if (D <= 10) a += 0.20;\n        else if (D <= 16) a += 0.10;\n        else a -= 0.10;\n\n        if (ratio >= 16.0) a += 0.20;\n        else if (ratio >= 10.0) a += 0.10;\n        else if (ratio <= 5.0) a -= 0.10;\n\n        if (placedCount >= N / 2) a += 0.10;\n\n        a = max(0.15, min(0.95, a));\n        return a;\n    }\n\n    double blended_score_group(int g, int placedCount) {\n        double alpha = fallback_alpha(placedCount);\n\n        double avgW = 0.0;\n        for (int h = 0; h < D; h++) avgW += estSum[h];\n        avgW = max(1e-9, avgW / D);\n\n        double avgS = 0.0;\n        for (int h = 0; h < D; h++) avgS += (double)groups[h].size();\n        avgS = max(1e-9, avgS / D);\n\n        double nw = estSum[g] / avgW;\n        double ns = ((double)groups[g].size()) / avgS;\n\n        return alpha * nw + (1.0 - alpha) * ns + 1e-6 * groups[g].size();\n    }\n\n    int find_lightest_group_blended(int placedCount) {\n        for (int g = 0; g < D; g++) {\n            if (groups[g].empty()) return g;\n        }\n\n        int best = 0;\n        double bestScore = 1e100;\n\n        for (int g = 0; g < D; g++) {\n            double score = blended_score_group(g, placedCount);\n            if (score < bestScore) {\n                bestScore = score;\n                best = g;\n            }\n        }\n\n        return best;\n    }\n\n    void push_unique(vector<int>& v, int x) {\n        if (x < 0 || x >= D) return;\n        for (int y : v) {\n            if (y == x) return;\n        }\n        v.push_back(x);\n    }\n\n    int find_lightest_group_partial_query(int placedCount, int remainingItems) {\n        for (int g = 0; g < D; g++) {\n            if (groups[g].empty()) return g;\n        }\n\n        int remQ = Q - used;\n        if (remQ <= 0) return find_lightest_group_blended(placedCount);\n\n        vector<int> byBlend(D);\n        iota(byBlend.begin(), byBlend.end(), 0);\n\n        sort(byBlend.begin(), byBlend.end(), [&](int a, int b) {\n            double sa = blended_score_group(a, placedCount);\n            double sb = blended_score_group(b, placedCount);\n            if (sa != sb) return sa < sb;\n            return a < b;\n        });\n\n        int minEst = 0;\n        int minSize = 0;\n        for (int g = 1; g < D; g++) {\n            if (estSum[g] < estSum[minEst]) minEst = g;\n            if (groups[g].size() < groups[minSize].size()) minSize = g;\n        }\n\n        int perItem = max(1, remQ / max(1, remainingItems));\n        int cmpBudget = min(remQ, perItem);\n\n        if (remainingItems <= 3) cmpBudget = remQ;\n        else if (remainingItems <= 6) cmpBudget = max(cmpBudget, remQ / 2);\n\n        cmpBudget = min(cmpBudget, 6);\n        int want = min(D, cmpBudget + 1);\n\n        vector<int> cand;\n        push_unique(cand, byBlend[0]);\n        push_unique(cand, minEst);\n        push_unique(cand, minSize);\n\n        for (int x : byBlend) {\n            if ((int)cand.size() >= want) break;\n            push_unique(cand, x);\n        }\n\n        int best = cand[0];\n        for (int i = 1; i < (int)cand.size() && used < Q; i++) {\n            int g = cand[i];\n            int cmp = compare_group(g, best);\n            if (cmp == -1) best = g;\n        }\n\n        return best;\n    }\n\n    void add_item(int item, int g) {\n        groups[g].push_back(item);\n        ans[item] = g;\n        estSum[g] += estW[item];\n    }\n\n    void make_partition() {\n        groups.assign(D, {});\n        ans.assign(N, 0);\n        estSum.assign(D, 0.0);\n\n        vector<int> heavy_to_light = ord;\n        reverse(heavy_to_light.begin(), heavy_to_light.end());\n\n        int placed = 0;\n\n        for (int idx = 0; idx < (int)heavy_to_light.size(); idx++) {\n            int item = heavy_to_light[idx];\n\n            int g;\n            if (used + D - 1 <= Q) {\n                g = find_lightest_group_by_query();\n            } else if (used < Q) {\n                int remainingItems = (int)heavy_to_light.size() - idx;\n                g = find_lightest_group_partial_query(placed, remainingItems);\n            } else {\n                g = find_lightest_group_blended(placed);\n            }\n\n            add_item(item, g);\n            placed++;\n        }\n    }\n\n    vector<int> build_blended_greedy_ans() {\n        vector<int> candAns(N, 0);\n        vector<vector<int>> tmpGroups(D);\n        vector<double> tmpSum(D, 0.0);\n\n        vector<int> items = ord;\n        reverse(items.begin(), items.end());\n\n        int placed = 0;\n        for (int item : items) {\n            int best = -1;\n            for (int g = 0; g < D; g++) {\n                if (tmpGroups[g].empty()) {\n                    best = g;\n                    break;\n                }\n            }\n\n            if (best == -1) {\n                double alpha = fallback_alpha(placed);\n\n                double avgW = 0.0;\n                for (int g = 0; g < D; g++) avgW += tmpSum[g];\n                avgW = max(1e-9, avgW / D);\n\n                double avgS = 0.0;\n                for (int g = 0; g < D; g++) avgS += (double)tmpGroups[g].size();\n                avgS = max(1e-9, avgS / D);\n\n                double bestScore = 1e100;\n\n                for (int g = 0; g < D; g++) {\n                    double nw = tmpSum[g] / avgW;\n                    double ns = ((double)tmpGroups[g].size()) / avgS;\n                    double score = alpha * nw + (1.0 - alpha) * ns;\n                    score += 1e-6 * tmpGroups[g].size();\n\n                    if (score < bestScore) {\n                        bestScore = score;\n                        best = g;\n                    }\n                }\n            }\n\n            candAns[item] = best;\n            tmpGroups[best].push_back(item);\n            tmpSum[best] += estW[item];\n            placed++;\n        }\n\n        return candAns;\n    }\n\n    void set_ans_from_vector(const vector<int>& candAns) {\n        ans = candAns;\n        groups.assign(D, {});\n        estSum.assign(D, 0.0);\n\n        for (int i = 0; i < N; i++) {\n            int g = ans[i];\n            if (g < 0 || g >= D) g = 0;\n            ans[i] = g;\n            groups[g].push_back(i);\n            estSum[g] += estW[i];\n        }\n    }\n\n    void partition_no_query_left() {\n        set_ans_from_vector(build_blended_greedy_ans());\n    }\n\n    void spend_remaining_queries() {\n        while (used < Q) {\n            int a = used % N;\n            int b = (a + 1) % N;\n            query_single(a, b);\n        }\n    }\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        bounded_insertion_sort();\n        build_est_weights();\n\n        if (used < Q) {\n            make_partition();\n        } else {\n            partition_no_query_left();\n        }\n\n        spend_remaining_queries();\n\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << ans[i];\n        }\n        cout << endl;\n        cout.flush();\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Config {\n    int mode; // 0 = rollout, 1 = split, 2 = micro two-split\n    int rolloutHorizon;\n    double costW;\n    double emptyBonus;\n    double goodBoundaryBonus;\n    double badBoundaryPenalty;\n    double badBoundaryDiffW;\n    double heightW;\n    double nearDepthW;\n    double topSmallBonus;\n    double coverSmallPenalty;\n    double staticW;\n    double bucketW;\n    int bucketSize;\n    double splitPenalty;\n    int splitMaxCandidates;\n};\n\nstruct Result {\n    vector<pair<int,int>> ops;\n    int energy;\n};\n\nstruct FirstAction {\n    int type; // 0 normal, 1 split, 2 micro two-split\n    int sp1;\n    int sp2;\n    int dst1;\n    int dst2;\n    int dst3;\n    double score;\n};\n\nstruct PortfolioSolver {\n    int n, m;\n    vector<vector<int>> init;\n    Timer timer;\n    static constexpr double TIME_LIMIT = 1.90;\n\n    PortfolioSolver(int n_, int m_, vector<vector<int>> init_)\n        : n(n_), m(m_), init(std::move(init_)) {}\n\n    bool time_ok() const {\n        return timer.elapsed() < TIME_LIMIT;\n    }\n\n    int find_stack(const vector<vector<int>>& a, int v) const {\n        for (int i = 0; i < m; i++) {\n            for (int x : a[i]) if (x == v) return i;\n        }\n        return -1;\n    }\n\n    int find_index(const vector<int>& s, int v) const {\n        for (int i = 0; i < (int)s.size(); i++) if (s[i] == v) return i;\n        return -1;\n    }\n\n    int bucket(int x, int bs) const {\n        return (x - 1) / bs;\n    }\n\n    int remove_greedy_sim(vector<vector<int>>& a, int cur, int limitCur) const {\n        bool changed = true;\n        while (cur <= limitCur && changed) {\n            changed = false;\n            for (int i = 0; i < m; i++) {\n                if (!a[i].empty() && a[i].back() == cur) {\n                    a[i].pop_back();\n                    cur++;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        return cur;\n    }\n\n    double bucket_eval_stack(const vector<int>& s, int cur, const Config& cfg) const {\n        if (s.empty()) return -cfg.emptyBonus * 0.2;\n\n        double sc = 0.0;\n        int h = (int)s.size();\n\n        for (int j = 0; j + 1 < h; j++) {\n            int lower = s[j];\n            int upper = s[j + 1];\n            int bl = bucket(lower, cfg.bucketSize);\n            int bu = bucket(upper, cfg.bucketSize);\n\n            if (bl < bu) {\n                sc += cfg.bucketW * (1 + bu - bl);\n                if (lower < cur + 50) sc += cfg.bucketW;\n            } else if (bl == bu) {\n                if (lower < upper) sc += cfg.bucketW * 0.6;\n                else sc -= cfg.bucketW * 0.15;\n            } else {\n                sc -= cfg.bucketW * 0.25;\n            }\n        }\n\n        for (int j = 0; j < h; j++) {\n            int v = s[j];\n            if (v >= cur && v < cur + 50) {\n                int above = h - 1 - j;\n                sc += above * (55 - (v - cur)) * 0.025 * cfg.bucketW;\n            }\n        }\n\n        return sc;\n    }\n\n    double static_eval(const vector<vector<int>>& a, int cur, const Config& cfg) const {\n        double score = 0.0;\n\n        for (int i = 0; i < m; i++) {\n            const auto& s = a[i];\n            int h = (int)s.size();\n\n            score += cfg.heightW * h;\n\n            for (int j = 0; j + 1 < h; j++) {\n                int lower = s[j];\n                int upper = s[j + 1];\n\n                if (lower < upper) {\n                    score += cfg.badBoundaryPenalty * 0.07;\n                    if (lower < cur + 45) score += cfg.badBoundaryPenalty * 0.07;\n                } else {\n                    score -= cfg.goodBoundaryBonus * 0.01;\n                }\n            }\n\n            for (int j = 0; j < h; j++) {\n                int v = s[j];\n                if (v >= cur && v < cur + 40) {\n                    int above = h - 1 - j;\n                    score += above * (42 - (v - cur)) * cfg.nearDepthW * 0.02;\n                }\n            }\n\n            if (!s.empty()) {\n                int top = s.back();\n                if (top >= cur && top < cur + 30) {\n                    score -= (32 - (top - cur)) * cfg.topSmallBonus * 0.03;\n                }\n            }\n\n            if (cfg.mode == 1 || cfg.mode == 2) {\n                score += bucket_eval_stack(s, cur, cfg);\n            }\n        }\n\n        return score;\n    }\n\n    double destination_score(\n        const vector<vector<int>>& a,\n        int dst,\n        const vector<int>& seg,\n        int cur,\n        const Config& cfg\n    ) const {\n        int bottom = seg.front();\n        int topSeg = seg.back();\n        int segMin = *min_element(seg.begin(), seg.end());\n        int k = (int)seg.size();\n\n        double sc = 0.0;\n\n        if (a[dst].empty()) {\n            sc -= cfg.emptyBonus;\n            sc += k * 1.5;\n        } else {\n            int top = a[dst].back();\n\n            if (top > bottom) {\n                sc -= cfg.goodBoundaryBonus;\n                sc += (top - bottom) * 0.7;\n            } else {\n                sc += cfg.badBoundaryPenalty;\n                sc += (bottom - top) * cfg.badBoundaryDiffW;\n            }\n\n            if (top < cur + 25) {\n                sc += cfg.coverSmallPenalty;\n                sc += (cur + 25 - top) * 3.0;\n            }\n\n            sc += abs(top - bottom) * 0.35;\n\n            if (cfg.mode == 1 || cfg.mode == 2) {\n                int bt = bucket(top, cfg.bucketSize);\n                int bb = bucket(bottom, cfg.bucketSize);\n                int bm = bucket(segMin, cfg.bucketSize);\n\n                if (bt > bb) {\n                    sc -= cfg.bucketW * (1 + bt - bb);\n                } else if (bt == bb) {\n                    if (top > bottom) sc -= cfg.bucketW * 0.4;\n                    else sc += cfg.bucketW * 0.8;\n                } else {\n                    sc += cfg.bucketW * (2 + bb - bt);\n                }\n\n                if (top < cur + cfg.bucketSize * 2) {\n                    sc += cfg.bucketW * 2.5;\n                }\n\n                if (segMin < cur + cfg.bucketSize * 2) {\n                    sc += (int)a[dst].size() * cfg.bucketW * 0.25;\n                }\n\n                if (bt >= bm) sc -= cfg.bucketW * 0.5;\n            }\n        }\n\n        sc += (int)a[dst].size() * cfg.heightW;\n\n        if (segMin < cur + 25) sc += (int)a[dst].size() * cfg.nearDepthW;\n        if (topSeg < cur + 20) sc += (int)a[dst].size() * cfg.nearDepthW * 0.8;\n\n        return sc;\n    }\n\n    vector<pair<double,int>> ranked_destinations(\n        const vector<vector<int>>& a,\n        int src,\n        const vector<int>& seg,\n        int cur,\n        const Config& cfg,\n        int lim\n    ) const {\n        vector<pair<double,int>> cand;\n        for (int d = 0; d < m; d++) {\n            if (d == src) continue;\n            cand.push_back({destination_score(a, d, seg, cur, cfg), d});\n        }\n        sort(cand.begin(), cand.end());\n        if ((int)cand.size() > lim) cand.resize(lim);\n        return cand;\n    }\n\n    int greedy_future_dst(\n        const vector<vector<int>>& a,\n        int src,\n        const vector<int>& seg,\n        int cur,\n        const Config& cfg\n    ) const {\n        auto cand = ranked_destinations(a, src, seg, cur, cfg, 1);\n        if (cand.empty()) return (src + 1) % m;\n        return cand[0].second;\n    }\n\n    double rollout_after_state(vector<vector<int>> a, int cur, double initialCost, const Config& cfg) const {\n        double futureCost = initialCost;\n        cur = remove_greedy_sim(a, cur, n);\n\n        int rolloutEnd = min(n, cur + cfg.rolloutHorizon);\n        int steps = 0;\n\n        while (cur <= rolloutEnd && steps < cfg.rolloutHorizon) {\n            int s = find_stack(a, cur);\n            if (s < 0) {\n                cur++;\n                continue;\n            }\n\n            int id = find_index(a[s], cur);\n            if (id == (int)a[s].size() - 1) {\n                cur = remove_greedy_sim(a, cur, rolloutEnd);\n                continue;\n            }\n\n            vector<int> sg;\n            for (int j = id + 1; j < (int)a[s].size(); j++) sg.push_back(a[s][j]);\n\n            int d = greedy_future_dst(a, s, sg, cur, cfg);\n            futureCost += (int)sg.size() + 1;\n\n            for (int x : sg) a[d].push_back(x);\n            a[s].resize(id + 1);\n\n            cur = remove_greedy_sim(a, cur, rolloutEnd);\n            steps++;\n        }\n\n        return cfg.costW * futureCost + cfg.staticW * static_eval(a, cur, cfg);\n    }\n\n    int choose_dst_rollout(\n        const vector<vector<int>>& st,\n        int src,\n        int idx,\n        int cur,\n        const Config& cfg\n    ) const {\n        vector<int> seg;\n        for (int j = idx + 1; j < (int)st[src].size(); j++) seg.push_back(st[src][j]);\n\n        int bestDst = -1;\n        double bestScore = 1e100;\n\n        for (int dst = 0; dst < m; dst++) {\n            if (dst == src) continue;\n\n            vector<vector<int>> a = st;\n            for (int x : seg) a[dst].push_back(x);\n            a[src].resize(idx + 1);\n\n            double score = rollout_after_state(a, cur, (int)seg.size() + 1, cfg)\n                         + destination_score(st, dst, seg, cur, cfg) * 0.15;\n\n            if (score < bestScore) {\n                bestScore = score;\n                bestDst = dst;\n            }\n        }\n\n        if (bestDst == -1) bestDst = (src + 1) % m;\n        return bestDst;\n    }\n\n    vector<int> select_split_candidates(const vector<vector<int>>& st, int src, int idx, int cur, const Config& cfg) const {\n        vector<int> ret;\n        int h = (int)st[src].size();\n        int start = idx + 1;\n        int len = h - start;\n        if (len < 6) return ret;\n\n        auto add = [&](int sp) {\n            if (sp <= start + 1 || sp >= h - 1) return;\n            ret.push_back(sp);\n        };\n\n        for (int sp = start + 2; sp <= h - 2; sp++) {\n            int lowerTop = st[src][sp - 1];\n            int upperBottom = st[src][sp];\n\n            bool good = false;\n            if (abs(lowerTop - upperBottom) >= 40) good = true;\n\n            int upperMin = 1000000, upperMax = -1;\n            int lowerMin = 1000000, lowerMax = -1;\n            for (int j = sp; j < h; j++) {\n                upperMin = min(upperMin, st[src][j]);\n                upperMax = max(upperMax, st[src][j]);\n            }\n            for (int j = start; j < sp; j++) {\n                lowerMin = min(lowerMin, st[src][j]);\n                lowerMax = max(lowerMax, st[src][j]);\n            }\n\n            if (upperMin < cur + 40) good = true;\n            if (upperMin + 35 < lowerMin) good = true;\n            if (lowerMax + 35 < upperMax) good = true;\n\n            if (good) add(sp);\n        }\n\n        int minPos = -1, minVal = INT_MAX;\n        for (int j = start; j < h; j++) {\n            if (st[src][j] < minVal) {\n                minVal = st[src][j];\n                minPos = j;\n            }\n        }\n        add(minPos);\n        add(minPos + 1);\n\n        vector<pair<int,int>> vals;\n        for (int j = start; j < h; j++) vals.push_back({st[src][j], j});\n        sort(vals.begin(), vals.end());\n\n        int smallCnt = min<int>(3, vals.size());\n        for (int t = 0; t < smallCnt; t++) {\n            int p = vals[t].second;\n            add(p);\n            add(p + 1);\n        }\n\n        int soonAdded = 0;\n        for (auto [v, p] : vals) {\n            if (v >= cur && v <= cur + 30) {\n                add(p);\n                add(p + 1);\n                soonAdded++;\n                if (soonAdded >= 3) break;\n            }\n        }\n\n        vector<pair<int,int>> jumps;\n        for (int sp = start + 2; sp <= h - 2; sp++) {\n            jumps.push_back({abs(st[src][sp] - st[src][sp - 1]), sp});\n        }\n        sort(jumps.rbegin(), jumps.rend());\n        for (int i = 0; i < (int)jumps.size() && i < 3; i++) add(jumps[i].second);\n\n        sort(ret.begin(), ret.end());\n        ret.erase(unique(ret.begin(), ret.end()), ret.end());\n\n        sort(ret.begin(), ret.end(), [&](int a, int b) {\n            auto key = [&](int sp) {\n                int upperMin = 1000000;\n                for (int j = sp; j < h; j++) upperMin = min(upperMin, st[src][j]);\n\n                int lowerMin = 1000000;\n                for (int j = start; j < sp; j++) lowerMin = min(lowerMin, st[src][j]);\n\n                int jump = abs(st[src][sp] - st[src][sp - 1]);\n                int nearSoon = min(abs(st[src][sp] - cur), abs(st[src][sp - 1] - cur));\n\n                return tuple<int,int,int,int>(\n                    min(upperMin, lowerMin),\n                    nearSoon,\n                    -jump,\n                    abs((sp - start) - (h - sp))\n                );\n            };\n            return key(a) < key(b);\n        });\n\n        if ((int)ret.size() > cfg.splitMaxCandidates) ret.resize(cfg.splitMaxCandidates);\n        return ret;\n    }\n\n    void add_normal_actions(\n        vector<FirstAction>& actions,\n        const vector<vector<int>>& st,\n        int src,\n        int start,\n        int cur,\n        const Config& cfg\n    ) const {\n        int h = st[src].size();\n        vector<int> whole;\n        for (int j = start; j < h; j++) whole.push_back(st[src][j]);\n\n        for (int d = 0; d < m; d++) {\n            if (d == src) continue;\n\n            vector<vector<int>> a = st;\n            for (int x : whole) a[d].push_back(x);\n            a[src].resize(start);\n\n            double sc = rollout_after_state(a, cur, (int)whole.size() + 1, cfg)\n                      + destination_score(st, d, whole, cur, cfg) * 0.15;\n\n            actions.push_back({0, -1, -1, d, -1, -1, sc});\n        }\n    }\n\n    FirstAction choose_action_split(\n        const vector<vector<int>>& st,\n        int src,\n        int idx,\n        int cur,\n        const Config& cfg\n    ) const {\n        vector<FirstAction> actions;\n\n        int h = (int)st[src].size();\n        int start = idx + 1;\n\n        add_normal_actions(actions, st, src, start, cur, cfg);\n\n        vector<int> candidateSplits = select_split_candidates(st, src, idx, cur, cfg);\n\n        for (int sp : candidateSplits) {\n            if (!time_ok()) break;\n\n            vector<int> lower, upper;\n            for (int j = start; j < sp; j++) lower.push_back(st[src][j]);\n            for (int j = sp; j < h; j++) upper.push_back(st[src][j]);\n\n            auto cand1 = ranked_destinations(st, src, upper, cur, cfg, 6);\n\n            for (auto [ds1, d1] : cand1) {\n                vector<vector<int>> a1 = st;\n                for (int x : upper) a1[d1].push_back(x);\n                a1[src].resize(sp);\n\n                auto cand2 = ranked_destinations(a1, src, lower, cur, cfg, 3);\n\n                for (auto [ds2, d2] : cand2) {\n                    vector<vector<int>> a = a1;\n                    for (int x : lower) a[d2].push_back(x);\n                    a[src].resize(start);\n\n                    double initCost = (int)upper.size() + 1 + (int)lower.size() + 1;\n                    double sc = rollout_after_state(a, cur, initCost, cfg)\n                              + ds1 * 0.10\n                              + ds2 * 0.10\n                              + cfg.splitPenalty;\n\n                    actions.push_back({1, sp, -1, d1, d2, -1, sc});\n                }\n            }\n        }\n\n        if (cfg.mode == 2 && time_ok()) {\n            int len = h - start;\n            if (len >= 10 && candidateSplits.size() >= 2) {\n                vector<int> splits = candidateSplits;\n                sort(splits.begin(), splits.end());\n\n                vector<pair<tuple<int,int,int>, pair<int,int>>> pairs;\n\n                for (int a = 0; a < (int)splits.size(); a++) {\n                    for (int b = a + 1; b < (int)splits.size(); b++) {\n                        int sp1 = splits[a], sp2 = splits[b];\n                        if (sp1 - start < 2 || sp2 - sp1 < 2 || h - sp2 < 2) continue;\n\n                        int minTop = INT_MAX, minMid = INT_MAX, minLow = INT_MAX;\n                        for (int j = sp2; j < h; j++) minTop = min(minTop, st[src][j]);\n                        for (int j = sp1; j < sp2; j++) minMid = min(minMid, st[src][j]);\n                        for (int j = start; j < sp1; j++) minLow = min(minLow, st[src][j]);\n\n                        tuple<int,int,int> key = {\n                            min({minTop, minMid, minLow}),\n                            min(minTop, minMid),\n                            -(sp2 - sp1)\n                        };\n                        pairs.push_back({key, {sp1, sp2}});\n                    }\n                }\n\n                sort(pairs.begin(), pairs.end());\n                if ((int)pairs.size() > 2) pairs.resize(2);\n\n                for (auto &pp : pairs) {\n                    if (!time_ok()) break;\n\n                    int sp1 = pp.second.first;\n                    int sp2 = pp.second.second;\n\n                    vector<int> low, mid, top;\n                    for (int j = start; j < sp1; j++) low.push_back(st[src][j]);\n                    for (int j = sp1; j < sp2; j++) mid.push_back(st[src][j]);\n                    for (int j = sp2; j < h; j++) top.push_back(st[src][j]);\n\n                    auto candTop = ranked_destinations(st, src, top, cur, cfg, 2);\n\n                    for (auto [dsTop, dTop] : candTop) {\n                        vector<vector<int>> a1 = st;\n                        for (int x : top) a1[dTop].push_back(x);\n                        a1[src].resize(sp2);\n\n                        auto candMid = ranked_destinations(a1, src, mid, cur, cfg, 2);\n                        for (auto [dsMid, dMid] : candMid) {\n                            vector<vector<int>> a2 = a1;\n                            for (int x : mid) a2[dMid].push_back(x);\n                            a2[src].resize(sp1);\n\n                            auto candLow = ranked_destinations(a2, src, low, cur, cfg, 2);\n                            for (auto [dsLow, dLow] : candLow) {\n                                vector<vector<int>> a = a2;\n                                for (int x : low) a[dLow].push_back(x);\n                                a[src].resize(start);\n\n                                double initCost = (int)top.size() + 1\n                                                + (int)mid.size() + 1\n                                                + (int)low.size() + 1;\n\n                                double sc = rollout_after_state(a, cur, initCost, cfg)\n                                          + dsTop * 0.08\n                                          + dsMid * 0.08\n                                          + dsLow * 0.08\n                                          + cfg.splitPenalty * 2.5\n                                          + 25.0;\n\n                                actions.push_back({2, sp1, sp2, dTop, dMid, dLow, sc});\n                            }\n                        }\n                    }\n                }\n            }\n        }\n\n        return *min_element(actions.begin(), actions.end(), [](const FirstAction& a, const FirstAction& b) {\n            return a.score < b.score;\n        });\n    }\n\n    Result run_one(const Config& cfg) const {\n        vector<vector<int>> st = init;\n        vector<pair<int,int>> ops;\n        int energy = 0;\n        int cur = 1;\n\n        auto real_remove = [&]() {\n            bool changed = true;\n            while (cur <= n && changed) {\n                changed = false;\n                for (int i = 0; i < m; i++) {\n                    if (!st[i].empty() && st[i].back() == cur) {\n                        st[i].pop_back();\n                        ops.push_back({cur, 0});\n                        cur++;\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n        };\n\n        real_remove();\n\n        while (cur <= n && (int)ops.size() < 5000) {\n            if (!time_ok()) break;\n\n            int src = find_stack(st, cur);\n            if (src < 0) {\n                real_remove();\n                continue;\n            }\n\n            int idx = find_index(st[src], cur);\n            if (idx == (int)st[src].size() - 1) {\n                real_remove();\n                continue;\n            }\n\n            if (cfg.mode == 1 || cfg.mode == 2) {\n                FirstAction act = choose_action_split(st, src, idx, cur, cfg);\n\n                int h = (int)st[src].size();\n                int start = idx + 1;\n\n                if (act.type == 0) {\n                    int d = act.dst1;\n                    int v = st[src][start];\n                    int k = h - start;\n\n                    ops.push_back({v, d + 1});\n                    energy += k + 1;\n\n                    for (int j = start; j < h; j++) st[d].push_back(st[src][j]);\n                    st[src].resize(start);\n                } else if (act.type == 1) {\n                    int sp = act.sp1;\n                    int d1 = act.dst1;\n                    int d2 = act.dst2;\n\n                    int v1 = st[src][sp];\n                    int k1 = h - sp;\n                    ops.push_back({v1, d1 + 1});\n                    energy += k1 + 1;\n\n                    for (int j = sp; j < h; j++) st[d1].push_back(st[src][j]);\n                    st[src].resize(sp);\n\n                    int v2 = st[src][start];\n                    int k2 = sp - start;\n                    ops.push_back({v2, d2 + 1});\n                    energy += k2 + 1;\n\n                    for (int j = start; j < sp; j++) st[d2].push_back(st[src][j]);\n                    st[src].resize(start);\n                } else {\n                    int sp1 = act.sp1;\n                    int sp2 = act.sp2;\n                    int dTop = act.dst1;\n                    int dMid = act.dst2;\n                    int dLow = act.dst3;\n\n                    int vTop = st[src][sp2];\n                    int kTop = h - sp2;\n                    ops.push_back({vTop, dTop + 1});\n                    energy += kTop + 1;\n                    for (int j = sp2; j < h; j++) st[dTop].push_back(st[src][j]);\n                    st[src].resize(sp2);\n\n                    int vMid = st[src][sp1];\n                    int kMid = sp2 - sp1;\n                    ops.push_back({vMid, dMid + 1});\n                    energy += kMid + 1;\n                    for (int j = sp1; j < sp2; j++) st[dMid].push_back(st[src][j]);\n                    st[src].resize(sp1);\n\n                    int vLow = st[src][start];\n                    int kLow = sp1 - start;\n                    ops.push_back({vLow, dLow + 1});\n                    energy += kLow + 1;\n                    for (int j = start; j < sp1; j++) st[dLow].push_back(st[src][j]);\n                    st[src].resize(start);\n                }\n            } else {\n                int dst = choose_dst_rollout(st, src, idx, cur, cfg);\n\n                int v = st[src][idx + 1];\n                int k = (int)st[src].size() - (idx + 1);\n\n                ops.push_back({v, dst + 1});\n                energy += k + 1;\n\n                for (int j = idx + 1; j < (int)st[src].size(); j++) {\n                    st[dst].push_back(st[src][j]);\n                }\n                st[src].resize(idx + 1);\n            }\n\n            real_remove();\n        }\n\n        if (cur <= n) return {{}, INT_MAX};\n        return {ops, energy};\n    }\n\n    Result fallback_solver() const {\n        vector<vector<int>> st = init;\n        vector<pair<int,int>> ops;\n        int energy = 0;\n        int cur = 1;\n\n        auto remove = [&]() {\n            bool changed = true;\n            while (cur <= n && changed) {\n                changed = false;\n                for (int i = 0; i < m; i++) {\n                    if (!st[i].empty() && st[i].back() == cur) {\n                        st[i].pop_back();\n                        ops.push_back({cur, 0});\n                        cur++;\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n        };\n\n        remove();\n\n        while (cur <= n) {\n            int src = find_stack(st, cur);\n            int idx = find_index(st[src], cur);\n\n            if (idx == (int)st[src].size() - 1) {\n                remove();\n                continue;\n            }\n\n            int dst = -1;\n            int bestH = INT_MAX;\n            for (int i = 0; i < m; i++) {\n                if (i == src) continue;\n                if ((int)st[i].size() < bestH) {\n                    bestH = st[i].size();\n                    dst = i;\n                }\n            }\n\n            int start = idx + 1;\n            int v = st[src][start];\n            int k = (int)st[src].size() - start;\n\n            ops.push_back({v, dst + 1});\n            energy += k + 1;\n\n            for (int j = start; j < (int)st[src].size(); j++) st[dst].push_back(st[src][j]);\n            st[src].resize(start);\n\n            remove();\n        }\n\n        return {ops, energy};\n    }\n\n    Result solve() {\n        vector<Config> configs = {\n            // Cheap rollout baseline first.\n            {0,45,100,250,180,350,5,3,4,30,500,1,0,20,0,4},\n            {0,55,125,220,160,380,5.5,3,5,25,550,0.8,0,20,0,4},\n            {0,50,90,260,220,420,6,4,5.5,35,650,1.4,0,20,0,4},\n            {0,45,105,350,170,360,5,3.5,4.5,30,520,1,0,20,0,4},\n            {0,50,100,240,170,340,5,3,4.5,30,850,1,0,20,0,4},\n\n            // Existing one-split family.\n            {1,45,105,260,190,380,5,3,4.5,30,550,1,45,20,35,4},\n            {1,55,110,240,210,410,5.5,3.5,5,35,620,1.1,55,20,25,5},\n            {1,40,120,300,180,360,5,3,4,25,520,0.9,50,15,20,4},\n            {1,60,100,250,220,430,6,4,5.5,35,650,1.2,60,20,15,5},\n            {1,50,95,320,180,380,5,5,6,35,700,1.4,70,25,10,5},\n            {1,70,115,220,190,370,5,3.5,4.5,30,600,1,45,20,30,4},\n            {1,35,130,280,170,350,4,2.5,3.5,25,480,0.8,40,20,5,5},\n\n            // Lightweight split variants.\n            {1,30,140,260,170,340,4,2,3,20,420,0.6,35,20,0,3},\n            {1,32,120,330,160,330,4,2.5,3.5,25,460,0.7,45,15,0,3},\n            {1,38,115,260,230,450,6,4,5,35,700,1.3,70,25,5,3},\n            {1,45,90,360,180,360,5,6,6,35,760,1.5,80,25,0,3},\n            {1,28,150,220,150,320,3.5,2,3,20,400,0.5,30,20,10,3},\n\n            // Micro two-split variants, time guarded.\n            {2,28,145,240,160,330,4,2,3,20,420,0.6,35,20,15,3},\n            {2,32,130,280,170,350,4,2.5,3.5,25,460,0.8,45,20,20,3},\n        };\n\n        Result best = fallback_solver();\n\n        for (const auto& cfg : configs) {\n            if (!time_ok()) break;\n            Result r = run_one(cfg);\n            if (!r.ops.empty() && (int)r.ops.size() <= 5000 && r.energy < best.energy) {\n                best = std::move(r);\n            }\n        }\n\n        return best;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, m;\n    cin >> n >> m;\n\n    vector<vector<int>> st(m);\n    int h = n / m;\n    for (int i = 0; i < m; i++) {\n        st[i].resize(h);\n        for (int j = 0; j < h; j++) cin >> st[i][j];\n    }\n\n    PortfolioSolver solver(n, m, st);\n    Result res = solver.solve();\n\n    for (auto [v, to] : res.ops) {\n        cout << v << ' ' << to << '\\n';\n    }\n\n    return 0;\n}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge{int to; char c;};\nstruct Cand{string route; long double score;};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    auto st=chrono::steady_clock::now();\n    auto elapsed=[&](){\n        return chrono::duration<double>(chrono::steady_clock::now()-st).count();\n    };\n\n    int N; cin>>N;\n    vector<string> h(N-1),v(N);\n    for(int i=0;i<N-1;i++) cin>>h[i];\n    for(int i=0;i<N;i++) cin>>v[i];\n\n    int V=N*N;\n    auto id=[&](int i,int j){return i*N+j;};\n    auto pos=[&](int x){return pair<int,int>{x/N,x%N};};\n\n    vector<int>dirt(V);\n    for(int i=0;i<N;i++) for(int j=0;j<N;j++) cin>>dirt[id(i,j)];\n\n    vector<vector<Edge>> g(V);\n    auto add=[&](int a,int b,char c){g[a].push_back({b,c});};\n\n    for(int i=0;i<N;i++)for(int j=0;j<N;j++){\n        int u=id(i,j);\n        if(i+1<N && h[i][j]=='0'){\n            add(u,id(i+1,j),'D');\n            add(id(i+1,j),u,'U');\n        }\n        if(j+1<N && v[i][j]=='0'){\n            add(u,id(i,j+1),'R');\n            add(id(i,j+1),u,'L');\n        }\n    }\n\n    auto opp=[&](char c){\n        if(c=='U')return 'D';\n        if(c=='D')return 'U';\n        if(c=='L')return 'R';\n        return 'L';\n    };\n\n    auto step=[&](int u,char c){\n        for(auto e:g[u]) if(e.c==c) return e.to;\n        return -1;\n    };\n\n    vector<vector<int>> dist(V,vector<int>(V,-1)),par(V,vector<int>(V,-1));\n    vector<vector<char>> pm(V,vector<char>(V,'?'));\n\n    for(int s=0;s<V;s++){\n        queue<int>q;\n        dist[s][s]=0;\n        q.push(s);\n\n        while(!q.empty()){\n            int u=q.front();\n            q.pop();\n\n            vector<Edge> es=g[u];\n            sort(es.begin(),es.end(),[&](auto&a,auto&b){\n                return dirt[a.to]>dirt[b.to];\n            });\n\n            for(auto e:es)if(dist[s][e.to]<0){\n                dist[s][e.to]=dist[s][u]+1;\n                par[s][e.to]=u;\n                pm[s][e.to]=e.c;\n                q.push(e.to);\n            }\n        }\n    }\n\n    auto path=[&](int s,int t){\n        string r;\n        int cur=t;\n        while(cur!=s){\n            r.push_back(pm[s][cur]);\n            cur=par[s][cur];\n        }\n        reverse(r.begin(),r.end());\n        return r;\n    };\n\n    auto revroute=[&](const string&s){\n        string r;\n        r.reserve(s.size());\n        for(int i=(int)s.size()-1;i>=0;i--) r.push_back(opp(s[i]));\n        return r;\n    };\n\n    auto eval=[&](const string& route)->long double{\n        int L=route.size();\n        if(L<=0||L>100000)return 1e100L;\n\n        vector<vector<int>> vis(V);\n        int cur=0;\n\n        for(int t=1;t<=L;t++){\n            cur=step(cur,route[t-1]);\n            if(cur<0)return 1e100L;\n            vis[cur].push_back(t);\n        }\n\n        if(cur!=0)return 1e100L;\n\n        long double res=0;\n        for(int x=0;x<V;x++){\n            if(vis[x].empty())return 1e100L;\n\n            long long tri=0;\n            int m=vis[x].size();\n\n            for(int k=0;k<m;k++){\n                int a=vis[x][k];\n                int b=vis[x][(k+1)%m];\n                int gap=(k+1<m?b-a:b+L-a);\n                tri+=1LL*gap*(gap-1)/2;\n            }\n\n            res+=(long double)dirt[x]*(long double)tri/(long double)L;\n        }\n\n        return res;\n    };\n\n    vector<Cand> cands;\n    unordered_set<string> seen;\n    seen.reserve(100000);\n\n    auto addcand=[&](const string&s){\n        if(s.empty()||(int)s.size()>100000)return;\n        if(seen.find(s)!=seen.end())return;\n        seen.insert(s);\n\n        long double sc=eval(s);\n        if(sc<1e90L)cands.push_back({s,sc});\n    };\n\n    auto prio=[&](int x,int mode)->long double{\n        auto [i,j]=pos(x);\n        long double cen=fabsl(i-(N-1)/2.0L)+fabsl(j-(N-1)/2.0L);\n\n        if(mode==0)return dirt[x];\n        if(mode==1)return -dirt[x];\n        if(mode==2)return i*N+j;\n        if(mode==3)return -(i*N+j);\n        if(mode==4)return i+j;\n        if(mode==5)return -(i+j);\n        if(mode==6)return i-j;\n        if(mode==7)return j-i;\n        if(mode==8)return -cen;\n        if(mode==9)return cen;\n        if(mode==10)return dirt[x]-5*cen;\n        if(mode==11)return dirt[x]+5*cen;\n        if(mode==12)return dirt[x]+2*(i+j);\n        if(mode==13)return dirt[x]-2*(i+j);\n\n        return dirt[x];\n    };\n\n    auto tree_tour_from_parent=[&](const vector<int>&parent,const vector<char>&pc,int orderMode){\n        vector<vector<int>> tr(V);\n        for(int x=1;x<V;x++){\n            if(parent[x]>=0)tr[parent[x]].push_back(x);\n        }\n\n        vector<long long> sub(V);\n        vector<int> sz(V);\n\n        function<void(int)> calc=[&](int u){\n            sub[u]=dirt[u];\n            sz[u]=1;\n            for(int w:tr[u]){\n                calc(w);\n                sub[u]+=sub[w];\n                sz[u]+=sz[w];\n            }\n        };\n\n        calc(0);\n\n        for(int u=0;u<V;u++){\n            sort(tr[u].begin(),tr[u].end(),[&](int a,int b){\n                if(orderMode==0)return sub[a]>sub[b];\n                if(orderMode==1)return sub[a]<sub[b];\n                if(orderMode==2)return dirt[a]>dirt[b];\n                if(orderMode==3)return dirt[a]<dirt[b];\n                if(orderMode==4)return sz[a]>sz[b];\n                if(orderMode==5)return sz[a]<sz[b];\n\n                auto [ai,aj]=pos(a);\n                auto [bi,bj]=pos(b);\n\n                if(orderMode==6)return ai+aj<bi+bj;\n                if(orderMode==7)return ai+aj>bi+bj;\n                if(orderMode==8)return ai-aj<bi-bj;\n                if(orderMode==9)return ai-aj>bi-bj;\n                if(orderMode==10)return (long double)sub[a]/sz[a]>(long double)sub[b]/sz[b];\n\n                return (long double)sub[a]/sz[a]<(long double)sub[b]/sz[b];\n            });\n        }\n\n        string ans;\n        ans.reserve(2*V);\n\n        function<void(int)> tour=[&](int u){\n            for(int w:tr[u]){\n                ans.push_back(pc[w]);\n                tour(w);\n                ans.push_back(opp(pc[w]));\n            }\n        };\n\n        tour(0);\n        return ans;\n    };\n\n    auto make_dfs=[&](int bm,int om){\n        vector<int> vis(V),parent(V,-1);\n        vector<char> pc(V);\n\n        function<void(int)> build=[&](int u){\n            vis[u]=1;\n            vector<Edge> es=g[u];\n\n            sort(es.begin(),es.end(),[&](auto&a,auto&b){\n                auto A=prio(a.to,bm),B=prio(b.to,bm);\n                if(A!=B)return A>B;\n                return a.to<b.to;\n            });\n\n            for(auto e:es)if(!vis[e.to]){\n                parent[e.to]=u;\n                pc[e.to]=e.c;\n                build(e.to);\n            }\n        };\n\n        build(0);\n        return tree_tour_from_parent(parent,pc,om);\n    };\n\n    for(int bm=0;bm<14;bm++){\n        for(int om=0;om<12;om++){\n            if(elapsed()>0.80)break;\n            string s=make_dfs(bm,om);\n            addcand(s);\n            addcand(revroute(s));\n        }\n    }\n\n    auto make_prim_tree=[&](int mode,int om){\n        vector<int> used(V,0),parent(V,-1);\n        vector<char> pc(V,'?');\n\n        struct Node{\n            long double key;\n            int from,to;\n            char c;\n            bool operator<(const Node&other)const{\n                return key<other.key;\n            }\n        };\n\n        priority_queue<Node> pq;\n        used[0]=1;\n\n        auto push_edges=[&](int u){\n            for(auto e:g[u]){\n                if(used[e.to])continue;\n\n                auto [ui,uj]=pos(u);\n                auto [vi,vj]=pos(e.to);\n\n                long double cen=fabsl(vi-(N-1)/2.0L)+fabsl(vj-(N-1)/2.0L);\n                long double key=0;\n\n                if(mode==0)key=dirt[e.to];\n                else if(mode==1)key=-dirt[e.to];\n                else if(mode==2)key=-dist[0][e.to];\n                else if(mode==3)key=dist[0][e.to];\n                else if(mode==4)key=dirt[e.to]-3*dist[0][e.to];\n                else if(mode==5)key=dirt[e.to]+3*dist[0][e.to];\n                else if(mode==6)key=(long double)dirt[e.to]/(dist[0][e.to]+1);\n                else if(mode==7)key=-cen;\n                else if(mode==8)key=cen;\n                else if(mode==9)key=vi+vj;\n                else if(mode==10)key=-(vi+vj);\n                else key=(long double)dirt[e.to]+0.1L*(ui+uj);\n\n                pq.push({key,u,e.to,e.c});\n            }\n        };\n\n        push_edges(0);\n        int cnt=1;\n\n        while(!pq.empty()&&cnt<V){\n            auto cur=pq.top();\n            pq.pop();\n\n            if(used[cur.to])continue;\n\n            used[cur.to]=1;\n            parent[cur.to]=cur.from;\n            pc[cur.to]=cur.c;\n            cnt++;\n\n            push_edges(cur.to);\n        }\n\n        return tree_tour_from_parent(parent,pc,om);\n    };\n\n    for(int mode=0;mode<12;mode++){\n        for(int om=0;om<8;om++){\n            if(elapsed()>0.93)break;\n            string s=make_prim_tree(mode,om);\n            addcand(s);\n            addcand(revroute(s));\n        }\n    }\n\n    auto route_from_order=[&](const vector<int>&ord,bool skip){\n        vector<char> used(V);\n        string ans;\n        int cur=0;\n        used[0]=1;\n\n        for(int x:ord){\n            if(x==cur)continue;\n            if(skip&&used[x])continue;\n\n            string p=path(cur,x);\n            for(char c:p){\n                ans.push_back(c);\n                cur=step(cur,c);\n                used[cur]=1;\n            }\n        }\n\n        for(int x=0;x<V;x++)if(!used[x]){\n            string p=path(cur,x);\n            for(char c:p){\n                ans.push_back(c);\n                cur=step(cur,c);\n                used[cur]=1;\n            }\n        }\n\n        ans+=path(cur,0);\n        return ans;\n    };\n\n    vector<vector<int>> orders;\n\n    {\n        vector<int> o;\n        for(int i=0;i<N;i++)for(int j=0;j<N;j++)o.push_back(id(i,j));\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n    {\n        vector<int> o;\n        for(int j=0;j<N;j++)for(int i=0;i<N;i++)o.push_back(id(i,j));\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n    {\n        vector<int> o;\n        for(int i=0;i<N;i++){\n            if(i%2==0)for(int j=0;j<N;j++)o.push_back(id(i,j));\n            else for(int j=N-1;j>=0;j--)o.push_back(id(i,j));\n        }\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n    {\n        vector<int> o;\n        for(int j=0;j<N;j++){\n            if(j%2==0)for(int i=0;i<N;i++)o.push_back(id(i,j));\n            else for(int i=N-1;i>=0;i--)o.push_back(id(i,j));\n        }\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n    {\n        vector<int> o;\n        for(int s=0;s<=2*(N-1);s++){\n            vector<int> tmp;\n            for(int i=0;i<N;i++){\n                int j=s-i;\n                if(0<=j&&j<N)tmp.push_back(id(i,j));\n            }\n            if(s%2)reverse(tmp.begin(),tmp.end());\n            for(int x:tmp)o.push_back(x);\n        }\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n    {\n        auto morton=[&](int x,int y){\n            int r=0;\n            for(int b=0;b<6;b++){\n                r|=((x>>b)&1)<<(2*b+1);\n                r|=((y>>b)&1)<<(2*b);\n            }\n            return r;\n        };\n\n        vector<int> o(V);\n        iota(o.begin(),o.end(),0);\n\n        sort(o.begin(),o.end(),[&](int a,int b){\n            auto [ai,aj]=pos(a);\n            auto [bi,bj]=pos(b);\n            return morton(ai,aj)<morton(bi,bj);\n        });\n\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    vector<int> Bs={2,3,4,5,6,8};\n\n    for(int B:Bs){\n        int RB=(N+B-1)/B;\n        int CB=(N+B-1)/B;\n\n        vector<pair<int,int>> blocks;\n\n        for(int br=0;br<RB;br++){\n            if(br%2==0){\n                for(int bc=0;bc<CB;bc++)blocks.push_back({br,bc});\n            }else{\n                for(int bc=CB-1;bc>=0;bc--)blocks.push_back({br,bc});\n            }\n        }\n\n        for(int var=0;var<2;var++){\n            vector<int> o;\n\n            for(auto [br,bc]:blocks){\n                vector<int> tmp;\n                int r0=br*B,r1=min(N,(br+1)*B);\n                int c0=bc*B,c1=min(N,(bc+1)*B);\n\n                for(int i=r0;i<r1;i++){\n                    if(((i-r0)&1)==0){\n                        for(int j=c0;j<c1;j++)tmp.push_back(id(i,j));\n                    }else{\n                        for(int j=c1-1;j>=c0;j--)tmp.push_back(id(i,j));\n                    }\n                }\n\n                if(var){\n                    sort(tmp.begin(),tmp.end(),[&](int a,int b){\n                        return dirt[a]>dirt[b];\n                    });\n                }\n\n                for(int x:tmp)o.push_back(x);\n            }\n\n            orders.push_back(o);\n            reverse(o.begin(),o.end());\n            orders.push_back(o);\n        }\n\n        vector<tuple<long long,int,int>> db;\n\n        for(int br=0;br<RB;br++){\n            for(int bc=0;bc<CB;bc++){\n                long long sum=0;\n                int r0=br*B,r1=min(N,(br+1)*B);\n                int c0=bc*B,c1=min(N,(bc+1)*B);\n\n                for(int i=r0;i<r1;i++){\n                    for(int j=c0;j<c1;j++){\n                        sum+=dirt[id(i,j)];\n                    }\n                }\n\n                db.push_back({-sum,br,bc});\n            }\n        }\n\n        sort(db.begin(),db.end());\n\n        vector<int> o;\n\n        for(auto [neg,br,bc]:db){\n            vector<int> tmp;\n            int r0=br*B,r1=min(N,(br+1)*B);\n            int c0=bc*B,c1=min(N,(bc+1)*B);\n\n            for(int i=r0;i<r1;i++){\n                for(int j=c0;j<c1;j++){\n                    tmp.push_back(id(i,j));\n                }\n            }\n\n            sort(tmp.begin(),tmp.end(),[&](int a,int b){\n                return dirt[a]>dirt[b];\n            });\n\n            for(int x:tmp)o.push_back(x);\n        }\n\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    for(int mode=0;mode<8;mode++){\n        vector<int> o(V);\n        iota(o.begin(),o.end(),0);\n\n        sort(o.begin(),o.end(),[&](int a,int b){\n            auto [ai,aj]=pos(a);\n            auto [bi,bj]=pos(b);\n\n            long double A,B;\n\n            if(mode==0){\n                A=dist[0][a];\n                B=dist[0][b];\n            }else if(mode==1){\n                A=-dist[0][a];\n                B=-dist[0][b];\n            }else if(mode==2){\n                A=dirt[a];\n                B=dirt[b];\n            }else if(mode==3){\n                A=-dirt[a];\n                B=-dirt[b];\n            }else if(mode==4){\n                A=ai+aj;\n                B=bi+bj;\n            }else if(mode==5){\n                A=ai-aj;\n                B=bi-bj;\n            }else if(mode==6){\n                A=(long double)dirt[a]/(dist[0][a]+1);\n                B=(long double)dirt[b]/(dist[0][b]+1);\n            }else{\n                A=(long double)dirt[a]-5*dist[0][a];\n                B=(long double)dirt[b]-5*dist[0][b];\n            }\n\n            if(A!=B)return A<B;\n            return a<b;\n        });\n\n        orders.push_back(o);\n        reverse(o.begin(),o.end());\n        orders.push_back(o);\n    }\n\n    for(auto&o:orders){\n        if(elapsed()>1.08)break;\n\n        string s=route_from_order(o,true);\n        addcand(s);\n        addcand(revroute(s));\n\n        if(elapsed()>1.08)break;\n\n        string t=route_from_order(o,false);\n        addcand(t);\n        addcand(revroute(t));\n    }\n\n    mt19937 rng(712367);\n    uniform_real_distribution<double> ur(-1,1);\n\n    auto make_greedy=[&](int mode,double noise){\n        vector<char> un(V,1);\n        un[0]=0;\n\n        int rem=V-1,cur=0;\n        string ans;\n        ans.reserve(20000);\n\n        while(rem>0){\n            int best=-1;\n            long double bs=-1e100L;\n\n            for(int x=0;x<V;x++)if(un[x]){\n                int dd=max(1,dist[cur][x]);\n                auto [ci,cj]=pos(cur);\n                auto [xi,xj]=pos(x);\n\n                long double geo=abs(xi-ci)+abs(xj-cj);\n                long double cen=fabsl(xi-(N-1)/2.0L)+fabsl(xj-(N-1)/2.0L);\n                long double sc;\n\n                if(mode==0)sc=-dd;\n                else if(mode==1)sc=(long double)dirt[x]/dd;\n                else if(mode==2)sc=(long double)dirt[x]/sqrt((long double)dd);\n                else if(mode==3)sc=(long double)dirt[x]-10.0L*dd;\n                else if(mode==4)sc=sqrt((long double)dirt[x])-dd;\n                else if(mode==5)sc=-dd+0.05L*dirt[x]-0.1L*geo;\n                else if(mode==6)sc=-dd+0.02L*dirt[x]+0.5L*geo;\n                else if(mode==7)sc=(long double)dirt[x]/(dd+5);\n                else if(mode==8)sc=(long double)dirt[x]/pow((long double)dd,0.75L);\n                else if(mode==9)sc=-dd+0.01L*dirt[x];\n                else if(mode==10)sc=-dd+0.03L*dirt[x];\n                else if(mode==11)sc=-dd+0.08L*dirt[x];\n                else if(mode==12)sc=(long double)dirt[x]/(dd+1)-0.03L*cen;\n                else if(mode==13)sc=-dd+0.04L*dirt[x]+0.02L*cen;\n                else if(mode==14)sc=-dd+0.02L*dirt[x]-0.25L*dist[0][x];\n                else sc=(long double)dirt[x]/pow((long double)(dd+1),0.55L)-0.05L*dist[0][x];\n\n                sc+=noise*ur(rng);\n\n                if(sc>bs){\n                    bs=sc;\n                    best=x;\n                }\n            }\n\n            string p=path(cur,best);\n\n            for(char c:p){\n                ans.push_back(c);\n                cur=step(cur,c);\n                if(un[cur]){\n                    un[cur]=0;\n                    rem--;\n                }\n            }\n\n            if((int)ans.size()>90000)break;\n        }\n\n        ans+=path(cur,0);\n        return ans;\n    };\n\n    for(int m=0;m<16;m++){\n        if(elapsed()>1.19)break;\n        string s=make_greedy(m,0);\n        addcand(s);\n        addcand(revroute(s));\n    }\n\n    int trials=0;\n    while(elapsed()<1.34&&trials<55){\n        string s=make_greedy(trials%16,0.4+(trials%10)*0.7);\n        addcand(s);\n        addcand(revroute(s));\n        trials++;\n    }\n\n    sort(cands.begin(),cands.end(),[](auto&a,auto&b){\n        return a.score<b.score;\n    });\n\n    auto route_positions=[&](const string&s){\n        vector<int> rp;\n        rp.reserve(s.size()+1);\n\n        int cur=0;\n        rp.push_back(cur);\n\n        for(char c:s){\n            cur=step(cur,c);\n            rp.push_back(cur);\n        }\n\n        return rp;\n    };\n\n    {\n        vector<string> ex;\n\n        for(int bi=0;bi<min<int>(12,cands.size());bi++){\n            const string&s=cands[bi].route;\n            int cur=0;\n            vector<int> cuts;\n\n            for(int t=0;t<(int)s.size();t++){\n                cur=step(cur,s[t]);\n                if(cur==0&&t+1<(int)s.size())cuts.push_back(t+1);\n            }\n\n            int stride=max(1,(int)cuts.size()/10);\n\n            for(int k=0;k<(int)cuts.size();k+=stride){\n                int cut=cuts[k];\n                ex.push_back(s.substr(cut)+s.substr(0,cut));\n            }\n        }\n\n        for(auto&s:ex){\n            if(elapsed()>1.43)break;\n            addcand(s);\n        }\n    }\n\n    sort(cands.begin(),cands.end(),[](auto&a,auto&b){\n        return a.score<b.score;\n    });\n\n    auto reverse_segment=[&](const string&s,int l,int r){\n        string ns;\n        ns.reserve(s.size());\n\n        ns.append(s.begin(),s.begin()+l);\n\n        for(int i=r-1;i>=l;i--){\n            ns.push_back(opp(s[i]));\n        }\n\n        ns.append(s.begin()+r,s.end());\n\n        return ns;\n    };\n\n    auto rotate_segment=[&](const string&s,int l,int m,int r){\n        string ns;\n        ns.reserve(s.size());\n\n        ns.append(s.begin(),s.begin()+l);\n        ns.append(s.begin()+m,s.begin()+r);\n        ns.append(s.begin()+l,s.begin()+m);\n        ns.append(s.begin()+r,s.end());\n\n        return ns;\n    };\n\n    auto delete_segment=[&](const string&s,int l,int r){\n        string ns;\n        ns.reserve(s.size()-(r-l));\n\n        ns.append(s.begin(),s.begin()+l);\n        ns.append(s.begin()+r,s.end());\n\n        return ns;\n    };\n\n    auto relocate_segment=[&](const string&s,int l,int r,int p){\n        // Closed segment [l,r) is moved to position p, where p is an occurrence of same endpoint.\n        // p must be outside [l,r].\n        string seg=s.substr(l,r-l);\n        string base;\n\n        base.reserve(s.size()-(r-l));\n        base.append(s.begin(),s.begin()+l);\n        base.append(s.begin()+r,s.end());\n\n        int pp=p;\n        if(p>r)pp=p-(r-l);\n        // insert at pp\n        string ns;\n        ns.reserve(s.size());\n        ns.append(base.begin(),base.begin()+pp);\n        ns+=seg;\n        ns.append(base.begin()+pp,base.end());\n        return ns;\n    };\n\n    auto local_opt_first=[&](string curRoute,long double curScore,double timelimit,int maxIter,int opLimit){\n        for(int iter=0;iter<maxIter;iter++){\n            if(elapsed()>timelimit)break;\n\n            auto rp=route_positions(curRoute);\n\n            vector<vector<int>> occ(V);\n            vector<int> cnt(V,0);\n\n            for(int p:rp)cnt[p]++;\n            for(int i=0;i<(int)rp.size();i++)occ[rp[i]].push_back(i);\n\n            struct Op{\n                long double key;\n                int type,l,m,r,p;\n            };\n\n            vector<Op> ops;\n            ops.reserve(7000);\n\n            for(int x=0;x<V;x++){\n                auto &vec=occ[x];\n                int msz=vec.size();\n                if(msz<2)continue;\n\n                for(int a=0;a<msz;a++){\n                    for(int delta:{1,2,3,4,5}){\n                        int b=a+delta;\n                        if(b>=msz)continue;\n\n                        int l=vec[a],r=vec[b];\n                        if(r-l<4)continue;\n\n                        long double key=(long double)dirt[x]*sqrt((long double)(r-l));\n\n                        ops.push_back({key,0,l,-1,r,-1});\n\n                        if(delta>=2){\n                            int mid=vec[a+delta/2];\n                            if(mid>l&&mid<r){\n                                ops.push_back({key*0.92L,1,l,mid,r,-1});\n                            }\n                        }\n\n                        if(r-l<=80){\n                            ops.push_back({key*0.75L,2,l,-1,r,-1});\n                        }\n                    }\n\n                    if(msz>=6){\n                        int b=min(msz-1,a+msz/2);\n\n                        if(b>a){\n                            int l=vec[a],r=vec[b];\n\n                            if(r-l>=6){\n                                long double key=(long double)dirt[x]*0.55L*sqrt((long double)(r-l));\n\n                                ops.push_back({key,0,l,-1,r,-1});\n\n                                int mid=vec[(a+b)/2];\n\n                                if(mid>l&&mid<r){\n                                    ops.push_back({key*0.9L,1,l,mid,r,-1});\n                                }\n\n                                if(r-l<=100){\n                                    ops.push_back({key*0.6L,2,l,-1,r,-1});\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n\n            shuffle(ops.begin(),ops.end(),rng);\n\n            sort(ops.begin(),ops.end(),[](const Op&a,const Op&b){\n                return a.key>b.key;\n            });\n\n            auto safe_delete_fast=[&](int l,int r){\n                for(int i=l+1;i<r;i++){\n                    if(cnt[rp[i]]<=1)return false;\n                }\n                return true;\n            };\n\n            bool improved=false;\n            int lim=min<int>(opLimit,ops.size());\n\n            for(int k=0;k<lim;k++){\n                string ns;\n\n                if(ops[k].type==0){\n                    ns=reverse_segment(curRoute,ops[k].l,ops[k].r);\n                }else if(ops[k].type==1){\n                    ns=rotate_segment(curRoute,ops[k].l,ops[k].m,ops[k].r);\n                }else{\n                    if(!safe_delete_fast(ops[k].l,ops[k].r))continue;\n                    ns=delete_segment(curRoute,ops[k].l,ops[k].r);\n                }\n\n                long double sc=eval(ns);\n\n                if(sc+1e-9L<curScore){\n                    curRoute.swap(ns);\n                    curScore=sc;\n                    improved=true;\n                    break;\n                }\n\n                if(elapsed()>timelimit)break;\n            }\n\n            if(!improved)break;\n        }\n\n        return pair<string,long double>{curRoute,curScore};\n    };\n\n    auto local_opt_best=[&](string curRoute,long double curScore,double timelimit,int maxIter,int opLimit){\n        for(int iter=0;iter<maxIter;iter++){\n            if(elapsed()>timelimit)break;\n\n            auto rp=route_positions(curRoute);\n\n            vector<vector<int>> occ(V);\n            vector<int> cnt(V,0);\n\n            for(int p:rp)cnt[p]++;\n            for(int i=0;i<(int)rp.size();i++)occ[rp[i]].push_back(i);\n\n            struct Op{\n                long double key;\n                int type,l,m,r,p;\n            };\n\n            vector<Op> ops;\n            ops.reserve(10000);\n\n            for(int x=0;x<V;x++){\n                auto &vec=occ[x];\n                int msz=vec.size();\n                if(msz<2)continue;\n\n                for(int a=0;a<msz;a++){\n                    for(int delta:{1,2,3,4,5,6}){\n                        int b=a+delta;\n                        if(b>=msz)continue;\n\n                        int l=vec[a],r=vec[b];\n                        if(r-l<4)continue;\n\n                        long double key=(long double)dirt[x]*sqrt((long double)(r-l));\n\n                        ops.push_back({key,0,l,-1,r,-1});\n\n                        if(delta>=2){\n                            int mid=vec[a+delta/2];\n                            if(mid>l&&mid<r){\n                                ops.push_back({key*0.92L,1,l,mid,r,-1});\n                            }\n                        }\n\n                        if(r-l<=120){\n                            ops.push_back({key*0.7L,2,l,-1,r,-1});\n                        }\n\n                        // Relocate short/medium closed subwalk to another occurrence of same cell.\n                        if(r-l<=160 && msz>=3){\n                            int p1=vec[0];\n                            int p2=vec[msz-1];\n                            int p3=vec[msz/2];\n\n                            for(int pp: {p1,p2,p3}){\n                                if(pp>=l && pp<=r)continue;\n                                long double k2=key*0.65L;\n                                ops.push_back({k2,3,l,-1,r,pp});\n                            }\n                        }\n                    }\n                }\n            }\n\n            shuffle(ops.begin(),ops.end(),rng);\n\n            sort(ops.begin(),ops.end(),[](const Op&a,const Op&b){\n                return a.key>b.key;\n            });\n\n            auto safe_delete_fast=[&](int l,int r){\n                for(int i=l+1;i<r;i++){\n                    if(cnt[rp[i]]<=1)return false;\n                }\n                return true;\n            };\n\n            bool found=false;\n            string bestRoute;\n            long double bestScore=curScore;\n\n            int lim=min<int>(opLimit,ops.size());\n\n            for(int k=0;k<lim;k++){\n                if(elapsed()>timelimit)break;\n\n                string ns;\n\n                if(ops[k].type==0){\n                    ns=reverse_segment(curRoute,ops[k].l,ops[k].r);\n                }else if(ops[k].type==1){\n                    ns=rotate_segment(curRoute,ops[k].l,ops[k].m,ops[k].r);\n                }else if(ops[k].type==2){\n                    if(!safe_delete_fast(ops[k].l,ops[k].r))continue;\n                    ns=delete_segment(curRoute,ops[k].l,ops[k].r);\n                }else{\n                    ns=relocate_segment(curRoute,ops[k].l,ops[k].r,ops[k].p);\n                }\n\n                long double sc=eval(ns);\n\n                if(sc+1e-9L<bestScore){\n                    bestScore=sc;\n                    bestRoute.swap(ns);\n                    found=true;\n                }\n            }\n\n            if(found){\n                curRoute.swap(bestRoute);\n                curScore=bestScore;\n            }else{\n                break;\n            }\n        }\n\n        return pair<string,long double>{curRoute,curScore};\n    };\n\n    {\n        vector<string> improved;\n        int base=min<int>(8,cands.size());\n\n        for(int bi=0;bi<base;bi++){\n            if(elapsed()>1.70)break;\n\n            auto res=local_opt_first(cands[bi].route,cands[bi].score,1.70,6,95);\n            improved.push_back(res.first);\n        }\n\n        for(auto&s:improved){\n            if(elapsed()>1.73)break;\n            addcand(s);\n        }\n    }\n\n    sort(cands.begin(),cands.end(),[](auto&a,auto&b){\n        return a.score<b.score;\n    });\n\n    vector<int> hi(V);\n    iota(hi.begin(),hi.end(),0);\n\n    sort(hi.begin(),hi.end(),[&](int a,int b){\n        return dirt[a]>dirt[b];\n    });\n\n    hi.resize(min(V,100));\n\n    vector<string>dets;\n    int base=min<int>(5,cands.size());\n\n    for(int bi=0;bi<base;bi++){\n        string s=cands[bi].route;\n        long double best=cands[bi].score;\n\n        for(int it=0;it<3;it++){\n            if(elapsed()>1.84)break;\n\n            auto rp=route_positions(s);\n            int L=s.size();\n\n            vector<tuple<long double,int,int>> ops;\n            int stride=max(1,L/180);\n\n            for(int t=0;t<L;t+=stride){\n                int u=rp[t];\n\n                for(int x:hi){\n                    int dd=dist[u][x];\n\n                    if(dd<=0||dd>8)continue;\n\n                    long double merit=(long double)dirt[x]/(2*dd+1);\n\n                    ops.push_back({merit,t,x});\n                }\n            }\n\n            sort(ops.begin(),ops.end(),greater<>());\n\n            bool imp=false;\n            int lim=min<int>(35,ops.size());\n\n            for(int k=0;k<lim;k++){\n                auto [mer,t,x]=ops[k];\n\n                int u=rp[t];\n\n                string go=path(u,x);\n                string ba=path(x,u);\n\n                if((int)s.size()+(int)go.size()+(int)ba.size()>100000)continue;\n\n                string ns;\n\n                ns.reserve(s.size()+go.size()+ba.size());\n                ns.append(s.begin(),s.begin()+t);\n                ns+=go;\n                ns+=ba;\n                ns.append(s.begin()+t,s.end());\n\n                long double sc=eval(ns);\n\n                if(sc+1e-9L<best){\n                    s.swap(ns);\n                    best=sc;\n                    imp=true;\n                    break;\n                }\n            }\n\n            if(!imp)break;\n        }\n\n        dets.push_back(s);\n    }\n\n    for(auto&s:dets){\n        if(elapsed()>1.88)break;\n        addcand(s);\n    }\n\n    sort(cands.begin(),cands.end(),[](auto&a,auto&b){\n        return a.score<b.score;\n    });\n\n    if(elapsed()<1.93 && !cands.empty()){\n        auto res=local_opt_best(cands[0].route,cands[0].score,1.945,3,150);\n        addcand(res.first);\n    }\n\n    sort(cands.begin(),cands.end(),[](auto&a,auto&b){\n        return a.score<b.score;\n    });\n\n    {\n        vector<string> conc;\n        int bc=min<int>(7,cands.size());\n\n        for(int i=0;i<bc;i++){\n            for(int j=0;j<bc;j++){\n                if(i==j)continue;\n\n                if((int)cands[i].route.size()+(int)cands[j].route.size()<=100000){\n                    conc.push_back(cands[i].route+cands[j].route);\n                }\n            }\n        }\n\n        for(auto&s:conc){\n            if(elapsed()>1.97)break;\n            addcand(s);\n        }\n    }\n\n    int best=0;\n\n    for(int i=1;i<(int)cands.size();i++){\n        if(cands[i].score<cands[best].score)best=i;\n    }\n\n    cout<<cands[best].route<<\"\\n\";\n    return 0;\n}","ahc028":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int r, c;\n};\n\nint mdist(const Pos& a, const Pos& b) {\n    return abs(a.r - b.r) + abs(a.c - b.c);\n}\n\nint overlap_len(const string& a, const string& b) {\n    int best = 0;\n    for (int k = 1; k <= 4; k++) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[5 - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) best = k;\n    }\n    return best;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    cin >> N >> M;\n\n    Pos start;\n    cin >> start.r >> start.c;\n\n    vector<string> grid(N);\n    for (int i = 0; i < N; i++) cin >> grid[i];\n\n    vector<string> word(M);\n    for (int i = 0; i < M; i++) cin >> word[i];\n\n    vector<vector<Pos>> occ(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            occ[grid[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) {\n            if (i != j) ov[i][j] = overlap_len(word[i], word[j]);\n        }\n    }\n\n    vector<vector<vector<vector<unsigned char>>>> cd(\n        26, vector<vector<vector<unsigned char>>>(26)\n    );\n\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            cd[a][b].assign(occ[a].size(), vector<unsigned char>(occ[b].size()));\n            for (int i = 0; i < (int)occ[a].size(); i++) {\n                for (int j = 0; j < (int)occ[b].size(); j++) {\n                    cd[a][b][i][j] = (unsigned char)(mdist(occ[a][i], occ[b][j]) + 1);\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> letter_cost(26, vector<int>(26, 1000000));\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            for (int i = 0; i < (int)occ[a].size(); i++) {\n                for (int j = 0; j < (int)occ[b].size(); j++) {\n                    letter_cost[a][b] = min<int>(letter_cost[a][b], cd[a][b][i][j]);\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> trans_cost(M, vector<int>(M, 0));\n    for (int a = 0; a < M; a++) {\n        for (int b = 0; b < M; b++) {\n            if (a == b) continue;\n\n            int k = ov[a][b];\n            int cost = 0;\n            char prev = word[a].back();\n\n            for (int p = k; p < 5; p++) {\n                char ch = word[b][p];\n                cost += letter_cost[prev - 'A'][ch - 'A'];\n                prev = ch;\n            }\n\n            trans_cost[a][b] = cost;\n        }\n    }\n\n    const int BIG = 10000;\n    const int START_PENALTY = 5 * BIG;\n\n    vector<int> weights = {0, 4, 8, 12, 16, 18, 22, 28, 36};\n    vector<vector<vector<int>>> edges;\n\n    for (int w : weights) {\n        vector<vector<int>> edge(M, vector<int>(M));\n        for (int a = 0; a < M; a++) {\n            for (int b = 0; b < M; b++) {\n                if (a == b) edge[a][b] = 0;\n                else edge[a][b] = (5 - ov[a][b]) * BIG + w * trans_cost[a][b];\n            }\n        }\n        edges.push_back(move(edge));\n    }\n\n    int base_edge_idx = 5;\n    const auto& base_edge = edges[base_edge_idx];\n\n    auto order_value = [&](const vector<int>& ord, const vector<vector<int>>& edge) {\n        int v = START_PENALTY;\n        for (int i = 1; i < (int)ord.size(); i++) {\n            v += edge[ord[i - 1]][ord[i]];\n        }\n        return v;\n    };\n\n    auto build_string = [&](const vector<int>& ord) {\n        string s = word[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            int k = ov[ord[i - 1]][ord[i]];\n            s += word[ord[i]].substr(k);\n        }\n        return s;\n    };\n\n    auto covers_all = [&](const string& s) {\n        for (int i = 0; i < M; i++) {\n            if (s.find(word[i]) == string::npos) return false;\n        }\n        return true;\n    };\n\n    auto exact_cost_only = [&](const string& s) {\n        const int INF = 1e9;\n\n        int c0 = s[0] - 'A';\n        vector<int> dp(occ[c0].size(), INF);\n\n        for (int i = 0; i < (int)occ[c0].size(); i++) {\n            dp[i] = mdist(start, occ[c0][i]) + 1;\n        }\n\n        for (int p = 1; p < (int)s.size(); p++) {\n            int pc = s[p - 1] - 'A';\n            int cc = s[p] - 'A';\n\n            vector<int> ndp(occ[cc].size(), INF);\n\n            for (int i = 0; i < (int)occ[pc].size(); i++) {\n                int base = dp[i];\n                if (base >= INF) continue;\n\n                for (int j = 0; j < (int)occ[cc].size(); j++) {\n                    int val = base + cd[pc][cc][i][j];\n                    if (val < ndp[j]) ndp[j] = val;\n                }\n            }\n\n            dp.swap(ndp);\n        }\n\n        return *min_element(dp.begin(), dp.end());\n    };\n\n    mt19937 rng(31415926);\n    auto global_start = chrono::steady_clock::now();\n\n    auto elapsed_time = [&]() {\n        return chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n    };\n\n    auto make_append_greedy = [&](int st, double noise, double cw) {\n        vector<int> ord;\n        vector<char> used(M, false);\n        ord.reserve(M);\n\n        int cur = st;\n        ord.push_back(cur);\n        used[cur] = true;\n\n        for (int step = 1; step < M; step++) {\n            int best = -1;\n            double best_score = -1e100;\n\n            for (int nxt = 0; nxt < M; nxt++) {\n                if (used[nxt]) continue;\n\n                int mxout = 0;\n                for (int z = 0; z < M; z++) {\n                    if (!used[z] && z != nxt) {\n                        mxout = max(mxout, ov[nxt][z]);\n                    }\n                }\n\n                double score = 1260.0 * ov[cur][nxt]\n                             + 16.0 * mxout\n                             - cw * trans_cost[cur][nxt];\n\n                if (noise > 0) {\n                    score += uniform_real_distribution<double>(0.0, noise)(rng);\n                }\n\n                if (score > best_score) {\n                    best_score = score;\n                    best = nxt;\n                }\n            }\n\n            cur = best;\n            used[cur] = true;\n            ord.push_back(cur);\n        }\n\n        return ord;\n    };\n\n    auto make_insertion_greedy = [&](int st, double noise, const vector<vector<int>>& edge) {\n        vector<int> ord;\n        vector<char> used(M, false);\n\n        ord.push_back(st);\n        used[st] = true;\n\n        while ((int)ord.size() < M) {\n            int sz = ord.size();\n            int best_word = -1;\n            int best_pos = -1;\n            double best_gain = 1e100;\n\n            for (int x = 0; x < M; x++) {\n                if (used[x]) continue;\n\n                for (int pos = 0; pos <= sz; pos++) {\n                    int gain;\n                    if (pos == 0) {\n                        gain = edge[x][ord[0]];\n                    } else if (pos == sz) {\n                        gain = edge[ord[sz - 1]][x];\n                    } else {\n                        int a = ord[pos - 1];\n                        int b = ord[pos];\n                        gain = edge[a][x] + edge[x][b] - edge[a][b];\n                    }\n\n                    double g = gain;\n                    if (noise > 0) {\n                        g += uniform_real_distribution<double>(0.0, noise)(rng);\n                    }\n\n                    if (g < best_gain) {\n                        best_gain = g;\n                        best_word = x;\n                        best_pos = pos;\n                    }\n                }\n            }\n\n            ord.insert(ord.begin() + best_pos, best_word);\n            used[best_word] = true;\n        }\n\n        return ord;\n    };\n\n    auto improve_swap = [&](vector<int> ord, const vector<vector<int>>& edge,\n                            double limit_time) {\n        for (int round = 0; round < 2; round++) {\n            bool improved = false;\n\n            for (int i = 0; i < M; i++) {\n                for (int j = i + 1; j < M; j++) {\n                    vector<int> idxs;\n                    for (int x : {i - 1, i, j - 1, j}) {\n                        if (0 <= x && x + 1 < M) idxs.push_back(x);\n                    }\n                    sort(idxs.begin(), idxs.end());\n                    idxs.erase(unique(idxs.begin(), idxs.end()), idxs.end());\n\n                    int before = 0, after = 0;\n                    for (int x : idxs) before += edge[ord[x]][ord[x + 1]];\n\n                    swap(ord[i], ord[j]);\n\n                    for (int x : idxs) after += edge[ord[x]][ord[x + 1]];\n\n                    if (after < before) {\n                        improved = true;\n                    } else {\n                        swap(ord[i], ord[j]);\n                    }\n                }\n\n                if (elapsed_time() > limit_time) return ord;\n            }\n\n            if (!improved) break;\n        }\n\n        return ord;\n    };\n\n    auto improve_reinsert_fast = [&](vector<int> ord, const vector<vector<int>>& edge,\n                                     double limit_time) {\n        auto e = [&](int a, int b) {\n            if (a < 0 || b < 0) return 0;\n            return edge[a][b];\n        };\n\n        for (int round = 0; round < 2; round++) {\n            bool any = false;\n\n            for (int i = 0; i < M; i++) {\n                int x = ord[i];\n\n                int left = (i > 0 ? ord[i - 1] : -1);\n                int right = (i + 1 < M ? ord[i + 1] : -1);\n\n                int remove_delta = -e(left, x) - e(x, right) + e(left, right);\n\n                int best_pos = -1;\n                int best_delta = 0;\n\n                for (int pos = 0; pos <= M - 1; pos++) {\n                    if (pos == i || pos == i + 1) continue;\n\n                    int a, b;\n                    if (pos == 0) {\n                        a = -1;\n                        b = ord[0];\n                    } else if (pos == M - 1) {\n                        a = ord[M - 1];\n                        b = -1;\n                    } else {\n                        a = ord[pos - 1];\n                        b = ord[pos];\n                    }\n\n                    if (a == x || b == x) continue;\n\n                    int insert_delta = -e(a, b) + e(a, x) + e(x, b);\n                    int delta = remove_delta + insert_delta;\n\n                    if (delta < best_delta) {\n                        best_delta = delta;\n                        best_pos = pos;\n                    }\n                }\n\n                if (best_pos != -1) {\n                    int val = x;\n                    ord.erase(ord.begin() + i);\n                    if (best_pos > i) best_pos--;\n                    ord.insert(ord.begin() + best_pos, val);\n                    any = true;\n                }\n\n                if (elapsed_time() > limit_time) return ord;\n            }\n\n            if (!any) break;\n        }\n\n        return ord;\n    };\n\n    auto remove_redundant = [&](vector<int> ord, double limit_time) {\n        bool changed = true;\n\n        while (changed) {\n            changed = false;\n\n            for (int i = 0; i < (int)ord.size(); i++) {\n                if (elapsed_time() > limit_time) return ord;\n\n                vector<int> cand = ord;\n                cand.erase(cand.begin() + i);\n\n                string s = build_string(cand);\n                if (covers_all(s)) {\n                    ord.swap(cand);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n\n        return ord;\n    };\n\n    vector<vector<int>> candidates;\n\n    auto add_candidate = [&](vector<int> ord) {\n        candidates.push_back(move(ord));\n    };\n\n    for (int st = 0; st < M; st++) {\n        add_candidate(make_append_greedy(st, 0.0, 2.5));\n    }\n\n    for (int wi = 0; wi < (int)edges.size(); wi += 2) {\n        for (int st = wi; st < M; st += 27) {\n            if (elapsed_time() > 0.40) goto deterministic_insert_done;\n            add_candidate(make_insertion_greedy(st, 0.0, edges[wi]));\n        }\n    }\n\ndeterministic_insert_done:\n\n    while (elapsed_time() < 0.74) {\n        int type = uniform_int_distribution<int>(0, 2)(rng);\n\n        if (type == 0) {\n            int st = uniform_int_distribution<int>(0, M - 1)(rng);\n            double noise = uniform_real_distribution<double>(50.0, 850.0)(rng);\n            double cw = uniform_real_distribution<double>(0.2, 7.5)(rng);\n            add_candidate(make_append_greedy(st, noise, cw));\n        } else {\n            int st = uniform_int_distribution<int>(0, M - 1)(rng);\n            double noise = uniform_real_distribution<double>(0.0, 800.0)(rng);\n            int wi = uniform_int_distribution<int>(0, (int)edges.size() - 1)(rng);\n            add_candidate(make_insertion_greedy(st, noise, edges[wi]));\n        }\n    }\n\n    sort(candidates.begin(), candidates.end(), [&](const vector<int>& a, const vector<int>& b) {\n        return order_value(a, base_edge) < order_value(b, base_edge);\n    });\n\n    if ((int)candidates.size() > 36) candidates.resize(36);\n\n    vector<vector<int>> pool = candidates;\n\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        if (elapsed_time() > 1.15) break;\n\n        const auto& edge = edges[i % edges.size()];\n        vector<int> ord = candidates[i];\n\n        if (i % 3 == 0) {\n            ord = improve_reinsert_fast(ord, edge, 1.15);\n        } else {\n            ord = improve_swap(ord, edge, 1.15);\n        }\n\n        pool.push_back(ord);\n\n        if (i < 5) {\n            vector<int> compressed = remove_redundant(ord, 1.23);\n            pool.push_back(move(compressed));\n        }\n    }\n\n    sort(pool.begin(), pool.end());\n    pool.erase(unique(pool.begin(), pool.end()), pool.end());\n\n    sort(pool.begin(), pool.end(), [&](const vector<int>& a, const vector<int>& b) {\n        return order_value(a, base_edge) < order_value(b, base_edge);\n    });\n\n    if ((int)pool.size() > 65) pool.resize(65);\n\n    string best_s;\n    vector<int> best_ord;\n    int best_exact = INT_MAX;\n\n    for (int i = 0; i < (int)pool.size(); i++) {\n        if (elapsed_time() > 1.48 && !best_s.empty()) break;\n\n        string s = build_string(pool[i]);\n        int cost = exact_cost_only(s);\n\n        if (cost < best_exact) {\n            best_exact = cost;\n            best_s = s;\n            best_ord = pool[i];\n        }\n    }\n\n    if (best_s.empty()) {\n        best_ord = pool[0];\n        best_s = build_string(best_ord);\n        best_exact = exact_cost_only(best_s);\n    }\n\n    auto edge_val = [&](int a, int b) {\n        if (a < 0 || b < 0) return 0;\n        return base_edge[a][b];\n    };\n\n    auto approx_reinsert_delta = [&](const vector<int>& ord, int i, int pos) {\n        int n = ord.size();\n        if (pos == i || pos == i + 1) return INT_MAX / 4;\n\n        int x = ord[i];\n\n        int l = (i > 0 ? ord[i - 1] : -1);\n        int r = (i + 1 < n ? ord[i + 1] : -1);\n\n        int delta = -edge_val(l, x) - edge_val(x, r) + edge_val(l, r);\n\n        int a, b;\n        if (pos == 0) {\n            a = -1;\n            b = ord[0];\n        } else if (pos == n) {\n            a = ord[n - 1];\n            b = -1;\n        } else {\n            a = ord[pos - 1];\n            b = ord[pos];\n        }\n\n        if (a == x || b == x) return INT_MAX / 4;\n\n        delta += -edge_val(a, b) + edge_val(a, x) + edge_val(x, b);\n        return delta;\n    };\n\n    auto approx_swap_delta = [&](const vector<int>& ord, int i, int j) {\n        if (i == j) return INT_MAX / 4;\n        if (i > j) swap(i, j);\n\n        vector<int> idxs;\n        for (int x : {i - 1, i, j - 1, j}) {\n            if (0 <= x && x + 1 < (int)ord.size()) idxs.push_back(x);\n        }\n        sort(idxs.begin(), idxs.end());\n        idxs.erase(unique(idxs.begin(), idxs.end()), idxs.end());\n\n        int before = 0, after = 0;\n        for (int x : idxs) before += edge_val(ord[x], ord[x + 1]);\n\n        vector<int> tmp = ord;\n        swap(tmp[i], tmp[j]);\n\n        for (int x : idxs) after += edge_val(tmp[x], tmp[x + 1]);\n\n        return after - before;\n    };\n\n    // Guided exact-cost polish: reinsert and swap only.\n    while (elapsed_time() < 1.84) {\n        int n = best_ord.size();\n        if (n <= 1) break;\n\n        struct Move {\n            int delta;\n            int type;\n            int a;\n            int b;\n        };\n\n        vector<Move> moves;\n        moves.reserve(128);\n\n        for (int rep = 0; rep < 115; rep++) {\n            int i = uniform_int_distribution<int>(0, n - 1)(rng);\n            int pos = uniform_int_distribution<int>(0, n)(rng);\n            int d = approx_reinsert_delta(best_ord, i, pos);\n            if (d < INT_MAX / 8) moves.push_back({d, 0, i, pos});\n        }\n\n        for (int rep = 0; rep < 85; rep++) {\n            int i = uniform_int_distribution<int>(0, n - 1)(rng);\n            int j = uniform_int_distribution<int>(0, n - 1)(rng);\n            if (i == j) continue;\n            int d = approx_swap_delta(best_ord, i, j);\n            if (d < INT_MAX / 8) moves.push_back({d, 1, i, j});\n        }\n\n        sort(moves.begin(), moves.end(), [](const Move& a, const Move& b) {\n            return a.delta < b.delta;\n        });\n\n        bool accepted = false;\n\n        int checks = min<int>(10, moves.size());\n\n        for (int mi = 0; mi < checks; mi++) {\n            if (elapsed_time() > 1.865) break;\n\n            vector<int> cand = best_ord;\n\n            if (moves[mi].type == 0) {\n                int i = moves[mi].a;\n                int pos = moves[mi].b;\n\n                int x = cand[i];\n                cand.erase(cand.begin() + i);\n                if (pos > i) pos--;\n                pos = max(0, min(pos, (int)cand.size()));\n                cand.insert(cand.begin() + pos, x);\n            } else {\n                int i = moves[mi].a;\n                int j = moves[mi].b;\n                swap(cand[i], cand[j]);\n            }\n\n            string s = build_string(cand);\n\n            if (!covers_all(s)) continue;\n\n            int cost = exact_cost_only(s);\n\n            if (cost < best_exact) {\n                best_exact = cost;\n                best_s = move(s);\n                best_ord = move(cand);\n                accepted = true;\n                break;\n            }\n        }\n\n        if (!accepted && elapsed_time() > 1.79) break;\n    }\n\n    int L = best_s.size();\n    const int INF = 1e9;\n\n    vector<vector<int>> dp(L);\n    vector<vector<int>> pre(L);\n\n    int first_c = best_s[0] - 'A';\n    dp[0].assign(occ[first_c].size(), INF);\n    pre[0].assign(occ[first_c].size(), -1);\n\n    for (int i = 0; i < (int)occ[first_c].size(); i++) {\n        dp[0][i] = mdist(start, occ[first_c][i]) + 1;\n    }\n\n    for (int p = 1; p < L; p++) {\n        int pc = best_s[p - 1] - 'A';\n        int cc = best_s[p] - 'A';\n\n        dp[p].assign(occ[cc].size(), INF);\n        pre[p].assign(occ[cc].size(), -1);\n\n        for (int i = 0; i < (int)occ[pc].size(); i++) {\n            int base = dp[p - 1][i];\n            if (base >= INF) continue;\n\n            for (int j = 0; j < (int)occ[cc].size(); j++) {\n                int val = base + cd[pc][cc][i][j];\n                if (val < dp[p][j]) {\n                    dp[p][j] = val;\n                    pre[p][j] = i;\n                }\n            }\n        }\n    }\n\n    int last_c = best_s.back() - 'A';\n    int best_last = 0;\n\n    for (int i = 1; i < (int)occ[last_c].size(); i++) {\n        if (dp[L - 1][i] < dp[L - 1][best_last]) {\n            best_last = i;\n        }\n    }\n\n    vector<Pos> ans(L);\n    int idx = best_last;\n\n    for (int p = L - 1; p >= 0; p--) {\n        int ch = best_s[p] - 'A';\n        ans[p] = occ[ch][idx];\n        idx = pre[p][idx];\n    }\n\n    for (auto& p : ans) {\n        cout << p.r << ' ' << p.c << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<unsigned long long> bits;\n};\n\nstruct Constraint {\n    int id;\n    int val;\n};\n\nstatic uint64_t rng_state = 1234567891234567ULL;\n\nstatic inline uint64_t rng64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\n\nstatic inline int randint(int n) {\n    return (int)(rng64() % n);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M;\n    double eps;\n    cin >> N >> M >> eps;\n\n    const int V = N * N;\n    const int W = (V + 63) / 64;\n\n    vector<vector<pair<int,int>>> shape(M);\n    vector<int> h(M, 0), w(M, 0);\n\n    for (int k = 0; k < M; k++) {\n        int d;\n        cin >> d;\n        shape[k].resize(d);\n        for (int t = 0; t < d; t++) {\n            int i, j;\n            cin >> i >> j;\n            shape[k][t] = {i, j};\n            h[k] = max(h[k], i + 1);\n            w[k] = max(w[k], j + 1);\n        }\n    }\n\n    vector<vector<Placement>> cand(M);\n\n    for (int k = 0; k < M; k++) {\n        for (int si = 0; si + h[k] <= N; si++) {\n            for (int sj = 0; sj + w[k] <= N; sj++) {\n                Placement p;\n                p.bits.assign(W, 0);\n\n                for (auto [di, dj] : shape[k]) {\n                    int ni = si + di;\n                    int nj = sj + dj;\n                    int id = ni * N + nj;\n                    p.cells.push_back(id);\n                    p.bits[id >> 6] |= 1ULL << (id & 63);\n                }\n\n                cand[k].push_back(std::move(p));\n            }\n        }\n    }\n\n    vector<int> known(V, -1);\n    vector<int> positives;\n    vector<Constraint> constraints;\n\n    vector<int> feasibleFreq(V, 0);\n    int feasibleSampleCount = 0;\n    double feasibleBestUncertainty = 0.0;\n\n    auto contains_cell = [&](const Placement& p, int id) -> bool {\n        return (p.bits[id >> 6] >> (id & 63)) & 1ULL;\n    };\n\n    auto clear_feasible_cache = [&]() {\n        fill(feasibleFreq.begin(), feasibleFreq.end(), 0);\n        feasibleSampleCount = 0;\n        feasibleBestUncertainty = 0.0;\n    };\n\n    auto total_candidates = [&]() -> long long {\n        long long s = 0;\n        for (int k = 0; k < M; k++) s += cand[k].size();\n        return s;\n    };\n\n    auto propagate = [&]() {\n        for (int round = 0; round < 3; round++) {\n            bool changed = false;\n\n            for (auto &con : constraints) {\n                int id = con.id;\n                int target = con.val;\n\n                vector<char> someCover(M, 0), someAvoid(M, 0);\n\n                for (int k = 0; k < M; k++) {\n                    for (auto &p : cand[k]) {\n                        if (contains_cell(p, id)) someCover[k] = 1;\n                        else someAvoid[k] = 1;\n                        if (someCover[k] && someAvoid[k]) break;\n                    }\n                }\n\n                int globalMin = 0;\n                int globalMax = 0;\n\n                for (int k = 0; k < M; k++) {\n                    if (!someAvoid[k]) globalMin++;\n                    if (someCover[k]) globalMax++;\n                }\n\n                if (target < globalMin || target > globalMax) {\n                    continue;\n                }\n\n                for (int k = 0; k < M; k++) {\n                    vector<Placement> nxt;\n                    nxt.reserve(cand[k].size());\n\n                    int otherMin = globalMin - (!someAvoid[k] ? 1 : 0);\n                    int otherMax = globalMax - (someCover[k] ? 1 : 0);\n\n                    for (auto &p : cand[k]) {\n                        bool has = contains_cell(p, id);\n                        int lo = otherMin + (has ? 1 : 0);\n                        int hi = otherMax + (has ? 1 : 0);\n\n                        if (target < lo || target > hi) {\n                            changed = true;\n                        } else {\n                            nxt.push_back(std::move(p));\n                        }\n                    }\n\n                    cand[k].swap(nxt);\n                }\n            }\n\n            if (!changed) break;\n        }\n    };\n\n    auto output_answer = [&](const vector<int>& ans) -> bool {\n        cout << \"a \" << ans.size();\n        for (int id : ans) {\n            cout << ' ' << id / N << ' ' << id % N;\n        }\n        cout << endl;\n        cout.flush();\n\n        int res;\n        cin >> res;\n        return res == 1;\n    };\n\n    auto drill = [&](int id) -> int {\n        cout << \"q 1 \" << id / N << ' ' << id % N << endl;\n        cout.flush();\n\n        int val;\n        cin >> val;\n\n        known[id] = val;\n        constraints.push_back({id, val});\n        if (val > 0) positives.push_back(id);\n\n        propagate();\n        clear_feasible_cache();\n\n        return val;\n    };\n\n    auto all_singleton = [&]() -> bool {\n        for (int k = 0; k < M; k++) {\n            if ((int)cand[k].size() != 1) return false;\n        }\n        return true;\n    };\n\n    auto build_union_from_choice = [&](const vector<int>& choice) -> vector<int> {\n        vector<int> mark(V, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (choice[k] < 0 || choice[k] >= (int)cand[k].size()) continue;\n            for (int id : cand[k][choice[k]].cells) mark[id] = 1;\n        }\n\n        for (int id : positives) mark[id] = 1;\n\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            if (mark[id]) ans.push_back(id);\n        }\n\n        return ans;\n    };\n\n    auto build_union_greedy = [&]() -> vector<int> {\n        vector<int> choice(M, 0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) {\n                choice[k] = -1;\n                continue;\n            }\n\n            int best = 0;\n            int bestScore = INT_MIN;\n\n            for (int idx = 0; idx < (int)cand[k].size(); idx++) {\n                int score = 0;\n\n                for (int id : cand[k][idx].cells) {\n                    if (known[id] > 0) score += 50;\n                    else if (known[id] == 0) score -= 100000;\n                }\n\n                for (int pid : positives) {\n                    int pi = pid / N;\n                    int pj = pid % N;\n                    for (int cid : cand[k][idx].cells) {\n                        int ci = cid / N;\n                        int cj = cid % N;\n                        int dist = abs(pi - ci) + abs(pj - cj);\n                        if (dist <= 2) score += 3 - dist;\n                    }\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = idx;\n                }\n            }\n\n            choice[k] = best;\n        }\n\n        return build_union_from_choice(choice);\n    };\n\n    auto eval_choice_error = [&](const vector<int>& ch) -> int {\n        int err = 0;\n\n        for (int ci = 0; ci < (int)constraints.size(); ci++) {\n            int sum = 0;\n            int id = constraints[ci].id;\n\n            for (int k = 0; k < M; k++) {\n                if (ch[k] >= 0 && contains_cell(cand[k][ch[k]], id)) sum++;\n            }\n\n            err += abs(sum - constraints[ci].val);\n        }\n\n        return err;\n    };\n\n    auto sample_feasible_consensus_answer = [&]() -> vector<int> {\n        clear_feasible_cache();\n\n        long long totalCand = total_candidates();\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) return {};\n        }\n\n        int trials;\n        if (totalCand <= 100) trials = 900;\n        else if (totalCand <= 220) trials = 700;\n        else if (totalCand <= 400) trials = 450;\n        else if (totalCand <= 650) trials = 260;\n        else trials = 0;\n\n        if (trials == 0) return {};\n\n        for (int t = 0; t < trials; t++) {\n            vector<int> ch(M);\n\n            for (int k = 0; k < M; k++) {\n                int sz = cand[k].size();\n\n                int best = randint(sz);\n                int bestScore = INT_MIN;\n\n                int samples = min(sz, 7);\n                for (int s = 0; s < samples; s++) {\n                    int idx = randint(sz);\n                    int sc = 0;\n\n                    for (int id : cand[k][idx].cells) {\n                        if (known[id] > 0) sc += 5;\n                        else if (known[id] == 0) sc -= 50;\n                    }\n\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = idx;\n                    }\n                }\n\n                ch[k] = best;\n            }\n\n            if (eval_choice_error(ch) != 0) continue;\n\n            vector<int> mark(V, 0);\n\n            for (int k = 0; k < M; k++) {\n                for (int id : cand[k][ch[k]].cells) {\n                    mark[id] = 1;\n                }\n            }\n            for (int id : positives) mark[id] = 1;\n\n            for (int id = 0; id < V; id++) {\n                if (mark[id]) feasibleFreq[id]++;\n            }\n            feasibleSampleCount++;\n\n            if (feasibleSampleCount >= 48) break;\n        }\n\n        if (feasibleSampleCount == 0) return {};\n\n        int uncertainCells = 0;\n        feasibleBestUncertainty = 0.0;\n\n        for (int id = 0; id < V; id++) {\n            if (known[id] != -1) continue;\n            if (feasibleFreq[id] > 0 && feasibleFreq[id] < feasibleSampleCount) {\n                uncertainCells++;\n            }\n            double p = (double)feasibleFreq[id] / feasibleSampleCount;\n            feasibleBestUncertainty = max(feasibleBestUncertainty, p * (1.0 - p));\n        }\n\n        int allowedUncertain;\n        if (feasibleSampleCount >= 24) allowedUncertain = max(9, V / 20);\n        else allowedUncertain = max(6, V / 32);\n\n        if (uncertainCells > allowedUncertain && feasibleSampleCount >= 6) {\n            return {};\n        }\n\n        vector<int> ans;\n        for (int id = 0; id < V; id++) {\n            bool include = false;\n            if (known[id] > 0) include = true;\n            else if (feasibleFreq[id] * 2 >= feasibleSampleCount) include = true;\n            if (include) ans.push_back(id);\n        }\n\n        return ans;\n    };\n\n    auto choose_next_cell = [&]() -> int {\n        long long totalCand = total_candidates();\n\n        if (feasibleSampleCount >= 8 && feasibleBestUncertainty >= 0.08) {\n            int best = -1;\n            double bestScore = -1.0;\n\n            for (int id = 0; id < V; id++) {\n                if (known[id] != -1) continue;\n\n                double p = (double)feasibleFreq[id] / feasibleSampleCount;\n                double score = p * (1.0 - p);\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = id;\n                }\n            }\n\n            if (best != -1 && bestScore >= 0.08) {\n                return best;\n            }\n        }\n\n        vector<double> cover(V, 0.0);\n        vector<double> split(V, 0.0);\n\n        for (int k = 0; k < M; k++) {\n            if (cand[k].empty()) continue;\n\n            vector<int> cnt(V, 0);\n\n            for (auto &p : cand[k]) {\n                for (int id : p.cells) {\n                    cnt[id]++;\n                }\n            }\n\n            double inv = 1.0 / cand[k].size();\n\n            for (int id = 0; id < V; id++) {\n                if (cnt[id] == 0) continue;\n                double pk = cnt[id] * inv;\n                cover[id] += pk;\n                split[id] += pk * (1.0 - pk);\n            }\n        }\n\n        double splitWeight;\n        if (totalCand > 600) splitWeight = 2.6;\n        else if (totalCand > 300) splitWeight = 2.0;\n        else if (totalCand > 120) splitWeight = 1.4;\n        else splitWeight = 0.8;\n\n        int best = -1;\n        double bestScore = -1e100;\n\n        for (int id = 0; id < V; id++) {\n            if (known[id] != -1) continue;\n\n            double lambda = cover[id];\n            double pOil = 1.0 - exp(-lambda);\n            double uncertain = pOil * (1.0 - pOil);\n\n            double score = 10.0 * uncertain + 0.65 * pOil + splitWeight * split[id];\n\n            int i = id / N;\n            int j = id % N;\n\n            for (int pid : positives) {\n                int pi = pid / N;\n                int pj = pid % N;\n                int dist = abs(i - pi) + abs(j - pj);\n                if (dist <= 3) score += 0.25 * (4 - dist);\n            }\n\n            int zeroNear = 0;\n            for (int di = -1; di <= 1; di++) {\n                for (int dj = -1; dj <= 1; dj++) {\n                    int ni = i + di;\n                    int nj = j + dj;\n                    if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n                    if (known[ni * N + nj] == 0) zeroNear++;\n                }\n            }\n\n            score -= 0.03 * zeroNear;\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = id;\n            }\n        }\n\n        if (best == -1) {\n            for (int id = 0; id < V; id++) {\n                if (known[id] == -1) return id;\n            }\n        }\n\n        return best;\n    };\n\n    int op_count = 0;\n    const int op_limit = 2 * N * N;\n    int last_answer_op = -100000;\n\n    /*\n       Pure prior-informed initial probing.\n    */\n    vector<double> priorCover(V, 0.0);\n\n    for (int k = 0; k < M; k++) {\n        if (cand[k].empty()) continue;\n        double inv = 1.0 / cand[k].size();\n\n        for (auto &p : cand[k]) {\n            for (int id : p.cells) {\n                priorCover[id] += inv;\n            }\n        }\n    }\n\n    int initialTarget = min(V, max(16, (N * N) / 14));\n    vector<int> initial;\n    vector<int> selected(V, 0);\n\n    for (int t = 0; t < initialTarget; t++) {\n        int best = -1;\n        double bestScore = -1e100;\n\n        for (int id = 0; id < V; id++) {\n            if (selected[id]) continue;\n\n            double lambda = priorCover[id];\n            double pOil = 1.0 - exp(-lambda);\n            double score = pOil * (1.0 - pOil) * 10.0 + 0.3 * pOil;\n\n            int i = id / N;\n            int j = id % N;\n\n            for (int sid : initial) {\n                int si = sid / N;\n                int sj = sid % N;\n                int dist = abs(i - si) + abs(j - sj);\n                if (dist <= 2) score -= 5.0;\n                else score += min(0.15, 0.02 * dist);\n            }\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = id;\n            }\n        }\n\n        if (best == -1) break;\n        selected[best] = 1;\n        initial.push_back(best);\n    }\n\n    for (int id : initial) {\n        if (op_count + 1 >= op_limit) break;\n        if (known[id] == -1) {\n            drill(id);\n            op_count++;\n        }\n    }\n\n    while (op_count + 1 < op_limit) {\n        if (all_singleton()) {\n            vector<int> choice(M, 0);\n            vector<int> ans = build_union_from_choice(choice);\n            op_count++;\n            if (output_answer(ans)) return 0;\n            last_answer_op = op_count;\n        }\n\n        long long totalCand = total_candidates();\n\n        bool enoughNewDrills = (op_count - last_answer_op >= 4);\n\n        if (enoughNewDrills &&\n            ((op_count >= 12 && totalCand <= 100) ||\n             (op_count >= 25 && totalCand <= 220) ||\n             (op_count >= 40 && totalCand <= 650))) {\n            vector<int> ans = sample_feasible_consensus_answer();\n            if (!ans.empty()) {\n                op_count++;\n                if (output_answer(ans)) return 0;\n                last_answer_op = op_count;\n            }\n        }\n\n        if (enoughNewDrills &&\n            ((op_count >= 22 && totalCand <= 60) ||\n             (op_count >= 42 && totalCand <= 120))) {\n            vector<int> ans = build_union_greedy();\n            op_count++;\n            if (output_answer(ans)) return 0;\n            last_answer_op = op_count;\n        }\n\n        int id = choose_next_cell();\n        if (id < 0) break;\n\n        drill(id);\n        op_count++;\n    }\n\n    for (int id = 0; id < V && op_count + 1 < op_limit; id++) {\n        if (known[id] == -1) {\n            drill(id);\n            op_count++;\n        }\n    }\n\n    vector<int> final_ans;\n    for (int id = 0; id < V; id++) {\n        if (known[id] > 0) final_ans.push_back(id);\n    }\n\n    op_count++;\n    output_answer(final_ans);\n\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n};\n\nint W, D, N;\nvector<vector<int>> A;\nvector<vector<int>> wid;\n\ninline long long shortage_cost(int d, int k, int w) {\n    long long area = 1LL * W * w;\n    return (A[d][k] > area) ? 100LL * (A[d][k] - area) : 0LL;\n}\n\nlong long shortage_cost_day(int d) {\n    long long c = 0;\n    for (int k = 0; k < N; k++) c += shortage_cost(d, k, wid[d][k]);\n    return c;\n}\n\nlong long transition_cost_widths(const vector<int>& a, const vector<int>& b) {\n    if (N <= 1) return 0;\n\n    int ia = 0, ib = 0;\n    int sa = a[0], sb = b[0];\n    int common = 0;\n\n    while (ia < N - 1 && ib < N - 1) {\n        if (sa == sb) {\n            common++;\n            ia++;\n            ib++;\n            if (ia < N - 1) sa += a[ia];\n            if (ib < N - 1) sb += b[ib];\n        } else if (sa < sb) {\n            ia++;\n            if (ia < N - 1) sa += a[ia];\n        } else {\n            ib++;\n            if (ib < N - 1) sb += b[ib];\n        }\n    }\n\n    int diff = 2 * (N - 1) - 2 * common;\n    return 1LL * W * diff;\n}\n\ninline long long transition_cost_pair(int d) {\n    if (d <= 0) return 0;\n    return transition_cost_widths(wid[d - 1], wid[d]);\n}\n\nlong long total_cost() {\n    long long c = 0;\n    for (int d = 0; d < D; d++) c += shortage_cost_day(d);\n    for (int d = 1; d < D; d++) c += transition_cost_pair(d);\n    return c;\n}\n\ninline long long local_part_cost(int d) {\n    long long c = shortage_cost_day(d);\n    if (d >= 1) c += transition_cost_pair(d);\n    if (d + 1 < D) c += transition_cost_pair(d + 1);\n    return c;\n}\n\nvoid normalize_day_initial(int d) {\n    wid[d].assign(N, 1);\n\n    long long sum = 0;\n    for (int k = 0; k < N; k++) {\n        wid[d][k] = max(1, (A[d][k] + W - 1) / W);\n        sum += wid[d][k];\n    }\n\n    if (sum < W) {\n        int rem = W - (int)sum;\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int x, int y) {\n            return A[d][x] > A[d][y];\n        });\n        int p = 0;\n        while (rem--) {\n            wid[d][ord[p]]++;\n            p++;\n            if (p == N) p = 0;\n        }\n    } else if (sum > W) {\n        int over = (int)(sum - W);\n        while (over > 0) {\n            int bestK = -1;\n            long long bestDamage = LLONG_MAX;\n\n            for (int k = 0; k < N; k++) {\n                if (wid[d][k] <= 1) continue;\n\n                long long before = shortage_cost(d, k, wid[d][k]);\n                long long after = shortage_cost(d, k, wid[d][k] - 1);\n                long long dmg = after - before;\n                long long key = dmg * 10000 - wid[d][k];\n\n                if (key < bestDamage) {\n                    bestDamage = key;\n                    bestK = k;\n                }\n            }\n\n            if (bestK < 0) break;\n            wid[d][bestK]--;\n            over--;\n        }\n    }\n}\n\nvoid initialize_solution() {\n    wid.assign(D, vector<int>(N, 1));\n\n    // Candidate 1: independent per-day layout.\n    vector<vector<int>> bestWid(D, vector<int>(N));\n    for (int d = 0; d < D; d++) normalize_day_initial(d);\n    bestWid = wid;\n    long long bestScore = total_cost();\n\n    // Candidate 2: fixed global DP layout.\n    vector<vector<long long>> cost(N, vector<long long>(W + 1, 0));\n    for (int k = 0; k < N; k++) {\n        for (int w = 1; w <= W; w++) {\n            long long c = 0;\n            for (int d = 0; d < D; d++) c += shortage_cost(d, k, w);\n            cost[k][w] = c;\n        }\n    }\n\n    const long long INF = (1LL << 60);\n    vector<vector<long long>> dp(N + 1, vector<long long>(W + 1, INF));\n    vector<vector<int>> pre(N + 1, vector<int>(W + 1, -1));\n    dp[0][0] = 0;\n\n    for (int k = 0; k < N; k++) {\n        for (int used = 0; used <= W; used++) {\n            if (dp[k][used] >= INF) continue;\n            int remain = N - k - 1;\n            for (int ww = 1; used + ww + remain <= W; ww++) {\n                long long nv = dp[k][used] + cost[k][ww];\n                if (nv < dp[k + 1][used + ww]) {\n                    dp[k + 1][used + ww] = nv;\n                    pre[k + 1][used + ww] = ww;\n                }\n            }\n        }\n    }\n\n    int bu = N;\n    for (int u = N; u <= W; u++) {\n        if (dp[N][u] < dp[N][bu]) bu = u;\n    }\n\n    vector<int> fixed(N);\n    int cur = bu;\n    for (int k = N; k >= 1; k--) {\n        fixed[k - 1] = pre[k][cur];\n        cur -= fixed[k - 1];\n    }\n\n    int used = accumulate(fixed.begin(), fixed.end(), 0);\n    while (used < W) {\n        int bestK = 0;\n        long long bestGain = LLONG_MIN;\n        for (int k = 0; k < N; k++) {\n            long long gain = cost[k][fixed[k]] - cost[k][fixed[k] + 1];\n            if (gain > bestGain) {\n                bestGain = gain;\n                bestK = k;\n            }\n        }\n        fixed[bestK]++;\n        used++;\n    }\n\n    wid.assign(D, fixed);\n    long long sc2 = total_cost();\n\n    if (sc2 < bestScore) {\n        bestWid = wid;\n    }\n\n    wid = bestWid;\n}\n\nvoid copy_day_refinement(const Timer& timer) {\n    bool improved = true;\n    int pass = 0;\n\n    while (improved && pass < 10 && timer.elapsed() < 2.10) {\n        improved = false;\n        pass++;\n\n        for (int d = 0; d < D && timer.elapsed() < 2.10; d++) {\n            long long base = local_part_cost(d);\n\n            vector<int> best = wid[d];\n            long long bestCost = base;\n\n            for (int off : {-2, -1, 1, 2}) {\n                int src = d + off;\n                if (src < 0 || src >= D) continue;\n\n                vector<int> old = wid[d];\n                wid[d] = wid[src];\n                long long c = local_part_cost(d);\n                if (c < bestCost) {\n                    bestCost = c;\n                    best = wid[d];\n                }\n                wid[d] = old;\n            }\n\n            if (bestCost < base) {\n                wid[d] = best;\n                improved = true;\n            }\n        }\n    }\n}\n\nvoid deterministic_transfer_search(const Timer& timer) {\n    bool improved = true;\n    int pass = 0;\n\n    while (improved && pass < 30 && timer.elapsed() < 2.50) {\n        improved = false;\n        pass++;\n\n        for (int d = 0; d < D && timer.elapsed() < 2.50; d++) {\n            bool dayImp = true;\n            int inner = 0;\n\n            while (dayImp && inner < 200 && timer.elapsed() < 2.50) {\n                dayImp = false;\n                inner++;\n\n                long long base = local_part_cost(d);\n                int bestFrom = -1, bestTo = -1;\n                long long bestDelta = 0;\n\n                for (int from = 0; from < N; from++) {\n                    if (wid[d][from] <= 1) continue;\n\n                    for (int to = 0; to < N; to++) {\n                        if (from == to) continue;\n\n                        wid[d][from]--;\n                        wid[d][to]++;\n                        long long nc = local_part_cost(d);\n                        wid[d][from]++;\n                        wid[d][to]--;\n\n                        long long delta = nc - base;\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestFrom = from;\n                            bestTo = to;\n                        }\n                    }\n                }\n\n                if (bestDelta < 0) {\n                    wid[d][bestFrom]--;\n                    wid[d][bestTo]++;\n                    improved = true;\n                    dayImp = true;\n                }\n            }\n        }\n    }\n}\n\nvoid random_local_search(const Timer& timer) {\n    XorShift rng;\n    const double TL = 2.84;\n\n    long long curScore = total_cost();\n    long long bestScore = curScore;\n    vector<vector<int>> bestWid = wid;\n\n    while (timer.elapsed() < TL) {\n        int d = rng.randint(0, D - 1);\n\n        int moveType = rng.randint(0, 99);\n        long long base = local_part_cost(d);\n\n        if (moveType < 8 && N >= 2) {\n            // Adjacent boundary shift.\n            int k = rng.randint(1, N - 1);\n            int dir = (rng.next() & 1) ? 1 : -1;\n\n            if (dir == -1) {\n                if (wid[d][k - 1] <= 1) continue;\n                wid[d][k - 1]--;\n                wid[d][k]++;\n            } else {\n                if (wid[d][k] <= 1) continue;\n                wid[d][k - 1]++;\n                wid[d][k]--;\n            }\n\n            long long nc = local_part_cost(d);\n            if (nc <= base) {\n                curScore += nc - base;\n                if (curScore < bestScore) {\n                    bestScore = curScore;\n                    bestWid = wid;\n                }\n            } else {\n                if (dir == -1) {\n                    wid[d][k - 1]++;\n                    wid[d][k]--;\n                } else {\n                    wid[d][k - 1]--;\n                    wid[d][k]++;\n                }\n            }\n        } else if (moveType < 10) {\n            // Whole-day copy from nearby day.\n            vector<int> sources;\n            for (int off : {-3, -2, -1, 1, 2, 3}) {\n                int s = d + off;\n                if (0 <= s && s < D) sources.push_back(s);\n            }\n            if (sources.empty()) continue;\n            int src = sources[rng.randint(0, (int)sources.size() - 1)];\n\n            vector<int> old = wid[d];\n            wid[d] = wid[src];\n\n            long long nc = local_part_cost(d);\n            if (nc <= base) {\n                curScore += nc - base;\n                if (curScore < bestScore) {\n                    bestScore = curScore;\n                    bestWid = wid;\n                }\n            } else {\n                wid[d] = old;\n            }\n        } else {\n            // Arbitrary width transfer.\n            int from = rng.randint(0, N - 1);\n            int to = rng.randint(0, N - 1);\n            if (from == to || wid[d][from] <= 1) continue;\n\n            int maxMove = min(wid[d][from] - 1, 10);\n            if (maxMove <= 0) continue;\n\n            int mv = 1;\n            if ((rng.next() & 7) == 0) mv = rng.randint(1, maxMove);\n\n            wid[d][from] -= mv;\n            wid[d][to] += mv;\n\n            long long nc = local_part_cost(d);\n\n            if (nc <= base) {\n                curScore += nc - base;\n                if (curScore < bestScore) {\n                    bestScore = curScore;\n                    bestWid = wid;\n                }\n            } else {\n                wid[d][from] += mv;\n                wid[d][to] -= mv;\n            }\n        }\n    }\n\n    wid = bestWid;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    cin >> W >> D >> N;\n    A.assign(D, vector<int>(N));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) cin >> A[d][k];\n    }\n\n    initialize_solution();\n\n    copy_day_refinement(timer);\n    deterministic_transfer_search(timer);\n    random_local_search(timer);\n\n    for (int d = 0; d < D; d++) {\n        int sum = accumulate(wid[d].begin(), wid[d].end(), 0);\n\n        while (sum < W) {\n            wid[d][N - 1]++;\n            sum++;\n        }\n        while (sum > W) {\n            for (int k = N - 1; k >= 0 && sum > W; k--) {\n                if (wid[d][k] > 1) {\n                    wid[d][k]--;\n                    sum--;\n                }\n            }\n        }\n\n        int x = 0;\n        for (int k = 0; k < N; k++) {\n            int x2 = x + wid[d][k];\n            if (k == N - 1) x2 = W;\n            cout << 0 << ' ' << x << ' ' << W << ' ' << x2 << '\\n';\n            x = x2;\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr long long MOD = 998244353LL;\nstatic constexpr int N = 9;\nstatic constexpr int M = 20;\nstatic constexpr int K = 81;\nstatic constexpr int POS = 7;\nstatic constexpr int ALL = M * POS * POS;\n\nstruct Op {\n    int m, p, q;\n};\n\nstruct Move {\n    long long gain;\n    Op op;\n};\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ULL) : x(seed) {}\n    inline uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    inline int randint(int l, int r) {\n        return l + int(next() % uint64_t(r - l + 1));\n    }\n    inline double uniform() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nlong long stamp[M][3][3];\nOp all_ops[ALL];\nint all_cnt = 0;\n\narray<array<long long, N>, N> initial_board;\nlong long initial_score = 0;\n\nstruct Result {\n    long long score;\n    vector<Op> ops;\n};\n\ninline bool same_op(const Op& a, const Op& b) {\n    return a.m == b.m && a.p == b.p && a.q == b.q;\n}\n\ninline long long gain_of(const array<array<long long, N>, N>& b, const Op& op) {\n    const int m = op.m;\n    const int p = op.p;\n    const int q = op.q;\n\n    long long gain = 0;\n    long long oldv, nv;\n\n    oldv = b[p][q];\n    nv = oldv + stamp[m][0][0];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p][q + 1];\n    nv = oldv + stamp[m][0][1];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p][q + 2];\n    nv = oldv + stamp[m][0][2];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 1][q];\n    nv = oldv + stamp[m][1][0];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 1][q + 1];\n    nv = oldv + stamp[m][1][1];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 1][q + 2];\n    nv = oldv + stamp[m][1][2];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 2][q];\n    nv = oldv + stamp[m][2][0];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 2][q + 1];\n    nv = oldv + stamp[m][2][1];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    oldv = b[p + 2][q + 2];\n    nv = oldv + stamp[m][2][2];\n    if (nv >= MOD) nv -= MOD;\n    gain += nv - oldv;\n\n    return gain;\n}\n\ninline void apply_op(array<array<long long, N>, N>& b, const Op& op) {\n    const int m = op.m;\n    const int p = op.p;\n    const int q = op.q;\n\n    long long &v00 = b[p][q];\n    v00 += stamp[m][0][0];\n    if (v00 >= MOD) v00 -= MOD;\n\n    long long &v01 = b[p][q + 1];\n    v01 += stamp[m][0][1];\n    if (v01 >= MOD) v01 -= MOD;\n\n    long long &v02 = b[p][q + 2];\n    v02 += stamp[m][0][2];\n    if (v02 >= MOD) v02 -= MOD;\n\n    long long &v10 = b[p + 1][q];\n    v10 += stamp[m][1][0];\n    if (v10 >= MOD) v10 -= MOD;\n\n    long long &v11 = b[p + 1][q + 1];\n    v11 += stamp[m][1][1];\n    if (v11 >= MOD) v11 -= MOD;\n\n    long long &v12 = b[p + 1][q + 2];\n    v12 += stamp[m][1][2];\n    if (v12 >= MOD) v12 -= MOD;\n\n    long long &v20 = b[p + 2][q];\n    v20 += stamp[m][2][0];\n    if (v20 >= MOD) v20 -= MOD;\n\n    long long &v21 = b[p + 2][q + 1];\n    v21 += stamp[m][2][1];\n    if (v21 >= MOD) v21 -= MOD;\n\n    long long &v22 = b[p + 2][q + 2];\n    v22 += stamp[m][2][2];\n    if (v22 >= MOD) v22 -= MOD;\n}\n\ninline void insert_top(vector<Move>& top, const Move& mv, int TOP) {\n    if (mv.gain <= 0) return;\n\n    if ((int)top.size() < TOP) {\n        top.push_back(mv);\n        int i = (int)top.size() - 1;\n        while (i > 0 && top[i].gain > top[i - 1].gain) {\n            swap(top[i], top[i - 1]);\n            i--;\n        }\n    } else if (mv.gain > top.back().gain) {\n        top.back() = mv;\n        int i = TOP - 1;\n        while (i > 0 && top[i].gain > top[i - 1].gain) {\n            swap(top[i], top[i - 1]);\n            i--;\n        }\n    }\n}\n\nlong long eval_ops(const vector<Op>& ops) {\n    auto b = initial_board;\n    long long score = initial_score;\n\n    for (const Op& op : ops) {\n        long long g = gain_of(b, op);\n        apply_op(b, op);\n        score += g;\n    }\n    return score;\n}\n\nResult construct_original_like(XorShift& rng, bool deterministic) {\n    auto b = initial_board;\n\n    Result res;\n    res.score = initial_score;\n    res.ops.reserve(K);\n\n    constexpr int TOP = 12;\n\n    for (int step = 0; step < K; step++) {\n        vector<Move> top;\n        top.reserve(TOP);\n\n        for (int i = 0; i < all_cnt; i++) {\n            long long g = gain_of(b, all_ops[i]);\n            insert_top(top, {g, all_ops[i]}, TOP);\n        }\n\n        if (top.empty()) break;\n\n        int idx = 0;\n\n        if (!deterministic) {\n            double greedy_prob = 0.70 + 0.25 * (double(step) / K);\n            if (rng.uniform() >= greedy_prob) {\n                idx = rng.randint(0, (int)top.size() - 1);\n            }\n        }\n\n        Move chosen = top[idx];\n        apply_op(b, chosen.op);\n        res.score += chosen.gain;\n        res.ops.push_back(chosen.op);\n    }\n\n    return res;\n}\n\nResult construct_variant(XorShift& rng, int mode) {\n    auto b = initial_board;\n\n    Result res;\n    res.score = initial_score;\n    res.ops.reserve(K);\n\n    int TOP = (mode == 0 ? 8 : mode == 1 ? 16 : 20);\n\n    for (int step = 0; step < K; step++) {\n        vector<Move> top;\n        top.reserve(TOP);\n\n        for (int i = 0; i < all_cnt; i++) {\n            long long g = gain_of(b, all_ops[i]);\n            insert_top(top, {g, all_ops[i]}, TOP);\n        }\n\n        if (top.empty()) break;\n\n        int idx = 0;\n\n        double t = double(step) / K;\n        double greedy_prob;\n\n        if (mode == 0) greedy_prob = 0.80 + 0.16 * t;\n        else if (mode == 1) greedy_prob = 0.62 + 0.30 * t;\n        else greedy_prob = 0.55 + 0.35 * t;\n\n        if (rng.uniform() >= greedy_prob) {\n            double r = rng.uniform();\n            if (mode != 2) r *= r;\n            int lim = (int)top.size();\n            idx = int(r * lim);\n            if (idx >= lim) idx = lim - 1;\n        }\n\n        Move chosen = top[idx];\n        apply_op(b, chosen.op);\n        res.score += chosen.gain;\n        res.ops.push_back(chosen.op);\n    }\n\n    return res;\n}\n\nint biased_index(int L, XorShift& rng) {\n    if (L <= 1) return 0;\n\n    if (rng.randint(0, 99) < 60) {\n        return rng.randint(0, L - 1);\n    } else {\n        double r = rng.uniform();\n        int idx = int(r * r * L);\n        if (idx >= L) idx = L - 1;\n        return idx;\n    }\n}\n\nbool improve_replacement(Result& best, XorShift& rng) {\n    int L = (int)best.ops.size();\n    if (L == 0) return false;\n\n    int idx = biased_index(L, rng);\n\n    auto b = initial_board;\n    for (int i = 0; i < idx; i++) {\n        apply_op(b, best.ops[i]);\n    }\n\n    constexpr int TOP = 10;\n    vector<Move> top;\n    top.reserve(TOP);\n\n    for (int i = 0; i < all_cnt; i++) {\n        long long g = gain_of(b, all_ops[i]);\n        insert_top(top, {g, all_ops[i]}, TOP);\n    }\n\n    vector<Op> candidates;\n    candidates.reserve(TOP + 5);\n\n    for (auto &mv : top) candidates.push_back(mv.op);\n\n    for (int t = 0; t < 5; t++) {\n        candidates.push_back(all_ops[rng.randint(0, all_cnt - 1)]);\n    }\n\n    for (const Op& op : candidates) {\n        if (same_op(op, best.ops[idx])) continue;\n\n        vector<Op> cand = best.ops;\n        cand[idx] = op;\n\n        long long sc = eval_ops(cand);\n        if (sc > best.score) {\n            best.score = sc;\n            best.ops.swap(cand);\n            return true;\n        }\n    }\n\n    return false;\n}\n\nbool improve_swap(Result& best, XorShift& rng) {\n    int L = (int)best.ops.size();\n    if (L < 2) return false;\n\n    int i = rng.randint(0, L - 2);\n    int j;\n\n    if (rng.randint(0, 99) < 75) {\n        j = i + 1;\n    } else {\n        j = rng.randint(0, L - 1);\n        if (i == j) return false;\n    }\n\n    vector<Op> cand = best.ops;\n    swap(cand[i], cand[j]);\n\n    long long sc = eval_ops(cand);\n    if (sc > best.score) {\n        best.score = sc;\n        best.ops.swap(cand);\n        return true;\n    }\n\n    return false;\n}\n\nbool improve_truncate(Result& best) {\n    int L = (int)best.ops.size();\n    if (L <= 1) return false;\n\n    auto b = initial_board;\n    long long score = initial_score;\n\n    long long best_pref_score = initial_score;\n    int best_len = 0;\n\n    for (int i = 0; i < L; i++) {\n        long long g = gain_of(b, best.ops[i]);\n        apply_op(b, best.ops[i]);\n        score += g;\n\n        if (score > best_pref_score) {\n            best_pref_score = score;\n            best_len = i + 1;\n        }\n    }\n\n    if (best_pref_score > best.score) {\n        best.score = best_pref_score;\n        best.ops.resize(best_len);\n        return true;\n    }\n\n    return false;\n}\n\nResult build_suffix_candidate(\n    const Result& base,\n    XorShift& rng,\n    bool variant\n) {\n    int L = (int)base.ops.size();\n\n    Result res;\n    res.score = initial_score;\n    res.ops.reserve(K);\n\n    if (L <= 3) {\n        return res;\n    }\n\n    int cut;\n\n    if (!variant) {\n        if (rng.randint(0, 99) < 70) {\n            cut = rng.randint(L / 3, L - 1);\n        } else {\n            cut = rng.randint(0, L - 1);\n        }\n    } else {\n        if (rng.randint(0, 99) < 60) {\n            cut = rng.randint(L / 2, L - 1);\n        } else {\n            cut = rng.randint(L / 4, L - 1);\n        }\n    }\n\n    auto b = initial_board;\n\n    for (int i = 0; i < cut; i++) {\n        res.ops.push_back(base.ops[i]);\n        long long g = gain_of(b, base.ops[i]);\n        apply_op(b, base.ops[i]);\n        res.score += g;\n    }\n\n    constexpr int TOP = 12;\n\n    for (int step = cut; step < K; step++) {\n        vector<Move> top;\n        top.reserve(TOP);\n\n        for (int i = 0; i < all_cnt; i++) {\n            long long g = gain_of(b, all_ops[i]);\n            insert_top(top, {g, all_ops[i]}, TOP);\n        }\n\n        if (top.empty()) break;\n\n        int idx = 0;\n\n        double greedy_prob = variant\n            ? (0.72 + 0.23 * (double(step) / K))\n            : (0.68 + 0.27 * (double(step) / K));\n\n        if (rng.uniform() >= greedy_prob) {\n            idx = rng.randint(0, (int)top.size() - 1);\n        }\n\n        Move chosen = top[idx];\n        res.ops.push_back(chosen.op);\n        apply_op(b, chosen.op);\n        res.score += chosen.gain;\n    }\n\n    return res;\n}\n\nbool improve_suffix_regreedy(Result& best, XorShift& rng, bool variant) {\n    Result cand = build_suffix_candidate(best, rng, variant);\n\n    if (cand.score > best.score) {\n        best = std::move(cand);\n        return true;\n    }\n\n    return false;\n}\n\nbool improve_multi_suffix_regreedy(Result& best, XorShift& rng) {\n    Result c1 = build_suffix_candidate(best, rng, false);\n    Result c2 = build_suffix_candidate(best, rng, true);\n\n    Result* cand = &c1;\n    if (c2.score > c1.score) cand = &c2;\n\n    if (cand->score > best.score) {\n        best = std::move(*cand);\n        return true;\n    }\n\n    return false;\n}\n\nbool improve_two_replacement(Result& best, XorShift& rng) {\n    int L = (int)best.ops.size();\n    if (L < 2) return false;\n\n    vector<Op> cand = best.ops;\n\n    int i = biased_index(L, rng);\n    int j;\n\n    if (rng.randint(0, 99) < 70) {\n        int d = rng.randint(1, 4);\n        j = min(L - 1, i + d);\n        if (j == i) j = max(0, i - d);\n    } else {\n        j = rng.randint(0, L - 1);\n    }\n\n    if (i == j) return false;\n\n    cand[i] = all_ops[rng.randint(0, all_cnt - 1)];\n    cand[j] = all_ops[rng.randint(0, all_cnt - 1)];\n\n    long long sc = eval_ops(cand);\n    if (sc > best.score) {\n        best.score = sc;\n        best.ops.swap(cand);\n        return true;\n    }\n\n    return false;\n}\n\nvoid add_elite(vector<Result>& elites, const Result& r) {\n    constexpr int ELITE_SIZE = 8;\n\n    for (const auto& e : elites) {\n        if (e.ops.size() == r.ops.size()) {\n            bool same = true;\n            for (size_t i = 0; i < e.ops.size(); i++) {\n                if (!same_op(e.ops[i], r.ops[i])) {\n                    same = false;\n                    break;\n                }\n            }\n            if (same) return;\n        }\n    }\n\n    elites.push_back(r);\n    sort(elites.begin(), elites.end(), [](const Result& a, const Result& b) {\n        return a.score > b.score;\n    });\n\n    if ((int)elites.size() > ELITE_SIZE) {\n        elites.resize(ELITE_SIZE);\n    }\n}\n\nvoid improve_one(Result& target, XorShift& rng) {\n    int r = rng.randint(0, 99);\n\n    if (r < 48) {\n        improve_replacement(target, rng);\n    } else if (r < 63) {\n        improve_suffix_regreedy(target, rng, false);\n    } else if (r < 70) {\n        improve_suffix_regreedy(target, rng, true);\n    } else if (r < 78) {\n        improve_multi_suffix_regreedy(target, rng);\n    } else if (r < 89) {\n        improve_swap(target, rng);\n    } else if (r < 97) {\n        improve_two_replacement(target, rng);\n    } else {\n        improve_truncate(target);\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, minput, kinput;\n    cin >> n >> minput >> kinput;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            cin >> initial_board[i][j];\n            initial_score += initial_board[i][j];\n        }\n    }\n\n    for (int m = 0; m < M; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamp[m][i][j];\n            }\n        }\n    }\n\n    for (int m = 0; m < M; m++) {\n        for (int p = 0; p < POS; p++) {\n            for (int q = 0; q < POS; q++) {\n                all_ops[all_cnt++] = {m, p, q};\n            }\n        }\n    }\n\n    auto start = chrono::steady_clock::now();\n    const double TIME_LIMIT = 1.88;\n\n    XorShift rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    Result best;\n    best.score = initial_score;\n\n    vector<Result> elites;\n    elites.reserve(10);\n\n    {\n        Result r = construct_original_like(rng, true);\n        if (r.score > best.score) best = r;\n        add_elite(elites, r);\n    }\n\n    int trial = 0;\n\n    while (true) {\n        double elapsed = chrono::duration<double>(\n            chrono::steady_clock::now() - start\n        ).count();\n\n        if (elapsed > 1.35) break;\n\n        Result r;\n\n        int x = trial % 14;\n        if (x < 10) {\n            r = construct_original_like(rng, false);\n        } else {\n            r = construct_variant(rng, x % 3);\n        }\n\n        if (r.score > best.score) {\n            best = r;\n        }\n\n        add_elite(elites, r);\n\n        trial++;\n    }\n\n    while (true) {\n        double elapsed = chrono::duration<double>(\n            chrono::steady_clock::now() - start\n        ).count();\n\n        if (elapsed > TIME_LIMIT) break;\n\n        Result target;\n\n        if (!elites.empty() && rng.randint(0, 99) < 35) {\n            int idx = rng.randint(0, (int)elites.size() - 1);\n            target = elites[idx];\n        } else {\n            target = best;\n        }\n\n        improve_one(target, rng);\n\n        if (rng.randint(0, 99) < 18) {\n            improve_one(target, rng);\n        }\n\n        if (target.score > best.score) {\n            best = target;\n        }\n\n        add_elite(elites, target);\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (const Op& op : best.ops) {\n        cout << op.m << ' ' << op.p << ' ' << op.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Params {\n    int nowW;\n    int laterW;\n    int rowPenaltyW;\n    int colPenaltyW;\n    int recvPenalty;\n    int sameRowBonus;\n    int nextGateW;\n};\n\nstruct Solver {\n    static constexpr int N = 5;\n\n    const vector<vector<int>>& A;\n    Params param;\n    vector<int> targetSeq;\n\n    int ptr[N];\n    int grid[N][N];\n    pair<int,int> pos[N * N];\n\n    string s0;\n\n    int cr = 0, cc = 0;\n    bool holding = false;\n    int hold = -1;\n    int currentTarget = 0;\n\n    Solver(const vector<vector<int>>& A_, Params p, const vector<int>& seq)\n        : A(A_), param(p), targetSeq(seq) {\n        for (int i = 0; i < N; i++) ptr[i] = 0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) grid[i][j] = -1;\n        }\n        for (int x = 0; x < N * N; x++) pos[x] = {-1, -1};\n\n        for (int i = 0; i < N; i++) {\n            int x = A[i][0];\n            grid[i][0] = x;\n            pos[x] = {i, 0};\n            ptr[i] = 1;\n        }\n\n        s0.reserve(1000);\n    }\n\n    inline int dist(int r1, int c1, int r2, int c2) const {\n        return abs(r1 - r2) + abs(c1 - c2);\n    }\n\n    inline void do_receive() {\n        for (int i = 0; i < N; i++) {\n            if (ptr[i] < N && grid[i][0] == -1) {\n                if (holding && cr == i && cc == 0) continue;\n\n                int x = A[i][ptr[i]++];\n                grid[i][0] = x;\n                pos[x] = {i, 0};\n            }\n        }\n    }\n\n    inline void append_large(char c) {\n        s0.push_back(c);\n\n        if (c == 'U') cr--;\n        else if (c == 'D') cr++;\n        else if (c == 'L') cc--;\n        else if (c == 'R') cc++;\n    }\n\n    inline void move_one(char c) {\n        do_receive();\n        append_large(c);\n    }\n\n    void move_to(int tr, int tc) {\n        while (cr < tr) move_one('D');\n        while (cr > tr) move_one('U');\n        while (cc < tc) move_one('R');\n        while (cc > tc) move_one('L');\n    }\n\n    inline void pick() {\n        do_receive();\n\n        int x = grid[cr][cc];\n\n        if (x == -1) {\n            append_large('.');\n            return;\n        }\n\n        append_large('P');\n\n        holding = true;\n        hold = x;\n        grid[cr][cc] = -1;\n        pos[x] = {-1, -1};\n    }\n\n    inline void release() {\n        do_receive();\n\n        append_large('Q');\n\n        holding = false;\n\n        if (cc == N - 1) {\n            pos[hold] = {-2, -2};\n        } else {\n            grid[cr][cc] = hold;\n            pos[hold] = {cr, cc};\n        }\n\n        hold = -1;\n    }\n\n    inline bool target_on_grid(int target) const {\n        return pos[target].first >= 0;\n    }\n\n    inline bool usable_storage(int r, int c) const {\n        if (c == N - 1) return false;\n        if (grid[r][c] != -1) return false;\n        if (c == 0 && ptr[r] < N) return false;\n        return true;\n    }\n\n    bool row_hides_target(int r, int target) const {\n        for (int k = ptr[r]; k < N; k++) {\n            if (A[r][k] == target) return true;\n        }\n        return false;\n    }\n\n    int next_gate_row_for_target(int target) const {\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] == -1) continue;\n            if (row_hides_target(r, target)) return r;\n        }\n\n        int best = -1;\n        int bestDist = INT_MAX;\n\n        for (int r = 0; r < N; r++) {\n            if (grid[r][0] != -1) {\n                int d = dist(cr, cc, r, 0);\n                if (d < bestDist) {\n                    bestDist = d;\n                    best = r;\n                }\n            }\n        }\n\n        return best;\n    }\n\n    pair<int,int> find_storage_for(int x) const {\n        int dest = x / N;\n        int nextR = next_gate_row_for_target(currentTarget);\n\n        pair<int,int> best = {-1, -1};\n        int bestScore = INT_MAX;\n\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N - 1; c++) {\n                if (!usable_storage(r, c)) continue;\n\n                int nowCost = dist(cr, cc, r, c);\n                int laterCost = dist(r, c, dest, N - 1);\n                int rowPenalty = abs(r - dest);\n                int colPenalty = 3 - c;\n\n                int score = 0;\n                score += param.nowW * nowCost;\n                score += param.laterW * laterCost;\n                score += param.rowPenaltyW * rowPenalty;\n                score += param.colPenaltyW * colPenalty;\n\n                if (c == 0) score += param.recvPenalty;\n                if (r == dest) score -= param.sameRowBonus;\n\n                if (nextR != -1) {\n                    score += param.nextGateW * dist(r, c, nextR, 0);\n                }\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = {r, c};\n                }\n            }\n        }\n\n        return best;\n    }\n\n    void store_held() {\n        auto p = find_storage_for(hold);\n\n        if (p.first == -1) {\n            int dest = hold / N;\n            move_to(dest, N - 1);\n            release();\n            return;\n        }\n\n        move_to(p.first, p.second);\n        release();\n    }\n\n    int choose_revealing_row(int target) const {\n        return next_gate_row_for_target(target);\n    }\n\n    void deliver_held_to_correct_gate() {\n        int dest = hold / N;\n        move_to(dest, N - 1);\n        release();\n    }\n\n    void move_to_and_pick(pair<int,int> p) {\n        move_to(p.first, p.second);\n        pick();\n    }\n\n    void solve_sequence() {\n        for (int target : targetSeq) {\n            currentTarget = target;\n\n            while (true) {\n                if (target_on_grid(target)) {\n                    move_to_and_pick(pos[target]);\n                    deliver_held_to_correct_gate();\n                    break;\n                }\n\n                int row = choose_revealing_row(target);\n\n                if (row == -1) {\n                    move_one('.');\n                    continue;\n                }\n\n                move_to(row, 0);\n                pick();\n\n                if (hold == target) {\n                    deliver_held_to_correct_gate();\n                    break;\n                } else {\n                    store_held();\n                }\n            }\n        }\n    }\n\n    string run() {\n        solve_sequence();\n        return s0;\n    }\n};\n\nvector<int> make_block_sequence(const array<int,5>& rowOrder) {\n    vector<int> seq;\n    seq.reserve(25);\n\n    for (int g : rowOrder) {\n        for (int k = 0; k < 5; k++) {\n            seq.push_back(g * 5 + k);\n        }\n    }\n\n    return seq;\n}\n\nvector<int> make_interleaved_sequence(const array<int,5>& rowOrder) {\n    vector<int> seq;\n    seq.reserve(25);\n\n    for (int k = 0; k < 5; k++) {\n        for (int g : rowOrder) {\n            seq.push_back(g * 5 + k);\n        }\n    }\n\n    return seq;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n\n    vector<vector<int>> A(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> A[i][j];\n    }\n\n    vector<Params> fullParams = {\n        {3, 4, 4, 1, 8, 0, 0},\n        {2, 5, 5, 1, 10, 0, 0},\n        {5, 3, 3, 1, 8, 0, 0},\n        {3, 4, 8, 1, 10, 0, 0},\n        {3, 4, 4, 4, 10, 0, 0},\n        {4, 4, 4, 2, 8, 0, 0},\n        {2, 4, 6, 2, 12, 0, 0},\n        {4, 5, 3, 1, 8, 0, 0},\n        {3, 5, 6, 2, 12, 0, 0},\n        {5, 5, 5, 1, 10, 0, 0},\n\n        {1, 6, 8, 1, 12, 0, 0},\n        {6, 2, 2, 1, 6, 0, 0},\n        {2, 6, 3, 4, 10, 0, 0},\n        {4, 3, 7, 2, 10, 0, 0},\n        {3, 6, 10, 1, 12, 0, 0},\n        {6, 4, 4, 3, 8, 0, 0},\n        {1, 5, 10, 1, 15, 0, 0},\n        {7, 2, 1, 1, 5, 0, 0},\n        {2, 7, 8, 2, 12, 0, 0},\n        {4, 6, 4, 4, 10, 0, 0},\n        {5, 4, 8, 2, 8, 0, 0},\n        {3, 7, 12, 1, 15, 0, 0},\n\n        {3, 4, 4, 1, 8, 4, 0},\n        {2, 5, 5, 1, 10, 4, 0},\n        {5, 3, 3, 1, 8, 4, 0},\n        {3, 4, 8, 1, 10, 6, 0},\n        {3, 5, 6, 2, 12, 6, 0},\n        {1, 6, 8, 1, 12, 8, 0},\n        {4, 6, 4, 4, 10, 5, 0},\n        {2, 7, 8, 2, 12, 8, 0},\n\n        {8, 1, 1, 1, 5, 0, 0},\n        {8, 2, 2, 2, 6, 0, 0},\n        {7, 3, 2, 3, 6, 2, 0},\n        {1, 8, 10, 1, 15, 10, 0},\n        {2, 8, 12, 1, 15, 10, 0},\n        {1, 9, 14, 1, 18, 12, 0},\n\n        {3, 4, 4, 1, 8, 0, 1},\n        {3, 4, 4, 1, 8, 0, 2},\n        {2, 5, 5, 1, 10, 0, 1},\n        {2, 5, 5, 1, 10, 0, 2},\n        {5, 3, 3, 1, 8, 0, 1},\n        {5, 3, 3, 1, 8, 0, 2},\n        {3, 5, 6, 2, 12, 6, 1},\n        {3, 5, 6, 2, 12, 6, 2},\n        {1, 6, 8, 1, 12, 8, 1},\n        {1, 6, 8, 1, 12, 8, 2},\n        {4, 6, 4, 4, 10, 5, 1},\n        {4, 6, 4, 4, 10, 5, 2},\n    };\n\n    vector<Params> compactParams = {\n        {3, 4, 4, 1, 8, 0, 0},\n        {2, 5, 5, 1, 10, 0, 0},\n        {5, 3, 3, 1, 8, 0, 0},\n        {3, 4, 8, 1, 10, 0, 0},\n        {1, 6, 8, 1, 12, 0, 0},\n        {6, 2, 2, 1, 6, 0, 0},\n        {3, 4, 4, 1, 8, 4, 0},\n        {1, 8, 10, 1, 15, 10, 0},\n        {3, 4, 4, 1, 8, 0, 1},\n        {3, 4, 4, 1, 8, 0, 2},\n    };\n\n    string best;\n    int bestLen = INT_MAX;\n\n    array<int,5> ord = {0, 1, 2, 3, 4};\n\n    do {\n        vector<int> seqBlock = make_block_sequence(ord);\n        for (auto p : fullParams) {\n            Solver solver(A, p, seqBlock);\n            string s = solver.run();\n            if ((int)s.size() < bestLen) {\n                bestLen = (int)s.size();\n                best = std::move(s);\n            }\n        }\n\n        vector<int> seqInter = make_interleaved_sequence(ord);\n        for (auto p : compactParams) {\n            Solver solver(A, p, seqInter);\n            string s = solver.run();\n            if ((int)s.size() < bestLen) {\n                bestLen = (int)s.size();\n                best = std::move(s);\n            }\n        }\n\n    } while (next_permutation(ord.begin(), ord.end()));\n\n    cout << best << '\\n';\n\n    for (int i = 1; i < N; i++) {\n        cout << 'B';\n        for (int k = 1; k < bestLen; k++) cout << '.';\n        cout << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nint N;\nvector<vector<int>> H;\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nstruct Result {\n    long long cost = (1LL << 60);\n    vector<string> ops;\n};\n\nstruct Cell {\n    int r, c;\n    int v;\n};\n\nstruct Params {\n    double emptyDistW;\n    double deliverDistW;\n    double amountBonus;\n    double sourceToSinkW;\n};\n\nstruct EvalInfo {\n    long long cost;\n    int start;\n};\n\nint manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nvoid move_to(vector<string>& ops, long long& cost, long long load,\n             int& r, int& c, int nr, int nc) {\n    while (r < nr) {\n        ops.push_back(\"D\");\n        cost += 100 + load;\n        r++;\n    }\n    while (r > nr) {\n        ops.push_back(\"U\");\n        cost += 100 + load;\n        r--;\n    }\n    while (c < nc) {\n        ops.push_back(\"R\");\n        cost += 100 + load;\n        c++;\n    }\n    while (c > nc) {\n        ops.push_back(\"L\");\n        cost += 100 + load;\n        c--;\n    }\n}\n\nResult simulate_greedy(const Params& par) {\n    vector<Cell> pos, neg;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (H[i][j] > 0) pos.push_back({i, j, H[i][j]});\n            if (H[i][j] < 0) neg.push_back({i, j, -H[i][j]});\n        }\n    }\n\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n    int lastSrcR = 0, lastSrcC = 0;\n\n    int remainNeg = 0;\n    for (auto& x : neg) remainNeg += x.v;\n\n    while (remainNeg > 0) {\n        if (load == 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)pos.size(); i++) {\n                if (pos[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, pos[i].r, pos[i].c);\n                int nearestSink = 1000000;\n                for (auto& g : neg) {\n                    if (g.v <= 0) continue;\n                    nearestSink = min(nearestSink, manhattan(pos[i].r, pos[i].c, g.r, g.c));\n                }\n\n                double score =\n                    par.emptyDistW * dcur\n                    + par.sourceToSinkW * nearestSink\n                    - par.amountBonus * sqrt((double)pos[i].v);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, pos[best].r, pos[best].c);\n\n            int d = pos[best].v;\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            pos[best].v = 0;\n            lastSrcR = r;\n            lastSrcC = c;\n        }\n\n        while (load > 0) {\n            int best = -1;\n            double bestScore = 1e100;\n\n            for (int i = 0; i < (int)neg.size(); i++) {\n                if (neg[i].v <= 0) continue;\n\n                int dcur = manhattan(r, c, neg[i].r, neg[i].c);\n                int dsrc = manhattan(lastSrcR, lastSrcC, neg[i].r, neg[i].c);\n                int give = min<long long>(load, neg[i].v);\n\n                double score =\n                    par.deliverDistW * dcur\n                    + 0.25 * dsrc\n                    - par.amountBonus * sqrt((double)give);\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = i;\n                }\n            }\n\n            if (best == -1) break;\n\n            move_to(ops, cost, load, r, c, neg[best].r, neg[best].c);\n\n            int d = min<long long>(load, neg[best].v);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            neg[best].v -= d;\n            remainNeg -= d;\n        }\n    }\n\n    if ((int)ops.size() > 100000) return Result();\n    return {cost, ops};\n}\n\nResult simulate_path(const vector<pair<int,int>>& path) {\n    vector<vector<int>> h = H;\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n\n    auto process_cell = [&](int i, int j) {\n        if (h[i][j] > 0) {\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        } else if (h[i][j] < 0 && load > 0) {\n            int d = min<long long>(-h[i][j], load);\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] += d;\n        }\n    };\n\n    for (auto [i,j] : path) {\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (int idx = (int)path.size() - 1; idx >= 0; idx--) {\n        auto [i,j] = path[idx];\n        move_to(ops, cost, load, r, c, i, j);\n        process_cell(i, j);\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] > 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = h[i][j];\n            ops.push_back(\"+\" + to_string(d));\n            cost += d;\n            load += d;\n            h[i][j] = 0;\n        }\n    }\n\n    for (auto [i,j] : path) {\n        if (h[i][j] < 0) {\n            move_to(ops, cost, load, r, c, i, j);\n            int d = -h[i][j];\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n            h[i][j] = 0;\n        }\n    }\n\n    if ((int)ops.size() > 100000) return Result();\n    return {cost, ops};\n}\n\nResult simulate_cyclic_path(const vector<pair<int,int>>& base, int start) {\n    int M = base.size();\n\n    vector<string> ops;\n    long long cost = 0;\n    long long load = 0;\n    int r = 0, c = 0;\n\n    for (int k = 0; k < M; k++) {\n        auto [i,j] = base[(start + k) % M];\n\n        move_to(ops, cost, load, r, c, i, j);\n\n        int v = H[i][j];\n        if (v > 0) {\n            ops.push_back(\"+\" + to_string(v));\n            cost += v;\n            load += v;\n        } else if (v < 0) {\n            int d = -v;\n            if (load < d) return Result();\n            ops.push_back(\"-\" + to_string(d));\n            cost += d;\n            load -= d;\n        }\n    }\n\n    if (load != 0) return Result();\n    if ((int)ops.size() > 100000) return Result();\n    return {cost, ops};\n}\n\nvector<pair<int,int>> compress_nonzero(const vector<pair<int,int>>& p) {\n    vector<pair<int,int>> q;\n    q.reserve(p.size());\n    for (auto [r,c] : p) {\n        if (H[r][c] != 0) q.push_back({r,c});\n    }\n    return q;\n}\n\nEvalInfo eval_cyclic_order(const vector<pair<int,int>>& base) {\n    int M = base.size();\n    if (M == 0) return {(long long)4e18, -1};\n\n    vector<long long> pref(M + 1, 0);\n    for (int i = 0; i < M; i++) {\n        auto [r,c] = base[i];\n        pref[i + 1] = pref[i] + H[r][c];\n    }\n\n    long long mn = *min_element(pref.begin(), pref.end());\n    long long bestCost = (long long)4e18;\n    int bestStart = -1;\n\n    long long baseCost = 0;\n    for (auto [r,c] : base) baseCost += abs(H[r][c]);\n\n    for (int st = 0; st < M; st++) {\n        if (pref[st] != mn) continue;\n\n        long long cost = baseCost;\n        long long load = 0;\n        int cr = 0, cc = 0;\n        bool ok = true;\n\n        for (int k = 0; k < M; k++) {\n            auto [r,c] = base[(st + k) % M];\n            int dist = manhattan(cr, cc, r, c);\n            cost += 100LL * dist + load * dist;\n\n            int v = H[r][c];\n            load += v;\n            if (load < 0) {\n                ok = false;\n                break;\n            }\n\n            cr = r;\n            cc = c;\n        }\n\n        if (ok && load == 0 && cost < bestCost) {\n            bestCost = cost;\n            bestStart = st;\n        }\n    }\n\n    return {bestCost, bestStart};\n}\n\nvoid test_cyclic_candidates(const vector<pair<int,int>>& base, Result& best) {\n    EvalInfo ev = eval_cyclic_order(base);\n    if (ev.start < 0) return;\n    if (ev.cost >= best.cost) return;\n\n    Result r = simulate_cyclic_path(base, ev.start);\n    if (r.cost < best.cost) best = move(r);\n}\n\nvector<pair<int,int>> improve_two_opt(vector<pair<int,int>> p, int maxIter, uint32_t seed) {\n    int M = p.size();\n    if (M < 4) return p;\n\n    EvalInfo curEval = eval_cyclic_order(p);\n    if (curEval.start < 0) return p;\n\n    long long curCost = curEval.cost;\n    long long bestCost = curCost;\n    vector<pair<int,int>> bestPath = p;\n    int noImprove = 0;\n\n    auto rnd = [&]() {\n        seed ^= seed << 13;\n        seed ^= seed >> 17;\n        seed ^= seed << 5;\n        return seed;\n    };\n\n    for (int it = 0; it < maxIter && noImprove < maxIter / 2; it++) {\n        if ((it & 127) == 0 && elapsed_sec() > 1.86) break;\n\n        int l = rnd() % M;\n        int r = rnd() % M;\n        if (l > r) swap(l, r);\n        if (r - l < 2) {\n            noImprove++;\n            continue;\n        }\n\n        reverse(p.begin() + l, p.begin() + r + 1);\n        EvalInfo ne = eval_cyclic_order(p);\n\n        if (ne.start >= 0 && ne.cost < curCost) {\n            curCost = ne.cost;\n            noImprove = 0;\n            if (curCost < bestCost) {\n                bestCost = curCost;\n                bestPath = p;\n            }\n        } else {\n            reverse(p.begin() + l, p.begin() + r + 1);\n            noImprove++;\n        }\n    }\n\n    return bestPath;\n}\n\nvector<pair<int,int>> improve_window_two_opt(vector<pair<int,int>> p, int maxLen) {\n    int M = p.size();\n    if (M < 4) return p;\n\n    EvalInfo ev = eval_cyclic_order(p);\n    if (ev.start < 0) return p;\n\n    long long curCost = ev.cost;\n    bool improved = true;\n\n    while (improved && elapsed_sec() < 1.84) {\n        improved = false;\n\n        for (int len = 3; len <= maxLen && !improved; len++) {\n            for (int l = 0; l + len <= M; l++) {\n                if ((l & 31) == 0 && elapsed_sec() > 1.84) return p;\n\n                int r = l + len - 1;\n                reverse(p.begin() + l, p.begin() + r + 1);\n                EvalInfo ne = eval_cyclic_order(p);\n\n                if (ne.start >= 0 && ne.cost < curCost) {\n                    curCost = ne.cost;\n                    improved = true;\n                    break;\n                } else {\n                    reverse(p.begin() + l, p.begin() + r + 1);\n                }\n            }\n        }\n    }\n\n    return p;\n}\n\nvector<pair<int,int>> row_snake_from_order(const vector<int>& rows, bool revFirst) {\n    vector<pair<int,int>> p;\n    for (int idx = 0; idx < (int)rows.size(); idx++) {\n        int i = rows[idx];\n        bool rev = (idx % 2) ^ revFirst;\n        if (!rev) for (int j = 0; j < N; j++) p.push_back({i,j});\n        else for (int j = N - 1; j >= 0; j--) p.push_back({i,j});\n    }\n    return p;\n}\n\nvector<pair<int,int>> col_snake_from_order(const vector<int>& cols, bool revFirst) {\n    vector<pair<int,int>> p;\n    for (int idx = 0; idx < (int)cols.size(); idx++) {\n        int j = cols[idx];\n        bool rev = (idx % 2) ^ revFirst;\n        if (!rev) for (int i = 0; i < N; i++) p.push_back({i,j});\n        else for (int i = N - 1; i >= 0; i--) p.push_back({i,j});\n    }\n    return p;\n}\n\nvector<int> normal_order() {\n    vector<int> v(N);\n    iota(v.begin(), v.end(), 0);\n    return v;\n}\n\nvector<int> reverse_order_vec() {\n    vector<int> v = normal_order();\n    reverse(v.begin(), v.end());\n    return v;\n}\n\nvector<int> center_out_order() {\n    vector<int> v;\n    int a = (N - 1) / 2, b = N / 2;\n    for (int d = 0; d < N; d++) {\n        int x = a - d;\n        int y = b + d;\n        if (x >= 0) v.push_back(x);\n        if (y < N && y != x) v.push_back(y);\n    }\n    return v;\n}\n\nvector<int> outside_in_order() {\n    vector<int> v;\n    for (int d = 0; d < (N + 1) / 2; d++) {\n        v.push_back(d);\n        if (N - 1 - d != d) v.push_back(N - 1 - d);\n    }\n    return v;\n}\n\nvector<int> even_odd_order() {\n    vector<int> v;\n    for (int i = 0; i < N; i += 2) v.push_back(i);\n    for (int i = 1; i < N; i += 2) v.push_back(i);\n    return v;\n}\n\nvector<int> odd_even_order() {\n    vector<int> v;\n    for (int i = 1; i < N; i += 2) v.push_back(i);\n    for (int i = 0; i < N; i += 2) v.push_back(i);\n    return v;\n}\n\nvector<pair<int,int>> row_raster() {\n    vector<pair<int,int>> p;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> col_raster() {\n    vector<pair<int,int>> p;\n    for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> spiral_outside_in() {\n    vector<pair<int,int>> p;\n    int top = 0, bottom = N - 1, left = 0, right = N - 1;\n    while (top <= bottom && left <= right) {\n        for (int j = left; j <= right; j++) p.push_back({top,j});\n        top++;\n        for (int i = top; i <= bottom; i++) p.push_back({i,right});\n        right--;\n        if (top <= bottom) {\n            for (int j = right; j >= left; j--) p.push_back({bottom,j});\n            bottom--;\n        }\n        if (left <= right) {\n            for (int i = bottom; i >= top; i--) p.push_back({i,left});\n            left++;\n        }\n    }\n    return p;\n}\n\nvector<pair<int,int>> spiral_center_out() {\n    auto p = spiral_outside_in();\n    reverse(p.begin(), p.end());\n    return p;\n}\n\nvector<pair<int,int>> diagonal_order(bool anti, bool zigzag) {\n    vector<pair<int,int>> p;\n    for (int s = 0; s <= 2 * (N - 1); s++) {\n        vector<pair<int,int>> v;\n        for (int i = 0; i < N; i++) {\n            int j = s - i;\n            if (0 <= j && j < N) {\n                if (!anti) v.push_back({i,j});\n                else v.push_back({i,N-1-j});\n            }\n        }\n        if (zigzag && (s & 1)) reverse(v.begin(), v.end());\n        for (auto x : v) p.push_back(x);\n    }\n    return p;\n}\n\nint morton_code(int r, int c) {\n    int z = 0;\n    for (int b = 0; b < 5; b++) {\n        z |= ((c >> b) & 1) << (2 * b);\n        z |= ((r >> b) & 1) << (2 * b + 1);\n    }\n    return z;\n}\n\nvector<pair<int,int>> morton_order(bool swapRC, bool revBits) {\n    vector<tuple<int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int a = swapRC ? j : i;\n            int b = swapRC ? i : j;\n            int code = morton_code(a, b);\n            if (revBits) code = -code;\n            v.push_back({code, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [_, i, j] : v) p.push_back({i,j});\n    return p;\n}\n\nint hilbert_xy2d(int n, int x, int y) {\n    int rx, ry, s, d = 0;\n    for (s = n / 2; s > 0; s /= 2) {\n        rx = (x & s) > 0;\n        ry = (y & s) > 0;\n        d += s * s * ((3 * rx) ^ ry);\n        if (ry == 0) {\n            if (rx == 1) {\n                x = n - 1 - x;\n                y = n - 1 - y;\n            }\n            swap(x, y);\n        }\n    }\n    return d;\n}\n\nvector<pair<int,int>> hilbert_order(int rot, bool rev) {\n    vector<tuple<int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int x = i, y = j;\n            if (rot == 1) { x = j; y = N - 1 - i; }\n            if (rot == 2) { x = N - 1 - i; y = N - 1 - j; }\n            if (rot == 3) { x = N - 1 - j; y = i; }\n            if (rot == 4) { x = j; y = i; }\n            if (rot == 5) { x = N - 1 - i; y = j; }\n            if (rot == 6) { x = i; y = N - 1 - j; }\n            if (rot == 7) { x = N - 1 - j; y = N - 1 - i; }\n\n            int code = hilbert_xy2d(32, x, y);\n            if (rev) code = -code;\n            v.push_back({code, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [_, i, j] : v) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> projection_order(int a, int b, bool zigzagTie, bool rev) {\n    vector<tuple<int,int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int key = a * i + b * j;\n            int tie = -b * i + a * j;\n            if (zigzagTie && (key & 1)) tie = -tie;\n            if (rev) key = -key;\n            v.push_back({key, tie, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [k,t,i,j] : v) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> block_snake(int B, bool blockColMajor, bool revBlockFirst, bool revInnerFirst) {\n    vector<pair<int,int>> p;\n    int nb = (N + B - 1) / B;\n\n    if (!blockColMajor) {\n        for (int bi = 0; bi < nb; bi++) {\n            vector<int> bjList;\n            if (((bi & 1) ^ revBlockFirst) == 0) {\n                for (int bj = 0; bj < nb; bj++) bjList.push_back(bj);\n            } else {\n                for (int bj = nb - 1; bj >= 0; bj--) bjList.push_back(bj);\n            }\n\n            for (int bj : bjList) {\n                int r0 = bi * B, r1 = min(N, r0 + B);\n                int c0 = bj * B, c1 = min(N, c0 + B);\n\n                for (int ii = r0; ii < r1; ii++) {\n                    bool rev = ((ii - r0) & 1) ^ revInnerFirst;\n                    if (!rev) for (int jj = c0; jj < c1; jj++) p.push_back({ii,jj});\n                    else for (int jj = c1 - 1; jj >= c0; jj--) p.push_back({ii,jj});\n                }\n            }\n        }\n    } else {\n        for (int bj = 0; bj < nb; bj++) {\n            vector<int> biList;\n            if (((bj & 1) ^ revBlockFirst) == 0) {\n                for (int bi = 0; bi < nb; bi++) biList.push_back(bi);\n            } else {\n                for (int bi = nb - 1; bi >= 0; bi--) biList.push_back(bi);\n            }\n\n            for (int bi : biList) {\n                int r0 = bi * B, r1 = min(N, r0 + B);\n                int c0 = bj * B, c1 = min(N, c0 + B);\n\n                for (int jj = c0; jj < c1; jj++) {\n                    bool rev = ((jj - c0) & 1) ^ revInnerFirst;\n                    if (!rev) for (int ii = r0; ii < r1; ii++) p.push_back({ii,jj});\n                    else for (int ii = r1 - 1; ii >= r0; ii--) p.push_back({ii,jj});\n                }\n            }\n        }\n    }\n\n    return p;\n}\n\nint smooth_height(int r, int c) {\n    int sum = 0, cnt = 0;\n    for (int dr = -1; dr <= 1; dr++) {\n        for (int dc = -1; dc <= 1; dc++) {\n            int nr = r + dr, nc = c + dc;\n            if (0 <= nr && nr < N && 0 <= nc && nc < N) {\n                sum += H[nr][nc];\n                cnt++;\n            }\n        }\n    }\n    return sum / cnt;\n}\n\nvector<pair<int,int>> height_sorted_order(bool smooth, bool descending, int tieMode) {\n    vector<tuple<int,int,int,int>> v;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int hv = smooth ? smooth_height(i,j) : H[i][j];\n            int key = descending ? -hv : hv;\n            int tie;\n            if (tieMode == 0) tie = i * N + j;\n            else if (tieMode == 1) tie = j * N + i;\n            else if (tieMode == 2) tie = manhattan(i,j,N/2,N/2);\n            else tie = morton_code(i,j);\n            v.push_back({key, tie, i, j});\n        }\n    }\n    sort(v.begin(), v.end());\n    vector<pair<int,int>> p;\n    for (auto [a,b,i,j] : v) p.push_back({i,j});\n    return p;\n}\n\nvector<pair<int,int>> nearest_terrain_path(int sr, int sc, double distW, double signW, double magW) {\n    vector<pair<int,int>> p;\n    vector<vector<int>> used(N, vector<int>(N, 0));\n    int r = sr, c = sc;\n    long long balance = 0;\n\n    for (int step = 0; step < N * N; step++) {\n        p.push_back({r,c});\n        used[r][c] = 1;\n        balance += H[r][c];\n\n        if (step == N * N - 1) break;\n\n        int bestR = -1, bestC = -1;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (used[i][j]) continue;\n\n                int d = manhattan(r,c,i,j);\n                int hv = H[i][j];\n\n                double signScore = 0;\n                if (balance < 0 && hv > 0) signScore -= signW * sqrt((double)abs(hv));\n                if (balance > 0 && hv < 0) signScore -= signW * sqrt((double)abs(hv));\n                if (balance < 0 && hv < 0) signScore += signW;\n                if (balance > 0 && hv > 0) signScore += signW * 0.3;\n\n                double score =\n                    distW * d\n                    + signScore\n                    - magW * sqrt((double)abs(hv));\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    bestR = i;\n                    bestC = j;\n                }\n            }\n        }\n\n        r = bestR;\n        c = bestC;\n    }\n\n    return p;\n}\n\nvector<pair<int,int>> nearest_nonzero_path(int sr, int sc, double distW, double signW, double magW, double startBias) {\n    vector<pair<int,int>> cells;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (H[i][j] != 0) cells.push_back({i,j});\n        }\n    }\n\n    int M = cells.size();\n    if (M == 0) return {};\n\n    int start = 0;\n    int bestD = 1e9;\n    for (int i = 0; i < M; i++) {\n        int d = manhattan(sr, sc, cells[i].first, cells[i].second);\n        if (d < bestD) {\n            bestD = d;\n            start = i;\n        }\n    }\n\n    vector<int> used(M, 0);\n    vector<pair<int,int>> p;\n    p.reserve(M);\n\n    int cur = start;\n    long long balance = 0;\n\n    for (int step = 0; step < M; step++) {\n        auto [r,c] = cells[cur];\n        p.push_back({r,c});\n        used[cur] = 1;\n        balance += H[r][c];\n\n        if (step == M - 1) break;\n\n        int best = -1;\n        double bestScore = 1e100;\n\n        for (int i = 0; i < M; i++) {\n            if (used[i]) continue;\n\n            auto [nr,nc] = cells[i];\n            int hv = H[nr][nc];\n            int d = manhattan(r,c,nr,nc);\n\n            double signScore = 0;\n            if (balance < 0 && hv > 0) signScore -= signW * sqrt((double)abs(hv));\n            if (balance > 0 && hv < 0) signScore -= signW * sqrt((double)abs(hv));\n            if (balance < 0 && hv < 0) signScore += signW;\n            if (balance > 0 && hv > 0) signScore += signW * 0.3;\n\n            double score =\n                distW * d\n                + signScore\n                - magW * sqrt((double)abs(hv))\n                + startBias * manhattan(sr, sc, nr, nc) / (double)(step + 5);\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = i;\n            }\n        }\n\n        cur = best;\n    }\n\n    return p;\n}\n\nbool valid_order(const vector<pair<int,int>>& p) {\n    if ((int)p.size() != N * N) return false;\n    vector<vector<int>> seen(N, vector<int>(N, 0));\n    for (auto [r,c] : p) {\n        if (r < 0 || r >= N || c < 0 || c >= N) return false;\n        if (seen[r][c]) return false;\n        seen[r][c] = 1;\n    }\n    return true;\n}\n\nbool valid_nonzero_order(const vector<pair<int,int>>& p) {\n    vector<vector<int>> seen(N, vector<int>(N, 0));\n    int cnt = 0;\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (H[i][j] != 0) cnt++;\n    if ((int)p.size() != cnt) return false;\n    for (auto [r,c] : p) {\n        if (r < 0 || r >= N || c < 0 || c >= N) return false;\n        if (H[r][c] == 0) return false;\n        if (seen[r][c]) return false;\n        seen[r][c] = 1;\n    }\n    return true;\n}\n\nint main() {\n    START_TIME = chrono::steady_clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    H.assign(N, vector<int>(N));\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) cin >> H[i][j];\n    }\n\n    Result best;\n\n    vector<Params> params = {\n        {1.0, 1.0, 0.0, 0.0},\n        {1.0, 1.0, 1.0, 0.2},\n        {1.0, 1.0, 2.0, 0.5},\n        {1.0, 1.3, 1.0, 0.5},\n        {1.3, 1.0, 1.0, 0.5},\n        {0.7, 1.2, 2.0, 0.8},\n        {1.5, 0.8, 1.5, 0.3},\n        {1.0, 2.0, 2.0, 1.0},\n        {2.0, 1.0, 2.0, 1.0},\n        {0.5, 1.5, 1.0, 1.0},\n    };\n\n    for (auto& p : params) {\n        Result res = simulate_greedy(p);\n        if (res.cost < best.cost) best = move(res);\n    }\n\n    vector<vector<pair<int,int>>> paths;\n\n    vector<vector<int>> orders = {\n        normal_order(),\n        reverse_order_vec(),\n        center_out_order(),\n        outside_in_order(),\n        even_odd_order(),\n        odd_even_order()\n    };\n\n    for (auto rows : orders) {\n        for (int rf = 0; rf < 2; rf++) {\n            paths.push_back(row_snake_from_order(rows, rf));\n            paths.push_back(col_snake_from_order(rows, rf));\n        }\n    }\n\n    paths.push_back(row_raster());\n    paths.push_back(col_raster());\n    paths.push_back(spiral_outside_in());\n    paths.push_back(spiral_center_out());\n\n    for (int anti = 0; anti < 2; anti++) {\n        for (int zig = 0; zig < 2; zig++) {\n            paths.push_back(diagonal_order(anti, zig));\n        }\n    }\n\n    for (int sw = 0; sw < 2; sw++) {\n        for (int rv = 0; rv < 2; rv++) {\n            paths.push_back(morton_order(sw, rv));\n        }\n    }\n\n    for (int rot = 0; rot < 8; rot++) {\n        for (int rv = 0; rv < 2; rv++) {\n            paths.push_back(hilbert_order(rot, rv));\n        }\n    }\n\n    vector<pair<int,int>> dirs = {\n        {1,1}, {1,-1}, {2,1}, {1,2}, {2,-1}, {1,-2},\n        {3,1}, {1,3}, {3,-1}, {1,-3}\n    };\n    for (auto [a,b] : dirs) {\n        for (int zig = 0; zig < 2; zig++) {\n            for (int rv = 0; rv < 2; rv++) {\n                paths.push_back(projection_order(a,b,zig,rv));\n            }\n        }\n    }\n\n    for (int B : {2, 4, 5, 10}) {\n        for (int cm = 0; cm < 2; cm++) {\n            for (int rb = 0; rb < 2; rb++) {\n                for (int ri = 0; ri < 2; ri++) {\n                    paths.push_back(block_snake(B, cm, rb, ri));\n                }\n            }\n        }\n    }\n\n    for (int sm = 0; sm < 2; sm++) {\n        for (int desc = 0; desc < 2; desc++) {\n            for (int tie = 0; tie < 4; tie++) {\n                paths.push_back(height_sorted_order(sm, desc, tie));\n            }\n        }\n    }\n\n    vector<pair<int,int>> starts = {\n        {0,0}, {0,N-1}, {N-1,0}, {N-1,N-1},\n        {N/2,N/2}, {0,N/2}, {N/2,0}, {N-1,N/2}, {N/2,N-1}\n    };\n\n    for (auto [sr,sc] : starts) {\n        for (double dw : {1.0, 1.5, 2.0}) {\n            for (double sw : {1.0, 2.0, 4.0}) {\n                paths.push_back(nearest_terrain_path(sr, sc, dw, sw, 0.2));\n                paths.push_back(nearest_terrain_path(sr, sc, dw, sw, 1.0));\n            }\n        }\n    }\n\n    int originalSize = paths.size();\n    for (int i = 0; i < originalSize; i++) {\n        auto q = paths[i];\n        reverse(q.begin(), q.end());\n        paths.push_back(q);\n    }\n\n    set<vector<pair<int,int>>> seen;\n    vector<vector<pair<int,int>>> uniq;\n    for (auto& p : paths) {\n        if (!valid_order(p)) continue;\n        if (seen.insert(p).second) uniq.push_back(p);\n    }\n\n    set<vector<pair<int,int>>> seenCompressed;\n    vector<pair<long long, vector<pair<int,int>>>> improveSeeds;\n\n    for (auto& path : uniq) {\n        Result res = simulate_path(path);\n        if (res.cost < best.cost) best = move(res);\n\n        test_cyclic_candidates(path, best);\n\n        auto cp = compress_nonzero(path);\n        if (!cp.empty() && seenCompressed.insert(cp).second) {\n            EvalInfo ev = eval_cyclic_order(cp);\n            if (ev.start >= 0) improveSeeds.push_back({ev.cost, cp});\n            test_cyclic_candidates(cp, best);\n        }\n\n        reverse(cp.begin(), cp.end());\n        if (!cp.empty() && seenCompressed.insert(cp).second) {\n            EvalInfo ev = eval_cyclic_order(cp);\n            if (ev.start >= 0) improveSeeds.push_back({ev.cost, cp});\n            test_cyclic_candidates(cp, best);\n        }\n    }\n\n    vector<vector<pair<int,int>>> nzPaths;\n    for (auto [sr,sc] : starts) {\n        for (double dw : {0.8, 1.0, 1.3, 1.8, 2.5}) {\n            for (double sw : {0.5, 1.0, 2.0, 4.0, 8.0}) {\n                for (double mw : {0.0, 0.5, 1.0}) {\n                    nzPaths.push_back(nearest_nonzero_path(sr, sc, dw, sw, mw, 0.0));\n                    nzPaths.push_back(nearest_nonzero_path(sr, sc, dw, sw, mw, 1.0));\n                }\n            }\n        }\n    }\n\n    for (auto& p : nzPaths) {\n        if (!valid_nonzero_order(p)) continue;\n\n        if (seenCompressed.insert(p).second) {\n            EvalInfo ev = eval_cyclic_order(p);\n            if (ev.start >= 0) improveSeeds.push_back({ev.cost, p});\n            test_cyclic_candidates(p, best);\n        }\n\n        auto q = p;\n        reverse(q.begin(), q.end());\n        if (seenCompressed.insert(q).second) {\n            EvalInfo ev = eval_cyclic_order(q);\n            if (ev.start >= 0) improveSeeds.push_back({ev.cost, q});\n            test_cyclic_candidates(q, best);\n        }\n    }\n\n    sort(improveSeeds.begin(), improveSeeds.end(),\n         [](const auto& a, const auto& b) { return a.first < b.first; });\n\n    int oldLimit = min<int>(20, improveSeeds.size());\n    for (int i = 0; i < oldLimit; i++) {\n        if (elapsed_sec() > 1.80) break;\n\n        auto p = improveSeeds[i].second;\n        p = improve_two_opt(p, 700, 2463534242u);\n        test_cyclic_candidates(p, best);\n\n        auto q = p;\n        reverse(q.begin(), q.end());\n        test_cyclic_candidates(q, best);\n    }\n\n    int deepLimit = min<int>(40, improveSeeds.size());\n    for (int i = 0; i < deepLimit; i++) {\n        if (elapsed_sec() > 1.82) break;\n\n        auto p = improveSeeds[i].second;\n        p = improve_two_opt(p, 1400, 2463534242u + 1000003u * i);\n        test_cyclic_candidates(p, best);\n\n        auto q = p;\n        reverse(q.begin(), q.end());\n        test_cyclic_candidates(q, best);\n    }\n\n    int winLimit = min<int>(10, improveSeeds.size());\n    for (int i = 0; i < winLimit; i++) {\n        if (elapsed_sec() > 1.82) break;\n\n        auto p = improveSeeds[i].second;\n        p = improve_window_two_opt(p, 40);\n        test_cyclic_candidates(p, best);\n    }\n\n    for (auto& s : best.ops) cout << s << '\\n';\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x;\n    XorShift(uint64_t seed = 88172645463325252ull) : x(seed) {}\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int n) {\n        return (int)(next() % n);\n    }\n    double rand01() {\n        return (next() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, T;\n    cin >> N >> M >> T;\n\n    const int S = 2 * N * (N - 1);\n    const int C = N * N;\n\n    vector<vector<int>> X(S, vector<int>(M));\n    for (int i = 0; i < S; i++) {\n        for (int j = 0; j < M; j++) cin >> X[i][j];\n    }\n\n    vector<int> target(M, 0);\n    for (int i = 0; i < S; i++) {\n        for (int l = 0; l < M; l++) target[l] = max(target[l], X[i][l]);\n    }\n    int targetSum = accumulate(target.begin(), target.end(), 0);\n\n    vector<pair<int,int>> edges;\n    vector<vector<int>> incident(C);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if (j + 1 < N) {\n                int id2 = id + 1;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n            if (i + 1 < N) {\n                int id2 = id + N;\n                edges.push_back({id, id2});\n                incident[id].push_back((int)edges.size() - 1);\n                incident[id2].push_back((int)edges.size() - 1);\n            }\n        }\n    }\n\n    vector<int> deg(C, 0);\n    for (auto [a,b] : edges) {\n        deg[a]++;\n        deg[b]++;\n    }\n\n    vector<int> blackCells, whiteCells, allCells(C);\n    iota(allCells.begin(), allCells.end(), 0);\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int id = i * N + j;\n            if ((i + j) & 1) whiteCells.push_back(id);\n            else blackCells.push_back(id);\n        }\n    }\n\n    auto sort_cells = [&](vector<int>& v) {\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n    };\n\n    sort_cells(blackCells);\n    sort_cells(whiteCells);\n    sort_cells(allCells);\n\n    auto start_time = chrono::steady_clock::now();\n    XorShift rng(246813579);\n\n    for (int turn = 0; turn < T; turn++) {\n        vector<int> curMax(M, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) curMax[l] = max(curMax[l], X[i][l]);\n        }\n\n        vector<int> sumv(S, 0);\n        for (int i = 0; i < S; i++) {\n            for (int l = 0; l < M; l++) sumv[i] += X[i][l];\n        }\n\n        double phase = (double)turn / max(1, T - 1);\n        bool finalTurn = (turn == T - 1);\n\n        vector<double> seedScore(S, 0);\n        vector<double> valueScore(S, 0);\n        vector<double> targetFit(S, 0);\n        vector<double> curFit(S, 0);\n\n        for (int i = 0; i < S; i++) {\n            double tr = 0, trsq = 0;\n            double cr = 0, crsq = 0;\n            double elite = 0;\n            int nearTarget = 0;\n            int exactCur = 0;\n\n            for (int l = 0; l < M; l++) {\n                double rt = (double)X[i][l] / max(1, target[l]);\n                double rc = (double)X[i][l] / max(1, curMax[l]);\n\n                tr += 100.0 * rt;\n                trsq += 100.0 * rt * rt;\n                cr += 100.0 * rc;\n                crsq += 100.0 * rc * rc;\n\n                if (X[i][l] >= target[l] * 0.95) nearTarget++;\n                if (X[i][l] == curMax[l]) exactCur++;\n\n                if (X[i][l] == curMax[l]) elite += 70.0;\n                if (X[i][l] >= target[l] * 0.95) elite += 45.0;\n                else if (X[i][l] >= target[l] * 0.88) elite += 18.0;\n            }\n\n            targetFit[i] = tr + 0.45 * trsq + 32.0 * nearTarget;\n            curFit[i] = cr + 0.35 * crsq + 38.0 * exactCur;\n            valueScore[i] = sumv[i] + 0.55 * targetFit[i];\n\n            seedScore[i] =\n                (0.70 + 0.95 * phase) * sumv[i]\n                + 0.80 * targetFit[i]\n                + 0.38 * curFit[i]\n                + elite;\n        }\n\n        vector<vector<double>> P(S, vector<double>(S, 0.0));\n\n        for (int a = 0; a < S; a++) {\n            for (int b = a + 1; b < S; b++) {\n                int maxsum = 0;\n                int minsum = 0;\n                int diff = 0;\n                int nearTarget = 0;\n                int nearCurrent = 0;\n                int exactCurrent = 0;\n                int bothMedium = 0;\n                double targetRatioSq = 0;\n\n                for (int l = 0; l < M; l++) {\n                    int ma = max(X[a][l], X[b][l]);\n                    int mi = min(X[a][l], X[b][l]);\n                    int d = abs(X[a][l] - X[b][l]);\n\n                    maxsum += ma;\n                    minsum += mi;\n                    diff += d;\n\n                    double rt = (double)ma / max(1, target[l]);\n                    targetRatioSq += rt * rt;\n\n                    if (ma >= target[l] * 0.92) nearTarget++;\n                    if (ma >= curMax[l] * 0.92) nearCurrent++;\n                    if (ma == curMax[l]) exactCurrent++;\n                    if (X[a][l] >= target[l] * 0.70 && X[b][l] >= target[l] * 0.70) bothMedium++;\n                }\n\n                double expected = 0.5 * (sumv[a] + sumv[b]);\n                double closeToTarget = targetSum > 0 ? (double)maxsum / targetSum : 0.0;\n\n                double sc = 0;\n                sc += (1.70 + 0.55 * phase) * maxsum;\n                sc += (0.18 + 1.10 * phase) * expected;\n                sc += 0.16 * minsum;\n                sc += (0.24 - 0.13 * phase) * diff;\n                sc += 34.0 * nearTarget;\n                sc += 18.0 * nearCurrent;\n                sc += 13.0 * exactCurrent;\n                sc += 7.0 * bothMedium;\n                sc += 18.0 * targetRatioSq;\n                sc += 300.0 * closeToTarget * closeToTarget;\n\n                P[a][b] = P[b][a] = sc;\n            }\n        }\n\n        auto make_selection = [&](int mode) {\n            vector<int> selected;\n            vector<int> used(S, 0);\n\n            auto add_seed = [&](int id) {\n                if (!used[id] && (int)selected.size() < C) {\n                    used[id] = 1;\n                    selected.push_back(id);\n                }\n            };\n\n            int champDepth = (turn <= 6 ? 2 : 1);\n            if (mode == 3) champDepth = 2;\n\n            for (int l = 0; l < M; l++) {\n                vector<int> ids(S);\n                iota(ids.begin(), ids.end(), 0);\n                sort(ids.begin(), ids.end(), [&](int a, int b) {\n                    if (X[a][l] != X[b][l]) return X[a][l] > X[b][l];\n                    return seedScore[a] > seedScore[b];\n                });\n\n                for (int r = 0; r < champDepth; r++) add_seed(ids[r]);\n            }\n\n            vector<int> ord(S);\n            iota(ord.begin(), ord.end(), 0);\n\n            if (mode == 0) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n            } else if (mode == 1) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return targetFit[a] > targetFit[b];\n                });\n            } else if (mode == 2) {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return valueScore[a] > valueScore[b];\n                });\n            } else {\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    return curFit[a] > curFit[b];\n                });\n            }\n\n            int mandatoryTop;\n            if (mode == 2) mandatoryTop = 14 + (int)(8 * phase);\n            else mandatoryTop = 10 + (int)(6 * phase);\n\n            for (int id : ord) {\n                if ((int)selected.size() >= mandatoryTop) break;\n                add_seed(id);\n            }\n\n            vector<int> cover(M, 0);\n            for (int id : selected) {\n                for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[id][l]);\n            }\n\n            while ((int)selected.size() < C) {\n                int best = -1;\n                double bestSc = -1e100;\n\n                for (int i = 0; i < S; i++) if (!used[i]) {\n                    double gain = 0;\n\n                    for (int l = 0; l < M; l++) {\n                        int d = max(0, X[i][l] - cover[l]);\n\n                        if (mode == 0) gain += 12.0 * d;\n                        if (mode == 1) gain += 15.0 * d;\n                        if (mode == 2) gain += 7.0 * d;\n                        if (mode == 3) gain += 13.0 * d;\n\n                        double rt = (double)X[i][l] / max(1, target[l]);\n                        double rc = (double)X[i][l] / max(1, curMax[l]);\n\n                        gain += 24.0 * rt + 12.0 * rc;\n\n                        if (X[i][l] >= target[l] * 0.92) gain += 18.0;\n                        if (X[i][l] == curMax[l]) gain += 22.0;\n                    }\n\n                    double bestPair = 0;\n                    double avgPair = 0;\n\n                    for (int id : selected) {\n                        bestPair = max(bestPair, P[i][id]);\n                        avgPair += P[i][id];\n                    }\n\n                    if (!selected.empty()) avgPair /= selected.size();\n\n                    double sc =\n                        gain\n                        + (0.32 + 0.55 * phase) * seedScore[i]\n                        + (mode == 2 ? 0.35 : 0.24) * bestPair\n                        + 0.08 * avgPair\n                        + rng.rand01() * 1e-5;\n\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        best = i;\n                    }\n                }\n\n                add_seed(best);\n                for (int l = 0; l < M; l++) cover[l] = max(cover[l], X[best][l]);\n            }\n\n            return selected;\n        };\n\n        auto layout_score = [&](const vector<int>& posSeed) {\n            double s = 0;\n            for (auto [u,v] : edges) s += P[posSeed[u]][posSeed[v]];\n            return s;\n        };\n\n        auto make_layouts = [&](const vector<int>& selected) {\n            vector<vector<int>> layouts;\n\n            // Layout A: complementary bipartite.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> gA, gB;\n                gA.push_back(rem[0]);\n\n                for (int idx = 1; idx < (int)rem.size(); idx++) {\n                    int id = rem[idx];\n\n                    if ((int)gA.size() >= 18) {\n                        gB.push_back(id);\n                        continue;\n                    }\n                    if ((int)gB.size() >= 18) {\n                        gA.push_back(id);\n                        continue;\n                    }\n\n                    double toA = 0;\n                    double toB = 0;\n\n                    for (int x : gA) toB += P[id][x];\n                    for (int x : gB) toA += P[id][x];\n\n                    if (toA > toB) gA.push_back(id);\n                    else gB.push_back(id);\n                }\n\n                while ((int)gA.size() < 18) {\n                    gA.push_back(gB.back());\n                    gB.pop_back();\n                }\n\n                while ((int)gB.size() < 18) {\n                    gB.push_back(gA.back());\n                    gA.pop_back();\n                }\n\n                sort(gA.begin(), gA.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                sort(gB.begin(), gB.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < 18; i++) {\n                    pos[blackCells[i]] = gA[i];\n                    pos[whiteCells[i]] = gB[i];\n                }\n\n                layouts.push_back(pos);\n            }\n\n            // Layout B: strength-degree.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < C; i++) {\n                    pos[allCells[i]] = rem[i];\n                }\n\n                layouts.push_back(pos);\n            }\n\n            // Layout C: alternating target/value on bipartition.\n            {\n                vector<int> rem = selected;\n                sort(rem.begin(), rem.end(), [&](int a, int b) {\n                    return targetFit[a] > targetFit[b];\n                });\n\n                vector<int> gA;\n                vector<int> gB;\n\n                for (int i = 0; i < C; i++) {\n                    if (i % 2 == 0) gA.push_back(rem[i]);\n                    else gB.push_back(rem[i]);\n                }\n\n                sort(gA.begin(), gA.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                sort(gB.begin(), gB.end(), [&](int a, int b) {\n                    return seedScore[a] > seedScore[b];\n                });\n\n                vector<int> pos(C, -1);\n                for (int i = 0; i < 18; i++) {\n                    pos[blackCells[i]] = gA[i];\n                    pos[whiteCells[i]] = gB[i];\n                }\n\n                layouts.push_back(pos);\n            }\n\n            return layouts;\n        };\n\n        auto improve_layout = [&](vector<int> posSeed, int iterations, double temp0) {\n            auto edgeScoreAt = [&](const vector<int>& ps, int eid) {\n                auto [u,v] = edges[eid];\n                return P[ps[u]][ps[v]];\n            };\n\n            double cur = layout_score(posSeed);\n\n            for (int it = 0; it < iterations; it++) {\n                int a = rng.randint(C);\n                int b = rng.randint(C);\n                if (a == b) continue;\n\n                vector<int> es;\n\n                for (int e : incident[a]) es.push_back(e);\n                for (int e : incident[b]) es.push_back(e);\n\n                sort(es.begin(), es.end());\n                es.erase(unique(es.begin(), es.end()), es.end());\n\n                double before = 0;\n                for (int e : es) before += edgeScoreAt(posSeed, e);\n\n                swap(posSeed[a], posSeed[b]);\n\n                double after = 0;\n                for (int e : es) after += edgeScoreAt(posSeed, e);\n\n                double delta = after - before;\n                double progress = (double)it / max(1, iterations);\n                double temp = temp0 * (1.0 - progress) + 1.0;\n\n                bool accept = false;\n\n                if (delta >= 0) {\n                    accept = true;\n                } else if (exp(delta / temp) > rng.rand01()) {\n                    accept = true;\n                }\n\n                if (accept) {\n                    cur += delta;\n                } else {\n                    swap(posSeed[a], posSeed[b]);\n                }\n            }\n\n            return pair<double, vector<int>>(cur, posSeed);\n        };\n\n        vector<pair<double, vector<int>>> pool;\n\n        int modes = finalTurn ? 3 : 4;\n\n        for (int mode = 0; mode < modes; mode++) {\n            vector<int> selected = make_selection(mode);\n            vector<vector<int>> layouts = make_layouts(selected);\n\n            for (auto &lay : layouts) {\n                auto res = improve_layout(lay, 2500, 55.0);\n                pool.push_back(res);\n            }\n        }\n\n        sort(pool.begin(), pool.end(), [&](const auto& a, const auto& b) {\n            return a.first > b.first;\n        });\n\n        int starts = min(3, (int)pool.size());\n        int perIter = 26000;\n\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start_time).count();\n\n        if (elapsed > 1.70) {\n            starts = 1;\n            perIter = 20000;\n        }\n\n        pair<double, vector<int>> bestFinal = {-1e100, pool[0].second};\n\n        for (int s = 0; s < starts; s++) {\n            // Different annealing lengths/temperatures give slight portfolio diversity.\n            int iter = perIter;\n            double temp = 75.0;\n            if (s == 1) temp = 62.0;\n            if (s == 2) temp = 90.0;\n\n            auto res = improve_layout(pool[s].second, iter, temp);\n            if (res.first > bestFinal.first) {\n                bestFinal = res;\n            }\n        }\n\n        vector<int> posSeed = bestFinal.second;\n\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                if (j) cout << ' ';\n                cout << posSeed[i * N + j];\n            }\n            cout << '\\n';\n        }\n\n        cout.flush();\n\n        for (int i = 0; i < S; i++) {\n            for (int j = 0; j < M; j++) {\n                cin >> X[i][j];\n            }\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstruct Reach {\n    int f, d, rx, ry;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, V;\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    vector<Pos> src, dst;\n    vector<vector<int>> src_id(N, vector<int>(N, -1));\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] == '0') {\n                src_id[i][j] = (int)src.size();\n                src.push_back({i, j});\n            }\n            if (s[i][j] == '0' && t[i][j] == '1') {\n                dst.push_back({i, j});\n            }\n        }\n    }\n\n    int K = (int)src.size();\n\n    int F = max(1, V - 1);\n    int Vp = F + 1;\n\n    vector<int> len(F);\n    for (int f = 0; f < F; f++) {\n        len[f] = min(N - 1, 1 + (f % 5));\n    }\n\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << len[i - 1] << '\\n';\n    }\n    cout << 0 << ' ' << 0 << '\\n';\n\n    vector<int> finger_dir(F, 0);\n    vector<int> holding(F, -1);\n\n    const int dx[4] = {0, 1, 0, -1};\n    const int dy[4] = {1, 0, -1, 0};\n\n    auto inside = [&](int x, int y) {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    auto manhattan = [&](Pos a, Pos b) {\n        return abs(a.x - b.x) + abs(a.y - b.y);\n    };\n\n    int root_x = 0, root_y = 0;\n\n    auto add_raw_op = [&](string op) {\n        char mv = op[0];\n\n        if (mv == 'U') root_x--;\n        if (mv == 'D') root_x++;\n        if (mv == 'L') root_y--;\n        if (mv == 'R') root_y++;\n\n        for (int f = 0; f < F; f++) {\n            char r = op[1 + f];\n            if (r == 'L') finger_dir[f] = (finger_dir[f] + 3) % 4;\n            if (r == 'R') finger_dir[f] = (finger_dir[f] + 1) % 4;\n        }\n\n        cout << op << '\\n';\n    };\n\n    auto add_move = [&](char mv) {\n        string op(2 * Vp, '.');\n        op[0] = mv;\n        add_raw_op(std::move(op));\n    };\n\n    auto add_rotate = [&](const vector<int>& target_dir) {\n        while (true) {\n            string op(2 * Vp, '.');\n            bool changed = false;\n\n            for (int f = 0; f < F; f++) {\n                if (target_dir[f] < 0) continue;\n                if (finger_dir[f] == target_dir[f]) continue;\n\n                int diff = (target_dir[f] - finger_dir[f] + 4) % 4;\n                if (diff == 1 || diff == 2) op[1 + f] = 'R';\n                else op[1 + f] = 'L';\n\n                changed = true;\n            }\n\n            if (!changed) break;\n            add_raw_op(std::move(op));\n        }\n    };\n\n    auto add_action = [&](const vector<int>& fingers) {\n        string op(2 * Vp, '.');\n        for (int f : fingers) {\n            op[Vp + 1 + f] = 'P';\n        }\n        add_raw_op(std::move(op));\n    };\n\n    auto move_root_to = [&](int tx, int ty) {\n        while (root_x < tx) add_move('D');\n        while (root_x > tx) add_move('U');\n        while (root_y < ty) add_move('R');\n        while (root_y > ty) add_move('L');\n    };\n\n    auto finger_can_reach_from_root = [&](int f, int rx, int ry, Pos p, int &dir_out) {\n        int L = len[f];\n\n        for (int d = 0; d < 4; d++) {\n            if (rx + dx[d] * L == p.x &&\n                ry + dy[d] * L == p.y) {\n                dir_out = d;\n                return true;\n            }\n        }\n\n        return false;\n    };\n\n    auto enumerate_reaches = [&](Pos p, vector<Reach>& out) {\n        out.clear();\n\n        for (int f = 0; f < F; f++) {\n            int L = len[f];\n\n            for (int d = 0; d < 4; d++) {\n                int rx = p.x - dx[d] * L;\n                int ry = p.y - dy[d] * L;\n\n                if (inside(rx, ry)) {\n                    out.push_back({f, d, rx, ry});\n                }\n            }\n        }\n    };\n\n    vector<int> pair_dst(K, -1);\n\n    {\n        struct Edge {\n            short dist, i, j;\n        };\n\n        vector<Edge> edges;\n        edges.reserve(K * K);\n\n        vector<vector<unsigned char>> dist(K, vector<unsigned char>(K));\n\n        for (int i = 0; i < K; i++) {\n            for (int j = 0; j < K; j++) {\n                int d = manhattan(src[i], dst[j]);\n                dist[i][j] = (unsigned char)d;\n                edges.push_back({\n                    (short)d,\n                    (short)i,\n                    (short)j\n                });\n            }\n        }\n\n        sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) {\n            if (a.dist != b.dist) return a.dist < b.dist;\n            if (a.i != b.i) return a.i < b.i;\n            return a.j < b.j;\n        });\n\n        vector<char> used_s(K, 0), used_d(K, 0);\n        int matched = 0;\n\n        for (const auto& e : edges) {\n            int i = e.i;\n            int j = e.j;\n\n            if (!used_s[i] && !used_d[j]) {\n                used_s[i] = 1;\n                used_d[j] = 1;\n                pair_dst[i] = j;\n                matched++;\n                if (matched == K) break;\n            }\n        }\n\n        for (int it = 0; it < 5; it++) {\n            bool improved = false;\n\n            for (int i = 0; i < K; i++) {\n                int ai = pair_dst[i];\n\n                for (int j = i + 1; j < K; j++) {\n                    int aj = pair_dst[j];\n\n                    int cur = dist[i][ai] + dist[j][aj];\n                    int swp = dist[i][aj] + dist[j][ai];\n\n                    if (swp + 1 < cur) {\n                        swap(pair_dst[i], pair_dst[j]);\n                        improved = true;\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    vector<char> done(K, 0);\n    int remaining = K;\n\n    vector<Reach> reach_buf;\n    reach_buf.reserve(F * 4);\n\n    auto best_root_for_cell = [&](Pos p, int &out_rx, int &out_ry) {\n        enumerate_reaches(p, reach_buf);\n\n        int best = INT_MAX;\n        out_rx = out_ry = -1;\n\n        for (const auto& rc : reach_buf) {\n            int c = abs(root_x - rc.rx) + abs(root_y - rc.ry);\n            if (c < best) {\n                best = c;\n                out_rx = rc.rx;\n                out_ry = rc.ry;\n            }\n        }\n\n        return best;\n    };\n\n    auto min_root_dist_to_cell = [&](Pos p) {\n        int rx, ry;\n        return best_root_for_cell(p, rx, ry);\n    };\n\n    auto reachable_source_bonus = [&](int rx, int ry) {\n        int cnt = 0;\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n\n            bool ok = false;\n            for (int f = 0; f < F && !ok; f++) {\n                int d;\n                if (finger_can_reach_from_root(f, rx, ry, src[i], d)) {\n                    ok = true;\n                }\n            }\n\n            if (ok) {\n                cnt++;\n                if (cnt >= 2 * F) break;\n            }\n        }\n\n        int first = min(cnt, F);\n        int extra = max(0, cnt - F);\n        return first * 4 + extra;\n    };\n\n    auto choose_seed = [&]() {\n        int best = -1;\n        int best_cost = INT_MAX;\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n\n            int brx, bry;\n            int approach = best_root_for_cell(src[i], brx, bry);\n\n            int transport = manhattan(src[i], dst[pair_dst[i]]);\n            int dest_near = min_root_dist_to_cell(dst[pair_dst[i]]);\n\n            int cost;\n            if (remaining > K * 2 / 3) {\n                cost = approach * 5 + transport;\n            } else if (remaining > K / 3) {\n                cost = approach * 4 + transport + dest_near;\n            } else {\n                cost = approach * 3 + transport + dest_near * 2;\n            }\n\n            cost -= reachable_source_bonus(brx, bry);\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best = i;\n            }\n        }\n\n        return best;\n    };\n\n    struct Cand {\n        int score, id, f, d;\n    };\n\n    vector<Cand> cands;\n    cands.reserve(10000);\n\n    vector<char> used_f(F), used_item(K);\n    vector<int> pick_pairs, pick_fingers, pick_dirs;\n    vector<int> target_dir(F);\n    vector<int> action_fingers;\n    vector<int> carrying;\n    vector<int> place_fingers, place_dirs;\n    vector<int> tdir(F);\n    vector<int> act_f;\n    vector<Reach> tmp_reaches;\n    tmp_reaches.reserve(F * 4);\n\n    while (remaining > 0) {\n        int seed = choose_seed();\n        if (seed < 0) break;\n\n        enumerate_reaches(src[seed], reach_buf);\n\n        Reach best_reach{-1, -1, -1, -1};\n        int best_cost = INT_MAX;\n\n        for (const auto& rc : reach_buf) {\n            int move_cost = abs(root_x - rc.rx) + abs(root_y - rc.ry);\n            int diff = abs(finger_dir[rc.f] - rc.d);\n            int rot_cost = min(diff, 4 - diff);\n            int cost = move_cost * 3 + rot_cost;\n\n            if (cost < best_cost) {\n                best_cost = cost;\n                best_reach = rc;\n            }\n        }\n\n        move_root_to(best_reach.rx, best_reach.ry);\n\n        cands.clear();\n\n        Pos seed_dest = dst[pair_dst[seed]];\n\n        for (int i = 0; i < K; i++) {\n            if (done[i]) continue;\n\n            for (int f = 0; f < F; f++) {\n                int d;\n\n                if (finger_can_reach_from_root(f, root_x, root_y, src[i], d)) {\n                    Pos di = dst[pair_dst[i]];\n                    int diff = abs(finger_dir[f] - d);\n                    int rot = min(diff, 4 - diff);\n\n                    int score = manhattan(di, seed_dest) * 4\n                              + manhattan(src[i], src[seed])\n                              + rot;\n\n                    cands.push_back({score, i, f, d});\n                }\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) {\n            if (a.score != b.score) return a.score < b.score;\n            return a.id < b.id;\n        });\n\n        fill(used_f.begin(), used_f.end(), 0);\n        fill(used_item.begin(), used_item.end(), 0);\n\n        pick_pairs.clear();\n        pick_fingers.clear();\n        pick_dirs.clear();\n\n        int bestf = -1, bestd = -1, bestr = INT_MAX;\n\n        for (int f = 0; f < F; f++) {\n            int d;\n\n            if (finger_can_reach_from_root(f, root_x, root_y, src[seed], d)) {\n                int diff = abs(finger_dir[f] - d);\n                int rr = min(diff, 4 - diff);\n\n                if (rr < bestr) {\n                    bestr = rr;\n                    bestf = f;\n                    bestd = d;\n                }\n            }\n        }\n\n        if (bestf >= 0) {\n            used_f[bestf] = 1;\n            used_item[seed] = 1;\n\n            pick_pairs.push_back(seed);\n            pick_fingers.push_back(bestf);\n            pick_dirs.push_back(bestd);\n        }\n\n        for (auto c : cands) {\n            if ((int)pick_pairs.size() >= F) break;\n            if (used_f[c.f]) continue;\n            if (used_item[c.id]) continue;\n\n            used_f[c.f] = 1;\n            used_item[c.id] = 1;\n\n            pick_pairs.push_back(c.id);\n            pick_fingers.push_back(c.f);\n            pick_dirs.push_back(c.d);\n        }\n\n        int cnt = (int)pick_pairs.size();\n\n        fill(target_dir.begin(), target_dir.end(), -1);\n        for (int k = 0; k < cnt; k++) {\n            target_dir[pick_fingers[k]] = pick_dirs[k];\n        }\n\n        add_rotate(target_dir);\n\n        action_fingers.clear();\n        for (int k = 0; k < cnt; k++) {\n            int f = pick_fingers[k];\n            int pid = pick_pairs[k];\n\n            action_fingers.push_back(f);\n            holding[f] = pid;\n            s[src[pid].x][src[pid].y] = '0';\n        }\n\n        add_action(action_fingers);\n\n        carrying.clear();\n        for (int f = 0; f < F; f++) {\n            if (holding[f] >= 0) carrying.push_back(f);\n        }\n\n        while (!carrying.empty()) {\n            int best_count = -1;\n            int best_cost2 = INT_MAX;\n            int best_rx = -1;\n            int best_ry = -1;\n\n            for (int f0 : carrying) {\n                int pid0 = holding[f0];\n                Pos q0 = dst[pair_dst[pid0]];\n\n                enumerate_reaches(q0, tmp_reaches);\n\n                for (const auto& rc : tmp_reaches) {\n                    int rr_x = rc.rx;\n                    int rr_y = rc.ry;\n\n                    int cnt_place = 0;\n\n                    for (int f : carrying) {\n                        int pid = holding[f];\n                        Pos q = dst[pair_dst[pid]];\n                        int dd;\n\n                        if (finger_can_reach_from_root(f, rr_x, rr_y, q, dd)) {\n                            cnt_place++;\n                        }\n                    }\n\n                    int cost = abs(root_x - rr_x) + abs(root_y - rr_y);\n\n                    if (cnt_place > best_count ||\n                        (cnt_place == best_count && cost < best_cost2)) {\n                        best_count = cnt_place;\n                        best_cost2 = cost;\n                        best_rx = rr_x;\n                        best_ry = rr_y;\n                    }\n                }\n            }\n\n            move_root_to(best_rx, best_ry);\n\n            place_fingers.clear();\n            place_dirs.clear();\n\n            for (int f : carrying) {\n                int pid = holding[f];\n                Pos q = dst[pair_dst[pid]];\n\n                int d;\n                if (finger_can_reach_from_root(f, root_x, root_y, q, d)) {\n                    place_fingers.push_back(f);\n                    place_dirs.push_back(d);\n                }\n            }\n\n            fill(tdir.begin(), tdir.end(), -1);\n            for (int i = 0; i < (int)place_fingers.size(); i++) {\n                tdir[place_fingers[i]] = place_dirs[i];\n            }\n\n            add_rotate(tdir);\n\n            act_f.clear();\n\n            for (int f : place_fingers) {\n                int pid = holding[f];\n                int did = pair_dst[pid];\n                Pos q = dst[did];\n\n                act_f.push_back(f);\n                holding[f] = -1;\n                done[pid] = 1;\n                remaining--;\n                s[q.x][q.y] = '1';\n            }\n\n            add_action(act_f);\n\n            carrying.clear();\n            for (int f = 0; f < F; f++) {\n                if (holding[f] >= 0) carrying.push_back(f);\n            }\n        }\n    }\n\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Pt {\n    int x, y;\n    bool operator==(const Pt& o) const { return x == o.x && y == o.y; }\n};\n\nstruct Fish {\n    int x, y, t;\n};\n\nstatic const int LIM = 100000;\n\nlong long perimeter_poly(const vector<Pt>& p) {\n    long long res = 0;\n    int m = (int)p.size();\n    for (int i = 0; i < m; i++) {\n        Pt a = p[i], b = p[(i + 1) % m];\n        res += abs(a.x - b.x) + abs(a.y - b.y);\n    }\n    return res;\n}\n\nvector<Pt> simplify_poly(vector<Pt> p) {\n    if (p.empty()) return p;\n\n    vector<Pt> q;\n    q.reserve(p.size());\n    for (auto v : p) {\n        if (q.empty() || !(q.back() == v)) q.push_back(v);\n    }\n    if (q.size() > 1 && q.front() == q.back()) q.pop_back();\n\n    bool changed = true;\n    while (changed && q.size() >= 4) {\n        changed = false;\n        vector<Pt> r;\n        r.reserve(q.size());\n        int m = q.size();\n        for (int i = 0; i < m; i++) {\n            Pt a = q[(i - 1 + m) % m], b = q[i], c = q[(i + 1) % m];\n            if ((a.x == b.x && b.x == c.x) || (a.y == b.y && b.y == c.y)) {\n                changed = true;\n            } else {\n                r.push_back(b);\n            }\n        }\n        q.swap(r);\n    }\n    return q;\n}\n\nbool inside_poly(const vector<Pt>& poly, int x, int y) {\n    bool in = false;\n    int m = poly.size();\n    for (int i = 0, j = m - 1; i < m; j = i++) {\n        Pt a = poly[j], b = poly[i];\n\n        if (a.x == b.x && x == a.x && min(a.y,b.y) <= y && y <= max(a.y,b.y)) return true;\n        if (a.y == b.y && y == a.y && min(a.x,b.x) <= x && x <= max(a.x,b.x)) return true;\n\n        if ((a.y > y) != (b.y > y)) {\n            long double xx = (long double)(b.x - a.x) * (y - a.y) / (long double)(b.y - a.y) + a.x;\n            if (xx >= x) in = !in;\n        }\n    }\n    return in;\n}\n\nint eval_exact(const vector<Pt>& poly, const vector<Fish>& fish) {\n    int s = 0;\n    for (auto &f : fish) {\n        if (inside_poly(poly, f.x, f.y)) s += f.t;\n    }\n    return s;\n}\n\nbool legal_basic(const vector<Pt>& p) {\n    if ((int)p.size() < 4 || (int)p.size() > 1000) return false;\n    if (perimeter_poly(p) > 400000) return false;\n\n    set<pair<int,int>> st;\n    for (auto &v : p) {\n        if (v.x < 0 || v.x > LIM || v.y < 0 || v.y > LIM) return false;\n        if (!st.insert({v.x, v.y}).second) return false;\n    }\n\n    for (int i = 0; i < (int)p.size(); i++) {\n        Pt a = p[i], b = p[(i + 1) % p.size()];\n        if (!(a.x == b.x || a.y == b.y)) return false;\n    }\n\n    return true;\n}\n\nvector<Pt> rect_poly(int x1, int y1, int x2, int y2) {\n    x1 = max(0, min(LIM, x1));\n    x2 = max(0, min(LIM, x2));\n    y1 = max(0, min(LIM, y1));\n    y2 = max(0, min(LIM, y2));\n    if (x1 > x2) swap(x1,x2);\n    if (y1 > y2) swap(y1,y2);\n    if (x1 == x2) x2 = min(LIM, x1 + 1);\n    if (y1 == y2) y2 = min(LIM, y1 + 1);\n    return {{x1,y1},{x2,y1},{x2,y2},{x1,y2}};\n}\n\nstruct CandComp {\n    int score = 0;\n    int per = 0;\n    int minx = 1e9, maxx = -1;\n    int miny = 1e9, maxy = -1;\n    vector<pair<int,int>> cells;\n};\n\npair<int,int> comp_center(const CandComp& c) {\n    long long sx = 0, sy = 0;\n    for (auto [x,y] : c.cells) {\n        sx += x;\n        sy += y;\n    }\n    if (c.cells.empty()) return {0,0};\n    return {(int)(sx / c.cells.size()), (int)(sy / c.cells.size())};\n}\n\nvector<CandComp> find_components(const vector<vector<unsigned char>>& sel,\n                                const vector<vector<int>>& diff) {\n    int W = sel.size(), H = sel[0].size();\n    vector<vector<unsigned char>> vis(W, vector<unsigned char>(H, 0));\n    vector<CandComp> comps;\n    int dx[4] = {1,-1,0,0};\n    int dy[4] = {0,0,1,-1};\n\n    for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n        if (!sel[i][j] || vis[i][j]) continue;\n\n        CandComp cc;\n        queue<pair<int,int>> q;\n        q.push({i,j});\n        vis[i][j] = 1;\n\n        while (!q.empty()) {\n            auto [x,y] = q.front();\n            q.pop();\n\n            cc.cells.push_back({x,y});\n            cc.score += diff[x][y];\n            cc.minx = min(cc.minx, x);\n            cc.maxx = max(cc.maxx, x);\n            cc.miny = min(cc.miny, y);\n            cc.maxy = max(cc.maxy, y);\n\n            for (int d = 0; d < 4; d++) {\n                int nx = x + dx[d], ny = y + dy[d];\n                if (nx < 0 || nx >= W || ny < 0 || ny >= H || !sel[nx][ny]) {\n                    cc.per++;\n                } else if (!vis[nx][ny]) {\n                    vis[nx][ny] = 1;\n                    q.push({nx,ny});\n                }\n            }\n        }\n\n        comps.push_back(move(cc));\n    }\n\n    sort(comps.begin(), comps.end(), [](const CandComp& a, const CandComp& b) {\n        return a.score > b.score;\n    });\n\n    return comps;\n}\n\nvector<Pt> boundary_from_selected(const vector<vector<unsigned char>>& occ, int G) {\n    int W = occ.size(), H = occ[0].size();\n\n    map<pair<int,int>, vector<pair<int,int>>> adj;\n\n    auto add = [&](int x1, int y1, int x2, int y2) {\n        adj[{x1,y1}].push_back({x2,y2});\n    };\n\n    for (int i = 0; i < W; i++) for (int j = 0; j < H; j++) {\n        if (!occ[i][j]) continue;\n\n        int x0 = i * G, x1 = min(LIM, (i + 1) * G);\n        int y0 = j * G, y1 = min(LIM, (j + 1) * G);\n\n        if (j == 0 || !occ[i][j - 1]) add(x0, y0, x1, y0);\n        if (i == W - 1 || !occ[i + 1][j]) add(x1, y0, x1, y1);\n        if (j == H - 1 || !occ[i][j + 1]) add(x1, y1, x0, y1);\n        if (i == 0 || !occ[i - 1][j]) add(x0, y1, x0, y0);\n    }\n\n    if (adj.empty()) return {};\n\n    pair<int,int> start = adj.begin()->first;\n    for (auto &kv : adj) {\n        if (kv.first.second < start.second ||\n            (kv.first.second == start.second && kv.first.first < start.first)) {\n            start = kv.first;\n        }\n    }\n\n    vector<Pt> poly;\n    pair<int,int> cur = start, prev = {-1,-1};\n\n    for (int iter = 0; iter < 30000; iter++) {\n        poly.push_back({cur.first, cur.second});\n\n        auto it = adj.find(cur);\n        if (it == adj.end() || it->second.empty()) break;\n\n        auto &v = it->second;\n        pair<int,int> nxt = v[0];\n        if (v.size() >= 2 && v[0] == prev) nxt = v[1];\n\n        for (int k = 0; k < (int)v.size(); k++) {\n            if (v[k] == nxt) {\n                v.erase(v.begin() + k);\n                break;\n            }\n        }\n\n        prev = cur;\n        cur = nxt;\n        if (cur == start) break;\n    }\n\n    return simplify_poly(poly);\n}\n\nvector<Pt> boundary_from_cells(const vector<pair<int,int>>& cells, int G, int W, int H) {\n    vector<vector<unsigned char>> occ(W, vector<unsigned char>(H, 0));\n    for (auto [i,j] : cells) occ[i][j] = 1;\n    return boundary_from_selected(occ, G);\n}\n\nint grid_perimeter(const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int per = 0;\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        if (i==0 || !occ[i-1][j]) per++;\n        if (i==W-1 || !occ[i+1][j]) per++;\n        if (j==0 || !occ[i][j-1]) per++;\n        if (j==H-1 || !occ[i][j+1]) per++;\n    }\n\n    return per;\n}\n\nvoid connect_point(vector<vector<unsigned char>>& occ, pair<int,int> a, pair<int,int> b) {\n    int W = occ.size(), H = occ[0].size();\n    int x = max(0, min(W-1, a.first));\n    int y = max(0, min(H-1, a.second));\n    int tx = max(0, min(W-1, b.first));\n    int ty = max(0, min(H-1, b.second));\n\n    while (x != tx) {\n        occ[x][y] = 1;\n        x += (tx > x ? 1 : -1);\n    }\n    while (y != ty) {\n        occ[x][y] = 1;\n        y += (ty > y ? 1 : -1);\n    }\n    occ[x][y] = 1;\n}\n\nvoid add_component(vector<vector<unsigned char>>& occ, const CandComp& c) {\n    for (auto [x,y] : c.cells) occ[x][y] = 1;\n}\n\nvoid prune_leaves(vector<vector<unsigned char>>& occ, const vector<vector<int>>& diff) {\n    int W = occ.size(), H = occ[0].size();\n    queue<pair<int,int>> q;\n\n    auto deg = [&](int x, int y) {\n        int d = 0;\n        if (x > 0 && occ[x-1][y]) d++;\n        if (x+1 < W && occ[x+1][y]) d++;\n        if (y > 0 && occ[x][y-1]) d++;\n        if (y+1 < H && occ[x][y+1]) d++;\n        return d;\n    };\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n        if (occ[i][j] && diff[i][j] <= 0 && deg(i,j) <= 1) q.push({i,j});\n    }\n\n    while (!q.empty()) {\n        auto [x,y] = q.front();\n        q.pop();\n        if (!occ[x][y] || diff[x][y] > 0 || deg(x,y) > 1) continue;\n        occ[x][y] = 0;\n\n        int dx[4] = {1,-1,0,0};\n        int dy[4] = {0,0,1,-1};\n\n        for (int d=0; d<4; d++) {\n            int nx=x+dx[d], ny=y+dy[d];\n            if (nx>=0 && nx<W && ny>=0 && ny<H &&\n                occ[nx][ny] && diff[nx][ny] <= 0 && deg(nx,ny) <= 1) {\n                q.push({nx,ny});\n            }\n        }\n    }\n}\n\nint manhattan_comp_to_occ(const CandComp& c, const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int best = 1e9;\n    auto cen = comp_center(c);\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        best = min(best, abs(cen.first - i) + abs(cen.second - j));\n    }\n\n    return best;\n}\n\npair<int,int> nearest_occ_cell(pair<int,int> p, const vector<vector<unsigned char>>& occ) {\n    int W = occ.size(), H = occ[0].size();\n    int best = 1e9;\n    pair<int,int> bp = p;\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) if (occ[i][j]) {\n        int d = abs(p.first-i) + abs(p.second-j);\n        if (d < best) {\n            best = d;\n            bp = {i,j};\n        }\n    }\n\n    return bp;\n}\n\nvector<vector<double>> smooth_grid1(const vector<vector<int>>& diff) {\n    int W = diff.size(), H = diff[0].size();\n    vector<vector<double>> sm(W, vector<double>(H, 0.0));\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n        double s = 0, w = 0;\n        for (int dx=-1; dx<=1; dx++) for (int dy=-1; dy<=1; dy++) {\n            int ni=i+dx, nj=j+dy;\n            if (ni<0 || ni>=W || nj<0 || nj>=H) continue;\n            double ww = (dx==0 && dy==0 ? 4.0 : (dx==0 || dy==0 ? 2.0 : 1.0));\n            s += ww * diff[ni][nj];\n            w += ww;\n        }\n        sm[i][j] = s / w;\n    }\n\n    return sm;\n}\n\nvector<vector<double>> smooth_grid2(const vector<vector<int>>& diff) {\n    int W = diff.size(), H = diff[0].size();\n    vector<vector<double>> sm(W, vector<double>(H, 0.0));\n\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n        double s = 0, w = 0;\n        for (int dx=-2; dx<=2; dx++) for (int dy=-2; dy<=2; dy++) {\n            if (abs(dx) + abs(dy) > 2) continue;\n            int ni=i+dx, nj=j+dy;\n            if (ni<0 || ni>=W || nj<0 || nj>=H) continue;\n            double ww = 3 - abs(dx) - abs(dy);\n            s += ww * diff[ni][nj];\n            w += ww;\n        }\n        sm[i][j] = s / w;\n    }\n\n    return sm;\n}\n\nstruct RectCand {\n    int score, x1, y1, x2, y2;\n    bool operator>(const RectCand& o) const {\n        return score > o.score;\n    }\n};\n\nvoid try_rectangles_2000(const vector<Fish>& fish, vector<Pt>& best, int& bestScore) {\n    const int G = 2000;\n    int W = (LIM + G) / G;\n    int H = (LIM + G) / G;\n    vector<vector<int>> a(W, vector<int>(H, 0));\n\n    for (auto &f : fish) {\n        a[min(W-1, f.x/G)][min(H-1, f.y/G)] += f.t;\n    }\n\n    vector<vector<int>> ps(W+1, vector<int>(H+1, 0));\n    for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n        ps[i+1][j+1] = ps[i+1][j] + ps[i][j+1] - ps[i][j] + a[i][j];\n    }\n\n    auto sum_rect = [&](int x1,int y1,int x2,int y2) {\n        return ps[x2][y2] - ps[x1][y2] - ps[x2][y1] + ps[x1][y1];\n    };\n\n    priority_queue<RectCand, vector<RectCand>, greater<RectCand>> pq;\n    const int KEEP = 120;\n\n    for (int x1=0;x1<W;x1++) for (int x2=x1+1;x2<=W;x2++) {\n        int width = (x2 - x1) * G;\n        if (2 * width > 400000) continue;\n        int maxh = 400000 / 2 - width;\n        int maxCellsH = maxh / G;\n        if (maxCellsH <= 0) continue;\n\n        for (int y1=0;y1<H;y1++) {\n            int yMax = min(H, y1 + maxCellsH);\n            for (int y2=y1+1;y2<=yMax;y2++) {\n                int s = sum_rect(x1,y1,x2,y2);\n                if (s <= 0) continue;\n                RectCand rc{s,x1,y1,x2,y2};\n                if ((int)pq.size() < KEEP) pq.push(rc);\n                else if (s > pq.top().score) {\n                    pq.pop();\n                    pq.push(rc);\n                }\n            }\n        }\n    }\n\n    vector<RectCand> cand;\n    while (!pq.empty()) {\n        cand.push_back(pq.top());\n        pq.pop();\n    }\n\n    sort(cand.begin(), cand.end(), [](const RectCand& a, const RectCand& b) {\n        return a.score > b.score;\n    });\n\n    for (auto &rc : cand) {\n        vector<Pt> p = rect_poly(rc.x1*G, rc.y1*G, min(LIM, rc.x2*G), min(LIM, rc.y2*G));\n        if (!legal_basic(p)) continue;\n\n        int sc = eval_exact(p, fish);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = p;\n        }\n    }\n}\n\nvoid try_component_rectangles(const vector<Fish>& fish,\n                              const vector<CandComp>& comps,\n                              int G, int W, int H,\n                              vector<Pt>& best, int& bestScore,\n                              int& rectEval, int rectEvalLimit) {\n    int K = min(8, (int)comps.size());\n    if (K == 0) return;\n\n    int mnx = 1e9, mny = 1e9, mxx = -1, mxy = -1;\n\n    for (int k=0; k<K; k++) {\n        if (comps[k].score <= 0) break;\n\n        mnx = min(mnx, comps[k].minx);\n        mny = min(mny, comps[k].miny);\n        mxx = max(mxx, comps[k].maxx);\n        mxy = max(mxy, comps[k].maxy);\n\n        for (int pad : {0,1,2}) {\n            if (rectEval >= rectEvalLimit) return;\n\n            int x1c = max(0, mnx - pad);\n            int y1c = max(0, mny - pad);\n            int x2c = min(W, mxx + 1 + pad);\n            int y2c = min(H, mxy + 1 + pad);\n\n            int x1 = x1c * G;\n            int y1 = y1c * G;\n            int x2 = min(LIM, x2c * G);\n            int y2 = min(LIM, y2c * G);\n\n            if (2LL * ((x2 - x1) + (y2 - y1)) > 400000) continue;\n\n            vector<Pt> p = rect_poly(x1,y1,x2,y2);\n            if (!legal_basic(p)) continue;\n\n            int sc = eval_exact(p, fish);\n            rectEval++;\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                best = p;\n            }\n        }\n    }\n}\n\nvoid process_grid(const vector<Fish>& fish, int G, const vector<double>& thresholds,\n                  bool radius2, int& exactEvalCount, int maxEval,\n                  vector<Pt>& best, int& bestScore,\n                  bool extraMode, const Timer* timer=nullptr,\n                  int* componentRectEval=nullptr) {\n    int W = (LIM + G) / G;\n    int H = (LIM + G) / G;\n\n    vector<vector<int>> diff(W, vector<int>(H, 0));\n    for (auto &f : fish) {\n        int ix = min(W - 1, f.x / G);\n        int iy = min(H - 1, f.y / G);\n        diff[ix][iy] += f.t;\n    }\n\n    vector<vector<double>> sm = radius2 ? smooth_grid2(diff) : smooth_grid1(diff);\n\n    for (double th : thresholds) {\n        if (timer && timer->sec() > 1.88) break;\n\n        vector<vector<unsigned char>> sel(W, vector<unsigned char>(H, 0));\n        for (int i=0;i<W;i++) for (int j=0;j<H;j++) {\n            if (sm[i][j] > th) sel[i][j] = 1;\n        }\n\n        auto comps = find_components(sel, diff);\n\n        if (!extraMode && componentRectEval && *componentRectEval < 40) {\n            try_component_rectangles(fish, comps, G, W, H, best, bestScore, *componentRectEval, 40);\n        }\n\n        int checked = 0;\n        int singleLimit = extraMode ? 2 : 4;\n\n        for (auto &cc : comps) {\n            if (cc.score <= 0) break;\n            if (checked >= singleLimit) break;\n            checked++;\n\n            if (1LL * cc.per * G > 400000) continue;\n            if ((int)cc.cells.size() > 3500) continue;\n\n            vector<Pt> poly = boundary_from_cells(cc.cells, G, W, H);\n            poly = simplify_poly(poly);\n            if (!legal_basic(poly)) continue;\n\n            if (cc.score + 50 < bestScore) continue;\n\n            int sc = eval_exact(poly, fish);\n            exactEvalCount++;\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                best = poly;\n            }\n\n            if (exactEvalCount >= maxEval) break;\n        }\n\n        if (exactEvalCount >= maxEval) break;\n\n        int K = min(12, (int)comps.size());\n        vector<int> usable;\n        for (int i=0;i<K;i++) {\n            if (comps[i].score > 0) usable.push_back(i);\n        }\n\n        vector<double> penalties = extraMode ? vector<double>{0.7, 1.3} : vector<double>{0.0, 0.6, 1.0, 1.5, 2.2};\n        int startVariants = extraMode ? min(2, (int)usable.size()) : 1;\n\n        for (int sv=0; sv<startVariants; sv++) {\n            for (double pen : penalties) {\n                if (timer && timer->sec() > 1.88) break;\n                if (usable.empty()) continue;\n\n                vector<vector<unsigned char>> occ(W, vector<unsigned char>(H, 0));\n                vector<unsigned char> used(comps.size(), 0);\n\n                int start = usable[sv];\n                add_component(occ, comps[start]);\n                used[start] = 1;\n\n                int maxStep = extraMode ? 4 : 6;\n\n                for (int step=1; step<=maxStep; step++) {\n                    if (timer && timer->sec() > 1.88) break;\n\n                    int bestId = -1;\n                    double bestGain = -1e100;\n\n                    for (int id : usable) if (!used[id]) {\n                        int d = manhattan_comp_to_occ(comps[id], occ);\n                        double gain = comps[id].score - pen * d;\n                        if (gain > bestGain) {\n                            bestGain = gain;\n                            bestId = id;\n                        }\n                    }\n\n                    if (bestId == -1) break;\n                    if (bestGain < -5.0 && step >= 2) break;\n\n                    auto ccen = comp_center(comps[bestId]);\n                    auto nearp = nearest_occ_cell(ccen, occ);\n                    connect_point(occ, nearp, ccen);\n                    add_component(occ, comps[bestId]);\n                    used[bestId] = 1;\n\n                    prune_leaves(occ, diff);\n\n                    int gper = grid_perimeter(occ);\n                    if (1LL * gper * G > 400000) continue;\n\n                    vector<Pt> poly = boundary_from_selected(occ, G);\n                    poly = simplify_poly(poly);\n\n                    if (!legal_basic(poly)) continue;\n\n                    int sc = eval_exact(poly, fish);\n                    exactEvalCount++;\n\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = poly;\n                    }\n\n                    if (exactEvalCount >= maxEval) break;\n                }\n\n                if (exactEvalCount >= maxEval) break;\n            }\n\n            if (exactEvalCount >= maxEval) break;\n        }\n\n        if (exactEvalCount >= maxEval) break;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int n;\n    cin >> n;\n\n    vector<Fish> fish;\n    fish.reserve(2 * n);\n\n    for (int i = 0; i < 2 * n; i++) {\n        int x, y;\n        cin >> x >> y;\n        fish.push_back({x, y, i < n ? 1 : -1});\n    }\n\n    vector<Pt> best = rect_poly(0,0,1,1);\n    int bestScore = eval_exact(best, fish);\n\n    int exactEvalCount = 0;\n    int componentRectEval = 0;\n    const int MAIN_MAX_EVAL = 95;\n\n    vector<int> gridSizes = {700, 850, 1000, 1250, 1600, 2000};\n    vector<double> thresholds = {-0.25, -0.10, 0.0, 0.20, 0.45, 0.75};\n\n    for (int G : gridSizes) {\n        process_grid(fish, G, thresholds, false, exactEvalCount, MAIN_MAX_EVAL,\n                     best, bestScore, false, nullptr, &componentRectEval);\n        if (exactEvalCount >= MAIN_MAX_EVAL) break;\n    }\n\n    if (timer.sec() < 1.55) {\n        int extraEval = 0;\n        vector<double> th2 = {0.0, 0.25, 0.5};\n        process_grid(fish, 1000, th2, true, extraEval, 18, best, bestScore, true, &timer);\n        if (timer.sec() < 1.75) {\n            process_grid(fish, 1600, th2, true, extraEval, 28, best, bestScore, true, &timer);\n        }\n    }\n\n    if (timer.sec() < 1.82) {\n        try_rectangles_2000(fish, best, bestScore);\n    }\n\n    best = simplify_poly(best);\n    if (!legal_basic(best)) {\n        best = rect_poly(0,0,1,1);\n    }\n\n    cout << best.size() << '\\n';\n    for (auto &p : best) {\n        cout << p.x << \" \" << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct Rect {\n    long long w, h;\n};\n\nstruct Op {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Placed {\n    long long x1, y1, x2, y2;\n};\n\nstruct Cand {\n    long long score;\n    vector<Op> ops;\n};\n\nstruct LocalChoice {\n    long double val;\n    Op op;\n    Placed p;\n};\n\nstatic inline bool overlap1d(long long l1, long long r1, long long l2, long long r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nlong long simulate_score(const vector<Op>& ops, const vector<Rect>& rects) {\n    int N = rects.size();\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n\n    long long W = 0, H = 0;\n\n    for (auto &op : ops) {\n        int i = op.p;\n        long long w = rects[i].w;\n        long long h = rects[i].h;\n        if (op.r) swap(w, h);\n\n        long long x = 0, y = 0;\n\n        if (op.d == 'U') {\n            x = (op.b == -1 ? 0 : pos[op.b].x2);\n            y = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(x, x + w, pos[j].x1, pos[j].x2)) {\n                    y = max(y, pos[j].y2);\n                }\n            }\n        } else {\n            y = (op.b == -1 ? 0 : pos[op.b].y2);\n            x = 0;\n            for (int j = 0; j < N; j++) if (used[j]) {\n                if (overlap1d(y, y + h, pos[j].y1, pos[j].y2)) {\n                    x = max(x, pos[j].x2);\n                }\n            }\n        }\n\n        pos[i] = {x, y, x + w, y + h};\n        used[i] = 1;\n        W = max(W, x + w);\n        H = max(H, y + h);\n    }\n\n    long long penalty = 0;\n    for (int i = 0; i < N; i++) if (!used[i]) {\n        penalty += rects[i].w + rects[i].h;\n    }\n\n    return W + H + penalty;\n}\n\nvector<int> make_rotation_policy(const vector<Rect>& a, int mode, int seed) {\n    int N = a.size();\n    vector<int> r(N, 0);\n\n    for (int i = 0; i < N; i++) {\n        long long w = a[i].w, h = a[i].h;\n\n        if (mode == 0) r[i] = 0;\n        else if (mode == 1) r[i] = (w > h);\n        else if (mode == 2) r[i] = (w < h);\n        else if (mode == 3) r[i] = ((i + seed) & 1);\n        else if (mode == 4) r[i] = ((i / 2 + seed) & 1);\n        else if (mode == 5) {\n            uint32_t x = (uint32_t)(i * 1103515245u + seed * 12345u + 998244353u);\n            r[i] = (x >> 30) & 1;\n        } else {\n            r[i] = ((i / 3 + seed) & 1);\n        }\n    }\n\n    return r;\n}\n\nPlaced calc_place(const vector<Placed>& pos, const vector<int>& used, const vector<Rect>& a,\n                  int i, int rot, char d, int b) {\n    int N = a.size();\n    long long w = a[i].w;\n    long long h = a[i].h;\n    if (rot) swap(w, h);\n\n    long long x = 0, y = 0;\n    if (d == 'U') {\n        x = (b == -1 ? 0 : pos[b].x2);\n        y = 0;\n        for (int j = 0; j < N; j++) if (used[j]) {\n            if (overlap1d(x, x + w, pos[j].x1, pos[j].x2)) {\n                y = max(y, pos[j].y2);\n            }\n        }\n    } else {\n        y = (b == -1 ? 0 : pos[b].y2);\n        x = 0;\n        for (int j = 0; j < N; j++) if (used[j]) {\n            if (overlap1d(y, y + h, pos[j].y1, pos[j].y2)) {\n                x = max(x, pos[j].x2);\n            }\n        }\n    }\n    return {x, y, x + w, y + h};\n}\n\nlong double eval_ld(long long W, long long H, long double placedArea, int mode) {\n    long double per = (long double)W + H;\n    long double balance = fabsl((long double)W - H);\n    long double boxArea = max((long double)1.0, (long double)W * (long double)H);\n    long double waste = max((long double)0.0, boxArea - placedArea);\n\n    if (mode == 0) return per;\n    if (mode == 1) return per + 0.25L * balance;\n    if (mode == 2) return max((long double)W, (long double)H) * 2.0L + min((long double)W, (long double)H);\n    if (mode == 3) return per + 0.0000010L * boxArea;\n    if (mode == 4) return per + 0.50L * balance;\n    if (mode == 5) return per + 0.0000006L * boxArea;\n    if (mode == 6) return per + 0.0000015L * waste;\n    if (mode == 7) return per + 0.15L * balance + 0.0000008L * waste;\n    if (mode == 8) return 1.20L * W + 0.90L * H;\n    if (mode == 9) return 0.90L * W + 1.20L * H;\n    if (mode == 10) return per + 0.35L * W;\n    if (mode == 11) return per + 0.35L * H;\n    return per;\n}\n\nvector<int> build_anchors(int i, int style) {\n    vector<int> anchors;\n    anchors.push_back(-1);\n\n    if (style == 0) {\n        for (int b = 0; b < i; b++) anchors.push_back(b);\n    } else if (style == 1) {\n        for (int b = max(0, i - 20); b < i; b++) anchors.push_back(b);\n        for (int b = 0; b < i; b += 8) anchors.push_back(b);\n    } else if (style == 2) {\n        for (int b = max(0, i - 10); b < i; b++) anchors.push_back(b);\n        for (int b = 0; b < i; b += 5) anchors.push_back(b);\n    } else {\n        for (int b = max(0, i - 30); b < i; b++) anchors.push_back(b);\n        for (int b = 0; b < i; b += 11) anchors.push_back(b);\n    }\n\n    sort(anchors.begin(), anchors.end());\n    anchors.erase(unique(anchors.begin(), anchors.end()), anchors.end());\n    return anchors;\n}\n\nvector<Op> make_vertical_shelves(const vector<Rect>& a, const vector<int>& r, long double targetH, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int last_col_first = -1;\n    int prev = -1;\n    long double curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newCol = false;\n\n        if (i == 0) {\n            newCol = true;\n        } else {\n            long double projected = curH + hh[i];\n            if (projected > targetH) {\n                long double before = fabsl(targetH - curH);\n                long double after = fabsl(targetH - projected);\n\n                if (variant == 0) newCol = true;\n                else if (variant == 1) newCol = after > before * 0.85L;\n                else if (variant == 2) newCol = after > before * 0.65L;\n                else newCol = after > before;\n            }\n        }\n\n        if (newCol) {\n            if (last_col_first == -1) ops.push_back({i, r[i], 'U', -1});\n            else ops.push_back({i, r[i], 'U', last_col_first});\n            last_col_first = i;\n            curH = hh[i];\n        } else {\n            ops.push_back({i, r[i], 'L', prev});\n            curH += hh[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\nvector<Op> make_horizontal_shelves(const vector<Rect>& a, const vector<int>& r, long double targetW, int variant) {\n    int N = a.size();\n    vector<long long> ww(N), hh(N);\n    for (int i = 0; i < N; i++) {\n        ww[i] = a[i].w;\n        hh[i] = a[i].h;\n        if (r[i]) swap(ww[i], hh[i]);\n    }\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    int first_row = -1;\n    int prev = -1;\n    long double curW = 0;\n\n    for (int i = 0; i < N; i++) {\n        bool newRow = false;\n\n        if (i == 0) {\n            newRow = true;\n        } else {\n            long double projected = curW + ww[i];\n            if (projected > targetW) {\n                long double before = fabsl(targetW - curW);\n                long double after = fabsl(targetW - projected);\n\n                if (variant == 0) newRow = true;\n                else if (variant == 1) newRow = after > before * 0.85L;\n                else if (variant == 2) newRow = after > before * 0.65L;\n                else newRow = after > before;\n            }\n        }\n\n        if (newRow) {\n            if (first_row == -1) ops.push_back({i, r[i], 'L', -1});\n            else ops.push_back({i, r[i], 'L', first_row});\n            first_row = i;\n            curW = ww[i];\n        } else {\n            ops.push_back({i, r[i], 'U', prev});\n            curW += ww[i];\n        }\n\n        prev = i;\n    }\n\n    return ops;\n}\n\nvector<Op> make_greedy_anchor_layout(const vector<Rect>& a, const vector<int>& r, int mode) {\n    int N = a.size();\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long double bestVal = 1e100;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n        for (int b = 0; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            Placed p = calc_place(pos, used, a, i, r[i], d, b);\n            long long nW = max(curW, p.x2);\n            long long nH = max(curH, p.y2);\n\n            long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n            val = val * 1000000.0L + p.x1 + p.y1;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = p;\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n        placedArea += (long double)wi * hi;\n    }\n\n    return ops;\n}\n\nvector<Op> make_free_rotation_greedy_layout(const vector<Rect>& a, int mode, int anchorStyle, int dirBias) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    for (int i = 0; i < N; i++) {\n        Op bestOp{i, 0, 'U', -1};\n        Placed bestP{0, 0, a[i].w, a[i].h};\n        long double bestVal = 1e100;\n\n        vector<int> anchors = build_anchors(i, anchorStyle);\n\n        for (int rot = 0; rot < 2; rot++) {\n            long long wi = a[i].w, hi = a[i].h;\n            if (rot) swap(wi, hi);\n\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n\n                    if (dirBias == 1 && d == 'U') val *= 0.985L;\n                    if (dirBias == 2 && d == 'L') val *= 0.985L;\n                    if (dirBias == 3) val += 0.08L * p.x1;\n                    if (dirBias == 4) val += 0.08L * p.y1;\n\n                    val = val * 1000000.0L + p.x1 + p.y1;\n\n                    if (val < bestVal) {\n                        bestVal = val;\n                        bestOp = {i, rot, d, b};\n                        bestP = p;\n                    }\n                }\n            }\n        }\n\n        long long bw = a[i].w, bh = a[i].h;\n        if (bestOp.r) swap(bw, bh);\n        placedArea += (long double)bw * bh;\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_target_aspect_free_greedy(const vector<Rect>& a, long double targetAspect, int anchorStyle) {\n    int N = a.size();\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        Op bestOp{i, 0, 'U', -1};\n        Placed bestP{0, 0, a[i].w, a[i].h};\n        long double bestVal = 1e100;\n\n        vector<int> anchors = build_anchors(i, anchorStyle);\n\n        for (int rot = 0; rot < 2; rot++) {\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double aspectPenalty = fabsl((long double)nW - targetAspect * (long double)nH);\n                    long double val = (long double)nW + nH + 0.22L * aspectPenalty;\n                    val = val * 1000000.0L + p.x1 + p.y1;\n\n                    if (val < bestVal) {\n                        bestVal = val;\n                        bestOp = {i, rot, d, b};\n                        bestP = p;\n                    }\n                }\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_topk_free_rotation_greedy(const vector<Rect>& a, int mode, int anchorStyle, int seed) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    uint32_t rng = 123456789u + seed * 1000003u;\n\n    auto next_rand = [&]() {\n        rng ^= rng << 13;\n        rng ^= rng >> 17;\n        rng ^= rng << 5;\n        return rng;\n    };\n\n    for (int i = 0; i < N; i++) {\n        vector<int> anchors = build_anchors(i, anchorStyle);\n\n        vector<LocalChoice> choices;\n        choices.reserve(anchors.size() * 4);\n\n        for (int rot = 0; rot < 2; rot++) {\n            long long wi = a[i].w, hi = a[i].h;\n            if (rot) swap(wi, hi);\n\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n\n                    long double perturb = 0;\n                    if (seed & 1) perturb += (long double)(p.x1 + p.y1) / 20.0L;\n                    if (seed & 2) perturb += (long double)llabs(nW - nH) / 10.0L;\n                    if (seed & 4) perturb -= (long double)min(p.x1, p.y1) / 30.0L;\n                    if (seed & 8) perturb += 0.0000003L * (long double)nW * nH;\n                    if (seed & 16) perturb += (d == 'U' ? -5000.0L : 5000.0L);\n                    if (seed & 32) perturb += (d == 'L' ? -5000.0L : 5000.0L);\n\n                    val = (val + perturb) * 1000000.0L + p.x1 + p.y1;\n\n                    choices.push_back({val, {i, rot, d, b}, p});\n                }\n            }\n        }\n\n        sort(choices.begin(), choices.end(), [](const LocalChoice& x, const LocalChoice& y) {\n            return x.val < y.val;\n        });\n\n        int topK = min((int)choices.size(), 1 + (seed % 4));\n        int pick = 0;\n        if (topK > 1 && i > 1) {\n            uint32_t rv = next_rand();\n            if ((rv & 7) == 0) pick = min(topK - 1, 2);\n            else if ((rv & 3) == 0) pick = min(topK - 1, 1);\n            else pick = 0;\n        }\n\n        auto ch = choices[pick];\n\n        long long bw = a[i].w, bh = a[i].h;\n        if (ch.op.r) swap(bw, bh);\n        placedArea += (long double)bw * bh;\n\n        ops.push_back(ch.op);\n        pos[i] = ch.p;\n        used[i] = 1;\n        curW = max(curW, ch.p.x2);\n        curH = max(curH, ch.p.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_forced_deviation_greedy(const vector<Rect>& a, int mode, int anchorStyle, int period, int offset, int pickRank) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    for (int i = 0; i < N; i++) {\n        vector<int> anchors = build_anchors(i, anchorStyle);\n\n        vector<LocalChoice> choices;\n        choices.reserve(anchors.size() * 4);\n\n        for (int rot = 0; rot < 2; rot++) {\n            long long wi = a[i].w, hi = a[i].h;\n            if (rot) swap(wi, hi);\n\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n                    val = val * 1000000.0L + p.x1 + p.y1;\n\n                    choices.push_back({val, {i, rot, d, b}, p});\n                }\n            }\n        }\n\n        sort(choices.begin(), choices.end(), [](const LocalChoice& x, const LocalChoice& y) {\n            return x.val < y.val;\n        });\n\n        int pick = 0;\n        if (i >= 2 && ((i + offset) % period == 0)) {\n            pick = min((int)choices.size() - 1, pickRank);\n        }\n        if (i < 8 && ((i + offset) % max(2, period / 2) == 0)) {\n            pick = min((int)choices.size() - 1, max(pick, 1));\n        }\n\n        auto ch = choices[pick];\n\n        long long bw = a[i].w, bh = a[i].h;\n        if (ch.op.r) swap(bw, bh);\n        placedArea += (long double)bw * bh;\n\n        ops.push_back(ch.op);\n        pos[i] = ch.p;\n        used[i] = 1;\n        curW = max(curW, ch.p.x2);\n        curH = max(curH, ch.p.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_early_deviation_greedy(const vector<Rect>& a, int mode, int anchorStyle, int pos1, int rank1, int pos2, int rank2) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    for (int i = 0; i < N; i++) {\n        vector<int> anchors = build_anchors(i, anchorStyle);\n\n        vector<LocalChoice> choices;\n        choices.reserve(anchors.size() * 4);\n\n        for (int rot = 0; rot < 2; rot++) {\n            long long wi = a[i].w, hi = a[i].h;\n            if (rot) swap(wi, hi);\n\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n                    val = val * 1000000.0L + p.x1 + p.y1;\n\n                    choices.push_back({val, {i, rot, d, b}, p});\n                }\n            }\n        }\n\n        sort(choices.begin(), choices.end(), [](const LocalChoice& x, const LocalChoice& y) {\n            return x.val < y.val;\n        });\n\n        int pick = 0;\n        if (i == pos1) pick = min((int)choices.size() - 1, rank1);\n        if (i == pos2) pick = min((int)choices.size() - 1, rank2);\n\n        auto ch = choices[pick];\n\n        long long bw = a[i].w, bh = a[i].h;\n        if (ch.op.r) swap(bw, bh);\n        placedArea += (long double)bw * bh;\n\n        ops.push_back(ch.op);\n        pos[i] = ch.p;\n        used[i] = 1;\n        curW = max(curW, ch.p.x2);\n        curH = max(curH, ch.p.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_single_early_deviation_greedy(const vector<Rect>& a, int mode, int anchorStyle, int posDev, int rankDev) {\n    int N = a.size();\n\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n    long double placedArea = 0;\n\n    for (int i = 0; i < N; i++) {\n        vector<int> anchors = build_anchors(i, anchorStyle);\n\n        vector<LocalChoice> choices;\n        choices.reserve(anchors.size() * 4);\n\n        for (int rot = 0; rot < 2; rot++) {\n            long long wi = a[i].w, hi = a[i].h;\n            if (rot) swap(wi, hi);\n\n            for (int b : anchors) {\n                for (char d : {'U', 'L'}) {\n                    Placed p = calc_place(pos, used, a, i, rot, d, b);\n                    long long nW = max(curW, p.x2);\n                    long long nH = max(curH, p.y2);\n\n                    long double val = eval_ld(nW, nH, placedArea + (long double)wi * hi, mode);\n                    val = val * 1000000.0L + p.x1 + p.y1;\n\n                    choices.push_back({val, {i, rot, d, b}, p});\n                }\n            }\n        }\n\n        sort(choices.begin(), choices.end(), [](const LocalChoice& x, const LocalChoice& y) {\n            return x.val < y.val;\n        });\n\n        int pick = 0;\n        if (i == posDev) pick = min((int)choices.size() - 1, rankDev);\n\n        auto ch = choices[pick];\n\n        long long bw = a[i].w, bh = a[i].h;\n        if (ch.op.r) swap(bw, bh);\n        placedArea += (long double)bw * bh;\n\n        ops.push_back(ch.op);\n        pos[i] = ch.p;\n        used[i] = 1;\n        curW = max(curW, ch.p.x2);\n        curH = max(curH, ch.p.y2);\n    }\n\n    return ops;\n}\n\nvector<Op> make_mixed_layout(const vector<Rect>& a, const vector<int>& r, int blockSize, int mode) {\n    int N = a.size();\n    vector<Op> ops;\n    ops.reserve(N);\n\n    vector<Placed> pos(N);\n    vector<int> used(N, 0);\n    long long curW = 0, curH = 0;\n\n    for (int i = 0; i < N; i++) {\n        long long wi = a[i].w, hi = a[i].h;\n        if (r[i]) swap(wi, hi);\n\n        Op bestOp{i, r[i], 'U', -1};\n        Placed bestP{0, 0, wi, hi};\n        long double bestVal = 1e100;\n\n        vector<pair<char,int>> tries;\n        tries.push_back({'U', -1});\n        tries.push_back({'L', -1});\n\n        int start = max(0, i - blockSize);\n        for (int b = start; b < i; b++) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (int b = 0; b < i; b += max(1, blockSize / 2)) if (used[b]) {\n            tries.push_back({'U', b});\n            tries.push_back({'L', b});\n        }\n\n        for (auto [d, b] : tries) {\n            Placed p = calc_place(pos, used, a, i, r[i], d, b);\n            long long nW = max(curW, p.x2);\n            long long nH = max(curH, p.y2);\n\n            long double val = eval_ld(nW, nH, 0, mode);\n            val = val * 1000000.0L + p.x1 + p.y1;\n\n            if (val < bestVal) {\n                bestVal = val;\n                bestOp = {i, r[i], d, b};\n                bestP = p;\n            }\n        }\n\n        ops.push_back(bestOp);\n        pos[i] = bestP;\n        used[i] = 1;\n        curW = max(curW, bestP.x2);\n        curH = max(curH, bestP.y2);\n    }\n\n    return ops;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, T;\n    long long sigma;\n    cin >> N >> T >> sigma;\n\n    vector<Rect> a(N);\n    for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n    long double area = 0;\n    for (auto &e : a) area += (long double)e.w * (long double)e.h;\n    long double root = sqrt(area);\n\n    vector<Cand> cands;\n    cands.reserve(15000);\n\n    auto add_candidate = [&](const vector<Op>& ops) {\n        long long sc = simulate_score(ops, a);\n        cands.push_back({sc, ops});\n    };\n\n    // Shelf candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 8; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n\n            for (int k = 0; k < 45; k++) {\n                long double factor = 0.45L + 0.035L * k;\n                for (int var = 0; var < 4; var++) {\n                    add_candidate(make_vertical_shelves(a, r, root * factor, var));\n                    add_candidate(make_horizontal_shelves(a, r, root * factor, var));\n                }\n            }\n        }\n    }\n\n    // Fixed-rotation greedy candidates.\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 12; seed++) {\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bm = 0; bm < 8; bm++) {\n                add_candidate(make_greedy_anchor_layout(a, r, bm));\n            }\n        }\n    }\n\n    // Free-rotation greedy candidates.\n    for (int bm = 0; bm < 12; bm++) {\n        for (int style = 0; style < 4; style++) {\n            add_candidate(make_free_rotation_greedy_layout(a, bm, style, 0));\n        }\n    }\n\n    // Direction-biased free-rotation candidates.\n    for (int bm = 0; bm < 8; bm++) {\n        for (int bias = 1; bias <= 4; bias++) {\n            add_candidate(make_free_rotation_greedy_layout(a, bm, 1 + (bias % 3), bias));\n        }\n    }\n\n    // Target-aspect free-rotation greedy.\n    vector<long double> aspects = {0.70L, 0.82L, 0.92L, 1.0L, 1.08L, 1.22L, 1.42L};\n    for (long double asp : aspects) {\n        for (int style = 0; style < 4; style++) {\n            add_candidate(make_target_aspect_free_greedy(a, asp, style));\n        }\n    }\n\n    // Top-k perturbed free-rotation greedy candidates.\n    for (int seed = 0; seed < 36; seed++) {\n        int bm = seed % 12;\n        int style = (seed / 2) % 4;\n        add_candidate(make_topk_free_rotation_greedy(a, bm, style, seed));\n    }\n\n    // Forced deviation candidates.\n    vector<int> periods = {4, 5, 7, 9, 11, 13};\n    for (int idx = 0; idx < 36; idx++) {\n        int period = periods[idx % periods.size()];\n        int offset = (idx / periods.size()) % period;\n        int mode = idx % 12;\n        int style = (idx / 2) % 4;\n        int rank = 1 + (idx % 3);\n        add_candidate(make_forced_deviation_greedy(a, mode, style, period, offset, rank));\n    }\n\n    // Two-position early-only deviation candidates.\n    for (int idx = 0; idx < 40; idx++) {\n        int mode = idx % 12;\n        int style = (idx / 3) % 4;\n        int p1 = 2 + (idx % 9);\n        int p2 = 5 + ((idx * 3) % 16);\n        if (p2 == p1) p2++;\n        int r1 = 1 + (idx % 3);\n        int r2 = 1 + ((idx / 2) % 3);\n        add_candidate(make_early_deviation_greedy(a, mode, style, p1, r1, p2, r2));\n    }\n\n    // Single early deviation candidates.\n    for (int idx = 0; idx < 36; idx++) {\n        int mode = idx % 12;\n        int style = (idx / 4) % 4;\n        int posDev;\n        if (idx < 18) posDev = 2 + (idx % 9);\n        else posDev = 8 + (idx % 13);\n        int rankDev = 1 + ((idx / 3) % 3);\n        add_candidate(make_single_early_deviation_greedy(a, mode, style, posDev, rankDev));\n    }\n\n    // Focused full-anchor early deviations.\n    for (int idx = 0; idx < 36; idx++) {\n        int mode = idx % 12;\n        int style = 0;\n        int posDev = 1 + (idx % 12);\n        int rankDev = 1 + ((idx / 12) % 3);\n        add_candidate(make_single_early_deviation_greedy(a, mode, style, posDev, rankDev));\n    }\n\n    for (int idx = 0; idx < 24; idx++) {\n        int mode = idx % 12;\n        int style = 0;\n        int p1 = 1 + (idx % 8);\n        int p2 = 4 + ((idx * 5) % 12);\n        if (p2 == p1) p2++;\n        int r1 = 1 + ((idx / 3) % 3);\n        int r2 = 1 + ((idx / 5) % 3);\n        add_candidate(make_early_deviation_greedy(a, mode, style, p1, r1, p2, r2));\n    }\n\n    // Mixed restricted-anchor candidates.\n    vector<int> blockSizes = {4, 6, 8, 10, 12, 15, 20, 30};\n    for (int mode = 0; mode < 7; mode++) {\n        for (int seed = 0; seed < 6; seed++) {\n            if (timer.elapsed() > 2.45) break;\n            vector<int> r = make_rotation_policy(a, mode, seed);\n            for (int bs : blockSizes) {\n                for (int bm = 0; bm < 4; bm++) {\n                    add_candidate(make_mixed_layout(a, r, bs, bm));\n                }\n            }\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [](const Cand& x, const Cand& y) {\n        return x.score < y.score;\n    });\n\n    vector<Cand> uniq;\n    uniq.reserve(cands.size());\n\n    auto signature = [](const vector<Op>& ops) {\n        string s;\n        s.reserve(ops.size() * 8);\n        for (auto &op : ops) {\n            s += char(op.r + '0');\n            s += op.d;\n            int b = op.b + 1;\n            s += char(33 + (b % 90));\n            s += char(33 + ((b / 90) % 90));\n            s += ',';\n        }\n        return s;\n    };\n\n    unordered_set<string> seen;\n    for (auto &c : cands) {\n        string sig = signature(c.ops);\n        if (seen.insert(sig).second) {\n            uniq.push_back(std::move(c));\n            if ((int)uniq.size() >= max(T * 4, 500)) break;\n        }\n    }\n\n    if (uniq.empty()) {\n        vector<int> r(N, 0);\n        vector<Op> ops = make_vertical_shelves(a, r, root, 0);\n        uniq.push_back({simulate_score(ops, a), ops});\n    }\n\n    for (int t = 0; t < T; t++) {\n        const vector<Op>& ops = uniq[t % uniq.size()].ops;\n\n        cout << ops.size() << '\\n';\n        for (auto &op : ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n\n        long long Wp, Hp;\n        cin >> Wp >> Hp;\n        if (!cin) return 0;\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>> g;\n    vector<pair<int,int>> xy;\n    vector<vector<int>> reach;\n\n    mt19937 rng;\n    chrono::steady_clock::time_point st;\n    const double TL = 1.94;\n\n    Solver() : rng(123456789) {}\n\n    double elapsed() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n\n    double rnd(double l, double r) {\n        return uniform_real_distribution<double>(l, r)(rng);\n    }\n\n    long long calcScore(const vector<int>& par) {\n        vector<vector<int>> ch(n);\n        vector<int> roots;\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -1) roots.push_back(v);\n            else ch[par[v]].push_back(v);\n        }\n\n        long long score = 1;\n        vector<int> dep(n, -1);\n        queue<int> q;\n\n        for (int r : roots) {\n            dep[r] = 0;\n            q.push(r);\n        }\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            score += 1LL * (dep[v] + 1) * A[v];\n\n            for (int to : ch[v]) {\n                dep[to] = dep[v] + 1;\n                q.push(to);\n            }\n        }\n\n        return score;\n    }\n\n    void precomputeReach() {\n        reach.assign(n, {});\n\n        for (int s = 0; s < n; s++) {\n            vector<int> d(n, -1);\n            queue<int> q;\n            d[s] = 0;\n            q.push(s);\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                reach[s].push_back(v);\n\n                if (d[v] == h) continue;\n\n                for (int to : g[v]) {\n                    if (d[to] == -1) {\n                        d[to] = d[v] + 1;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n    }\n\n    vector<int> bfsConstruct(double lowBias, double noise, bool randomOrder) {\n        vector<char> covered(n, 0), isRoot(n, 0);\n        vector<int> roots;\n        int coveredCnt = 0;\n\n        while (coveredCnt < n) {\n            int best = -1;\n            double bestVal = -1e100;\n\n            vector<int> cand(n);\n            iota(cand.begin(), cand.end(), 0);\n            if (randomOrder) shuffle(cand.begin(), cand.end(), rng);\n\n            for (int v : cand) {\n                if (isRoot[v]) continue;\n\n                int gain = 0;\n                int gainW = 0;\n\n                for (int u : reach[v]) {\n                    if (!covered[u]) {\n                        gain++;\n                        gainW += A[u];\n                    }\n                }\n\n                if (gain == 0) continue;\n\n                double val =\n                    gain * 1000.0\n                    - lowBias * A[v]\n                    + 0.04 * gainW\n                    + rnd(-noise, noise);\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = v;\n                }\n            }\n\n            if (best == -1) {\n                for (int v = 0; v < n; v++) {\n                    if (!covered[v]) {\n                        best = v;\n                        break;\n                    }\n                }\n            }\n\n            roots.push_back(best);\n            isRoot[best] = 1;\n\n            for (int u : reach[best]) {\n                if (!covered[u]) {\n                    covered[u] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        vector<int> dist(n, INT_MAX), par(n, -2);\n\n        struct Node {\n            double key;\n            int v;\n            bool operator<(const Node& other) const {\n                return key > other.key;\n            }\n        };\n\n        priority_queue<Node> pq;\n\n        for (int r : roots) {\n            dist[r] = 0;\n            par[r] = -1;\n            pq.push({0.003 * A[r], r});\n        }\n\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n\n            int v = cur.v;\n            if (dist[v] == h) continue;\n\n            vector<int> ns = g[v];\n            shuffle(ns.begin(), ns.end(), rng);\n\n            for (int to : ns) {\n                if (dist[to] == INT_MAX) {\n                    dist[to] = dist[v] + 1;\n                    par[to] = v;\n\n                    double key =\n                        dist[to]\n                        + 0.014 * (100 - A[to])\n                        + rnd(0.0, 0.04);\n\n                    pq.push({key, to});\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    int selectByTopK(vector<pair<double,int>>& scored, double topKProb) {\n        sort(scored.begin(), scored.end(), [](auto& x, auto& y) {\n            return x.first > y.first;\n        });\n\n        int sz = (int)scored.size();\n        if (sz == 1) return scored[0].second;\n\n        int rank = 0;\n\n        if (rnd(0.0, 1.0) < topKProb) {\n            int k = min(3, sz);\n            double r = rnd(0.0, 1.0);\n            if (k >= 3 && r < 0.20) rank = 2;\n            else if (k >= 2 && r < 0.55) rank = 1;\n            else rank = 0;\n        }\n\n        return scored[rank].second;\n    }\n\n    double lookaheadValue(int v, const vector<char>& used) {\n        int best1 = 0, best2 = 0;\n        for (int to : g[v]) {\n            if (used[to]) continue;\n            int val = A[to];\n            if (val > best1) {\n                best2 = best1;\n                best1 = val;\n            } else if (val > best2) {\n                best2 = val;\n            }\n        }\n        return best1 + 0.5 * best2;\n    }\n\n    vector<int> deepDfsConstruct(\n        double rootBias,\n        double childBias,\n        double randomness,\n        double branchProb,\n        double topKProb,\n        double lookAheadCoef\n    ) {\n        vector<int> par(n, -2), dep(n, -1);\n        vector<char> used(n, 0);\n        int usedCnt = 0;\n\n        vector<pair<double,int>> key;\n        key.reserve(n);\n\n        for (int v = 0; v < n; v++) {\n            key.push_back({A[v] * rootBias + rnd(0.0, randomness), v});\n        }\n\n        sort(key.begin(), key.end());\n\n        vector<int> order;\n        order.reserve(n);\n        for (auto [_, v] : key) order.push_back(v);\n\n        int ptr = 0;\n\n        while (usedCnt < n) {\n            int root = -1;\n\n            while (ptr < n && used[order[ptr]]) ptr++;\n            if (ptr < n) root = order[ptr];\n\n            if (root == -1) {\n                for (int v = 0; v < n; v++) {\n                    if (!used[v]) {\n                        root = v;\n                        break;\n                    }\n                }\n            }\n\n            used[root] = 1;\n            usedCnt++;\n            par[root] = -1;\n            dep[root] = 0;\n\n            vector<int> stk;\n            stk.push_back(root);\n\n            while (!stk.empty()) {\n                int v = stk.back();\n\n                if (dep[v] >= h) {\n                    stk.pop_back();\n                    continue;\n                }\n\n                vector<pair<double,int>> scored;\n\n                for (int to : g[v]) {\n                    if (!used[to]) {\n                        int freeNei = 0;\n                        for (int w : g[to]) {\n                            if (!used[w]) freeNei++;\n                        }\n\n                        double la = lookaheadValue(to, used);\n\n                        double sc =\n                            childBias * A[to]\n                            + 4.0 * freeNei\n                            + 12.0 * dep[v]\n                            + lookAheadCoef * la\n                            + rnd(0.0, randomness);\n\n                        scored.push_back({sc, to});\n                    }\n                }\n\n                if (scored.empty()) {\n                    stk.pop_back();\n                    continue;\n                }\n\n                int best = selectByTopK(scored, topKProb);\n\n                used[best] = 1;\n                usedCnt++;\n                par[best] = v;\n                dep[best] = dep[v] + 1;\n                stk.push_back(best);\n\n                if (dep[v] + 1 <= h && rnd(0.0, 1.0) < branchProb) {\n                    vector<pair<double,int>> scored2;\n                    for (int to : g[v]) {\n                        if (!used[to]) {\n                            double sc =\n                                0.7 * childBias * A[to]\n                                + 0.5 * lookAheadCoef * lookaheadValue(to, used)\n                                + rnd(0.0, randomness);\n\n                            scored2.push_back({sc, to});\n                        }\n                    }\n\n                    if (!scored2.empty()) {\n                        int b2 = selectByTopK(scored2, topKProb * 0.7);\n\n                        used[b2] = 1;\n                        usedCnt++;\n                        par[b2] = v;\n                        dep[b2] = dep[v] + 1;\n                        stk.push_back(b2);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    vector<int> greedyLayerConstruct(double randomness) {\n        vector<int> par(n, -2), dep(n, -1);\n        vector<char> used(n, 0);\n        int usedCnt = 0;\n\n        while (usedCnt < n) {\n            int root = -1;\n            double bestRootScore = 1e100;\n\n            for (int v = 0; v < n; v++) {\n                if (used[v]) continue;\n\n                int un = 0;\n                for (int to : g[v]) {\n                    if (!used[to]) un++;\n                }\n\n                double sc =\n                    A[v] * 5.0\n                    - un * 8.0\n                    + rnd(0.0, randomness);\n\n                if (sc < bestRootScore) {\n                    bestRootScore = sc;\n                    root = v;\n                }\n            }\n\n            used[root] = 1;\n            usedCnt++;\n            par[root] = -1;\n            dep[root] = 0;\n\n            vector<int> frontier = {root};\n\n            for (int d = 0; d < h && !frontier.empty(); d++) {\n                vector<pair<double, pair<int,int>>> cand;\n\n                for (int v : frontier) {\n                    for (int to : g[v]) {\n                        if (!used[to]) {\n                            int un = 0;\n                            for (int w : g[to]) {\n                                if (!used[w]) un++;\n                            }\n\n                            double sc =\n                                A[to] * (1.0 + 0.25 * d)\n                                + 2.5 * un\n                                + rnd(0.0, randomness);\n\n                            cand.push_back({-sc, {v, to}});\n                        }\n                    }\n                }\n\n                if (cand.empty()) break;\n\n                sort(cand.begin(), cand.end());\n\n                vector<int> next;\n\n                for (auto &e : cand) {\n                    int p = e.second.first;\n                    int v = e.second.second;\n\n                    if (used[v]) continue;\n\n                    used[v] = 1;\n                    usedCnt++;\n                    par[v] = p;\n                    dep[v] = d + 1;\n                    next.push_back(v);\n                }\n\n                frontier.swap(next);\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (par[v] == -2) par[v] = -1;\n        }\n\n        return par;\n    }\n\n    pair<int, vector<int>> farthestInComponent(\n        int start,\n        const vector<vector<int>>& treeAdj\n    ) {\n        vector<int> d(n, -1);\n        queue<int> q;\n        d[start] = 0;\n        q.push(start);\n\n        int far = start;\n\n        while (!q.empty()) {\n            int v = q.front();\n            q.pop();\n\n            if (d[v] > d[far]) far = v;\n\n            for (int to : treeAdj[v]) {\n                if (d[to] == -1) {\n                    d[to] = d[v] + 1;\n                    q.push(to);\n                }\n            }\n        }\n\n        return {far, d};\n    }\n\n    vector<int> rerootTrees(const vector<int>& par0) {\n        vector<vector<int>> treeAdj(n);\n\n        for (int v = 0; v < n; v++) {\n            if (par0[v] != -1) {\n                treeAdj[v].push_back(par0[v]);\n                treeAdj[par0[v]].push_back(v);\n            }\n        }\n\n        vector<int> compId(n, -1);\n        vector<vector<int>> comps;\n\n        for (int s = 0; s < n; s++) {\n            if (compId[s] != -1) continue;\n\n            comps.push_back({});\n            int cid = (int)comps.size() - 1;\n\n            queue<int> q;\n            q.push(s);\n            compId[s] = cid;\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                comps.back().push_back(v);\n\n                for (int to : treeAdj[v]) {\n                    if (compId[to] == -1) {\n                        compId[to] = cid;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n\n        vector<int> newPar(n, -2);\n\n        vector<int> parent(n), order;\n        vector<long long> subW(n), dp(n);\n        vector<int> depth(n);\n\n        for (auto &comp : comps) {\n            int root0 = comp[0];\n            long long totalW = 0;\n            for (int v : comp) totalW += A[v];\n\n            order.clear();\n            queue<int> q;\n            fill(parent.begin(), parent.end(), -2);\n            fill(depth.begin(), depth.end(), -1);\n\n            parent[root0] = -1;\n            depth[root0] = 0;\n            q.push(root0);\n\n            while (!q.empty()) {\n                int v = q.front();\n                q.pop();\n\n                order.push_back(v);\n\n                for (int to : treeAdj[v]) {\n                    if (parent[to] == -2) {\n                        parent[to] = v;\n                        depth[to] = depth[v] + 1;\n                        q.push(to);\n                    }\n                }\n            }\n\n            long long rootDist = 0;\n            for (int v : comp) {\n                subW[v] = A[v];\n                rootDist += 1LL * depth[v] * A[v];\n            }\n\n            for (int i = (int)order.size() - 1; i >= 0; i--) {\n                int v = order[i];\n                for (int to : treeAdj[v]) {\n                    if (parent[to] == v) subW[v] += subW[to];\n                }\n            }\n\n            dp[root0] = rootDist;\n\n            for (int v : order) {\n                for (int to : treeAdj[v]) {\n                    if (parent[to] == v) {\n                        dp[to] = dp[v] + totalW - 2LL * subW[to];\n                    }\n                }\n            }\n\n            auto [s, d0] = farthestInComponent(root0, treeAdj);\n            auto [t, ds] = farthestInComponent(s, treeAdj);\n            auto [dummy, dt] = farthestInComponent(t, treeAdj);\n\n            int bestRoot = root0;\n            long long bestVal = LLONG_MIN;\n\n            for (int v : comp) {\n                int ecc = max(ds[v], dt[v]);\n                if (ecc <= h) {\n                    long long val = dp[v] + totalW;\n                    if (val > bestVal) {\n                        bestVal = val;\n                        bestRoot = v;\n                    }\n                }\n            }\n\n            queue<int> q2;\n            vector<char> seen(n, 0);\n\n            newPar[bestRoot] = -1;\n            seen[bestRoot] = 1;\n            q2.push(bestRoot);\n\n            while (!q2.empty()) {\n                int v = q2.front();\n                q2.pop();\n\n                for (int to : treeAdj[v]) {\n                    if (!seen[to]) {\n                        seen[to] = 1;\n                        newPar[to] = v;\n                        q2.push(to);\n                    }\n                }\n            }\n        }\n\n        for (int v = 0; v < n; v++) {\n            if (newPar[v] == -2) newPar[v] = -1;\n        }\n\n        return newPar;\n    }\n\n    void solve() {\n        cin >> n >> m >> h;\n\n        A.resize(n);\n        for (int i = 0; i < n; i++) cin >> A[i];\n\n        g.assign(n, {});\n        for (int i = 0; i < m; i++) {\n            int u, v;\n            cin >> u >> v;\n            g[u].push_back(v);\n            g[v].push_back(u);\n        }\n\n        xy.resize(n);\n        for (int i = 0; i < n; i++) {\n            cin >> xy[i].first >> xy[i].second;\n        }\n\n        st = chrono::steady_clock::now();\n\n        precomputeReach();\n\n        vector<int> bestPar(n, -1);\n        long long bestScore = -1;\n\n        int iter = 0;\n\n        while (elapsed() < TL) {\n            vector<int> par;\n\n            int mode = iter % 8;\n\n            if (mode == 0) {\n                double lowBias = 8.0 + (iter % 11) * 7.0;\n                double noise = 100.0 + (iter % 9) * 250.0;\n                par = bfsConstruct(lowBias, noise, iter & 1);\n            } else if (mode == 7) {\n                double randomness = 20.0 + (iter % 19) * 15.0;\n                par = greedyLayerConstruct(randomness);\n            } else {\n                double rootBias = 2.0 + (iter % 7);\n                double childBias = 8.0 + (iter % 13) * 2.0;\n                double randomness = 20.0 + (iter % 17) * 12.0;\n\n                double branchProb;\n                if (mode == 1 || mode == 2 || mode == 6) branchProb = 0.05;\n                else if (mode == 3 || mode == 4) branchProb = 0.15;\n                else branchProb = 0.25;\n\n                double topKProb;\n                if (mode == 1) topKProb = 0.10;\n                else if (mode == 2) topKProb = 0.25;\n                else if (mode == 3) topKProb = 0.15;\n                else if (mode == 4) topKProb = 0.30;\n                else if (mode == 5) topKProb = 0.20;\n                else topKProb = 0.18;\n\n                double lookAheadCoef;\n                if (mode == 1) lookAheadCoef = 0.0;\n                else if (mode == 2) lookAheadCoef = 1.5;\n                else if (mode == 3) lookAheadCoef = 2.5;\n                else if (mode == 4) lookAheadCoef = 3.5;\n                else if (mode == 5) lookAheadCoef = 2.0;\n                else lookAheadCoef = 4.5;\n\n                par = deepDfsConstruct(\n                    rootBias,\n                    childBias,\n                    randomness,\n                    branchProb,\n                    topKProb,\n                    lookAheadCoef\n                );\n            }\n\n            par = rerootTrees(par);\n\n            long long sc = calcScore(par);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPar = par;\n            }\n\n            iter++;\n        }\n\n        for (int i = 0; i < n; i++) {\n            if (i) cout << ' ';\n            cout << bestPar[i];\n        }\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Solver solver;\n    solver.solve();\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Operation {\n    char d;\n    int p;\n};\n\nstruct Cycle {\n    char d;\n    int p;\n    int k;\n    int cost;\n    unsigned long long mask;\n};\n\nstruct DirectCand {\n    char d;\n    int p;\n    int k;\n    int removed;\n    int cost;\n    vector<string> nb;\n};\n\nint N;\nvector<string> initial_board;\nvector<pair<int,int>> oni;\nint oid[20][20];\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsed_time() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nchar rev_dir(char d) {\n    if (d == 'U') return 'D';\n    if (d == 'D') return 'U';\n    if (d == 'L') return 'R';\n    return 'L';\n}\n\nint popcnt(unsigned long long x) {\n    return __builtin_popcountll(x);\n}\n\nint count_oni_board(const vector<string>& b) {\n    int c = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] == 'x') c++;\n        }\n    }\n    return c;\n}\n\nvoid shift_once_raw(vector<string>& b, char d, int p, int& remO, int& remF) {\n    if (d == 'L') {\n        if (b[p][0] == 'x') remO++;\n        if (b[p][0] == 'o') remF++;\n        for (int j = 0; j + 1 < N; j++) b[p][j] = b[p][j + 1];\n        b[p][N - 1] = '.';\n    } else if (d == 'R') {\n        if (b[p][N - 1] == 'x') remO++;\n        if (b[p][N - 1] == 'o') remF++;\n        for (int j = N - 1; j >= 1; j--) b[p][j] = b[p][j - 1];\n        b[p][0] = '.';\n    } else if (d == 'U') {\n        if (b[0][p] == 'x') remO++;\n        if (b[0][p] == 'o') remF++;\n        for (int i = 0; i + 1 < N; i++) b[i][p] = b[i + 1][p];\n        b[N - 1][p] = '.';\n    } else {\n        if (b[N - 1][p] == 'x') remO++;\n        if (b[N - 1][p] == 'o') remF++;\n        for (int i = N - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n}\n\nvoid shift_once(vector<string>& b, char d, int p) {\n    int ro = 0, rf = 0;\n    shift_once_raw(b, d, p, ro, rf);\n}\n\nbool verify_answer(const vector<Operation>& ops) {\n    if ((int)ops.size() > 4 * N * N) return false;\n\n    vector<string> b = initial_board;\n    int remO = 0;\n    int remF = 0;\n\n    for (auto [d, p] : ops) {\n        if (p < 0 || p >= N) return false;\n        if (!(d == 'L' || d == 'R' || d == 'U' || d == 'D')) return false;\n\n        shift_once_raw(b, d, p, remO, remF);\n        if (remF > 0) return false;\n    }\n\n    return remF == 0 && count_oni_board(b) == 0;\n}\n\nvector<pair<int,int>> collect_oni(const vector<string>& b) {\n    vector<pair<int,int>> v;\n    memset(oid, -1, sizeof(oid));\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            if (b[i][j] == 'x') {\n                oid[i][j] = (int)v.size();\n                v.push_back({i, j});\n            }\n        }\n    }\n\n    return v;\n}\n\nvector<Cycle> enumerate_cycles_from_board(const vector<string>& board) {\n    vector<Cycle> cycles;\n\n    auto add = [&](char d, int p, int k, unsigned long long mask) {\n        if (mask == 0) return;\n        cycles.push_back({d, p, k, 2 * k, mask});\n    };\n\n    for (int j = 0; j < N; j++) {\n        bool block = false;\n        unsigned long long mask = 0;\n\n        for (int i = 0; i < N; i++) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('U', j, i + 1, mask);\n        }\n    }\n\n    for (int j = 0; j < N; j++) {\n        bool block = false;\n        unsigned long long mask = 0;\n\n        for (int i = N - 1; i >= 0; i--) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('D', j, N - i, mask);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        bool block = false;\n        unsigned long long mask = 0;\n\n        for (int j = 0; j < N; j++) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('L', i, j + 1, mask);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        bool block = false;\n        unsigned long long mask = 0;\n\n        for (int j = N - 1; j >= 0; j--) {\n            if (board[i][j] == 'o') block = true;\n            if (block) break;\n\n            if (board[i][j] == 'x') mask |= 1ULL << oid[i][j];\n            add('R', i, N - j, mask);\n        }\n    }\n\n    return cycles;\n}\n\nvector<Operation> dynamic_greedy(const vector<string>& start_board) {\n    vector<string> board = start_board;\n    vector<Operation> ops;\n\n    while (count_oni_board(board) > 0) {\n        oni = collect_oni(board);\n        vector<Cycle> cycles = enumerate_cycles_from_board(board);\n\n        int best = -1;\n\n        for (int i = 0; i < (int)cycles.size(); i++) {\n            int gain = popcnt(cycles[i].mask);\n            if (gain == 0) continue;\n\n            if (best == -1) {\n                best = i;\n            } else {\n                int bgain = popcnt(cycles[best].mask);\n\n                long long lhs = 1LL * gain * cycles[best].cost;\n                long long rhs = 1LL * bgain * cycles[i].cost;\n\n                if (lhs > rhs ||\n                    (lhs == rhs && gain > bgain) ||\n                    (lhs == rhs && gain == bgain && cycles[i].cost < cycles[best].cost)) {\n                    best = i;\n                }\n            }\n        }\n\n        if (best == -1) break;\n\n        Cycle c = cycles[best];\n\n        for (int id = 0; id < (int)oni.size(); id++) {\n            if ((c.mask >> id) & 1ULL) {\n                auto [r, col] = oni[id];\n                board[r][col] = '.';\n            }\n        }\n\n        char rd = rev_dir(c.d);\n\n        for (int t = 0; t < c.k; t++) ops.push_back({c.d, c.p});\n        for (int t = 0; t < c.k; t++) ops.push_back({rd, c.p});\n    }\n\n    return ops;\n}\n\nvector<Operation> cycles_to_ops(const vector<Cycle>& selected) {\n    vector<Operation> ops;\n\n    for (const Cycle& c : selected) {\n        char r = rev_dir(c.d);\n\n        for (int t = 0; t < c.k; t++) ops.push_back({c.d, c.p});\n        for (int t = 0; t < c.k; t++) ops.push_back({r, c.p});\n    }\n\n    return ops;\n}\n\nint total_cost_idx(const vector<int>& v, const vector<Cycle>& cycles) {\n    int s = 0;\n    for (int x : v) s += cycles[x].cost;\n    return s;\n}\n\nvoid cleanup(vector<int>& sel, const vector<Cycle>& cycles, unsigned long long ALL) {\n    bool changed = true;\n\n    while (changed) {\n        changed = false;\n        int m = sel.size();\n\n        vector<unsigned long long> pref(m + 1, 0), suff(m + 1, 0);\n        for (int i = 0; i < m; i++) pref[i + 1] = pref[i] | cycles[sel[i]].mask;\n        for (int i = m - 1; i >= 0; i--) suff[i] = suff[i + 1] | cycles[sel[i]].mask;\n\n        for (int i = 0; i < m; i++) {\n            if ((pref[i] | suff[i + 1]) == ALL) {\n                sel.erase(sel.begin() + i);\n                changed = true;\n                break;\n            }\n        }\n    }\n}\n\nvector<int> greedy_cover_indices(const vector<Cycle>& cycles, unsigned long long ALL, mt19937& rng, bool randomize) {\n    unsigned long long covered = 0;\n    vector<int> sel;\n\n    while (covered != ALL) {\n        struct Item {\n            double score;\n            int idx;\n            int gain;\n        };\n\n        vector<Item> items;\n\n        for (int i = 0; i < (int)cycles.size(); i++) {\n            unsigned long long gm = cycles[i].mask & ~covered;\n            int gain = popcnt(gm);\n            if (gain == 0) continue;\n\n            double score = (double)gain / cycles[i].cost;\n            if (randomize) score *= uniform_real_distribution<double>(0.80, 1.20)(rng);\n\n            items.push_back({score, i, gain});\n        }\n\n        if (items.empty()) break;\n\n        sort(items.begin(), items.end(), [](const Item& a, const Item& b) {\n            if (a.score != b.score) return a.score > b.score;\n            if (a.gain != b.gain) return a.gain > b.gain;\n            return a.idx < b.idx;\n        });\n\n        int choose = 0;\n        if (randomize) {\n            int lim = min<int>(6, items.size());\n            choose = uniform_int_distribution<int>(0, lim - 1)(rng);\n        }\n\n        int idx = items[choose].idx;\n        sel.push_back(idx);\n        covered |= cycles[idx].mask;\n    }\n\n    cleanup(sel, cycles, ALL);\n    return sel;\n}\n\nvector<Operation> solve_static_cover(const vector<string>& board, int trials = 800) {\n    oni = collect_oni(board);\n    if (oni.empty()) return {};\n\n    vector<Cycle> cycles = enumerate_cycles_from_board(board);\n\n    vector<char> bad(cycles.size(), false);\n    for (int i = 0; i < (int)cycles.size(); i++) {\n        for (int j = 0; j < (int)cycles.size(); j++) {\n            if (i == j) continue;\n\n            if ((cycles[i].mask & ~cycles[j].mask) == 0 &&\n                cycles[i].cost >= cycles[j].cost) {\n                bad[i] = true;\n                break;\n            }\n        }\n    }\n\n    vector<Cycle> filtered;\n    for (int i = 0; i < (int)cycles.size(); i++) {\n        if (!bad[i]) filtered.push_back(cycles[i]);\n    }\n    cycles.swap(filtered);\n\n    int M = oni.size();\n    unsigned long long ALL = (M == 64 ? ~0ULL : ((1ULL << M) - 1));\n\n    mt19937 rng(123456789);\n\n    vector<int> bestSel;\n    int bestCost = 1e9;\n\n    for (int t = 0; t < trials; t++) {\n        vector<int> sel = greedy_cover_indices(cycles, ALL, rng, t != 0);\n\n        unsigned long long cov = 0;\n        for (int idx : sel) cov |= cycles[idx].mask;\n        if (cov != ALL) continue;\n\n        int cst = total_cost_idx(sel, cycles);\n        if (cst < bestCost) {\n            bestCost = cst;\n            bestSel = sel;\n        }\n    }\n\n    if (bestSel.empty()) return {};\n\n    vector<Cycle> selected;\n    for (int idx : bestSel) selected.push_back(cycles[idx]);\n\n    return cycles_to_ops(selected);\n}\n\nvector<DirectCand> enumerate_direct(const vector<string>& board, bool zeroFukuOnly) {\n    vector<DirectCand> cands;\n\n    auto add = [&](char d, int p, int k, int removed, int removedFuku, const vector<string>& nb) {\n        if (removed <= 0) return;\n        if (removedFuku > 0) return;\n\n        cands.push_back({d, p, k, removed, k, nb});\n    };\n\n    for (char d : {'L', 'R', 'U', 'D'}) {\n        for (int p = 0; p < N; p++) {\n            if (zeroFukuOnly) {\n                bool hasO = false;\n\n                if (d == 'L' || d == 'R') {\n                    for (int j = 0; j < N; j++) {\n                        if (board[p][j] == 'o') hasO = true;\n                    }\n                } else {\n                    for (int i = 0; i < N; i++) {\n                        if (board[i][p] == 'o') hasO = true;\n                    }\n                }\n\n                if (hasO) continue;\n            }\n\n            vector<string> b = board;\n            int totalO = 0;\n            int totalF = 0;\n\n            for (int k = 1; k <= N; k++) {\n                int ro = 0;\n                int rf = 0;\n                shift_once_raw(b, d, p, ro, rf);\n                totalO += ro;\n                totalF += rf;\n\n                if (totalF > 0) break;\n\n                add(d, p, k, totalO, totalF, b);\n            }\n        }\n    }\n\n    sort(cands.begin(), cands.end(), [](const DirectCand& a, const DirectCand& b) {\n        long long lhs = 1LL * a.removed * b.cost;\n        long long rhs = 1LL * b.removed * a.cost;\n\n        if (lhs != rhs) return lhs > rhs;\n        if (a.removed != b.removed) return a.removed > b.removed;\n        if (a.cost != b.cost) return a.cost < b.cost;\n        if (a.d != b.d) return a.d < b.d;\n        return a.p < b.p;\n    });\n\n    return cands;\n}\n\nvector<Operation> solve_with_direct_attempt(\n    mt19937& rng,\n    bool randomized,\n    bool zeroFukuOnly,\n    double stopProb,\n    int topK\n) {\n    vector<string> board = initial_board;\n    vector<Operation> answer;\n\n    int steps = 0;\n\n    while (true) {\n        if (randomized && steps > 0) {\n            double r = uniform_real_distribution<double>(0.0, 1.0)(rng);\n            if (r < stopProb) break;\n        }\n\n        vector<DirectCand> cands = enumerate_direct(board, zeroFukuOnly);\n        if (cands.empty()) break;\n\n        int choose = 0;\n        if (randomized) {\n            int lim = min<int>(topK, cands.size());\n            choose = uniform_int_distribution<int>(0, lim - 1)(rng);\n        }\n\n        DirectCand dc = cands[choose];\n\n        for (int t = 0; t < dc.k; t++) {\n            answer.push_back({dc.d, dc.p});\n        }\n\n        board = dc.nb;\n\n        steps++;\n        if (steps > 50) break;\n        if ((int)answer.size() > 4 * N * N) break;\n    }\n\n    vector<Operation> rest = dynamic_greedy(board);\n    answer.insert(answer.end(), rest.begin(), rest.end());\n\n    return answer;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    START_TIME = chrono::steady_clock::now();\n\n    cin >> N;\n\n    initial_board.resize(N);\n    memset(oid, -1, sizeof(oid));\n\n    for (int i = 0; i < N; i++) cin >> initial_board[i];\n\n    vector<Operation> answer = dynamic_greedy(initial_board);\n\n    auto consider = [&](const vector<Operation>& cand) {\n        if (!cand.empty() &&\n            cand.size() < answer.size() &&\n            verify_answer(cand)) {\n            answer = cand;\n        }\n    };\n\n    vector<Operation> staticAns = solve_static_cover(initial_board, 900);\n    consider(staticAns);\n\n    mt19937 rng(246813579);\n\n    consider(solve_with_direct_attempt(rng, false, true, 0.0, 1));\n    consider(solve_with_direct_attempt(rng, false, false, 0.0, 1));\n\n    int iter = 0;\n\n    while (elapsed_time() < 1.85) {\n        bool zeroOnly = (iter % 5 == 0);\n\n        double stopProb;\n        if (iter % 3 == 0) stopProb = 0.00;\n        else if (iter % 3 == 1) stopProb = 0.08;\n        else stopProb = 0.16;\n\n        int topK;\n        if (iter % 4 == 0) topK = 4;\n        else if (iter % 4 == 1) topK = 6;\n        else if (iter % 4 == 2) topK = 8;\n        else topK = 12;\n\n        vector<Operation> cand = solve_with_direct_attempt(\n            rng,\n            true,\n            zeroOnly,\n            stopProb,\n            topK\n        );\n\n        consider(cand);\n        iter++;\n    }\n\n    for (auto [d, p] : answer) {\n        cout << d << ' ' << p << '\\n';\n    }\n\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 100;\nstatic constexpr int L = 500000;\nstatic constexpr int SHORT_L = 100000;\n\nstruct Plan {\n    int a[N];\n    int b[N];\n};\n\nstruct RNG {\n    uint64_t x;\n    RNG(uint64_t seed = 1234567891234567ULL) : x(seed) {}\n\n    inline uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n\n    inline int next_int(int l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n\n    inline double next_double() {\n        return (next_u64() >> 11) * (1.0 / 9007199254740992.0);\n    }\n};\n\ninline int eval_plan_len(const Plan& p, const int Target[N], int len) {\n    static int cnt[N];\n    memset(cnt, 0, sizeof(cnt));\n\n    int x = 0;\n\n    for (int week = 0; week < len; week++) {\n        int c = ++cnt[x];\n        x = (c & 1) ? p.a[x] : p.b[x];\n    }\n\n    int err = 0;\n    for (int i = 0; i < N; i++) {\n        err += abs(cnt[i] - Target[i]);\n    }\n\n    return err;\n}\n\nint sample_weighted(const int pref[N], RNG& rng) {\n    int v = rng.next_int(1, L);\n\n    int lo = 0;\n    int hi = N - 1;\n\n    while (lo < hi) {\n        int mid = (lo + hi) >> 1;\n        if (pref[mid] >= v) hi = mid;\n        else lo = mid + 1;\n    }\n\n    return lo;\n}\n\nPlan weighted_balance_plan(const int T[N], RNG& rng, double noise) {\n    struct Item {\n        int src;\n        double w;\n        double key;\n    };\n\n    Item items[200];\n    int ptr = 0;\n\n    for (int i = 0; i < N; i++) {\n        double w = T[i] * 0.5;\n\n        double r1 = 1.0 + noise * (rng.next_double() - 0.5);\n        double r2 = 1.0 + noise * (rng.next_double() - 0.5);\n\n        items[ptr++] = {i, w, w * r1};\n        items[ptr++] = {i, w, w * r2};\n    }\n\n    sort(items, items + 200, [](const Item& x, const Item& y) {\n        return x.key > y.key;\n    });\n\n    double load[N];\n    int outs[N][2];\n    int deg[N];\n\n    for (int i = 0; i < N; i++) {\n        load[i] = 0.0;\n        deg[i] = 0;\n        outs[i][0] = outs[i][1] = 0;\n    }\n\n    for (int idx = 0; idx < 200; idx++) {\n        const auto& it = items[idx];\n\n        int best = 0;\n        double best_score = -1e100;\n\n        for (int j = 0; j < N; j++) {\n            double rem = T[j] - load[j];\n            double score = rem + noise * 2500.0 * (rng.next_double() - 0.5);\n\n            if (score > best_score) {\n                best_score = score;\n                best = j;\n            }\n        }\n\n        load[best] += it.w;\n\n        int s = it.src;\n        if (deg[s] < 2) {\n            outs[s][deg[s]++] = best;\n        }\n    }\n\n    Plan p;\n\n    for (int i = 0; i < N; i++) {\n        while (deg[i] < 2) {\n            outs[i][deg[i]++] = rng.next_int(0, N - 1);\n        }\n\n        if (rng.next_int(0, 1)) {\n            swap(outs[i][0], outs[i][1]);\n        }\n\n        p.a[i] = outs[i][0];\n        p.b[i] = outs[i][1];\n    }\n\n    return p;\n}\n\nPlan flip_mutate_plan(const Plan& base, RNG& rng) {\n    Plan p = base;\n\n    int changes = 1 + rng.next_int(0, 3);\n    for (int k = 0; k < changes; k++) {\n        int i = rng.next_int(0, N - 1);\n        swap(p.a[i], p.b[i]);\n    }\n\n    return p;\n}\n\nPlan swap_mutate_plan(const Plan& base, RNG& rng) {\n    Plan p = base;\n\n    int changes = 1 + rng.next_int(0, 2);\n    for (int k = 0; k < changes; k++) {\n        int i1 = rng.next_int(0, N - 1);\n        int i2 = rng.next_int(0, N - 1);\n        int s1 = rng.next_int(0, 1);\n        int s2 = rng.next_int(0, 1);\n\n        int* e1 = (s1 == 0 ? &p.a[i1] : &p.b[i1]);\n        int* e2 = (s2 == 0 ? &p.a[i2] : &p.b[i2]);\n\n        swap(*e1, *e2);\n    }\n\n    return p;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n, l;\n    cin >> n >> l;\n\n    int T[N];\n    int Tshort[N];\n\n    for (int i = 0; i < N; i++) {\n        cin >> T[i];\n    }\n\n    for (int i = 0; i < N; i++) {\n        Tshort[i] = (int)llround((long long)T[i] * SHORT_L / (double)L);\n    }\n\n    RNG rng(chrono::steady_clock::now().time_since_epoch().count());\n\n    Plan best;\n    for (int i = 0; i < N; i++) {\n        best.a[i] = best.b[i] = 0;\n    }\n\n    int best_full = eval_plan_len(best, T, L);\n    int best_short = eval_plan_len(best, Tshort, SHORT_L);\n\n    auto start = chrono::steady_clock::now();\n\n    int iter = 0;\n\n    while (true) {\n        auto now = chrono::steady_clock::now();\n        double elapsed = chrono::duration<double>(now - start).count();\n\n        if (elapsed > 1.88) break;\n\n        Plan cand;\n\n        int mode = iter % 18;\n\n        if (mode <= 15) {\n            static constexpr double noises[16] = {\n                0.00, 0.008, 0.015, 0.025,\n                0.04, 0.06, 0.085, 0.12,\n                0.16, 0.22, 0.30, 0.40,\n                0.52, 0.70, 0.95, 1.25\n            };\n\n            cand = weighted_balance_plan(T, rng, noises[mode]);\n        } else if (mode == 16) {\n            cand = flip_mutate_plan(best, rng);\n        } else {\n            cand = swap_mutate_plan(best, rng);\n        }\n\n        int se = eval_plan_len(cand, Tshort, SHORT_L);\n\n        bool do_full = false;\n\n        if (iter < 35) {\n            do_full = true;\n        } else {\n            double elapsed_now = chrono::duration<double>(\n                chrono::steady_clock::now() - start\n            ).count();\n\n            int threshold;\n\n            if (elapsed_now < 0.65) {\n                threshold = 2600;\n            } else if (elapsed_now < 1.25) {\n                threshold = 2000;\n            } else {\n                threshold = 1500;\n            }\n\n            if (se <= best_short + threshold) {\n                do_full = true;\n            } else if ((iter & 15) == 0 && se <= best_short + threshold + 3000) {\n                do_full = true;\n            }\n        }\n\n        if (do_full) {\n            int fe = eval_plan_len(cand, T, L);\n\n            if (fe < best_full) {\n                best_full = fe;\n                best = cand;\n                best_short = se;\n            }\n        }\n\n        iter++;\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double sec() const {\n        return chrono::duration<double>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n) {\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) {\n        while (p[x] != x) {\n            p[x] = p[p[x]];\n            x = p[x];\n        }\n        return x;\n    }\n    bool unite(int a, int b) {\n        a = find(a);\n        b = find(b);\n        if (a == b) return false;\n        if (sz[a] < sz[b]) swap(a, b);\n        p[b] = a;\n        sz[a] += sz[b];\n        return true;\n    }\n};\n\nstruct Edge {\n    int u, v;\n    long long w;\n    bool operator<(const Edge& o) const {\n        if (w != o.w) return w < o.w;\n        if (u != o.u) return u < o.u;\n        return v < o.v;\n    }\n};\n\nstatic uint64_t rng_state = 3141592653589793ULL;\n\nuint64_t rng64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\nint rnd_int(int l, int r) {\n    return l + (int)(rng64() % (uint64_t)(r - l + 1));\n}\ndouble rnd01() {\n    return (rng64() >> 11) * (1.0 / 9007199254740992.0);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\n\n    vector<int> G(M);\n    for (int i = 0; i < M; i++) cin >> G[i];\n\n    vector<int> lx(N), rx(N), ly(N), ry(N);\n    vector<double> x(N), y(N), rad(N), side(N);\n\n    double avgSide = 0.0;\n\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n\n        x[i] = 0.5 * (lx[i] + rx[i]);\n        y[i] = 0.5 * (ly[i] + ry[i]);\n\n        double wx = rx[i] - lx[i];\n        double wy = ry[i] - ly[i];\n\n        side[i] = max(wx, wy);\n        rad[i] = 0.5 * sqrt(wx * wx + wy * wy);\n        avgSide += side[i];\n    }\n\n    avgSide /= N;\n\n    double uncertainRatio = min(1.0, max(0.0, avgSide / 1800.0));\n    double centerWeight = 0.82 - 0.18 * uncertainRatio;\n    double minWeight = 1.0 - centerWeight;\n    double uncertaintyCoef = 0.045 + 0.075 * uncertainRatio;\n\n    vector<vector<double>> cd(N, vector<double>(N, 0.0));\n    vector<vector<double>> wd(N, vector<double>(N, 0.0));\n    vector<vector<int>> iw(N, vector<int>(N, 0));\n    vector<vector<int>> nearest(N);\n\n    for (int i = 0; i < N; i++) {\n        nearest[i].reserve(N - 1);\n        for (int j = 0; j < N; j++) if (i != j) nearest[i].push_back(j);\n    }\n\n    auto rectMinDist = [&](int a, int b) -> double {\n        double dx = 0.0;\n        if (rx[a] < lx[b]) dx = lx[b] - rx[a];\n        else if (rx[b] < lx[a]) dx = lx[a] - rx[b];\n\n        double dy = 0.0;\n        if (ry[a] < ly[b]) dy = ly[b] - ry[a];\n        else if (ry[b] < ly[a]) dy = ly[a] - ry[b];\n\n        return sqrt(dx * dx + dy * dy);\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            double dx = x[i] - x[j];\n            double dy = y[i] - y[j];\n            double d = sqrt(dx * dx + dy * dy);\n            cd[i][j] = cd[j][i] = d;\n\n            double md = rectMinDist(i, j);\n            double uncertainty = uncertaintyCoef * (rad[i] + rad[j]);\n\n            double robust = centerWeight * d + minWeight * md + uncertainty;\n\n            if (md < 1e-9) {\n                robust = min(robust, d * (0.86 - 0.08 * uncertainRatio) + uncertainty * 0.45);\n            }\n\n            wd[i][j] = wd[j][i] = robust;\n            iw[i][j] = iw[j][i] = max(0, (int)robust);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        sort(nearest[i].begin(), nearest[i].end(), [&](int a, int b) {\n            return wd[i][a] < wd[i][b];\n        });\n    }\n\n    auto mstCostMat = [&](const vector<int>& v, const vector<vector<double>>& mat) -> double {\n        int n = (int)v.size();\n        if (n <= 1) return 0.0;\n\n        vector<double> mn(n, 1e100);\n        vector<char> used(n, 0);\n        mn[0] = 0;\n\n        double cost = 0;\n\n        for (int it = 0; it < n; it++) {\n            int bi = -1;\n\n            for (int i = 0; i < n; i++) {\n                if (!used[i] && (bi == -1 || mn[i] < mn[bi])) bi = i;\n            }\n\n            used[bi] = 1;\n            cost += mn[bi];\n\n            int a = v[bi];\n\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                double d = mat[a][v[j]];\n                if (d < mn[j]) mn[j] = d;\n            }\n        }\n\n        return cost;\n    };\n\n    double robustScoreWeight = 0.55 + 0.30 * uncertainRatio;\n\n    auto mstCost = [&](const vector<int>& v) -> double {\n        return robustScoreWeight * mstCostMat(v, wd)\n             + (1.0 - robustScoreWeight) * mstCostMat(v, cd);\n    };\n\n    auto totalMSTCost = [&](const vector<vector<int>>& groups) -> double {\n        double s = 0;\n        for (const auto &g : groups) s += mstCost(g);\n        return s;\n    };\n\n    auto makeByOrder = [&](const vector<int>& order) {\n        vector<vector<int>> groups(M);\n        int p = 0;\n\n        for (int k = 0; k < M; k++) {\n            groups[k].assign(order.begin() + p, order.begin() + p + G[k]);\n            p += G[k];\n        }\n\n        return groups;\n    };\n\n    vector<vector<vector<int>>> candidates;\n\n    auto addCandidate = [&](vector<vector<int>> g) {\n        bool ok = true;\n        vector<int> cnt(N, 0);\n\n        for (int k = 0; k < M; k++) {\n            if ((int)g[k].size() != G[k]) ok = false;\n\n            for (int v : g[k]) {\n                if (0 <= v && v < N) cnt[v]++;\n                else ok = false;\n            }\n        }\n\n        for (int i = 0; i < N; i++) if (cnt[i] != 1) ok = false;\n\n        if (ok) candidates.push_back(std::move(g));\n    };\n\n    auto mortonKey = [&](int i, bool swapxy, bool revx, bool revy) -> long long {\n        int xi = max(0, min(10000, (int)x[i]));\n        int yi = max(0, min(10000, (int)y[i]));\n\n        if (revx) xi = 10000 - xi;\n        if (revy) yi = 10000 - yi;\n        if (swapxy) swap(xi, yi);\n\n        long long key = 0;\n\n        for (int b = 0; b < 14; b++) {\n            key |= ((long long)((xi >> b) & 1)) << (2 * b);\n            key |= ((long long)((yi >> b) & 1)) << (2 * b + 1);\n        }\n\n        return key;\n    };\n\n    // Basic geometric candidates.\n    {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (x[a] != x[b]) return x[a] < x[b];\n            return y[a] < y[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (y[a] != y[b]) return y[a] < y[b];\n            return x[a] < x[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka = x[a] + y[a];\n            double kb = x[b] + y[b];\n            if (ka != kb) return ka < kb;\n            return x[a] < x[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            double ka = x[a] - y[a];\n            double kb = x[b] - y[b];\n            if (ka != kb) return ka < kb;\n            return x[a] < x[b];\n        });\n        addCandidate(makeByOrder(ord));\n\n        for (int sw = 0; sw < 2; sw++) {\n            for (int rxv = 0; rxv < 2; rxv++) {\n                for (int ryv = 0; ryv < 2; ryv++) {\n                    iota(ord.begin(), ord.end(), 0);\n\n                    sort(ord.begin(), ord.end(), [&](int a, int b) {\n                        long long ka = mortonKey(a, sw, rxv, ryv);\n                        long long kb = mortonKey(b, sw, rxv, ryv);\n                        if (ka != kb) return ka < kb;\n                        return a < b;\n                    });\n\n                    addCandidate(makeByOrder(ord));\n                }\n            }\n        }\n\n        for (int B : {4, 5, 7, 8, 10, 12, 16, 20, 25}) {\n            for (int mode = 0; mode < 2; mode++) {\n                iota(ord.begin(), ord.end(), 0);\n\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int ca = min(B - 1, max(0, (int)(x[a] * B / 10001.0)));\n                    int cb = min(B - 1, max(0, (int)(x[b] * B / 10001.0)));\n                    int ra = min(B - 1, max(0, (int)(y[a] * B / 10001.0)));\n                    int rb = min(B - 1, max(0, (int)(y[b] * B / 10001.0)));\n\n                    long long ka, kb;\n\n                    if (mode == 0) {\n                        ka = (long long)ra * B + ((ra & 1) ? (B - 1 - ca) : ca);\n                        kb = (long long)rb * B + ((rb & 1) ? (B - 1 - cb) : cb);\n                    } else {\n                        ka = (long long)ca * B + ((ca & 1) ? (B - 1 - ra) : ra);\n                        kb = (long long)cb * B + ((cb & 1) ? (B - 1 - rb) : rb);\n                    }\n\n                    if (ka != kb) return ka < kb;\n                    return mode == 0 ? x[a] < x[b] : y[a] < y[b];\n                });\n\n                addCandidate(makeByOrder(ord));\n            }\n        }\n    }\n\n    // Global MST traversal candidates.\n    {\n        vector<Edge> allEdges;\n        allEdges.reserve(N * (N - 1) / 2);\n\n        for (int i = 0; i < N; i++) {\n            for (int j = i + 1; j < N; j++) {\n                allEdges.push_back({i, j, (long long)(wd[i][j] * 1000)});\n            }\n        }\n\n        sort(allEdges.begin(), allEdges.end());\n\n        DSU dsu(N);\n        vector<vector<int>> tree(N);\n\n        for (auto &e : allEdges) {\n            if (dsu.unite(e.u, e.v)) {\n                tree[e.u].push_back(e.v);\n                tree[e.v].push_back(e.u);\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            sort(tree[i].begin(), tree[i].end(), [&](int a, int b) {\n                return atan2(y[a] - y[i], x[a] - x[i]) < atan2(y[b] - y[i], x[b] - x[i]);\n            });\n        }\n\n        vector<int> roots;\n        {\n            vector<int> tmp(N);\n            iota(tmp.begin(), tmp.end(), 0);\n\n            sort(tmp.begin(), tmp.end(), [&](int a, int b) {\n                return x[a] + y[a] < x[b] + y[b];\n            });\n            roots.push_back(tmp.front());\n            roots.push_back(tmp.back());\n\n            sort(tmp.begin(), tmp.end(), [&](int a, int b) {\n                return x[a] - y[a] < x[b] - y[b];\n            });\n            roots.push_back(tmp.front());\n            roots.push_back(tmp.back());\n\n            for (int t = 0; t < 6; t++) roots.push_back(rnd_int(0, N - 1));\n        }\n\n        for (int root : roots) {\n            vector<int> ord;\n            ord.reserve(N);\n\n            function<void(int,int)> dfs = [&](int v, int p) {\n                ord.push_back(v);\n                for (int to : tree[v]) if (to != p) dfs(to, v);\n            };\n\n            dfs(root, -1);\n\n            if ((int)ord.size() == N) {\n                addCandidate(makeByOrder(ord));\n                reverse(ord.begin(), ord.end());\n                addCandidate(makeByOrder(ord));\n            }\n\n            vector<int> bord;\n            bord.reserve(N);\n            vector<int> vis(N, 0);\n            queue<int> qu;\n            qu.push(root);\n            vis[root] = 1;\n\n            while (!qu.empty()) {\n                int v = qu.front();\n                qu.pop();\n\n                bord.push_back(v);\n\n                vector<int> ch = tree[v];\n                sort(ch.begin(), ch.end(), [&](int a, int b) {\n                    return wd[v][a] < wd[v][b];\n                });\n\n                for (int to : ch) if (!vis[to]) {\n                    vis[to] = 1;\n                    qu.push(to);\n                }\n            }\n\n            if ((int)bord.size() == N) addCandidate(makeByOrder(bord));\n        }\n    }\n\n    // Recursive bisection candidates.\n    function<void(vector<int>&, vector<int>&, vector<vector<int>>&, int)> recBuild =\n        [&](vector<int>& pts, vector<int>& gids, vector<vector<int>>& groups, int depth) {\n            if (gids.empty()) return;\n\n            if ((int)gids.size() == 1) {\n                groups[gids[0]] = pts;\n                return;\n            }\n\n            double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n\n            for (int p : pts) {\n                minx = min(minx, x[p]);\n                maxx = max(maxx, x[p]);\n                miny = min(miny, y[p]);\n                maxy = max(maxy, y[p]);\n            }\n\n            vector<int> order = gids;\n\n            sort(order.begin(), order.end(), [&](int a, int b) {\n                if (G[a] != G[b]) return G[a] > G[b];\n                return a < b;\n            });\n\n            for (int i = 0; i < (int)order.size(); i++) {\n                if (rnd01() < 0.25) {\n                    int j = rnd_int(i, (int)order.size() - 1);\n                    swap(order[i], order[j]);\n                }\n            }\n\n            int total = (int)pts.size();\n            int target = total / 2;\n\n            vector<int> leftG, rightG;\n            int sumL = 0;\n\n            for (int id : order) {\n                if (sumL < target) {\n                    leftG.push_back(id);\n                    sumL += G[id];\n                } else {\n                    rightG.push_back(id);\n                }\n            }\n\n            bool improved = true;\n\n            while (improved) {\n                improved = false;\n                int cur = abs(sumL - (total - sumL));\n\n                for (int i = 0; i < (int)leftG.size(); i++) {\n                    int ns = sumL - G[leftG[i]];\n                    int nd = abs(ns - (total - ns));\n\n                    if (!rightG.empty() && nd < cur) {\n                        rightG.push_back(leftG[i]);\n                        leftG.erase(leftG.begin() + i);\n                        sumL = ns;\n                        improved = true;\n                        break;\n                    }\n                }\n\n                if (improved) continue;\n\n                for (int i = 0; i < (int)rightG.size(); i++) {\n                    int ns = sumL + G[rightG[i]];\n                    int nd = abs(ns - (total - ns));\n\n                    if (nd < cur) {\n                        leftG.push_back(rightG[i]);\n                        rightG.erase(rightG.begin() + i);\n                        sumL = ns;\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n\n            if (leftG.empty() || rightG.empty()) {\n                leftG.clear();\n                rightG.clear();\n                sumL = 0;\n\n                for (int i = 0; i < (int)order.size(); i++) {\n                    if (i < (int)order.size() / 2) {\n                        leftG.push_back(order[i]);\n                        sumL += G[order[i]];\n                    } else {\n                        rightG.push_back(order[i]);\n                    }\n                }\n            }\n\n            bool splitX = (maxx - minx) >= (maxy - miny);\n            if (rnd01() < 0.15) splitX = !splitX;\n\n            sort(pts.begin(), pts.end(), [&](int a, int b) {\n                double va = splitX ? x[a] : y[a];\n                double vb = splitX ? x[b] : y[b];\n\n                if (va != vb) return va < vb;\n                return (splitX ? y[a] : x[a]) < (splitX ? y[b] : x[b]);\n            });\n\n            vector<int> lpts(pts.begin(), pts.begin() + sumL);\n            vector<int> rpts(pts.begin() + sumL, pts.end());\n\n            recBuild(lpts, leftG, groups, depth + 1);\n            recBuild(rpts, rightG, groups, depth + 1);\n        };\n\n    int recAttempts = 60;\n    if (M <= 20) recAttempts = 100;\n    if (M >= 180) recAttempts = 30;\n\n    for (int at = 0; at < recAttempts && timer.sec() < 0.85; at++) {\n        vector<int> pts(N), gids(M);\n        iota(pts.begin(), pts.end(), 0);\n        iota(gids.begin(), gids.end(), 0);\n\n        vector<vector<int>> g(M);\n        recBuild(pts, gids, g, 0);\n        addCandidate(g);\n    }\n\n    // Capacity-constrained seed clustering.\n    auto buildSeedCluster = [&](int variant) {\n        vector<vector<int>> groups(M);\n\n        vector<int> gids(M);\n        iota(gids.begin(), gids.end(), 0);\n\n        sort(gids.begin(), gids.end(), [&](int a, int b) {\n            if (G[a] != G[b]) return G[a] > G[b];\n            return a < b;\n        });\n\n        vector<int> seeds(M, -1);\n        vector<int> all(N);\n        iota(all.begin(), all.end(), 0);\n\n        int firstSeed;\n\n        if (variant % 6 == 0) {\n            firstSeed = min_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] + y[a] < x[b] + y[b];\n            })[0];\n        } else if (variant % 6 == 1) {\n            firstSeed = max_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] + y[a] < x[b] + y[b];\n            })[0];\n        } else if (variant % 6 == 2) {\n            firstSeed = min_element(all.begin(), all.end(), [&](int a, int b) {\n                return x[a] - y[a] < x[b] - y[b];\n            })[0];\n        } else {\n            firstSeed = rnd_int(0, N - 1);\n        }\n\n        seeds[gids[0]] = firstSeed;\n\n        vector<int> chosen;\n        chosen.push_back(firstSeed);\n\n        for (int idx = 1; idx < M; idx++) {\n            int gid = gids[idx];\n\n            int bestCity = -1;\n            double bestVal = -1;\n\n            int trials = (variant < 8 ? N : min(N, 180));\n\n            for (int tt = 0; tt < trials; tt++) {\n                int c = (trials == N ? tt : rnd_int(0, N - 1));\n\n                double md = 1e100;\n                for (int s : chosen) md = min(md, wd[c][s]);\n\n                double val = md * (1.0 + 0.12 * (rnd01() - 0.5));\n\n                if (val > bestVal) {\n                    bestVal = val;\n                    bestCity = c;\n                }\n            }\n\n            seeds[gid] = bestCity;\n            chosen.push_back(bestCity);\n        }\n\n        vector<int> rem = G;\n        vector<int> order(N);\n        iota(order.begin(), order.end(), 0);\n\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            double ba = 1e100, sa = 1e100;\n            double bb = 1e100, sb = 1e100;\n\n            for (int k = 0; k < M; k++) {\n                double da = wd[a][seeds[k]];\n                if (da < ba) {\n                    sa = ba;\n                    ba = da;\n                } else if (da < sa) {\n                    sa = da;\n                }\n\n                double db = wd[b][seeds[k]];\n                if (db < bb) {\n                    sb = bb;\n                    bb = db;\n                } else if (db < sb) {\n                    sb = db;\n                }\n            }\n\n            return (sa - ba) > (sb - bb);\n        });\n\n        for (int c : order) {\n            int bestK = -1;\n            double bestD = 1e100;\n\n            for (int k = 0; k < M; k++) {\n                if (rem[k] <= 0) continue;\n\n                double d = wd[c][seeds[k]] * (1.0 + 0.05 * (rnd01() - 0.5));\n\n                if (d < bestD) {\n                    bestD = d;\n                    bestK = k;\n                }\n            }\n\n            if (bestK < 0) {\n                for (int k = 0; k < M; k++) if (rem[k] > 0) {\n                    bestK = k;\n                    break;\n                }\n            }\n\n            groups[bestK].push_back(c);\n            rem[bestK]--;\n        }\n\n        return groups;\n    };\n\n    int seedAttempts = 30;\n    if (M <= 30) seedAttempts = 65;\n    if (M >= 180) seedAttempts = 12;\n\n    for (int at = 0; at < seedAttempts && timer.sec() < 1.05; at++) {\n        addCandidate(buildSeedCluster(at));\n    }\n\n    vector<vector<int>> groups;\n    double bestScore = 1e100;\n\n    for (auto &cand : candidates) {\n        double sc = totalMSTCost(cand);\n        if (sc < bestScore) {\n            bestScore = sc;\n            groups = cand;\n        }\n    }\n\n    vector<int> belong(N), posInGroup(N);\n\n    auto rebuildBelong = [&]() {\n        for (int k = 0; k < M; k++) {\n            for (int i = 0; i < (int)groups[k].size(); i++) {\n                belong[groups[k][i]] = k;\n                posInGroup[groups[k][i]] = i;\n            }\n        }\n    };\n\n    rebuildBelong();\n\n    vector<double> gCost(M);\n    for (int k = 0; k < M; k++) gCost[k] = mstCost(groups[k]);\n\n    // Local swap improvement.\n    for (int iter = 0; iter < 8500 && timer.sec() < 1.32; iter++) {\n        int aCity = rnd_int(0, N - 1);\n        int ga = belong[aCity];\n\n        int bCity = -1;\n        int scan = min(45, N - 1);\n        int offset = rnd_int(0, max(0, scan - 1));\n\n        for (int t = 0; t < scan; t++) {\n            int cand = nearest[aCity][(t + offset) % scan];\n\n            if (belong[cand] != ga) {\n                bCity = cand;\n                break;\n            }\n        }\n\n        if (bCity < 0) continue;\n\n        int gb = belong[bCity];\n        if (ga == gb) continue;\n\n        int ia = posInGroup[aCity];\n        int ib = posInGroup[bCity];\n\n        double old = gCost[ga] + gCost[gb];\n\n        swap(groups[ga][ia], groups[gb][ib]);\n\n        double na = mstCost(groups[ga]);\n        double nb = mstCost(groups[gb]);\n        double nw = na + nb;\n\n        if (nw + 1e-9 < old) {\n            gCost[ga] = na;\n            gCost[gb] = nb;\n\n            belong[aCity] = gb;\n            belong[bCity] = ga;\n            posInGroup[aCity] = ib;\n            posInGroup[bCity] = ia;\n        } else {\n            swap(groups[ga][ia], groups[gb][ib]);\n        }\n    }\n\n    // Sort inside groups by long axis.\n    for (int k = 0; k < M; k++) {\n        double minx = 1e100, maxx = -1e100, miny = 1e100, maxy = -1e100;\n\n        for (int p : groups[k]) {\n            minx = min(minx, x[p]);\n            maxx = max(maxx, x[p]);\n            miny = min(miny, y[p]);\n            maxy = max(maxy, y[p]);\n        }\n\n        bool sx = (maxx - minx) >= (maxy - miny);\n\n        sort(groups[k].begin(), groups[k].end(), [&](int a, int b) {\n            double va = sx ? x[a] : y[a];\n            double vb = sx ? x[b] : y[b];\n\n            if (va != vb) return va < vb;\n            return (sx ? y[a] : x[a]) < (sx ? y[b] : x[b]);\n        });\n    }\n\n    vector<vector<pair<int,int>>> queriedEdges(M);\n    vector<int> exactWhole(M, 0);\n    vector<set<vector<int>>> usedQueries(M);\n\n    int qcnt = 0;\n\n    auto query = [&](const vector<int>& c) -> vector<pair<int,int>> {\n        cout << \"? \" << c.size();\n\n        for (int v : c) cout << ' ' << v;\n\n        cout << endl;\n        cout.flush();\n\n        vector<pair<int,int>> ret;\n\n        for (int i = 0; i < (int)c.size() - 1; i++) {\n            int a, b;\n            cin >> a >> b;\n\n            if (a > b) swap(a, b);\n\n            ret.push_back({a, b});\n        }\n\n        return ret;\n    };\n\n    auto tryQuery = [&](int k, vector<int> c) -> bool {\n        if (qcnt >= Q) return false;\n        if ((int)c.size() < 2) return false;\n        if ((int)c.size() > L) c.resize(L);\n\n        vector<int> key = c;\n        sort(key.begin(), key.end());\n\n        if (usedQueries[k].count(key)) return false;\n\n        // Skip if highly overlapping with previous subsets in this group.\n        for (const auto& old : usedQueries[k]) {\n            int i = 0, j = 0, inter = 0;\n            while (i < (int)old.size() && j < (int)key.size()) {\n                if (old[i] == key[j]) {\n                    inter++;\n                    i++;\n                    j++;\n                } else if (old[i] < key[j]) {\n                    i++;\n                } else {\n                    j++;\n                }\n            }\n            if (inter >= (int)key.size() - 1 && (int)key.size() >= 4) return false;\n        }\n\n        usedQueries[k].insert(key);\n\n        auto ret = query(c);\n        qcnt++;\n        queriedEdges[k].insert(queriedEdges[k].end(), ret.begin(), ret.end());\n\n        return true;\n    };\n\n    // Exact small groups first, but size-2 groups do not need a query.\n    vector<int> qorder(M);\n    iota(qorder.begin(), qorder.end(), 0);\n\n    sort(qorder.begin(), qorder.end(), [&](int a, int b) {\n        bool aa = (G[a] >= 3 && G[a] <= L);\n        bool bb = (G[b] >= 3 && G[b] <= L);\n\n        if (aa != bb) return aa > bb;\n        if (G[a] != G[b]) return G[a] < G[b];\n        return a < b;\n    });\n\n    for (int k : qorder) {\n        if (qcnt >= Q) break;\n\n        if (G[k] >= 3 && G[k] <= L) {\n            if (tryQuery(k, groups[k])) {\n                exactWhole[k] = 1;\n            }\n        }\n    }\n\n    // Important larger groups.\n    vector<int> imp(M);\n    iota(imp.begin(), imp.end(), 0);\n\n    sort(imp.begin(), imp.end(), [&](int a, int b) {\n        double va = gCost[a] / max(1, G[a] - 1);\n        double vb = gCost[b] / max(1, G[b] - 1);\n        return va > vb;\n    });\n\n    auto farthestAnchors = [&](const vector<int>& vec, int cnt) {\n        vector<int> anchors;\n        int s = (int)vec.size();\n        if (s == 0 || cnt <= 0) return anchors;\n\n        int first = vec[s / 2];\n        anchors.push_back(first);\n\n        vector<double> mind(s, 1e100);\n        for (int i = 0; i < s; i++) mind[i] = wd[vec[i]][first];\n\n        while ((int)anchors.size() < cnt) {\n            int bestIdx = -1;\n            double bestD = -1.0;\n\n            for (int i = 0; i < s; i++) {\n                if (mind[i] > bestD) {\n                    bestD = mind[i];\n                    bestIdx = i;\n                }\n            }\n\n            if (bestIdx < 0) break;\n\n            int a = vec[bestIdx];\n            anchors.push_back(a);\n\n            for (int i = 0; i < s; i++) {\n                mind[i] = min(mind[i], wd[vec[i]][a]);\n            }\n        }\n\n        return anchors;\n    };\n\n    for (int k : imp) {\n        if (qcnt >= Q) break;\n\n        int s = groups[k].size();\n\n        if (s < 2 || exactWhole[k]) continue;\n\n        int tq = 1;\n\n        if (s >= 120) tq = 10;\n        else if (s >= 80) tq = 8;\n        else if (s >= 50) tq = 5;\n        else if (s >= 25) tq = 3;\n        else if (s >= 10) tq = 2;\n\n        tq = min(tq, Q - qcnt);\n\n        vector<int> anchors = farthestAnchors(groups[k], tq);\n\n        for (int anchor : anchors) {\n            if (qcnt >= Q) break;\n\n            vector<pair<double,int>> nb;\n            nb.reserve(s);\n\n            for (int p : groups[k]) nb.push_back({wd[anchor][p], p});\n\n            sort(nb.begin(), nb.end());\n\n            vector<int> c;\n\n            for (int i = 0; i < min(L, (int)nb.size()); i++) c.push_back(nb[i].second);\n\n            tryQuery(k, c);\n        }\n    }\n\n    auto groupApproxMSTEdges = [&](const vector<int>& vec) {\n        int s = (int)vec.size();\n        vector<tuple<double,int,int>> ret;\n        if (s <= 1) return ret;\n\n        vector<double> mn(s, 1e100);\n        vector<int> par(s, -1);\n        vector<char> used(s, 0);\n        mn[0] = 0;\n\n        for (int it = 0; it < s; it++) {\n            int bi = -1;\n\n            for (int i = 0; i < s; i++) {\n                if (!used[i] && (bi == -1 || mn[i] < mn[bi])) bi = i;\n            }\n\n            used[bi] = 1;\n\n            if (par[bi] != -1) {\n                ret.push_back({mn[bi], vec[bi], vec[par[bi]]});\n            }\n\n            int a = vec[bi];\n\n            for (int j = 0; j < s; j++) if (!used[j]) {\n                double d = wd[a][vec[j]];\n                if (d < mn[j]) {\n                    mn[j] = d;\n                    par[j] = bi;\n                }\n            }\n        }\n\n        sort(ret.begin(), ret.end(), greater<tuple<double,int,int>>());\n        return ret;\n    };\n\n    auto makeEdgeLocalQuery = [&](const vector<int>& vec, int a, int b) {\n        vector<pair<double,int>> nb;\n        nb.reserve(vec.size());\n\n        for (int p : vec) {\n            double d = min(wd[a][p], wd[b][p]);\n            nb.push_back({d, p});\n        }\n\n        sort(nb.begin(), nb.end());\n\n        vector<int> c;\n        for (int i = 0; i < min(L, (int)nb.size()); i++) c.push_back(nb[i].second);\n\n        return c;\n    };\n\n    // Remaining queries: target heavy approximate MST edges.\n    for (int k : imp) {\n        if (qcnt >= Q) break;\n        if (exactWhole[k]) continue;\n\n        int s = groups[k].size();\n        if (s < 2) continue;\n\n        auto mstEdges = groupApproxMSTEdges(groups[k]);\n\n        int limit = min((int)mstEdges.size(), max(3, s / max(2, L - 2)));\n\n        for (int i = 0; i < limit && qcnt < Q; i++) {\n            auto [w, a, b] = mstEdges[i];\n            vector<int> c = makeEdgeLocalQuery(groups[k], a, b);\n            tryQuery(k, c);\n        }\n    }\n\n    // Final fallback if queries remain: local windows.\n    for (int k : imp) {\n        if (qcnt >= Q) break;\n        if (exactWhole[k]) continue;\n\n        int s = groups[k].size();\n        if (s < 2) continue;\n\n        int step = max(2, L - 1);\n\n        for (int st = 0; st < s && qcnt < Q; st += step) {\n            int en = min(s, st + L);\n\n            if (en - st < 2) break;\n\n            vector<int> c(groups[k].begin() + st, groups[k].begin() + en);\n\n            tryQuery(k, c);\n\n            if (en == s) break;\n        }\n    }\n\n    vector<vector<pair<int,int>>> ansEdges(M);\n\n    auto ekey = [](int a, int b) -> long long {\n        if (a > b) swap(a, b);\n        return ((long long)a << 32) ^ (unsigned int)b;\n    };\n\n    for (int k = 0; k < M; k++) {\n        int s = groups[k].size();\n\n        if (s <= 1) continue;\n\n        if (s == 2) {\n            ansEdges[k].push_back({groups[k][0], groups[k][1]});\n            continue;\n        }\n\n        if (exactWhole[k]) {\n            ansEdges[k] = queriedEdges[k];\n            continue;\n        }\n\n        unordered_set<long long> qset;\n        qset.reserve(queriedEdges[k].size() * 2 + 10);\n\n        for (auto [a, b] : queriedEdges[k]) qset.insert(ekey(a, b));\n\n        vector<Edge> edges;\n        edges.reserve(s * (s - 1) / 2);\n\n        for (int i = 0; i < s; i++) {\n            for (int j = i + 1; j < s; j++) {\n                int a = groups[k][i];\n                int b = groups[k][j];\n\n                long long w = iw[a][b];\n\n                if (qset.count(ekey(a, b))) w -= 550;\n\n                edges.push_back({a, b, w});\n            }\n        }\n\n        sort(edges.begin(), edges.end());\n\n        DSU dsu(N);\n\n        for (auto &e : edges) {\n            if ((int)ansEdges[k].size() == s - 1) break;\n\n            if (dsu.unite(e.u, e.v)) {\n                ansEdges[k].push_back({e.u, e.v});\n            }\n        }\n\n        for (int i = 0; i + 1 < s && (int)ansEdges[k].size() < s - 1; i++) {\n            if (dsu.unite(groups[k][i], groups[k][i + 1])) {\n                ansEdges[k].push_back({groups[k][i], groups[k][i + 1]});\n            }\n        }\n    }\n\n    cout << \"!\" << '\\n';\n\n    for (int k = 0; k < M; k++) {\n        for (int i = 0; i < (int)groups[k].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[k][i];\n        }\n\n        cout << '\\n';\n\n        for (auto [a, b] : ansEdges[k]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Action {\n    char a, d;\n};\n\nstruct Prev {\n    int pi = -1;\n    int pj = -1;\n    Action act;\n};\n\nint N, M;\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'};\n\nchrono::steady_clock::time_point START_TIME;\n\ndouble elapsed_sec() {\n    return chrono::duration<double>(chrono::steady_clock::now() - START_TIME).count();\n}\n\nbool inside(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nint dir_id(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\npair<int,int> slide_dest(int i, int j, int dir, const vector<vector<int>>& block) {\n    while (true) {\n        int ni = i + di[dir];\n        int nj = j + dj[dir];\n\n        if (!inside(ni, nj)) break;\n        if (block[ni][nj]) break;\n\n        i = ni;\n        j = nj;\n    }\n\n    return {i, j};\n}\n\nvector<Action> bfs_path(\n    pair<int,int> start,\n    pair<int,int> goal,\n    const vector<vector<int>>& block\n) {\n    vector<vector<int>> dist(N, vector<int>(N, -1));\n    vector<vector<Prev>> prv(N, vector<Prev>(N));\n\n    queue<pair<int,int>> q;\n    dist[start.first][start.second] = 0;\n    q.push(start);\n\n    while (!q.empty()) {\n        auto [i, j] = q.front();\n        q.pop();\n\n        if (i == goal.first && j == goal.second) break;\n\n        for (int dir = 0; dir < 4; dir++) {\n            // Move\n            {\n                int ni = i + di[dir];\n                int nj = j + dj[dir];\n\n                if (inside(ni, nj) && !block[ni][nj] && dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    prv[ni][nj] = {i, j, {'M', dc[dir]}};\n                    q.push({ni, nj});\n                }\n            }\n\n            // Slide\n            {\n                auto [ni, nj] = slide_dest(i, j, dir, block);\n\n                if ((ni != i || nj != j) && dist[ni][nj] == -1) {\n                    dist[ni][nj] = dist[i][j] + 1;\n                    prv[ni][nj] = {i, j, {'S', dc[dir]}};\n                    q.push({ni, nj});\n                }\n            }\n        }\n    }\n\n    vector<Action> path;\n\n    if (dist[goal.first][goal.second] == -1) {\n        return path;\n    }\n\n    int ci = goal.first;\n    int cj = goal.second;\n\n    while (!(ci == start.first && cj == start.second)) {\n        Prev pr = prv[ci][cj];\n        path.push_back(pr.act);\n        ci = pr.pi;\n        cj = pr.pj;\n    }\n\n    reverse(path.begin(), path.end());\n    return path;\n}\n\nbool apply_action(\n    pair<int,int>& pos,\n    vector<vector<int>>& block,\n    Action act\n) {\n    int dir = dir_id(act.d);\n\n    if (act.a == 'M') {\n        int ni = pos.first + di[dir];\n        int nj = pos.second + dj[dir];\n\n        if (!inside(ni, nj)) return false;\n        if (block[ni][nj]) return false;\n\n        pos = {ni, nj};\n        return true;\n    }\n\n    if (act.a == 'S') {\n        pos = slide_dest(pos.first, pos.second, dir, block);\n        return true;\n    }\n\n    if (act.a == 'A') {\n        int ni = pos.first + di[dir];\n        int nj = pos.second + dj[dir];\n\n        if (!inside(ni, nj)) return false;\n\n        block[ni][nj] ^= 1;\n        return true;\n    }\n\n    return false;\n}\n\nbool is_target_cell(const vector<pair<int,int>>& p, int i, int j) {\n    for (auto [x, y] : p) {\n        if (x == i && y == j) return true;\n    }\n    return false;\n}\n\nbool simulate_full(\n    const vector<pair<int,int>>& p,\n    const vector<Action>& ans\n) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    pair<int,int> pos = p[0];\n    int next_target = 1;\n\n    for (auto act : ans) {\n        if (!apply_action(pos, block, act)) {\n            return false;\n        }\n\n        if (next_target < M && pos == p[next_target]) {\n            next_target++;\n        }\n    }\n\n    return next_target == M;\n}\n\nvector<Action> baseline_solution(const vector<pair<int,int>>& p) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    vector<Action> ans;\n    pair<int,int> cur = p[0];\n\n    for (int t = 1; t < M; t++) {\n        auto path = bfs_path(cur, p[t], block);\n\n        for (auto a : path) {\n            ans.push_back(a);\n            apply_action(cur, block, a);\n        }\n    }\n\n    return ans;\n}\n\nvector<Action> construct_blocks(\n    pair<int,int>& cur,\n    vector<vector<int>>& block,\n    const vector<pair<int,int>>& wanted,\n    const vector<pair<int,int>>& p\n) {\n    vector<Action> res;\n\n    for (auto [bi, bj] : wanted) {\n        if (elapsed_sec() > 1.88) return {};\n        if (!inside(bi, bj)) continue;\n        if (block[bi][bj]) continue;\n        if (is_target_cell(p, bi, bj)) continue;\n\n        vector<Action> best;\n        bool found = false;\n\n        for (int dir = 0; dir < 4; dir++) {\n            int si = bi - di[dir];\n            int sj = bj - dj[dir];\n\n            if (!inside(si, sj)) continue;\n            if (block[si][sj]) continue;\n\n            auto path = bfs_path(cur, {si, sj}, block);\n\n            if (path.empty() && cur != make_pair(si, sj)) continue;\n\n            vector<Action> cand = path;\n            cand.push_back({'A', dc[dir]});\n\n            if (!found || cand.size() < best.size()) {\n                found = true;\n                best = cand;\n            }\n        }\n\n        if (!found) continue;\n\n        for (auto a : best) {\n            res.push_back(a);\n            bool ok = apply_action(cur, block, a);\n            if (!ok) return {};\n        }\n    }\n\n    return res;\n}\n\nvector<Action> solve_with_initial_blocks(\n    const vector<pair<int,int>>& p,\n    const vector<pair<int,int>>& wanted_blocks\n) {\n    vector<vector<int>> block(N, vector<int>(N, 0));\n    pair<int,int> cur = p[0];\n    vector<Action> ans;\n\n    auto build = construct_blocks(cur, block, wanted_blocks, p);\n\n    if (!wanted_blocks.empty() && build.empty()) {\n        return {};\n    }\n\n    ans.insert(ans.end(), build.begin(), build.end());\n\n    for (int t = 1; t < M; t++) {\n        if (elapsed_sec() > 1.88) return {};\n\n        auto goal = p[t];\n\n        if (block[goal.first][goal.second]) {\n            return {};\n        }\n\n        auto path = bfs_path(cur, goal, block);\n\n        if (path.empty() && cur != goal) {\n            return {};\n        }\n\n        for (auto a : path) {\n            ans.push_back(a);\n            bool ok = apply_action(cur, block, a);\n            if (!ok) return {};\n        }\n    }\n\n    return ans;\n}\n\nvector<pair<int,int>> unique_cells(vector<pair<int,int>> v) {\n    sort(v.begin(), v.end());\n    v.erase(unique(v.begin(), v.end()), v.end());\n    return v;\n}\n\nvoid add_candidate(\n    vector<vector<pair<int,int>>>& candidates,\n    vector<pair<int,int>> cells,\n    const vector<pair<int,int>>& p,\n    int max_size = 18\n) {\n    vector<pair<int,int>> filtered;\n\n    for (auto [i, j] : cells) {\n        if (!inside(i, j)) continue;\n        if (is_target_cell(p, i, j)) continue;\n        filtered.push_back({i, j});\n    }\n\n    filtered = unique_cells(filtered);\n\n    if (!filtered.empty() && (int)filtered.size() <= max_size) {\n        candidates.push_back(filtered);\n    }\n}\n\nint try_solution_eval(\n    const vector<pair<int,int>>& p,\n    const vector<pair<int,int>>& cells,\n    vector<Action>& best\n) {\n    auto ans = solve_with_initial_blocks(p, cells);\n\n    if (ans.empty()) return INT_MAX;\n    if ((int)ans.size() > 2 * N * M) return INT_MAX;\n    if (!simulate_full(p, ans)) return INT_MAX;\n\n    int len = (int)ans.size();\n\n    if (len < (int)best.size()) {\n        best = ans;\n    }\n\n    return len;\n}\n\nbool contains_cell(const vector<pair<int,int>>& v, pair<int,int> x) {\n    return binary_search(v.begin(), v.end(), x);\n}\n\nvoid refine_candidate(\n    const vector<pair<int,int>>& p,\n    vector<pair<int,int>> cells,\n    const vector<pair<int,int>>& top,\n    vector<Action>& best\n) {\n    cells = unique_cells(cells);\n\n    bool changed = true;\n\n    // Greedy deletion loop.\n    while (changed && elapsed_sec() < 1.73) {\n        changed = false;\n\n        for (int skip = 0; skip < (int)cells.size(); skip++) {\n            if (elapsed_sec() > 1.82) return;\n\n            vector<pair<int,int>> reduced;\n\n            for (int i = 0; i < (int)cells.size(); i++) {\n                if (i != skip) reduced.push_back(cells[i]);\n            }\n\n            int before = best.size();\n            int len = try_solution_eval(p, reduced, best);\n\n            if (len < before) {\n                cells = unique_cells(reduced);\n                changed = true;\n                break;\n            }\n        }\n    }\n\n    // Pair deletion for small prefix of the set.\n    if (elapsed_sec() < 1.76 && cells.size() >= 5) {\n        int lim = min<int>(cells.size(), 10);\n\n        for (int a = 0; a < lim; a++) {\n            if (elapsed_sec() > 1.82) return;\n\n            for (int b = a + 1; b < lim; b++) {\n                if (elapsed_sec() > 1.82) return;\n\n                vector<pair<int,int>> reduced;\n\n                for (int i = 0; i < (int)cells.size(); i++) {\n                    if (i != a && i != b) reduced.push_back(cells[i]);\n                }\n\n                try_solution_eval(p, reduced, best);\n            }\n        }\n    }\n\n    // Limited one-block addition from high-scoring blockers.\n    if (elapsed_sec() < 1.77) {\n        for (int k = 0; k < (int)top.size() && k < 12; k++) {\n            if (elapsed_sec() > 1.82) return;\n\n            auto add = top[k];\n\n            vector<pair<int,int>> cur = unique_cells(cells);\n\n            if (contains_cell(cur, add)) continue;\n\n            cur.push_back(add);\n            cur = unique_cells(cur);\n\n            if ((int)cur.size() > 18) continue;\n\n            try_solution_eval(p, cur, best);\n        }\n    }\n\n    // Swap mutation: remove one current block, add one high-score block.\n    if (elapsed_sec() < 1.78 && cells.size() >= 3) {\n        int max_remove = min<int>(cells.size(), 8);\n        int max_add = min<int>(top.size(), 10);\n\n        for (int r = 0; r < max_remove; r++) {\n            if (elapsed_sec() > 1.82) return;\n\n            for (int a = 0; a < max_add; a++) {\n                if (elapsed_sec() > 1.82) return;\n\n                vector<pair<int,int>> cur;\n\n                for (int i = 0; i < (int)cells.size(); i++) {\n                    if (i != r) cur.push_back(cells[i]);\n                }\n\n                auto sorted_cur = unique_cells(cur);\n\n                if (!contains_cell(sorted_cur, top[a])) {\n                    cur.push_back(top[a]);\n                }\n\n                cur = unique_cells(cur);\n\n                if ((int)cur.size() > 18) continue;\n\n                try_solution_eval(p, cur, best);\n            }\n        }\n    }\n}\n\nint main() {\n    START_TIME = chrono::steady_clock::now();\n\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> M;\n\n    vector<pair<int,int>> p(M);\n    for (int i = 0; i < M; i++) {\n        cin >> p[i].first >> p[i].second;\n    }\n\n    vector<Action> best = baseline_solution(p);\n\n    vector<vector<pair<int,int>>> candidates;\n    candidates.push_back({});\n\n    // Sparse lattice candidates.\n    for (int step : {5, 6, 7}) {\n        for (int oi = 1; oi < step; oi++) {\n            for (int oj = 1; oj < step; oj++) {\n                vector<pair<int,int>> cells;\n\n                for (int i = oi; i < N; i += step) {\n                    for (int j = oj; j < N; j += step) {\n                        cells.push_back({i, j});\n                    }\n                }\n\n                add_candidate(candidates, cells, p, 12);\n            }\n        }\n    }\n\n    vector<pair<int,int>> top;\n\n    // Route-aware target stopper scoring.\n    {\n        map<pair<int,int>, int> score;\n\n        for (int t = 1; t < M; t++) {\n            auto [gi, gj] = p[t];\n            auto [pi0, pj0] = p[t - 1];\n\n            for (int dir = 0; dir < 4; dir++) {\n                int bi = gi + di[dir];\n                int bj = gj + dj[dir];\n\n                if (!inside(bi, bj)) continue;\n                if (is_target_cell(p, bi, bj)) continue;\n\n                int val = 5;\n\n                int opp = dir ^ 1;\n                int len = 0;\n                int ci = gi + di[opp];\n                int cj = gj + dj[opp];\n\n                while (inside(ci, cj)) {\n                    len++;\n                    ci += di[opp];\n                    cj += dj[opp];\n                }\n\n                val += len;\n\n                if (dir <= 1) {\n                    if (pj0 == gj) val += 8;\n                    val += max(0, 5 - abs(pj0 - gj));\n                } else {\n                    if (pi0 == gi) val += 8;\n                    val += max(0, 5 - abs(pi0 - gi));\n                }\n\n                if (gi == 0 || gi == N - 1 || gj == 0 || gj == N - 1) {\n                    val -= 3;\n                }\n\n                for (int u = 1; u < M; u++) {\n                    if (u == t) continue;\n                    if (dir <= 1 && p[u].second == gj) val++;\n                    if (dir >= 2 && p[u].first == gi) val++;\n                }\n\n                score[{bi, bj}] += val;\n            }\n        }\n\n        vector<pair<int,pair<int,int>>> ord;\n\n        for (auto [cell, sc] : score) {\n            ord.push_back({-sc, cell});\n        }\n\n        sort(ord.begin(), ord.end());\n\n        for (int k = 0; k < (int)ord.size() && k < 30; k++) {\n            top.push_back(ord[k].second);\n        }\n\n        // Prefixes.\n        for (int lim : {3, 4, 5, 6, 7, 8, 10, 12, 14, 16}) {\n            vector<pair<int,int>> cells;\n            for (int k = 0; k < (int)top.size() && k < lim; k++) {\n                cells.push_back(top[k]);\n            }\n            add_candidate(candidates, cells, p, 18);\n        }\n\n        // Shifted windows.\n        for (int start : {1, 2, 3, 5, 8, 11}) {\n            for (int lim : {5, 7, 9, 11}) {\n                vector<pair<int,int>> cells;\n                for (int k = start; k < (int)top.size() && k < start + lim; k++) {\n                    cells.push_back(top[k]);\n                }\n                add_candidate(candidates, cells, p, 16);\n            }\n        }\n\n        // Even / odd / modulo subsets.\n        for (int mod : {2, 3, 4}) {\n            for (int rem = 0; rem < mod; rem++) {\n                vector<pair<int,int>> cells;\n                for (int k = 0; k < (int)top.size() && k < 24; k++) {\n                    if (k % mod == rem) cells.push_back(top[k]);\n                }\n                add_candidate(candidates, cells, p, 14);\n            }\n        }\n\n        // Prefix minus one variants.\n        for (int lim : {8, 10, 12, 14}) {\n            for (int skip = 0; skip < min(lim, (int)top.size()); skip++) {\n                vector<pair<int,int>> cells;\n                for (int k = 0; k < (int)top.size() && k < lim; k++) {\n                    if (k != skip) cells.push_back(top[k]);\n                }\n                add_candidate(candidates, cells, p, 16);\n            }\n        }\n    }\n\n    // Row/column rail candidates.\n    {\n        vector<int> rowcnt(N, 0), colcnt(N, 0);\n\n        for (int t = 1; t < M; t++) {\n            rowcnt[p[t].first]++;\n            colcnt[p[t].second]++;\n        }\n\n        vector<int> rows(N), cols(N);\n        iota(rows.begin(), rows.end(), 0);\n        iota(cols.begin(), cols.end(), 0);\n\n        sort(rows.begin(), rows.end(), [&](int a, int b) {\n            return rowcnt[a] > rowcnt[b];\n        });\n\n        sort(cols.begin(), cols.end(), [&](int a, int b) {\n            return colcnt[a] > colcnt[b];\n        });\n\n        for (int rcnt : {1, 2, 3}) {\n            for (int off = 2; off <= 5; off++) {\n                vector<pair<int,int>> cells;\n\n                for (int a = 0; a < rcnt; a++) {\n                    int r = rows[a];\n                    for (int c = off; c < N; c += 5) {\n                        cells.push_back({r, c});\n                    }\n                }\n\n                add_candidate(candidates, cells, p, 14);\n            }\n        }\n\n        for (int ccnt : {1, 2, 3}) {\n            for (int off = 2; off <= 5; off++) {\n                vector<pair<int,int>> cells;\n\n                for (int b = 0; b < ccnt; b++) {\n                    int c = cols[b];\n                    for (int r = off; r < N; r += 5) {\n                        cells.push_back({r, c});\n                    }\n                }\n\n                add_candidate(candidates, cells, p, 14);\n            }\n        }\n\n        for (int rcnt : {1, 2}) {\n            for (int ccnt : {1, 2}) {\n                for (int off = 2; off <= 5; off++) {\n                    vector<pair<int,int>> cells;\n\n                    for (int a = 0; a < rcnt; a++) {\n                        int r = rows[a];\n                        for (int c = off; c < N; c += 5) {\n                            cells.push_back({r, c});\n                        }\n                    }\n\n                    for (int b = 0; b < ccnt; b++) {\n                        int c = cols[b];\n                        for (int r = off; r < N; r += 5) {\n                            cells.push_back({r, c});\n                        }\n                    }\n\n                    add_candidate(candidates, cells, p, 16);\n                }\n            }\n        }\n    }\n\n    // Mixed lattice + top blockers.\n    if (!top.empty()) {\n        for (int step : {6, 7}) {\n            for (int oi = 1; oi < step; oi += 2) {\n                for (int oj = 1; oj < step; oj += 2) {\n                    vector<pair<int,int>> cells;\n\n                    for (int i = oi; i < N; i += step) {\n                        for (int j = oj; j < N; j += step) {\n                            cells.push_back({i, j});\n                        }\n                    }\n\n                    for (int k = 0; k < (int)top.size() && k < 4; k++) {\n                        cells.push_back(top[k]);\n                    }\n\n                    add_candidate(candidates, cells, p, 16);\n                }\n            }\n        }\n    }\n\n    // Remove duplicate candidates.\n    for (auto& c : candidates) {\n        c = unique_cells(c);\n    }\n\n    sort(candidates.begin(), candidates.end());\n    candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n    for (auto cells : candidates) {\n        if (elapsed_sec() > 1.82) break;\n\n        int old_best = best.size();\n        int len = try_solution_eval(p, cells, best);\n\n        if (elapsed_sec() > 1.72) continue;\n\n        // Refine if improved, or if reasonably close to the current best.\n        if (len < old_best || len <= (int)best.size() + 8) {\n            refine_candidate(p, cells, top, best);\n        }\n    }\n\n    if ((int)best.size() > 2 * N * M || !simulate_full(p, best)) {\n        best = baseline_solution(p);\n    }\n\n    for (auto [a, d] : best) {\n        cout << a << ' ' << d << '\\n';\n    }\n\n    return 0;\n}"}}}