{"model_name":"gpt-5.4-none","codes":{"1":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int LIM = 10000;\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nstruct Input {\n    int x, y;\n    int r;\n};\n\nstatic inline bool overlap1D(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstatic inline bool overlap2D(const Rect& p, const Rect& q) {\n    return overlap1D(p.a, p.c, q.a, q.c) && overlap1D(p.b, p.d, q.b, q.d);\n}\n\nstatic inline long long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\nstatic inline double score_one(long long s, long long r) {\n    double t = (double)min(s, r) / (double)max(s, r);\n    double u = 1.0 - t;\n    return 1.0 - u * u;\n}\n\nstruct Solver {\n    int n;\n    vector<Input> in;\n    vector<Rect> rects;\n    mt19937 rng;\n\n    Solver(int n_, vector<Input> in_) : n(n_), in(std::move(in_)) {\n        rng.seed((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n        rects.resize(n);\n        for (int i = 0; i < n; i++) {\n            rects[i] = {in[i].x, in[i].y, in[i].x + 1, in[i].y + 1};\n        }\n    }\n\n    double gain_if(const Rect& oldr, const Rect& newr, int i) {\n        long long s0 = area(oldr);\n        long long s1 = area(newr);\n        return score_one(s1, in[i].r) - score_one(s0, in[i].r);\n    }\n\n    // max expandable cells in each direction without overlap\n    int max_left(int i) {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && q.c <= r.a) {\n                bound = max(bound, q.c);\n            }\n        }\n        return r.a - bound;\n    }\n\n    int max_right(int i) {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && r.c <= q.a) {\n                bound = min(bound, q.a);\n            }\n        }\n        return bound - r.c;\n    }\n\n    int max_down(int i) {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && q.d <= r.b) {\n                bound = max(bound, q.d);\n            }\n        }\n        return r.b - bound;\n    }\n\n    int max_up(int i) {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && r.d <= q.b) {\n                bound = min(bound, q.b);\n            }\n        }\n        return bound - r.d;\n    }\n\n    void try_expand_best(int i) {\n        Rect cur = rects[i];\n        long long curA = area(cur);\n        long long target = in[i].r;\n        double bestGain = 1e-18;\n        Rect bestRect = cur;\n\n        auto eval_dir = [&](int dir, int lim) {\n            if (lim <= 0) return;\n            int w = cur.c - cur.a;\n            int h = cur.d - cur.b;\n\n            vector<int> cand;\n            cand.push_back(1);\n            cand.push_back(lim);\n\n            if (dir == 0 || dir == 1) { // left/right, area += h * t\n                if (curA < target) {\n                    int need = (int)((target - curA + h - 1) / h);\n                    for (int dt = -2; dt <= 2; dt++) {\n                        int t = need + dt;\n                        if (1 <= t && t <= lim) cand.push_back(t);\n                    }\n                }\n            } else { // down/up, area += w * t\n                if (curA < target) {\n                    int need = (int)((target - curA + w - 1) / w);\n                    for (int dt = -2; dt <= 2; dt++) {\n                        int t = need + dt;\n                        if (1 <= t && t <= lim) cand.push_back(t);\n                    }\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n            for (int t : cand) {\n                Rect nxt = cur;\n                if (dir == 0) nxt.a -= t;      // left\n                if (dir == 1) nxt.c += t;      // right\n                if (dir == 2) nxt.b -= t;      // down\n                if (dir == 3) nxt.d += t;      // up\n\n                double g = gain_if(cur, nxt, i);\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestRect = nxt;\n                }\n            }\n        };\n\n        eval_dir(0, max_left(i));\n        eval_dir(1, max_right(i));\n        eval_dir(2, max_down(i));\n        eval_dir(3, max_up(i));\n\n        if (bestGain > 1e-15) rects[i] = bestRect;\n    }\n\n    void micro_adjust_pass(const vector<int>& ord) {\n        for (int i : ord) {\n            Rect cur = rects[i];\n            double bestGain = 1e-18;\n            Rect bestRect = cur;\n\n            auto try_one = [&](Rect nxt) {\n                double g = gain_if(cur, nxt, i);\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestRect = nxt;\n                }\n            };\n\n            if (max_left(i)  >= 1) { Rect t = cur; t.a--; try_one(t); }\n            if (max_right(i) >= 1) { Rect t = cur; t.c++; try_one(t); }\n            if (max_down(i)  >= 1) { Rect t = cur; t.b--; try_one(t); }\n            if (max_up(i)    >= 1) { Rect t = cur; t.d++; try_one(t); }\n\n            if (bestGain > 1e-15) rects[i] = bestRect;\n        }\n    }\n\n    void solve() {\n        auto st = chrono::steady_clock::now();\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n\n        int phase = 0;\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - st).count();\n            if (elapsed > 4.7) break;\n\n            shuffle(ord.begin(), ord.end(), rng);\n            bool updated = false;\n\n            for (int i : ord) {\n                Rect before = rects[i];\n                try_expand_best(i);\n                if (rects[i].a != before.a || rects[i].b != before.b ||\n                    rects[i].c != before.c || rects[i].d != before.d) {\n                    updated = true;\n                }\n            }\n\n            phase++;\n            if (!updated && phase > 10) break;\n        }\n\n        // remaining time for micro adjustment\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - st).count();\n            if (elapsed > 4.95) break;\n            shuffle(ord.begin(), ord.end(), rng);\n            micro_adjust_pass(ord);\n        }\n    }\n\n    void output() {\n        for (int i = 0; i < n; i++) {\n            cout << rects[i].a << ' ' << rects[i].b << ' ' << rects[i].c << ' ' << rects[i].d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Input> in(n);\n    for (int i = 0; i < n; i++) {\n        cin >> in[i].x >> in[i].y >> in[i].r;\n    }\n\n    Solver solver(n, in);\n    solver.solve();\n    solver.output();\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int INF = 1e9;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { // [l, r)\n        return l + (int)(next_u32() % (uint32_t)(r - l));\n    }\n    double next_double() {\n        return (double)next_u32() / (double)UINT32_MAX;\n    }\n};\n\nstruct Param {\n    double w_gain;\n    double w_future;\n    double w_mob;\n    double w_dead;\n    double noise;\n    int bfs_depth;\n    int bfs_cap;\n};\n\nint si, sj;\nint tile_id[N][N];\nint valv[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\nvector<pair<int,int>> cells_of_tile[2500];\nint tile_cnt = 0;\n\nint vis_cell_stamp[N][N];\nint global_stamp = 1;\n\ninline bool inb(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nstruct Candidate {\n    int dir;\n    double score;\n};\n\ndouble bounded_bfs_eval(\n    int si, int sj,\n    const vector<unsigned char>& usedTile,\n    int depth_limit,\n    int node_cap\n) {\n    ++global_stamp;\n    if (global_stamp == INT_MAX) {\n        memset(vis_cell_stamp, 0, sizeof(vis_cell_stamp));\n        global_stamp = 1;\n    }\n\n    static int dista[N][N];\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    vis_cell_stamp[si][sj] = global_stamp;\n    dista[si][sj] = 0;\n\n    static const double decay[32] = {\n        1.0,\n        0.92, 0.85, 0.79, 0.73, 0.68, 0.63, 0.58,\n        0.54, 0.50, 0.46, 0.43, 0.40, 0.37, 0.34, 0.31,\n        0.29, 0.27, 0.25, 0.23, 0.21, 0.20, 0.19, 0.18,\n        0.17, 0.16, 0.15, 0.14, 0.13, 0.12, 0.11, 0.10\n    };\n\n    double score = 0.0;\n    int seen = 0;\n    int frontier_bonus = 0;\n\n    while (!q.empty() && seen < node_cap) {\n        auto [i, j] = q.front(); q.pop();\n        int d = dista[i][j];\n        ++seen;\n\n        if (d > 0) {\n            score += valv[i][j] * decay[min(d, 31)];\n        }\n\n        int local_moves = 0;\n        if (d < depth_limit) {\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (!inb(ni, nj)) continue;\n                int tid = tile_id[ni][nj];\n                if (usedTile[tid]) continue;\n                local_moves++;\n                if (vis_cell_stamp[ni][nj] == global_stamp) continue;\n                vis_cell_stamp[ni][nj] = global_stamp;\n                dista[ni][nj] = d + 1;\n                q.push({ni, nj});\n            }\n        }\n        frontier_bonus += local_moves;\n    }\n\n    score += 1.2 * frontier_bonus;\n    score += 0.5 * seen;\n    return score;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    int max_tid = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tile_id[i][j];\n            max_tid = max(max_tid, tile_id[i][j]);\n        }\n    }\n    tile_cnt = max_tid + 1;\n    for (int i = 0; i < tile_cnt; ++i) cells_of_tile[i].clear();\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cells_of_tile[tile_id[i][j]].push_back({i,j});\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> valv[i][j];\n        }\n    }\n\n    Timer timer;\n    XorShift rng;\n\n    vector<Param> params = {\n        {1.00, 0.070, 10.0, 20.0, 3.0, 10, 120},\n        {1.15, 0.060,  8.0, 18.0, 4.0,  9, 100},\n        {0.90, 0.090, 12.0, 25.0, 2.5, 12, 140},\n        {1.25, 0.050,  6.0, 15.0, 5.0,  8,  90},\n        {0.95, 0.100, 14.0, 28.0, 2.0, 13, 150},\n    };\n\n    string best_path;\n    int best_score = valv[si][sj];\n\n    vector<unsigned char> usedTile(tile_cnt, 0);\n\n    while (timer.elapsed() < 1.95) {\n        Param par = params[rng.next_int(0, (int)params.size())];\n\n        // small random perturbation\n        par.w_gain += (rng.next_double() - 0.5) * 0.20;\n        par.w_future += (rng.next_double() - 0.5) * 0.03;\n        par.w_mob += (rng.next_double() - 0.5) * 4.0;\n        par.w_dead += (rng.next_double() - 0.5) * 8.0;\n\n        fill(usedTile.begin(), usedTile.end(), 0);\n\n        int ci = si, cj = sj;\n        int cur_score = valv[ci][cj];\n        string path;\n        usedTile[tile_id[ci][cj]] = 1;\n\n        while (true) {\n            Candidate best{-1, -1e100};\n            vector<Candidate> cand_list;\n\n            for (int d = 0; d < 4; ++d) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (!inb(ni, nj)) continue;\n                int tid = tile_id[ni][nj];\n                if (usedTile[tid]) continue;\n\n                usedTile[tid] = 1;\n\n                int mobility = 0;\n                for (int k = 0; k < 4; ++k) {\n                    int xi = ni + di[k], xj = nj + dj[k];\n                    if (!inb(xi, xj)) continue;\n                    int t2 = tile_id[xi][xj];\n                    if (!usedTile[t2]) mobility++;\n                }\n\n                double future = bounded_bfs_eval(ni, nj, usedTile, par.bfs_depth, par.bfs_cap);\n\n                double dead_penalty = (mobility == 0 ? 1.0 : 0.0);\n                double sc = 0.0;\n                sc += par.w_gain * valv[ni][nj];\n                sc += par.w_future * future;\n                sc += par.w_mob * mobility;\n                sc -= par.w_dead * dead_penalty;\n                sc += (rng.next_double() - 0.5) * par.noise;\n\n                usedTile[tid] = 0;\n\n                cand_list.push_back({d, sc});\n                if (sc > best.score) best = {d, sc};\n            }\n\n            if (cand_list.empty()) break;\n\n            // randomized selection among top few\n            sort(cand_list.begin(), cand_list.end(), [](const Candidate& a, const Candidate& b) {\n                return a.score > b.score;\n            });\n\n            int take = 0;\n            if ((int)cand_list.size() >= 2 && rng.next_double() < 0.20) take = 1;\n            if ((int)cand_list.size() >= 3 && rng.next_double() < 0.08) take = 2;\n            int dir = cand_list[take].dir;\n\n            ci += di[dir];\n            cj += dj[dir];\n            path.push_back(dc[dir]);\n            usedTile[tile_id[ci][cj]] = 1;\n            cur_score += valv[ci][cj];\n        }\n\n        if (cur_score > best_score) {\n            best_score = cur_score;\n            best_path = path;\n        }\n    }\n\n    cout << best_path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HN = 29; // horizontal edges per row\nstatic constexpr int VN = 29; // vertical edges per col\nstatic constexpr double INIT_COST = 5000.0;\nstatic constexpr double MIN_COST = 500.0;\nstatic constexpr double MAX_COST = 9500.0;\n\nstruct EdgeRef {\n    bool horiz; // true: h[i][j] between (i,j) and (i,j+1), false: v[i][j] between (i,j) and (i+1,j)\n    int i, j;\n};\n\nstruct Solver {\n    // current local edge estimates\n    double h_est[N][HN];\n    double v_est[VN][N];\n\n    // traversal stats\n    double h_sum[N][HN], v_sum[VN][N];\n    int h_cnt[N][HN], v_cnt[VN][N];\n\n    // segmented priors\n    double h_prior[N][HN];\n    double v_prior[VN][N];\n\n    int turn = 0;\n\n    Solver() {\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = INIT_COST;\n                h_sum[i][j] = 0.0;\n                h_cnt[i][j] = 0;\n                h_prior[i][j] = INIT_COST;\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = INIT_COST;\n                v_sum[i][j] = 0.0;\n                v_cnt[i][j] = 0;\n                v_prior[i][j] = INIT_COST;\n            }\n        }\n    }\n\n    static double clamp_cost(double x) {\n        if (x < MIN_COST) return MIN_COST;\n        if (x > MAX_COST) return MAX_COST;\n        return x;\n    }\n\n    // Fit 1-or-2 segment piecewise constant model to each row/column using current local estimates.\n    void rebuild_priors() {\n        // Horizontal rows: 29 values each\n        for (int i = 0; i < N; i++) {\n            double a[HN];\n            for (int j = 0; j < HN; j++) a[j] = h_est[i][j];\n\n            // Prefix sums for SSE\n            double ps[HN + 1] = {}, ps2[HN + 1] = {};\n            for (int j = 0; j < HN; j++) {\n                ps[j + 1] = ps[j] + a[j];\n                ps2[j + 1] = ps2[j] + a[j] * a[j];\n            }\n            auto seg_cost = [&](int l, int r) -> pair<double,double> { // [l,r)\n                double s = ps[r] - ps[l];\n                double s2 = ps2[r] - ps2[l];\n                int len = r - l;\n                double mean = s / len;\n                double cost = s2 - 2 * mean * s + len * mean * mean;\n                return {cost, mean};\n            };\n\n            // one segment\n            auto [bestCost1, mean1] = seg_cost(0, HN);\n            double bestCost = bestCost1;\n            int bestSplit = -1;\n            double bestL = mean1, bestR = mean1;\n\n            // two segments\n            for (int sp = 1; sp < HN; sp++) {\n                auto [c1, m1] = seg_cost(0, sp);\n                auto [c2, m2] = seg_cost(sp, HN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestL = m1;\n                    bestR = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int j = 0; j < HN; j++) h_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int j = 0; j < bestSplit; j++) h_prior[i][j] = clamp_cost(bestL);\n                for (int j = bestSplit; j < HN; j++) h_prior[i][j] = clamp_cost(bestR);\n            }\n        }\n\n        // Vertical columns: 29 values each for each col\n        for (int j = 0; j < N; j++) {\n            double a[VN];\n            for (int i = 0; i < VN; i++) a[i] = v_est[i][j];\n\n            double ps[VN + 1] = {}, ps2[VN + 1] = {};\n            for (int i = 0; i < VN; i++) {\n                ps[i + 1] = ps[i] + a[i];\n                ps2[i + 1] = ps2[i] + a[i] * a[i];\n            }\n            auto seg_cost = [&](int l, int r) -> pair<double,double> {\n                double s = ps[r] - ps[l];\n                double s2 = ps2[r] - ps2[l];\n                int len = r - l;\n                double mean = s / len;\n                double cost = s2 - 2 * mean * s + len * mean * mean;\n                return {cost, mean};\n            };\n\n            auto [bestCost1, mean1] = seg_cost(0, VN);\n            double bestCost = bestCost1;\n            int bestSplit = -1;\n            double bestU = mean1, bestD = mean1;\n\n            for (int sp = 1; sp < VN; sp++) {\n                auto [c1, m1] = seg_cost(0, sp);\n                auto [c2, m2] = seg_cost(sp, VN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestU = m1;\n                    bestD = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int i = 0; i < VN; i++) v_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int i = 0; i < bestSplit; i++) v_prior[i][j] = clamp_cost(bestU);\n                for (int i = bestSplit; i < VN; i++) v_prior[i][j] = clamp_cost(bestD);\n            }\n        }\n    }\n\n    double blended_h(int i, int j) const {\n        // Early: stronger prior. Later: stronger local.\n        double alpha = min(0.85, 0.15 + 0.7 * turn / 1000.0); // weight of local\n        return alpha * h_est[i][j] + (1.0 - alpha) * h_prior[i][j];\n    }\n\n    double blended_v(int i, int j) const {\n        double alpha = min(0.85, 0.15 + 0.7 * turn / 1000.0);\n        return alpha * v_est[i][j] + (1.0 - alpha) * v_prior[i][j];\n    }\n\n    int vid(int i, int j) const { return i * N + j; }\n    pair<int,int> pos(int id) const { return {id / N, id % N}; }\n\n    pair<string, vector<EdgeRef>> shortest_path(int si, int sj, int ti, int tj) {\n        const int V = N * N;\n        vector<double> dist(V, 1e100);\n        vector<int> prev(V, -1);\n        vector<char> prevMove(V, '?');\n\n        using P = pair<double,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        int s = vid(si, sj), t = vid(ti, tj);\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == t) break;\n            auto [i, j] = pos(u);\n\n            // U\n            if (i > 0) {\n                int ni = i - 1, nj = j;\n                int v = vid(ni, nj);\n                double w = blended_v(ni, nj);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'U';\n                    pq.push({dist[v], v});\n                }\n            }\n            // D\n            if (i + 1 < N) {\n                int ni = i + 1, nj = j;\n                int v = vid(ni, nj);\n                double w = blended_v(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'D';\n                    pq.push({dist[v], v});\n                }\n            }\n            // L\n            if (j > 0) {\n                int ni = i, nj = j - 1;\n                int v = vid(ni, nj);\n                double w = blended_h(i, nj);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'L';\n                    pq.push({dist[v], v});\n                }\n            }\n            // R\n            if (j + 1 < N) {\n                int ni = i, nj = j + 1;\n                int v = vid(ni, nj);\n                double w = blended_h(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'R';\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        string path;\n        vector<EdgeRef> edges_rev;\n        int cur = t;\n        while (cur != s) {\n            char mv = prevMove[cur];\n            path.push_back(mv);\n            auto [i, j] = pos(cur);\n            if (mv == 'U') {\n                // prev = (i+1, j), traversed vertical edge at (i, j)\n                edges_rev.push_back({false, i, j});\n            } else if (mv == 'D') {\n                // prev = (i-1, j), traversed vertical edge at (i-1, j)\n                edges_rev.push_back({false, i - 1, j});\n            } else if (mv == 'L') {\n                // prev = (i, j+1), traversed horizontal edge at (i, j)\n                edges_rev.push_back({true, i, j});\n            } else if (mv == 'R') {\n                // prev = (i, j-1), traversed horizontal edge at (i, j - 1)\n                edges_rev.push_back({true, i, j - 1});\n            } else {\n                // Should never happen\n                break;\n            }\n            cur = prev[cur];\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges_rev.begin(), edges_rev.end());\n        return {path, edges_rev};\n    }\n\n    double path_pred_cost(const vector<EdgeRef>& edges) const {\n        double s = 0.0;\n        for (auto &e : edges) {\n            if (e.horiz) s += blended_h(e.i, e.j);\n            else s += blended_v(e.i, e.j);\n        }\n        return s;\n    }\n\n    void update_from_feedback(const vector<EdgeRef>& edges, int observed) {\n        if (edges.empty()) return;\n\n        double pred = path_pred_cost(edges);\n        pred = max(pred, 1.0);\n        double ratio = observed / pred;\n\n        // multiplicative-noise robust clipping\n        ratio = max(0.8, min(1.25, ratio));\n\n        int L = (int)edges.size();\n        double avg_obs = 1.0 * observed / L;\n\n        // learning rates\n        double lr_mult = (turn < 100 ? 0.22 : turn < 300 ? 0.16 : 0.12);\n        double lr_avg  = (turn < 100 ? 0.050 : 0.030);\n\n        for (auto &e : edges) {\n            if (e.horiz) {\n                double cur = h_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = avg_obs;\n                double nv = cur * (1.0 - lr_mult) + target1 * lr_mult;\n                nv = nv * (1.0 - lr_avg) + target2 * lr_avg;\n                nv = clamp_cost(nv);\n\n                h_est[e.i][e.j] = nv;\n                h_sum[e.i][e.j] += avg_obs;\n                h_cnt[e.i][e.j] += 1;\n            } else {\n                double cur = v_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = avg_obs;\n                double nv = cur * (1.0 - lr_mult) + target1 * lr_mult;\n                nv = nv * (1.0 - lr_avg) + target2 * lr_avg;\n                nv = clamp_cost(nv);\n\n                v_est[e.i][e.j] = nv;\n                v_sum[e.i][e.j] += avg_obs;\n                v_cnt[e.i][e.j] += 1;\n            }\n        }\n\n        // gentle denoising toward empirical means if enough samples\n        for (auto &e : edges) {\n            if (e.horiz) {\n                if (h_cnt[e.i][e.j] >= 3) {\n                    double mean = h_sum[e.i][e.j] / h_cnt[e.i][e.j];\n                    h_est[e.i][e.j] = clamp_cost(0.9 * h_est[e.i][e.j] + 0.1 * mean);\n                }\n            } else {\n                if (v_cnt[e.i][e.j] >= 3) {\n                    double mean = v_sum[e.i][e.j] / v_cnt[e.i][e.j];\n                    v_est[e.i][e.j] = clamp_cost(0.9 * v_est[e.i][e.j] + 0.1 * mean);\n                }\n            }\n        }\n\n        // rebuild segmented priors every turn; cheap enough\n        rebuild_priors();\n\n        // global smoothing toward prior\n        double smooth = (turn < 150 ? 0.06 : 0.03);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = clamp_cost((1.0 - smooth) * h_est[i][j] + smooth * h_prior[i][j]);\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = clamp_cost((1.0 - smooth) * v_est[i][j] + smooth * v_prior[i][j]);\n            }\n        }\n    }\n\n    void solve() {\n        rebuild_priors();\n\n        for (turn = 0; turn < 1000; turn++) {\n            int si, sj, ti, tj;\n            cin >> si >> sj >> ti >> tj;\n\n            auto [path, edges] = shortest_path(si, sj, ti, tj);\n            cout << path << '\\n';\n            cout.flush();\n\n            int observed;\n            cin >> observed;\n\n            update_from_feedback(edges, observed);\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}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int randint(int l, int r) { // inclusive\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n    double rand01() {\n        return (next() >> 11) * (1.0 / (1ull << 53));\n    }\n} rng;\n\nstruct Pattern {\n    string s;\n    int w;\n};\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed() const {\n        auto ed = chrono::steady_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nint M_input;\nvector<string> input_strings;\nvector<Pattern> pats;\n\ninline int ch_id(char c) { return c - 'A'; }\n\nbool contains_cyclic_line(const string& line, const string& s) {\n    int L = (int)s.size();\n    for (int st = 0; st < N; st++) {\n        bool ok = true;\n        for (int k = 0; k < L; k++) {\n            if (line[(st + k) % N] != s[k]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n    return false;\n}\n\nint evaluate_grid(const vector<string>& g) {\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] = g[i][j];\n    }\n\n    int score = 0;\n    for (auto &p : pats) {\n        bool ok = false;\n        for (int i = 0; i < N && !ok; i++) {\n            if (contains_cyclic_line(g[i], p.s)) ok = true;\n        }\n        for (int j = 0; j < N && !ok; j++) {\n            if (contains_cyclic_line(cols[j], p.s)) ok = true;\n        }\n        if (ok) score += p.w;\n    }\n    return score;\n}\n\nvector<int> covered_by_rows(const vector<string>& rows) {\n    vector<int> covered((int)pats.size(), 0);\n    for (int idx = 0; idx < (int)pats.size(); idx++) {\n        for (int i = 0; i < (int)rows.size(); i++) {\n            if (contains_cyclic_line(rows[i], pats[idx].s)) {\n                covered[idx] = 1;\n                break;\n            }\n        }\n    }\n    return covered;\n}\n\nint place_gain(const string& row, const vector<int>& fixed, const string& s, int pos) {\n    int gain = 0;\n    for (int k = 0; k < (int)s.size(); k++) {\n        int p = (pos + k) % N;\n        if (!fixed[p]) gain++;\n        else if (row[p] != s[k]) return -1;\n    }\n    return gain;\n}\n\nstring build_one_row(const vector<int>& already_covered) {\n    string row(N, '?');\n    vector<int> fixed(N, 0);\n\n    // Greedy placements\n    for (int iter = 0; iter < 60; iter++) {\n        long long bestScore = -1;\n        int bestPid = -1, bestPos = -1;\n\n        for (int pid = 0; pid < (int)pats.size(); pid++) {\n            const auto& p = pats[pid];\n            long long baseVal = 1LL * p.w * (int)p.s.size() * (int)p.s.size();\n            if (already_covered[pid]) baseVal /= 4; // still useful, but less priority\n\n            for (int pos = 0; pos < N; pos++) {\n                int gain = place_gain(row, fixed, p.s, pos);\n                if (gain < 0) continue;\n                long long sc = baseVal + 3LL * gain;\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestPid = pid;\n                    bestPos = pos;\n                }\n            }\n        }\n\n        if (bestPid == -1) break;\n        if (bestScore <= 0) break;\n\n        const string& s = pats[bestPid].s;\n        for (int k = 0; k < (int)s.size(); k++) {\n            int p = (bestPos + k) % N;\n            row[p] = s[k];\n            fixed[p] = 1;\n        }\n    }\n\n    // Frequency-based fill for remaining cells\n    array<array<long long, 8>, N> freq{};\n    for (int pos = 0; pos < N; pos++) for (int c = 0; c < 8; c++) freq[pos][c] = 1;\n\n    for (int pid = 0; pid < (int)pats.size(); pid++) {\n        const auto& p = pats[pid];\n        long long mult = p.w;\n        if (!already_covered[pid]) mult *= 3;\n        for (int st = 0; st < N; st++) {\n            bool ok = true;\n            for (int k = 0; k < (int)p.s.size(); k++) {\n                int pp = (st + k) % N;\n                if (fixed[pp] && row[pp] != p.s[k]) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (!ok) continue;\n            for (int k = 0; k < (int)p.s.size(); k++) {\n                int pp = (st + k) % N;\n                freq[pp][ch_id(p.s[k])] += mult;\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (!fixed[i]) {\n            int bestc = 0;\n            for (int c = 1; c < 8; c++) {\n                if (freq[i][c] > freq[i][bestc]) bestc = c;\n            }\n            row[i] = char('A' + bestc);\n            fixed[i] = 1;\n        }\n    }\n    return row;\n}\n\nvector<string> build_initial_grid() {\n    vector<string> rows;\n    rows.reserve(N);\n    vector<int> covered((int)pats.size(), 0);\n\n    for (int r = 0; r < N; r++) {\n        string row = build_one_row(covered);\n        rows.push_back(row);\n        covered = covered_by_rows(rows);\n    }\n    return rows;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin;\n    cin >> Nin >> M_input;\n    input_strings.resize(M_input);\n    for (int i = 0; i < M_input; i++) cin >> input_strings[i];\n\n    unordered_map<string, int> mp;\n    mp.reserve(M_input * 2);\n    for (auto &s : input_strings) mp[s]++;\n\n    pats.clear();\n    pats.reserve(mp.size());\n    for (auto &kv : mp) pats.push_back({kv.first, kv.second});\n\n    sort(pats.begin(), pats.end(), [](const Pattern& a, const Pattern& b) {\n        long long \u10e1\u10d0 = 1LL * a.w * (int)a.s.size() * (int)a.s.size();\n        long long \u10e1b = 1LL * b.w * (int)b.s.size() * (int)b.s.size();\n        if (\u10e1\u10d0 != \u10e1b) return \u10e1\u10d0 > \u10e1b;\n        if (a.s.size() != b.s.size()) return a.s.size() > b.s.size();\n        return a.s < b.s;\n    });\n\n    Timer timer;\n\n    vector<string> best = build_initial_grid();\n    int bestScore = evaluate_grid(best);\n\n    vector<string> cur = best;\n    int curScore = bestScore;\n\n    // Small random diversification: shuffle a few rows and rebuild if time permits\n    while (timer.elapsed() < 0.6) {\n        vector<string> cand = build_initial_grid();\n        int sc = evaluate_grid(cand);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = cand;\n            cur = cand;\n            curScore = sc;\n        }\n    }\n\n    cur = best;\n    curScore = bestScore;\n\n    // Hill climbing / local search\n    while (timer.elapsed() < 2.95) {\n        int i = rng.randint(0, N - 1);\n        int j = rng.randint(0, N - 1);\n        char oldc = cur[i][j];\n\n        char bestc = oldc;\n        int localBest = curScore;\n\n        // Try all letters sometimes, otherwise random subset\n        int tries = 8;\n        array<int, 8> ord{};\n        iota(ord.begin(), ord.end(), 0);\n        shuffle(ord.begin(), ord.end(), std::mt19937((unsigned)rng.next()));\n\n        for (int t = 0; t < tries; t++) {\n            char nc = char('A' + ord[t]);\n            if (nc == oldc) continue;\n            cur[i][j] = nc;\n            int sc = evaluate_grid(cur);\n            if (sc > localBest || (sc == localBest && rng.rand01() < 0.1)) {\n                localBest = sc;\n                bestc = nc;\n            }\n        }\n\n        cur[i][j] = bestc;\n        curScore = localBest;\n\n        if (curScore > bestScore) {\n            bestScore = curScore;\n            best = cur;\n        } else if (bestc == oldc) {\n            // occasional kick\n            if (rng.rand01() < 0.02) {\n                cur[i][j] = char('A' + rng.randint(0, 7));\n                curScore = evaluate_grid(cur);\n                if (curScore > bestScore) {\n                    bestScore = curScore;\n                    best = cur;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best[i] << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC005 - heuristic solution\n\nIdea:\n- Compress the road graph into \"important\" cells:\n  * start cell\n  * intersections / dead-ends / corners (degree != 2 or not straight)\n- Between important cells connected by a straight corridor, build an edge with travel cost\n  equal to sum of entering costs along the corridor.\n- Visibility:\n  From a cell, the whole straight maximal road segment in each of 4 directions is visible.\n  In the generated instances, covering all \"important cells\" is usually enough to cover all roads\n  when we consider line-of-sight from those cells; more precisely, we greedily select important cells\n  whose visibility covers yet-uncovered road cells.\n- Then solve on the compressed graph:\n  Need a closed walk starting/ending at start visiting selected important nodes.\n  We build metric closure (all-pairs shortest paths on compressed graph),\n  then repeatedly insert uncovered targets into a current tour at minimum incremental cost.\n  Finally expand the tour back to moves on the grid.\n\nThis is not optimal, but is fast and robust.\n*/\n\nstatic const int INF = 1e9;\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, si, sj;\n    cin >> N >> si >> sj;\n    vector<string> c(N);\n    for (int i = 0; i < N; i++) cin >> c[i];\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n    auto road = [&](int x, int y) -> bool {\n        return inb(x, y) && c[x][y] != '#';\n    };\n    auto wcell = [&](int x, int y) -> int {\n        return c[x][y] - '0';\n    };\n\n    vector<Pos> roads;\n    vector<vector<int>> road_id(N, vector<int>(N, -1));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (road(i, j)) {\n            road_id[i][j] = (int)roads.size();\n            roads.push_back({i, j});\n        }\n    }\n    int R = (int)roads.size();\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    // Degree on grid road graph\n    vector<vector<int>> deg(N, vector<int>(N, 0));\n    for (auto &p : roads) {\n        int d = 0;\n        for (int k = 0; k < 4; k++) {\n            int nx = p.x + dx[k], ny = p.y + dy[k];\n            if (road(nx, ny)) d++;\n        }\n        deg[p.x][p.y] = d;\n    }\n\n    auto is_important = [&](int x, int y) -> bool {\n        if (x == si && y == sj) return true;\n        int d = deg[x][y];\n        if (d != 2) return true;\n        bool ud = road(x - 1, y) && road(x + 1, y);\n        bool lr = road(x, y - 1) && road(x, y + 1);\n        if (ud || lr) return false; // straight corridor cell\n        return true; // corner\n    };\n\n    vector<Pos> nodes;\n    vector<vector<int>> node_id(N, vector<int>(N, -1));\n    for (auto &p : roads) {\n        if (is_important(p.x, p.y)) {\n            node_id[p.x][p.y] = (int)nodes.size();\n            nodes.push_back(p);\n        }\n    }\n    int M = (int)nodes.size();\n\n    int start_node = node_id[si][sj];\n\n    struct Edge {\n        int to;\n        int cost;\n        vector<Pos> path; // sequence of cells after current node, including destination\n    };\n    vector<vector<Edge>> g(M);\n\n    // Build compressed graph by extending from each important node along each direction.\n    for (int id = 0; id < M; id++) {\n        auto [x, y] = nodes[id];\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            if (!road(nx, ny)) continue;\n\n            vector<Pos> path;\n            int cost = 0;\n            int px = x, py = y;\n            int cx = nx, cy = ny;\n            cost += wcell(cx, cy);\n            path.push_back({cx, cy});\n\n            while (true) {\n                if (node_id[cx][cy] != -1) {\n                    int to = node_id[cx][cy];\n                    g[id].push_back({to, cost, path});\n                    break;\n                }\n                // corridor cell: continue to the next road cell excluding previous\n                int tx = -1, ty = -1;\n                for (int k = 0; k < 4; k++) {\n                    int xx = cx + dx[k], yy = cy + dy[k];\n                    if (!road(xx, yy)) continue;\n                    if (xx == px && yy == py) continue;\n                    tx = xx; ty = yy;\n                    break;\n                }\n                if (tx == -1) break; // should not happen\n                px = cx; py = cy;\n                cx = tx; cy = ty;\n                cost += wcell(cx, cy);\n                path.push_back({cx, cy});\n            }\n        }\n    }\n\n    // Visibility set for each important node\n    vector<vector<int>> vis_nodes(M);\n    for (int id = 0; id < M; id++) {\n        auto [x, y] = nodes[id];\n        vector<int> mark;\n        mark.push_back(road_id[x][y]);\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x, ny = y;\n            while (true) {\n                nx += dx[dir]; ny += dy[dir];\n                if (!road(nx, ny)) break;\n                mark.push_back(road_id[nx][ny]);\n            }\n        }\n        sort(mark.begin(), mark.end());\n        mark.erase(unique(mark.begin(), mark.end()), mark.end());\n        vis_nodes[id] = move(mark);\n    }\n\n    // Greedy set cover: choose important nodes to cover all road cells.\n    vector<char> covered(R, 0);\n    int covered_cnt = 0;\n    auto apply_cover = [&](int id) {\n        for (int r : vis_nodes[id]) {\n            if (!covered[r]) {\n                covered[r] = 1;\n                covered_cnt++;\n            }\n        }\n    };\n\n    vector<int> targets;\n    apply_cover(start_node);\n    targets.push_back(start_node);\n\n    vector<char> chosen(M, 0);\n    chosen[start_node] = 1;\n\n    while (covered_cnt < R) {\n        int best = -1;\n        double best_score = -1e100;\n        for (int id = 0; id < M; id++) if (!chosen[id]) {\n            int gain = 0;\n            for (int r : vis_nodes[id]) gain += !covered[r];\n            if (gain == 0) continue;\n            // light bias toward centrality/start proximity by Manhattan\n            int md = abs(nodes[id].x - si) + abs(nodes[id].y - sj);\n            double score = (double)gain * 1000.0 - md;\n            if (score > best_score) {\n                best_score = score;\n                best = id;\n            }\n        }\n        if (best == -1) break;\n        chosen[best] = 1;\n        targets.push_back(best);\n        apply_cover(best);\n    }\n\n    // Dijkstra from every compressed node\n    vector<vector<int>> dist(M, vector<int>(M, INF));\n    vector<vector<int>> prevv(M, vector<int>(M, -1));\n    vector<vector<int>> preve(M, vector<int>(M, -1));\n\n    for (int s = 0; s < M; s++) {\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,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 (int ei = 0; ei < (int)g[v].size(); ei++) {\n                auto &e = g[v][ei];\n                int nd = cd + e.cost;\n                if (nd < dist[s][e.to]) {\n                    dist[s][e.to] = nd;\n                    prevv[s][e.to] = v;\n                    preve[s][e.to] = ei;\n                    pq.push({nd, e.to});\n                }\n            }\n        }\n    }\n\n    // Build a tour over targets with cheapest insertion on metric closure.\n    vector<int> need = targets;\n    sort(need.begin(), need.end());\n    need.erase(unique(need.begin(), need.end()), need.end());\n\n    vector<int> others;\n    for (int x : need) if (x != start_node) others.push_back(x);\n\n    vector<int> tour = {start_node, start_node}; // cyclic representation\n\n    if (!others.empty()) {\n        // start with nearest target\n        int first = others[0];\n        int bestd = INF;\n        for (int x : others) {\n            if (dist[start_node][x] + dist[x][start_node] < bestd) {\n                bestd = dist[start_node][x] + dist[x][start_node];\n                first = x;\n            }\n        }\n        tour = {start_node, first, start_node};\n\n        vector<char> used(M, 0);\n        used[start_node] = 1;\n        used[first] = 1;\n\n        int rem = (int)others.size() - 1;\n        while (rem--) {\n            int best_x = -1, best_pos = -1, best_inc = INF;\n            for (int x : others) if (!used[x]) {\n                for (int i = 0; i + 1 < (int)tour.size(); i++) {\n                    int a = tour[i], b = tour[i + 1];\n                    int inc = dist[a][x] + dist[x][b] - dist[a][b];\n                    if (inc < best_inc) {\n                        best_inc = inc;\n                        best_x = x;\n                        best_pos = i + 1;\n                    }\n                }\n            }\n            if (best_x == -1) break;\n            tour.insert(tour.begin() + best_pos, best_x);\n            used[best_x] = 1;\n        }\n    }\n\n    // Reconstruct compressed-node path for a->b\n    auto get_node_path = [&](int s, int t) {\n        vector<int> rev;\n        int cur = t;\n        while (cur != s) {\n            rev.push_back(cur);\n            cur = prevv[s][cur];\n            if (cur == -1) break;\n        }\n        rev.push_back(s);\n        reverse(rev.begin(), rev.end());\n        return rev;\n    };\n\n    // Convert compressed path to moves\n    string ans;\n    auto emit_move = [&](int x1, int y1, int x2, int y2) {\n        if (x2 == x1 - 1 && y2 == y1) ans.push_back('U');\n        else if (x2 == x1 + 1 && y2 == y1) ans.push_back('D');\n        else if (x2 == x1 && y2 == y1 - 1) ans.push_back('L');\n        else if (x2 == x1 && y2 == y1 + 1) ans.push_back('R');\n    };\n\n    for (int i = 0; i + 1 < (int)tour.size(); i++) {\n        int s = tour[i], t = tour[i + 1];\n        auto np = get_node_path(s, t);\n        for (int j = 0; j + 1 < (int)np.size(); j++) {\n            int u = np[j], v = np[j + 1];\n            int ei = -1;\n            for (int k = 0; k < (int)g[u].size(); k++) {\n                if (g[u][k].to == v && k == preve[u][v]) { // rarely true only if source=u\n                    ei = k;\n                    break;\n                }\n            }\n            if (ei == -1) {\n                ei = preve[u][v];\n            }\n            // For adjacent nodes on shortest-path tree from source=u to target=v,\n            // preve[u][v] is the edge to take.\n            auto &path = g[u][preve[u][v]].path;\n            int cx = nodes[u].x, cy = nodes[u].y;\n            for (auto &p : path) {\n                emit_move(cx, cy, p.x, p.y);\n                cx = p.x; cy = p.y;\n            }\n        }\n    }\n\n    // Safety fallback: if somehow not back at start, try to append shortest path to start.\n    {\n        int x = si, y = sj;\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n        }\n        if (x != si || y != sj) {\n            int cur_node = node_id[x][y];\n            if (cur_node != -1) {\n                auto np = get_node_path(cur_node, start_node);\n                for (int j = 0; j + 1 < (int)np.size(); j++) {\n                    int u = np[j], v = np[j + 1];\n                    auto &path = g[u][preve[u][v]].path;\n                    int cx = nodes[u].x, cy = nodes[u].y;\n                    for (auto &p : path) {\n                        emit_move(cx, cy, p.x, p.y);\n                        cx = p.x; cy = p.y;\n                    }\n                }\n            }\n        }\n    }\n\n    // Final strict validator fallback: if route invalid, output empty route.\n    {\n        int x = si, y = sj;\n        bool ok = true;\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n            else ok = false;\n            if (!inb(x, y) || !road(x, y)) ok = false;\n        }\n        if (!(x == si && y == sj)) ok = false;\n        if (!ok) ans.clear();\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskInfo {\n    vector<int> d;\n    int diff_sum = 0;\n    int priority = 1; // longest path to sink\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<TaskInfo> tasks(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].d.resize(K);\n        int s = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n            s += tasks[i].d[k];\n        }\n        tasks[i].diff_sum = s;\n    }\n\n    vector<vector<int>> out(N), in(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        in[v].push_back(u);\n    }\n\n    // Static priority = longest path to sink\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int to : out[i]) best = max(best, tasks[to].priority);\n        tasks[i].priority = best + 1;\n    }\n\n    // State\n    // task_state: 0 not started, 1 in progress, 2 done\n    vector<int> task_state(N, 0);\n    vector<int> rem_pre(N);\n    for (int i = 0; i < N; ++i) rem_pre[i] = (int)in[i].size();\n\n    vector<int> member_task(M, -1);\n    vector<int> member_start(M, -1);\n\n    // Skill estimates\n    vector<vector<double>> est(M, vector<double>(K, 20.0));\n    vector<int> obs_cnt(M, 0);\n\n    // For updates when a member finishes a task\n    auto predicted_deficit = [&](int task_id, int member_id) -> double {\n        double w = 0.0;\n        const auto &d = tasks[task_id].d;\n        const auto &s = est[member_id];\n        for (int k = 0; k < K; ++k) {\n            if (d[k] > s[k]) w += d[k] - s[k];\n        }\n        return w;\n    };\n\n    auto predicted_time = [&](int task_id, int member_id) -> double {\n        return max(1.0, predicted_deficit(task_id, member_id));\n    };\n\n    auto update_estimate = [&](int member_id, int task_id, int duration) {\n        // target deficit estimate\n        // conservative estimate due to noise and lower bound at 1\n        double target = (duration <= 1 ? 0.0 : (double)duration - 1.0);\n\n        const auto &d = tasks[task_id].d;\n        auto &s = est[member_id];\n\n        for (int iter = 0; iter < 3; ++iter) {\n            double pred = 0.0;\n            for (int k = 0; k < K; ++k) {\n                if (d[k] > s[k]) pred += d[k] - s[k];\n            }\n            double diff = target - pred; // positive => skills too high, negative => too low\n\n            double lr = 0.45 / (1.0 + 0.08 * obs_cnt[member_id]);\n            if (fabs(diff) < 0.5) break;\n\n            if (diff < 0) {\n                // Predicted deficit too large => estimated skills too low => increase skills\n                // Focus on dimensions where d[k] > s[k]\n                double total_gap = 0.0;\n                for (int k = 0; k < K; ++k) total_gap += max(0.0, (double)d[k] - s[k]);\n                if (total_gap < 1e-9) total_gap = 1.0;\n                double need = -diff * lr;\n                for (int k = 0; k < K; ++k) {\n                    double gap = max(0.0, (double)d[k] - s[k]);\n                    if (gap <= 0) continue;\n                    s[k] += need * (gap / total_gap);\n                    if (s[k] > 80.0) s[k] = 80.0;\n                }\n            } else {\n                // Predicted deficit too small => estimated skills too high => decrease a bit\n                // Decrease dimensions relevant to this task.\n                double total_rel = 0.0;\n                for (int k = 0; k < K; ++k) total_rel += d[k] + 1.0;\n                double need = diff * lr * 0.6;\n                for (int k = 0; k < K; ++k) {\n                    double dec = need * ((d[k] + 1.0) / total_rel);\n                    s[k] -= dec;\n                    if (s[k] < 0.0) s[k] = 0.0;\n                }\n            }\n        }\n\n        obs_cnt[member_id]++;\n    };\n\n    int day = 0;\n    int completed_tasks = 0;\n\n    while (true) {\n        day++;\n\n        // Ready tasks\n        vector<int> ready;\n        ready.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 0 && rem_pre[i] == 0) ready.push_back(i);\n        }\n\n        // Sort ready tasks by importance\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (tasks[a].priority != tasks[b].priority) return tasks[a].priority > tasks[b].priority;\n            if (tasks[a].diff_sum != tasks[b].diff_sum) return tasks[a].diff_sum > tasks[b].diff_sum;\n            return a < b;\n        });\n\n        // Candidate truncation\n        const int LIMIT = 180;\n        if ((int)ready.size() > LIMIT) ready.resize(LIMIT);\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) if (member_task[j] == -1) free_members.push_back(j);\n\n        vector<pair<int,int>> assignments;\n        vector<char> used_task(N, 0), used_member(M, 0);\n\n        // Greedy global pair selection\n        while (true) {\n            double bestScore = -1e100;\n            int bestMem = -1, bestTask = -1;\n\n            for (int j : free_members) {\n                if (used_member[j]) continue;\n                for (int t : ready) {\n                    if (used_task[t]) continue;\n\n                    double pt = predicted_time(t, j);\n                    // Exploration: lightly favor less-observed members early\n                    double explore = (obs_cnt[j] < 5 ? (5 - obs_cnt[j]) * 3.0 : 0.0);\n\n                    // Strong emphasis on precedence-critical tasks\n                    double score =\n                        1000.0 * tasks[t].priority\n                        + 2.0 * tasks[t].diff_sum\n                        - 25.0 * pt\n                        + explore;\n\n                    // Mild bonus for assigning very hard tasks to seemingly strong members\n                    if (obs_cnt[j] >= 3) {\n                        double strength = 0.0;\n                        for (int k = 0; k < K; ++k) strength += est[j][k];\n                        score += 0.02 * strength;\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestMem = j;\n                        bestTask = t;\n                    }\n                }\n            }\n\n            if (bestMem == -1) break;\n\n            used_member[bestMem] = 1;\n            used_task[bestTask] = 1;\n            assignments.push_back({bestMem, bestTask});\n\n            task_state[bestTask] = 1;\n            member_task[bestMem] = bestTask;\n            member_start[bestMem] = day;\n        }\n\n        // Output today's assignments\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << (mem + 1) << ' ' << (task + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        // Optional visualization comments of estimated skills\n        // Keep disabled in judge for speed/noise. Uncomment if desired.\n        /*\n        for (int j = 0; j < M; ++j) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; ++k) cout << ' ' << (int)round(est[j][k]);\n            cout << '\\n';\n        }\n        cout.flush();\n        */\n\n        string first;\n        if (!(cin >> first)) return 0;\n        if (first == \"-1\") {\n            return 0;\n        }\n\n        int n = stoi(first);\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int mem : finished) {\n            int task = member_task[mem];\n            if (task == -1) continue; // safety\n\n            int duration = day - member_start[mem] + 1;\n            update_estimate(mem, task, duration);\n\n            task_state[task] = 2;\n            completed_tasks++;\n\n            member_task[mem] = -1;\n            member_start[mem] = -1;\n\n            for (int to : out[task]) {\n                rem_pre[to]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 1000;\nstatic constexpr int M = 50;\nstatic constexpr int DEPOT_X = 400;\nstatic constexpr int DEPOT_Y = 400;\n\nstruct Order {\n    int a, b, c, d;\n    int id; // 1-indexed for output\n};\n\nstruct Pt {\n    int x, y;\n};\n\nstatic inline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\nstatic inline int mdist(const Pt& p, const Pt& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstruct Solver {\n    vector<Order> ord;\n    mt19937 rng;\n\n    Solver() : ord(N) {\n        rng.seed((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    }\n\n    double elapsed_ms(chrono::steady_clock::time_point st) {\n        return chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now() - st).count() / 1000.0;\n    }\n\n    Pt rest_pt(int idx) const { return {ord[idx].a, ord[idx].b}; }\n    Pt dest_pt(int idx) const { return {ord[idx].c, ord[idx].d}; }\n\n    int route_cost(const vector<int>& sel, const vector<int>& pord, const vector<int>& dord) const {\n        Pt cur{DEPOT_X, DEPOT_Y};\n        int cost = 0;\n        for (int pos : pord) {\n            Pt nxt = rest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        for (int pos : dord) {\n            Pt nxt = dest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        cost += mdist(cur, Pt{DEPOT_X, DEPOT_Y});\n        return cost;\n    }\n\n    vector<int> nearest_order_restaurant(const vector<int>& sel) const {\n        vector<int> rem(M);\n        iota(rem.begin(), rem.end(), 0);\n        vector<int> res;\n        res.reserve(M);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        vector<char> used(M, false);\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = 1e9;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                Pt p = rest_pt(sel[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(best);\n            cur = rest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    vector<int> nearest_order_destination_from(const vector<int>& sel, const Pt& start) const {\n        vector<int> res;\n        res.reserve(M);\n        Pt cur = start;\n        vector<char> used(M, false);\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = 1e9;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                Pt p = dest_pt(sel[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(best);\n            cur = dest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    void improve_two_opt_pick(const vector<int>& sel, vector<int>& pord, const vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    auto getP = [&](int idx) -> Pt {\n                        if (idx < 0) return Pt{DEPOT_X, DEPOT_Y};\n                        if (idx >= M) return dest_pt(sel[dord[0]]);\n                        return rest_pt(sel[pord[idx]]);\n                    };\n                    Pt A = getP(l - 1);\n                    Pt B = getP(l);\n                    Pt C = getP(r);\n                    Pt D = getP(r + 1);\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(pord.begin() + l, pord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void improve_two_opt_del(const vector<int>& sel, const vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    auto getD = [&](int idx) -> Pt {\n                        if (idx < 0) return rest_pt(sel[pord.back()]);\n                        if (idx >= M) return Pt{DEPOT_X, DEPOT_Y};\n                        return dest_pt(sel[dord[idx]]);\n                    };\n                    Pt A = getD(l - 1);\n                    Pt B = getD(l);\n                    Pt C = getD(r);\n                    Pt D = getD(r + 1);\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(dord.begin() + l, dord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void improve_swaps(const vector<int>& sel, vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            // pickup swaps\n            for (int i = 0; i < M; ++i) {\n                for (int j = i + 1; j < M; ++j) {\n                    int cur = route_cost(sel, pord, dord);\n                    swap(pord[i], pord[j]);\n                    int nw = route_cost(sel, pord, dord);\n                    if (nw < cur) {\n                        improved = true;\n                    } else {\n                        swap(pord[i], pord[j]);\n                    }\n                }\n            }\n            // delivery swaps\n            for (int i = 0; i < M; ++i) {\n                for (int j = i + 1; j < M; ++j) {\n                    int cur = route_cost(sel, pord, dord);\n                    swap(dord[i], dord[j]);\n                    int nw = route_cost(sel, pord, dord);\n                    if (nw < cur) {\n                        improved = true;\n                    } else {\n                        swap(dord[i], dord[j]);\n                    }\n                }\n            }\n        }\n    }\n\n    pair<vector<int>, pair<vector<int>, vector<int>>> build_initial_from_pool(const vector<int>& pool) {\n        vector<int> sel;\n        sel.reserve(M);\n\n        // Greedy selection on restaurant proximity, with a simple order-level score.\n        vector<char> used(N, false);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        for (int it = 0; it < M; ++it) {\n            int best = -1;\n            int bestScore = 1e9;\n            for (int idx : pool) if (!used[idx]) {\n                const auto& o = ord[idx];\n                int score =\n                    mdist(cur.x, cur.y, o.a, o.b) +\n                    mdist(o.a, o.b, o.c, o.d) / 3 +\n                    mdist(o.c, o.d, DEPOT_X, DEPOT_Y) / 3;\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = idx;\n                }\n            }\n            if (best == -1) break;\n            used[best] = true;\n            sel.push_back(best);\n            cur = rest_pt(best);\n        }\n\n        // if pool smaller somehow, fill from global\n        if ((int)sel.size() < M) {\n            vector<pair<int,int>> all;\n            all.reserve(N);\n            for (int i = 0; i < N; ++i) if (!used[i]) {\n                int base = mdist(ord[i].a, ord[i].b, DEPOT_X, DEPOT_Y)\n                         + mdist(ord[i].a, ord[i].b, ord[i].c, ord[i].d)\n                         + mdist(ord[i].c, ord[i].d, DEPOT_X, DEPOT_Y);\n                all.push_back({base, i});\n            }\n            sort(all.begin(), all.end());\n            for (auto &p : all) {\n                if ((int)sel.size() >= M) break;\n                used[p.second] = true;\n                sel.push_back(p.second);\n            }\n        }\n\n        auto pord = nearest_order_restaurant(sel);\n        Pt lastPick = rest_pt(sel[pord.back()]);\n        auto dord = nearest_order_destination_from(sel, lastPick);\n\n        improve_two_opt_pick(sel, pord, dord);\n        improve_two_opt_del(sel, pord, dord);\n        improve_swaps(sel, pord, dord);\n\n        return {sel, {pord, dord}};\n    }\n\n    void solve() {\n        for (int i = 0; i < N; ++i) {\n            cin >> ord[i].a >> ord[i].b >> ord[i].c >> ord[i].d;\n            ord[i].id = i + 1;\n        }\n\n        auto st = chrono::steady_clock::now();\n\n        vector<pair<int,int>> ranked;\n        ranked.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            int base =\n                mdist(ord[i].a, ord[i].b, DEPOT_X, DEPOT_Y) +\n                mdist(ord[i].a, ord[i].b, ord[i].c, ord[i].d) +\n                mdist(ord[i].c, ord[i].d, DEPOT_X, DEPOT_Y);\n            ranked.push_back({base, i});\n        }\n        sort(ranked.begin(), ranked.end());\n\n        int bestCost = INT_MAX;\n        vector<int> bestSel, bestP, bestD;\n\n        vector<int> poolSizes = {50, 60, 80, 100, 150, 200, 300};\n\n        for (int K : poolSizes) {\n            if (elapsed_ms(st) > 700) break;\n            K = min(K, N);\n            vector<int> pool;\n            pool.reserve(K);\n            for (int i = 0; i < K; ++i) pool.push_back(ranked[i].second);\n\n            auto init = build_initial_from_pool(pool);\n            auto sel = init.first;\n            auto pord = init.second.first;\n            auto dord = init.second.second;\n            int cost = route_cost(sel, pord, dord);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSel = sel;\n                bestP = pord;\n                bestD = dord;\n            }\n        }\n\n        // Improvement by replacement from good candidates / random candidates.\n        vector<int> topPool;\n        {\n            int K = 250;\n            for (int i = 0; i < K; ++i) topPool.push_back(ranked[i].second);\n        }\n\n        auto rebuild_orders = [&](const vector<int>& sel) {\n            auto pord = nearest_order_restaurant(sel);\n            auto dord = nearest_order_destination_from(sel, rest_pt(sel[pord.back()]));\n            improve_two_opt_pick(sel, pord, dord);\n            improve_two_opt_del(sel, pord, dord);\n            improve_swaps(sel, pord, dord);\n            return pair<vector<int>, vector<int>>(pord, dord);\n        };\n\n        while (elapsed_ms(st) < 1900) {\n            vector<int> sel = bestSel;\n\n            vector<char> inSel(N, false);\n            for (int x : sel) inSel[x] = true;\n\n            int outPos = uniform_int_distribution<int>(0, M - 1)(rng);\n            int inIdx;\n            if (uniform_int_distribution<int>(0, 99)(rng) < 80) {\n                inIdx = topPool[uniform_int_distribution<int>(0, (int)topPool.size() - 1)(rng)];\n            } else {\n                inIdx = uniform_int_distribution<int>(0, N - 1)(rng);\n            }\n            if (inSel[inIdx]) continue;\n\n            sel[outPos] = inIdx;\n\n            auto [pord, dord] = rebuild_orders(sel);\n            int cost = route_cost(sel, pord, dord);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSel = move(sel);\n                bestP = move(pord);\n                bestD = move(dord);\n            }\n        }\n\n        // Output\n        cout << M;\n        for (int idx : bestSel) cout << ' ' << ord[idx].id;\n        cout << '\\n';\n\n        vector<Pt> route;\n        route.reserve(2 * M + 2);\n        route.push_back({DEPOT_X, DEPOT_Y});\n        for (int pos : bestP) route.push_back(rest_pt(bestSel[pos]));\n        for (int pos : bestD) route.push_back(dest_pt(bestSel[pos]));\n        route.push_back({DEPOT_X, DEPOT_Y});\n\n        cout << route.size();\n        for (auto &p : route) cout << ' ' << p.x << ' ' << p.y;\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}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n) { 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 same(int a, int b) { return find(a) == find(b); }\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 type; // 0 = accepted edge, 1 = current edge, 2 = future undecided edge\n    int idx;\n    int u, v;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return type < other.type;\n    }\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    double dd = sqrt((double)(dx * dx + dy * dy));\n    return (int)llround(dd);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<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    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].d = rounded_dist(x[u], y[u], x[v], y[v]);\n    }\n\n    vector<int> state(M, -1);   // -1 undecided, 0 rejected, 1 accepted\n    DSU accepted(N);\n\n    auto feasible_without_current = [&](int cur) -> bool {\n        DSU dsu(N);\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            } else if (j > cur && state[j] == -1) {\n                if (j == cur) continue;\n                dsu.unite(edges[j].u, edges[j].v);\n            }\n        }\n        return dsu.same(edges[cur].u, edges[cur].v);\n    };\n\n    auto current_in_surrogate_mst = [&](int cur, int lcur) -> bool {\n        vector<KEdge> es;\n        es.reserve(M - cur + N);\n\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                es.push_back({0, 0, j, edges[j].u, edges[j].v});\n            } else if (j == cur) {\n                es.push_back({lcur, 1, j, edges[j].u, edges[j].v});\n            } else if (j > cur && state[j] == -1) {\n                es.push_back({2 * edges[j].d, 2, j, edges[j].u, edges[j].v});\n            }\n        }\n\n        sort(es.begin(), es.end());\n        DSU dsu(N);\n        for (auto &e : es) {\n            if (dsu.unite(e.u, e.v)) {\n                if (e.type == 1) return true;\n            }\n        }\n        return false;\n    };\n\n    auto alternative_threshold = [&](int cur) -> int {\n        // Find a cheap expected alternative connecting the current accepted components\n        // of the endpoints of cur. We use the best future undecided crossing edge between\n        // the two sides represented by current accepted DSU components.\n        int ru = accepted.find(edges[cur].u);\n        int rv = accepted.find(edges[cur].v);\n        if (ru == rv) return 0;\n\n        int best = INT_MAX;\n        for (int j = cur + 1; j < M; j++) {\n            if (state[j] != -1) continue;\n            int a = accepted.find(edges[j].u);\n            int b = accepted.find(edges[j].v);\n            if (a == b) continue;\n\n            // Crossing the current two super-components directly is the strongest signal.\n            bool good = (a == ru && b == rv) || (a == rv && b == ru);\n            if (good) {\n                best = min(best, 2 * edges[j].d);\n            }\n        }\n\n        // Fallback: any future edge incident to one of the two components.\n        if (best == INT_MAX) {\n            for (int j = cur + 1; j < M; j++) {\n                if (state[j] != -1) continue;\n                int a = accepted.find(edges[j].u);\n                int b = accepted.find(edges[j].v);\n                if (a == b) continue;\n                bool relevant = (a == ru || a == rv || b == ru || b == rv);\n                if (relevant) best = min(best, 2 * edges[j].d);\n            }\n        }\n\n        return best;\n    };\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n\n        int ans = 0;\n        int u = edges[i].u, v = edges[i].v;\n\n        if (accepted.same(u, v)) {\n            ans = 0;\n        } else {\n            // indispensable for connectivity?\n            if (!feasible_without_current(i)) {\n                ans = 1;\n            } else {\n                bool in_mst = current_in_surrogate_mst(i, l);\n                if (!in_mst) {\n                    ans = 0;\n                } else {\n                    int alt = alternative_threshold(i);\n                    if (alt == INT_MAX) {\n                        ans = 1;\n                    } else {\n                        // modest margin; if current realized cost is close to best expected alternative, accept\n                        ans = (double)l <= 1.15 * (double)alt ? 1 : 0;\n                    }\n                }\n            }\n        }\n\n        state[i] = ans;\n        if (ans) accepted.unite(u, v);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC008 - heuristic solution\n\nIdea:\n- Split humans into two roles:\n  1) builders: most humans gather near the center and gradually build a horizontal wall.\n  2) roamers: a few humans move toward distant corners to secure large pet-free areas there.\n- After the wall is mostly built, builders spread and continue sealing around center.\n- Roamers, after reaching their target side/corner, try to build local closures opportunistically.\n- We use only current pet positions, not prediction. This is simple but robust.\n\nThis is not an optimal strategy, but it is safe and usually achieves non-trivial scores.\n*/\n\nstatic const int H = 30;\nstatic const int W = 30;\nstatic const int TURNS = 300;\n\nstruct Pet {\n    int x, y, t;\n};\n\nstruct Human {\n    int x, y;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\nbool wall_[31][31]; // 1-indexed passable=false if true\n\nint dx4[4] = {-1, 1, 0, 0};\nint dy4[4] = {0, 0, -1, 1};\nchar moveCh[4] = {'U','D','L','R'};\nchar buildCh[4] = {'u','d','l','r'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nbool has_pet_at_start[31][31];\nbool has_human_at_start[31][31];\n\nbool adj_pet(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx4[d], ny = y + dy4[d];\n        if (inside(nx, ny) && has_pet_at_start[nx][ny]) return true;\n    }\n    return false;\n}\n\nbool can_block_cell(int x, int y) {\n    if (!inside(x,y)) return false;\n    if (has_pet_at_start[x][y]) return false;\n    if (has_human_at_start[x][y]) return false;\n    if (adj_pet(x,y)) return false;\n    return true;\n}\n\nbool passable_after_existing(int x, int y) {\n    return inside(x,y) && !wall_[x][y];\n}\n\nstruct Task {\n    int mode; // 0 gather/build line, 1 move to anchor, 2 local seal\n    int tx, ty;\n};\n\nvector<Task> tasks;\n\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1-x2) + abs(y1-y2);\n}\n\npair<int,int> bfs_next_step(int sx, int sy, int tx, int ty) {\n    if (sx == tx && sy == ty) return {sx, sy};\n    static int dist[31][31];\n    static pair<int,int> prevv[31][31];\n    for (int i = 1; i <= 30; i++) for (int j = 1; j <= 30; j++) {\n        dist[i][j] = -1;\n        prevv[i][j] = {-1,-1};\n    }\n    queue<pair<int,int>> q;\n    q.push({sx,sy});\n    dist[sx][sy] = 0;\n    while (!q.empty()) {\n        auto [x,y] = q.front(); q.pop();\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx4[d], ny = y + dy4[d];\n            if (!inside(nx,ny) || wall_[nx][ny]) continue;\n            if (dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            prevv[nx][ny] = {x,y};\n            q.push({nx,ny});\n        }\n    }\n    if (dist[tx][ty] == -1) return {sx,sy};\n\n    int cx = tx, cy = ty;\n    while (!(prevv[cx][cy].first == sx && prevv[cx][cy].second == sy)) {\n        auto p = prevv[cx][cy];\n        cx = p.first;\n        cy = p.second;\n        if (cx == -1) return {sx,sy};\n    }\n    return {tx==sx&&ty==sy ? sx : cx, ty==sy&&tx==sx ? sy : cy};\n}\n\nchar move_toward(int id, int tx, int ty, const vector<pair<int,int>>& reserved_targets) {\n    int x = humans[id].x, y = humans[id].y;\n    auto [nx, ny] = bfs_next_step(x, y, tx, ty);\n    if (nx == x && ny == y) return '.';\n\n    // avoid stepping onto a square another human targets this turn if possible\n    bool conflict = false;\n    for (int j = 0; j < (int)reserved_targets.size(); j++) {\n        if (j == id) continue;\n        if (reserved_targets[j].first == nx && reserved_targets[j].second == ny) {\n            conflict = true;\n            break;\n        }\n    }\n    if (conflict) {\n        // fallback greedy local move\n        int bestd = 1e9, bestdir = -1;\n        for (int d = 0; d < 4; d++) {\n            int xx = x + dx4[d], yy = y + dy4[d];\n            if (!inside(xx,yy) || wall_[xx][yy]) continue;\n            bool ok = true;\n            for (int j = 0; j < (int)reserved_targets.size(); j++) {\n                if (j == id) continue;\n                if (reserved_targets[j].first == xx && reserved_targets[j].second == yy) {\n                    ok = false;\n                    break;\n                }\n            }\n            if (!ok) continue;\n            int dd = manhattan(xx,yy,tx,ty);\n            if (dd < bestd) {\n                bestd = dd;\n                bestdir = d;\n            }\n        }\n        if (bestdir == -1) return '.';\n        return moveCh[bestdir];\n    }\n\n    for (int d = 0; d < 4; d++) {\n        if (x + dx4[d] == nx && y + dy4[d] == ny) return moveCh[d];\n    }\n    return '.';\n}\n\nbool try_block_dir(int hx, int hy, int dir) {\n    int x = hx + dx4[dir], y = hy + dy4[dir];\n    return can_block_cell(x,y);\n}\n\nint pet_count_side(bool top_side) {\n    int cnt = 0;\n    for (auto &p : pets) {\n        if (top_side) {\n            if (p.x <= 15) cnt++;\n        } else {\n            if (p.x >= 16) cnt++;\n        }\n    }\n    return cnt;\n}\n\nint pet_count_rect(int x1, int y1, int x2, int y2) {\n    int cnt = 0;\n    for (auto &p : pets) {\n        if (x1 <= p.x && p.x <= x2 && y1 <= p.y && p.y <= y2) cnt++;\n    }\n    return cnt;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n    for (int i = 0; i < N; i++) cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; i++) cin >> humans[i].x >> humans[i].y;\n\n    memset(wall_, 0, sizeof(wall_));\n\n    // assign tasks\n    tasks.resize(M);\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n\n    // farthest humans become roamers to corners\n    sort(ord.begin(), ord.end(), [&](int a, int b){\n        int da = min({manhattan(humans[a].x, humans[a].y, 2, 2),\n                      manhattan(humans[a].x, humans[a].y, 2, 29),\n                      manhattan(humans[a].x, humans[a].y, 29, 2),\n                      manhattan(humans[a].x, humans[a].y, 29, 29)});\n        int db = min({manhattan(humans[b].x, humans[b].y, 2, 2),\n                      manhattan(humans[b].x, humans[b].y, 2, 29),\n                      manhattan(humans[b].x, humans[b].y, 29, 2),\n                      manhattan(humans[b].x, humans[b].y, 29, 29)});\n        return da > db;\n    });\n\n    int roamers = max(2, M / 3);\n    roamers = min(roamers, M);\n\n    vector<pair<int,int>> cornerCand = {{2,2},{2,29},{29,2},{29,29},{2,15},{29,15}};\n    for (int i = 0; i < M; i++) {\n        tasks[i] = {0, 15, 15};\n    }\n    for (int k = 0; k < roamers; k++) {\n        int id = ord[k];\n        pair<int,int> best = cornerCand[0];\n        int bestScore = -1e9;\n        for (auto c : cornerCand) {\n            int dist = manhattan(humans[id].x, humans[id].y, c.first, c.second);\n            int px1 = max(1, c.first - 5), py1 = max(1, c.second - 5);\n            int px2 = min(30, c.first + 5), py2 = min(30, c.second + 5);\n            int petsNear = pet_count_rect(px1, py1, px2, py2);\n            int score = dist - 8 * petsNear;\n            if (score > bestScore) {\n                bestScore = score;\n                best = c;\n            }\n        }\n        tasks[id] = {1, best.first, best.second};\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        memset(has_pet_at_start, 0, sizeof(has_pet_at_start));\n        memset(has_human_at_start, 0, sizeof(has_human_at_start));\n        for (auto &p : pets) has_pet_at_start[p.x][p.y] = true;\n        for (auto &h : humans) has_human_at_start[h.x][h.y] = true;\n\n        string ans(M, '.');\n        vector<pair<int,int>> reserved(M, {-100,-100});\n\n        int topPets = pet_count_side(true);\n        int bottomPets = pet_count_side(false);\n        bool buildUpper = (topPets <= bottomPets); // secure upper side, build row 16 downward/upward separators\n        int barrierRow = buildUpper ? 16 : 15;\n        int safeRow = buildUpper ? 14 : 17;\n\n        // pre-reserve current positions\n        for (int i = 0; i < M; i++) reserved[i] = {humans[i].x, humans[i].y};\n\n        for (int i = 0; i < M; i++) {\n            int x = humans[i].x, y = humans[i].y;\n\n            if (tasks[i].mode == 1) {\n                // roamer heading to anchor\n                if (manhattan(x, y, tasks[i].tx, tasks[i].ty) <= 1) {\n                    tasks[i].mode = 2;\n                }\n            }\n\n            if (tasks[i].mode == 2) {\n                // local seal near edge: prefer building inward-facing wall segments\n                vector<int> dirs;\n                if (x <= 3) dirs.push_back(1);\n                if (x >= 28) dirs.push_back(0);\n                if (y <= 3) dirs.push_back(3);\n                if (y >= 28) dirs.push_back(2);\n\n                bool done = false;\n                for (int d : dirs) {\n                    int bx = x + dx4[d], by = y + dy4[d];\n                    if (can_block_cell(bx,by)) {\n                        ans[i] = buildCh[d];\n                        done = true;\n                        break;\n                    }\n                }\n                if (done) continue;\n\n                // move along perimeter to a better sealing point\n                vector<pair<int,int>> cand;\n                if (x <= 3) {\n                    if (inside(x, y-1) && !wall_[x][y-1]) cand.push_back({x, y-1});\n                    if (inside(x, y+1) && !wall_[x][y+1]) cand.push_back({x, y+1});\n                } else if (x >= 28) {\n                    if (inside(x, y-1) && !wall_[x][y-1]) cand.push_back({x, y-1});\n                    if (inside(x, y+1) && !wall_[x][y+1]) cand.push_back({x, y+1});\n                } else if (y <= 3) {\n                    if (inside(x-1, y) && !wall_[x-1][y]) cand.push_back({x-1, y});\n                    if (inside(x+1, y) && !wall_[x+1][y]) cand.push_back({x+1, y});\n                } else if (y >= 28) {\n                    if (inside(x-1, y) && !wall_[x-1][y]) cand.push_back({x-1, y});\n                    if (inside(x+1, y) && !wall_[x+1][y]) cand.push_back({x+1, y});\n                }\n\n                bool moved = false;\n                for (auto [nx,ny] : cand) {\n                    bool ok = true;\n                    for (int j = 0; j < i; j++) if (reserved[j] == make_pair(nx,ny)) ok = false;\n                    if (!ok) continue;\n                    for (int d = 0; d < 4; d++) if (x+dx4[d]==nx && y+dy4[d]==ny) {\n                        ans[i] = moveCh[d];\n                        reserved[i] = {nx,ny};\n                        moved = true;\n                        break;\n                    }\n                    if (moved) break;\n                }\n                if (moved) continue;\n            }\n\n            // builders / fallback:\n            // if on safe row, build barrier row adjacent when possible\n            if (x == safeRow) {\n                if (barrierRow == x + 1) {\n                    if (can_block_cell(x+1, y)) {\n                        ans[i] = 'd';\n                        continue;\n                    }\n                } else if (barrierRow == x - 1) {\n                    if (can_block_cell(x-1, y)) {\n                        ans[i] = 'u';\n                        continue;\n                    }\n                }\n\n                // extend sideways to uncovered columns\n                int leftNeed = 1000, rightNeed = 1000;\n                for (int yy = y; yy >= 1; yy--) {\n                    if (!wall_[barrierRow][yy]) { leftNeed = y - yy; break; }\n                }\n                for (int yy = y; yy <= 30; yy++) {\n                    if (!wall_[barrierRow][yy]) { rightNeed = yy - y; break; }\n                }\n\n                int targetY = y;\n                if (leftNeed == 1000 && rightNeed == 1000) {\n                    // barrier row mostly done, keep opportunistic local closures\n                } else if (leftNeed <= rightNeed) {\n                    targetY = max(1, y - 1);\n                } else {\n                    targetY = min(30, y + 1);\n                }\n\n                if (targetY != y && !wall_[x][targetY]) {\n                    bool occ = false;\n                    for (int j = 0; j < i; j++) if (reserved[j] == make_pair(x,targetY)) occ = true;\n                    if (!occ) {\n                        ans[i] = (targetY < y ? 'L' : 'R');\n                        reserved[i] = {x,targetY};\n                        continue;\n                    }\n                }\n            }\n\n            // move to safe row first\n            if (tasks[i].mode == 0 && x != safeRow) {\n                char c = move_toward(i, safeRow, y, reserved);\n                ans[i] = c;\n                int dsel = -1;\n                for (int d = 0; d < 4; d++) if (moveCh[d] == c) dsel = d;\n                if (dsel != -1) reserved[i] = {x + dx4[dsel], y + dy4[dsel]};\n                continue;\n            }\n\n            // gather to center-ish columns to spread barrier\n            if (tasks[i].mode == 0 && x == safeRow) {\n                int desiredY = 3 + (24 * i) / max(1, M-1);\n                char c = move_toward(i, safeRow, desiredY, reserved);\n                ans[i] = c;\n                int dsel = -1;\n                for (int d = 0; d < 4; d++) if (moveCh[d] == c) dsel = d;\n                if (dsel != -1) reserved[i] = {x + dx4[dsel], y + dy4[dsel]};\n                continue;\n            }\n\n            // mode 1 movement to target anchor\n            if (tasks[i].mode == 1) {\n                char c = move_toward(i, tasks[i].tx, tasks[i].ty, reserved);\n                ans[i] = c;\n                int dsel = -1;\n                for (int d = 0; d < 4; d++) if (moveCh[d] == c) dsel = d;\n                if (dsel != -1) reserved[i] = {x + dx4[dsel], y + dy4[dsel]};\n                continue;\n            }\n\n            // mode 2 fallback: if no local edge action, stay or go anchor\n            if (tasks[i].mode == 2) {\n                char c = move_toward(i, tasks[i].tx, tasks[i].ty, reserved);\n                ans[i] = c;\n                int dsel = -1;\n                for (int d = 0; d < 4; d++) if (moveCh[d] == c) dsel = d;\n                if (dsel != -1) reserved[i] = {x + dx4[dsel], y + dy4[dsel]};\n                continue;\n            }\n        }\n\n        cout << ans << '\\n';\n        cout.flush();\n\n        // reflect human actions locally\n        for (int i = 0; i < M; i++) {\n            char c = ans[i];\n            int x = humans[i].x, y = humans[i].y;\n            if (c == 'U' || c == 'D' || c == 'L' || c == 'R') {\n                for (int d = 0; d < 4; d++) if (moveCh[d] == c) {\n                    int nx = x + dx4[d], ny = y + dy4[d];\n                    if (inside(nx,ny) && !wall_[nx][ny]) {\n                        humans[i].x = nx;\n                        humans[i].y = ny;\n                    }\n                }\n            } else if (c == 'u' || c == 'd' || c == 'l' || c == 'r') {\n                for (int d = 0; d < 4; d++) if (buildCh[d] == c) {\n                    int bx = x + dx4[d], by = y + dy4[d];\n                    if (can_block_cell(bx,by)) wall_[bx][by] = true;\n                }\n            }\n        }\n\n        // read pet actions and update positions\n        for (int i = 0; i < N; i++) {\n            string s;\n            cin >> s;\n            if (!cin) return 0;\n            if (s == \".\") continue;\n            for (char c : s) {\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 == -1) continue;\n                int nx = pets[i].x + dx4[d], ny = pets[i].y + dy4[d];\n                if (inside(nx,ny) && !wall_[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - 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 l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nint si, sj, ti, tj;\ndouble pforget;\nstring hs[H];\nstring vs[H - 1];\n\ninline int id(int i, int j) { return i * W + j; }\ninline pair<int,int> pos(int v) { return {v / W, v % W}; }\n\nint nxt[N][4]; // U,D,L,R\nchar dirch[4] = {'U','D','L','R'};\nint di[4] = {-1,1,0,0};\nint dj[4] = {0,0,-1,1};\n\nint targetDist[N];\nint targetNextDir[N]; // one step on shortest path to target, -1 for target/unreachable\nvector<int> revAdj[N];\n\ndouble eval_string(const string &s) {\n    vector<double> cur(N, 0.0), nxtp(N, 0.0);\n    int s0 = id(si, sj);\n    int tg = id(ti, tj);\n    cur[s0] = 1.0;\n    double ans = 0.0;\n    for (int t = 1; t <= (int)s.size(); t++) {\n        fill(nxtp.begin(), nxtp.end(), 0.0);\n        int d;\n        char c = s[t - 1];\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == tg) {\n                ans += pr * (401 - t);\n                continue;\n            }\n            nxtp[v] += pr * pforget;\n            int to = nxt[v][d];\n            nxtp[to] += pr * (1.0 - pforget);\n        }\n        cur.swap(nxtp);\n    }\n    // if already at target after all commands, not counted later; failure gives 0\n    return ans;\n}\n\nvector<int> bfs_dist_from_target() {\n    vector<int> dist(N, (int)1e9);\n    queue<int> q;\n    int tg = id(ti, tj);\n    dist[tg] = 0;\n    q.push(tg);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        auto [i, j] = pos(v);\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    return dist;\n}\n\nstring shortest_path_lexi() {\n    int S = id(si, sj), T = id(ti, tj);\n    vector<int> dist(N, (int)1e9), par(N, -1), pard(N, -1);\n    queue<int> q;\n    dist[S] = 0;\n    q.push(S);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == T) break;\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            if (to == v) continue;\n            if (dist[to] > dist[v] + 1) {\n                dist[to] = dist[v] + 1;\n                par[to] = v;\n                pard[to] = d;\n                q.push(to);\n            }\n        }\n    }\n    string res;\n    int cur = T;\n    while (cur != S) {\n        res.push_back(dirch[pard[cur]]);\n        cur = par[cur];\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nstring shortest_path_target_greedy_randomized() {\n    // randomized shortest path using targetDist\n    int cur = id(si, sj), tg = id(ti, tj);\n    string s;\n    while (cur != tg) {\n        vector<int> cand;\n        int best = targetDist[cur];\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[cur][d];\n            if (to == cur) continue;\n            if (targetDist[to] + 1 == targetDist[cur]) cand.push_back(d);\n        }\n        if (cand.empty()) break;\n        int d = cand[rng.next_int(0, (int)cand.size() - 1)];\n        s.push_back(dirch[d]);\n        cur = nxt[cur][d];\n    }\n    return s;\n}\n\nstring repeat_each(const string &base, int k) {\n    string s;\n    for (char c : base) {\n        for (int i = 0; i < k; i++) {\n            if ((int)s.size() < MAXL) s.push_back(c);\n        }\n    }\n    return s;\n}\n\nstring build_attractor_suffix(int len) {\n    // Construct a generic target-directed suffix:\n    // at each step choose direction that decreases shortest distance for the largest total mass\n    // approximated by global usefulness count.\n    vector<array<int,4>> improve(N);\n    for (int v = 0; v < N; v++) {\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            improve[v][d] = (targetDist[to] < targetDist[v]) ? 1 : 0;\n        }\n    }\n    string suf;\n    vector<double> cur(N, 0.0), nxtp(N, 0.0);\n    cur[id(si, sj)] = 1.0;\n    int tg = id(ti, tj);\n\n    // First simulate empty prefix? Here we just choose a good generic suffix via rolling optimization.\n    for (int step = 0; step < len; step++) {\n        double bestScore = -1;\n        int bestD = 0;\n        for (int d = 0; d < 4; d++) {\n            double sc = 0;\n            for (int v = 0; v < N; v++) {\n                if (v == tg) continue;\n                sc += cur[v] * improve[v][d];\n            }\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestD = d;\n            }\n        }\n        suf.push_back(dirch[bestD]);\n\n        fill(nxtp.begin(), nxtp.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == tg) {\n                nxtp[v] += pr;\n                continue;\n            }\n            nxtp[v] += pr * pforget;\n            int to = nxt[v][bestD];\n            nxtp[to] += pr * (1.0 - pforget);\n        }\n        cur.swap(nxtp);\n    }\n    return suf;\n}\n\nstring build_candidate_from_base(const string &base) {\n    string best = base;\n    double bestVal = eval_string(best);\n\n    for (int k = 1; k <= 8; k++) {\n        string s = repeat_each(base, k);\n        int rem = MAXL - (int)s.size();\n        if (rem > 0) {\n            string suf = build_attractor_suffix(rem);\n            s += suf;\n        }\n        double val = eval_string(s);\n        if (val > bestVal) {\n            bestVal = val;\n            best = s;\n        }\n    }\n    return best;\n}\n\nstring mutate(const string &s) {\n    string t = s;\n    int op = rng.next_int(0, 99);\n\n    if (op < 30 && !t.empty()) {\n        // change one char\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n    } else if (op < 55 && (int)t.size() < MAXL) {\n        // insert\n        int i = rng.next_int(0, (int)t.size());\n        char c = dirch[rng.next_int(0, 3)];\n        t.insert(t.begin() + i, c);\n    } else if (op < 70 && !t.empty()) {\n        // erase\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t.erase(t.begin() + i);\n    } else if (op < 85 && !t.empty()) {\n        // duplicate segment\n        int l = rng.next_int(0, (int)t.size() - 1);\n        int r = rng.next_int(l, min((int)t.size() - 1, l + 7));\n        string seg = t.substr(l, r - l + 1);\n        if ((int)t.size() + (int)seg.size() <= MAXL) {\n            int pos = rng.next_int(0, (int)t.size());\n            t.insert(pos, seg);\n        }\n    } else if (!t.empty()) {\n        // local target-biased rewrite\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n        if (i + 1 < (int)t.size() && rng.next_double() < 0.5) t[i + 1] = dirch[rng.next_int(0, 3)];\n    }\n\n    if ((int)t.size() > MAXL) t.resize(MAXL);\n    return t;\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 < H; i++) cin >> hs[i];\n    for (int i = 0; i < H - 1; i++) cin >> vs[i];\n\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {\n        int v = id(i, j);\n        // U\n        if (i == 0 || vs[i - 1][j] == '1') nxt[v][0] = v;\n        else nxt[v][0] = id(i - 1, j);\n        // D\n        if (i == H - 1 || vs[i][j] == '1') nxt[v][1] = v;\n        else nxt[v][1] = id(i + 1, j);\n        // L\n        if (j == 0 || hs[i][j - 1] == '1') nxt[v][2] = v;\n        else nxt[v][2] = id(i, j - 1);\n        // R\n        if (j == W - 1 || hs[i][j] == '1') nxt[v][3] = v;\n        else nxt[v][3] = id(i, j + 1);\n    }\n\n    auto dist = bfs_dist_from_target();\n    for (int v = 0; v < N; v++) targetDist[v] = dist[v];\n\n    for (int v = 0; v < N; v++) {\n        targetNextDir[v] = -1;\n        int best = targetDist[v];\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            if (to != v && targetDist[to] < best) {\n                best = targetDist[to];\n                targetNextDir[v] = d;\n            }\n        }\n    }\n\n    Timer timer;\n\n    vector<string> seeds;\n    string sp = shortest_path_lexi();\n    seeds.push_back(sp);\n    for (int it = 0; it < 20; it++) {\n        seeds.push_back(shortest_path_target_greedy_randomized());\n    }\n\n    string best = sp;\n    double bestVal = eval_string(best);\n\n    for (auto &base : seeds) {\n        string cand = build_candidate_from_base(base);\n        double val = eval_string(cand);\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n    }\n\n    // Simulated annealing / hill climbing\n    string cur = best;\n    double curVal = bestVal;\n\n    const double TL = 1.92;\n    int iter = 0;\n    while (true) {\n        double tm = timer.elapsed();\n        if (tm > TL) break;\n        iter++;\n\n        string nxts = mutate(cur);\n        double nv = eval_string(nxts);\n\n        double progress = tm / TL;\n        double temp = 30.0 * (1.0 - progress) + 1e-6;\n        double diff = nv - curVal;\n        if (diff >= 0 || rng.next_double() < exp(diff / temp)) {\n            cur = nxts;\n            curVal = nv;\n            if (nv > bestVal) {\n                bestVal = nv;\n                best = nxts;\n            }\n        }\n\n        // occasional restart near best\n        if ((iter % 500) == 0 && rng.next_double() < 0.3) {\n            cur = best;\n            curVal = bestVal;\n        }\n    }\n\n    if (best.empty()) best = sp;\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n    cout << best << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int NN = N * N;\n\n// directions: 0:left, 1:up, 2:right, 3:down\nstatic const int di[4] = {0, -1, 0, 1};\nstatic const int dj[4] = {-1, 0, 1, 0};\n\nstatic const int TO[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\ninline int rotTile(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (t <= 3) t = (t + 1) & 3;\n        else if (t <= 5) t = 9 - t;   // 4 <-> 5\n        else t = 13 - t;              // 6 <-> 7\n    }\n    return t;\n}\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstruct Solver {\n    array<string, N> s;\n    int base[N][N];\n    int curTile[N][N];\n\n    mt19937 rng;\n\n    Solver() : rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void readInput() {\n        for (int i = 0; i < N; i++) {\n            cin >> s[i];\n            for (int j = 0; j < N; j++) base[i][j] = s[i][j] - '0';\n        }\n    }\n\n    void applyRot(const array<unsigned char, NN>& rot) {\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            curTile[i][j] = rotTile(base[i][j], rot[i * N + j]);\n        }\n    }\n\n    int traceCycleFrom(int si, int sj, int sd) {\n        int i = si, j = sj, d = sd;\n        int len = 0;\n        while (true) {\n            int d2 = TO[curTile[i][j]][d];\n            if (d2 == -1) return 0;\n            i += di[d2];\n            j += dj[d2];\n            if (i < 0 || i >= N || j < 0 || j >= N) return 0;\n            d = (d2 + 2) & 3;\n            ++len;\n            if (i == si && j == sj && d == sd) return len;\n            // safety upper bound\n            if (len > 4 * NN + 5) return 0;\n        }\n    }\n\n    long long evalExact(const array<unsigned char, NN>& rot) {\n        applyRot(rot);\n\n        static unsigned char vis[N][N][4];\n        memset(vis, 0, sizeof(vis));\n\n        int best1 = 0, best2 = 0;\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) for (int d = 0; d < 4; d++) {\n            if (vis[i][j][d]) continue;\n\n            // follow component states\n            vector<tuple<int,int,int>> path;\n            int ci = i, cj = j, cd = d;\n            bool broken = false;\n            int cycLen = 0;\n\n            while (true) {\n                if (ci < 0 || ci >= N || cj < 0 || cj >= N) {\n                    broken = true;\n                    break;\n                }\n                if (vis[ci][cj][cd]) {\n                    // this state already settled before or in this walk\n                    break;\n                }\n                vis[ci][cj][cd] = 1;\n                path.emplace_back(ci, cj, cd);\n\n                int d2 = TO[curTile[ci][cj]][cd];\n                if (d2 == -1) {\n                    broken = true;\n                    break;\n                }\n                int ni = ci + di[d2];\n                int nj = cj + dj[d2];\n                if (ni < 0 || ni >= N || nj < 0 || nj >= N) {\n                    broken = true;\n                    break;\n                }\n                int nd = (d2 + 2) & 3;\n\n                if (ni == i && nj == j && nd == d) {\n                    cycLen = (int)path.size();\n                    break;\n                }\n\n                ci = ni; cj = nj; cd = nd;\n            }\n\n            if (!broken && cycLen > 0) {\n                if (cycLen > best1) {\n                    best2 = best1;\n                    best1 = cycLen;\n                } else if (cycLen > best2) {\n                    best2 = cycLen;\n                }\n            }\n        }\n\n        if (best2 == 0) return 0;\n        return 1LL * best1 * best2;\n    }\n\n    array<unsigned char, NN> randomRot() {\n        array<unsigned char, NN> rot{};\n        for (int k = 0; k < NN; k++) rot[k] = rng() & 3;\n        return rot;\n    }\n\n    array<unsigned char, NN> zeroRot() {\n        array<unsigned char, NN> rot{};\n        rot.fill(0);\n        return rot;\n    }\n\n    array<unsigned char, NN> patternRot(int type) {\n        array<unsigned char, NN> rot{};\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int v = 0;\n            if (type == 0) v = (i + j) & 3;\n            else if (type == 1) v = i & 3;\n            else if (type == 2) v = j & 3;\n            else if (type == 3) v = ((i / 2) + (j / 2)) & 3;\n            else v = 0;\n            rot[i * N + j] = v;\n        }\n        return rot;\n    }\n\n    void hillClimb(array<unsigned char, NN>& rot, long long& score, Timer& timer, double limit) {\n        score = evalExact(rot);\n\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n\n        while (timer.elapsed() < limit) {\n            bool improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n\n            for (int idx : ord) {\n                if (timer.elapsed() >= limit) return;\n                unsigned char old = rot[idx];\n                long long bestSc = score;\n                unsigned char bestR = old;\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    long long sc = evalExact(rot);\n                    if (sc > bestSc) {\n                        bestSc = sc;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = bestR;\n                if (bestSc > score) {\n                    score = bestSc;\n                    improved = true;\n                } else {\n                    rot[idx] = old;\n                }\n            }\n\n            if (!improved) {\n                // kick\n                int changes = 8 + (rng() % 16);\n                vector<pair<int,unsigned char>> backup;\n                backup.reserve(changes);\n                for (int t = 0; t < changes; t++) {\n                    int idx = rng() % NN;\n                    backup.push_back({idx, rot[idx]});\n                    rot[idx] = rng() & 3;\n                }\n                long long sc2 = evalExact(rot);\n                if (sc2 >= score) {\n                    score = sc2;\n                } else {\n                    for (auto &p : backup) rot[p.first] = p.second;\n                }\n            }\n        }\n    }\n\n    void solve() {\n        Timer timer;\n        const double TL = 1.95;\n\n        array<unsigned char, NN> bestRot = zeroRot();\n        long long bestScore = evalExact(bestRot);\n\n        vector<array<unsigned char, NN>> initials;\n        initials.push_back(zeroRot());\n        for (int t = 0; t < 4; t++) initials.push_back(patternRot(t));\n        for (int t = 0; t < 6; t++) initials.push_back(randomRot());\n\n        int ptr = 0;\n        while (timer.elapsed() < TL) {\n            array<unsigned char, NN> cur = initials[ptr % initials.size()];\n            long long curScore = 0;\n            double rem = TL - timer.elapsed();\n            double slice = min(0.25, rem);\n            hillClimb(cur, curScore, timer, timer.elapsed() + slice);\n\n            if (curScore > bestScore) {\n                bestScore = curScore;\n                bestRot = cur;\n            }\n            ptr++;\n            if (ptr > 1000000) break;\n        }\n\n        string ans;\n        ans.resize(NN);\n        for (int i = 0; i < NN; i++) ans[i] = char('0' + bestRot[i]);\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.readInput();\n    solver.solve();\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        auto ed = chrono::steady_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstatic constexpr int di[4] = {-1, 1, 0, 0};\nstatic constexpr int dj[4] = {0, 0, -1, 1};\nstatic constexpr char dc[4] = {'U', 'D', 'L', 'R'};\n\nint N, Tlim;\nvector<int> init_board;\nint init_empty;\n\ninline int opp_dir(int d) {\n    if (d == 0) return 1;\n    if (d == 1) return 0;\n    if (d == 2) return 3;\n    return 2;\n}\n\ninline bool can_move(int empty_pos, int d) {\n    int i = empty_pos / N, j = empty_pos % N;\n    int ni = i + di[d], nj = j + dj[d];\n    return (0 <= ni && ni < N && 0 <= nj && nj < N);\n}\n\n// Problem statement: output character denotes sliding the upward/downward/leftward/rightward adjacent tile into the empty square.\n// So if move is 'U', the tile above empty moves down into empty => empty moves up.\n// Hence our direction d is new empty movement direction as well.\ninline void apply_move(vector<int>& board, int& empty_pos, int d) {\n    int ei = empty_pos / N, ej = empty_pos % N;\n    int ni = ei + di[d], nj = ej + dj[d];\n    int np = ni * N + nj;\n    swap(board[empty_pos], board[np]);\n    empty_pos = np;\n}\n\nint evaluate_board(const vector<int>& board) {\n    int V = N * N;\n    vector<vector<int>> g(V);\n    vector<int> alive(V, 1);\n    int empty = -1;\n    for (int p = 0; p < V; ++p) {\n        if (board[p] == 0) {\n            alive[p] = 0;\n            empty = p;\n        }\n    }\n\n    auto has = [&](int mask, int bit) -> bool {\n        return (mask & bit) != 0;\n    };\n\n    int edges2 = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int p = i * N + j;\n            if (!alive[p]) continue;\n            int m = board[p];\n            if (i + 1 < N) {\n                int q = (i + 1) * N + j;\n                if (alive[q] && has(m, 8) && has(board[q], 2)) {\n                    g[p].push_back(q);\n                    g[q].push_back(p);\n                    edges2 += 2;\n                }\n            }\n            if (j + 1 < N) {\n                int q = i * N + (j + 1);\n                if (alive[q] && has(m, 4) && has(board[q], 1)) {\n                    g[p].push_back(q);\n                    g[q].push_back(p);\n                    edges2 += 2;\n                }\n            }\n        }\n    }\n\n    vector<int> vis(V, 0);\n    int best = 0;\n    for (int s = 0; s < V; ++s) {\n        if (!alive[s] || vis[s]) continue;\n        queue<int> q;\n        q.push(s);\n        vis[s] = 1;\n        int vc = 0;\n        long long degsum = 0;\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            vc++;\n            degsum += (int)g[v].size();\n            for (int to : g[v]) {\n                if (!vis[to]) {\n                    vis[to] = 1;\n                    q.push(to);\n                }\n            }\n        }\n        long long ec = degsum / 2;\n        if (ec == vc - 1) best = max(best, vc);\n    }\n    return best;\n}\n\nstruct StateSeq {\n    string ops;\n    int score = -1;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    init_board.assign(N * N, 0);\n    for (int i = 0; i < N; ++i) {\n        string s; cin >> s;\n        for (int j = 0; j < N; ++j) {\n            char c = s[j];\n            int v;\n            if ('0' <= c && c <= '9') v = c - '0';\n            else v = 10 + (c - 'a');\n            init_board[i * N + j] = v;\n            if (v == 0) init_empty = i * N + j;\n        }\n    }\n\n    Timer timer;\n    mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\n    StateSeq best;\n    best.score = evaluate_board(init_board);\n    best.ops = \"\";\n\n    // Precompute initial legal moves cache unnecessary; board legality depends only on empty.\n    // Strategy:\n    // - many random walks\n    // - some mutations around best sequence prefix\n    const double TL = 2.90;\n\n    auto build_and_eval = [&](const string& ops) -> int {\n        vector<int> board = init_board;\n        int empty = init_empty;\n        for (char c : ops) {\n            int d = (c == 'U' ? 0 : c == 'D' ? 1 : c == 'L' ? 2 : 3);\n            if (!can_move(empty, d)) return -1;\n            apply_move(board, empty, d);\n        }\n        return evaluate_board(board);\n    };\n\n    auto random_walk = [&](int maxlen, bool avoid_backtrack = true) -> StateSeq {\n        vector<int> board = init_board;\n        int empty = init_empty;\n        string ops;\n        int prev = -1;\n\n        int curScore = evaluate_board(board);\n        StateSeq local_best{ops, curScore};\n\n        uniform_int_distribution<int> lenDist(0, maxlen);\n        int target_len = lenDist(rng);\n\n        for (int step = 0; step < target_len; ++step) {\n            int cand[4], cnt = 0;\n            for (int d = 0; d < 4; ++d) {\n                if (!can_move(empty, d)) continue;\n                if (avoid_backtrack && prev != -1 && d == opp_dir(prev)) continue;\n                cand[cnt++] = d;\n            }\n            if (cnt == 0) {\n                for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n            }\n            int d = cand[rng() % cnt];\n            apply_move(board, empty, d);\n            ops.push_back(dc[d]);\n            prev = d;\n\n            int sc = evaluate_board(board);\n            if (sc > local_best.score) {\n                local_best.score = sc;\n                local_best.ops = ops;\n            }\n        }\n        return local_best;\n    };\n\n    auto mutate_from = [&](const string& base) -> StateSeq {\n        if (base.empty()) return random_walk(Tlim, true);\n\n        int L = (int)base.size();\n        uniform_int_distribution<int> cutDist(0, L);\n        int cut = cutDist(rng);\n\n        vector<int> board = init_board;\n        int empty = init_empty;\n        string ops;\n        ops.reserve(Tlim);\n\n        int prev = -1;\n        for (int i = 0; i < cut; ++i) {\n            char c = base[i];\n            int d = (c == 'U' ? 0 : c == 'D' ? 1 : c == 'L' ? 2 : 3);\n            if (!can_move(empty, d)) break;\n            apply_move(board, empty, d);\n            ops.push_back(c);\n            prev = d;\n        }\n\n        int curScore = evaluate_board(board);\n        StateSeq local_best{ops, curScore};\n\n        uniform_int_distribution<int> extendDist(0, Tlim - (int)ops.size());\n        int extra = extendDist(rng);\n\n        for (int step = 0; step < extra && (int)ops.size() < Tlim; ++step) {\n            int cand[4], cnt = 0;\n            for (int d = 0; d < 4; ++d) {\n                if (!can_move(empty, d)) continue;\n                if (prev != -1 && d == opp_dir(prev) && (rng() & 3)) continue;\n                cand[cnt++] = d;\n            }\n            if (cnt == 0) {\n                for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n            }\n            int d = cand[rng() % cnt];\n            apply_move(board, empty, d);\n            ops.push_back(dc[d]);\n            prev = d;\n\n            if ((step & 3) == 0) {\n                int sc = evaluate_board(board);\n                if (sc > local_best.score) {\n                    local_best.score = sc;\n                    local_best.ops = ops;\n                }\n            }\n        }\n\n        int finalScore = evaluate_board(board);\n        if (finalScore > local_best.score) {\n            local_best.score = finalScore;\n            local_best.ops = ops;\n        }\n        return local_best;\n    };\n\n    while (timer.elapsed() < TL) {\n        StateSeq cand;\n        if ((rng() % 100) < 40) cand = random_walk(Tlim, true);\n        else cand = mutate_from(best.ops);\n\n        if (cand.score > best.score || (cand.score == best.score && cand.ops.size() < best.ops.size())) {\n            best = cand;\n            if (best.score == N * N - 1 && best.ops.size() == 0) break;\n        }\n    }\n\n    cout << best.ops << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nstruct Candidate {\n    int score = -1;\n    double theta = 0.0;\n    vector<int> groups; // consecutive segment sizes summing to N\n};\n\nstatic const double R = 10000.0;\nstatic const long long LIM = 1000000000LL;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    vector<int> a(11);\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // Candidate directions.\n    // Enough diversity while keeping runtime safe.\n    int M = 180;\n\n    Candidate best;\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n\n    vector<double> proj(N);\n    vector<int> ord(N);\n\n    for (int it = 0; it < M; it++) {\n        double theta = M_PI * it / M; // [0, pi)\n        double c = cos(theta), s = sin(theta);\n\n        for (int i = 0; i < N; i++) {\n            proj[i] = p[i].x * c + p[i].y * s;\n            ord[i] = i;\n        }\n        sort(ord.begin(), ord.end(), [&](int i, int j) {\n            if (proj[i] != proj[j]) return proj[i] < proj[j];\n            return i < j;\n        });\n\n        // Try a few prefix leftovers. Prefix of length off is made junk by merging into first group.\n        // Then DP on remaining suffix using group sizes 1..10.\n        for (int off = 0; off <= min(10, N); off++) {\n            int rem = N - off;\n            if (rem <= 0) continue;\n\n            // dp[pos][used1..used10] is impossible; too large.\n            // Instead, because each useful group size d only gives gain up to a[d],\n            // we can greedily reward first a[d] groups of size d encountered.\n            // To optimize globally, keep counts of used sizes in state is too big.\n            //\n            // Simpler surrogate:\n            // value of a group of size d is w[d], where rarer / demanded sizes get more weight.\n            // Then after reconstructing, actual score is min(count[d], a[d]).\n            //\n            // We use lexicographic-ish weights favoring demanded sizes:\n            static double w[11];\n            for (int d = 1; d <= 10; d++) {\n                // Positive weight only if there is demand.\n                // Slightly prefer smaller d as they are easier to realize many times.\n                w[d] = (a[d] > 0 ? (1000.0 + 10.0 * a[d] - d) : 0.0);\n            }\n\n            vector<double> dp(rem + 1, -1e100);\n            vector<int> prv(rem + 1, -1), take(rem + 1, -1);\n            dp[0] = 0.0;\n\n            for (int i = 0; i < rem; i++) {\n                if (dp[i] < -1e90) continue;\n                for (int d = 1; d <= 10; d++) {\n                    if (i + d <= rem) {\n                        double ndp = dp[i] + w[d];\n                        if (ndp > dp[i + d]) {\n                            dp[i + d] = ndp;\n                            prv[i + d] = i;\n                            take[i + d] = d;\n                        }\n                    }\n                }\n            }\n\n            // Since rem can always be fully tiled by 1..10, use rem.\n            vector<int> gs_rev;\n            int cur = rem;\n            while (cur > 0) {\n                gs_rev.push_back(take[cur]);\n                cur = prv[cur];\n            }\n            reverse(gs_rev.begin(), gs_rev.end());\n\n            vector<int> groups;\n            if (off > 0) {\n                if (!gs_rev.empty()) gs_rev[0] += off;\n                else groups.push_back(off);\n            }\n            for (int x : gs_rev) groups.push_back(x);\n\n            // If too many cuts, reject. (#pieces = groups.size(), cuts = pieces-1)\n            if ((int)groups.size() - 1 > K) continue;\n\n            vector<int> cnt(11, 0);\n            for (int g : groups) if (1 <= g && g <= 10) cnt[g]++;\n            int realScore = 0;\n            for (int d = 1; d <= 10; d++) realScore += min(a[d], cnt[d]);\n\n            if (realScore > best.score) {\n                best.score = realScore;\n                best.theta = theta;\n                best.groups = groups;\n            }\n        }\n    }\n\n    // Fallback: all singletons for first min(N,101) pieces via one direction.\n    if (best.score < 0) {\n        best.theta = 0.0;\n        best.groups.clear();\n        int rem = N;\n        while (rem > 0 && (int)best.groups.size() < K) {\n            best.groups.push_back(1);\n            rem--;\n        }\n        best.groups.push_back(rem);\n    }\n\n    double c = cos(best.theta), s = sin(best.theta);\n\n    for (int i = 0; i < N; i++) {\n        proj[i] = p[i].x * c + p[i].y * s;\n        ord[i] = i;\n    }\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (proj[i] != proj[j]) return proj[i] < proj[j];\n        return i < j;\n    });\n\n    vector<double> alphas;\n    int pref = 0;\n    for (int i = 0; i + 1 < (int)best.groups.size(); i++) {\n        pref += best.groups[i];\n        // cut between ord[pref-1] and ord[pref]\n        double a1 = proj[ord[pref - 1]];\n        double a2 = proj[ord[pref]];\n        double alpha = (a1 + a2) * 0.5;\n        alphas.push_back(alpha);\n    }\n\n    // Build integer line representation for c x + s y = alpha.\n    // Point on line: alpha * (c, s)\n    // Direction along line: (-s, c)\n    // Use large scale, then round.\n    auto clampLL = [&](long long x) -> long long {\n        return max(-LIM, min(LIM, x));\n    };\n\n    cout << alphas.size() << '\\n';\n    const double T = 200000.0; // large enough\n    for (double alpha : alphas) {\n        double x0 = alpha * c;\n        double y0 = alpha * s;\n        double dx = -s, dy = c;\n\n        long long x1 = llround(x0 + T * dx);\n        long long y1 = llround(y0 + T * dy);\n        long long x2 = llround(x0 - T * dx);\n        long long y2 = llround(y0 - T * dy);\n\n        x1 = clampLL(x1);\n        y1 = clampLL(y1);\n        x2 = clampLL(x2);\n        y2 = clampLL(y2);\n\n        // Ensure distinct points.\n        if (x1 == x2 && y1 == y2) {\n            x2++;\n            if (x2 > LIM) x2 -= 2;\n        }\n\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstruct Op {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nstatic constexpr int DX4[4] = {1, 0, 1, 1};   // H, V, D\\, D/\nstatic constexpr int DY4[4] = {0, 1, 1, -1};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M;\n    cin >> N >> M;\n\n    vector<vector<char>> dot(N, vector<char>(N, 0));\n    for (int i = 0; i < M; i++) {\n        int x, y;\n        cin >> x >> y;\n        dot[x][y] = 1;\n    }\n\n    // used unit segments\n    // horizontal: (x,y) -> (x+1,y), 0<=x<N-1, 0<=y<N\n    vector<vector<char>> usedH(max(0, N - 1), vector<char>(N, 0));\n    // vertical: (x,y) -> (x,y+1), 0<=x<N, 0<=y<N-1\n    vector<vector<char>> usedV(N, vector<char>(max(0, N - 1), 0));\n    // diag down-right \"\\\" : (x,y) -> (x+1,y+1), 0<=x,y<N-1\n    vector<vector<char>> usedD1(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n    // diag up-right \"/\" : (x,y) -> (x+1,y-1), canonical by lower point (x,y-1)->(x+1,y)\n    // store at (x, ylow), segment (x,ylow)->(x+1,ylow+1)\n    vector<vector<char>> usedD2(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    auto weight = [&](int x, int y) -> int {\n        int c = (N - 1) / 2;\n        int dx = x - c, dy = y - c;\n        return dx * dx + dy * dy + 1;\n    };\n\n    auto getSegUsed = [&](int x1, int y1, int x2, int y2) -> bool {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            return usedV[x1][y1];\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            return usedH[x1][y1];\n        } else if (x2 - x1 == y2 - y1) { // \"\\\"\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            return usedD1[x1][y1];\n        } else { // \"/\"\n            // canonical lower-left to upper-right\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            return usedD2[x1][yl];\n        }\n    };\n\n    auto setSegUsed = [&](int x1, int y1, int x2, int y2) {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            usedV[x1][y1] = 1;\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            usedH[x1][y1] = 1;\n        } else if (x2 - x1 == y2 - y1) { // \"\\\"\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            usedD1[x1][y1] = 1;\n        } else { // \"/\"\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            usedD2[x1][yl] = 1;\n        }\n    };\n\n    auto edge_clear_and_unused = [&](int ax, int ay, int bx, int by) -> bool {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            if (getSegUsed(x, y, nx, ny)) return false;\n            if (t + 1 < len) {\n                if (dot[nx][ny]) return false; // intermediate lattice point on perimeter cannot have dot\n            }\n            x = nx; y = ny;\n        }\n        return true;\n    };\n\n    auto mark_edge = [&](int ax, int ay, int bx, int by) {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            setSegUsed(x, y, nx, ny);\n            x = nx; y = ny;\n        }\n    };\n\n    auto legal_rect = [&](int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) -> bool {\n        if (!inside(x1, y1) || !inside(x2, y2) || !inside(x3, y3) || !inside(x4, y4)) return false;\n        if (dot[x1][y1]) return false;\n        if (!dot[x2][y2] || !dot[x3][y3] || !dot[x4][y4]) return false;\n\n        // Check edges are among allowed directions and contiguous.\n        auto ok_edge = [&](int ax, int ay, int bx, int by) -> bool {\n            int dx = bx - ax, dy = by - ay;\n            if (dx == 0 && dy != 0) return true;\n            if (dy == 0 && dx != 0) return true;\n            if (abs(dx) == abs(dy) && dx != 0) return true;\n            return false;\n        };\n        if (!ok_edge(x1,y1,x2,y2) || !ok_edge(x2,y2,x3,y3) || !ok_edge(x3,y3,x4,y4) || !ok_edge(x4,y4,x1,y1)) return false;\n\n        // Orthogonality and parallelogram shape\n        int a1x = x2 - x1, a1y = y2 - y1;\n        int b1x = x4 - x1, b1y = y4 - y1;\n        if (a1x == 0 && a1y == 0) return false;\n        if (b1x == 0 && b1y == 0) return false;\n        if (a1x * b1x + a1y * b1y != 0) return false;\n        if (x3 != x2 + b1x || y3 != y2 + b1y) return false;\n        if (x3 != x4 + a1x || y3 != y4 + a1y) return false;\n\n        // perimeter checks\n        if (!edge_clear_and_unused(x1,y1,x2,y2)) return false;\n        if (!edge_clear_and_unused(x2,y2,x3,y3)) return false;\n        if (!edge_clear_and_unused(x3,y3,x4,y4)) return false;\n        if (!edge_clear_and_unused(x4,y4,x1,y1)) return false;\n\n        return true;\n    };\n\n    vector<Op> ans;\n\n    auto apply_rect = [&](const Op& op) {\n        dot[op.x1][op.y1] = 1;\n        mark_edge(op.x1, op.y1, op.x2, op.y2);\n        mark_edge(op.x2, op.y2, op.x3, op.y3);\n        mark_edge(op.x3, op.y3, op.x4, op.y4);\n        mark_edge(op.x4, op.y4, op.x1, op.y1);\n        ans.push_back(op);\n    };\n\n    // Precompute occupied list updater on demand\n    auto collect_dots = [&]() {\n        vector<pair<int,int>> pts;\n        pts.reserve(N * N);\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) if (dot[x][y]) pts.push_back({x,y});\n        return pts;\n    };\n\n    // Candidate generation:\n    // for each empty p1, look for small to medium rectangles using occupied p2/p4 and checking p3.\n    // prioritize high weight and modest perimeter.\n    const double TL = 4.8;\n\n    while (timer.elapsed() < TL) {\n        Op best{};\n        double bestScore = -1e100;\n        bool found = false;\n\n        auto pts = collect_dots();\n\n        // To speed up point existence checks already using dot[].\n        // Enumerate empty cells in descending weight order via shells from outside.\n        vector<pair<int,int>> empties;\n        empties.reserve(N * N);\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) if (!dot[x][y]) empties.push_back({x,y});\n        sort(empties.begin(), empties.end(), [&](auto& a, auto& b) {\n            return weight(a.first, a.second) > weight(b.first, b.second);\n        });\n\n        // Dynamic caps to keep time safe.\n        int maxEmpties = (timer.elapsed() < 2.5 ? (int)empties.size() : min((int)empties.size(), 400));\n        int maxPtsScan = (timer.elapsed() < 2.5 ? (int)pts.size() : min((int)pts.size(), 250));\n\n        for (int ei = 0; ei < maxEmpties && timer.elapsed() < TL; ei++) {\n            auto [x1, y1] = empties[ei];\n\n            // Axis-aligned candidates:\n            // choose p2 on same row, p4 on same col\n            int scanned2 = 0;\n            for (auto [x2, y2] : pts) {\n                if (scanned2 >= maxPtsScan) break;\n                scanned2++;\n                if (y2 != y1 || x2 == x1) continue;\n                int x3 = x2;\n\n                // p4 determines y4, and p3=(x2,y4)\n                // use existing points on x=x1\n                int scanned4 = 0;\n                for (auto [x4, y4] : pts) {\n                    if (scanned4 >= maxPtsScan) break;\n                    scanned4++;\n                    if (x4 != x1 || y4 == y1) continue;\n                    if (!inside(x3, y4) || !dot[x3][y4]) continue;\n\n                    if (legal_rect(x1,y1,x2,y2,x3,y4,x4,y4)) {\n                        int perim = abs(x2-x1) + abs(y4-y1);\n                        double sc = 1000.0 * weight(x1,y1) - 1.0 * perim;\n                        if (sc > bestScore) {\n                            bestScore = sc;\n                            best = {x1,y1,x2,y2,x3,y4,x4,y4};\n                            found = true;\n                        }\n                    }\n                }\n            }\n\n            // Rotated 45-degree candidates:\n            // p2 = p1 + a, p4 = p1 + b where a=(d,d') with |d|=|d'|, b=(-d',d)\n            // enumerate using existing p2\n            int scannedR = 0;\n            for (auto [x2, y2] : pts) {\n                if (scannedR >= maxPtsScan) break;\n                scannedR++;\n                int ax = x2 - x1, ay = y2 - y1;\n                if (ax == 0 && ay == 0) continue;\n                if (abs(ax) != abs(ay)) continue; // edge of rotated rect\n                int bx = -ay, by = ax;\n                int x4 = x1 + bx, y4 = y1 + by;\n                int x3 = x2 + bx, y3 = y2 + by;\n                if (!inside(x4,y4) || !inside(x3,y3)) continue;\n                if (!dot[x4][y4] || !dot[x3][y3]) continue;\n\n                if (legal_rect(x1,y1,x2,y2,x3,y3,x4,y4)) {\n                    int perim = max(abs(ax),abs(ay)) * 2;\n                    double sc = 1000.0 * weight(x1,y1) - 1.5 * perim;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = {x1,y1,x2,y2,x3,y3,x4,y4};\n                        found = true;\n                    }\n                }\n\n                // other orientation: b=(ay,-ax)\n                bx = ay; by = -ax;\n                x4 = x1 + bx; y4 = y1 + by;\n                x3 = x2 + bx; y3 = y2 + by;\n                if (!inside(x4,y4) || !inside(x3,y3)) continue;\n                if (!dot[x4][y4] || !dot[x3][y3]) continue;\n\n                if (legal_rect(x1,y1,x2,y2,x3,y3,x4,y4)) {\n                    int perim = max(abs(ax),abs(ay)) * 2;\n                    double sc = 1000.0 * weight(x1,y1) - 1.5 * perim;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        best = {x1,y1,x2,y2,x3,y3,x4,y4};\n                        found = true;\n                    }\n                }\n            }\n        }\n\n        if (!found) break;\n        apply_rect(best);\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto &op : ans) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << ' '\n             << op.x3 << ' ' << op.y3 << ' '\n             << op.x4 << ' ' << op.y4 << '\\n';\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\nstatic constexpr int EMPTY = 0;\n\nstruct Pos {\n    int r, c;\n};\n\nstruct Board {\n    int a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n\n    int occupied() const {\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cnt += (a[i][j] != 0);\n        return cnt;\n    }\n\n    vector<Pos> empty_cells_ordered() const {\n        vector<Pos> e;\n        e.reserve(100 - occupied());\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) e.push_back({i, j});\n        }\n        return e;\n    }\n\n    void place_by_index(int p, int flavor) {\n        // p is 1-indexed among empty cells in row-major order\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) {\n                cnt++;\n                if (cnt == p) {\n                    a[i][j] = flavor;\n                    return;\n                }\n            }\n        }\n        // should never happen\n        assert(false);\n    }\n\n    Board tilted(char dir) const {\n        Board b;\n        if (dir == 'L') {\n            for (int i = 0; i < N; i++) {\n                int t = 0;\n                for (int j = 0; j < N; j++) if (a[i][j] != 0) b.a[i][t++] = a[i][j];\n            }\n        } else if (dir == 'R') {\n            for (int i = 0; i < N; i++) {\n                int t = N - 1;\n                for (int j = N - 1; j >= 0; j--) if (a[i][j] != 0) b.a[i][t--] = a[i][j];\n            }\n        } else if (dir == 'F') { // up\n            for (int j = 0; j < N; j++) {\n                int t = 0;\n                for (int i = 0; i < N; i++) if (a[i][j] != 0) b.a[t++][j] = a[i][j];\n            }\n        } else if (dir == 'B') { // down\n            for (int j = 0; j < N; j++) {\n                int t = N - 1;\n                for (int i = N - 1; i >= 0; i--) if (a[i][j] != 0) b.a[t--][j] = a[i][j];\n            }\n        } else {\n            assert(false);\n        }\n        return b;\n    }\n\n    long long comp_square_sum() const {\n        bool vis[N][N];\n        memset(vis, 0, sizeof(vis));\n        long long res = 0;\n        static const int dr[4] = {-1,1,0,0};\n        static const int dc[4] = {0,0,-1,1};\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0 || vis[i][j]) continue;\n            int col = a[i][j];\n            int sz = 0;\n            queue<pair<int,int>> q;\n            q.push({i,j});\n            vis[i][j] = true;\n            while (!q.empty()) {\n                auto [r,c] = q.front(); q.pop();\n                sz++;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (!vis[nr][nc] && a[nr][nc] == col) {\n                        vis[nr][nc] = true;\n                        q.push({nr,nc});\n                    }\n                }\n            }\n            res += 1LL * sz * sz;\n        }\n        return res;\n    }\n};\n\nstruct AnchorSet {\n    Pos p[4];\n    int m;\n};\n\nstatic vector<Pos> candidateAnchors = {\n    {0,0}, {0,9}, {9,0}, {9,9}, // corners\n    {0,4}, {0,5}, {9,4}, {9,5}, // top/bottom centers\n    {4,0}, {5,0}, {4,9}, {5,9}, // left/right centers\n    {2,2}, {2,7}, {7,2}, {7,7}  // inner corners\n};\n\nstruct Solver {\n    vector<int> f;              // 1..100\n    int totalCnt[4]{};\n    Pos flavorAnchor[4];\n    mt19937 rng;\n\n    Solver(const vector<int>& flavors) : f(flavors), rng(712367821) {\n        for (int x : f) totalCnt[x]++;\n        choose_anchors();\n    }\n\n    void choose_anchors() {\n        // Choose 3 distinct anchors out of a curated set.\n        // Objective: spread frequent flavors apart.\n        // We simply maximize weighted pairwise distances between assigned anchors,\n        // favoring larger-count flavors to occupy more separated locations.\n        long long best = LLONG_MIN;\n        array<int,3> bestIdx = {0,1,2};\n\n        vector<int> ord = {1,2,3};\n        sort(ord.begin(), ord.end(), [&](int x, int y){ return totalCnt[x] > totalCnt[y]; });\n\n        int M = (int)candidateAnchors.size();\n        for (int i = 0; i < M; i++) for (int j = 0; j < M; j++) if (j != i)\n        for (int k = 0; k < M; k++) if (k != i && k != j) {\n            Pos a = candidateAnchors[i];\n            Pos b = candidateAnchors[j];\n            Pos c = candidateAnchors[k];\n            auto dist = [&](Pos u, Pos v) {\n                return abs(u.r - v.r) + abs(u.c - v.c);\n            };\n            long long score = 0;\n            // Larger counts should be far apart\n            score += 1LL * totalCnt[ord[0]] * totalCnt[ord[1]] * dist(a, b);\n            score += 1LL * totalCnt[ord[0]] * totalCnt[ord[2]] * dist(a, c);\n            score += 1LL * totalCnt[ord[1]] * totalCnt[ord[2]] * dist(b, c);\n\n            // Prefer actual corners slightly\n            auto corner_bonus = [&](Pos p) {\n                return (p.r == 0 || p.r == 9) && (p.c == 0 || p.c == 9) ? 8 : 0;\n            };\n            score += corner_bonus(a) + corner_bonus(b) + corner_bonus(c);\n\n            if (score > best) {\n                best = score;\n                bestIdx = {i,j,k};\n            }\n        }\n\n        flavorAnchor[ord[0]] = candidateAnchors[bestIdx[0]];\n        flavorAnchor[ord[1]] = candidateAnchors[bestIdx[1]];\n        flavorAnchor[ord[2]] = candidateAnchors[bestIdx[2]];\n    }\n\n    double evaluate(const Board& b, int turn) const {\n        // Main score term\n        double score = 0.0;\n\n        long long comp = b.comp_square_sum();\n        score += 2000.0 * comp;\n\n        // Adjacency\n        int sameAdj = 0, diffAdj = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j] != 0) {\n            if (i + 1 < N && b.a[i+1][j] != 0) {\n                if (b.a[i+1][j] == b.a[i][j]) sameAdj++;\n                else diffAdj++;\n            }\n            if (j + 1 < N && b.a[i][j+1] != 0) {\n                if (b.a[i][j+1] == b.a[i][j]) sameAdj++;\n                else diffAdj++;\n            }\n        }\n        score += 180.0 * sameAdj;\n        score -= 120.0 * diffAdj;\n\n        // Distance to anchors\n        // Stronger in early-mid game to enforce territorial separation.\n        double wAnchor = (turn <= 70 ? 26.0 : (turn <= 90 ? 18.0 : 8.0));\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j] != 0) {\n            Pos p = flavorAnchor[b.a[i][j]];\n            int d = abs(i - p.r) + abs(j - p.c);\n            score -= wAnchor * d;\n        }\n\n        // Row/column purity encouragement\n        // Helps build strips/blobs under repeated compression.\n        for (int i = 0; i < N; i++) {\n            int cnt[4] = {};\n            for (int j = 0; j < N; j++) cnt[b.a[i][j]]++;\n            score += 12.0 * (cnt[1]*cnt[1] + cnt[2]*cnt[2] + cnt[3]*cnt[3]);\n        }\n        for (int j = 0; j < N; j++) {\n            int cnt[4] = {};\n            for (int i = 0; i < N; i++) cnt[b.a[i][j]]++;\n            score += 12.0 * (cnt[1]*cnt[1] + cnt[2]*cnt[2] + cnt[3]*cnt[3]);\n        }\n\n        // Slight reward for convex packing toward borders:\n        int borderCnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j] != 0) {\n            if (i == 0 || i == 9 || j == 0 || j == 9) borderCnt++;\n        }\n        score += 15.0 * borderCnt;\n\n        return score;\n    }\n\n    double expected_one_step(const Board& b, int turn) const {\n        // If there is a next turn, sample possible next insertions and best response.\n        if (turn >= 100) return evaluate(b, turn);\n\n        int nextFlavor = f[turn]; // 0-indexed vector; turn is current 1-based, next is index turn\n        vector<Pos> empties = b.empty_cells_ordered();\n        int m = (int)empties.size();\n        if (m == 0) return evaluate(b, turn);\n\n        vector<int> samples;\n        if (m <= 10) {\n            for (int i = 0; i < m; i++) samples.push_back(i);\n        } else {\n            // deterministic spread samples\n            int S = min(8, m);\n            for (int s = 0; s < S; s++) {\n                int idx = (long long)s * m / S;\n                if (idx >= m) idx = m - 1;\n                samples.push_back(idx);\n            }\n        }\n\n        static const char dirs[4] = {'F','B','L','R'};\n        double acc = 0.0;\n        for (int idx : samples) {\n            Board nb = b;\n            nb.a[empties[idx].r][empties[idx].c] = nextFlavor;\n\n            double bestv = -1e100;\n            for (char d : dirs) {\n                Board tb = nb.tilted(d);\n                bestv = max(bestv, evaluate(tb, turn + 1));\n            }\n            acc += bestv;\n        }\n        return acc / samples.size();\n    }\n\n    char decide(const Board& board, int turn) {\n        static const char dirs[4] = {'F','B','L','R'};\n        char bestDir = 'F';\n        double bestScore = -1e100;\n\n        bool useLookahead = (turn >= 85);\n\n        for (char d : dirs) {\n            Board tb = board.tilted(d);\n            double sc = evaluate(tb, turn);\n            if (useLookahead) {\n                sc = 0.55 * sc + 0.45 * expected_one_step(tb, turn);\n            }\n            // Tiny deterministic tie-break preference to avoid oscillation\n            sc += (d == 'F' ? 0.03 : d == 'L' ? 0.02 : d == 'R' ? 0.01 : 0.0);\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = d;\n            }\n        }\n        return bestDir;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Solver solver(f);\n    Board board;\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        board.place_by_index(p, f[t-1]);\n        char ans = solver.decide(board, t);\n\n        // Apply chosen move to maintain internal state\n        board = board.tilted(ans);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC016 - heuristic solution\n\nIdea\n----\nVertex labels are lost, so we should use graph features invariant under permutation.\nA simple and fairly strong invariant is the sorted degree sequence.\n\nConstruction:\n- Use one common N.\n- For each graph G_k, create a threshold graph:\n    choose x_k \"dominant\" vertices connected to all others,\n    and the remaining vertices isolated among themselves.\n  Then degree multiset is:\n    x_k vertices of degree N-1\n    N-x_k vertices of degree x_k\n  This is uniquely determined by x_k (except tiny degeneracies avoided by N>=4).\n- So each graph is identified by one parameter x_k.\n\nDecoding:\n- From received H, compute degree sequence, sort it.\n- Compare against the expected noisy degree distributions of every codeword x_k.\n- Since each edge flips independently with probability eps, each vertex degree is approximately:\n    original_degree * (1-eps) + (N-1-original_degree) * eps\n  We score a candidate by sum of squared errors to the sorted expected degrees.\n- Also compare edge count likelihood as auxiliary score.\n\nChoosing N and codewords:\n- Need M distinct graphs. We only have N+1 possible x values, so N >= M-1.\n- To improve robustness, spread codewords across [0, N].\n- Since score has 1/N penalty, use the minimum N that allows spacing:\n    N = min(100, max(4, M-1))\n  Then just set x_k = k.\nThis is simple, safe, and fast.\n\nThis is not state-of-the-art, but robust and compact.\n*/\n\nstatic string make_graph_threshold(int N, int x) {\n    // Vertices [0, x) are dominant: connected to everyone else.\n    // Vertices [x, N) have no edges among themselves.\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            char c = (i < x || j < x) ? '1' : '0';\n            s.push_back(c);\n        }\n    }\n    return s;\n}\n\nstatic vector<int> degree_sequence_from_string(int N, const string& g) {\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 (g[p++] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    int N = max(4, M - 1);\n    N = min(N, 100);\n\n    vector<int> xs(M);\n    for (int k = 0; k < M; ++k) xs[k] = k; // since N >= M-1\n\n    vector<string> graphs(M);\n    vector<vector<double>> exp_deg_sorted(M, vector<double>(N));\n    vector<double> exp_edges(M);\n\n    for (int k = 0; k < M; ++k) {\n        int x = xs[k];\n        graphs[k] = make_graph_threshold(N, x);\n\n        double d_small = x * (1.0 - eps) + (N - 1 - x) * eps;\n        double d_big = (N - 1) * (1.0 - eps); // since original degree N-1\n        int cnt_small = N - x, cnt_big = x;\n\n        for (int i = 0; i < cnt_small; ++i) exp_deg_sorted[k][i] = d_small;\n        for (int i = 0; i < cnt_big; ++i) exp_deg_sorted[k][cnt_small + i] = d_big;\n\n        double m0 = 1.0 * x * (2 * N - x - 1) / 2.0; // #edges in threshold graph\n        double total = 1.0 * N * (N - 1) / 2.0;\n        exp_edges[k] = m0 * (1.0 - eps) + (total - m0) * eps;\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\n        vector<int> deg = degree_sequence_from_string(N, H);\n        int edges = 0;\n        for (char c : H) if (c == '1') edges++;\n\n        int best = 0;\n        double best_score = 1e100;\n\n        for (int k = 0; k < M; ++k) {\n            double sse = 0.0;\n            for (int i = 0; i < N; ++i) {\n                double diff = deg[i] - exp_deg_sorted[k][i];\n                sse += diff * diff;\n            }\n            double ediff = edges - exp_edges[k];\n            double score = sse + 0.5 * ediff * ediff;\n            if (score < best_score) {\n                best_score = 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    int cell;\n    double imp = 0.0;\n};\n\nstatic const long long INF64 = (1LL << 60);\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>>> g(N); // to, edge id\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        g[u].push_back({v, i});\n        g[v].push_back({u, i});\n    }\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n    // ---- Build geometric cells from edge midpoints ----\n    // Coarse grid. Since coordinates are in [0,1000], 6x6 or 7x7 works well.\n    const int G = 6;\n    auto get_cell = [&](double x, double y) {\n        int gx = min(G - 1, max(0, (int)(x * G / 1001.0)));\n        int gy = min(G - 1, max(0, (int)(y * G / 1001.0)));\n        return gy * G + gx;\n    };\n    int C = G * G;\n    for (int i = 0; i < M; i++) {\n        double mx = (xs[edges[i].u] + xs[edges[i].v]) * 0.5;\n        double my = (ys[edges[i].u] + ys[edges[i].v]) * 0.5;\n        edges[i].cell = get_cell(mx, my);\n    }\n\n    // ---- Approximate edge importance by sampled shortest path trees ----\n    vector<double> imp(M, 0.0);\n    vector<double> vcen(N, 0.0);\n\n    // Sample roots: far-spread by coordinates + random-ish deterministic picks.\n    vector<int> roots;\n    roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n    roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n    roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n    roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n\n    // Add a few deterministic pseudo-random roots.\n    int S = min(24, max(8, 2 * D));\n    for (int t = 0; (int)roots.size() < S; t++) {\n        int r = (int)((1LL * t * 911382323 + 972663749) % N);\n        roots.push_back(r);\n    }\n    sort(roots.begin(), roots.end());\n    roots.erase(unique(roots.begin(), roots.end()), roots.end());\n\n    vector<long long> dist(N);\n    vector<int> parent_e(N), parent_v(N);\n\n    auto dijkstra = [&](int s) {\n        fill(dist.begin(), dist.end(), INF64);\n        fill(parent_e.begin(), parent_e.end(), -1);\n        fill(parent_v.begin(), parent_v.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        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    parent_e[to] = ei;\n                    parent_v[to] = v;\n                    pq.push({nd, to});\n                } else if (nd == dist[to]) {\n                    // Tie-breaking: prefer larger weight slightly less, then edge id\n                    if (parent_e[to] == -1 || ei < parent_e[to]) {\n                        parent_e[to] = ei;\n                        parent_v[to] = v;\n                    }\n                }\n            }\n        }\n    };\n\n    for (int s : roots) {\n        if (timer.elapsed() > 1.8) break;\n        dijkstra(s);\n        double sumd = 0.0;\n        for (int i = 0; i < N; i++) {\n            if (dist[i] < INF64 / 4) sumd += dist[i];\n        }\n        double inv = (sumd > 0 ? 1.0 / sumd : 0.0);\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            if (parent_e[v] != -1) {\n                // Edge used in one SPT; weighted by closeness from root.\n                double add = 1.0 + 3.0 * (1.0 - dist[v] * inv);\n                imp[parent_e[v]] += add;\n            }\n            if (dist[v] < INF64 / 4) {\n                vcen[v] += (1.0 - dist[v] * inv);\n            }\n        }\n    }\n\n    // Add static features: edge length and endpoint degree/centrality\n    for (int i = 0; i < M; i++) {\n        int u = edges[i].u, v = edges[i].v;\n        double val = imp[i];\n        val += 0.15 * (double)g[u].size();\n        val += 0.15 * (double)g[v].size();\n        val += 1.2 * (vcen[u] + vcen[v]);\n        val += 0.000002 * edges[i].w; // very small length effect\n        edges[i].imp = val;\n    }\n\n    // ---- Greedy assignment ----\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n        return edges[a].w > edges[b].w;\n    });\n\n    vector<int> day_of(M, -1); // 0-based\n    vector<int> load(D, 0);\n    vector<double> day_imp(D, 0.0);\n\n    vector<vector<int>> cell_cnt(D, vector<int>(C, 0));\n    vector<vector<int>> vday_cnt(D, vector<int>(N, 0));\n\n    auto day_cost_insert = [&](int day, int ei) -> double {\n        const Edge &e = edges[ei];\n        int u = e.u, v = e.v, c = e.cell;\n        double cost = 0.0;\n        cost += 7.0 * load[day];\n        cost += 4.5 * cell_cnt[day][c];\n        cost += 3.0 * (vday_cnt[day][u] + vday_cnt[day][v]);\n        cost += 0.22 * day_imp[day];\n        cost += 0.9 * e.imp * (double)load[day] / max(1, K);\n        return cost;\n    };\n\n    for (int ei : ord) {\n        double best = 1e100;\n        int bestd = -1;\n        for (int d = 0; d < D; d++) {\n            if (load[d] >= K) continue;\n            double c = day_cost_insert(d, ei);\n            if (c < best) {\n                best = c;\n                bestd = d;\n            }\n        }\n        if (bestd == -1) {\n            // Should not happen, but fallback.\n            bestd = min_element(load.begin(), load.end()) - load.begin();\n        }\n        day_of[ei] = bestd;\n        load[bestd]++;\n        day_imp[bestd] += edges[ei].imp;\n        cell_cnt[bestd][edges[ei].cell]++;\n        vday_cnt[bestd][edges[ei].u]++;\n        vday_cnt[bestd][edges[ei].v]++;\n    }\n\n    // ---- Surrogate score for local search ----\n    auto delta_move = [&](int ei, int from, int to) -> double {\n        if (from == to) return 0.0;\n        const Edge &e = edges[ei];\n        int c = e.cell, u = e.u, v = e.v;\n\n        auto contrib = [&](int d, int sign) -> double {\n            // sign = -1 remove, +1 add\n            double res = 0.0;\n\n            int oldLoad = load[d];\n            int newLoad = oldLoad + sign;\n            res += 3.5 * (1LL * newLoad * newLoad - 1LL * oldLoad * oldLoad);\n\n            int oldCell = cell_cnt[d][c];\n            int newCell = oldCell + sign;\n            res += 5.0 * (1LL * newCell * newCell - 1LL * oldCell * oldCell);\n\n            int oldu = vday_cnt[d][u];\n            int newu = oldu + sign;\n            res += 2.2 * (1LL * newu * newu - 1LL * oldu * oldu);\n\n            int oldv = vday_cnt[d][v];\n            int newv = oldv + sign;\n            res += 2.2 * (1LL * newv * newv - 1LL * oldv * oldv);\n\n            double oldImp = day_imp[d];\n            double newImp = oldImp + sign * e.imp;\n            res += 0.018 * (newImp * newImp - oldImp * oldImp);\n\n            return res;\n        };\n\n        return contrib(from, -1) + contrib(to, +1);\n    };\n\n    auto apply_move = [&](int ei, int from, int to) {\n        const Edge &e = edges[ei];\n        load[from]--;\n        day_imp[from] -= e.imp;\n        cell_cnt[from][e.cell]--;\n        vday_cnt[from][e.u]--;\n        vday_cnt[from][e.v]--;\n\n        load[to]++;\n        day_imp[to] += e.imp;\n        cell_cnt[to][e.cell]++;\n        vday_cnt[to][e.u]++;\n        vday_cnt[to][e.v]++;\n\n        day_of[ei] = to;\n    };\n\n    // ---- Local search: random moves and swaps ----\n    mt19937 rng(712367821);\n    vector<vector<int>> by_day(D);\n    for (int i = 0; i < M; i++) by_day[day_of[i]].push_back(i);\n\n    auto rebuild_by_day = [&]() {\n        for (int d = 0; d < D; d++) by_day[d].clear();\n        for (int i = 0; i < M; i++) by_day[day_of[i]].push_back(i);\n    };\n\n    int iter = 0;\n    while (timer.elapsed() < 5.7) {\n        iter++;\n        if ((iter & 255) == 0) rebuild_by_day();\n\n        if ((rng() & 1) == 0) {\n            // move\n            int ei = rng() % M;\n            int from = day_of[ei];\n            int to = rng() % D;\n            if (from == to || load[to] >= K) continue;\n            double dlt = delta_move(ei, from, to);\n            if (dlt < 0.0 || (rng() % 1000 == 0)) {\n                apply_move(ei, from, to);\n            }\n        } else {\n            // swap\n            int e1 = rng() % M;\n            int d1 = day_of[e1];\n            int d2 = rng() % D;\n            if (d1 == d2 || by_day[d2].empty()) continue;\n            int e2 = by_day[d2][rng() % by_day[d2].size()];\n            int cur1 = day_of[e1], cur2 = day_of[e2];\n            if (cur1 == cur2) continue;\n\n            double dlt = delta_move(e1, cur1, cur2) + delta_move(e2, cur2, cur1);\n\n            // small correction because after first move counts change; good enough as surrogate\n            if (dlt < 0.0 || (rng() % 3000 == 0)) {\n                apply_move(e1, cur1, cur2);\n                apply_move(e2, cur2, cur1);\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << day_of[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n): n(n), p(n), sz(n,1) { iota(p.begin(), p.end(), 0); }\n    int find(int x){ return p[x]==x?x:p[x]=find(p[x]); }\n    bool unite(int 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 const int dx[6] = {1,-1,0,0,0,0};\nstatic const int dy[6] = {0,0,1,-1,0,0};\nstatic const int dz[6] = {0,0,0,0,1,-1};\n\nint main(){\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for(int t=0;t<2;t++){\n        f[t].resize(D);\n        r[t].resize(D);\n        for(int i=0;i<D;i++) cin >> f[t][i];\n        for(int i=0;i<D;i++) cin >> r[t][i];\n    }\n\n    auto idx = [&](int x,int y,int z){ return (x*D + y)*D + z; };\n    int N3 = D*D*D;\n\n    // Build sparse feasible object per silhouette.\n    // For each z-layer, choose exactly max(|X|,|Y|) cells.\n    vector<char> occ[2];\n    occ[0].assign(N3, 0);\n    occ[1].assign(N3, 0);\n\n    // First pass independently.\n    for(int t=0;t<2;t++){\n        for(int z=0; z<D; z++){\n            vector<int> X, Y;\n            for(int x=0;x<D;x++) if(f[t][z][x]=='1') X.push_back(x);\n            for(int y=0;y<D;y++) if(r[t][z][y]=='1') Y.push_back(y);\n\n            int a = (int)X.size(), b = (int)Y.size();\n            if(a==0 || b==0) continue; // shouldn't happen by constraints per row, but safe\n\n            if(a <= b){\n                for(int i=0;i<a;i++) occ[t][idx(X[i], Y[i], z)] = 1;\n                int fixedx = X[0];\n                for(int i=a;i<b;i++) occ[t][idx(fixedx, Y[i], z)] = 1;\n            }else{\n                for(int i=0;i<b;i++) occ[t][idx(X[i], Y[i], z)] = 1;\n                int fixedy = Y[0];\n                for(int i=b;i<a;i++) occ[t][idx(X[i], fixedy, z)] = 1;\n            }\n        }\n    }\n\n    // Second pass: rebuild object 1 and 2 with simple overlap-aware heuristics per layer.\n    // We try both orders and keep the better overlap.\n    auto build_with_reference = [&](int cur, int ref, const vector<char>& occRef){\n        vector<char> res(N3, 0);\n        for(int z=0; z<D; z++){\n            vector<int> X, Y;\n            for(int x=0;x<D;x++) if(f[cur][z][x]=='1') X.push_back(x);\n            for(int y=0;y<D;y++) if(r[cur][z][y]=='1') Y.push_back(y);\n            if(X.empty() || Y.empty()) continue;\n\n            int a = (int)X.size(), b = (int)Y.size();\n\n            // Score pairs by whether reference already occupies same coordinate.\n            vector<tuple<int,int,int>> cand;\n            for(int i=0;i<a;i++){\n                for(int j=0;j<b;j++){\n                    int x = X[i], y = Y[j];\n                    int sc = occRef[idx(x,y,z)] ? 1 : 0;\n                    cand.emplace_back(-sc, i, j); // sort ascending => prefer sc=1\n                }\n            }\n            sort(cand.begin(), cand.end());\n\n            vector<int> mx(a, -1), my(b, -1);\n            for(auto [nsc,i,j] : cand){\n                if(mx[i] == -1 && my[j] == -1){\n                    mx[i] = j;\n                    my[j] = i;\n                }\n            }\n\n            // Place matched pairs\n            for(int i=0;i<a;i++){\n                if(mx[i] != -1){\n                    res[idx(X[i], Y[mx[i]], z)] = 1;\n                }\n            }\n\n            // Unmatched X -> choose y maximizing overlap\n            if(a > b){\n                int bestj = 0, bestsc = -1;\n                for(int j=0;j<b;j++){\n                    int sc = 0;\n                    for(int i=0;i<a;i++) if(mx[i]==-1) sc += occRef[idx(X[i], Y[j], z)] ? 1 : 0;\n                    if(sc > bestsc){ bestsc = sc; bestj = j; }\n                }\n                for(int i=0;i<a;i++) if(mx[i]==-1){\n                    res[idx(X[i], Y[bestj], z)] = 1;\n                }\n            }\n            // Unmatched Y -> choose x maximizing overlap\n            if(b > a){\n                int besti = 0, bestsc = -1;\n                for(int i=0;i<a;i++){\n                    int sc = 0;\n                    for(int j=0;j<b;j++) if(my[j]==-1) sc += occRef[idx(X[i], Y[j], z)] ? 1 : 0;\n                    if(sc > bestsc){ bestsc = sc; besti = i; }\n                }\n                for(int j=0;j<b;j++) if(my[j]==-1){\n                    res[idx(X[besti], Y[j], z)] = 1;\n                }\n            }\n        }\n        return res;\n    };\n\n    vector<char> a0 = build_with_reference(0, 1, occ[1]);\n    vector<char> a1 = build_with_reference(1, 0, a0);\n    int ovA = 0;\n    for(int i=0;i<N3;i++) if(a0[i] && a1[i]) ovA++;\n\n    vector<char> b1 = build_with_reference(1, 0, occ[0]);\n    vector<char> b0 = build_with_reference(0, 1, b1);\n    int ovB = 0;\n    for(int i=0;i<N3;i++) if(b0[i] && b1[i]) ovB++;\n\n    if(ovA >= ovB){\n        occ[0] = move(a0);\n        occ[1] = move(a1);\n    }else{\n        occ[0] = move(b0);\n        occ[1] = move(b1);\n    }\n\n    // Shared cells = exact same coordinates occupied in both.\n    vector<char> shared(N3, 0), only0(N3, 0), only1(N3, 0);\n    for(int i=0;i<N3;i++){\n        if(occ[0][i] && occ[1][i]) shared[i] = 1;\n        else if(occ[0][i]) only0[i] = 1;\n        else if(occ[1][i]) only1[i] = 1;\n    }\n\n    // Make connected components:\n    // 1) shared by adjacency in common coordinates\n    // 2) object-specific by adjacency inside each object-specific mask\n    vector<int> lab0(N3, 0), lab1(N3, 0);\n    int block_id = 0;\n\n    auto bfs_components_same_for_both = [&](const vector<char>& mask){\n        vector<int> vis(N3, 0);\n        for(int x=0;x<D;x++) for(int y=0;y<D;y++) for(int z=0;z<D;z++){\n            int s = idx(x,y,z);\n            if(!mask[s] || vis[s]) continue;\n            ++block_id;\n            queue<int> q;\n            q.push(s);\n            vis[s] = 1;\n            lab0[s] = block_id;\n            lab1[s] = block_id;\n            while(!q.empty()){\n                int v = q.front(); q.pop();\n                int zz = v % D;\n                int tmp = v / D;\n                int yy = tmp % D;\n                int xx = tmp / D;\n                for(int dir=0;dir<6;dir++){\n                    int nx = xx + dx[dir], ny = yy + dy[dir], nz = zz + dz[dir];\n                    if(nx<0||nx>=D||ny<0||ny>=D||nz<0||nz>=D) continue;\n                    int to = idx(nx,ny,nz);\n                    if(mask[to] && !vis[to]){\n                        vis[to] = 1;\n                        lab0[to] = block_id;\n                        lab1[to] = block_id;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n    };\n\n    auto bfs_components_single = [&](const vector<char>& mask, vector<int>& lab){\n        vector<int> vis(N3, 0);\n        for(int x=0;x<D;x++) for(int y=0;y<D;y++) for(int z=0;z<D;z++){\n            int s = idx(x,y,z);\n            if(!mask[s] || vis[s]) continue;\n            ++block_id;\n            queue<int> q;\n            q.push(s);\n            vis[s] = 1;\n            lab[s] = block_id;\n            while(!q.empty()){\n                int v = q.front(); q.pop();\n                int zz = v % D;\n                int tmp = v / D;\n                int yy = tmp % D;\n                int xx = tmp / D;\n                for(int dir=0;dir<6;dir++){\n                    int nx = xx + dx[dir], ny = yy + dy[dir], nz = zz + dz[dir];\n                    if(nx<0||nx>=D||ny<0||ny>=D||nz<0||nz>=D) continue;\n                    int to = idx(nx,ny,nz);\n                    if(mask[to] && !vis[to]){\n                        vis[to] = 1;\n                        lab[to] = block_id;\n                        q.push(to);\n                    }\n                }\n            }\n        }\n    };\n\n    bfs_components_same_for_both(shared);\n    bfs_components_single(only0, lab0);\n    bfs_components_single(only1, lab1);\n\n    int n = block_id;\n\n    cout << n << '\\n';\n    for(int i=0;i<N3;i++){\n        if(i) cout << ' ';\n        cout << lab0[i];\n    }\n    cout << '\\n';\n    for(int i=0;i<N3;i++){\n        if(i) cout << ' ';\n        cout << lab1[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v;\n    int w;\n};\n\nstruct DijkstraResult {\n    vector<ll> dist;\n    vector<int> prev_v;\n    vector<int> prev_e;\n};\n\nstatic inline ll sqll(ll x) { return x * x; }\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    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); // (to, edge_id)\n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        g[u].push_back({v, i});\n        g[v].push_back({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    // Precompute squared distances station -> resident, sorted order for each station.\n    vector<vector<pair<ll,int>>> station_res(N);\n    vector<vector<int>> reqR(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        station_res[i].reserve(K);\n        for (int k = 0; k < K; k++) {\n            ll dx = (ll)x[i] - a[k];\n            ll dy = (ll)y[i] - b[k];\n            ll d2 = dx*dx + dy*dy;\n            station_res[i].push_back({d2, k});\n            int r = (int)ceil(sqrt((long double)d2));\n            if (r > 5000) r = 5001; // impossible\n            reqR[i][k] = r;\n        }\n        sort(station_res[i].begin(), station_res[i].end());\n    }\n\n    auto dijkstra = [&](int s) -> DijkstraResult {\n        vector<ll> dist(N, INF64);\n        vector<int> prev_v(N, -1), prev_e(N, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                ll nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    prev_v[to] = v;\n                    prev_e[to] = ei;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        return {dist, prev_v, prev_e};\n    };\n\n    // APSP by Dijkstra from each vertex\n    vector<vector<ll>> allDist(N, vector<ll>(N, INF64));\n    vector<vector<int>> allPrevV(N), allPrevE(N);\n    for (int s = 0; s < N; s++) {\n        auto res = dijkstra(s);\n        allDist[s] = move(res.dist);\n        allPrevV[s] = move(res.prev_v);\n        allPrevE[s] = move(res.prev_e);\n    }\n\n    auto build_edges_from_terminals = [&](const vector<int>& terminals) {\n        // terminals should include root 0 if non-empty? we'll include internally.\n        vector<int> ts = terminals;\n        sort(ts.begin(), ts.end());\n        ts.erase(unique(ts.begin(), ts.end()), ts.end());\n        if (find(ts.begin(), ts.end(), 0) == ts.end()) ts.insert(ts.begin(), 0);\n\n        int T = (int)ts.size();\n        vector<ll> mincost(T, INF64);\n        vector<int> parent(T, -1);\n        vector<char> used(T, 0);\n        mincost[0] = 0;\n        for (int it = 0; it < T; it++) {\n            int v = -1;\n            for (int i = 0; i < T; i++) if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int to = 0; to < T; to++) if (!used[to]) {\n                ll w = allDist[ts[v]][ts[to]];\n                if (w < mincost[to]) {\n                    mincost[to] = w;\n                    parent[to] = v;\n                }\n            }\n        }\n\n        vector<char> edge_on(M, 0);\n        vector<char> vert_on(N, 0);\n        vert_on[0] = 1;\n\n        for (int i = 1; i < T; i++) {\n            int a_v = ts[i];\n            int b_v = ts[parent[i]];\n            // Reconstruct shortest path from a_v to b_v using Dijkstra tree rooted at a_v\n            // allPrev arrays for source a_v\n            int cur = b_v;\n            // Need path b_v -> a_v through prev from source a_v\n            while (cur != a_v) {\n                int ei = allPrevE[a_v][cur];\n                int pv = allPrevV[a_v][cur];\n                if (ei < 0 || pv < 0) break; // should not happen\n                edge_on[ei] = 1;\n                vert_on[cur] = 1;\n                vert_on[pv] = 1;\n                cur = pv;\n            }\n        }\n        return pair(edge_on, vert_on);\n    };\n\n    auto greedy_cover = [&](const vector<int>& usableStations, double alpha, bool useConnPenalty) {\n        vector<char> covered(K, 0);\n        vector<int> P(N, 0);\n        vector<int> selectedStations;\n        int coveredCnt = 0;\n\n        vector<char> usable(N, 0);\n        for (int v : usableStations) usable[v] = 1;\n\n        while (coveredCnt < K) {\n            double bestScore = -1.0;\n            int bestV = -1;\n            int bestR = -1;\n            int gain = 0;\n\n            for (int v = 0; v < N; v++) if (usable[v]) {\n                int uncov = 0;\n                int lastR = -1;\n                int bestLocalGain = 0;\n                int bestLocalR = -1;\n                double stationPenalty = useConnPenalty ? alpha * (double)allDist[0][v] : 0.0;\n\n                for (auto [d2, rid] : station_res[v]) {\n                    int r = (int)ceil(sqrt((long double)d2));\n                    if (r > 5000) break;\n                    if (!covered[rid]) uncov++;\n                    if (r != lastR) {\n                        if (uncov > 0) {\n                            double cost = (double)r * (double)r + stationPenalty;\n                            double score = (double)uncov / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                                gain = uncov;\n                            }\n                        }\n                        lastR = r;\n                    } else {\n                        if (uncov > 0) {\n                            double cost = (double)r * (double)r + stationPenalty;\n                            double score = (double)uncov / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                                gain = uncov;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) {\n                // Fallback: assign each uncovered resident to nearest usable station\n                for (int k = 0; k < K; k++) if (!covered[k]) {\n                    int bv = -1, br = 5001;\n                    for (int v = 0; v < N; v++) if (usable[v]) {\n                        int r = reqR[v][k];\n                        if (r <= 5000 && r < br) {\n                            br = r; bv = v;\n                        }\n                    }\n                    if (bv != -1) {\n                        P[bv] = max(P[bv], br);\n                        covered[k] = 1;\n                        coveredCnt++;\n                    }\n                }\n                break;\n            }\n\n            if (P[bestV] < bestR) {\n                if (P[bestV] == 0) selectedStations.push_back(bestV);\n                P[bestV] = bestR;\n            }\n\n            for (auto [d2, rid] : station_res[bestV]) {\n                int r = (int)ceil(sqrt((long double)d2));\n                if (r > bestR) break;\n                if (!covered[rid]) {\n                    covered[rid] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        // cleanup selected list\n        sort(selectedStations.begin(), selectedStations.end());\n        selectedStations.erase(unique(selectedStations.begin(), selectedStations.end()), selectedStations.end());\n\n        ll powerCost = 0;\n        for (int i = 0; i < N; i++) powerCost += 1LL * P[i] * P[i];\n        return tuple<vector<int>, vector<int>, ll>(P, selectedStations, powerCost);\n    };\n\n    auto compute_score_cost = [&](const vector<int>& P, const vector<char>& edge_on) {\n        ll S = 0;\n        for (int i = 0; i < N; i++) S += 1LL * P[i] * P[i];\n        for (int i = 0; i < M; i++) if (edge_on[i]) S += edges[i].w;\n        return S;\n    };\n\n    vector<int> bestP(N, 0);\n    vector<char> bestB(M, 0);\n    ll bestS = INF64;\n\n    vector<double> alphas = {0.0, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0};\n\n    vector<int> allStations(N);\n    iota(allStations.begin(), allStations.end(), 0);\n\n    for (double alpha : alphas) {\n        // Phase 1: coarse greedy over all stations with connection proxy\n        auto [P1, terms1, powerCost1] = greedy_cover(allStations, alpha, true);\n\n        // Connect selected stations\n        auto [edge_on1, vert_on1] = build_edges_from_terminals(terms1);\n\n        vector<int> reachableStations;\n        for (int i = 0; i < N; i++) if (vert_on1[i]) reachableStations.push_back(i);\n\n        // Phase 2: re-cover using all reachable stations, no connection penalty\n        auto [P2, terms2, powerCost2] = greedy_cover(reachableStations, 0.0, false);\n\n        // Reconnect only actually used powered stations\n        vector<int> positiveStations;\n        for (int i = 0; i < N; i++) if (P2[i] > 0) positiveStations.push_back(i);\n        auto [edge_on2, vert_on2] = build_edges_from_terminals(positiveStations);\n\n        // Prune edges: keep only subtree needed for root and positive stations inside chosen subgraph\n        vector<vector<pair<int,int>>> sg(N);\n        for (int i = 0; i < M; i++) if (edge_on2[i]) {\n            int u = edges[i].u, v = edges[i].v;\n            sg[u].push_back({v, i});\n            sg[v].push_back({u, i});\n        }\n\n        vector<char> needV(N, 0);\n        needV[0] = 1;\n        for (int i = 0; i < N; i++) if (P2[i] > 0) needV[i] = 1;\n\n        vector<char> keepE(M, 0), vis(N, 0);\n        function<bool(int,int)> dfs = [&](int v, int pe) -> bool {\n            vis[v] = 1;\n            bool need = needV[v];\n            for (auto [to, ei] : sg[v]) {\n                if (ei == pe) continue;\n                if (!vis[to]) {\n                    if (dfs(to, ei)) {\n                        keepE[ei] = 1;\n                        need = true;\n                    }\n                }\n            }\n            return need;\n        };\n        dfs(0, -1);\n\n        ll S = compute_score_cost(P2, keepE);\n        if (S < bestS) {\n            bestS = S;\n            bestP = P2;\n            bestB = keepE;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestB[i] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC021-like heuristic.\n\nIdea:\n- We want a heap order on triangular grid:\n    a[x][y] < a[x+1][y], a[x+1][y+1]\n- We construct it top-down.\n- Target set for row x is the smallest T(x+1) values, where T(r)=r*(r+1)/2.\n  Thus row 0 should contain smallest 1 value, rows 0..1 smallest 3 values, etc.\n- For each row x and position y, place the smallest remaining value among rows x..N-1\n  into (x,y), processing y from left to right.\n- A ball can be moved upward by repeated swaps with one of its two parents.\n  We use a shortest path in the triangular graph restricted to rows <= current row.\n  Since N=30, BFS per placement is cheap enough.\n\nThis is not optimal, but usually reaches a valid state well within 10000 moves.\n*/\n\nstatic constexpr int N = 30;\nstatic constexpr int MAXK = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; i++) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; j++) cin >> a[i][j];\n    }\n\n    vector<pair<int,int>> pos(465);\n    for (int i = 0; i < N; i++) for (int j = 0; j <= i; j++) pos[a[i][j]] = {i, j};\n\n    vector<Op> ops;\n    ops.reserve(MAXK);\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y <= x;\n    };\n\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        if ((int)ops.size() >= MAXK) return;\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    };\n\n    auto neighbors = [&](int x, int y) {\n        array<pair<int,int>, 6> cand = {{\n            {x-1, y-1}, {x-1, y},\n            {x, y-1},   {x, y+1},\n            {x+1, y},   {x+1, y+1}\n        }};\n        vector<pair<int,int>> res;\n        for (auto [nx, ny] : cand) if (inside(nx, ny)) res.push_back({nx, ny});\n        return res;\n    };\n\n    // shortest path between two cells in the triangular graph\n    auto get_path = [&](pair<int,int> s, pair<int,int> t) {\n        static int dist[N][N];\n        static pair<int,int> pre[N][N];\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j <= i; j++) {\n                dist[i][j] = -1;\n                pre[i][j] = {-1,-1};\n            }\n        }\n        queue<pair<int,int>> q;\n        dist[s.first][s.second] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            if (x == t.first && y == t.second) break;\n            for (auto [nx,ny] : neighbors(x,y)) {\n                if (dist[nx][ny] != -1) continue;\n                dist[nx][ny] = dist[x][y] + 1;\n                pre[nx][ny] = {x,y};\n                q.push({nx,ny});\n            }\n        }\n        vector<pair<int,int>> path;\n        if (dist[t.first][t.second] == -1) return path;\n        pair<int,int> cur = t;\n        while (!(cur == s)) {\n            path.push_back(cur);\n            cur = pre[cur.first][cur.second];\n        }\n        path.push_back(s);\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    // Greedy top-down construction\n    vector<char> fixedv(465, 0);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if ((int)ops.size() >= MAXK) break;\n\n            // choose minimum-valued ball among cells not fixed yet, restricted to rows >= x\n            int bestVal = INT_MAX;\n            pair<int,int> bestPos = {-1,-1};\n\n            for (int i = x; i < N; i++) {\n                int j0 = (i == x ? y : 0);\n                for (int j = j0; j <= i; j++) {\n                    int v = a[i][j];\n                    if (!fixedv[v] && v < bestVal) {\n                        bestVal = v;\n                        bestPos = {i,j};\n                    }\n                }\n            }\n\n            if (bestPos.first == -1) continue;\n\n            // move bestPos to (x,y) along a shortest path\n            auto path = get_path(bestPos, {x,y});\n            if (path.empty()) continue;\n\n            // swap backwards along path so target ball moves forward to destination\n            for (int k = 0; k + 1 < (int)path.size(); k++) {\n                // We want ball at path[k] to move to path[k+1] if traversing from source to target,\n                // so execute swaps in reverse order.\n            }\n            for (int k = (int)path.size() - 1; k >= 1; k--) {\n                auto [x1,y1] = path[k];\n                auto [x2,y2] = path[k-1];\n                if ((int)ops.size() >= MAXK) break;\n                do_swap(x1,y1,x2,y2);\n            }\n\n            fixedv[bestVal] = 1;\n        }\n        if ((int)ops.size() >= MAXK) break;\n    }\n\n    // Local improvement: bubble up inversions while possible within move budget.\n    // If parent > child, swap them; this reduces E locally.\n    bool updated = true;\n    while (updated && (int)ops.size() < MAXK) {\n        updated = false;\n        for (int x = N - 2; x >= 0; x--) {\n            for (int y = 0; y <= x; y++) {\n                if ((int)ops.size() >= MAXK) break;\n                if (a[x][y] > a[x+1][y]) {\n                    do_swap(x, y, x+1, y);\n                    updated = true;\n                }\n                if ((int)ops.size() >= MAXK) break;\n                if (a[x][y] > a[x+1][y+1]) {\n                    do_swap(x, y, x+1, y+1);\n                    updated = true;\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    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nHeuristic idea\n\nWe must place containers online (arrival order unknown; label revealed on arrival),\nsubject to current empties maintaining reachability from entrance.\n\nAfter all placements, we may choose any feasible retrieval order where each next\ncontainer must be currently reachable from entrance through empty cells.\n\nKey observation:\nIf we place containers in a reverse topological order of some rooted spanning tree\nof free cells (excluding entrance), then every placement is feasible, and later\nretrieval in root-to-leaf order is always feasible.\nSo if each cell has a fixed \"retrieval priority\" rank, and we always assign newly\narrived containers to cells according to their label (smaller label => earlier\nretrieval rank), retrieval sequence becomes approximately sorted by labels.\n\nConstruction:\n- Build BFS tree from entrance over all usable cells.\n- Sort cells by depth descending; this is a valid online placement order:\n  placing only on deepest remaining cells preserves reachability of all empty cells.\n- Retrieval order is reverse of that: depth ascending.\n- To improve quality, within each depth layer, use subtree size / local geometry tie-breaks,\n  and map labels to ranks among currently free cells by quantile:\n    choose k = floor(label * remaining_cells / total_labels)\n    and place in k-th cell of retrieval-order among free cells.\nThis approximates storing smaller labels closer to entrance.\n\nSince total cells <= 80, simple recomputation is fine.\n*/\n\nstruct Pos {\n    int i, j;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<int>> obstacle(D, vector<int>(D, 0));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = 1;\n    }\n\n    const int ei = 0, ej = (D - 1) / 2;\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D;\n    };\n\n    vector<Pos> dirs = {{1,0},{-1,0},{0,1},{0,-1}};\n\n    // Enumerate usable cells (non-obstacle, non-entrance)\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<Pos> cells;\n    for (int i = 0; i < D; ++i) for (int j = 0; j < D; ++j) {\n        if (i == ei && j == ej) continue;\n        if (obstacle[i][j]) continue;\n        id[i][j] = (int)cells.size();\n        cells.push_back({i,j});\n    }\n    int M = (int)cells.size(); // number of containers total\n\n    // BFS tree from entrance\n    vector<int> depth(M, -1), parent(M, -1);\n    queue<pair<int,int>> q;\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    q.push({ei, ej});\n    vis[ei][ej] = 1;\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (auto d : dirs) {\n            int nx = x + d.i, ny = y + d.j;\n            if (!inside(nx, ny) || vis[nx][ny] || obstacle[nx][ny]) continue;\n            vis[nx][ny] = 1;\n            q.push({nx, ny});\n            if (!(nx == ei && ny == ej)) {\n                int v = id[nx][ny];\n                depth[v] = (x == ei && y == ej) ? 1 : depth[id[x][y]] + 1;\n                if (x == ei && y == ej) parent[v] = -1;\n                else parent[v] = id[x][y];\n            }\n        }\n    }\n\n    // children and subtree sizes\n    vector<vector<int>> children(M);\n    for (int v = 0; v < M; ++v) if (parent[v] != -1) children[parent[v]].push_back(v);\n\n    vector<int> sub(M, 1);\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n    for (int v : order) {\n        if (parent[v] != -1) sub[parent[v]] += sub[v];\n    }\n\n    // Static retrieval preference order:\n    // smaller depth first; among same depth, larger subtree first; then centrality / coordinates\n    vector<int> retrieval_order(M);\n    iota(retrieval_order.begin(), retrieval_order.end(), 0);\n    sort(retrieval_order.begin(), retrieval_order.end(), [&](int a, int b) {\n        if (depth[a] != depth[b]) return depth[a] < depth[b];\n        if (sub[a] != sub[b]) return sub[a] > sub[b];\n        int ca = abs(cells[a].j - ej);\n        int cb = abs(cells[b].j - ej);\n        if (ca != cb) return ca < cb;\n        if (cells[a].i != cells[b].i) return cells[a].i < cells[b].i;\n        return cells[a].j < cells[b].j;\n    });\n\n    // Placement order corresponding to reverse retrieval order\n    vector<int> placement_order = retrieval_order;\n    reverse(placement_order.begin(), placement_order.end());\n\n    vector<int> label_at_cell(M, -1);\n    vector<int> cell_of_label(M, -1);\n    vector<int> occupied(M, 0);\n\n    // For online placement:\n    // among currently free cells, consider them in retrieval_order;\n    // choose quantile by label among all labels [0, M-1].\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        vector<int> free_retrieval;\n        free_retrieval.reserve(M - step);\n        for (int v : retrieval_order) {\n            if (!occupied[v]) free_retrieval.push_back(v);\n        }\n\n        int rem = (int)free_retrieval.size();\n        int idx = (long long)t * rem / M;\n        if (idx >= rem) idx = rem - 1;\n\n        int chosen = free_retrieval[idx];\n\n        occupied[chosen] = 1;\n        label_at_cell[chosen] = t;\n        cell_of_label[t] = chosen;\n\n        cout << cells[chosen].i << ' ' << cells[chosen].j << '\\n';\n        cout.flush();\n    }\n\n    // Retrieval phase:\n    // Output occupied cells in retrieval_order. This is feasible because\n    // retrieval_order is root-to-leaf in the BFS tree.\n    for (int v : retrieval_order) {\n        cout << cells[v].i << ' ' << cells[v].j << '\\n';\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXC = 100;\n\nstruct Solver {\n    int n, m;\n    vector<vector<int>> orig;\n    vector<vector<int>> cur;\n    bitset<MAXC + 1> origAdj[MAXC + 1];\n    mt19937 rng;\n\n    Solver() : rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    bool inside(int i, int j) const {\n        return 0 <= i && i < n && 0 <= j && j < n;\n    }\n\n    void buildOrigAdj() {\n        for (int i = 0; i <= m; i++) origAdj[i].reset();\n        const int di[4] = {-1, 1, 0, 0};\n        const int dj[4] = {0, 0, -1, 1};\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = orig[i][j];\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    origAdj[0].set(c);\n                    origAdj[c].set(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 cc = orig[ni][nj];\n                    if (cc != c) {\n                        origAdj[c].set(cc);\n                        origAdj[cc].set(c);\n                    }\n                }\n            }\n        }\n    }\n\n    bool checkConnectivityColor(int color) {\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                if (cur[i][j] == color) cells.push_back({i, j});\n            }\n        }\n        if (cells.empty()) return false;\n\n        queue<pair<int,int>> q;\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        q.push(cells[0]);\n        vis[cells[0].first][cells[0].second] = true;\n        int cnt = 1;\n\n        const int di[4] = {-1, 1, 0, 0};\n        const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); q.pop();\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj) || vis[ni][nj] || cur[ni][nj] != color) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n                cnt++;\n            }\n        }\n        return cnt == (int)cells.size();\n    }\n\n    bool checkZeroConnectedToOutside() {\n        // 0-cells are connected through outside, so all 0-cells inside the board\n        // must belong to a single component touching boundary.\n        vector<pair<int,int>> zeros;\n        zeros.reserve(n * n);\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (cur[i][j] == 0) zeros.push_back({i, j});\n            }\n        }\n        if (zeros.empty()) return true;\n\n        queue<pair<int,int>> q;\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        for (auto [i, j] : zeros) {\n            if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                q.push({i, j});\n                vis[i][j] = true;\n            }\n        }\n        if (q.empty()) return false; // zero component does not touch outside\n\n        int cnt = 0;\n        const int di[4] = {-1, 1, 0, 0};\n        const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || cur[ni][nj] != 0) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == (int)zeros.size();\n    }\n\n    bool checkAdjacency() {\n        bitset<MAXC + 1> adj[MAXC + 1];\n        for (int i = 0; i <= m; i++) adj[i].reset();\n\n        const int di[4] = {-1, 1, 0, 0};\n        const int dj[4] = {0, 0, -1, 1};\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = cur[i][j];\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    adj[0].set(c);\n                    adj[c].set(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 cc = cur[ni][nj];\n                    if (cc != c) {\n                        adj[c].set(cc);\n                        adj[cc].set(c);\n                    }\n                }\n            }\n        }\n\n        for (int c = 0; c <= m; c++) {\n            if (adj[c] != origAdj[c]) return false;\n        }\n        return true;\n    }\n\n    bool legal() {\n        // every nonzero color must exist and be connected\n        for (int c = 1; c <= m; c++) {\n            if (!checkConnectivityColor(c)) return false;\n        }\n        if (!checkZeroConnectedToOutside()) return false;\n        if (!checkAdjacency()) return false;\n        return true;\n    }\n\n    int sameNeighborCount(int i, int j) {\n        int c = cur[i][j];\n        int res = 0;\n        if (i > 0 && cur[i-1][j] == c) res++;\n        if (i+1 < n && cur[i+1][j] == c) res++;\n        if (j > 0 && cur[i][j-1] == c) res++;\n        if (j+1 < n && cur[i][j+1] == c) res++;\n        return res;\n    }\n\n    int distinctNeighborColors(int i, int j) {\n        set<int> s;\n        if (i == 0 || i == n-1 || j == 0 || j == n-1) s.insert(0);\n        if (i > 0) s.insert(cur[i-1][j]);\n        else s.insert(0);\n        if (i+1 < n) s.insert(cur[i+1][j]);\n        else s.insert(0);\n        if (j > 0) s.insert(cur[i][j-1]);\n        else s.insert(0);\n        if (j+1 < n) s.insert(cur[i][j+1]);\n        else s.insert(0);\n        return (int)s.size();\n    }\n\n    void solve() {\n        cin >> n >> m;\n        orig.assign(n, vector<int>(n));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> orig[i][j];\n        cur = orig;\n\n        buildOrigAdj();\n\n        // Greedy deletion in multiple passes with shuffled, locally prioritized order.\n        auto start = chrono::steady_clock::now();\n\n        vector<pair<pair<int,int>, pair<int,int>>> cand;\n        // key = (sameNeighborCount, distinctNeighborColors), value=(i,j)\n\n        int pass = 0;\n        while (true) {\n            pass++;\n            cand.clear();\n            for (int i = 0; i < n; i++) {\n                for (int j = 0; j < n; j++) {\n                    if (cur[i][j] == 0) continue;\n                    int s = sameNeighborCount(i, j);\n                    int d = distinctNeighborColors(i, j);\n                    cand.push_back({{s, d}, {i, j}});\n                }\n            }\n\n            shuffle(cand.begin(), cand.end(), rng);\n            stable_sort(cand.begin(), cand.end(), [](const auto& a, const auto& b) {\n                if (a.first.first != b.first.first) return a.first.first < b.first.first;\n                return a.first.second < b.first.second;\n            });\n\n            bool improved = false;\n            for (auto &e : cand) {\n                auto [i, j] = e.second;\n                if (cur[i][j] == 0) continue;\n                int old = cur[i][j];\n                cur[i][j] = 0;\n                if (legal()) {\n                    improved = true;\n                } else {\n                    cur[i][j] = old;\n                }\n\n                auto now = chrono::steady_clock::now();\n                double elapsed = chrono::duration<double>(now - start).count();\n                if (elapsed > 1.90) break;\n            }\n\n            auto now = chrono::steady_clock::now();\n            double elapsed = chrono::duration<double>(now - start).count();\n            if (!improved || elapsed > 1.90) break;\n        }\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (j) cout << ' ';\n                cout << cur[i][j];\n            }\n            cout << '\\n';\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}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used_queries = 0;\n\n    // compare weight(a) ? weight(b)\n    // return -1 if a<b, 0 if a=b, 1 if a>b\n    int cmp_item(int a, int b) {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        used_queries++;\n        if (s == \"<\") return -1;\n        if (s == \">\") return 1;\n        return 0;\n    }\n\n    void dummy_query(int a, int b) {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        used_queries++;\n    }\n\n    vector<int> approximate_sort_items() {\n        vector<int> ord;\n        ord.reserve(N);\n        ord.push_back(0);\n\n        for (int x = 1; x < N; x++) {\n            if (used_queries >= Q) {\n                ord.push_back(x);\n                continue;\n            }\n\n            int l = 0, r = (int)ord.size();\n            // binary insertion while budget remains\n            while (l < r && used_queries < Q) {\n                int m = (l + r) >> 1;\n                int c = cmp_item(x, ord[m]);\n                if (c == -1) {\n                    r = m;\n                } else {\n                    l = m + 1;\n                }\n            }\n            ord.insert(ord.begin() + l, x);\n        }\n        return ord; // light -> heavy approximately\n    }\n\n    vector<int> build_initial_assignment(const vector<int>& ord, const vector<double>& pw) {\n        vector<int> assign(N, 0);\n        vector<double> load(D, 0.0);\n\n        // process heavy -> light\n        for (int idx = N - 1; idx >= 0; --idx) {\n            int item = ord[idx];\n            int best = 0;\n            for (int d = 1; d < D; d++) {\n                if (load[d] < load[best]) best = d;\n            }\n            assign[item] = best;\n            load[best] += pw[item];\n        }\n        return assign;\n    }\n\n    double objective(const vector<int>& assign, const vector<double>& pw) {\n        vector<double> load(D, 0.0);\n        for (int i = 0; i < N; i++) load[assign[i]] += pw[i];\n        double mean = 0.0;\n        for (double x : load) mean += x;\n        mean /= D;\n        double var = 0.0;\n        for (double x : load) {\n            double t = x - mean;\n            var += t * t;\n        }\n        var /= D;\n        return var;\n    }\n\n    vector<double> get_loads(const vector<int>& assign, const vector<double>& pw) {\n        vector<double> load(D, 0.0);\n        for (int i = 0; i < N; i++) load[assign[i]] += pw[i];\n        return load;\n    }\n\n    void local_improve(vector<int>& assign, const vector<double>& pw) {\n        double cur = objective(assign, pw);\n\n        // several rounds of move / swap local search\n        for (int iter = 0; iter < 6; iter++) {\n            bool improved = false;\n\n            // move: try moving heavy pseudo-weight items first\n            vector<int> items(N);\n            iota(items.begin(), items.end(), 0);\n            sort(items.begin(), items.end(), [&](int a, int b) {\n                return pw[a] > pw[b];\n            });\n\n            auto load = get_loads(assign, pw);\n\n            for (int item : items) {\n                int from = assign[item];\n                for (int to = 0; to < D; to++) {\n                    if (to == from) continue;\n\n                    // quick estimate by checking max-min gap tendency\n                    double old_from = load[from], old_to = load[to];\n                    double nw_from = old_from - pw[item];\n                    double nw_to = old_to + pw[item];\n\n                    // if this cannot possibly help much, skip some cases\n                    double old_gap = max(old_from, old_to) - min(old_from, old_to);\n                    double new_gap = max(nw_from, nw_to) - min(nw_from, nw_to);\n                    if (new_gap > old_gap + 1e-9) continue;\n\n                    int old = assign[item];\n                    assign[item] = to;\n                    double nxt = objective(assign, pw);\n                    if (nxt + 1e-12 < cur) {\n                        cur = nxt;\n                        load = get_loads(assign, pw);\n                        improved = true;\n                        from = to;\n                    } else {\n                        assign[item] = old;\n                    }\n                }\n            }\n\n            // swap\n            for (int a = 0; a < N; a++) {\n                for (int b = a + 1; b < N; b++) {\n                    if (assign[a] == assign[b]) continue;\n                    swap(assign[a], assign[b]);\n                    double nxt = objective(assign, pw);\n                    if (nxt + 1e-12 < cur) {\n                        cur = nxt;\n                        improved = true;\n                    } else {\n                        swap(assign[a], assign[b]);\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        // 1) approximate sort by interactive singleton comparisons\n        vector<int> ord = approximate_sort_items(); // light -> heavy\n\n        // 2) consume remaining queries exactly\n        while (used_queries < Q) {\n            int a = 0, b = min(1, N - 1);\n            if (a == b) { // impossible under constraints N>=30, but keep safe\n                a = 0; b = 0;\n            }\n            dummy_query(a, b);\n        }\n\n        // 3) pseudo-weight from rank\n        // stronger emphasis on heavy items than linear rank\n        vector<double> pw(N, 1.0);\n        for (int r = 0; r < N; r++) {\n            int item = ord[r];\n            double x = (double)(r + 1);\n            pw[item] = x * x; // quadratic emphasis\n        }\n\n        // 4) greedy assignment\n        vector<int> assign = build_initial_assignment(ord, pw);\n\n        // 5) local improvement\n        local_improve(assign, pw);\n\n        // 6) output final partition\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << assign[i];\n        }\n        cout << '\\n';\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    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    static constexpr int N = 200;\n    static constexpr int M = 10;\n\n    int n, m;\n    vector<vector<int>> st;                  // bottom -> top\n    vector<pair<int,int>> ans;               // (v, i), i=0 means remove\n    long long energy = 0;\n\n    Solver() {\n        cin >> n >> m;\n        st.assign(m, {});\n        for (int i = 0; i < m; i++) {\n            st[i].resize(n / m);\n            for (int j = 0; j < n / m; j++) cin >> st[i][j];\n        }\n    }\n\n    pair<int,int> find_box(int x) {\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < (int)st[i].size(); j++) {\n                if (st[i][j] == x) return {i, j};\n            }\n        }\n        return {-1, -1};\n    }\n\n    int stack_min_value(int s) {\n        if (st[s].empty()) return 1000000000;\n        int mn = 1000000000;\n        for (int v : st[s]) mn = min(mn, v);\n        return mn;\n    }\n\n    int stack_top_min_window(int s, int w = 6) {\n        if (st[s].empty()) return 1000000000;\n        int mn = 1000000000;\n        int sz = (int)st[s].size();\n        for (int i = max(0, sz - w); i < sz; i++) mn = min(mn, st[s][i]);\n        return mn;\n    }\n\n    // move suffix starting at position pos in stack from -> stack to\n    void move_suffix(int from, int pos, int to) {\n        if (from == to) return; // should not happen\n        int v = st[from][pos];\n        ans.push_back({v, to + 1});\n        int k = (int)st[from].size() - pos;\n        energy += k + 1;\n\n        vector<int> moved(st[from].begin() + pos, st[from].end());\n        st[from].erase(st[from].begin() + pos, st[from].end());\n        for (int x : moved) st[to].push_back(x);\n    }\n\n    void remove_top(int x) {\n        auto [s, p] = find_box(x);\n        if (s == -1) return;\n        // x must be on top\n        ans.push_back({x, 0});\n        st[s].pop_back();\n    }\n\n    int best_destination(int from, int moved_min, int moved_size, int forbid1 = -1, int forbid2 = -1) {\n        long long bestScore = LLONG_MIN;\n        int best = -1;\n        for (int s = 0; s < m; s++) {\n            if (s == from) continue;\n            // soft avoid\n            long long score = 0;\n\n            int mn_all = stack_min_value(s);\n            int mn_top = stack_top_min_window(s, 6);\n            int h = (int)st[s].size();\n\n            // Prefer stacks with large labels only\n            score += 100000LL * min(mn_all, 1000);\n            score += 20000LL * min(mn_top, 1000);\n\n            // Prefer shorter stacks a bit\n            score -= 300LL * h;\n\n            // If this stack contains urgent small boxes, avoid\n            if (mn_all < moved_min) score -= 50000LL;\n            if (mn_top < moved_min) score -= 30000LL;\n\n            // soft forbid\n            if (s == forbid1) score -= 20000LL;\n            if (s == forbid2) score -= 10000LL;\n\n            // Slightly prefer empty stack\n            if (st[s].empty()) score += 5000;\n\n            // Slightly penalize creating too high a stack\n            score -= 50LL * (h + moved_size);\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = s;\n            }\n        }\n        return best;\n    }\n\n    void solve() {\n        for (int need = 1; need <= n; need++) {\n            while (true) {\n                auto [s, p] = find_box(need);\n                if (p == (int)st[s].size() - 1) {\n                    remove_top(need);\n                    break;\n                }\n\n                int top = (int)st[s].size() - 1;\n\n                // Option A: move whole blocker suffix [p+1 .. top]\n                int whole_pos = p + 1;\n                int whole_min = 1e9;\n                for (int i = whole_pos; i <= top; i++) whole_min = min(whole_min, st[s][i]);\n                int whole_sz = top - whole_pos + 1;\n\n                // Option B: move suffix starting at minimum blocker in [p+1 .. top]\n                int min_pos = p + 1;\n                int min_val = st[s][min_pos];\n                for (int i = p + 1; i <= top; i++) {\n                    if (st[s][i] < min_val) {\n                        min_val = st[s][i];\n                        min_pos = i;\n                    }\n                }\n                int part_pos = min_pos;\n                int part_min = min_val;\n                int part_sz = top - part_pos + 1;\n\n                // Identify stacks containing next urgent boxes, to avoid burying them further\n                int forbid1 = -1, forbid2 = -1;\n                if (need + 1 <= n) forbid1 = find_box(need + 1).first;\n                if (need + 2 <= n) forbid2 = find_box(need + 2).first;\n\n                // Heuristic choice between whole move and partial move\n                bool use_whole = false;\n                // If all blockers are relatively large, moving all at once is usually better\n                if (whole_min >= need + 15) use_whole = true;\n                // If partial move is almost as large as whole move, whole move is better (save future chunking)\n                if (part_sz >= whole_sz - 2) use_whole = true;\n                // If there are very urgent small blockers, isolate from minimum blocker\n                if (whole_min <= need + 5) use_whole = false;\n\n                if (use_whole) {\n                    int to = best_destination(s, whole_min, whole_sz, forbid1, forbid2);\n                    move_suffix(s, whole_pos, to);\n                } else {\n                    int to = best_destination(s, part_min, part_sz, forbid1, forbid2);\n                    move_suffix(s, part_pos, to);\n                }\n\n                if ((int)ans.size() > 4900) {\n                    // Emergency fallback: just finish greedily.\n                    // This should not happen in practice.\n                    while (true) {\n                        auto [ss, pp] = find_box(need);\n                        if (pp == (int)st[ss].size() - 1) {\n                            remove_top(need);\n                            break;\n                        }\n                        int pos = pp + 1;\n                        int mn = 1e9;\n                        for (int i = pos; i < (int)st[ss].size(); i++) mn = min(mn, st[ss][i]);\n                        int to = best_destination(ss, mn, (int)st[ss].size() - pos);\n                        move_suffix(ss, pos, to);\n                    }\n                    break;\n                }\n            }\n        }\n\n        // Safety: operation count must be <= 5000\n        if ((int)ans.size() > 5000) {\n            ans.resize(5000);\n        }\n\n        for (auto &[v, i] : ans) {\n            cout << v << ' ' << i << '\\n';\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}","ahc027":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Edge {\n    int to;\n    char dir;\n};\n\nstatic const int DI[4] = {-1, 1, 0, 0};\nstatic const int DJ[4] = {0, 0, -1, 1};\nstatic const char DC[4] = {'U', 'D', 'L', 'R'};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\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    vector<vector<int>> d(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> d[i][j];\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<Edge>> g(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = id(i, j);\n            if (i > 0 && h[i - 1][j] == '0') g[u].push_back({id(i - 1, j), 'U'});\n            if (i + 1 < N && h[i][j] == '0') g[u].push_back({id(i + 1, j), 'D'});\n            if (j > 0 && v[i][j - 1] == '0') g[u].push_back({id(i, j - 1), 'L'});\n            if (j + 1 < N && v[i][j] == '0') g[u].push_back({id(i, j + 1), 'R'});\n        }\n    }\n\n    auto rev = [&](char c) -> char {\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<double> wcell(V);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) wcell[id(i,j)] = d[i][j];\n\n    // exact evaluation of periodic score for route\n    auto evaluate = [&](const string& route) -> long long {\n        int L = (int)route.size();\n        vector<vector<int>> visits(V);\n        int cur = 0;\n        for (int t = 1; t <= L; t++) {\n            char c = route[t - 1];\n            int ni, nj;\n            auto [ci, cj] = pos(cur);\n            if (c == 'U') ni = ci - 1, nj = cj;\n            else if (c == 'D') ni = ci + 1, nj = cj;\n            else if (c == 'L') ni = ci, nj = cj - 1;\n            else ni = ci, nj = cj + 1;\n            cur = id(ni, nj);\n            visits[cur].push_back(t);\n        }\n        // since route starts at (0,0) and repeats, (0,0) is visited at t=0 and t=L each cycle\n        visits[0].insert(visits[0].begin(), 0);\n\n        long double total = 0;\n        for (int u = 0; u < V; u++) {\n            auto &vec = visits[u];\n            if (vec.empty()) {\n                // should not happen for valid route\n                return (long long)4e18;\n            }\n            long long s = 0;\n            for (int k = 0; k + 1 < (int)vec.size(); k++) {\n                long long gap = vec[k + 1] - vec[k];\n                s += gap * (gap - 1) / 2;\n            }\n            long long lastGap = L - vec.back() + vec[0];\n            s += lastGap * (lastGap - 1) / 2;\n            total += (long double)d[u / N][u % N] * (long double)s;\n        }\n        long double avg = total / (long double)L;\n        long long ans = llround(avg);\n        return ans;\n    };\n\n    // build shortest path tree with node-entry cost depending on alpha\n    auto build_tree = [&](double alpha, int mode) {\n        const double INF = 1e100;\n        vector<double> dist(V, INF);\n        vector<int> par(V, -1);\n        vector<char> pdir(V, '?');\n\n        auto cell_priority = [&](int u) -> double {\n            double x = wcell[u];\n            return 1.0 / pow(x, alpha);\n        };\n\n        using P = pair<double,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        dist[0] = 0;\n        pq.push({0, 0});\n\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top();\n            pq.pop();\n            if (cd != dist[u]) continue;\n\n            vector<Edge> ng = g[u];\n            auto [ui, uj] = pos(u);\n\n            sort(ng.begin(), ng.end(), [&](const Edge& a, const Edge& b) {\n                auto [ai, aj] = pos(a.to);\n                auto [bi, bj] = pos(b.to);\n                if (mode == 0) {\n                    if (wcell[a.to] != wcell[b.to]) return wcell[a.to] > wcell[b.to];\n                } else if (mode == 1) {\n                    int da = abs(ai) + abs(aj);\n                    int db = abs(bi) + abs(bj);\n                    if (wcell[a.to] != wcell[b.to]) return wcell[a.to] > wcell[b.to];\n                    if (da != db) return da < db;\n                } else if (mode == 2) {\n                    int da = abs(ai - (N-1)/2) + abs(aj - (N-1)/2);\n                    int db = abs(bi - (N-1)/2) + abs(bj - (N-1)/2);\n                    if (wcell[a.to] != wcell[b.to]) return wcell[a.to] > wcell[b.to];\n                    if (da != db) return da < db;\n                } else {\n                    if (wcell[a.to] != wcell[b.to]) return wcell[a.to] > wcell[b.to];\n                    if (ai != bi) return ai < bi;\n                    return aj < bj;\n                }\n                if (ai != bi) return ai < bi;\n                return aj < bj;\n            });\n\n            for (auto &e : ng) {\n                int vtx = e.to;\n                double nd = cd + cell_priority(vtx);\n                if (nd + 1e-12 < dist[vtx]) {\n                    dist[vtx] = nd;\n                    par[vtx] = u;\n                    pdir[vtx] = e.dir;\n                    pq.push({nd, vtx});\n                } else if (abs(nd - dist[vtx]) <= 1e-12) {\n                    // tie-break: prefer high-d parent / shallower in geometric sense\n                    if (par[vtx] == -1 || wcell[u] > wcell[par[vtx]]) {\n                        par[vtx] = u;\n                        pdir[vtx] = e.dir;\n                    }\n                }\n            }\n        }\n\n        vector<vector<pair<int,char>>> tree(V);\n        for (int u = 1; u < V; u++) {\n            int p = par[u];\n            char c = pdir[u];\n            tree[p].push_back({u, c});\n        }\n\n        // sort children order for DFS tour\n        for (int u = 0; u < V; u++) {\n            auto [ui, uj] = pos(u);\n            sort(tree[u].begin(), tree[u].end(), [&](auto &A, auto &B) {\n                int a = A.first, b = B.first;\n                auto [ai, aj] = pos(a);\n                auto [bi, bj] = pos(b);\n                if (mode == 0) {\n                    if (wcell[a] != wcell[b]) return wcell[a] > wcell[b];\n                    int da = abs(ai-ui)+abs(aj-uj);\n                    int db = abs(bi-ui)+abs(bj-uj);\n                    if (da != db) return da < db;\n                } else if (mode == 1) {\n                    int da = abs(ai) + abs(aj);\n                    int db = abs(bi) + abs(bj);\n                    if (wcell[a] != wcell[b]) return wcell[a] > wcell[b];\n                    if (da != db) return da < db;\n                } else if (mode == 2) {\n                    int da = abs(ai - (N-1)/2) + abs(aj - (N-1)/2);\n                    int db = abs(bi - (N-1)/2) + abs(bj - (N-1)/2);\n                    if (wcell[a] != wcell[b]) return wcell[a] > wcell[b];\n                    if (da != db) return da < db;\n                } else {\n                    if (wcell[a] != wcell[b]) return wcell[a] > wcell[b];\n                    if (ai != bi) return ai < bi;\n                    return aj < bj;\n                }\n                if (ai != bi) return ai < bi;\n                return aj < bj;\n            });\n        }\n\n        string route;\n        route.reserve(2 * (V - 1));\n\n        function<void(int)> dfs = [&](int u) {\n            for (auto [ch, c] : tree[u]) {\n                route.push_back(c);\n                dfs(ch);\n                route.push_back(rev(c));\n            }\n        };\n        dfs(0);\n        return route;\n    };\n\n    string best;\n    long long bestScore = (long long)4e18;\n\n    vector<double> alphas = {\n        0.0, 0.15, 0.25, 0.35, 0.5, 0.7, 1.0\n    };\n\n    for (double alpha : alphas) {\n        for (int mode = 0; mode < 4; mode++) {\n            string cand = build_tree(alpha, mode);\n            if ((int)cand.size() > 100000) continue;\n            long long sc = evaluate(cand);\n            if (sc < bestScore) {\n                bestScore = sc;\n                best = cand;\n            }\n        }\n    }\n\n    // Fallback (should never be needed)\n    if (best.empty()) {\n        vector<int> vis(V, 0);\n        string route;\n        function<void(int)> dfs = [&](int u) {\n            vis[u] = 1;\n            for (auto &e : g[u]) {\n                if (!vis[e.to]) {\n                    route.push_back(e.dir);\n                    dfs(e.to);\n                    route.push_back(rev(e.dir));\n                }\n            }\n        };\n        dfs(0);\n        best = route;\n    }\n\n    cout << best << '\\n';\n    return 0;\n}","ahc028":"#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        auto ed = chrono::steady_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstatic const int INF = 1e9;\n\nstruct Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    // Positions of each letter\n    vector<vector<Pos>> pos(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            pos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    // Precompute min movement distances between letters\n    int bestDist[26][26];\n    int startDist[26];\n    for (int c = 0; c < 26; c++) {\n        startDist[c] = INF;\n        for (auto &p : pos[c]) {\n            startDist[c] = min(startDist[c], abs(si - p.x) + abs(sj - p.y));\n        }\n    }\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            int d = INF;\n            for (auto &p : pos[a]) for (auto &q : pos[b]) {\n                d = min(d, abs(p.x - q.x) + abs(p.y - q.y));\n            }\n            bestDist[a][b] = d;\n        }\n    }\n\n    // Overlap matrix\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++) if (i != j) {\n            int best = 0;\n            for (int k = 1; k <= 4; k++) {\n                bool ok = true;\n                for (int x = 0; x < k; x++) {\n                    if (t[i][5 - k + x] != t[j][x]) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) best = k;\n            }\n            ov[i][j] = best;\n        }\n    }\n\n    auto approx_word_cost = [&](const string &s) -> int {\n        int c0 = s[0] - 'A';\n        int cost = startDist[c0] + 1;\n        for (int i = 1; i < (int)s.size(); i++) {\n            int a = s[i - 1] - 'A';\n            int b = s[i] - 'A';\n            cost += bestDist[a][b] + 1;\n        }\n        return cost;\n    };\n\n    auto approx_append_cost = [&](char lastc, const string &add) -> int {\n        if (add.empty()) return 0;\n        int cost = bestDist[lastc - 'A'][add[0] - 'A'] + 1;\n        for (int i = 1; i < (int)add.size(); i++) {\n            cost += bestDist[add[i - 1] - 'A'][add[i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    mt19937 rng(712367821);\n\n    auto build_string_from_order = [&](const vector<int> &ord) -> string {\n        if (ord.empty()) return \"\";\n        string s = t[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            int o = ov[ord[i - 1]][ord[i]];\n            s += t[ord[i]].substr(o);\n        }\n        return s;\n    };\n\n    auto approx_score_order = [&](const vector<int> &ord) -> long long {\n        if (ord.empty()) return (long long)4e18;\n        string s = build_string_from_order(ord);\n        // approximate total typing cost\n        long long cost = approx_word_cost(string(1, s[0]));\n        // fix because approx_word_cost on 1-char works but let's do direct full:\n        cost = startDist[s[0] - 'A'] + 1;\n        for (int i = 1; i < (int)s.size(); i++) {\n            cost += bestDist[s[i - 1] - 'A'][s[i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    auto greedy_build = [&](int start, double overlap_w, double move_w, int topk_random) {\n        vector<int> ord;\n        vector<char> used(M, 0);\n        ord.reserve(M);\n        ord.push_back(start);\n        used[start] = 1;\n        int cur = start;\n        for (int step = 1; step < M; step++) {\n            vector<pair<double,int>> cand;\n            cand.reserve(M);\n            for (int nx = 0; nx < M; nx++) if (!used[nx]) {\n                int o = ov[cur][nx];\n                string add = t[nx].substr(o);\n                int move = approx_append_cost(t[cur][4], add);\n                double sc = overlap_w * o - move_w * move;\n                // tiny tie breaker\n                sc += 1e-6 * (rng() % 1000);\n                cand.push_back({sc, nx});\n            }\n            sort(cand.begin(), cand.end(), [&](auto &a, auto &b) {\n                return a.first > b.first;\n            });\n            int choose_idx = 0;\n            if ((int)cand.size() > 1 && topk_random > 1) {\n                int lim = min(topk_random, (int)cand.size());\n                choose_idx = rng() % lim;\n            }\n            int nx = cand[choose_idx].second;\n            used[nx] = 1;\n            ord.push_back(nx);\n            cur = nx;\n        }\n        return ord;\n    };\n\n    vector<int> best_order;\n    long long best_approx = (long long)4e18;\n\n    // candidate starts\n    vector<pair<int,int>> startRank;\n    for (int i = 0; i < M; i++) {\n        int val = -startDist[t[i][0] - 'A'];\n        startRank.push_back({val, i});\n    }\n    sort(startRank.begin(), startRank.end(), greater<>());\n\n    // Multi-start randomized greedy\n    int trials = 0;\n    while (timer.elapsed() < 1.2) {\n        int sidx;\n        if (trials < 30) sidx = startRank[trials % min(M, 30)].second;\n        else sidx = rng() % M;\n\n        double overlap_w = 10.0 + (rng() % 900) / 100.0; // 10.0 .. 18.99\n        double move_w = 0.6 + (rng() % 120) / 100.0;     // 0.6 .. 1.79\n        int topk = 1 + (rng() % 4);\n\n        auto ord = greedy_build(sidx, overlap_w, move_w, topk);\n        long long sc = approx_score_order(ord);\n        if (sc < best_approx) {\n            best_approx = sc;\n            best_order = ord;\n        }\n        trials++;\n    }\n\n    // Simple local search on order using approximate score\n    auto try_improve = [&](vector<int> ord) {\n        long long curScore = approx_score_order(ord);\n        bool improved = true;\n        while (improved && timer.elapsed() < 1.75) {\n            improved = false;\n\n            // random relocate\n            for (int it = 0; it < 80 && timer.elapsed() < 1.75; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                auto tmp = ord;\n                int v = tmp[i];\n                tmp.erase(tmp.begin() + i);\n                tmp.insert(tmp.begin() + j, v);\n                long long ns = approx_score_order(tmp);\n                if (ns < curScore) {\n                    ord.swap(tmp);\n                    curScore = ns;\n                    improved = true;\n                }\n            }\n\n            // random swap\n            for (int it = 0; it < 80 && timer.elapsed() < 1.75; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                auto tmp = ord;\n                swap(tmp[i], tmp[j]);\n                long long ns = approx_score_order(tmp);\n                if (ns < curScore) {\n                    ord.swap(tmp);\n                    curScore = ns;\n                    improved = true;\n                }\n            }\n        }\n        return make_pair(ord, curScore);\n    };\n\n    if (!best_order.empty()) {\n        auto improved = try_improve(best_order);\n        if (improved.second < best_approx) {\n            best_order = improved.first;\n            best_approx = improved.second;\n        }\n    }\n\n    string S = build_string_from_order(best_order);\n\n    // Exact DP for minimal typing path on the board for S\n    int L = (int)S.size();\n    vector<vector<int>> candIdx(L);\n    for (int i = 0; i < L; i++) {\n        int c = S[i] - 'A';\n        candIdx[i].resize(pos[c].size());\n        iota(candIdx[i].begin(), candIdx[i].end(), 0);\n    }\n\n    vector<vector<int>> dp(L), pre(L);\n    {\n        int c = S[0] - 'A';\n        int sz = pos[c].size();\n        dp[0].assign(sz, INF);\n        pre[0].assign(sz, -1);\n        for (int j = 0; j < sz; j++) {\n            auto &p = pos[c][j];\n            dp[0][j] = abs(si - p.x) + abs(sj - p.y) + 1;\n        }\n    }\n\n    for (int i = 1; i < L; i++) {\n        int pc = S[i - 1] - 'A';\n        int cc = S[i] - 'A';\n        int psz = pos[pc].size();\n        int csz = pos[cc].size();\n        dp[i].assign(csz, INF);\n        pre[i].assign(csz, -1);\n        for (int v = 0; v < csz; v++) {\n            auto &q = pos[cc][v];\n            int best = INF, bestu = -1;\n            for (int u = 0; u < psz; u++) {\n                auto &p = pos[pc][u];\n                int val = dp[i - 1][u] + abs(p.x - q.x) + abs(p.y - q.y) + 1;\n                if (val < best) {\n                    best = val;\n                    bestu = u;\n                }\n            }\n            dp[i][v] = best;\n            pre[i][v] = bestu;\n        }\n    }\n\n    int lastIdx = 0;\n    for (int j = 1; j < (int)dp[L - 1].size(); j++) {\n        if (dp[L - 1][j] < dp[L - 1][lastIdx]) lastIdx = j;\n    }\n\n    vector<Pos> ans(L);\n    int curIdx = lastIdx;\n    for (int i = L - 1; i >= 0; i--) {\n        int c = S[i] - 'A';\n        ans[i] = pos[c][curIdx];\n        if (i > 0) curIdx = pre[i][curIdx];\n    }\n\n    // Output operations\n    // Number of operations = |S| <= 5000 safely\n    for (auto &p : ans) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct FastBitset {\n    static constexpr int MAXB = 400;\n    int nblk;\n    array<unsigned long long, (MAXB + 63) / 64> a{};\n    FastBitset(int n = 0) { nblk = (n + 63) >> 6; reset(); }\n    void reset() { for (int i = 0; i < (int)a.size(); i++) a[i] = 0ULL; }\n    void set(int p) { a[p >> 6] |= 1ULL << (p & 63); }\n    bool test(int p) const { return (a[p >> 6] >> (p & 63)) & 1ULL; }\n    void OR(const FastBitset& o) { for (int i = 0; i < nblk; i++) a[i] |= o.a[i]; }\n    int count() const {\n        int s = 0;\n        for (int i = 0; i < nblk; i++) s += __builtin_popcountll(a[i]);\n        return s;\n    }\n};\n\nstruct Placement {\n    int di, dj;\n    vector<int> cells;\n    FastBitset bs;\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    int h = 0, w = 0;\n    vector<Placement> plc;\n    vector<char> alive;\n};\n\nstruct Solver {\n    int N, M;\n    double eps;\n    vector<Field> fields;\n\n    int maxOps;\n    int ops = 0;\n\n    vector<int> drilled;          // -1 unknown else exact v\n    vector<int> drilledList;\n\n    vector<vector<int>> coverCnt; // [m][cell] alive placements covering\n    vector<int> aliveCnt;         // [m]\n\n    mt19937 rng{712367821};\n\n    Solver() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> M >> eps;\n        fields.resize(M);\n        for (int m = 0; m < M; m++) {\n            int d;\n            cin >> d;\n            fields[m].shape.resize(d);\n            int hi = 0, hj = 0;\n            for (int t = 0; t < d; t++) {\n                int i, j;\n                cin >> i >> j;\n                fields[m].shape[t] = {i, j};\n                hi = max(hi, i);\n                hj = max(hj, j);\n            }\n            fields[m].h = hi + 1;\n            fields[m].w = hj + 1;\n        }\n\n        maxOps = 2 * N * N;\n        drilled.assign(N * N, -1);\n\n        buildPlacements();\n        initCounts();\n    }\n\n    int id(int i, int j) const { return i * N + j; }\n    pair<int,int> rc(int x) const { return {x / N, x % N}; }\n\n    void buildPlacements() {\n        for (int m = 0; m < M; m++) {\n            auto &f = fields[m];\n            for (int di = 0; di + f.h <= N; di++) {\n                for (int dj = 0; dj + f.w <= N; dj++) {\n                    Placement p;\n                    p.di = di; p.dj = dj;\n                    p.bs = FastBitset(N * N);\n                    for (auto [i, j] : f.shape) {\n                        int c = id(di + i, dj + j);\n                        p.cells.push_back(c);\n                        p.bs.set(c);\n                    }\n                    f.plc.push_back(move(p));\n                }\n            }\n            f.alive.assign(f.plc.size(), 1);\n        }\n    }\n\n    void initCounts() {\n        coverCnt.assign(M, vector<int>(N * N, 0));\n        aliveCnt.assign(M, 0);\n        for (int m = 0; m < M; m++) {\n            aliveCnt[m] = (int)fields[m].plc.size();\n            for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                for (int c : fields[m].plc[p].cells) coverCnt[m][c]++;\n            }\n        }\n    }\n\n    void eliminatePlacement(int m, int p) {\n        if (!fields[m].alive[p]) return;\n        fields[m].alive[p] = 0;\n        aliveCnt[m]--;\n        for (int c : fields[m].plc[p].cells) coverCnt[m][c]--;\n    }\n\n    void propagate() {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n\n            // Immediate elimination from zero cells and interval feasibility on drilled cells.\n            vector<int> minCov(N * N, 0), maxCov(N * N, 0);\n            for (int c : drilledList) {\n                int mn = 0, mx = 0;\n                for (int m = 0; m < M; m++) {\n                    if (coverCnt[m][c] == aliveCnt[m]) mn++;\n                    if (coverCnt[m][c] > 0) mx++;\n                }\n                minCov[c] = mn;\n                maxCov[c] = mx;\n            }\n\n            for (int m = 0; m < M; m++) {\n                for (int p = 0; p < (int)fields[m].plc.size(); p++) if (fields[m].alive[p]) {\n                    bool bad = false;\n                    for (int c : drilledList) {\n                        int b = fields[m].plc[p].bs.test(c) ? 1 : 0;\n                        int mnOther = minCov[c] - (coverCnt[m][c] == aliveCnt[m] ? 1 : 0);\n                        int mxOther = maxCov[c] - (coverCnt[m][c] > 0 ? 1 : 0);\n                        int need = drilled[c] - b;\n                        if (need < mnOther || need > mxOther) {\n                            bad = true;\n                            break;\n                        }\n                    }\n                    if (bad) {\n                        eliminatePlacement(m, p);\n                        changed = true;\n                    }\n                }\n                if (aliveCnt[m] == 0) return; // inconsistent, but continue robustly\n            }\n\n            // Handle exact zero drilled: no alive placement may cover it.\n            for (int c : drilledList) if (drilled[c] == 0) {\n                for (int m = 0; m < M; m++) {\n                    if (coverCnt[m][c] == 0) continue;\n                    for (int p = 0; p < (int)fields[m].plc.size(); p++) if (fields[m].alive[p]) {\n                        if (fields[m].plc[p].bs.test(c)) {\n                            eliminatePlacement(m, p);\n                            changed = true;\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    int queryDrill(int c) {\n        auto [i, j] = rc(c);\n        cout << \"q 1 \" << i << \" \" << j << '\\n';\n        cout.flush();\n        int x;\n        cin >> x;\n        ops++;\n        if (drilled[c] == -1) {\n            drilled[c] = x;\n            drilledList.push_back(c);\n        } else {\n            drilled[c] = x;\n        }\n        return x;\n    }\n\n    vector<double> oilProb() {\n        vector<double> p(N * N, 0.0);\n        for (int c = 0; c < N * N; c++) {\n            long double prod = 1.0L;\n            for (int m = 0; m < M; m++) {\n                if (aliveCnt[m] <= 0) continue;\n                double q = (double)coverCnt[m][c] / (double)aliveCnt[m];\n                prod *= (1.0L - q);\n            }\n            p[c] = 1.0 - (double)prod;\n        }\n        for (int c : drilledList) p[c] = (drilled[c] > 0 ? 1.0 : 0.0);\n        return p;\n    }\n\n    vector<double> expReserve() {\n        vector<double> e(N * N, 0.0);\n        for (int c = 0; c < N * N; c++) {\n            double s = 0.0;\n            for (int m = 0; m < M; m++) {\n                if (aliveCnt[m] <= 0) continue;\n                s += (double)coverCnt[m][c] / (double)aliveCnt[m];\n            }\n            e[c] = s;\n        }\n        for (int c : drilledList) e[c] = drilled[c];\n        return e;\n    }\n\n    int chooseNextCell() {\n        auto p = oilProb();\n        auto e = expReserve();\n\n        int best = -1;\n        double bestScore = -1e100;\n\n        for (int c = 0; c < N * N; c++) {\n            if (drilled[c] != -1) continue;\n            double amb = p[c] * (1.0 - p[c]);\n            double local = 0.0;\n            auto [i, j] = rc(c);\n            for (int di = -1; di <= 1; di++) for (int dj = -1; dj <= 1; dj++) {\n                int ni = i + di, nj = j + dj;\n                if (0 <= ni && ni < N && 0 <= nj && nj < N) {\n                    local += p[id(ni, nj)] * (1.0 - p[id(ni, nj)]);\n                }\n            }\n            double score = amb * 10.0 + 0.3 * e[c] + 0.2 * local;\n\n            // Slight preference for cells constrained by many shapes\n            int cnt = 0;\n            for (int m = 0; m < M; m++) if (coverCnt[m][c] > 0) cnt++;\n            score += 0.1 * cnt;\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = c;\n            }\n        }\n        return best;\n    }\n\n    struct Node {\n        int idx;\n        int score;\n        vector<int> choice;\n        vector<unsigned char> sum; // contribution on drilledList positions\n        bool operator<(const Node& other) const { return score < other.score; }\n    };\n\n    bool buildAnswer(vector<int>& outCells) {\n        vector<int> order(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return aliveCnt[a] < aliveCnt[b];\n        });\n\n        int D = drilledList.size();\n        vector<int> target(D);\n        for (int t = 0; t < D; t++) target[t] = drilled[drilledList[t]];\n\n        const int BEAM = 200;\n        vector<Node> beam(1), nextBeam;\n        beam[0].idx = 0;\n        beam[0].score = 0;\n        beam[0].choice.assign(M, -1);\n        beam[0].sum.assign(D, 0);\n\n        for (int z = 0; z < M; z++) {\n            int m = order[z];\n            nextBeam.clear();\n\n            // collect candidate placements with local score\n            vector<pair<int,int>> cand; // (-badness, p)\n            cand.reserve(fields[m].plc.size());\n            for (int p = 0; p < (int)fields[m].plc.size(); p++) if (fields[m].alive[p]) {\n                int loc = 0;\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    int b = fields[m].plc[p].bs.test(c) ? 1 : 0;\n                    if (b && target[t] == 0) loc -= 1000;\n                    else if (b && target[t] > 0) loc += 2;\n                }\n                cand.push_back({-loc, p});\n            }\n            sort(cand.begin(), cand.end());\n            int LIM = min<int>((int)cand.size(), max(20, BEAM));\n\n            for (auto &node : beam) {\n                for (int ii = 0; ii < LIM; ii++) {\n                    int pidx = cand[ii].second;\n                    const auto &pl = fields[m].plc[pidx];\n                    bool bad = false;\n                    Node nd = node;\n                    nd.idx = z + 1;\n                    nd.choice[m] = pidx;\n                    int addScore = 0;\n                    for (int t = 0; t < D; t++) {\n                        int c = drilledList[t];\n                        int b = pl.bs.test(c) ? 1 : 0;\n                        int s = nd.sum[t] + b;\n                        if (s > target[t]) { bad = true; break; }\n                        // remaining fields upper bound\n                        int remMax = 0;\n                        for (int zz = z + 1; zz < M; zz++) {\n                            int mm = order[zz];\n                            if (coverCnt[mm][c] > 0) remMax++;\n                        }\n                        if (s + remMax < target[t]) { bad = true; break; }\n                        nd.sum[t] = (unsigned char)s;\n                        if (b && target[t] > 0) addScore += 2;\n                    }\n                    if (bad) continue;\n                    nd.score += addScore;\n                    nextBeam.push_back(move(nd));\n                }\n            }\n\n            if (nextBeam.empty()) return false;\n            nth_element(nextBeam.begin(), nextBeam.begin() + min<int>(BEAM, nextBeam.size()) - 1, nextBeam.end(),\n                        [](const Node& a, const Node& b){ return a.score > b.score; });\n            sort(nextBeam.begin(), nextBeam.begin() + min<int>(BEAM, nextBeam.size()),\n                 [](const Node& a, const Node& b){ return a.score > b.score; });\n            if ((int)nextBeam.size() > BEAM) nextBeam.resize(BEAM);\n            beam.swap(nextBeam);\n        }\n\n        Node* bestNode = nullptr;\n        for (auto &node : beam) {\n            bool ok = true;\n            for (int t = 0; t < D; t++) if ((int)node.sum[t] != target[t]) { ok = false; break; }\n            if (ok) {\n                bestNode = &node;\n                break;\n            }\n        }\n        if (!bestNode) return false;\n\n        vector<char> has(N * N, 0);\n        for (int m = 0; m < M; m++) {\n            int p = bestNode->choice[m];\n            if (p < 0) return false;\n            for (int c : fields[m].plc[p].cells) has[c] = 1;\n        }\n        for (int c : drilledList) {\n            if (drilled[c] > 0 && !has[c]) return false;\n            if (drilled[c] == 0 && has[c]) return false;\n        }\n        outCells.clear();\n        for (int c = 0; c < N * N; c++) if (has[c]) outCells.push_back(c);\n        return true;\n    }\n\n    bool answer(const vector<int>& cells) {\n        cout << \"a \" << cells.size();\n        for (int c : cells) {\n            auto [i, j] = rc(c);\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << '\\n';\n        cout.flush();\n        int res;\n        cin >> res;\n        ops++;\n        return res == 1;\n    }\n\n    void solve() {\n        int softBudget = min(maxOps - 1, max(40, N * N / 2));\n\n        for (;;) {\n            propagate();\n\n            bool impossible = false;\n            for (int m = 0; m < M; m++) if (aliveCnt[m] == 0) impossible = true;\n\n            vector<int> candAns;\n            if (!impossible && buildAnswer(candAns)) {\n                // If sufficiently determined or budget almost consumed, answer.\n                int uncertainty = 0;\n                for (int m = 0; m < M; m++) uncertainty += max(0, aliveCnt[m] - 1);\n                if (uncertainty == 0 || ops >= softBudget || (int)drilledList.size() >= N * N / 3) {\n                    if (answer(candAns)) return;\n                }\n            }\n\n            if (ops >= maxOps - 1) {\n                // final fallback\n                vector<int> finalAns;\n                if (!impossible && buildAnswer(finalAns)) {\n                    answer(finalAns);\n                    return;\n                } else {\n                    auto p = oilProb();\n                    vector<int> cells;\n                    vector<char> used(N * N, 0);\n                    for (int c : drilledList) if (drilled[c] > 0) used[c] = 1;\n                    for (int c = 0; c < N * N; c++) if (p[c] >= 0.5) used[c] = 1;\n                    for (int c = 0; c < N * N; c++) if (used[c]) cells.push_back(c);\n                    answer(cells);\n                    return;\n                }\n            }\n\n            int c = chooseNextCell();\n            if (c == -1) {\n                vector<int> finalAns;\n                if (!impossible && buildAnswer(finalAns)) {\n                    if (answer(finalAns)) return;\n                } else {\n                    auto p = oilProb();\n                    vector<int> cells;\n                    for (int x = 0; x < N * N; x++) if (drilled[x] > 0 || p[x] >= 0.5) cells.push_back(x);\n                    answer(cells);\n                    return;\n                }\n            } else {\n                queryDrill(c);\n            }\n        }\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const int W = 1000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W_in, D, N;\n    cin >> W_in >> D >> 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    // We use a static vertical partition:\n    // rectangle k = [0,W] x [prefix[k], prefix[k+1]]\n    // area = 1000 * width[k], width[k] integer, sum width = 1000.\n    //\n    // Optimize widths greedily by marginal penalty reduction.\n\n    vector<int> width(N, 1);\n    int remaining = W - N; // extra width units to distribute\n\n    // gain[k][t]: reduction in total missing area (not *100) when capacity of k\n    // increases from 1000*t to 1000*(t+1), where current width = t.\n    // Since width starts from 1, t >= 1 in use. But precompute for t=0..999.\n    vector<vector<int>> gain(N, vector<int>(W, 0));\n\n    for (int k = 0; k < N; k++) {\n        for (int t = 0; t < W; t++) {\n            int c0 = W * t;       // 1000 * t\n            int c1 = W * (t + 1); // 1000 * (t+1)\n            ll g = 0;\n            for (int d = 0; d < D; d++) {\n                int x = a[d][k];\n                int before = max(0, x - c0);\n                int after  = max(0, x - c1);\n                g += (before - after);\n            }\n            gain[k][t] = (int)g;\n        }\n    }\n\n    // Priority queue of current marginal gains.\n    using T = pair<int,int>; // gain, k\n    priority_queue<T> pq;\n    for (int k = 0; k < N; k++) {\n        pq.push({gain[k][1], k}); // next gain when width 1 -> 2\n    }\n\n    while (remaining > 0) {\n        auto [g, k] = pq.top(); pq.pop();\n        int t = width[k];\n        // stale check\n        int realg = (t < W ? gain[k][t] : 0);\n        if (g != realg) {\n            pq.push({realg, k});\n            continue;\n        }\n        width[k]++;\n        remaining--;\n        t = width[k];\n        pq.push({(t < W ? gain[k][t] : 0), k});\n    }\n\n    // Build coordinates\n    vector<int> pref(N + 1, 0);\n    for (int k = 0; k < N; k++) pref[k + 1] = pref[k] + width[k];\n\n    // Output same layout every day, giving zero partition transition cost.\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int i0 = 0, j0 = pref[k], i1 = W, j1 = pref[k + 1];\n            cout << i0 << ' ' << j0 << ' ' << i1 << ' ' << j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 9;\nstatic constexpr int P = 7; // positions per axis = N-2\nstatic constexpr int MMAX = 20;\nstatic constexpr int KMAX = 81;\nstatic constexpr long long MOD = 998244353LL;\n\nstruct Action {\n    int m, p, q;\n    int idx[9];          // affected board indices (0..80)\n    long long add[9];    // added values mod MOD\n};\n\nstruct Move {\n    int m, p, q;\n};\n\nlong long gain_cell(long long cur, long long x) {\n    long long y = cur + x;\n    return (y >= MOD) ? (x - MOD) : x;\n}\n\nlong long action_gain(const array<long long, 81>& board, const Action& a) {\n    long long g = 0;\n    for (int t = 0; t < 9; t++) {\n        g += gain_cell(board[a.idx[t]], a.add[t]);\n    }\n    return g;\n}\n\nvoid apply_action(array<long long,81>& board, const Action& a) {\n    for (int t = 0; t < 9; t++) {\n        long long &v = board[a.idx[t]];\n        v += a.add[t];\n        if (v >= MOD) v -= MOD;\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin, Min, Kin;\n    cin >> Nin >> Min >> Kin;\n\n    array<long long, 81> board{};\n    for (int i = 0; i < Nin; i++) {\n        for (int j = 0; j < Nin; j++) {\n            cin >> board[i * N + j];\n        }\n    }\n\n    vector<array<array<long long,3>,3>> stamps(Min);\n    for (int m = 0; m < Min; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    vector<Action> actions;\n    actions.reserve(Min * P * P);\n    for (int m = 0; m < Min; m++) {\n        for (int p = 0; p < P; p++) {\n            for (int q = 0; q < P; q++) {\n                Action a;\n                a.m = m; a.p = p; a.q = q;\n                int t = 0;\n                for (int i = 0; i < 3; i++) {\n                    for (int j = 0; j < 3; j++) {\n                        a.idx[t] = (p + i) * N + (q + j);\n                        a.add[t] = stamps[m][i][j];\n                        t++;\n                    }\n                }\n                actions.push_back(a);\n            }\n        }\n    }\n\n    vector<Move> ans;\n    ans.reserve(Kin);\n\n    const int BEAM = 30;\n\n    for (int step = 0; step < Kin; step++) {\n        vector<pair<long long,int>> cand;\n        cand.reserve(actions.size());\n\n        long long best_now_gain = LLONG_MIN;\n        int best_now_idx = -1;\n\n        for (int i = 0; i < (int)actions.size(); i++) {\n            long long g = action_gain(board, actions[i]);\n            if (g > best_now_gain) {\n                best_now_gain = g;\n                best_now_idx = i;\n            }\n            if (g > 0) cand.push_back({g, i});\n        }\n\n        if (best_now_gain <= 0) break;\n\n        sort(cand.begin(), cand.end(), [&](const auto& x, const auto& y) {\n            if (x.first != y.first) return x.first > y.first;\n            return x.second < y.second;\n        });\n        if ((int)cand.size() > BEAM) cand.resize(BEAM);\n\n        long long best_eval = LLONG_MIN;\n        int best_idx = best_now_idx;\n\n        array<long long,81> tmp;\n        for (auto [g1, idx1] : cand) {\n            tmp = board;\n            apply_action(tmp, actions[idx1]);\n\n            long long best2 = 0; // stopping is allowed\n            for (int j = 0; j < (int)actions.size(); j++) {\n                long long g2 = action_gain(tmp, actions[j]);\n                if (g2 > best2) best2 = g2;\n            }\n\n            long long eval = g1 + best2;\n            if (eval > best_eval) {\n                best_eval = eval;\n                best_idx = idx1;\n            }\n        }\n\n        apply_action(board, actions[best_idx]);\n        ans.push_back({actions[best_idx].m, actions[best_idx].p, actions[best_idx].q});\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto &mv : ans) {\n        cout << mv.m << ' ' << mv.p << ' ' << mv.q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n; // always 5\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<string> ans(N);\n\n    auto add_turn = [&](char c0, char c1='.', char c2='.', char c3='.', char c4='.') {\n        ans[0].push_back(c0);\n        ans[1].push_back(c1);\n        ans[2].push_back(c2);\n        ans[3].push_back(c3);\n        ans[4].push_back(c4);\n    };\n\n    // Bomb all small cranes immediately.\n    add_turn('.', 'B', 'B', 'B', 'B');\n\n    vector<int> ptr(N, 0);         // next unseen container in each receiving row\n    vector<int> need(N);           // next required container for each dispatch row\n    for (int r = 0; r < N; r++) need[r] = r * N;\n\n    int cr = 0, cc = 0;            // large crane position\n    int delivered = 0;\n\n    auto move_large = [&](int tr, int tc) {\n        while (cr < tr) { add_turn('D'); cr++; }\n        while (cr > tr) { add_turn('U'); cr--; }\n        while (cc < tc) { add_turn('R'); cc++; }\n        while (cc > tc) { add_turn('L'); cc--; }\n    };\n\n    while (delivered < N * N) {\n        int bestRow = -1;\n        int bestDist = 1e9;\n        int bestX = -1;\n\n        for (int i = 0; i < N; i++) {\n            if (ptr[i] >= N) continue;\n            int x = A[i][ptr[i]];\n            int gr = x / N;\n            if (x == need[gr]) {\n                int dist = abs(cr - i) + abs(cc - 0);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestRow = i;\n                    bestX = x;\n                }\n            }\n        }\n\n        // This should not happen, but for safety:\n        // if no currently front container is \"deliverable\", just take the nearest front one.\n        // This keeps the program producing a valid answer.\n        if (bestRow == -1) {\n            for (int i = 0; i < N; i++) {\n                if (ptr[i] >= N) continue;\n                int x = A[i][ptr[i]];\n                int dist = abs(cr - i) + abs(cc - 0);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestRow = i;\n                    bestX = x;\n                }\n            }\n        }\n\n        // Move to receiving gate\n        move_large(bestRow, 0);\n\n        // Pick the front container\n        add_turn('P');\n        ptr[bestRow]++;\n\n        // Deliver to its correct dispatch gate\n        int goalRow = bestX / N;\n        move_large(goalRow, N - 1);\n        add_turn('Q');\n\n        // If delivered in-order to correct gate, advance need.\n        if (bestX == need[goalRow]) need[goalRow]++;\n        delivered++;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (ans[i].empty()) ans[i] = \".\";\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int N = 20;\nstatic constexpr int TURN_LIMIT = 100000;\n\nstruct Solver {\n    int n;\n    vector<vector<int>> h;\n    vector<string> ops;\n    int x = 0, y = 0;\n    ll load = 0;\n\n    Solver(int n_, vector<vector<int>> h_) : n(n_), h(move(h_)) {}\n\n    void emit(const string& s) {\n        if ((int)ops.size() < TURN_LIMIT) ops.push_back(s);\n    }\n\n    void move_one(char c) {\n        emit(string(1, c));\n        if (c == 'U') --x;\n        else if (c == 'D') ++x;\n        else if (c == 'L') --y;\n        else if (c == 'R') ++y;\n    }\n\n    void move_to(int nx, int ny) {\n        while (x < nx) move_one('D');\n        while (x > nx) move_one('U');\n        while (y < ny) move_one('R');\n        while (y > ny) move_one('L');\n    }\n\n    void pickup(int d) {\n        if (d <= 0) return;\n        emit(\"+\" + to_string(d));\n        h[x][y] -= d;\n        load += d;\n    }\n\n    void dropoff(int d) {\n        if (d <= 0) return;\n        emit(\"-\" + to_string(d));\n        h[x][y] += d;\n        load -= d;\n    }\n\n    void process_cell() {\n        if ((int)ops.size() >= TURN_LIMIT) return;\n        if (h[x][y] > 0) {\n            pickup(h[x][y]);\n        } else if (h[x][y] < 0) {\n            int d = (int)min<ll>(load, -h[x][y]);\n            dropoff(d);\n        }\n    }\n\n    bool all_zero() const {\n        for (int i = 0; i < n; ++i)\n            for (int j = 0; j < n; ++j)\n                if (h[i][j] != 0) return false;\n        return load == 0;\n    }\n\n    vector<pair<int,int>> make_snake() {\n        vector<pair<int,int>> ord;\n        for (int i = 0; i < n; ++i) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < n; ++j) ord.push_back({i, j});\n            } else {\n                for (int j = n - 1; j >= 0; --j) ord.push_back({i, j});\n            }\n        }\n        return ord;\n    }\n\n    void traverse(const vector<pair<int,int>>& ord) {\n        for (auto [nx, ny] : ord) {\n            if ((int)ops.size() >= TURN_LIMIT) return;\n            move_to(nx, ny);\n            process_cell();\n        }\n    }\n\n    void solve() {\n        auto ord = make_snake();\n\n        // Start at (0,0), process it first.\n        process_cell();\n\n        // Alternate forward/backward sweeps.\n        // Usually a couple of sweeps are enough.\n        for (int rep = 0; rep < 20; ++rep) {\n            if (all_zero()) break;\n            if ((int)ops.size() >= TURN_LIMIT - 1000) break;\n\n            if (rep % 2 == 0) {\n                traverse(ord);\n            } else {\n                vector<pair<int,int>> rev = ord;\n                reverse(rev.begin(), rev.end());\n                traverse(rev);\n            }\n        }\n\n        // If load remains, try to dump it into remaining negative cells if any,\n        // otherwise this should not happen when total sum is zero and enough sweeps were done.\n        if (!all_zero()) {\n            // Extra cleanup sweeps\n            vector<pair<int,int>> rev = ord;\n            reverse(rev.begin(), rev.end());\n            while (!all_zero() && (int)ops.size() < TURN_LIMIT - 1000) {\n                traverse(ord);\n                if (all_zero()) break;\n                traverse(rev);\n            }\n        }\n\n        // In the very unlikely event still unfinished, we just output what we have.\n        // But normally this completes exactly.\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<vector<int>> h(n, vector<int>(n));\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) cin >> h[i][j];\n    }\n\n    Solver solver(n, h);\n    solver.solve();\n\n    for (auto &s : solver.ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 6;\nstatic constexpr int M = 15;\nstatic constexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nstatic constexpr int CELL_COUNT = N * N;           // 36\n\nstruct Seed {\n    array<int, M> x{};\n    int sum = 0;\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    vector<Seed> seeds(SEED_COUNT);\n    for (int i = 0; i < SEED_COUNT; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    // Grid adjacency\n    vector<vector<int>> cellNbr(CELL_COUNT);\n    vector<pair<int,int>> edges;\n    auto id = [&](int r, int c) { return r * N + c; };\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int v = id(r, c);\n            if (r + 1 < N) {\n                int u = id(r + 1, c);\n                cellNbr[v].push_back(u);\n                cellNbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n            if (c + 1 < N) {\n                int u = id(r, c + 1);\n                cellNbr[v].push_back(u);\n                cellNbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n        }\n    }\n\n    vector<int> cellOrder(CELL_COUNT);\n    iota(cellOrder.begin(), cellOrder.end(), 0);\n    auto cellDeg = [&](int c) { return (int)cellNbr[c].size(); };\n    sort(cellOrder.begin(), cellOrder.end(), [&](int a, int b) {\n        int da = cellDeg(a), db = cellDeg(b);\n        if (da != db) return da > db;\n        int ra = a / N, ca = a % N;\n        int rb = b / N, cb = b % N;\n        int dca = abs(ra - 2) + abs(ca - 2);\n        int dcb = abs(rb - 2) + abs(cb - 2);\n        return dca < dcb;\n    });\n\n    for (int turn = 0; turn < T; turn++) {\n        // 1) Select top 36 seeds by total value\n        vector<int> ord(SEED_COUNT);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n        vector<int> chosen(ord.begin(), ord.begin() + CELL_COUNT);\n\n        // Local index mapping for chosen seeds\n        vector<int> posOfSeed(SEED_COUNT, -1);\n        for (int i = 0; i < CELL_COUNT; i++) posOfSeed[chosen[i]] = i;\n\n        // 2) Pair score among chosen seeds: sum max by coordinate\n        static int pairScore[CELL_COUNT][CELL_COUNT];\n        for (int i = 0; i < CELL_COUNT; i++) {\n            pairScore[i][i] = 0;\n            for (int j = i + 1; j < CELL_COUNT; j++) {\n                int a = chosen[i], b = chosen[j];\n                int sc = 0;\n                for (int k = 0; k < M; k++) sc += max(seeds[a].x[k], seeds[b].x[k]);\n                pairScore[i][j] = pairScore[j][i] = sc;\n            }\n        }\n\n        // 3) Greedy placement\n        vector<int> place(CELL_COUNT, -1);      // cell -> local chosen index\n        vector<int> used(CELL_COUNT, 0);\n\n        for (int step = 0; step < CELL_COUNT; step++) {\n            int cell = cellOrder[step];\n\n            int bestSeed = -1;\n            long long bestScore = LLONG_MIN;\n\n            for (int si = 0; si < CELL_COUNT; si++) if (!used[si]) {\n                long long sc = 0;\n\n                // reward high-value seeds in high-degree cells\n                sc += 8LL * seeds[chosen[si]].sum * cellDeg(cell);\n\n                // adjacency with already placed neighbors\n                for (int nb : cellNbr[cell]) {\n                    if (place[nb] != -1) {\n                        sc += 10LL * pairScore[si][place[nb]];\n                    }\n                }\n\n                // small center preference for stronger seeds\n                int r = cell / N, c = cell % N;\n                int centerPenalty = abs(r - 2) + abs(c - 2);\n                sc -= 3LL * centerPenalty * seeds[chosen[si]].sum;\n\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestSeed = si;\n                }\n            }\n\n            place[cell] = bestSeed;\n            used[bestSeed] = 1;\n        }\n\n        auto totalPlacementScore = [&](const vector<int>& pl) -> long long {\n            long long res = 0;\n            for (auto [u, v] : edges) {\n                res += pairScore[pl[u]][pl[v]];\n            }\n            for (int c = 0; c < CELL_COUNT; c++) {\n                res += 2LL * seeds[chosen[pl[c]]].sum * cellDeg(c);\n            }\n            return res;\n        };\n\n        auto deltaSwap = [&](const vector<int>& pl, int a, int b) -> long long {\n            if (a == b) return 0;\n            int \u0938\u093e = pl[a], sb = pl[b];\n            long long before = 0, after = 0;\n\n            vector<int> touched;\n            touched.push_back(a);\n            touched.push_back(b);\n            for (int nb : cellNbr[a]) touched.push_back(nb);\n            for (int nb : cellNbr[b]) touched.push_back(nb);\n            sort(touched.begin(), touched.end());\n            touched.erase(unique(touched.begin(), touched.end()), touched.end());\n\n            auto edgeContribution = [&](int u, int v, bool swapped) -> long long {\n                int pu = pl[u], pv = pl[v];\n                if (swapped) {\n                    if (u == a) pu = sb;\n                    else if (u == b) pu = \u0938\u093e;\n                    if (v == a) pv = sb;\n                    else if (v == b) pv = \u0938\u093e;\n                }\n                return pairScore[pu][pv];\n            };\n\n            set<pair<int,int>> es;\n            for (int u : touched) {\n                for (int v : cellNbr[u]) {\n                    if (u < v) es.insert({u, v});\n                }\n            }\n            for (auto [u, v] : es) {\n                before += edgeContribution(u, v, false);\n                after  += edgeContribution(u, v, true);\n            }\n\n            before += 2LL * seeds[chosen[\u0938\u093e]].sum * cellDeg(a);\n            before += 2LL * seeds[chosen[sb]].sum * cellDeg(b);\n            after  += 2LL * seeds[chosen[sb]].sum * cellDeg(a);\n            after  += 2LL * seeds[chosen[\u0938\u093e]].sum * cellDeg(b);\n\n            return after - before;\n        };\n\n        // 4) Local improvement by swapping\n        long long curScore = totalPlacementScore(place);\n        bool improved = true;\n        int iter = 0;\n        while (improved && iter < 8) {\n            improved = false;\n            iter++;\n            for (int a = 0; a < CELL_COUNT; a++) {\n                for (int b = a + 1; b < CELL_COUNT; b++) {\n                    long long d = deltaSwap(place, a, b);\n                    if (d > 0) {\n                        swap(place[a], place[b]);\n                        curScore += d;\n                        improved = true;\n                    }\n                }\n            }\n        }\n\n        // 5) Output grid using original seed indices\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (c) cout << ' ';\n                cout << chosen[place[id(r, c)]];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // 6) Read generated seeds\n        for (int i = 0; i < SEED_COUNT; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC038 heuristic solution\n\nIdea:\n- Use a star arm: root + K leaves, each of length 1.\n- Root moves on the grid; each leaf can independently point to one of 4 neighboring cells.\n- In one turn, after root move and rotations, leaves may pick/place simultaneously.\n- We greedily operate in phases:\n  1) If a leaf is holding, try to place to an adjacent target-needed cell.\n  2) Otherwise, pick from adjacent source-extra cell.\n  3) Move root toward a \"good\" nearby position maximizing immediate gain:\n     score = (#adjacent target-needed cells if holding leaves exist)\n           + (#adjacent source-extra cells if empty leaves exist)\n     minus small distance term.\n- If no direct gain nearby, move toward nearest relevant cell.\n- Stop when all targets are satisfied or turn limit reached.\n\nThis is a simple but reasonably effective baseline exploiting multiple fingers.\n*/\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int DX[4] = {0, 1, 0, -1};   // R D L U in coordinate deltas? wait x=row, y=col\nstatic const int DY[4] = {1, 0, -1, 0};\nstatic const char DIRCH[4] = {'R', 'D', 'L', 'U'};\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    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    // Number of leaves: use as many as possible with star tree.\n    // root + K leaves <= V\n    int K = max(1, V - 1);\n    int Vp = K + 1;\n\n    // Output tree: star centered at root, all edges length 1\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << 1 << '\\n';\n    }\n\n    // Initial root position: center\n    int rx = N / 2, ry = N / 2;\n    cout << rx << ' ' << ry << '\\n';\n\n    // Leaf direction state: 0:R 1:D 2:L 3:U\n    vector<int> dir(K, 0);\n    // Holding state for each leaf\n    vector<int> holding(K, 0);\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    auto need_pick = [&](int x, int y) -> bool {\n        return s[x][y] == '1' && t[x][y] == '0';\n    };\n    auto need_place = [&](int x, int y) -> bool {\n        return s[x][y] == '0' && t[x][y] == '1';\n    };\n\n    auto remaining = [&]() -> int {\n        int r = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (s[i][j] != t[i][j]) r++;\n        }\n        return r / 2;\n    };\n\n    auto nearest_dist = [&](int sx, int sy, bool for_pick) -> int {\n        int best = 1e9;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            bool ok = for_pick ? need_pick(i, j) : need_place(i, j);\n            if (!ok) continue;\n            best = min(best, abs(i - sx) + abs(j - sy));\n        }\n        return best;\n    };\n\n    auto score_pos = [&](int x, int y, int empty_cnt, int hold_cnt) -> int {\n        int gain_pick = 0, gain_place = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + DX[d], ny = y + DY[d];\n            if (!inb(nx, ny)) continue;\n            if (need_pick(nx, ny)) gain_pick++;\n            if (need_place(nx, ny)) gain_place++;\n        }\n        gain_pick = min(gain_pick, empty_cnt);\n        gain_place = min(gain_place, hold_cnt);\n        int sc = 100 * gain_pick + 100 * gain_place;\n        if (empty_cnt > 0) {\n            int md = nearest_dist(x, y, true);\n            if (md < (int)1e9) sc -= md;\n        }\n        if (hold_cnt > 0) {\n            int md = nearest_dist(x, y, false);\n            if (md < (int)1e9) sc -= md;\n        }\n        return sc;\n    };\n\n    vector<string> ops;\n    const int TURN_LIMIT = 100000;\n\n    for (int turn = 0; turn < TURN_LIMIT; turn++) {\n        if (remaining() == 0) break;\n\n        int empty_cnt = 0, hold_cnt = 0;\n        for (int i = 0; i < K; i++) {\n            if (holding[i]) hold_cnt++;\n            else empty_cnt++;\n        }\n\n        // Choose root move among staying + 4 directions\n        int best_mv = -1;\n        int best_sc = score_pos(rx, ry, empty_cnt, hold_cnt);\n\n        for (int mv = 0; mv < 4; mv++) {\n            int nx = rx + DX[mv], ny = ry + DY[mv];\n            if (!inb(nx, ny)) continue;\n            int sc = score_pos(nx, ny, empty_cnt, hold_cnt);\n            if (sc > best_sc) {\n                best_sc = sc;\n                best_mv = mv;\n            }\n        }\n\n        char move_ch = '.';\n        if (best_mv != -1) {\n            rx += DX[best_mv];\n            ry += DY[best_mv];\n            move_ch = DIRCH[best_mv];\n        }\n\n        string cmd(2 * Vp, '.');\n        cmd[0] = move_ch;\n\n        // Determine desired directions for leaves this turn.\n        // We assign unique adjacent cells greedily:\n        // place first (usually more constrained because holding leaves can block progress),\n        // then pick.\n        vector<int> usedDir(4, -1); // which leaf uses this adjacent direction\n        vector<int> leafTargetDir(K, -1);\n\n        // Candidate directions by usefulness\n        vector<int> placeDirs, pickDirs;\n        for (int d = 0; d < 4; d++) {\n            int x = rx + DX[d], y = ry + DY[d];\n            if (!inb(x, y)) continue;\n            if (need_place(x, y)) placeDirs.push_back(d);\n            if (need_pick(x, y)) pickDirs.push_back(d);\n        }\n\n        // Assign holding leaves to place\n        int pi = 0;\n        for (int i = 0; i < K && pi < (int)placeDirs.size(); i++) {\n            if (!holding[i]) continue;\n            int d = placeDirs[pi++];\n            leafTargetDir[i] = d;\n            usedDir[d] = i;\n        }\n\n        // Assign empty leaves to pick\n        int qi = 0;\n        for (int i = 0; i < K && qi < (int)pickDirs.size(); i++) {\n            if (holding[i]) continue;\n            int d = pickDirs[qi++];\n            if (usedDir[d] != -1) continue;\n            leafTargetDir[i] = d;\n            usedDir[d] = i;\n        }\n\n        // Rotate each leaf directly toward target direction (single 90-degree step only).\n        // If opposite, choose arbitrary one-step rotation; next turn it can continue.\n        for (int i = 0; i < K; i++) {\n            int td = leafTargetDir[i];\n            if (td == -1) continue;\n            int cur = dir[i];\n            int diff = (td - cur + 4) % 4;\n            char rc = '.';\n            if (diff == 1) {\n                rc = 'R';\n                dir[i] = (dir[i] + 1) % 4;\n            } else if (diff == 3) {\n                rc = 'L';\n                dir[i] = (dir[i] + 3) % 4;\n            } else if (diff == 2) {\n                rc = 'R';\n                dir[i] = (dir[i] + 1) % 4;\n            }\n            cmd[1 + i] = rc;\n        }\n\n        // Action phase. Process leaves in vertex order.\n        for (int i = 0; i < K; i++) {\n            int x = rx + DX[dir[i]];\n            int y = ry + DY[dir[i]];\n            if (!inb(x, y)) continue;\n\n            if (holding[i]) {\n                if (need_place(x, y)) {\n                    s[x][y] = '1';\n                    holding[i] = 0;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            } else {\n                if (need_pick(x, y)) {\n                    s[x][y] = '0';\n                    holding[i] = 1;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            }\n        }\n\n        ops.push_back(cmd);\n    }\n\n    for (auto &z : ops) cout << z << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct CellInfo {\n    int gx, gy;\n    int w = 0;\n};\n\nstatic inline long long pack_key(int x, int y) {\n    return ( (long long)x << 32 ) ^ (unsigned int)y;\n}\n\nstruct CandidateResult {\n    int D = 0;\n    vector<pair<int,int>> cells; // selected grid cells (gx, gy)\n    long long score = LLONG_MIN; // sum of cell weights\n    long long perim_edges = 0;   // in grid edges\n    vector<pair<int,int>> polygon; // output polygon vertices\n    bool valid = false;\n};\n\nstruct BuildResult {\n    vector<pair<int,int>> polygon;\n    bool single_cycle = false;\n};\n\nBuildResult build_polygon_from_cells(const vector<pair<int,int>>& cells, int D) {\n    // Boundary edges of union of cells.\n    // Use oriented edges with interior on the left (CCW outer boundary for hole-free region).\n    // For each selected cell (x,y) representing [xD,(x+1)D] x [yD,(y+1)D]:\n    // bottom: (x,y)->(x+1,y)\n    // right : (x+1,y)->(x+1,y+1)\n    // top   : (x+1,y+1)->(x,y+1)\n    // left  : (x,y+1)->(x,y)\n    //\n    // Shared internal edges appear in opposite directions and cancel.\n\n    struct Edge {\n        int x1, y1, x2, y2;\n        bool operator==(const Edge& o) const {\n            return x1==o.x1 && y1==o.y1 && x2==o.x2 && y2==o.y2;\n        }\n    };\n    struct EdgeHash {\n        size_t operator()(Edge const& e) const noexcept {\n            size_t h = 0;\n            auto mix = [&](int v) {\n                h ^= std::hash<long long>{}(((long long)v << 1) + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2));\n            };\n            mix(e.x1); mix(e.y1); mix(e.x2); mix(e.y2);\n            return h;\n        }\n    };\n\n    unordered_set<Edge, EdgeHash> S;\n    S.reserve(cells.size() * 8);\n\n    auto toggle_edge = [&](Edge e) {\n        Edge rev{e.x2, e.y2, e.x1, e.y1};\n        auto it = S.find(rev);\n        if (it != S.end()) S.erase(it);\n        else S.insert(e);\n    };\n\n    for (auto [gx, gy] : cells) {\n        int x = gx * D, y = gy * D;\n        toggle_edge({x, y, x + D, y});\n        toggle_edge({x + D, y, x + D, y + D});\n        toggle_edge({x + D, y + D, x, y + D});\n        toggle_edge({x, y + D, x, y});\n    }\n\n    BuildResult res;\n    if (S.empty()) return res;\n\n    // Build next-edge map by start point.\n    // For a proper simple boundary, each vertex should have outdegree 1 and indegree 1 on the chosen cycle(s).\n    unordered_map<long long, vector<pair<int,int>>> out;\n    out.reserve(S.size() * 2);\n\n    auto pkey = [&](int x, int y) -> long long {\n        return pack_key(x, y);\n    };\n\n    for (const auto& e : S) {\n        out[pkey(e.x1, e.y1)].push_back({e.x2, e.y2});\n    }\n\n    // Traverse cycles. We require exactly one cycle using all edges.\n    unordered_set<long long> usedEdge;\n    usedEdge.reserve(S.size() * 2);\n\n    auto edgekey = [&](int x1, int y1, int x2, int y2) -> long long {\n        // coordinates are <= 1e5, but with D multiples still <=1e5; encode robustly via hash combine\n        long long h = 1469598103934665603ULL;\n        auto add = [&](long long v) {\n            h ^= (unsigned long long)v + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n        };\n        add(x1); add(y1); add(x2); add(y2);\n        return h;\n    };\n\n    int cycle_count = 0;\n    vector<pair<int,int>> best_cycle;\n\n    for (const auto& e : S) {\n        long long ek = edgekey(e.x1, e.y1, e.x2, e.y2);\n        if (usedEdge.count(ek)) continue;\n\n        cycle_count++;\n        vector<pair<int,int>> poly;\n        int sx = e.x1, sy = e.y1;\n        int cx = e.x1, cy = e.y1;\n        int nx = e.x2, ny = e.y2;\n\n        poly.push_back({cx, cy});\n\n        while (true) {\n            long long cek = edgekey(cx, cy, nx, ny);\n            if (usedEdge.count(cek)) break;\n            usedEdge.insert(cek);\n\n            cx = nx; cy = ny;\n            poly.push_back({cx, cy});\n            if (cx == sx && cy == sy) break;\n\n            auto it = out.find(pkey(cx, cy));\n            if (it == out.end() || it->second.empty()) {\n                return res;\n            }\n\n            // On simple orthogonal boundary there should be one unique continuation among unused edges.\n            int found = 0;\n            pair<int,int> cand;\n            for (auto to : it->second) {\n                long long nk = edgekey(cx, cy, to.first, to.second);\n                if (!usedEdge.count(nk)) {\n                    cand = to;\n                    found++;\n                }\n            }\n            if (found != 1) {\n                // Multiple cycles touching / malformed / hole complications.\n                return res;\n            }\n            nx = cand.first; ny = cand.second;\n        }\n\n        if ((int)poly.size() >= 4 && poly.front() == poly.back()) {\n            poly.pop_back();\n        }\n        if (poly.size() > best_cycle.size()) best_cycle = poly;\n    }\n\n    if ((int)usedEdge.size() != (int)S.size()) {\n        return res;\n    }\n    if (cycle_count != 1) {\n        return res;\n    }\n\n    // Compress collinear consecutive vertices.\n    vector<pair<int,int>> comp;\n    int m = (int)best_cycle.size();\n    for (int i = 0; i < m; i++) {\n        auto p0 = best_cycle[(i - 1 + m) % m];\n        auto p1 = best_cycle[i];\n        auto p2 = best_cycle[(i + 1) % m];\n        int dx1 = (p1.first > p0.first) - (p1.first < p0.first);\n        int dy1 = (p1.second > p0.second) - (p1.second < p0.second);\n        int dx2 = (p2.first > p1.first) - (p2.first < p1.first);\n        int dy2 = (p2.second > p1.second) - (p2.second < p1.second);\n        if (dx1 == dx2 && dy1 == dy2) continue;\n        comp.push_back(p1);\n    }\n\n    if (comp.size() < 4) return res;\n    if (comp.size() > 1000) return res;\n\n    // Distinct coordinates condition\n    {\n        set<pair<int,int>> st(comp.begin(), comp.end());\n        if (st.size() != comp.size()) return res;\n    }\n\n    res.polygon = move(comp);\n    res.single_cycle = true;\n    return res;\n}\n\nCandidateResult solve_for_grid(const vector<Point>& mac, const vector<Point>& sar, int D) {\n    unordered_map<long long, int> id;\n    vector<CellInfo> cells;\n    cells.reserve(12000);\n    id.reserve(24000);\n\n    auto add_point = [&](int gx, int gy, int delta) {\n        long long key = pack_key(gx, gy);\n        auto it = id.find(key);\n        if (it == id.end()) {\n            int idx = (int)cells.size();\n            id[key] = idx;\n            cells.push_back({gx, gy, delta});\n        } else {\n            cells[it->second].w += delta;\n        }\n    };\n\n    for (auto &p : mac) add_point(p.x / D, p.y / D, +1);\n    for (auto &p : sar) add_point(p.x / D, p.y / D, -1);\n\n    int K = (int)cells.size();\n    if (K == 0) return {};\n\n    vector<array<int,4>> nei(K);\n    for (int i = 0; i < K; i++) {\n        int x = cells[i].gx, y = cells[i].gy;\n        const int dx[4] = {1,0,-1,0};\n        const int dy[4] = {0,1,0,-1};\n        for (int d = 0; d < 4; d++) {\n            auto it = id.find(pack_key(x + dx[d], y + dy[d]));\n            nei[i][d] = (it == id.end() ? -1 : it->second);\n        }\n    }\n\n    vector<int> ord(K);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b){\n        if (cells[a].w != cells[b].w) return cells[a].w > cells[b].w;\n        if (cells[a].gx != cells[b].gx) return cells[a].gx < cells[b].gx;\n        return cells[a].gy < cells[b].gy;\n    });\n\n    CandidateResult best;\n    best.score = LLONG_MIN;\n\n    int max_seeds = min(30, K);\n    for (int si = 0; si < max_seeds; si++) {\n        int seed = ord[si];\n        if (cells[seed].w <= 0) break;\n\n        vector<char> in(K, 0), frontier(K, 0);\n        long long score = 0;\n        long long perim_edges = 0;\n\n        auto selected_neighbors = [&](int v) {\n            int c = 0;\n            for (int d = 0; d < 4; d++) {\n                int u = nei[v][d];\n                if (u != -1 && in[u]) c++;\n            }\n            return c;\n        };\n\n        struct Node {\n            double pri;\n            int v;\n            int ver;\n            bool operator<(const Node& o) const {\n                return pri < o.pri;\n            }\n        };\n\n        vector<int> ver(K, 0);\n        priority_queue<Node> pq;\n\n        auto push_frontier = [&](int v) {\n            if (v < 0 || in[v]) return;\n            frontier[v] = 1;\n            int sn = selected_neighbors(v);\n            int delta_edges = 4 - 2 * sn;\n            // Tuned heuristic: favor weight, dislike perimeter increase.\n            // Slightly encourage attachment with more selected neighbors.\n            double pri = cells[v].w * 10.0 - delta_edges * 2.5 + sn * 1.0;\n            pq.push({pri, v, ++ver[v]});\n        };\n\n        auto add_cell = [&](int v) {\n            in[v] = 1;\n            score += cells[v].w;\n            int sn = selected_neighbors(v); // includes already-selected neighbors only, before this addition\n            int delta_edges = 4 - 2 * sn;\n            perim_edges += delta_edges;\n            for (int d = 0; d < 4; d++) {\n                int u = nei[v][d];\n                if (u != -1 && !in[u]) push_frontier(u);\n            }\n        };\n\n        add_cell(seed);\n\n        long long perimeter_limit_edges = 400000LL / D;\n\n        for (int d = 0; d < 4; d++) {\n            int u = nei[seed][d];\n            if (u != -1 && !in[u]) push_frontier(u);\n        }\n\n        while (!pq.empty()) {\n            auto cur = pq.top(); pq.pop();\n            int v = cur.v;\n            if (in[v]) continue;\n            if (cur.ver != ver[v]) continue;\n\n            int sn = selected_neighbors(v);\n            if (sn == 0) continue; // connectivity\n\n            int delta_edges = 4 - 2 * sn;\n            long long np = perim_edges + delta_edges;\n            if (np > perimeter_limit_edges) continue;\n\n            // Acceptance rule.\n            // Main criterion: positive enough benefit.\n            double gain = cells[v].w * 10.0 - delta_edges * 2.5 + sn * 1.0;\n\n            // Also allow slight negative if cell has high attachment and region already strong.\n            if (gain < 0) continue;\n\n            add_cell(v);\n        }\n\n        vector<pair<int,int>> sel;\n        sel.reserve(K);\n        for (int i = 0; i < K; i++) if (in[i]) sel.push_back({cells[i].gx, cells[i].gy});\n        if (sel.empty()) continue;\n\n        auto br = build_polygon_from_cells(sel, D);\n        if (!br.single_cycle) continue;\n        if ((long long)br.polygon.size() > 1000) continue;\n        if (perim_edges * 1LL * D > 400000LL) continue;\n\n        if (score > best.score) {\n            best.D = D;\n            best.cells = move(sel);\n            best.score = score;\n            best.perim_edges = perim_edges;\n            best.polygon = move(br.polygon);\n            best.valid = true;\n        }\n    }\n\n    return best;\n}\n\nvector<pair<int,int>> fallback_polygon(const vector<Point>& mac) {\n    // Tiny 1x1 rectangle around first mackerel if possible, clamped.\n    int x = mac[0].x;\n    int y = mac[0].y;\n    int x0 = max(0, x);\n    int y0 = max(0, y);\n    int x1 = min(100000, x0 + 1);\n    int y1 = min(100000, y0 + 1);\n    if (x1 == x0) x0 = max(0, x1 - 1);\n    if (y1 == y0) y0 = max(0, y1 - 1);\n    if (x0 == x1) x1 = min(100000, x0 + 1);\n    if (y0 == y1) y1 = min(100000, y0 + 1);\n\n    vector<pair<int,int>> poly = {\n        {x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}\n    };\n    set<pair<int,int>> st(poly.begin(), poly.end());\n    if (st.size() < 4) {\n        poly = {{0,0},{1,0},{1,1},{0,1}};\n    }\n    return poly;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> mac(N), sar(N);\n    for (int i = 0; i < N; i++) cin >> mac[i].x >> mac[i].y;\n    for (int i = 0; i < N; i++) cin >> sar[i].x >> sar[i].y;\n\n    vector<int> Ds = {1600, 2000, 2500, 3200, 1200};\n\n    CandidateResult best;\n    best.score = LLONG_MIN;\n\n    for (int D : Ds) {\n        auto cand = solve_for_grid(mac, sar, D);\n        if (cand.valid && cand.score > best.score) {\n            best = move(cand);\n        }\n    }\n\n    vector<pair<int,int>> ans;\n    if (best.valid) ans = best.polygon;\n    else ans = fallback_polygon(mac);\n\n    // Final legality cleanup: ensure within range and distinct.\n    for (auto& p : ans) {\n        p.first = max(0, min(100000, p.first));\n        p.second = max(0, min(100000, p.second));\n    }\n\n    // If duplicates accidentally introduced by clamp, fallback.\n    {\n        set<pair<int,int>> st(ans.begin(), ans.end());\n        if (ans.size() < 4 || st.size() != ans.size()) {\n            ans = {{0,0},{1,0},{1,1},{0,1}};\n        }\n    }\n\n    cout << ans.size() << '\\n';\n    for (auto [x, y] : ans) {\n        cout << x << ' ' << y << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Rect {\n    int w, h;\n};\n\nstruct Candidate {\n    vector<Op> ops;\n    long long estW = 0, estH = 0, estScore = (1LL << 60);\n    string tag;\n};\n\nstatic long long INF64 = (1LL << 62);\n\nstruct Solver {\n    int N, T, sigma;\n    vector<Rect> a;\n    vector<Candidate> pool;\n    mt19937 rng;\n\n    Solver() : rng(712367821) {}\n\n    // Build vertical columns from contiguous groups [l..r)\n    // first rect of each column is anchored next to previous column's first rect\n    // subsequent rects in same column are anchored to the column's first rect\n    Candidate build_columns(const vector<pair<int,int>>& groups, int mode, const string& tag) {\n        // mode:\n        // 0: width=min, height=max\n        // 1: no rotation\n        // 2: width=max, height=min\n        Candidate c;\n        c.tag = tag;\n\n        vector<int> firsts;\n        firsts.reserve(groups.size());\n\n        long long totalW = 0;\n        long long totalH = 0;\n\n        for (int gi = 0; gi < (int)groups.size(); gi++) {\n            auto [l, r] = groups[gi];\n            long long colW = 0, colH = 0;\n            int first = l;\n            firsts.push_back(first);\n\n            for (int i = l; i < r; i++) {\n                int w = a[i].w, h = a[i].h;\n                int rot = 0;\n                int ww = w, hh = h;\n                if (mode == 0) {\n                    // make width smaller\n                    if (w > h) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                } else if (mode == 1) {\n                    rot = 0;\n                    ww = w; hh = h;\n                } else {\n                    // make width larger\n                    if (w < h) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                }\n\n                int b;\n                if (i == l) {\n                    b = (gi == 0 ? -1 : firsts[gi - 1]);\n                } else {\n                    b = first;\n                }\n                c.ops.push_back({i, rot, 'U', b});\n                colW = max<long long>(colW, ww);\n                colH += hh;\n            }\n            totalW += colW;\n            totalH = max(totalH, colH);\n        }\n\n        c.estW = totalW;\n        c.estH = totalH;\n        c.estScore = totalW + totalH;\n        return c;\n    }\n\n    // Build horizontal rows from contiguous groups [l..r)\n    Candidate build_rows(const vector<pair<int,int>>& groups, int mode, const string& tag) {\n        // mode:\n        // 0: height=min\n        // 1: no rotation\n        // 2: height=max\n        Candidate c;\n        c.tag = tag;\n\n        vector<int> firsts;\n        firsts.reserve(groups.size());\n\n        long long totalW = 0;\n        long long totalH = 0;\n\n        for (int gi = 0; gi < (int)groups.size(); gi++) {\n            auto [l, r] = groups[gi];\n            long long rowW = 0, rowH = 0;\n            int first = l;\n            firsts.push_back(first);\n\n            for (int i = l; i < r; i++) {\n                int w = a[i].w, h = a[i].h;\n                int rot = 0;\n                int ww = w, hh = h;\n                if (mode == 0) {\n                    // make height smaller\n                    if (h > w) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                } else if (mode == 1) {\n                    rot = 0;\n                    ww = w; hh = h;\n                } else {\n                    // make height larger\n                    if (h < w) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                }\n\n                int b;\n                if (i == l) {\n                    b = (gi == 0 ? -1 : firsts[gi - 1]);\n                } else {\n                    b = first;\n                }\n                c.ops.push_back({i, rot, 'L', b});\n                rowW += ww;\n                rowH = max<long long>(rowH, hh);\n            }\n            totalW = max(totalW, rowW);\n            totalH += rowH;\n        }\n\n        c.estW = totalW;\n        c.estH = totalH;\n        c.estScore = totalW + totalH;\n        return c;\n    }\n\n    vector<pair<int,int>> split_equal(int k) {\n        vector<pair<int,int>> groups;\n        for (int g = 0; g < k; g++) {\n            int l = (long long)N * g / k;\n            int r = (long long)N * (g + 1) / k;\n            if (l < r) groups.push_back({l, r});\n        }\n        return groups;\n    }\n\n    vector<pair<int,int>> split_balanced_columns(int k, int mode) {\n        // balance estimated column heights\n        vector<long long> val(N);\n        for (int i = 0; i < N; i++) {\n            int w = a[i].w, h = a[i].h;\n            if (mode == 0) val[i] = max(w, h);\n            else if (mode == 1) val[i] = h;\n            else val[i] = min(w, h);\n        }\n        long long sum = 0;\n        for (auto x : val) sum += x;\n        long long target = max(1LL, (sum + k - 1) / k);\n\n        vector<pair<int,int>> groups;\n        int l = 0;\n        long long cur = 0;\n        for (int i = 0; i < N; i++) {\n            if ((int)groups.size() < k - 1 && i > l && cur + val[i] > target) {\n                groups.push_back({l, i});\n                l = i;\n                cur = 0;\n            }\n            cur += val[i];\n        }\n        if (l < N) groups.push_back({l, N});\n        return groups;\n    }\n\n    vector<pair<int,int>> split_balanced_rows(int k, int mode) {\n        // balance estimated row widths\n        vector<long long> val(N);\n        for (int i = 0; i < N; i++) {\n            int w = a[i].w, h = a[i].h;\n            if (mode == 0) val[i] = max(w, h);\n            else if (mode == 1) val[i] = w;\n            else val[i] = min(w, h);\n        }\n        long long sum = 0;\n        for (auto x : val) sum += x;\n        long long target = max(1LL, (sum + k - 1) / k);\n\n        vector<pair<int,int>> groups;\n        int l = 0;\n        long long cur = 0;\n        for (int i = 0; i < N; i++) {\n            if ((int)groups.size() < k - 1 && i > l && cur + val[i] > target) {\n                groups.push_back({l, i});\n                l = i;\n                cur = 0;\n            }\n            cur += val[i];\n        }\n        if (l < N) groups.push_back({l, N});\n        return groups;\n    }\n\n    void generate_pool() {\n        pool.clear();\n\n        int K = min(N, 12);\n\n        for (int mode = 0; mode < 3; mode++) {\n            {\n                auto g = split_equal(1);\n                pool.push_back(build_columns(g, mode, \"col_eq_1_m\" + to_string(mode)));\n                pool.push_back(build_rows(g, mode, \"row_eq_1_m\" + to_string(mode)));\n            }\n\n            for (int k = 2; k <= K; k++) {\n                {\n                    auto g = split_equal(k);\n                    pool.push_back(build_columns(g, mode, \"col_eq_\" + to_string(k) + \"_m\" + to_string(mode)));\n                    pool.push_back(build_rows(g, mode, \"row_eq_\" + to_string(k) + \"_m\" + to_string(mode)));\n                }\n                {\n                    auto g = split_balanced_columns(k, mode);\n                    pool.push_back(build_columns(g, mode, \"col_bal_\" + to_string(k) + \"_m\" + to_string(mode)));\n                }\n                {\n                    auto g = split_balanced_rows(k, mode);\n                    pool.push_back(build_rows(g, mode, \"row_bal_\" + to_string(k) + \"_m\" + to_string(mode)));\n                }\n            }\n        }\n\n        // Deduplicate by operation sequence hash\n        unordered_set<string> seen;\n        vector<Candidate> uniq;\n        for (auto &c : pool) {\n            string key;\n            key.reserve(c.ops.size() * 10);\n            for (auto &op : c.ops) {\n                key += to_string(op.p);\n                key += ',';\n                key += char('0' + op.r);\n                key += ',';\n                key += op.d;\n                key += ',';\n                key += to_string(op.b);\n                key += ';';\n            }\n            if (seen.insert(key).second) uniq.push_back(c);\n        }\n        pool.swap(uniq);\n\n        sort(pool.begin(), pool.end(), [&](const Candidate& x, const Candidate& y) {\n            if (x.estScore != y.estScore) return x.estScore < y.estScore;\n            return x.tag < y.tag;\n        });\n    }\n\n    void output_candidate(const Candidate& c) {\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n    }\n\n    void solve() {\n        cin >> N >> T >> sigma;\n        a.resize(N);\n        for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n        generate_pool();\n\n        vector<int> order(pool.size());\n        iota(order.begin(), order.end(), 0);\n\n        // We will send best-estimated candidates first.\n        // Then recycle top few if T is larger.\n        int topReuse = min<int>(10, pool.size());\n\n        long long bestMeasured = INF64;\n        int bestIdx = 0;\n\n        for (int t = 0; t < T; t++) {\n            int idx;\n            if (t < (int)pool.size()) {\n                idx = t;\n            } else {\n                // Reuse one of top candidates, slightly preferring current measured best\n                if (t % 3 == 0) idx = bestIdx;\n                else idx = (t - (int)pool.size()) % topReuse;\n            }\n\n            // Optional comment line for local visualizer\n            // judge ignores lines beginning with '#'\n            cout << \"# \" << pool[idx].tag << \" est=\" << pool[idx].estW << \"+\" << pool[idx].estH\n                 << \"=\" << pool[idx].estScore << '\\n';\n\n            output_candidate(pool[idx]);\n\n            long long Wm, Hm;\n            cin >> Wm >> Hm;\n            long long sm = Wm + Hm;\n            if (sm < bestMeasured) {\n                bestMeasured = sm;\n                bestIdx = idx;\n            }\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}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Candidate {\n    int depth;   // target depth\n    int beauty;\n    int parent;\n    int v;\n    bool operator<(const Candidate& other) const {\n        if (depth != other.depth) return depth < other.depth;      // max depth first\n        if (beauty != other.beauty) return beauty < other.beauty;  // then large beauty\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, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<pair<int,int>> edges(M);\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n\n    vector<pair<int,int>> coord(N);\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        coord[i] = {x, y};\n    }\n\n    // -------- Initial construction --------\n    // Idea:\n    // - small A vertices are better as roots / shallow scaffold\n    // - use a global candidate PQ that prefers deeper assignment and larger A\n    vector<int> parent(N, -2); // -2 = unassigned, -1 = root\n    vector<int> depth(N, -1);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (A[a] != A[b]) return A[a] < A[b];\n        return a < b;\n    });\n\n    priority_queue<Candidate> pq;\n\n    auto add_frontier = [&](int u) {\n        if (depth[u] >= H) return;\n        for (int v : g[u]) {\n            if (parent[v] == -2) {\n                pq.push(Candidate{depth[u] + 1, A[v], u, v});\n            }\n        }\n    };\n\n    // Start from several low-beauty roots gradually.\n    int ptr = 0;\n    while (true) {\n        while (ptr < N && parent[ord[ptr]] != -2) ptr++;\n        if (ptr == N) break;\n\n        int r = ord[ptr];\n        parent[r] = -1;\n        depth[r] = 0;\n        add_frontier(r);\n\n        // Expand as much as possible with current frontier.\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n            int v = cur.v, p = cur.parent;\n            if (parent[v] != -2) continue;\n            if (parent[p] == -2) continue;\n            if (depth[p] + 1 != cur.depth) continue;\n            if (cur.depth > H) continue;\n\n            parent[v] = p;\n            depth[v] = cur.depth;\n            add_frontier(v);\n\n            // If everything assigned, done.\n            // (No need to check here, outer loop handles it.)\n        }\n    }\n\n    // Safety fallback\n    for (int i = 0; i < N; i++) {\n        if (parent[i] == -2) {\n            parent[i] = -1;\n            depth[i] = 0;\n        }\n    }\n\n    // -------- Data structures for local improvement --------\n    vector<vector<int>> children(N);\n    vector<int> tin(N), tout(N), subSum(N), subHeight(N);\n    int timer = 0;\n\n    function<void()> rebuild = [&]() {\n        for (int i = 0; i < N; i++) children[i].clear();\n        for (int v = 0; v < N; v++) {\n            if (parent[v] >= 0) children[parent[v]].push_back(v);\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            }\n        }\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (int v : children[u]) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n\n        timer = 0;\n        function<void(int)> dfs = [&](int u) {\n            tin[u] = timer++;\n            subSum[u] = A[u];\n            subHeight[u] = 0;\n            for (int v : children[u]) {\n                dfs(v);\n                subSum[u] += subSum[v];\n                subHeight[u] = max(subHeight[u], subHeight[v] + 1);\n            }\n            tout[u] = timer;\n        };\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) dfs(i);\n        }\n    };\n\n    auto is_ancestor = [&](int a, int b) -> bool {\n        return tin[a] <= tin[b] && tout[b] <= tout[a];\n    };\n\n    rebuild();\n\n    auto score_est = [&]() -> long long {\n        long long s = 1;\n        for (int i = 0; i < N; i++) s += 1LL * (depth[i] + 1) * A[i];\n        return s;\n    };\n\n    // -------- Local improvement: subtree reparenting --------\n    // Move subtree v under neighboring u if gain positive and valid.\n    // Since H is small and N=1000, full rebuild after successful move is acceptable.\n    long long bestScore = score_est();\n\n    bool improved = true;\n    int rounds = 0;\n    while (improved && rounds < 30) {\n        improved = false;\n        rounds++;\n\n        // Try promising vertices first: larger subtree weight and larger A.\n        vector<int> vs(N);\n        iota(vs.begin(), vs.end(), 0);\n        sort(vs.begin(), vs.end(), [&](int a, int b) {\n            long long wa = 1LL * subSum[a] * 100 + A[a];\n            long long wb = 1LL * subSum[b] * 100 + A[b];\n            if (wa != wb) return wa > wb;\n            return a < b;\n        });\n\n        for (int v : vs) {\n            int bestParent = -3;\n            int bestNewDepth = depth[v];\n\n            for (int u : g[v]) {\n                if (u == parent[v]) continue;\n                // Cannot attach under own descendant.\n                if (is_ancestor(v, u)) continue;\n\n                int nd = depth[u] + 1;\n                if (nd <= depth[v]) continue; // only improving moves\n                if (nd + subHeight[v] > H) continue; // subtree must fit\n\n                if (nd > bestNewDepth) {\n                    bestNewDepth = nd;\n                    bestParent = u;\n                }\n            }\n\n            if (bestParent != -3) {\n                int oldParent = parent[v];\n                parent[v] = bestParent;\n                rebuild();\n                long long sc = score_est();\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    improved = true;\n                } else {\n                    // revert\n                    parent[v] = oldParent;\n                    rebuild();\n                }\n            }\n        }\n    }\n\n    // -------- Final validity repair (just in case) --------\n    // Ensure depth <= H and no invalid parent remains. If any issue, make root.\n    rebuild();\n    for (int i = 0; i < N; i++) {\n        if (depth[i] < 0 || depth[i] > H) {\n            parent[i] = -1;\n        }\n    }\n    rebuild();\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nstruct Candidate {\n    char d;\n    int p;\n    int k;\n    int removed;\n    bool valid = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<string> b(n);\n    for (int i = 0; i < n; i++) cin >> b[i];\n\n    vector<Op> ans;\n\n    auto count_oni = [&]() -> int {\n        int c = 0;\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) c += (b[i][j] == 'x');\n        return c;\n    };\n\n    auto do_move = [&](char d, int p) {\n        ans.push_back({d, p});\n        if (d == 'L') {\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            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            for (int i = 0; i + 1 < n; i++) b[i][p] = b[i + 1][p];\n            b[n - 1][p] = '.';\n        } else if (d == 'D') {\n            for (int i = n - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n            b[0][p] = '.';\n        }\n    };\n\n    auto safe_no_fuku_above = [&](int i, int j) -> bool {\n        for (int r = 0; r < i; r++) if (b[r][j] == 'o') return false;\n        return true;\n    };\n    auto safe_no_fuku_below = [&](int i, int j) -> bool {\n        for (int r = i + 1; r < n; r++) if (b[r][j] == 'o') return false;\n        return true;\n    };\n    auto safe_no_fuku_left = [&](int i, int j) -> bool {\n        for (int c = 0; c < j; c++) if (b[i][c] == 'o') return false;\n        return true;\n    };\n    auto safe_no_fuku_right = [&](int i, int j) -> bool {\n        for (int c = j + 1; c < n; c++) if (b[i][c] == 'o') return false;\n        return true;\n    };\n\n    auto better = [&](const Candidate& a, const Candidate& c) -> bool {\n        if (!c.valid) return true;\n        // maximize removed / k\n        long long lhs = 1LL * a.removed * c.k;\n        long long rhs = 1LL * c.removed * a.k;\n        if (lhs != rhs) return lhs > rhs;\n        if (a.removed != c.removed) return a.removed > c.removed;\n        if (a.k != c.k) return a.k < c.k;\n        if (a.d != c.d) return a.d < c.d;\n        return a.p < c.p;\n    };\n\n    auto find_best_candidate = [&]() -> Candidate {\n        Candidate best;\n\n        // Rows: Left / Right\n        for (int i = 0; i < n; i++) {\n            // Left\n            int safe = 0;\n            while (safe < n && b[i][safe] != 'o') safe++;\n            int removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[i][k - 1] == 'x') removed++;\n                Candidate cand{'L', i, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n\n            // Right\n            safe = 0;\n            while (safe < n && b[i][n - 1 - safe] != 'o') safe++;\n            removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[i][n - k] == 'x') removed++;\n                Candidate cand{'R', i, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n        }\n\n        // Columns: Up / Down\n        for (int j = 0; j < n; j++) {\n            // Up\n            int safe = 0;\n            while (safe < n && b[safe][j] != 'o') safe++;\n            int removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[k - 1][j] == 'x') removed++;\n                Candidate cand{'U', j, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n\n            // Down\n            safe = 0;\n            while (safe < n && b[n - 1 - safe][j] != 'o') safe++;\n            removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[n - k][j] == 'x') removed++;\n                Candidate cand{'D', j, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n        }\n\n        return best;\n    };\n\n    // Greedy sweeps:\n    // Use only clearly beneficial candidates to avoid wasting move budget.\n    while (true) {\n        Candidate best = find_best_candidate();\n        if (!best.valid) break;\n\n        // Conservative acceptance rule:\n        // - always accept if removes at least 2 Oni\n        // - or removes 1 Oni with cost 1\n        if (!(best.removed >= 2 || (best.removed == 1 && best.k == 1))) break;\n\n        if ((int)ans.size() + best.k > 4 * n * n) break;\n        for (int t = 0; t < best.k; t++) do_move(best.d, best.p);\n    }\n\n    // Fallback: remove remaining Oni one by one with restore.\n    while (count_oni() > 0) {\n        bool done = false;\n        for (int i = 0; i < n && !done; i++) {\n            for (int j = 0; j < n && !done; j++) {\n                if (b[i][j] != 'x') continue;\n\n                if (safe_no_fuku_above(i, j)) {\n                    int need = i + 1;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('U', j);\n                    for (int t = 0; t < need; t++) do_move('D', j);\n                    done = true;\n                } else if (safe_no_fuku_below(i, j)) {\n                    int need = n - i;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('D', j);\n                    for (int t = 0; t < need; t++) do_move('U', j);\n                    done = true;\n                } else if (safe_no_fuku_left(i, j)) {\n                    int need = j + 1;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('L', i);\n                    for (int t = 0; t < need; t++) do_move('R', i);\n                    done = true;\n                } else if (safe_no_fuku_right(i, j)) {\n                    int need = n - j;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('R', i);\n                    for (int t = 0; t < need; t++) do_move('L', i);\n                    done = true;\n                } else {\n                    // Guaranteed not to happen by problem statement.\n                }\n            }\n        }\n        if (!done) break;\n    }\n\n    // Output operations\n    // The algorithm is designed to stay within the limit.\n    if ((int)ans.size() > 4 * n * n) {\n        ans.resize(4 * n * n);\n    }\n    for (auto &op : ans) {\n        cout << op.d << ' ' << op.p << '\\n';\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC044\n\nModel:\n- Each node i has two outgoing edges:\n    odd visit count  -> a[i]\n    even visit count -> b[i]\n- Starting from node 0, after L=500000 visits total, counts t[i] are induced.\n\nIdea:\n- Build a simple \"hub + self-loop\" structure.\n- Select several high-target nodes as hubs.\n- For a hub h:\n    a[h] = h (odd visit -> stay once more)\n    b[h] = next_hub_or_sink (even visit -> leave)\n  Thus each time we enter h, we spend exactly 2 consecutive weeks at h, except maybe final truncation.\n- For a leaf i assigned to hub h:\n    a[i] = h, b[i] = h\n  So leaf contributes exactly 1 visit whenever used.\n- The sink node s has a[s]=b[s]=s and absorbs all remaining weeks.\n\nConstruction:\n1. Reserve one sink node.\n2. Choose K hubs among largest T except sink.\n3. Distribute all non-hub, non-sink nodes as leaves to hubs.\n4. Create a cyclic order of \"items\":\n      hub h repeated floor(T[h]/2) times,\n      leaf i repeated T[i] times.\n   Traversing an item means:\n      if item is hub h: enter h from previous node; h stays one extra step via a[h]=h,\n                        then b[h] sends to next item's node.\n      if item is leaf i: visit i once, then go to its hub, whose b[h] sends to next item.\n   This makes each leaf item cost 2 weeks (leaf + hub) and each hub item cost 2 weeks (hub + hub).\n   Exact global realization is messy because leaves always pass through a hub.\n   So instead we optimize a simpler deterministic cycle over hubs and leaves by simulation.\n5. Since exact design is difficult, perform local improvement by trying reassignment / edge tweaks and\n   evaluating by fast simulation over L steps.\n\nPractical approach implemented:\n- Start from near-trivial solution:\n    sort nodes by T descending\n    pick sink = smallest T\n    pick K hubs among largest T excluding sink\n    each non-hub goes to nearest-loaded hub\n    hubs chained cyclically, sink self-loop\n    hub odd->hub self, even->next\n    leaves both->assigned hub\n- Then hill-climb:\n    * move a leaf to another hub\n    * swap a hub with a leaf candidate\n    * change cyclic hub order by swapping positions\n    * optionally redirect one hub's even-edge to sink or another hub\n- Score evaluation by full simulation of 500000 steps.\n  Since N=100 and time limit 2 sec, we keep iterations moderate.\n\nThis is not guaranteed optimal, but usually yields a decent heuristic score quickly.\n*/\n\nstatic constexpr int NFIX = 100;\nstatic constexpr int LFIX = 500000;\n\nstruct State {\n    array<int, NFIX> a, b;\n    long long err = (1LL<<60);\n};\n\nint N, L;\narray<int, NFIX> Tgt;\n\ninline long long eval_err(const array<int, NFIX>& a, const array<int, NFIX>& b) {\n    static array<int, NFIX> cnt;\n    static array<int, NFIX> used;\n    cnt.fill(0);\n    int cur = 0;\n    for (int step = 0; step < L; step++) {\n        cnt[cur]++;\n        int t = cnt[cur];\n        cur = (t & 1) ? a[cur] : b[cur];\n    }\n    long long err = 0;\n    for (int i = 0; i < N; i++) err += llabs((long long)cnt[i] - Tgt[i]);\n    return err;\n}\n\nstruct Builder {\n    int sink;\n    vector<int> hubs;          // designated hubs\n    vector<int> leaves;\n    array<int, NFIX> hub_of;   // for leaves\n    vector<int> order;         // cyclic order of hubs\n\n    State materialize_basic(bool connect_to_sink_tail = false) const {\n        State st;\n        for (int i = 0; i < N; i++) {\n            st.a[i] = st.b[i] = sink;\n        }\n\n        st.a[sink] = sink;\n        st.b[sink] = sink;\n\n        int K = (int)order.size();\n        unordered_map<int,int> pos;\n        pos.reserve(K * 2 + 1);\n        for (int i = 0; i < K; i++) pos[order[i]] = i;\n\n        // hubs\n        for (int idx = 0; idx < K; idx++) {\n            int h = order[idx];\n            int nxt;\n            if (connect_to_sink_tail && idx == K - 1) nxt = sink;\n            else nxt = order[(idx + 1) % K];\n            st.a[h] = h;\n            st.b[h] = nxt;\n        }\n\n        // leaves\n        for (int x : leaves) {\n            int h = hub_of[x];\n            st.a[x] = h;\n            st.b[x] = h;\n        }\n\n        st.err = eval_err(st.a, st.b);\n        return st;\n    }\n};\n\nstatic uint64_t rng_state =\n    chrono::high_resolution_clock::now().time_since_epoch().count();\n\ninline uint64_t rng64() {\n    rng_state ^= rng_state << 7;\n    rng_state ^= rng_state >> 9;\n    return rng_state;\n}\ninline int rnd(int l, int r) {\n    return l + (int)(rng64() % (uint64_t)(r - l + 1));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; i++) cin >> Tgt[i];\n\n    vector<int> ids(N);\n    iota(ids.begin(), ids.end(), 0);\n    sort(ids.begin(), ids.end(), [&](int x, int y) {\n        if (Tgt[x] != Tgt[y]) return Tgt[x] > Tgt[y];\n        return x < y;\n    });\n\n    int sink = min_element(ids.begin(), ids.end(), [&](int x, int y) {\n        if (Tgt[x] != Tgt[y]) return Tgt[x] < Tgt[y];\n        return x < y;\n    }) - ids.begin();\n    sink = ids[sink];\n\n    State best;\n    best.a.fill(0);\n    best.b.fill(0);\n    for (int i = 0; i < N; i++) best.a[i] = best.b[i] = 0;\n    best.a[0] = 0; best.b[0] = 0;\n    best.err = eval_err(best.a, best.b);\n\n    // Try several K values\n    vector<int> candK = {4, 6, 8, 10, 12, 16, 20, 24, 32};\n    for (int K : candK) {\n        if (K >= N) continue;\n\n        Builder bu;\n        bu.sink = sink;\n        bu.hub_of.fill(sink);\n\n        vector<int> cand;\n        for (int x : ids) if (x != sink) cand.push_back(x);\n        K = min(K, (int)cand.size());\n\n        bu.hubs.assign(cand.begin(), cand.begin() + K);\n        bu.order = bu.hubs;\n\n        vector<char> is_hub(N, false);\n        is_hub[sink] = true;\n        for (int h : bu.hubs) is_hub[h] = true;\n\n        bu.leaves.clear();\n        for (int i = 0; i < N; i++) if (!is_hub[i]) bu.leaves.push_back(i);\n\n        // Assign leaves to hubs preferring larger T hubs\n        vector<long long> load(N, 0);\n        for (int h : bu.hubs) load[h] = Tgt[h];\n        for (int x : bu.leaves) {\n            int besth = bu.hubs[0];\n            long long bestv = (1LL<<60);\n            for (int h : bu.hubs) {\n                long long v = load[h];\n                if (v < bestv) {\n                    bestv = v;\n                    besth = h;\n                }\n            }\n            bu.hub_of[x] = besth;\n            load[besth] += max(1, Tgt[x] / 4);\n        }\n\n        // Initial orders: by descending target and a few shuffled variants\n        vector<vector<int>> init_orders;\n        init_orders.push_back(bu.order);\n        {\n            auto v = bu.order;\n            reverse(v.begin(), v.end());\n            init_orders.push_back(v);\n        }\n        for (int rep = 0; rep < 3; rep++) {\n            auto v = bu.order;\n            shuffle(v.begin(), v.end(), std::mt19937((unsigned)rng64()));\n            init_orders.push_back(v);\n        }\n\n        for (auto ord : init_orders) {\n            bu.order = ord;\n            State cur = bu.materialize_basic(false);\n            if (cur.err < best.err) best = cur;\n\n            auto st_time = chrono::high_resolution_clock::now();\n            while (chrono::duration<double>(chrono::high_resolution_clock::now() - st_time).count() < 0.10) {\n                int typ = rnd(0, 2);\n\n                if (typ == 0 && !bu.leaves.empty()) {\n                    // reassign one leaf\n                    int idx = rnd(0, (int)bu.leaves.size() - 1);\n                    int x = bu.leaves[idx];\n                    int oldh = bu.hub_of[x];\n                    int newh = bu.hubs[rnd(0, (int)bu.hubs.size() - 1)];\n                    if (newh == oldh) continue;\n                    bu.hub_of[x] = newh;\n                    State nxt = bu.materialize_basic(false);\n                    if (nxt.err <= cur.err) {\n                        cur = nxt;\n                        if (cur.err < best.err) best = cur;\n                    } else {\n                        bu.hub_of[x] = oldh;\n                    }\n                } else if (typ == 1 && (int)bu.order.size() >= 2) {\n                    // swap hubs in cycle\n                    int i = rnd(0, (int)bu.order.size() - 1);\n                    int j = rnd(0, (int)bu.order.size() - 1);\n                    if (i == j) continue;\n                    swap(bu.order[i], bu.order[j]);\n                    State nxt = bu.materialize_basic(false);\n                    if (nxt.err <= cur.err) {\n                        cur = nxt;\n                        if (cur.err < best.err) best = cur;\n                    } else {\n                        swap(bu.order[i], bu.order[j]);\n                    }\n                } else if (typ == 2 && !bu.leaves.empty() && !bu.hubs.empty()) {\n                    // swap one hub with one leaf\n                    int hi = rnd(0, (int)bu.hubs.size() - 1);\n                    int li = rnd(0, (int)bu.leaves.size() - 1);\n                    int h = bu.hubs[hi], x = bu.leaves[li];\n                    if (x == sink) continue;\n\n                    // save\n                    auto old_hubs = bu.hubs;\n                    auto old_leaves = bu.leaves;\n                    auto old_order = bu.order;\n                    auto old_hubof = bu.hub_of;\n\n                    // replace in hubs/order\n                    bu.hubs[hi] = x;\n                    for (int &v : bu.order) if (v == h) { v = x; break; }\n\n                    bu.leaves[li] = h;\n\n                    // fix assignments\n                    bu.hub_of[h] = x;\n                    for (int y : bu.leaves) {\n                        if (bu.hub_of[y] == h) bu.hub_of[y] = x;\n                    }\n\n                    State nxt = bu.materialize_basic(false);\n                    if (nxt.err <= cur.err) {\n                        cur = nxt;\n                        if (cur.err < best.err) best = cur;\n                    } else {\n                        bu.hubs = old_hubs;\n                        bu.leaves = old_leaves;\n                        bu.order = old_order;\n                        bu.hub_of = old_hubof;\n                    }\n                }\n            }\n        }\n    }\n\n    // Fallback: direct 2-cycle-ish chain to strongest nodes if somehow poor\n    {\n        array<int, NFIX> a, b;\n        int mx = max_element(Tgt.begin(), Tgt.begin() + N) - Tgt.begin();\n        for (int i = 0; i < N; i++) {\n            a[i] = mx;\n            b[i] = mx;\n        }\n        a[mx] = mx;\n        b[mx] = mx;\n        long long e = eval_err(a, b);\n        if (e < best.err) {\n            best.a = a;\n            best.b = b;\n            best.err = e;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (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 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\nstatic inline long long part1by1(unsigned x) {\n    long long n = x;\n    n = (n | (n << 16)) & 0x0000FFFF0000FFFFLL;\n    n = (n | (n << 8)) & 0x00FF00FF00FF00FFLL;\n    n = (n | (n << 4)) & 0x0F0F0F0F0F0F0F0FLL;\n    n = (n | (n << 2)) & 0x3333333333333333LL;\n    n = (n | (n << 1)) & 0x5555555555555555LL;\n    return n;\n}\n\nstatic inline long long morton_key(int x, int y) {\n    return (part1by1((unsigned)x) << 1) | part1by1((unsigned)y);\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    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<int> cx(N), cy(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    auto est_dist = [&](int a, int b) -> int {\n        long long dx = (long long)cx[a] - cx[b];\n        long long dy = (long long)cy[a] - cy[b];\n        return (int)floor(sqrt((double)(dx * dx + dy * dy)));\n    };\n\n    // Initial grouping by Morton order.\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        long long ka = morton_key(cx[a], cy[a]);\n        long long kb = morton_key(cx[b], cy[b]);\n        if (ka != kb) return ka < kb;\n        if (cx[a] != cx[b]) return cx[a] < cx[b];\n        return cy[a] < cy[b];\n    });\n\n    vector<vector<int>> groups(M);\n    {\n        int ptr = 0;\n        for (int i = 0; i < M; i++) {\n            groups[i].assign(ord.begin() + ptr, ord.begin() + ptr + G[i]);\n            ptr += G[i];\n        }\n    }\n\n    // Approximate MST cost for a small group using Prim on estimated distances.\n    auto approx_mst_cost = [&](const vector<int>& vs) -> long long {\n        int n = (int)vs.size();\n        if (n <= 1) return 0;\n        const int INF = 1e9;\n        vector<int> minc(n, INF);\n        vector<char> used(n, 0);\n        minc[0] = 0;\n        long long res = 0;\n        for (int it = 0; it < n; it++) {\n            int v = -1;\n            for (int i = 0; i < n; i++) {\n                if (!used[i] && (v == -1 || minc[i] < minc[v])) v = i;\n            }\n            used[v] = 1;\n            res += minc[v];\n            for (int to = 0; to < n; to++) if (!used[to]) {\n                int w = est_dist(vs[v], vs[to]);\n                if (w < minc[to]) minc[to] = w;\n            }\n        }\n        return res;\n    };\n\n    // Small local swap improvement between adjacent groups.\n    for (int pass = 0; pass < 2; pass++) {\n        for (int gi = 0; gi + 1 < M; gi++) {\n            auto &A = groups[gi], &B = groups[gi + 1];\n            if (A.empty() || B.empty()) continue;\n\n            long long base = approx_mst_cost(A) + approx_mst_cost(B);\n            long long best = base;\n            int besta = -1, bestb = -1;\n\n            int sa = (int)A.size(), sb = (int)B.size();\n            vector<int> candA, candB;\n            for (int i = max(0, sa - 5); i < sa; i++) candA.push_back(i);\n            for (int i = 0; i < min(sb, 5); i++) candB.push_back(i);\n\n            for (int ia : candA) for (int ib : candB) {\n                vector<int> nA = A, nB = B;\n                swap(nA[ia], nB[ib]);\n                long long val = approx_mst_cost(nA) + approx_mst_cost(nB);\n                if (val < best) {\n                    best = val;\n                    besta = ia;\n                    bestb = ib;\n                }\n            }\n            if (besta != -1) {\n                swap(A[besta], B[bestb]);\n            }\n        }\n    }\n\n    // Query budget allocation.\n    vector<vector<pair<int,int>>> queried_edges(M);\n    int used_queries = 0;\n\n    auto do_query = [&](const vector<int>& subset) -> vector<pair<int,int>> {\n        cout << \"? \" << subset.size();\n        for (int v : subset) cout << ' ' << v;\n        cout << '\\n';\n        cout.flush();\n        vector<pair<int,int>> ret;\n        for (int i = 0; i < (int)subset.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    // Prioritize larger groups for queries.\n    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n    sort(gids.begin(), gids.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    for (int id : gids) {\n        if (used_queries >= Q) break;\n        auto &g = groups[id];\n        int sz = (int)g.size();\n        if (sz <= 1) continue;\n\n        int block = min(L, sz);\n        if (block < 2) continue;\n\n        // overlapping blocks\n        int step = max(1, block / 2);\n        for (int s = 0; s < sz && used_queries < Q; s += step) {\n            int e = min(sz, s + block);\n            if (e - s < 2) break;\n            if (e - s < 2) continue;\n            vector<int> subset(g.begin() + s, g.begin() + e);\n            auto ret = do_query(subset);\n            for (auto &p : ret) queried_edges[id].push_back(p);\n            used_queries++;\n            if (e == sz) break;\n        }\n    }\n\n    // Build final trees.\n    vector<vector<pair<int,int>>> answer_edges(M);\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        if (sz <= 1) continue;\n\n        unordered_map<int,int> lid;\n        lid.reserve(sz * 2);\n        for (int i = 0; i < sz; i++) lid[g[i]] = i;\n\n        vector<Edge> cand;\n        cand.reserve(sz * 10);\n\n        // queried edges\n        {\n            set<pair<int,int>> seen;\n            for (auto [a, b] : queried_edges[gi]) {\n                if (!lid.count(a) || !lid.count(b)) continue;\n                if (a > b) swap(a, b);\n                if (seen.insert({a, b}).second) {\n                    cand.push_back({a, b, est_dist(a, b)});\n                }\n            }\n        }\n\n        // k nearest neighbors by estimated center distance\n        int k = min(6, sz - 1);\n        for (int i = 0; i < sz; i++) {\n            vector<pair<int,int>> nei;\n            nei.reserve(sz - 1);\n            for (int j = 0; j < sz; j++) if (i != j) {\n                nei.push_back({est_dist(g[i], g[j]), g[j]});\n            }\n            nth_element(nei.begin(), nei.begin() + k, nei.end());\n            for (int t = 0; t < k; t++) {\n                int a = g[i], b = nei[t].second;\n                if (a > b) swap(a, b);\n                cand.push_back({a, b, nei[t].first});\n            }\n        }\n\n        // dedup\n        sort(cand.begin(), cand.end(), [&](const Edge& a, const Edge& b) {\n            if (a.u != b.u) return a.u < b.u;\n            if (a.v != b.v) return a.v < b.v;\n            return a.w < b.w;\n        });\n        vector<Edge> uniq;\n        for (auto &e : cand) {\n            if (e.u == e.v) continue;\n            if (uniq.empty() || uniq.back().u != e.u || uniq.back().v != e.v) uniq.push_back(e);\n        }\n        cand.swap(uniq);\n\n        sort(cand.begin(), cand.end());\n\n        DSU dsu(N);\n        vector<pair<int,int>> tree;\n        tree.reserve(sz - 1);\n\n        for (auto &e : cand) {\n            if (dsu.unite(e.u, e.v)) {\n                tree.push_back({e.u, e.v});\n                if ((int)tree.size() == sz - 1) break;\n            }\n        }\n\n        // Fallback: connect remaining components greedily\n        while ((int)tree.size() < sz - 1) {\n            int bu = -1, bv = -1, bw = INT_MAX;\n            for (int i = 0; i < sz; i++) for (int j = i + 1; j < sz; j++) {\n                int a = g[i], b = g[j];\n                if (dsu.find(a) == dsu.find(b)) continue;\n                int w = est_dist(a, b);\n                if (w < bw) {\n                    bw = w; bu = a; bv = b;\n                }\n            }\n            if (bu == -1) break;\n            dsu.unite(bu, bv);\n            tree.push_back({bu, bv});\n        }\n\n        answer_edges[gi] = move(tree);\n    }\n\n    // Final output\n    cout << \"!\\n\";\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < (int)groups[i].size(); j++) {\n            if (j) cout << ' ';\n            cout << groups[i][j];\n        }\n        cout << '\\n';\n        for (auto [a, b] : answer_edges[i]) {\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\nstatic const int N = 20;\nstatic const int INF = 1e9;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar DCH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nstruct Solver {\n    int M;\n    vector<Pos> pts;\n    vector<vector<int>> block;\n    vector<Action> ans;\n    Pos cur;\n\n    Solver(int M_, vector<Pos> pts_) : M(M_), pts(move(pts_)) {\n        block.assign(N, vector<int>(N, 0));\n        cur = pts[0];\n    }\n\n    // BFS path using only moves avoiding blocks\n    vector<int> bfs_move_dirs(Pos s, Pos g, const vector<vector<int>>& blk) {\n        vector<vector<int>> dist(N, vector<int>(N, -1));\n        vector<vector<pair<Pos,int>>> par(N, vector<pair<Pos,int>>(N, {{-1,-1}, -1}));\n        queue<Pos> q;\n        dist[s.r][s.c] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            auto v = q.front(); q.pop();\n            if (v == g) break;\n            for (int d = 0; d < 4; d++) {\n                int nr = v.r + dr[d], nc = v.c + dc[d];\n                if (!inside(nr, nc) || blk[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[v.r][v.c] + 1;\n                par[nr][nc] = {v, d};\n                q.push({nr, nc});\n            }\n        }\n        if (dist[g.r][g.c] == -1) return {};\n        vector<int> dirs;\n        Pos x = g;\n        while (x != s) {\n            auto [p, d] = par[x.r][x.c];\n            dirs.push_back(d);\n            x = p;\n        }\n        reverse(dirs.begin(), dirs.end());\n        return dirs;\n    }\n\n    pair<Pos,int> slide_result(Pos s, int d, const vector<vector<int>>& blk) {\n        int r = s.r, c = s.c;\n        while (true) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc) || blk[nr][nc]) break;\n            r = nr; c = nc;\n        }\n        return {{r, c}, (r != s.r || c != s.c)};\n    }\n\n    bool can_stop_at(Pos s, Pos g, int &dir_out) {\n        if (s.r == g.r) {\n            if (s.c < g.c) {\n                int d = 3;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            } else if (s.c > g.c) {\n                int d = 2;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            }\n        }\n        if (s.c == g.c) {\n            if (s.r < g.r) {\n                int d = 1;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            } else if (s.r > g.r) {\n                int d = 0;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            }\n        }\n        return false;\n    }\n\n    void apply_move_dir(int d) {\n        int nr = cur.r + dr[d], nc = cur.c + dc[d];\n        if (!inside(nr, nc) || block[nr][nc]) return; // safety\n        ans.push_back({'M', DCH[d]});\n        cur = {nr, nc};\n    }\n\n    void apply_slide_dir(int d) {\n        ans.push_back({'S', DCH[d]});\n        cur = slide_result(cur, d, block).first;\n    }\n\n    void apply_alter_dir(int d) {\n        int nr = cur.r + dr[d], nc = cur.c + dc[d];\n        if (!inside(nr, nc)) return; // safety\n        ans.push_back({'A', DCH[d]});\n        block[nr][nc] ^= 1;\n    }\n\n    int dir_between_adj(Pos a, Pos b) {\n        for (int d = 0; d < 4; d++) {\n            if (a.r + dr[d] == b.r && a.c + dc[d] == b.c) return d;\n        }\n        return -1;\n    }\n\n    struct Plan {\n        int cost = INF;\n        vector<Action> acts;\n        vector<pair<Pos,int>> toggles; // (cell, final toggled once)\n    };\n\n    void relax(Plan &best, const Plan &cand) {\n        if (cand.cost < best.cost) best = cand;\n    }\n\n    Plan pure_move_plan(Pos s, Pos g) {\n        Plan p;\n        auto dirs = bfs_move_dirs(s, g, block);\n        if (dirs.empty() && s != g) return p;\n        p.cost = (int)dirs.size();\n        for (int d : dirs) p.acts.push_back({'M', DCH[d]});\n        return p;\n    }\n\n    Plan direct_slide_plan(Pos s, Pos g) {\n        Plan p;\n        int d;\n        if (can_stop_at(s, g, d)) {\n            p.cost = 1;\n            p.acts.push_back({'S', DCH[d]});\n        }\n        return p;\n    }\n\n    // Move to x then slide to g\n    Plan move_then_slide(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d;\n        if (!can_stop_at(x, g, d)) return p;\n        auto dirs = bfs_move_dirs(s, x, block);\n        if (dirs.empty() && s != x) return p;\n        p.cost = (int)dirs.size() + 1;\n        for (int dd : dirs) p.acts.push_back({'M', DCH[dd]});\n        p.acts.push_back({'S', DCH[d]});\n        return p;\n    }\n\n    // Slide to x then move to g\n    Plan slide_then_move(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d = -1;\n        if (s.r == x.r) {\n            if (s.c < x.c) d = 3;\n            else if (s.c > x.c) d = 2;\n        } else if (s.c == x.c) {\n            if (s.r < x.r) d = 1;\n            else if (s.r > x.r) d = 0;\n        }\n        if (d == -1) return p;\n        auto res = slide_result(s, d, block);\n        if (res.first != x) return p;\n        auto dirs = bfs_move_dirs(x, g, block);\n        if (dirs.empty() && x != g) return p;\n        p.cost = 1 + (int)dirs.size();\n        p.acts.push_back({'S', DCH[d]});\n        for (int dd : dirs) p.acts.push_back({'M', DCH[dd]});\n        return p;\n    }\n\n    Plan slide_then_slide(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d1 = -1, d2 = -1;\n        if (s.r == x.r) {\n            if (s.c < x.c) d1 = 3;\n            else if (s.c > x.c) d1 = 2;\n        } else if (s.c == x.c) {\n            if (s.r < x.r) d1 = 1;\n            else if (s.r > x.r) d1 = 0;\n        }\n        if (d1 == -1) return p;\n        if (slide_result(s, d1, block).first != x) return p;\n        if (!can_stop_at(x, g, d2)) return p;\n        p.cost = 2;\n        p.acts.push_back({'S', DCH[d1]});\n        p.acts.push_back({'S', DCH[d2]});\n        return p;\n    }\n\n    // Create one stopper adjacent beyond g, then slide from aligned position x\n    Plan create_stopper_and_slide(Pos s, Pos g) {\n        Plan best;\n        for (int d = 0; d < 4; d++) {\n            int br = g.r + dr[d], bc = g.c + dc[d]; // blocker cell\n            if (!inside(br, bc)) continue;           // border already acts as stopper, no need here\n            if (block[br][bc]) continue;             // already blocked -> direct existing-block cases handled elsewhere\n\n            int sd = d ^ 1; // need to slide toward g from opposite side\n            // x must be on same line as g, and slide from x in sd must stop at g after placing block at (br,bc)\n            // Enumerate all possible x on that ray.\n            for (int k = 1; ; k++) {\n                int xr = g.r + dr[sd] * k;\n                int xc = g.c + dc[sd] * k;\n                if (!inside(xr, xc)) break;\n                if (block[xr][xc]) break; // can't stand there\n                Pos x{xr, xc};\n\n                // Need path s -> some y adjacent to blocker cell, place block, then path to x, then slide.\n                for (int ad = 0; ad < 4; ad++) {\n                    int yr = br - dr[ad], yc = bc - dc[ad];\n                    if (!inside(yr, yc) || block[yr][yc]) continue;\n                    Pos y{yr, yc};\n                    if (y.r == br && y.c == bc) continue;\n\n                    auto path1 = bfs_move_dirs(s, y, block);\n                    if (path1.empty() && s != y) continue;\n\n                    auto blk2 = block;\n                    blk2[br][bc] = 1;\n                    auto path2 = bfs_move_dirs(y, x, blk2);\n                    if (path2.empty() && y != x) continue;\n\n                    // verify slide with new block\n                    int dslide = -1;\n                    if (x.r == g.r) {\n                        if (x.c < g.c) dslide = 3;\n                        else if (x.c > g.c) dslide = 2;\n                    } else if (x.c == g.c) {\n                        if (x.r < g.r) dslide = 1;\n                        else if (x.r > g.r) dslide = 0;\n                    }\n                    if (dslide == -1) continue;\n\n                    // simulate on blk2\n                    int rr = x.r, cc = x.c;\n                    while (true) {\n                        int nr = rr + dr[dslide], nc = cc + dc[dslide];\n                        if (!inside(nr, nc) || blk2[nr][nc]) break;\n                        rr = nr; cc = nc;\n                    }\n                    if (rr != g.r || cc != g.c) continue;\n\n                    Plan p;\n                    p.cost = (int)path1.size() + 1 + (int)path2.size() + 1;\n                    for (int dd : path1) p.acts.push_back({'M', DCH[dd]});\n                    p.acts.push_back({'A', DCH[ad]});\n                    for (int dd : path2) p.acts.push_back({'M', DCH[dd]});\n                    p.acts.push_back({'S', DCH[dslide]});\n                    p.toggles.push_back({{br, bc}, 1});\n                    relax(best, p);\n                }\n            }\n        }\n        return best;\n    }\n\n    void execute_plan(const Plan &p) {\n        for (auto act : p.acts) {\n            if (act.a == 'M') {\n                int d = string(\"UDLR\").find(act.d);\n                apply_move_dir(d);\n            } else if (act.a == 'S') {\n                int d = string(\"UDLR\").find(act.d);\n                apply_slide_dir(d);\n            } else {\n                int d = string(\"UDLR\").find(act.d);\n                apply_alter_dir(d);\n            }\n        }\n    }\n\n    void solve() {\n        for (int idx = 1; idx < M; idx++) {\n            Pos g = pts[idx];\n            Plan best = pure_move_plan(cur, g);\n\n            relax(best, direct_slide_plan(cur, g));\n\n            for (int r = 0; r < N; r++) for (int c = 0; c < N; c++) {\n                if (block[r][c]) continue;\n                Pos x{r, c};\n                relax(best, move_then_slide(cur, x, g));\n                relax(best, slide_then_move(cur, x, g));\n                relax(best, slide_then_slide(cur, x, g));\n            }\n\n            relax(best, create_stopper_and_slide(cur, g));\n\n            if (best.cost >= INF) {\n                best = pure_move_plan(cur, g);\n            }\n\n            execute_plan(best);\n\n            // safety fallback if not reached due to any inconsistency\n            if (cur != g) {\n                auto dirs = bfs_move_dirs(cur, g, block);\n                for (int d : dirs) apply_move_dir(d);\n            }\n\n            // if target cell somehow blocked (shouldn't happen if reached), unblock from adjacent later if needed.\n            // We guarantee current cell is unblocked because moves/slides can't end on blocked cell.\n        }\n\n        // Hard safety: ensure action count not excessive; if somehow too large, truncate is invalid.\n        // But this heuristic should stay comfortably below 1600.\n        for (auto &x : ans) {\n            cout << x.a << ' ' << x.d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N_in, M;\n    cin >> N_in >> M;\n    vector<Pos> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].r >> pts[i].c;\n\n    Solver solver(M, pts);\n    solver.solve();\n    return 0;\n}"},"2":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int LIM = 10000;\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nstruct Input {\n    int x, y;\n    int r;\n};\n\nstatic inline bool overlap1D(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstatic inline bool overlap2D(const Rect& p, const Rect& q) {\n    return overlap1D(p.a, p.c, q.a, q.c) && overlap1D(p.b, p.d, q.b, q.d);\n}\n\nstatic inline long long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\nstatic inline double score_one(long long s, long long r) {\n    double t = (double)min(s, r) / (double)max(s, r);\n    double u = 1.0 - t;\n    return 1.0 - u * u;\n}\n\nstruct Solver {\n    int n;\n    vector<Input> in;\n    vector<Rect> rects;\n    mt19937 rng;\n\n    Solver(int n_, vector<Input> in_) : n(n_), in(std::move(in_)) {\n        rng.seed((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n        rects.resize(n);\n        for (int i = 0; i < n; i++) {\n            rects[i] = {in[i].x, in[i].y, in[i].x + 1, in[i].y + 1};\n        }\n    }\n\n    double gain_if(const Rect& oldr, const Rect& newr, int i) {\n        long long s0 = area(oldr);\n        long long s1 = area(newr);\n        return score_one(s1, in[i].r) - score_one(s0, in[i].r);\n    }\n\n    // max expandable cells in each direction without overlap\n    int max_left(int i) {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && q.c <= r.a) {\n                bound = max(bound, q.c);\n            }\n        }\n        return r.a - bound;\n    }\n\n    int max_right(int i) {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && r.c <= q.a) {\n                bound = min(bound, q.a);\n            }\n        }\n        return bound - r.c;\n    }\n\n    int max_down(int i) {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && q.d <= r.b) {\n                bound = max(bound, q.d);\n            }\n        }\n        return r.b - bound;\n    }\n\n    int max_up(int i) {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && r.d <= q.b) {\n                bound = min(bound, q.b);\n            }\n        }\n        return bound - r.d;\n    }\n\n    void try_expand_best(int i) {\n        Rect cur = rects[i];\n        long long curA = area(cur);\n        long long target = in[i].r;\n        double bestGain = 1e-18;\n        Rect bestRect = cur;\n\n        auto eval_dir = [&](int dir, int lim) {\n            if (lim <= 0) return;\n            int w = cur.c - cur.a;\n            int h = cur.d - cur.b;\n\n            vector<int> cand;\n            cand.push_back(1);\n            cand.push_back(lim);\n\n            if (dir == 0 || dir == 1) { // left/right, area += h * t\n                if (curA < target) {\n                    int need = (int)((target - curA + h - 1) / h);\n                    for (int dt = -2; dt <= 2; dt++) {\n                        int t = need + dt;\n                        if (1 <= t && t <= lim) cand.push_back(t);\n                    }\n                }\n            } else { // down/up, area += w * t\n                if (curA < target) {\n                    int need = (int)((target - curA + w - 1) / w);\n                    for (int dt = -2; dt <= 2; dt++) {\n                        int t = need + dt;\n                        if (1 <= t && t <= lim) cand.push_back(t);\n                    }\n                }\n            }\n\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n            for (int t : cand) {\n                Rect nxt = cur;\n                if (dir == 0) nxt.a -= t;      // left\n                if (dir == 1) nxt.c += t;      // right\n                if (dir == 2) nxt.b -= t;      // down\n                if (dir == 3) nxt.d += t;      // up\n\n                double g = gain_if(cur, nxt, i);\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestRect = nxt;\n                }\n            }\n        };\n\n        eval_dir(0, max_left(i));\n        eval_dir(1, max_right(i));\n        eval_dir(2, max_down(i));\n        eval_dir(3, max_up(i));\n\n        if (bestGain > 1e-15) rects[i] = bestRect;\n    }\n\n    void micro_adjust_pass(const vector<int>& ord) {\n        for (int i : ord) {\n            Rect cur = rects[i];\n            double bestGain = 1e-18;\n            Rect bestRect = cur;\n\n            auto try_one = [&](Rect nxt) {\n                double g = gain_if(cur, nxt, i);\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestRect = nxt;\n                }\n            };\n\n            if (max_left(i)  >= 1) { Rect t = cur; t.a--; try_one(t); }\n            if (max_right(i) >= 1) { Rect t = cur; t.c++; try_one(t); }\n            if (max_down(i)  >= 1) { Rect t = cur; t.b--; try_one(t); }\n            if (max_up(i)    >= 1) { Rect t = cur; t.d++; try_one(t); }\n\n            if (bestGain > 1e-15) rects[i] = bestRect;\n        }\n    }\n\n    void solve() {\n        auto st = chrono::steady_clock::now();\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n\n        int phase = 0;\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - st).count();\n            if (elapsed > 4.7) break;\n\n            shuffle(ord.begin(), ord.end(), rng);\n            bool updated = false;\n\n            for (int i : ord) {\n                Rect before = rects[i];\n                try_expand_best(i);\n                if (rects[i].a != before.a || rects[i].b != before.b ||\n                    rects[i].c != before.c || rects[i].d != before.d) {\n                    updated = true;\n                }\n            }\n\n            phase++;\n            if (!updated && phase > 10) break;\n        }\n\n        // remaining time for micro adjustment\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - st).count();\n            if (elapsed > 4.95) break;\n            shuffle(ord.begin(), ord.end(), rng);\n            micro_adjust_pass(ord);\n        }\n    }\n\n    void output() {\n        for (int i = 0; i < n; i++) {\n            cout << rects[i].a << ' ' << rects[i].b << ' ' << rects[i].c << ' ' << rects[i].d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Input> in(n);\n    for (int i = 0; i < n; i++) {\n        cin >> in[i].x >> in[i].y >> in[i].r;\n    }\n\n    Solver solver(n, in);\n    solver.solve();\n    solver.output();\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { // [l, r)\n        return l + (int)(next_u32() % (uint32_t)(r - l));\n    }\n    double next_double() {\n        return (double)next_u32() / (double)UINT32_MAX;\n    }\n};\n\nstruct Param {\n    double w_gain;\n    double w_future;\n    double w_reach;\n    double w_mob;\n    double w_dead;\n    double w_corr;\n    double noise;\n    int bfs_depth;\n    int bfs_cap;\n};\n\nint si, sj;\nint tid[N][N];\nint p[N][N];\nint tile_cnt;\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 inb(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nstruct EvalResult {\n    double future_score;\n    int reach_cnt;\n    int frontier_sum;\n};\n\nint vis_stamp[N][N];\nint dista[N][N];\nint cur_stamp = 1;\n\n// bounded BFS heuristic from current cell over unused tiles\nEvalResult bfs_eval(int si, int sj, const vector<unsigned char>& usedTile, int depth_limit, int node_cap) {\n    ++cur_stamp;\n    if (cur_stamp == INT_MAX) {\n        memset(vis_stamp, 0, sizeof(vis_stamp));\n        cur_stamp = 1;\n    }\n\n    static const double decay[64] = {\n        1.0,\n        0.94, 0.88, 0.83, 0.78, 0.73, 0.69, 0.65,\n        0.61, 0.57, 0.54, 0.51, 0.48, 0.45, 0.42, 0.40,\n        0.38, 0.36, 0.34, 0.32, 0.30, 0.28, 0.27, 0.26,\n        0.25, 0.24, 0.23, 0.22, 0.21, 0.20, 0.19, 0.18,\n        0.17, 0.16, 0.15, 0.145, 0.14, 0.135, 0.13, 0.125,\n        0.12, 0.115, 0.11, 0.105, 0.10, 0.095, 0.09, 0.085,\n        0.08, 0.075, 0.07, 0.065, 0.06, 0.055, 0.05, 0.045,\n        0.04, 0.038, 0.036, 0.034, 0.032, 0.03, 0.028, 0.026\n    };\n\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    vis_stamp[si][sj] = cur_stamp;\n    dista[si][sj] = 0;\n\n    double future_score = 0.0;\n    int reach_cnt = 0;\n    int frontier_sum = 0;\n\n    while (!q.empty() && reach_cnt < node_cap) {\n        auto [i, j] = q.front();\n        q.pop();\n        int d = dista[i][j];\n        ++reach_cnt;\n\n        if (d > 0) future_score += p[i][j] * decay[min(d, 63)];\n\n        int local_frontier = 0;\n        if (d < depth_limit) {\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (!inb(ni, nj)) continue;\n                if (usedTile[tid[ni][nj]]) continue;\n                ++local_frontier;\n                if (vis_stamp[ni][nj] == cur_stamp) continue;\n                vis_stamp[ni][nj] = cur_stamp;\n                dista[ni][nj] = d + 1;\n                q.push({ni, nj});\n            }\n        }\n        frontier_sum += local_frontier;\n    }\n\n    return {future_score, reach_cnt, frontier_sum};\n}\n\nstruct Cand {\n    int dir;\n    double score;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    int mx = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tid[i][j];\n            mx = max(mx, tid[i][j]);\n        }\n    }\n    tile_cnt = mx + 1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> p[i][j];\n        }\n    }\n\n    vector<Param> params = {\n        {1.00, 0.090, 1.20, 10.0, 26.0, 8.0, 1.5, 12, 160},\n        {1.10, 0.080, 1.00,  8.0, 22.0, 7.0, 1.8, 11, 140},\n        {0.92, 0.105, 1.35, 12.0, 30.0, 9.0, 1.2, 13, 180},\n        {1.18, 0.070, 0.90,  7.0, 20.0, 6.0, 2.0, 10, 130},\n        {0.98, 0.095, 1.15, 11.0, 28.0, 8.5, 1.4, 14, 170}\n    };\n\n    Timer timer;\n    XorShift rng;\n\n    string best_path;\n    int best_score = p[si][sj];\n\n    vector<unsigned char> usedTile(tile_cnt, 0);\n\n    while (timer.elapsed() < 1.95) {\n        Param par = params[rng.next_int(0, (int)params.size())];\n        par.w_gain += (rng.next_double() - 0.5) * 0.10;\n        par.w_future += (rng.next_double() - 0.5) * 0.02;\n        par.w_reach += (rng.next_double() - 0.5) * 0.20;\n        par.w_mob += (rng.next_double() - 0.5) * 2.0;\n        par.w_dead += (rng.next_double() - 0.5) * 5.0;\n        par.w_corr += (rng.next_double() - 0.5) * 2.0;\n\n        fill(usedTile.begin(), usedTile.end(), 0);\n\n        int ci = si, cj = sj;\n        int score = p[ci][cj];\n        string path;\n        usedTile[tid[ci][cj]] = 1;\n\n        while (true) {\n            vector<Cand> cand;\n\n            int step_id = (int)path.size();\n\n            for (int d = 0; d < 4; ++d) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (!inb(ni, nj)) continue;\n                int nt = tid[ni][nj];\n                if (usedTile[nt]) continue;\n\n                usedTile[nt] = 1;\n\n                int mob = 0;\n                int vmask = 0;\n                for (int k = 0; k < 4; ++k) {\n                    int xi = ni + di[k], xj = nj + dj[k];\n                    if (!inb(xi, xj)) continue;\n                    if (usedTile[tid[xi][xj]]) continue;\n                    ++mob;\n                    vmask |= (1 << k);\n                }\n\n                EvalResult e = bfs_eval(ni, nj, usedTile, par.bfs_depth, par.bfs_cap);\n\n                double dead_pen = 0.0;\n                if (mob == 0) dead_pen = 1.0;\n                else if (mob == 1 && step_id < 800) dead_pen = 0.6;\n                else if (mob == 2 && step_id < 600) {\n                    // mild corridor penalty\n                    // opposite directions => corridor-ish, perpendicular => less dangerous\n                    bool opposite =\n                        (vmask == ((1 << 0) | (1 << 1))) ||\n                        (vmask == ((1 << 2) | (1 << 3)));\n                    if (opposite) dead_pen = 0.25;\n                }\n\n                // if reachable future region is tiny, heavily discourage\n                double small_region_pen = 0.0;\n                if (e.reach_cnt <= 8 && step_id < 1200) small_region_pen += (9 - e.reach_cnt) * 2.5;\n                if (e.reach_cnt <= 3 && step_id < 1200) small_region_pen += 12.0;\n\n                double sc = 0.0;\n                sc += par.w_gain * p[ni][nj];\n                sc += par.w_future * e.future_score;\n                sc += par.w_reach * e.reach_cnt;\n                sc += par.w_mob * mob;\n                sc += 0.15 * e.frontier_sum;\n                sc -= par.w_dead * dead_pen;\n                sc -= par.w_corr * small_region_pen;\n                sc += (rng.next_double() - 0.5) * par.noise;\n\n                usedTile[nt] = 0;\n\n                cand.push_back({d, sc});\n            }\n\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n                return a.score > b.score;\n            });\n\n            int idx = 0;\n            if ((int)cand.size() >= 2 && rng.next_double() < 0.12) idx = 1;\n            if ((int)cand.size() >= 3 && rng.next_double() < 0.03) idx = 2;\n\n            int d = cand[idx].dir;\n            ci += di[d];\n            cj += dj[d];\n            usedTile[tid[ci][cj]] = 1;\n            path.push_back(dc[d]);\n            score += p[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    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HN = 29; // horizontal edges per row\nstatic constexpr int VN = 29; // vertical edges per col\nstatic constexpr double INIT_COST = 5000.0;\nstatic constexpr double MIN_COST = 500.0;\nstatic constexpr double MAX_COST = 9500.0;\n\nstruct EdgeRef {\n    bool horiz; // true: h[i][j] between (i,j) and (i,j+1), false: v[i][j] between (i,j) and (i+1,j)\n    int i, j;\n};\n\nstruct Solver {\n    // current local edge estimates\n    double h_est[N][HN];\n    double v_est[VN][N];\n\n    // traversal stats\n    double h_sum[N][HN], v_sum[VN][N];\n    int h_cnt[N][HN], v_cnt[VN][N];\n\n    // segmented priors\n    double h_prior[N][HN];\n    double v_prior[VN][N];\n\n    int turn = 0;\n\n    Solver() {\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = INIT_COST;\n                h_sum[i][j] = 0.0;\n                h_cnt[i][j] = 0;\n                h_prior[i][j] = INIT_COST;\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = INIT_COST;\n                v_sum[i][j] = 0.0;\n                v_cnt[i][j] = 0;\n                v_prior[i][j] = INIT_COST;\n            }\n        }\n    }\n\n    static double clamp_cost(double x) {\n        if (x < MIN_COST) return MIN_COST;\n        if (x > MAX_COST) return MAX_COST;\n        return x;\n    }\n\n    // Fit 1-or-2 segment piecewise constant model to each row/column using current local estimates.\n    void rebuild_priors() {\n        // Horizontal rows: 29 values each\n        for (int i = 0; i < N; i++) {\n            double a[HN];\n            for (int j = 0; j < HN; j++) a[j] = h_est[i][j];\n\n            // Prefix sums for SSE\n            double ps[HN + 1] = {}, ps2[HN + 1] = {};\n            for (int j = 0; j < HN; j++) {\n                ps[j + 1] = ps[j] + a[j];\n                ps2[j + 1] = ps2[j] + a[j] * a[j];\n            }\n            auto seg_cost = [&](int l, int r) -> pair<double,double> { // [l,r)\n                double s = ps[r] - ps[l];\n                double s2 = ps2[r] - ps2[l];\n                int len = r - l;\n                double mean = s / len;\n                double cost = s2 - 2 * mean * s + len * mean * mean;\n                return {cost, mean};\n            };\n\n            // one segment\n            auto [bestCost1, mean1] = seg_cost(0, HN);\n            double bestCost = bestCost1;\n            int bestSplit = -1;\n            double bestL = mean1, bestR = mean1;\n\n            // two segments\n            for (int sp = 1; sp < HN; sp++) {\n                auto [c1, m1] = seg_cost(0, sp);\n                auto [c2, m2] = seg_cost(sp, HN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestL = m1;\n                    bestR = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int j = 0; j < HN; j++) h_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int j = 0; j < bestSplit; j++) h_prior[i][j] = clamp_cost(bestL);\n                for (int j = bestSplit; j < HN; j++) h_prior[i][j] = clamp_cost(bestR);\n            }\n        }\n\n        // Vertical columns: 29 values each for each col\n        for (int j = 0; j < N; j++) {\n            double a[VN];\n            for (int i = 0; i < VN; i++) a[i] = v_est[i][j];\n\n            double ps[VN + 1] = {}, ps2[VN + 1] = {};\n            for (int i = 0; i < VN; i++) {\n                ps[i + 1] = ps[i] + a[i];\n                ps2[i + 1] = ps2[i] + a[i] * a[i];\n            }\n            auto seg_cost = [&](int l, int r) -> pair<double,double> {\n                double s = ps[r] - ps[l];\n                double s2 = ps2[r] - ps2[l];\n                int len = r - l;\n                double mean = s / len;\n                double cost = s2 - 2 * mean * s + len * mean * mean;\n                return {cost, mean};\n            };\n\n            auto [bestCost1, mean1] = seg_cost(0, VN);\n            double bestCost = bestCost1;\n            int bestSplit = -1;\n            double bestU = mean1, bestD = mean1;\n\n            for (int sp = 1; sp < VN; sp++) {\n                auto [c1, m1] = seg_cost(0, sp);\n                auto [c2, m2] = seg_cost(sp, VN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestU = m1;\n                    bestD = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int i = 0; i < VN; i++) v_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int i = 0; i < bestSplit; i++) v_prior[i][j] = clamp_cost(bestU);\n                for (int i = bestSplit; i < VN; i++) v_prior[i][j] = clamp_cost(bestD);\n            }\n        }\n    }\n\n    double blended_h(int i, int j) const {\n        // Early: stronger prior. Later: stronger local.\n        double alpha = min(0.85, 0.15 + 0.7 * turn / 1000.0); // weight of local\n        return alpha * h_est[i][j] + (1.0 - alpha) * h_prior[i][j];\n    }\n\n    double blended_v(int i, int j) const {\n        double alpha = min(0.85, 0.15 + 0.7 * turn / 1000.0);\n        return alpha * v_est[i][j] + (1.0 - alpha) * v_prior[i][j];\n    }\n\n    int vid(int i, int j) const { return i * N + j; }\n    pair<int,int> pos(int id) const { return {id / N, id % N}; }\n\n    pair<string, vector<EdgeRef>> shortest_path(int si, int sj, int ti, int tj) {\n        const int V = N * N;\n        vector<double> dist(V, 1e100);\n        vector<int> prev(V, -1);\n        vector<char> prevMove(V, '?');\n\n        using P = pair<double,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        int s = vid(si, sj), t = vid(ti, tj);\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == t) break;\n            auto [i, j] = pos(u);\n\n            // U\n            if (i > 0) {\n                int ni = i - 1, nj = j;\n                int v = vid(ni, nj);\n                double w = blended_v(ni, nj);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'U';\n                    pq.push({dist[v], v});\n                }\n            }\n            // D\n            if (i + 1 < N) {\n                int ni = i + 1, nj = j;\n                int v = vid(ni, nj);\n                double w = blended_v(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'D';\n                    pq.push({dist[v], v});\n                }\n            }\n            // L\n            if (j > 0) {\n                int ni = i, nj = j - 1;\n                int v = vid(ni, nj);\n                double w = blended_h(i, nj);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'L';\n                    pq.push({dist[v], v});\n                }\n            }\n            // R\n            if (j + 1 < N) {\n                int ni = i, nj = j + 1;\n                int v = vid(ni, nj);\n                double w = blended_h(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'R';\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        string path;\n        vector<EdgeRef> edges_rev;\n        int cur = t;\n        while (cur != s) {\n            char mv = prevMove[cur];\n            path.push_back(mv);\n            auto [i, j] = pos(cur);\n            if (mv == 'U') {\n                // prev = (i+1, j), traversed vertical edge at (i, j)\n                edges_rev.push_back({false, i, j});\n            } else if (mv == 'D') {\n                // prev = (i-1, j), traversed vertical edge at (i-1, j)\n                edges_rev.push_back({false, i - 1, j});\n            } else if (mv == 'L') {\n                // prev = (i, j+1), traversed horizontal edge at (i, j)\n                edges_rev.push_back({true, i, j});\n            } else if (mv == 'R') {\n                // prev = (i, j-1), traversed horizontal edge at (i, j - 1)\n                edges_rev.push_back({true, i, j - 1});\n            } else {\n                // Should never happen\n                break;\n            }\n            cur = prev[cur];\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges_rev.begin(), edges_rev.end());\n        return {path, edges_rev};\n    }\n\n    double path_pred_cost(const vector<EdgeRef>& edges) const {\n        double s = 0.0;\n        for (auto &e : edges) {\n            if (e.horiz) s += blended_h(e.i, e.j);\n            else s += blended_v(e.i, e.j);\n        }\n        return s;\n    }\n\n    void update_from_feedback(const vector<EdgeRef>& edges, int observed) {\n        if (edges.empty()) return;\n\n        double pred = path_pred_cost(edges);\n        pred = max(pred, 1.0);\n        double ratio = observed / pred;\n\n        // multiplicative-noise robust clipping\n        ratio = max(0.8, min(1.25, ratio));\n\n        int L = (int)edges.size();\n        double avg_obs = 1.0 * observed / L;\n\n        // learning rates\n        double lr_mult = (turn < 100 ? 0.22 : turn < 300 ? 0.16 : 0.12);\n        double lr_avg  = (turn < 100 ? 0.050 : 0.030);\n\n        for (auto &e : edges) {\n            if (e.horiz) {\n                double cur = h_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = avg_obs;\n                double nv = cur * (1.0 - lr_mult) + target1 * lr_mult;\n                nv = nv * (1.0 - lr_avg) + target2 * lr_avg;\n                nv = clamp_cost(nv);\n\n                h_est[e.i][e.j] = nv;\n                h_sum[e.i][e.j] += avg_obs;\n                h_cnt[e.i][e.j] += 1;\n            } else {\n                double cur = v_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = avg_obs;\n                double nv = cur * (1.0 - lr_mult) + target1 * lr_mult;\n                nv = nv * (1.0 - lr_avg) + target2 * lr_avg;\n                nv = clamp_cost(nv);\n\n                v_est[e.i][e.j] = nv;\n                v_sum[e.i][e.j] += avg_obs;\n                v_cnt[e.i][e.j] += 1;\n            }\n        }\n\n        // gentle denoising toward empirical means if enough samples\n        for (auto &e : edges) {\n            if (e.horiz) {\n                if (h_cnt[e.i][e.j] >= 3) {\n                    double mean = h_sum[e.i][e.j] / h_cnt[e.i][e.j];\n                    h_est[e.i][e.j] = clamp_cost(0.9 * h_est[e.i][e.j] + 0.1 * mean);\n                }\n            } else {\n                if (v_cnt[e.i][e.j] >= 3) {\n                    double mean = v_sum[e.i][e.j] / v_cnt[e.i][e.j];\n                    v_est[e.i][e.j] = clamp_cost(0.9 * v_est[e.i][e.j] + 0.1 * mean);\n                }\n            }\n        }\n\n        // rebuild segmented priors every turn; cheap enough\n        rebuild_priors();\n\n        // global smoothing toward prior\n        double smooth = (turn < 150 ? 0.06 : 0.03);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = clamp_cost((1.0 - smooth) * h_est[i][j] + smooth * h_prior[i][j]);\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = clamp_cost((1.0 - smooth) * v_est[i][j] + smooth * v_prior[i][j]);\n            }\n        }\n    }\n\n    void solve() {\n        rebuild_priors();\n\n        for (turn = 0; turn < 1000; turn++) {\n            int si, sj, ti, tj;\n            cin >> si >> sj >> ti >> tj;\n\n            auto [path, edges] = shortest_path(si, sj, ti, tj);\n            cout << path << '\\n';\n            cout.flush();\n\n            int observed;\n            cin >> observed;\n\n            update_from_feedback(edges, observed);\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}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\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 rand01() {\n        return (next() >> 11) * (1.0 / (1ull << 53));\n    }\n} rng;\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 Pattern {\n    string s;\n    int w;\n};\n\nstruct Candidate {\n    string line;               // length 20\n    vector<uint64_t> bits;     // covered unique patterns\n    int coverWeight = 0;       // sum of weights of covered unique patterns\n};\n\nint Nin, M;\nvector<Pattern> pats;\nint P;\n\ninline int cid(char c) { return c - 'A'; }\n\nbool contains_cyclic_line(const string& line, const string& s) {\n    int L = (int)s.size();\n    for (int st = 0; st < N; st++) {\n        bool ok = true;\n        for (int k = 0; k < L; k++) {\n            if (line[(st + k) % N] != s[k]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n    return false;\n}\n\nstring minimal_rotation(string s) {\n    // Booth O(n^2) is fine for n=20, but implement simple O(n^2)\n    string best = s;\n    for (int i = 1; i < (int)s.size(); i++) {\n        string t = s.substr(i) + s.substr(0, i);\n        if (t < best) best = t;\n    }\n    return best;\n}\n\nint overlap_suffix_prefix(const string& a, const string& b) {\n    int mx = min((int)a.size(), (int)b.size());\n    for (int k = mx; k >= 1; k--) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[(int)a.size() - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nbool is_substring_noncyclic(const string& a, const string& b) {\n    // is a substring of b\n    return b.find(a) != string::npos;\n}\n\nstring fill_to_20(const string& base, const vector<Pattern>& pats, bool randomize) {\n    if ((int)base.size() >= N) return base.substr(0, N);\n    string s = base;\n    while ((int)s.size() < N) {\n        array<long long, 8> score{};\n        score.fill(1);\n        int pos = (int)s.size();\n        for (auto &p : pats) {\n            const string& t = p.s;\n            for (int st = max(0, pos - (int)t.size() + 1); st <= pos; st++) {\n                int k = pos - st;\n                if (st < 0 || k < 0 || k >= (int)t.size()) continue;\n                bool ok = true;\n                for (int i = 0; i < pos - st; i++) {\n                    if (st + i < (int)s.size() && s[st + i] != t[i]) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) score[cid(t[k])] += p.w;\n            }\n        }\n        int bestc = 0;\n        if (randomize && rng.rand01() < 0.25) {\n            long long sum = 0;\n            for (int c = 0; c < 8; c++) sum += score[c];\n            long long r = rng.next() % sum;\n            long long acc = 0;\n            for (int c = 0; c < 8; c++) {\n                acc += score[c];\n                if (r < acc) { bestc = c; break; }\n            }\n        } else {\n            for (int c = 1; c < 8; c++) if (score[c] > score[bestc]) bestc = c;\n        }\n        s.push_back(char('A' + bestc));\n    }\n    return s;\n}\n\nCandidate make_candidate(const string& line) {\n    Candidate c;\n    c.line = minimal_rotation(line);\n    c.bits.assign((P + 63) >> 6, 0ULL);\n    int sw = 0;\n    for (int i = 0; i < P; i++) {\n        if (contains_cyclic_line(c.line, pats[i].s)) {\n            c.bits[i >> 6] |= 1ULL << (i & 63);\n            sw += pats[i].w;\n        }\n    }\n    c.coverWeight = sw;\n    return c;\n}\n\nvector<Candidate> generate_candidates(double time_limit) {\n    Timer timer;\n    vector<Candidate> cands;\n    unordered_set<string> seen;\n    seen.reserve(4096);\n\n    auto add_candidate = [&](const string& raw) {\n        string line = minimal_rotation(raw.substr(0, N));\n        if (seen.insert(line).second) {\n            cands.push_back(make_candidate(line));\n        }\n    };\n\n    // sort patterns by value\n    vector<int> ord(P);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        long long va = 1LL * pats[a].w * (int)pats[a].s.size() * (int)pats[a].s.size();\n        long long vb = 1LL * pats[b].w * (int)pats[b].s.size() * (int)pats[b].s.size();\n        if (va != vb) return va > vb;\n        return pats[a].s.size() > pats[b].s.size();\n    });\n\n    // deterministic top seeds\n    int topSeeds = min(P, 120);\n    for (int si = 0; si < topSeeds; si++) {\n        string cur = pats[ord[si]].s;\n        vector<int> used(P, 0);\n        used[ord[si]] = 1;\n\n        while ((int)cur.size() < N) {\n            long long bestScore = -1;\n            int bestj = -1;\n            bool bestAppend = true;\n            int bestOv = 0;\n\n            for (int t = 0; t < min(P, 200); t++) {\n                int j = ord[t];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = true;\n                        bestOv = ov1;\n                    }\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = false;\n                        bestOv = ov2;\n                    }\n                }\n            }\n\n            if (bestj == -1) break;\n            used[bestj] = 1;\n            const string& s = pats[bestj].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (bestAppend) cur += s.substr(bestOv);\n            else cur = s + cur.substr(bestOv);\n        }\n        add_candidate(fill_to_20(cur, pats, false));\n    }\n\n    // randomized builds\n    while (timer.elapsed() < time_limit) {\n        int seed = ord[rng.randint(0, min(P, 80) - 1)];\n        string cur = pats[seed].s;\n        vector<int> used(P, 0);\n        used[seed] = 1;\n\n        int steps = rng.randint(8, 20);\n        for (int step = 0; step < steps && (int)cur.size() < N; step++) {\n            vector<pair<long long, tuple<int,bool,int>>> opts;\n            int pool = min(P, 180);\n            for (int it = 0; it < pool; it++) {\n                int j = ord[it];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, true, ov1}});\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, false, ov2}});\n                }\n            }\n            if (opts.empty()) break;\n            nth_element(opts.begin(),\n                        opts.begin() + min<int>(opts.size(), 5) - 1,\n                        opts.end(),\n                        [&](auto& a, auto& b){ return a.first > b.first; });\n            int pick = rng.randint(0, min<int>(opts.size(), 5) - 1);\n            auto [sc, tup] = opts[pick];\n            auto [j, app, ov] = tup;\n            used[j] = 1;\n            const string& s = pats[j].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (app) cur += s.substr(ov);\n            else cur = s + cur.substr(ov);\n        }\n        add_candidate(fill_to_20(cur, pats, true));\n    }\n\n    // single-pattern direct cyclic fills\n    for (int i = 0; i < min(P, 100); i++) {\n        add_candidate(fill_to_20(pats[ord[i]].s, pats, true));\n    }\n\n    return cands;\n}\n\nint total_weight_from_count(const vector<int>& cnt) {\n    int s = 0;\n    for (int i = 0; i < P; i++) if (cnt[i] > 0) s += pats[i].w;\n    return s;\n}\n\nvector<int> greedy_select_rows(const vector<Candidate>& cands) {\n    int C = (int)cands.size();\n    vector<int> selected;\n    vector<int> cnt(P, 0);\n    vector<char> used(C, 0);\n\n    for (int iter = 0; iter < N; iter++) {\n        int best = -1;\n        long long bestGain = -1;\n\n        for (int i = 0; i < C; i++) if (!used[i]) {\n            long long gain = 0;\n            for (int p = 0; p < P; p++) {\n                if (cnt[p] == 0) {\n                    if ((cands[i].bits[p >> 6] >> (p & 63)) & 1ULL) gain += pats[p].w;\n                }\n            }\n            // slight diversity bonus\n            gain += cands[i].coverWeight / 50;\n            if (gain > bestGain) {\n                bestGain = gain;\n                best = i;\n            }\n        }\n\n        if (best == -1) best = 0;\n        used[best] = 1;\n        selected.push_back(best);\n        for (int p = 0; p < P; p++) {\n            if ((cands[best].bits[p >> 6] >> (p & 63)) & 1ULL) cnt[p]++;\n        }\n    }\n    return selected;\n}\n\nint evaluate_grid(const vector<string>& g) {\n    vector<string> cols(N, string(N, 'A'));\n    for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) cols[j][i] = g[i][j];\n\n    int score = 0;\n    for (int p = 0; p < P; p++) {\n        bool ok = false;\n        for (int i = 0; i < N && !ok; i++) if (contains_cyclic_line(g[i], pats[p].s)) ok = true;\n        for (int j = 0; j < N && !ok; j++) if (contains_cyclic_line(cols[j], pats[p].s)) ok = true;\n        if (ok) score += pats[p].w;\n    }\n    return score;\n}\n\nvector<string> rows_from_selection(const vector<Candidate>& cands, const vector<int>& sel) {\n    vector<string> g(N);\n    for (int i = 0; i < N; i++) g[i] = cands[sel[i]].line;\n    return g;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> Nin >> M;\n    vector<string> input(M);\n    for (int i = 0; i < M; i++) cin >> input[i];\n\n    unordered_map<string, int> mp;\n    mp.reserve(M * 2);\n    for (auto &s : input) mp[s]++;\n\n    pats.clear();\n    pats.reserve(mp.size());\n    for (auto &kv : mp) pats.push_back({kv.first, kv.second});\n    P = (int)pats.size();\n\n    sort(pats.begin(), pats.end(), [&](const Pattern& a, const Pattern& b) {\n        long long va = 1LL * a.w * (int)a.s.size() * (int)a.s.size();\n        long long vb = 1LL * b.w * (int)b.s.size() * (int)b.s.size();\n        if (va != vb) return va > vb;\n        if (a.s.size() != b.s.size()) return a.s.size() > b.s.size();\n        return a.s < b.s;\n    });\n\n    Timer allTimer;\n\n    // Phase 1: generate candidate lines\n    auto cands = generate_candidates(0.9);\n    if (cands.empty()) {\n        string s(N, 'A');\n        for (int i = 0; i < N; i++) cout << s << '\\n';\n        return 0;\n    }\n\n    // Phase 2: select 20 rows greedily\n    auto sel = greedy_select_rows(cands);\n    vector<string> bestGrid = rows_from_selection(cands, sel);\n    int bestScore = evaluate_grid(bestGrid);\n\n    // Phase 3: row replacement local improvement\n    {\n        vector<int> curSel = sel;\n        vector<string> curGrid = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 1.6) {\n            int pos = rng.randint(0, N - 1);\n            int candId = rng.randint(0, (int)cands.size() - 1);\n\n            int old = curSel[pos];\n            if (old == candId) continue;\n            curSel[pos] = candId;\n            curGrid[pos] = cands[candId].line;\n\n            int sc = evaluate_grid(curGrid);\n            if (sc >= curScore || rng.rand01() < 0.01) {\n                curScore = sc;\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestGrid = curGrid;\n                }\n            } else {\n                curSel[pos] = old;\n                curGrid[pos] = cands[old].line;\n            }\n        }\n    }\n\n    // Phase 4: cell-wise hill climbing\n    {\n        vector<string> cur = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 2.95) {\n            int i = rng.randint(0, N - 1);\n            int j = rng.randint(0, N - 1);\n            char oldc = cur[i][j];\n\n            char bestc = oldc;\n            int localBest = curScore;\n\n            array<int, 8> perm{};\n            iota(perm.begin(), perm.end(), 0);\n            shuffle(perm.begin(), perm.end(), std::mt19937((uint32_t)rng.next()));\n\n            int tries = 4;\n            for (int t = 0; t < tries; t++) {\n                char nc = char('A' + perm[t]);\n                if (nc == oldc) continue;\n                cur[i][j] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc > localBest || (sc == localBest && rng.rand01() < 0.05)) {\n                    localBest = sc;\n                    bestc = nc;\n                }\n            }\n\n            cur[i][j] = bestc;\n            curScore = localBest;\n\n            if (curScore > bestScore) {\n                bestScore = curScore;\n                bestGrid = cur;\n            }\n\n            // rare random kick\n            if (rng.rand01() < 0.01) {\n                int x = rng.randint(0, N - 1), y = rng.randint(0, N - 1);\n                char nc = char('A' + rng.randint(0, 7));\n                char bak = cur[x][y];\n                cur[x][y] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc >= curScore || rng.rand01() < 0.2) {\n                    curScore = sc;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestGrid = cur;\n                    }\n                } else {\n                    cur[x][y] = bak;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << bestGrid[i] << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int INF = 1e9;\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    vector<string> C(N);\n    for (int i = 0; i < N; i++) cin >> C[i];\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n    auto road = [&](int x, int y) -> bool {\n        return inb(x, y) && C[x][y] != '#';\n    };\n    auto w = [&](int x, int y) -> int {\n        return C[x][y] - '0';\n    };\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n    const char dc[4] = {'U', 'D', 'L', 'R'};\n\n    // Road indexing\n    vector<Pos> roads;\n    vector<vector<int>> rid(N, vector<int>(N, -1));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (road(i, j)) {\n            rid[i][j] = (int)roads.size();\n            roads.push_back({i, j});\n        }\n    }\n    int R = (int)roads.size();\n\n    // Degrees and shape\n    vector<vector<int>> deg(N, vector<int>(N, 0));\n    for (auto &p : roads) {\n        int d = 0;\n        for (int k = 0; k < 4; k++) if (road(p.x + dx[k], p.y + dy[k])) d++;\n        deg[p.x][p.y] = d;\n    }\n\n    auto is_corner = [&](int x, int y) -> bool {\n        if (!road(x, y) || deg[x][y] != 2) return false;\n        bool ud = road(x - 1, y) && road(x + 1, y);\n        bool lr = road(x, y - 1) && road(x, y + 1);\n        return !(ud || lr);\n    };\n    auto is_important = [&](int x, int y) -> bool {\n        if (x == si && y == sj) return true;\n        if (deg[x][y] != 2) return true;\n        return is_corner(x, y);\n    };\n\n    // Maximal horizontal / vertical segments\n    vector<vector<int>> hs(N, vector<int>(N, -1));\n    vector<vector<int>> vs(N, vector<int>(N, -1));\n    int H = 0, V = 0;\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (!road(i, j)) { j++; continue; }\n            int k = j;\n            while (k < N && road(i, k)) k++;\n            for (int y = j; y < k; y++) hs[i][y] = H;\n            H++;\n            j = k;\n        }\n    }\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (!road(i, j)) { i++; continue; }\n            int k = i;\n            while (k < N && road(k, j)) k++;\n            for (int x = i; x < k; x++) vs[x][j] = V;\n            V++;\n            i = k;\n        }\n    }\n\n    // Cells in each segment\n    vector<vector<int>> hCells(H), vCells(V);\n    for (auto &p : roads) {\n        int id = rid[p.x][p.y];\n        hCells[hs[p.x][p.y]].push_back(id);\n        vCells[vs[p.x][p.y]].push_back(id);\n    }\n\n    // Candidate viewpoints:\n    // important nodes + sampled corridor cells on long straight segments\n    vector<Pos> cand;\n    vector<vector<int>> cid(N, vector<int>(N, -1));\n\n    auto add_candidate = [&](int x, int y) {\n        if (!road(x, y)) return;\n        if (cid[x][y] != -1) return;\n        cid[x][y] = (int)cand.size();\n        cand.push_back({x, y});\n    };\n\n    for (auto &p : roads) {\n        if (is_important(p.x, p.y)) add_candidate(p.x, p.y);\n    }\n\n    // Add sampled corridor cells\n    // horizontal corridors\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (!road(i, j)) { j++; continue; }\n            int k = j;\n            while (k < N && road(i, k)) k++;\n            int len = k - j;\n            if (len >= 6) {\n                for (int y = j + 2; y <= k - 3; y += 4) {\n                    if (deg[i][y] == 2 && !is_corner(i, y)) add_candidate(i, y);\n                }\n            }\n            j = k;\n        }\n    }\n    // vertical corridors\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (!road(i, j)) { i++; continue; }\n            int k = i;\n            while (k < N && road(k, j)) k++;\n            int len = k - i;\n            if (len >= 6) {\n                for (int x = i + 2; x <= k - 3; x += 4) {\n                    if (deg[x][j] == 2 && !is_corner(x, j)) add_candidate(x, j);\n                }\n            }\n            i = k;\n        }\n    }\n\n    add_candidate(si, sj);\n\n    int M = (int)cand.size();\n    int start = cid[si][sj];\n\n    // For each candidate, list road cells it makes visible (union of row/col LOS)\n    vector<vector<int>> visible(M);\n    for (int id = 0; id < M; id++) {\n        auto [x, y] = cand[id];\n        vector<int> tmp;\n        tmp.push_back(rid[x][y]);\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x, ny = y;\n            while (true) {\n                nx += dx[dir];\n                ny += dy[dir];\n                if (!road(nx, ny)) break;\n                tmp.push_back(rid[nx][ny]);\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());\n        visible[id] = move(tmp);\n    }\n\n    // Greedy covering on cells directly, but with better candidates.\n    vector<char> covered(R, 0);\n    int covered_cnt = 0;\n    auto cover_by = [&](int id) -> int {\n        int gain = 0;\n        for (int r : visible[id]) if (!covered[r]) gain++;\n        return gain;\n    };\n    auto apply_cover = [&](int id) {\n        for (int r : visible[id]) {\n            if (!covered[r]) {\n                covered[r] = 1;\n                covered_cnt++;\n            }\n        }\n    };\n\n    vector<int> targets;\n    vector<char> chosen(M, 0);\n    chosen[start] = 1;\n    targets.push_back(start);\n    apply_cover(start);\n\n    // Greedy selection with gain / rough cost\n    while (covered_cnt < R) {\n        int best = -1;\n        double bestScore = -1e100;\n        for (int id = 0; id < M; id++) {\n            if (chosen[id]) continue;\n            int gain = cover_by(id);\n            if (gain == 0) continue;\n            int md = abs(cand[id].x - si) + abs(cand[id].y - sj);\n            double score = (double)gain * 1000.0 - 2.5 * md;\n            if (score > bestScore) {\n                bestScore = score;\n                best = id;\n            }\n        }\n        if (best == -1) break;\n        chosen[best] = 1;\n        targets.push_back(best);\n        apply_cover(best);\n    }\n\n    // Remove redundant targets greedily\n    auto fully_covered_by_set = [&](const vector<int>& setv) -> bool {\n        vector<char> cov(R, 0);\n        for (int id : setv) {\n            for (int r : visible[id]) cov[r] = 1;\n        }\n        for (int i = 0; i < R; i++) if (!cov[i]) return false;\n        return true;\n    };\n\n    {\n        vector<int> cur = targets;\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = 0; i < (int)cur.size(); i++) {\n                if (cur[i] == start) continue;\n                vector<int> nxt;\n                nxt.reserve(cur.size() - 1);\n                for (int j = 0; j < (int)cur.size(); j++) if (j != i) nxt.push_back(cur[j]);\n                if (fully_covered_by_set(nxt)) {\n                    cur.swap(nxt);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        targets.swap(cur);\n    }\n\n    // Build list of special nodes = targets\n    sort(targets.begin(), targets.end());\n    targets.erase(unique(targets.begin(), targets.end()), targets.end());\n\n    int T = (int)targets.size();\n    vector<int> idxOfCand(M, -1);\n    for (int i = 0; i < T; i++) idxOfCand[targets[i]] = i;\n    int sidx = idxOfCand[start];\n\n    // Dijkstra from each target on full grid\n    int NN = N * N;\n    auto vid = [&](int x, int y) { return x * N + y; };\n\n    vector<vector<int>> distT(T, vector<int>(NN, INF));\n    vector<vector<int>> parentT(T, vector<int>(NN, -1));\n\n    for (int ti = 0; ti < T; ti++) {\n        auto [sx, sy] = cand[targets[ti]];\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        int s = vid(sx, sy);\n        distT[ti][s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != distT[ti][v]) continue;\n            int x = v / N, y = v % N;\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dx[k], ny = y + dy[k];\n                if (!road(nx, ny)) continue;\n                int nv = vid(nx, ny);\n                int nd = cd + w(nx, ny);\n                if (nd < distT[ti][nv]) {\n                    distT[ti][nv] = nd;\n                    parentT[ti][nv] = v;\n                    pq.push({nd, nv});\n                }\n            }\n        }\n    }\n\n    // Metric closure among targets\n    vector<vector<int>> d(T, vector<int>(T, INF));\n    for (int i = 0; i < T; i++) {\n        for (int j = 0; j < T; j++) {\n            auto [x, y] = cand[targets[j]];\n            d[i][j] = distT[i][vid(x, y)];\n        }\n    }\n\n    // Initial TSP tour by cheapest insertion\n    vector<int> others;\n    for (int i = 0; i < T; i++) if (i != sidx) others.push_back(i);\n\n    vector<int> tour;\n    if (others.empty()) {\n        tour = {sidx, sidx};\n    } else {\n        int first = others[0];\n        int best = INF;\n        for (int x : others) {\n            int val = d[sidx][x] + d[x][sidx];\n            if (val < best) best = val, first = x;\n        }\n        tour = {sidx, first, sidx};\n\n        vector<char> used(T, 0);\n        used[sidx] = 1;\n        used[first] = 1;\n\n        for (int step = 1; step < (int)others.size(); step++) {\n            int bestx = -1, bestpos = -1, bestinc = INF;\n            for (int x : others) if (!used[x]) {\n                for (int i = 0; i + 1 < (int)tour.size(); i++) {\n                    int a = tour[i], b = tour[i + 1];\n                    int inc = d[a][x] + d[x][b] - d[a][b];\n                    if (inc < bestinc) {\n                        bestinc = inc;\n                        bestx = x;\n                        bestpos = i + 1;\n                    }\n                }\n            }\n            if (bestx == -1) break;\n            tour.insert(tour.begin() + bestpos, bestx);\n            used[bestx] = 1;\n        }\n    }\n\n    auto tour_cost = [&](const vector<int>& tr) -> long long {\n        long long res = 0;\n        for (int i = 0; i + 1 < (int)tr.size(); i++) res += d[tr[i]][tr[i + 1]];\n        return res;\n    };\n\n    // 2-opt on cycle representation [s ... s]\n    {\n        bool improved = true;\n        int loop = 0;\n        while (improved && loop < 6) {\n            improved = false;\n            loop++;\n            for (int i = 1; i + 2 < (int)tour.size(); i++) {\n                for (int j = i + 1; j + 1 < (int)tour.size(); j++) {\n                    int a = tour[i - 1], b = tour[i];\n                    int c = tour[j], e = tour[j + 1];\n                    long long before = (long long)d[a][b] + d[c][e];\n                    long long after  = (long long)d[a][c] + d[b][e];\n                    if (after < before) {\n                        reverse(tour.begin() + i, tour.begin() + j + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    // Relocation local search\n    {\n        bool improved = true;\n        int loop = 0;\n        while (improved && loop < 6) {\n            improved = false;\n            loop++;\n            for (int i = 1; i + 1 < (int)tour.size(); i++) {\n                int x = tour[i];\n                long long rem = (long long)d[tour[i - 1]][x] + d[x][tour[i + 1]] - d[tour[i - 1]][tour[i + 1]];\n                int bestPos = -1;\n                long long bestDelta = 0;\n                for (int j = 0; j + 1 < (int)tour.size(); j++) {\n                    if (j == i || j + 1 == i) continue;\n                    long long add = (long long)d[tour[j]][x] + d[x][tour[j + 1]] - d[tour[j]][tour[j + 1]];\n                    long long delta = add - rem;\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestPos = j;\n                    }\n                }\n                if (bestPos != -1) {\n                    vector<int> nt = tour;\n                    nt.erase(nt.begin() + i);\n                    int ins = bestPos + 1;\n                    if (bestPos >= i) ins--;\n                    nt.insert(nt.begin() + ins, x);\n                    tour.swap(nt);\n                    improved = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    // Reconstruct path between two target nodes using stored parent from source target\n    auto restore_path = [&](int fromIdx, int toIdx) -> vector<Pos> {\n        auto [tx, ty] = cand[targets[toIdx]];\n        int cur = vid(tx, ty);\n        int s = vid(cand[targets[fromIdx]].x, cand[targets[fromIdx]].y);\n        vector<int> rev;\n        while (cur != s) {\n            rev.push_back(cur);\n            cur = parentT[fromIdx][cur];\n            if (cur == -1) {\n                // Should not happen on connected road graph, but fail-safe\n                return {};\n            }\n        }\n        reverse(rev.begin(), rev.end());\n        vector<Pos> res;\n        for (int v : rev) res.push_back({v / N, v % N});\n        return res;\n    };\n\n    string ans;\n    int cx = si, cy = sj;\n    auto emit_step = [&](int nx, int ny) {\n        if (nx == cx - 1 && ny == cy) ans.push_back('U');\n        else if (nx == cx + 1 && ny == cy) ans.push_back('D');\n        else if (nx == cx && ny == cy - 1) ans.push_back('L');\n        else if (nx == cx && ny == cy + 1) ans.push_back('R');\n        cx = nx; cy = ny;\n    };\n\n    for (int i = 0; i + 1 < (int)tour.size(); i++) {\n        auto path = restore_path(tour[i], tour[i + 1]);\n        for (auto &p : path) emit_step(p.x, p.y);\n    }\n\n    // final validation, fallback to empty if invalid\n    {\n        int x = si, y = sj;\n        bool ok = true;\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n            else ok = false;\n            if (!inb(x, y) || !road(x, y)) ok = false;\n        }\n        if (x != si || y != sj) ok = false;\n        if (!ok) ans.clear();\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskInfo {\n    vector<int> d;\n    int diff_sum = 0;\n    int priority = 1; // longest path to sink\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<TaskInfo> tasks(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].d.resize(K);\n        int s = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n            s += tasks[i].d[k];\n        }\n        tasks[i].diff_sum = s;\n    }\n\n    vector<vector<int>> out(N), in(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        in[v].push_back(u);\n    }\n\n    // Static priority = longest path to sink\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int to : out[i]) best = max(best, tasks[to].priority);\n        tasks[i].priority = best + 1;\n    }\n\n    // State\n    // task_state: 0 not started, 1 in progress, 2 done\n    vector<int> task_state(N, 0);\n    vector<int> rem_pre(N);\n    for (int i = 0; i < N; ++i) rem_pre[i] = (int)in[i].size();\n\n    vector<int> member_task(M, -1);\n    vector<int> member_start(M, -1);\n\n    // Skill estimates\n    vector<vector<double>> est(M, vector<double>(K, 20.0));\n    vector<int> obs_cnt(M, 0);\n\n    // For updates when a member finishes a task\n    auto predicted_deficit = [&](int task_id, int member_id) -> double {\n        double w = 0.0;\n        const auto &d = tasks[task_id].d;\n        const auto &s = est[member_id];\n        for (int k = 0; k < K; ++k) {\n            if (d[k] > s[k]) w += d[k] - s[k];\n        }\n        return w;\n    };\n\n    auto predicted_time = [&](int task_id, int member_id) -> double {\n        return max(1.0, predicted_deficit(task_id, member_id));\n    };\n\n    auto update_estimate = [&](int member_id, int task_id, int duration) {\n        // target deficit estimate\n        // conservative estimate due to noise and lower bound at 1\n        double target = (duration <= 1 ? 0.0 : (double)duration - 1.0);\n\n        const auto &d = tasks[task_id].d;\n        auto &s = est[member_id];\n\n        for (int iter = 0; iter < 3; ++iter) {\n            double pred = 0.0;\n            for (int k = 0; k < K; ++k) {\n                if (d[k] > s[k]) pred += d[k] - s[k];\n            }\n            double diff = target - pred; // positive => skills too high, negative => too low\n\n            double lr = 0.45 / (1.0 + 0.08 * obs_cnt[member_id]);\n            if (fabs(diff) < 0.5) break;\n\n            if (diff < 0) {\n                // Predicted deficit too large => estimated skills too low => increase skills\n                // Focus on dimensions where d[k] > s[k]\n                double total_gap = 0.0;\n                for (int k = 0; k < K; ++k) total_gap += max(0.0, (double)d[k] - s[k]);\n                if (total_gap < 1e-9) total_gap = 1.0;\n                double need = -diff * lr;\n                for (int k = 0; k < K; ++k) {\n                    double gap = max(0.0, (double)d[k] - s[k]);\n                    if (gap <= 0) continue;\n                    s[k] += need * (gap / total_gap);\n                    if (s[k] > 80.0) s[k] = 80.0;\n                }\n            } else {\n                // Predicted deficit too small => estimated skills too high => decrease a bit\n                // Decrease dimensions relevant to this task.\n                double total_rel = 0.0;\n                for (int k = 0; k < K; ++k) total_rel += d[k] + 1.0;\n                double need = diff * lr * 0.6;\n                for (int k = 0; k < K; ++k) {\n                    double dec = need * ((d[k] + 1.0) / total_rel);\n                    s[k] -= dec;\n                    if (s[k] < 0.0) s[k] = 0.0;\n                }\n            }\n        }\n\n        obs_cnt[member_id]++;\n    };\n\n    int day = 0;\n    int completed_tasks = 0;\n\n    while (true) {\n        day++;\n\n        // Ready tasks\n        vector<int> ready;\n        ready.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 0 && rem_pre[i] == 0) ready.push_back(i);\n        }\n\n        // Sort ready tasks by importance\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (tasks[a].priority != tasks[b].priority) return tasks[a].priority > tasks[b].priority;\n            if (tasks[a].diff_sum != tasks[b].diff_sum) return tasks[a].diff_sum > tasks[b].diff_sum;\n            return a < b;\n        });\n\n        // Candidate truncation\n        const int LIMIT = 180;\n        if ((int)ready.size() > LIMIT) ready.resize(LIMIT);\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) if (member_task[j] == -1) free_members.push_back(j);\n\n        vector<pair<int,int>> assignments;\n        vector<char> used_task(N, 0), used_member(M, 0);\n\n        // Greedy global pair selection\n        while (true) {\n            double bestScore = -1e100;\n            int bestMem = -1, bestTask = -1;\n\n            for (int j : free_members) {\n                if (used_member[j]) continue;\n                for (int t : ready) {\n                    if (used_task[t]) continue;\n\n                    double pt = predicted_time(t, j);\n                    // Exploration: lightly favor less-observed members early\n                    double explore = (obs_cnt[j] < 5 ? (5 - obs_cnt[j]) * 3.0 : 0.0);\n\n                    // Strong emphasis on precedence-critical tasks\n                    double score =\n                        1000.0 * tasks[t].priority\n                        + 2.0 * tasks[t].diff_sum\n                        - 25.0 * pt\n                        + explore;\n\n                    // Mild bonus for assigning very hard tasks to seemingly strong members\n                    if (obs_cnt[j] >= 3) {\n                        double strength = 0.0;\n                        for (int k = 0; k < K; ++k) strength += est[j][k];\n                        score += 0.02 * strength;\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestMem = j;\n                        bestTask = t;\n                    }\n                }\n            }\n\n            if (bestMem == -1) break;\n\n            used_member[bestMem] = 1;\n            used_task[bestTask] = 1;\n            assignments.push_back({bestMem, bestTask});\n\n            task_state[bestTask] = 1;\n            member_task[bestMem] = bestTask;\n            member_start[bestMem] = day;\n        }\n\n        // Output today's assignments\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << (mem + 1) << ' ' << (task + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        // Optional visualization comments of estimated skills\n        // Keep disabled in judge for speed/noise. Uncomment if desired.\n        /*\n        for (int j = 0; j < M; ++j) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; ++k) cout << ' ' << (int)round(est[j][k]);\n            cout << '\\n';\n        }\n        cout.flush();\n        */\n\n        string first;\n        if (!(cin >> first)) return 0;\n        if (first == \"-1\") {\n            return 0;\n        }\n\n        int n = stoi(first);\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int mem : finished) {\n            int task = member_task[mem];\n            if (task == -1) continue; // safety\n\n            int duration = day - member_start[mem] + 1;\n            update_estimate(mem, task, duration);\n\n            task_state[task] = 2;\n            completed_tasks++;\n\n            member_task[mem] = -1;\n            member_start[mem] = -1;\n\n            for (int to : out[task]) {\n                rem_pre[to]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 1000;\nstatic constexpr int M = 50;\nstatic constexpr int DEPOT_X = 400;\nstatic constexpr int DEPOT_Y = 400;\n\nstruct Order {\n    int a, b, c, d;\n    int id; // 1-indexed for output\n};\n\nstruct Pt {\n    int x, y;\n};\n\nstatic inline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\nstatic inline int mdist(const Pt& p, const Pt& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstruct Solver {\n    vector<Order> ord;\n    mt19937 rng;\n\n    Solver() : ord(N) {\n        rng.seed((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    }\n\n    double elapsed_ms(chrono::steady_clock::time_point st) {\n        return chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now() - st).count() / 1000.0;\n    }\n\n    Pt rest_pt(int idx) const { return {ord[idx].a, ord[idx].b}; }\n    Pt dest_pt(int idx) const { return {ord[idx].c, ord[idx].d}; }\n\n    int route_cost(const vector<int>& sel, const vector<int>& pord, const vector<int>& dord) const {\n        Pt cur{DEPOT_X, DEPOT_Y};\n        int cost = 0;\n        for (int pos : pord) {\n            Pt nxt = rest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        for (int pos : dord) {\n            Pt nxt = dest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        cost += mdist(cur, Pt{DEPOT_X, DEPOT_Y});\n        return cost;\n    }\n\n    vector<int> nearest_order_restaurant(const vector<int>& sel) const {\n        vector<int> rem(M);\n        iota(rem.begin(), rem.end(), 0);\n        vector<int> res;\n        res.reserve(M);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        vector<char> used(M, false);\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = 1e9;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                Pt p = rest_pt(sel[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(best);\n            cur = rest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    vector<int> nearest_order_destination_from(const vector<int>& sel, const Pt& start) const {\n        vector<int> res;\n        res.reserve(M);\n        Pt cur = start;\n        vector<char> used(M, false);\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = 1e9;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                Pt p = dest_pt(sel[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(best);\n            cur = dest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    void improve_two_opt_pick(const vector<int>& sel, vector<int>& pord, const vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    auto getP = [&](int idx) -> Pt {\n                        if (idx < 0) return Pt{DEPOT_X, DEPOT_Y};\n                        if (idx >= M) return dest_pt(sel[dord[0]]);\n                        return rest_pt(sel[pord[idx]]);\n                    };\n                    Pt A = getP(l - 1);\n                    Pt B = getP(l);\n                    Pt C = getP(r);\n                    Pt D = getP(r + 1);\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(pord.begin() + l, pord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void improve_two_opt_del(const vector<int>& sel, const vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    auto getD = [&](int idx) -> Pt {\n                        if (idx < 0) return rest_pt(sel[pord.back()]);\n                        if (idx >= M) return Pt{DEPOT_X, DEPOT_Y};\n                        return dest_pt(sel[dord[idx]]);\n                    };\n                    Pt A = getD(l - 1);\n                    Pt B = getD(l);\n                    Pt C = getD(r);\n                    Pt D = getD(r + 1);\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(dord.begin() + l, dord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void improve_swaps(const vector<int>& sel, vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            // pickup swaps\n            for (int i = 0; i < M; ++i) {\n                for (int j = i + 1; j < M; ++j) {\n                    int cur = route_cost(sel, pord, dord);\n                    swap(pord[i], pord[j]);\n                    int nw = route_cost(sel, pord, dord);\n                    if (nw < cur) {\n                        improved = true;\n                    } else {\n                        swap(pord[i], pord[j]);\n                    }\n                }\n            }\n            // delivery swaps\n            for (int i = 0; i < M; ++i) {\n                for (int j = i + 1; j < M; ++j) {\n                    int cur = route_cost(sel, pord, dord);\n                    swap(dord[i], dord[j]);\n                    int nw = route_cost(sel, pord, dord);\n                    if (nw < cur) {\n                        improved = true;\n                    } else {\n                        swap(dord[i], dord[j]);\n                    }\n                }\n            }\n        }\n    }\n\n    pair<vector<int>, pair<vector<int>, vector<int>>> build_initial_from_pool(const vector<int>& pool) {\n        vector<int> sel;\n        sel.reserve(M);\n\n        // Greedy selection on restaurant proximity, with a simple order-level score.\n        vector<char> used(N, false);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        for (int it = 0; it < M; ++it) {\n            int best = -1;\n            int bestScore = 1e9;\n            for (int idx : pool) if (!used[idx]) {\n                const auto& o = ord[idx];\n                int score =\n                    mdist(cur.x, cur.y, o.a, o.b) +\n                    mdist(o.a, o.b, o.c, o.d) / 3 +\n                    mdist(o.c, o.d, DEPOT_X, DEPOT_Y) / 3;\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = idx;\n                }\n            }\n            if (best == -1) break;\n            used[best] = true;\n            sel.push_back(best);\n            cur = rest_pt(best);\n        }\n\n        // if pool smaller somehow, fill from global\n        if ((int)sel.size() < M) {\n            vector<pair<int,int>> all;\n            all.reserve(N);\n            for (int i = 0; i < N; ++i) if (!used[i]) {\n                int base = mdist(ord[i].a, ord[i].b, DEPOT_X, DEPOT_Y)\n                         + mdist(ord[i].a, ord[i].b, ord[i].c, ord[i].d)\n                         + mdist(ord[i].c, ord[i].d, DEPOT_X, DEPOT_Y);\n                all.push_back({base, i});\n            }\n            sort(all.begin(), all.end());\n            for (auto &p : all) {\n                if ((int)sel.size() >= M) break;\n                used[p.second] = true;\n                sel.push_back(p.second);\n            }\n        }\n\n        auto pord = nearest_order_restaurant(sel);\n        Pt lastPick = rest_pt(sel[pord.back()]);\n        auto dord = nearest_order_destination_from(sel, lastPick);\n\n        improve_two_opt_pick(sel, pord, dord);\n        improve_two_opt_del(sel, pord, dord);\n        improve_swaps(sel, pord, dord);\n\n        return {sel, {pord, dord}};\n    }\n\n    void solve() {\n        for (int i = 0; i < N; ++i) {\n            cin >> ord[i].a >> ord[i].b >> ord[i].c >> ord[i].d;\n            ord[i].id = i + 1;\n        }\n\n        auto st = chrono::steady_clock::now();\n\n        vector<pair<int,int>> ranked;\n        ranked.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            int base =\n                mdist(ord[i].a, ord[i].b, DEPOT_X, DEPOT_Y) +\n                mdist(ord[i].a, ord[i].b, ord[i].c, ord[i].d) +\n                mdist(ord[i].c, ord[i].d, DEPOT_X, DEPOT_Y);\n            ranked.push_back({base, i});\n        }\n        sort(ranked.begin(), ranked.end());\n\n        int bestCost = INT_MAX;\n        vector<int> bestSel, bestP, bestD;\n\n        vector<int> poolSizes = {50, 60, 80, 100, 150, 200, 300};\n\n        for (int K : poolSizes) {\n            if (elapsed_ms(st) > 700) break;\n            K = min(K, N);\n            vector<int> pool;\n            pool.reserve(K);\n            for (int i = 0; i < K; ++i) pool.push_back(ranked[i].second);\n\n            auto init = build_initial_from_pool(pool);\n            auto sel = init.first;\n            auto pord = init.second.first;\n            auto dord = init.second.second;\n            int cost = route_cost(sel, pord, dord);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSel = sel;\n                bestP = pord;\n                bestD = dord;\n            }\n        }\n\n        // Improvement by replacement from good candidates / random candidates.\n        vector<int> topPool;\n        {\n            int K = 250;\n            for (int i = 0; i < K; ++i) topPool.push_back(ranked[i].second);\n        }\n\n        auto rebuild_orders = [&](const vector<int>& sel) {\n            auto pord = nearest_order_restaurant(sel);\n            auto dord = nearest_order_destination_from(sel, rest_pt(sel[pord.back()]));\n            improve_two_opt_pick(sel, pord, dord);\n            improve_two_opt_del(sel, pord, dord);\n            improve_swaps(sel, pord, dord);\n            return pair<vector<int>, vector<int>>(pord, dord);\n        };\n\n        while (elapsed_ms(st) < 1900) {\n            vector<int> sel = bestSel;\n\n            vector<char> inSel(N, false);\n            for (int x : sel) inSel[x] = true;\n\n            int outPos = uniform_int_distribution<int>(0, M - 1)(rng);\n            int inIdx;\n            if (uniform_int_distribution<int>(0, 99)(rng) < 80) {\n                inIdx = topPool[uniform_int_distribution<int>(0, (int)topPool.size() - 1)(rng)];\n            } else {\n                inIdx = uniform_int_distribution<int>(0, N - 1)(rng);\n            }\n            if (inSel[inIdx]) continue;\n\n            sel[outPos] = inIdx;\n\n            auto [pord, dord] = rebuild_orders(sel);\n            int cost = route_cost(sel, pord, dord);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSel = move(sel);\n                bestP = move(pord);\n                bestD = move(dord);\n            }\n        }\n\n        // Output\n        cout << M;\n        for (int idx : bestSel) cout << ' ' << ord[idx].id;\n        cout << '\\n';\n\n        vector<Pt> route;\n        route.reserve(2 * M + 2);\n        route.push_back({DEPOT_X, DEPOT_Y});\n        for (int pos : bestP) route.push_back(rest_pt(bestSel[pos]));\n        for (int pos : bestD) route.push_back(dest_pt(bestSel[pos]));\n        route.push_back({DEPOT_X, DEPOT_Y});\n\n        cout << route.size();\n        for (auto &p : route) cout << ' ' << p.x << ' ' << p.y;\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}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n) { 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 same(int a, int b) { return find(a) == find(b); }\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 type; // 0 = accepted edge, 1 = current edge, 2 = future undecided edge\n    int idx;\n    int u, v;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return type < other.type;\n    }\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    double dd = sqrt((double)(dx * dx + dy * dy));\n    return (int)llround(dd);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<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    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i].u = u;\n        edges[i].v = v;\n        edges[i].d = rounded_dist(x[u], y[u], x[v], y[v]);\n    }\n\n    vector<int> state(M, -1);   // -1 undecided, 0 rejected, 1 accepted\n    DSU accepted(N);\n\n    auto feasible_without_current = [&](int cur) -> bool {\n        DSU dsu(N);\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            } else if (j > cur && state[j] == -1) {\n                if (j == cur) continue;\n                dsu.unite(edges[j].u, edges[j].v);\n            }\n        }\n        return dsu.same(edges[cur].u, edges[cur].v);\n    };\n\n    auto current_in_surrogate_mst = [&](int cur, int lcur) -> bool {\n        vector<KEdge> es;\n        es.reserve(M - cur + N);\n\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                es.push_back({0, 0, j, edges[j].u, edges[j].v});\n            } else if (j == cur) {\n                es.push_back({lcur, 1, j, edges[j].u, edges[j].v});\n            } else if (j > cur && state[j] == -1) {\n                es.push_back({2 * edges[j].d, 2, j, edges[j].u, edges[j].v});\n            }\n        }\n\n        sort(es.begin(), es.end());\n        DSU dsu(N);\n        for (auto &e : es) {\n            if (dsu.unite(e.u, e.v)) {\n                if (e.type == 1) return true;\n            }\n        }\n        return false;\n    };\n\n    auto alternative_threshold = [&](int cur) -> int {\n        // Find a cheap expected alternative connecting the current accepted components\n        // of the endpoints of cur. We use the best future undecided crossing edge between\n        // the two sides represented by current accepted DSU components.\n        int ru = accepted.find(edges[cur].u);\n        int rv = accepted.find(edges[cur].v);\n        if (ru == rv) return 0;\n\n        int best = INT_MAX;\n        for (int j = cur + 1; j < M; j++) {\n            if (state[j] != -1) continue;\n            int a = accepted.find(edges[j].u);\n            int b = accepted.find(edges[j].v);\n            if (a == b) continue;\n\n            // Crossing the current two super-components directly is the strongest signal.\n            bool good = (a == ru && b == rv) || (a == rv && b == ru);\n            if (good) {\n                best = min(best, 2 * edges[j].d);\n            }\n        }\n\n        // Fallback: any future edge incident to one of the two components.\n        if (best == INT_MAX) {\n            for (int j = cur + 1; j < M; j++) {\n                if (state[j] != -1) continue;\n                int a = accepted.find(edges[j].u);\n                int b = accepted.find(edges[j].v);\n                if (a == b) continue;\n                bool relevant = (a == ru || a == rv || b == ru || b == rv);\n                if (relevant) best = min(best, 2 * edges[j].d);\n            }\n        }\n\n        return best;\n    };\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n\n        int ans = 0;\n        int u = edges[i].u, v = edges[i].v;\n\n        if (accepted.same(u, v)) {\n            ans = 0;\n        } else {\n            // indispensable for connectivity?\n            if (!feasible_without_current(i)) {\n                ans = 1;\n            } else {\n                bool in_mst = current_in_surrogate_mst(i, l);\n                if (!in_mst) {\n                    ans = 0;\n                } else {\n                    int alt = alternative_threshold(i);\n                    if (alt == INT_MAX) {\n                        ans = 1;\n                    } else {\n                        // modest margin; if current realized cost is close to best expected alternative, accept\n                        ans = (double)l <= 1.15 * (double)alt ? 1 : 0;\n                    }\n                }\n            }\n        }\n\n        state[i] = ans;\n        if (ans) accepted.unite(u, v);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int SZ = 30;\nstatic const int TURNS = 300;\n\nstruct Pet {\n    int x, y, t;\n};\nstruct Human {\n    int x, y;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\n\n// true = impassable\nbool wall_[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar MCH[4] = {'U', 'D', 'L', 'R'};\nchar BCH[4] = {'u', 'd', 'l', 'r'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nint dir_from_move(char c) {\n    for (int d = 0; d < 4; d++) if (MCH[d] == c) return d;\n    return -1;\n}\nint dir_from_build(char c) {\n    for (int d = 0; d < 4; d++) if (BCH[d] == c) return d;\n    return -1;\n}\n\nbool pet_at[31][31];\nbool human_at[31][31];\n\nbool adj_pet(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && pet_at[nx][ny]) return true;\n    }\n    return false;\n}\n\n// legal to newly block at start of turn\nbool can_block_startturn(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (pet_at[x][y]) return false;\n    if (human_at[x][y]) return false;\n    if (adj_pet(x, y)) return false;\n    return true;\n}\n\nstruct Role {\n    // 0 = builder, 1 = camper\n    int type;\n    int tx, ty;\n};\n\nvector<Role> roles;\n\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\npair<int,int> bfs_next_step(\n    int sx, int sy, int tx, int ty,\n    const vector<vector<int>>& blocked_future\n) {\n    if (sx == tx && sy == ty) return {sx, sy};\n\n    static int dist[31][31];\n    static pair<int,int> pre[31][31];\n    for (int i = 1; i <= 30; i++) for (int j = 1; j <= 30; j++) {\n        dist[i][j] = -1;\n        pre[i][j] = {-1, -1};\n    }\n\n    queue<pair<int,int>> q;\n    dist[sx][sy] = 0;\n    q.push({sx, sy});\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (wall_[nx][ny]) continue;\n            if (blocked_future[nx][ny]) continue; // cannot move into a square blocked this turn\n            if (dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            pre[nx][ny] = {x, y};\n            q.push({nx, ny});\n        }\n    }\n\n    if (dist[tx][ty] == -1) return {sx, sy};\n\n    int cx = tx, cy = ty;\n    while (pre[cx][cy] != make_pair(sx, sy)) {\n        auto p = pre[cx][cy];\n        if (p.first == -1) return {sx, sy};\n        cx = p.first;\n        cy = p.second;\n    }\n    return {cx, cy};\n}\n\nchar move_toward_safe(\n    int id, int tx, int ty,\n    const vector<vector<int>>& blocked_future,\n    const vector<pair<int,int>>& move_reserved\n) {\n    int sx = humans[id].x, sy = humans[id].y;\n    auto [nx, ny] = bfs_next_step(sx, sy, tx, ty, blocked_future);\n    if (nx == sx && ny == sy) return '.';\n\n    // conflict check with already reserved move destinations\n    for (int j = 0; j < id; j++) {\n        if (move_reserved[j] == make_pair(nx, ny)) {\n            nx = ny = -1;\n            break;\n        }\n    }\n\n    if (nx != -1) {\n        for (int d = 0; d < 4; d++) {\n            if (sx + dx[d] == nx && sy + dy[d] == ny) return MCH[d];\n        }\n    }\n\n    // fallback: greedy legal move\n    int bestd = 1e9, bestdir = -1;\n    for (int d = 0; d < 4; d++) {\n        int xx = sx + dx[d], yy = sy + dy[d];\n        if (!inside(xx, yy)) continue;\n        if (wall_[xx][yy]) continue;\n        if (blocked_future[xx][yy]) continue;\n        bool used = false;\n        for (int j = 0; j < id; j++) {\n            if (move_reserved[j] == make_pair(xx, yy)) {\n                used = true;\n                break;\n            }\n        }\n        if (used) continue;\n        int val = manhattan(xx, yy, tx, ty);\n        if (val < bestd) {\n            bestd = val;\n            bestdir = d;\n        }\n    }\n    if (bestdir == -1) return '.';\n    return MCH[bestdir];\n}\n\nint count_pets_top() {\n    int c = 0;\n    for (auto &p : pets) if (p.x <= 15) c++;\n    return c;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n    for (int i = 0; i < N; i++) cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; i++) cin >> humans[i].x >> humans[i].y;\n\n    memset(wall_, 0, sizeof(wall_));\n\n    roles.assign(M, {0, 15, 15});\n\n    // assign some campers to corners, rest builders\n    vector<int> ids(M);\n    iota(ids.begin(), ids.end(), 0);\n\n    vector<pair<int,int>> cornerList = {{2,2}, {2,29}, {29,2}, {29,29}};\n    int campers = max(1, M / 4);\n\n    sort(ids.begin(), ids.end(), [&](int a, int b) {\n        int da = 1e9, db = 1e9;\n        for (auto [cx, cy] : cornerList) {\n            da = min(da, manhattan(humans[a].x, humans[a].y, cx, cy));\n            db = min(db, manhattan(humans[b].x, humans[b].y, cx, cy));\n        }\n        return da > db;\n    });\n\n    for (int k = 0; k < campers; k++) {\n        int id = ids[k];\n        pair<int,int> best = cornerList[0];\n        int bd = 1e9;\n        for (auto c : cornerList) {\n            int d = manhattan(humans[id].x, humans[id].y, c.first, c.second);\n            if (d < bd) {\n                bd = d;\n                best = c;\n            }\n        }\n        roles[id] = {1, best.first, best.second};\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        memset(pet_at, 0, sizeof(pet_at));\n        memset(human_at, 0, sizeof(human_at));\n        for (auto &p : pets) pet_at[p.x][p.y] = true;\n        for (auto &h : humans) human_at[h.x][h.y] = true;\n\n        string ans(M, '.');\n\n        // choose which side looks safer and build horizontal barrier there\n        int topPets = count_pets_top();\n        int bottomPets = N - topPets;\n        bool secureTop = (topPets <= bottomPets);\n\n        int barrierRow = secureTop ? 16 : 15;\n        int standRow   = secureTop ? 15 : 16;\n\n        vector<vector<int>> blocked_future(31, vector<int>(31, 0));\n        vector<pair<int,int>> move_reserved(M, {-1, -1});\n\n        // Phase 1: decide build actions first\n        for (int i = 0; i < M; i++) {\n            if (roles[i].type != 0) continue; // builders only\n\n            int x = humans[i].x, y = humans[i].y;\n            if (x != standRow) continue;\n\n            // If adjacent to target barrier cell, try to block it.\n            int d = (barrierRow == x + 1 ? 1 : (barrierRow == x - 1 ? 0 : -1));\n            if (d != -1) {\n                int bx = x + dx[d], by = y + dy[d];\n                if (!blocked_future[bx][by] && can_block_startturn(bx, by)) {\n                    ans[i] = BCH[d];\n                    blocked_future[bx][by] = 1;\n                }\n            }\n        }\n\n        // Phase 2: movement decisions, avoiding blocked_future\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue; // already building\n\n            int x = humans[i].x, y = humans[i].y;\n\n            if (roles[i].type == 1) {\n                // camper: go to corner, then mostly stay / opportunistic inward block\n                if (manhattan(x, y, roles[i].tx, roles[i].ty) <= 1) {\n                    // try to block inward direction\n                    vector<int> pref;\n                    if (x <= 2) pref.push_back(1);\n                    if (x >= 29) pref.push_back(0);\n                    if (y <= 2) pref.push_back(3);\n                    if (y >= 29) pref.push_back(2);\n\n                    bool done = false;\n                    for (int d : pref) {\n                        int bx = x + dx[d], by = y + dy[d];\n                        if (!inside(bx, by)) continue;\n                        if (blocked_future[bx][by]) continue;\n                        if (can_block_startturn(bx, by)) {\n                            ans[i] = BCH[d];\n                            blocked_future[bx][by] = 1;\n                            done = true;\n                            break;\n                        }\n                    }\n                    if (done) continue;\n                }\n\n                char c = move_toward_safe(i, roles[i].tx, roles[i].ty, blocked_future, move_reserved);\n                ans[i] = c;\n                int d = dir_from_move(c);\n                if (d != -1) move_reserved[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            // builder\n            if (x != standRow) {\n                char c = move_toward_safe(i, standRow, y, blocked_future, move_reserved);\n                ans[i] = c;\n                int d = dir_from_move(c);\n                if (d != -1) move_reserved[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            // on standRow: spread across columns\n            int targetY = 2 + (27 * i) / max(1, M - 1);\n\n            // prefer columns where barrier not yet blocked\n            if (inside(barrierRow, y) && !wall_[barrierRow][y] && !blocked_future[barrierRow][y]) {\n                // stay here for future block chance\n                ans[i] = '.';\n                continue;\n            }\n\n            char c = move_toward_safe(i, standRow, targetY, blocked_future, move_reserved);\n            ans[i] = c;\n            int d = dir_from_move(c);\n            if (d != -1) move_reserved[i] = {x + dx[d], y + dy[d]};\n        }\n\n        // Final legality sanitizer:\n        // 1) no move into existing wall\n        // 2) no move into blocked_future\n        // 3) no duplicate move destinations\n        {\n            set<pair<int,int>> used;\n            for (int i = 0; i < M; i++) {\n                int d = dir_from_move(ans[i]);\n                if (d == -1) continue;\n                int nx = humans[i].x + dx[d], ny = humans[i].y + dy[d];\n                bool bad = false;\n                if (!inside(nx, ny) || wall_[nx][ny] || blocked_future[nx][ny]) bad = true;\n                if (used.count({nx, ny})) bad = true;\n                if (bad) ans[i] = '.';\n                else used.insert({nx, ny});\n            }\n        }\n\n        cout << ans << '\\n';\n        cout.flush();\n\n        // reflect humans\n        for (int i = 0; i < M; i++) {\n            int md = dir_from_move(ans[i]);\n            int bd = dir_from_build(ans[i]);\n\n            if (md != -1) {\n                int nx = humans[i].x + dx[md], ny = humans[i].y + dy[md];\n                // keep local state consistent safely\n                if (inside(nx, ny) && !wall_[nx][ny] && !blocked_future[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            } else if (bd != -1) {\n                int bx = humans[i].x + dx[bd], by = humans[i].y + dy[bd];\n                if (inside(bx, by) && can_block_startturn(bx, by)) {\n                    wall_[bx][by] = true;\n                }\n            }\n        }\n\n        // read pets' actual moves\n        for (int i = 0; i < N; i++) {\n            string s;\n            cin >> s;\n            if (!cin) return 0;\n            if (s == \".\") continue;\n            for (char c : s) {\n                int d = dir_from_move(c);\n                if (d == -1) continue;\n                int nx = pets[i].x + dx[d], ny = pets[i].y + dy[d];\n                if (inside(nx, ny) && !wall_[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - 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 l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nint si, sj, ti, tj;\ndouble pforget;\nstring hs[H];\nstring vs[H - 1];\n\ninline int id(int i, int j) { return i * W + j; }\ninline pair<int,int> pos(int v) { return {v / W, v % W}; }\n\nint nxt[N][4]; // U,D,L,R\nchar dirch[4] = {'U','D','L','R'};\nint di[4] = {-1,1,0,0};\nint dj[4] = {0,0,-1,1};\n\nint targetDist[N];\nint targetNextDir[N]; // one step on shortest path to target, -1 for target/unreachable\nvector<int> revAdj[N];\n\ndouble eval_string(const string &s) {\n    vector<double> cur(N, 0.0), nxtp(N, 0.0);\n    int s0 = id(si, sj);\n    int tg = id(ti, tj);\n    cur[s0] = 1.0;\n    double ans = 0.0;\n    for (int t = 1; t <= (int)s.size(); t++) {\n        fill(nxtp.begin(), nxtp.end(), 0.0);\n        int d;\n        char c = s[t - 1];\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == tg) {\n                ans += pr * (401 - t);\n                continue;\n            }\n            nxtp[v] += pr * pforget;\n            int to = nxt[v][d];\n            nxtp[to] += pr * (1.0 - pforget);\n        }\n        cur.swap(nxtp);\n    }\n    // if already at target after all commands, not counted later; failure gives 0\n    return ans;\n}\n\nvector<int> bfs_dist_from_target() {\n    vector<int> dist(N, (int)1e9);\n    queue<int> q;\n    int tg = id(ti, tj);\n    dist[tg] = 0;\n    q.push(tg);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        auto [i, j] = pos(v);\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    return dist;\n}\n\nstring shortest_path_lexi() {\n    int S = id(si, sj), T = id(ti, tj);\n    vector<int> dist(N, (int)1e9), par(N, -1), pard(N, -1);\n    queue<int> q;\n    dist[S] = 0;\n    q.push(S);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == T) break;\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            if (to == v) continue;\n            if (dist[to] > dist[v] + 1) {\n                dist[to] = dist[v] + 1;\n                par[to] = v;\n                pard[to] = d;\n                q.push(to);\n            }\n        }\n    }\n    string res;\n    int cur = T;\n    while (cur != S) {\n        res.push_back(dirch[pard[cur]]);\n        cur = par[cur];\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nstring shortest_path_target_greedy_randomized() {\n    // randomized shortest path using targetDist\n    int cur = id(si, sj), tg = id(ti, tj);\n    string s;\n    while (cur != tg) {\n        vector<int> cand;\n        int best = targetDist[cur];\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[cur][d];\n            if (to == cur) continue;\n            if (targetDist[to] + 1 == targetDist[cur]) cand.push_back(d);\n        }\n        if (cand.empty()) break;\n        int d = cand[rng.next_int(0, (int)cand.size() - 1)];\n        s.push_back(dirch[d]);\n        cur = nxt[cur][d];\n    }\n    return s;\n}\n\nstring repeat_each(const string &base, int k) {\n    string s;\n    for (char c : base) {\n        for (int i = 0; i < k; i++) {\n            if ((int)s.size() < MAXL) s.push_back(c);\n        }\n    }\n    return s;\n}\n\nstring build_attractor_suffix(int len) {\n    // Construct a generic target-directed suffix:\n    // at each step choose direction that decreases shortest distance for the largest total mass\n    // approximated by global usefulness count.\n    vector<array<int,4>> improve(N);\n    for (int v = 0; v < N; v++) {\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            improve[v][d] = (targetDist[to] < targetDist[v]) ? 1 : 0;\n        }\n    }\n    string suf;\n    vector<double> cur(N, 0.0), nxtp(N, 0.0);\n    cur[id(si, sj)] = 1.0;\n    int tg = id(ti, tj);\n\n    // First simulate empty prefix? Here we just choose a good generic suffix via rolling optimization.\n    for (int step = 0; step < len; step++) {\n        double bestScore = -1;\n        int bestD = 0;\n        for (int d = 0; d < 4; d++) {\n            double sc = 0;\n            for (int v = 0; v < N; v++) {\n                if (v == tg) continue;\n                sc += cur[v] * improve[v][d];\n            }\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestD = d;\n            }\n        }\n        suf.push_back(dirch[bestD]);\n\n        fill(nxtp.begin(), nxtp.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == tg) {\n                nxtp[v] += pr;\n                continue;\n            }\n            nxtp[v] += pr * pforget;\n            int to = nxt[v][bestD];\n            nxtp[to] += pr * (1.0 - pforget);\n        }\n        cur.swap(nxtp);\n    }\n    return suf;\n}\n\nstring build_candidate_from_base(const string &base) {\n    string best = base;\n    double bestVal = eval_string(best);\n\n    for (int k = 1; k <= 8; k++) {\n        string s = repeat_each(base, k);\n        int rem = MAXL - (int)s.size();\n        if (rem > 0) {\n            string suf = build_attractor_suffix(rem);\n            s += suf;\n        }\n        double val = eval_string(s);\n        if (val > bestVal) {\n            bestVal = val;\n            best = s;\n        }\n    }\n    return best;\n}\n\nstring mutate(const string &s) {\n    string t = s;\n    int op = rng.next_int(0, 99);\n\n    if (op < 30 && !t.empty()) {\n        // change one char\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n    } else if (op < 55 && (int)t.size() < MAXL) {\n        // insert\n        int i = rng.next_int(0, (int)t.size());\n        char c = dirch[rng.next_int(0, 3)];\n        t.insert(t.begin() + i, c);\n    } else if (op < 70 && !t.empty()) {\n        // erase\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t.erase(t.begin() + i);\n    } else if (op < 85 && !t.empty()) {\n        // duplicate segment\n        int l = rng.next_int(0, (int)t.size() - 1);\n        int r = rng.next_int(l, min((int)t.size() - 1, l + 7));\n        string seg = t.substr(l, r - l + 1);\n        if ((int)t.size() + (int)seg.size() <= MAXL) {\n            int pos = rng.next_int(0, (int)t.size());\n            t.insert(pos, seg);\n        }\n    } else if (!t.empty()) {\n        // local target-biased rewrite\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n        if (i + 1 < (int)t.size() && rng.next_double() < 0.5) t[i + 1] = dirch[rng.next_int(0, 3)];\n    }\n\n    if ((int)t.size() > MAXL) t.resize(MAXL);\n    return t;\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 < H; i++) cin >> hs[i];\n    for (int i = 0; i < H - 1; i++) cin >> vs[i];\n\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {\n        int v = id(i, j);\n        // U\n        if (i == 0 || vs[i - 1][j] == '1') nxt[v][0] = v;\n        else nxt[v][0] = id(i - 1, j);\n        // D\n        if (i == H - 1 || vs[i][j] == '1') nxt[v][1] = v;\n        else nxt[v][1] = id(i + 1, j);\n        // L\n        if (j == 0 || hs[i][j - 1] == '1') nxt[v][2] = v;\n        else nxt[v][2] = id(i, j - 1);\n        // R\n        if (j == W - 1 || hs[i][j] == '1') nxt[v][3] = v;\n        else nxt[v][3] = id(i, j + 1);\n    }\n\n    auto dist = bfs_dist_from_target();\n    for (int v = 0; v < N; v++) targetDist[v] = dist[v];\n\n    for (int v = 0; v < N; v++) {\n        targetNextDir[v] = -1;\n        int best = targetDist[v];\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            if (to != v && targetDist[to] < best) {\n                best = targetDist[to];\n                targetNextDir[v] = d;\n            }\n        }\n    }\n\n    Timer timer;\n\n    vector<string> seeds;\n    string sp = shortest_path_lexi();\n    seeds.push_back(sp);\n    for (int it = 0; it < 20; it++) {\n        seeds.push_back(shortest_path_target_greedy_randomized());\n    }\n\n    string best = sp;\n    double bestVal = eval_string(best);\n\n    for (auto &base : seeds) {\n        string cand = build_candidate_from_base(base);\n        double val = eval_string(cand);\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n    }\n\n    // Simulated annealing / hill climbing\n    string cur = best;\n    double curVal = bestVal;\n\n    const double TL = 1.92;\n    int iter = 0;\n    while (true) {\n        double tm = timer.elapsed();\n        if (tm > TL) break;\n        iter++;\n\n        string nxts = mutate(cur);\n        double nv = eval_string(nxts);\n\n        double progress = tm / TL;\n        double temp = 30.0 * (1.0 - progress) + 1e-6;\n        double diff = nv - curVal;\n        if (diff >= 0 || rng.next_double() < exp(diff / temp)) {\n            cur = nxts;\n            curVal = nv;\n            if (nv > bestVal) {\n                bestVal = nv;\n                best = nxts;\n            }\n        }\n\n        // occasional restart near best\n        if ((iter % 500) == 0 && rng.next_double() < 0.3) {\n            cur = best;\n            curVal = bestVal;\n        }\n    }\n\n    if (best.empty()) best = sp;\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n    cout << best << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int NN = N * N;\n\nstatic const int di[4] = {0, -1, 0, 1}; // L U R D\nstatic const int dj[4] = {-1, 0, 1, 0};\n\nstatic const int TO[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\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\ninline int rotTile(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (t <= 3) t = (t + 1) & 3;\n        else if (t <= 5) t = 9 - t;   // 4 <-> 5\n        else t = 13 - t;              // 6 <-> 7\n    }\n    return t;\n}\n\ninline int maskOfTile(int t) {\n    int m = 0;\n    for (int d = 0; d < 4; d++) {\n        if (TO[t][d] != -1) m |= (1 << d);\n    }\n    return m;\n}\n\nstruct Solver {\n    array<string, N> s;\n    int base[N][N];\n    int rotTileId[N][N][4];\n    int rotMask[N][N][4];\n\n    mt19937 rng;\n\n    Solver() : rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void readInput() {\n        for (int i = 0; i < N; i++) {\n            cin >> s[i];\n            for (int j = 0; j < N; j++) {\n                base[i][j] = s[i][j] - '0';\n                for (int r = 0; r < 4; r++) {\n                    rotTileId[i][j][r] = rotTile(base[i][j], r);\n                    rotMask[i][j][r] = maskOfTile(rotTileId[i][j][r]);\n                }\n            }\n        }\n    }\n\n    long long exactScore(const array<unsigned char, NN>& rot) {\n        static int tile[N][N];\n        static unsigned char vis[N][N][4];\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            tile[i][j] = rotTileId[i][j][rot[i * N + j]];\n        }\n        memset(vis, 0, sizeof(vis));\n\n        int best1 = 0, best2 = 0;\n\n        for (int si = 0; si < N; si++) for (int sj = 0; sj < N; sj++) for (int sd = 0; sd < 4; sd++) {\n            if (vis[si][sj][sd]) continue;\n\n            int i = si, j = sj, d = sd;\n            int len = 0;\n            bool ok = true;\n\n            while (true) {\n                if (vis[i][j][d]) {\n                    ok = false;\n                    break;\n                }\n                vis[i][j][d] = 1;\n\n                int d2 = TO[tile[i][j]][d];\n                if (d2 == -1) {\n                    ok = false;\n                    break;\n                }\n                i += di[d2];\n                j += dj[d2];\n                if (i < 0 || i >= N || j < 0 || j >= N) {\n                    ok = false;\n                    break;\n                }\n                d = (d2 + 2) & 3;\n                ++len;\n\n                if (i == si && j == sj && d == sd) break;\n                if (len > 4 * NN + 5) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) {\n                if (len > best1) {\n                    best2 = best1;\n                    best1 = len;\n                } else if (len > best2) {\n                    best2 = len;\n                }\n            }\n        }\n\n        if (best2 == 0) return 0;\n        return 1LL * best1 * best2;\n    }\n\n    inline int cellContribution(const array<unsigned char, NN>& rot, int i, int j) const {\n        int m = rotMask[i][j][rot[i * N + j]];\n        int sc = 0;\n\n        // count only right and down neighbors to avoid double counting\n        if (j + 1 < N) {\n            int m2 = rotMask[i][j + 1][rot[i * N + (j + 1)]];\n            int a = (m >> 2) & 1; // right\n            int b = (m2 >> 0) & 1; // left\n            if (a == b) sc += a ? 1 : 0;\n        } else {\n            if ((m >> 2) & 1) sc -= 1;\n        }\n\n        if (i + 1 < N) {\n            int m2 = rotMask[i + 1][j][rot[(i + 1) * N + j]];\n            int a = (m >> 3) & 1; // down\n            int b = (m2 >> 1) & 1; // up\n            if (a == b) sc += a ? 1 : 0;\n        } else {\n            if ((m >> 3) & 1) sc -= 1;\n        }\n\n        // boundary penalties for left/up are counted here\n        if (j == 0 && ((m >> 0) & 1)) sc -= 1;\n        if (i == 0 && ((m >> 1) & 1)) sc -= 1;\n\n        return sc;\n    }\n\n    int localScore(const array<unsigned char, NN>& rot) const {\n        int sc = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            sc += cellContribution(rot, i, j);\n        }\n        return sc;\n    }\n\n    inline int affectedLocal(const array<unsigned char, NN>& rot, int i, int j) const {\n        int sc = 0;\n        for (int ni = max(0, i - 1); ni <= min(N - 1, i + 1); ni++) {\n            for (int nj = max(0, j - 1); nj <= min(N - 1, j + 1); nj++) {\n                sc += cellContribution(rot, ni, nj);\n            }\n        }\n        return sc;\n    }\n\n    array<unsigned char, NN> makeInitial(int type) {\n        array<unsigned char, NN> rot{};\n        if (type == 0) {\n            rot.fill(0);\n        } else if (type == 1) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = (i + j) & 3;\n        } else if (type == 2) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = i & 3;\n        } else if (type == 3) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = j & 3;\n        } else {\n            for (int k = 0; k < NN; k++) rot[k] = rng() & 3;\n        }\n        return rot;\n    }\n\n    void optimizeLocal(array<unsigned char, NN>& rot, Timer& timer, double endTime) {\n        int cur = localScore(rot);\n\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n\n        // greedy passes\n        while (timer.elapsed() < endTime) {\n            bool improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int idx : ord) {\n                if (timer.elapsed() >= endTime) return;\n                int i = idx / N, j = idx % N;\n                int before = affectedLocal(rot, i, j);\n                unsigned char old = rot[idx];\n                int bestDelta = 0;\n                unsigned char bestR = old;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int after = affectedLocal(rot, i, j);\n                    int delta = after - before;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = old;\n                if (bestDelta > 0) {\n                    rot[idx] = bestR;\n                    cur += bestDelta;\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n\n        // short annealing / random walk on local objective\n        double startT = 1.5, endT = 0.01;\n        while (timer.elapsed() < endTime) {\n            double prog = timer.elapsed() / max(endTime, 1e-9);\n            double temp = startT * pow(endT / startT, prog);\n\n            int idx = rng() % NN;\n            int i = idx / N, j = idx % N;\n            unsigned char old = rot[idx];\n            unsigned char nr = rng() & 3;\n            if (nr == old) continue;\n\n            int before = affectedLocal(rot, i, j);\n            rot[idx] = nr;\n            int after = affectedLocal(rot, i, j);\n            int delta = after - before;\n\n            if (delta >= 0) {\n                cur += delta;\n            } else {\n                double prob = exp((double)delta / temp);\n                if ((double)uniform_real_distribution<double>(0.0, 1.0)(rng) < prob) {\n                    cur += delta;\n                } else {\n                    rot[idx] = old;\n                }\n            }\n        }\n    }\n\n    void optimizeExact(array<unsigned char, NN>& rot, long long& bestSc, Timer& timer, double endTime) {\n        bestSc = exactScore(rot);\n        int curLocal = localScore(rot);\n\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n\n        while (timer.elapsed() < endTime) {\n            bool improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n\n            for (int idx : ord) {\n                if (timer.elapsed() >= endTime) return;\n                int i = idx / N, j = idx % N;\n                unsigned char old = rot[idx];\n                int beforeLocal = affectedLocal(rot, i, j);\n\n                long long bestMoveScore = bestSc;\n                int bestMoveLocalDelta = 0;\n                unsigned char bestR = old;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int afterLocal = affectedLocal(rot, i, j);\n                    int localDelta = afterLocal - beforeLocal;\n\n                    // Only spend exact evaluation on non-terrible local moves\n                    if (localDelta >= -1) {\n                        long long sc = exactScore(rot);\n                        if (sc > bestMoveScore || (sc == bestMoveScore && localDelta > bestMoveLocalDelta)) {\n                            bestMoveScore = sc;\n                            bestMoveLocalDelta = localDelta;\n                            bestR = nr;\n                        }\n                    }\n                }\n\n                rot[idx] = old;\n                if (bestR != old) {\n                    rot[idx] = bestR;\n                    bestSc = bestMoveScore;\n                    curLocal += bestMoveLocalDelta;\n                    improved = true;\n                }\n            }\n\n            if (!improved) {\n                // kick guided by local objective\n                array<unsigned char, NN> backup = rot;\n                long long backupScore = bestSc;\n                int backupLocal = curLocal;\n\n                int changes = 6 + (rng() % 10);\n                for (int t = 0; t < changes; t++) {\n                    int idx = rng() % NN;\n                    int i = idx / N, j = idx % N;\n                    int before = affectedLocal(rot, i, j);\n                    unsigned char bestR = rot[idx];\n                    int bestDelta = INT_MIN;\n                    for (unsigned char nr = 0; nr < 4; nr++) {\n                        rot[idx] = nr;\n                        int after = affectedLocal(rot, i, j);\n                        int delta = after - before;\n                        if (delta > bestDelta) {\n                            bestDelta = delta;\n                            bestR = nr;\n                        }\n                    }\n                    rot[idx] = bestR;\n                }\n\n                curLocal = localScore(rot);\n                long long sc = exactScore(rot);\n                if (sc >= bestSc) {\n                    bestSc = sc;\n                } else {\n                    rot = backup;\n                    bestSc = backupScore;\n                    curLocal = backupLocal;\n                    // random perturbation if greedy kick failed\n                    for (int t = 0; t < 4; t++) {\n                        int idx = rng() % NN;\n                        rot[idx] = rng() & 3;\n                    }\n                    curLocal = localScore(rot);\n                    bestSc = exactScore(rot);\n                }\n            }\n        }\n    }\n\n    void solve() {\n        Timer timer;\n        const double TL = 1.95;\n\n        array<unsigned char, NN> globalBest{};\n        globalBest.fill(0);\n        long long globalBestScore = exactScore(globalBest);\n\n        int trial = 0;\n        while (timer.elapsed() < TL) {\n            array<unsigned char, NN> rot = makeInitial(trial < 4 ? trial : 4 + (trial % 8));\n\n            double rem = TL - timer.elapsed();\n            if (rem <= 0.0) break;\n\n            double t1 = min(0.10, rem * 0.45);\n            optimizeLocal(rot, timer, timer.elapsed() + t1);\n\n            rem = TL - timer.elapsed();\n            if (rem <= 0.0) break;\n\n            long long sc = 0;\n            double t2 = min(0.22, rem * 0.80);\n            optimizeExact(rot, sc, timer, timer.elapsed() + t2);\n\n            if (sc > globalBestScore) {\n                globalBestScore = sc;\n                globalBest = rot;\n            }\n            trial++;\n        }\n\n        string ans(NN, '0');\n        for (int i = 0; i < NN; i++) ans[i] = char('0' + globalBest[i]);\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.readInput();\n    solver.solve();\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\nstatic constexpr int DI[4] = {-1, 1, 0, 0};\nstatic constexpr int DJ[4] = {0, 0, -1, 1};\nstatic constexpr char DC[4] = {'U', 'D', 'L', 'R'};\n\nint N, Tlim;\nvector<unsigned char> init_board;\nint init_empty;\n\ninline int opp(int d) {\n    return d ^ 1;\n}\n\ninline int c2d(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\ninline bool can_move(int empty_pos, int d) {\n    int i = empty_pos / N, j = empty_pos % N;\n    int ni = i + DI[d], nj = j + DJ[d];\n    return 0 <= ni && ni < N && 0 <= nj && nj < N;\n}\n\ninline void apply_move(vector<unsigned char>& board, int& empty_pos, int d) {\n    int ei = empty_pos / N, ej = empty_pos % N;\n    int ni = ei + DI[d], nj = ej + DJ[d];\n    int np = ni * N + nj;\n    swap(board[empty_pos], board[np]);\n    empty_pos = np;\n}\n\nint evaluate_board(const vector<unsigned char>& board) {\n    int V = N * N;\n    static int g[100][4];\n    static int deg[100];\n    static unsigned char alive[100];\n    static unsigned char vis[100];\n\n    for (int p = 0; p < V; ++p) {\n        deg[p] = 0;\n        alive[p] = (board[p] != 0);\n        vis[p] = 0;\n    }\n\n    auto has = [&](int mask, int bit) -> bool { return (mask & bit) != 0; };\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int p = i * N + j;\n            if (!alive[p]) continue;\n            int m = board[p];\n            if (i + 1 < N) {\n                int q = (i + 1) * N + j;\n                if (alive[q] && has(m, 8) && has(board[q], 2)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                }\n            }\n            if (j + 1 < N) {\n                int q = i * N + (j + 1);\n                if (alive[q] && has(m, 4) && has(board[q], 1)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                }\n            }\n        }\n    }\n\n    int best = 0;\n    int q[100];\n    for (int s = 0; s < V; ++s) {\n        if (!alive[s] || vis[s]) continue;\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = 1;\n        int vc = 0;\n        int sumdeg = 0;\n        while (head < tail) {\n            int v = q[head++];\n            ++vc;\n            sumdeg += deg[v];\n            for (int k = 0; k < deg[v]; ++k) {\n                int to = g[v][k];\n                if (!vis[to]) {\n                    vis[to] = 1;\n                    q[tail++] = to;\n                }\n            }\n        }\n        int ec = sumdeg / 2;\n        if (ec == vc - 1) best = max(best, vc);\n    }\n    return best;\n}\n\nstruct Candidate {\n    string ops;       // full legal sequence\n    int bestScore;    // best score among prefixes\n    int bestLen;      // prefix length achieving bestScore (shortest such)\n};\n\nmt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\nCandidate evaluate_sequence(const string& ops) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n\n    Candidate res;\n    res.ops = ops;\n    res.bestScore = evaluate_board(board);\n    res.bestLen = 0;\n\n    for (int i = 0; i < (int)ops.size(); ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) {\n            res.ops.resize(i);\n            break;\n        }\n        apply_move(board, empty, d);\n        int sc = evaluate_board(board);\n        if (sc > res.bestScore || (sc == res.bestScore && i + 1 < res.bestLen)) {\n            res.bestScore = sc;\n            res.bestLen = i + 1;\n        }\n    }\n    return res;\n}\n\nbool better(const Candidate& a, const Candidate& b) {\n    if (a.bestScore != b.bestScore) return a.bestScore > b.bestScore;\n    return a.bestLen < b.bestLen;\n}\n\nstring random_legal_suffix(int empty, int maxAdd, int prevDir = -1, bool prefer_no_back = true) {\n    string s;\n    s.reserve(maxAdd);\n    for (int step = 0; step < maxAdd; ++step) {\n        int cand[4], cnt = 0;\n        for (int d = 0; d < 4; ++d) {\n            if (!can_move(empty, d)) continue;\n            if (prefer_no_back && prevDir != -1 && d == opp(prevDir)) continue;\n            cand[cnt++] = d;\n        }\n        if (cnt == 0) {\n            for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n        }\n        int d = cand[rng() % cnt];\n        s.push_back(DC[d]);\n        int ei = empty / N, ej = empty % N;\n        int ni = ei + DI[d], nj = ej + DJ[d];\n        empty = ni * N + nj;\n        prevDir = d;\n    }\n    return s;\n}\n\nvoid replay_prefix(const string& ops, int upto, vector<unsigned char>& board, int& empty, int& prevDir) {\n    board = init_board;\n    empty = init_empty;\n    prevDir = -1;\n    for (int i = 0; i < upto; ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) break;\n        apply_move(board, empty, d);\n        prevDir = d;\n    }\n}\n\nCandidate make_random_candidate() {\n    uniform_int_distribution<int> lenDist(0, Tlim);\n    int L = lenDist(rng);\n    string ops = random_legal_suffix(init_empty, L, -1, true);\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_cut_regrow(const Candidate& base) {\n    int L = (int)base.ops.size();\n    int cut = 0;\n    if (L > 0) {\n        // Bias around useful prefix but allow broad variation\n        int mode = rng() % 3;\n        if (mode == 0) {\n            uniform_int_distribution<int> dist(0, L);\n            cut = dist(rng);\n        } else if (mode == 1) {\n            int lo = max(0, base.bestLen - 10);\n            int hi = min(L, base.bestLen + 10);\n            uniform_int_distribution<int> dist(lo, hi);\n            cut = dist(rng);\n        } else {\n            uniform_int_distribution<int> dist(0, min(L, base.bestLen));\n            cut = dist(rng);\n        }\n    }\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, cut, board, empty, prevDir);\n\n    int rem = Tlim - cut;\n    uniform_int_distribution<int> addDist(0, rem);\n    int add = addDist(rng);\n\n    string ops = base.ops.substr(0, cut);\n    ops += random_legal_suffix(empty, add, prevDir, true);\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_edit(const Candidate& base) {\n    if (base.ops.empty()) return make_random_candidate();\n    int L = (int)base.ops.size();\n    int pos = rng() % L;\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, pos, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, pos);\n\n    // choose a possibly different legal move\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) {\n        if (!can_move(empty, d)) continue;\n        cand[cnt++] = d;\n    }\n    int nd = cand[rng() % cnt];\n    ops.push_back(DC[nd]);\n    apply_move(board, empty, nd);\n    prevDir = nd;\n\n    int remOld = L - pos - 1;\n    int remCap = Tlim - (int)ops.size();\n\n    // sometimes reuse some of suffix length, sometimes not\n    int newLen = min(remCap, remOld + (int)(rng() % 7) - 3);\n    if (newLen < 0) newLen = 0;\n\n    ops += random_legal_suffix(empty, newLen, prevDir, true);\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_insert_delete(const Candidate& base) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n    int prevDir = -1;\n\n    string ops;\n    ops.reserve(Tlim);\n\n    int i = 0;\n    while (i < (int)base.ops.size() && (int)ops.size() < Tlim) {\n        // random insertion before current move\n        if ((rng() % 100) < 8 && (int)ops.size() < Tlim) {\n            int cand[4], cnt = 0;\n            for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n            int d = cand[rng() % cnt];\n            ops.push_back(DC[d]);\n            apply_move(board, empty, d);\n            prevDir = d;\n        }\n\n        // maybe delete current move\n        if ((rng() % 100) < 15) {\n            ++i;\n            continue;\n        }\n\n        int d = c2d(base.ops[i]);\n        if (!can_move(empty, d)) break;\n        ops.push_back(base.ops[i]);\n        apply_move(board, empty, d);\n        prevDir = d;\n        ++i;\n    }\n\n    // small random tail\n    int rem = Tlim - (int)ops.size();\n    int add = rem > 0 ? (rng() % (min(rem, 20) + 1)) : 0;\n    ops += random_legal_suffix(empty, add, prevDir, true);\n\n    return evaluate_sequence(ops);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    init_board.assign(N * N, 0);\n\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            char c = s[j];\n            int v = ('0' <= c && c <= '9') ? c - '0' : 10 + (c - 'a');\n            init_board[i * N + j] = (unsigned char)v;\n            if (v == 0) init_empty = i * N + j;\n        }\n    }\n\n    Timer timer;\n    const double TL = 2.90;\n\n    const int BEAM = 12;\n    vector<Candidate> pool;\n    pool.reserve(BEAM * 2 + 10);\n\n    Candidate best;\n    best.ops = \"\";\n    best.bestScore = evaluate_board(init_board);\n    best.bestLen = 0;\n\n    // initial population\n    pool.push_back(best);\n    while ((int)pool.size() < BEAM && timer.elapsed() < 0.3) {\n        Candidate c = make_random_candidate();\n        if (better(c, best)) best = c;\n        pool.push_back(c);\n    }\n\n    auto shrink_pool = [&]() {\n        sort(pool.begin(), pool.end(), better);\n        vector<Candidate> np;\n        for (auto& c : pool) {\n            bool dup = false;\n            for (auto& x : np) {\n                if (c.bestScore == x.bestScore && c.bestLen == x.bestLen && c.ops == x.ops) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) np.push_back(c);\n            if ((int)np.size() >= BEAM) break;\n        }\n        pool.swap(np);\n        if (!pool.empty() && better(pool[0], best)) best = pool[0];\n    };\n\n    shrink_pool();\n\n    while (timer.elapsed() < TL) {\n        int idx = rng() % pool.size();\n        // bias to better individuals\n        if ((rng() & 1) == 0) idx = min(idx, (int)pool.size() - 1 - (int)(rng() % min(4, (int)pool.size())));\n\n        Candidate cand;\n        int typ = rng() % 100;\n        if (typ < 18) cand = make_random_candidate();\n        else if (typ < 60) cand = mutate_cut_regrow(pool[idx]);\n        else if (typ < 85) cand = mutate_edit(pool[idx]);\n        else cand = mutate_insert_delete(pool[idx]);\n\n        pool.push_back(cand);\n        if (better(cand, best)) best = cand;\n\n        if ((int)pool.size() >= BEAM * 2) shrink_pool();\n    }\n\n    cout << best.ops.substr(0, best.bestLen) << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nstruct Candidate {\n    int score = -1;\n    double theta = 0.0;\n    vector<int> groups; // consecutive segment sizes summing to N\n};\n\nstatic const double R = 10000.0;\nstatic const long long LIM = 1000000000LL;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    vector<int> a(11);\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // Candidate directions.\n    // Enough diversity while keeping runtime safe.\n    int M = 180;\n\n    Candidate best;\n\n    vector<int> idx(N);\n    iota(idx.begin(), idx.end(), 0);\n\n    vector<double> proj(N);\n    vector<int> ord(N);\n\n    for (int it = 0; it < M; it++) {\n        double theta = M_PI * it / M; // [0, pi)\n        double c = cos(theta), s = sin(theta);\n\n        for (int i = 0; i < N; i++) {\n            proj[i] = p[i].x * c + p[i].y * s;\n            ord[i] = i;\n        }\n        sort(ord.begin(), ord.end(), [&](int i, int j) {\n            if (proj[i] != proj[j]) return proj[i] < proj[j];\n            return i < j;\n        });\n\n        // Try a few prefix leftovers. Prefix of length off is made junk by merging into first group.\n        // Then DP on remaining suffix using group sizes 1..10.\n        for (int off = 0; off <= min(10, N); off++) {\n            int rem = N - off;\n            if (rem <= 0) continue;\n\n            // dp[pos][used1..used10] is impossible; too large.\n            // Instead, because each useful group size d only gives gain up to a[d],\n            // we can greedily reward first a[d] groups of size d encountered.\n            // To optimize globally, keep counts of used sizes in state is too big.\n            //\n            // Simpler surrogate:\n            // value of a group of size d is w[d], where rarer / demanded sizes get more weight.\n            // Then after reconstructing, actual score is min(count[d], a[d]).\n            //\n            // We use lexicographic-ish weights favoring demanded sizes:\n            static double w[11];\n            for (int d = 1; d <= 10; d++) {\n                // Positive weight only if there is demand.\n                // Slightly prefer smaller d as they are easier to realize many times.\n                w[d] = (a[d] > 0 ? (1000.0 + 10.0 * a[d] - d) : 0.0);\n            }\n\n            vector<double> dp(rem + 1, -1e100);\n            vector<int> prv(rem + 1, -1), take(rem + 1, -1);\n            dp[0] = 0.0;\n\n            for (int i = 0; i < rem; i++) {\n                if (dp[i] < -1e90) continue;\n                for (int d = 1; d <= 10; d++) {\n                    if (i + d <= rem) {\n                        double ndp = dp[i] + w[d];\n                        if (ndp > dp[i + d]) {\n                            dp[i + d] = ndp;\n                            prv[i + d] = i;\n                            take[i + d] = d;\n                        }\n                    }\n                }\n            }\n\n            // Since rem can always be fully tiled by 1..10, use rem.\n            vector<int> gs_rev;\n            int cur = rem;\n            while (cur > 0) {\n                gs_rev.push_back(take[cur]);\n                cur = prv[cur];\n            }\n            reverse(gs_rev.begin(), gs_rev.end());\n\n            vector<int> groups;\n            if (off > 0) {\n                if (!gs_rev.empty()) gs_rev[0] += off;\n                else groups.push_back(off);\n            }\n            for (int x : gs_rev) groups.push_back(x);\n\n            // If too many cuts, reject. (#pieces = groups.size(), cuts = pieces-1)\n            if ((int)groups.size() - 1 > K) continue;\n\n            vector<int> cnt(11, 0);\n            for (int g : groups) if (1 <= g && g <= 10) cnt[g]++;\n            int realScore = 0;\n            for (int d = 1; d <= 10; d++) realScore += min(a[d], cnt[d]);\n\n            if (realScore > best.score) {\n                best.score = realScore;\n                best.theta = theta;\n                best.groups = groups;\n            }\n        }\n    }\n\n    // Fallback: all singletons for first min(N,101) pieces via one direction.\n    if (best.score < 0) {\n        best.theta = 0.0;\n        best.groups.clear();\n        int rem = N;\n        while (rem > 0 && (int)best.groups.size() < K) {\n            best.groups.push_back(1);\n            rem--;\n        }\n        best.groups.push_back(rem);\n    }\n\n    double c = cos(best.theta), s = sin(best.theta);\n\n    for (int i = 0; i < N; i++) {\n        proj[i] = p[i].x * c + p[i].y * s;\n        ord[i] = i;\n    }\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (proj[i] != proj[j]) return proj[i] < proj[j];\n        return i < j;\n    });\n\n    vector<double> alphas;\n    int pref = 0;\n    for (int i = 0; i + 1 < (int)best.groups.size(); i++) {\n        pref += best.groups[i];\n        // cut between ord[pref-1] and ord[pref]\n        double a1 = proj[ord[pref - 1]];\n        double a2 = proj[ord[pref]];\n        double alpha = (a1 + a2) * 0.5;\n        alphas.push_back(alpha);\n    }\n\n    // Build integer line representation for c x + s y = alpha.\n    // Point on line: alpha * (c, s)\n    // Direction along line: (-s, c)\n    // Use large scale, then round.\n    auto clampLL = [&](long long x) -> long long {\n        return max(-LIM, min(LIM, x));\n    };\n\n    cout << alphas.size() << '\\n';\n    const double T = 200000.0; // large enough\n    for (double alpha : alphas) {\n        double x0 = alpha * c;\n        double y0 = alpha * s;\n        double dx = -s, dy = c;\n\n        long long x1 = llround(x0 + T * dx);\n        long long y1 = llround(y0 + T * dy);\n        long long x2 = llround(x0 - T * dx);\n        long long y2 = llround(y0 - T * dy);\n\n        x1 = clampLL(x1);\n        y1 = clampLL(y1);\n        x2 = clampLL(x2);\n        y2 = clampLL(y2);\n\n        // Ensure distinct points.\n        if (x1 == x2 && y1 == y2) {\n            x2++;\n            if (x2 > LIM) x2 -= 2;\n        }\n\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\nstruct Op {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nstruct Candidate {\n    double score;\n    Op op;\n    bool operator<(const Candidate& other) const {\n        return score < other.score;\n    }\n};\n\nstruct Solver {\n    int N, M;\n    vector<pair<int,int>> initDots;\n    int c;\n    long long Ssum;\n\n    Solver(int N_, int M_, const vector<pair<int,int>>& pts): N(N_), M(M_), initDots(pts) {\n        c = (N - 1) / 2;\n        Ssum = 0;\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            long long dx = x - c, dy = y - c;\n            Ssum += dx * dx + dy * dy + 1;\n        }\n    }\n\n    int weight(int x, int y) const {\n        int dx = x - c, dy = y - c;\n        return dx * dx + dy * dy + 1;\n    }\n\n    struct State {\n        int N;\n        vector<vector<char>> dot;\n        vector<vector<char>> usedH, usedV, usedD1, usedD2;\n        vector<Op> ops;\n        vector<pair<int,int>> dots;\n        long long wsum = 0;\n\n        State(int N_=0): N(N_) {}\n    };\n\n    State initial_state() const {\n        State st(N);\n        st.dot.assign(N, vector<char>(N, 0));\n        st.usedH.assign(max(0, N - 1), vector<char>(N, 0));\n        st.usedV.assign(N, vector<char>(max(0, N - 1), 0));\n        st.usedD1.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        st.usedD2.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        for (auto [x, y] : initDots) {\n            st.dot[x][y] = 1;\n            st.dots.push_back({x, y});\n            st.wsum += weight(x, y);\n        }\n        return st;\n    }\n\n    bool inside(int x, int y) const {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    }\n\n    bool getSegUsed(const State& st, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            return st.usedV[x1][y1];\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            return st.usedH[x1][y1];\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            return st.usedD1[x1][y1];\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            return st.usedD2[x1][yl];\n        }\n    }\n\n    void setSegUsed(State& st, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            st.usedV[x1][y1] = 1;\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            st.usedH[x1][y1] = 1;\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            st.usedD1[x1][y1] = 1;\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            st.usedD2[x1][yl] = 1;\n        }\n    }\n\n    bool edge_clear_and_unused(const State& st, int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            if (getSegUsed(st, x, y, nx, ny)) return false;\n            if (t + 1 < len && st.dot[nx][ny]) return false;\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void mark_edge(State& st, int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            setSegUsed(st, x, y, nx, ny);\n            x = nx; y = ny;\n        }\n    }\n\n    bool legal_rect(const State& st, const Op& op) const {\n        int x1=op.x1,y1=op.y1,x2=op.x2,y2=op.y2,x3=op.x3,y3=op.y3,x4=op.x4,y4=op.y4;\n        if (!inside(x1,y1)||!inside(x2,y2)||!inside(x3,y3)||!inside(x4,y4)) return false;\n        if (st.dot[x1][y1]) return false;\n        if (!st.dot[x2][y2] || !st.dot[x3][y3] || !st.dot[x4][y4]) return false;\n\n        auto ok_edge = [&](int ax, int ay, int bx, int by) {\n            int dx = bx - ax, dy = by - ay;\n            if (dx == 0 && dy != 0) return true;\n            if (dy == 0 && dx != 0) return true;\n            if (abs(dx) == abs(dy) && dx != 0) return true;\n            return false;\n        };\n        if (!ok_edge(x1,y1,x2,y2) || !ok_edge(x2,y2,x3,y3) ||\n            !ok_edge(x3,y3,x4,y4) || !ok_edge(x4,y4,x1,y1)) return false;\n\n        int ax = x2 - x1, ay = y2 - y1;\n        int bx = x4 - x1, by = y4 - y1;\n        if (ax == 0 && ay == 0) return false;\n        if (bx == 0 && by == 0) return false;\n        if (ax * bx + ay * by != 0) return false;\n        if (x3 != x2 + bx || y3 != y2 + by) return false;\n        if (x3 != x4 + ax || y3 != y4 + ay) return false;\n\n        if (!edge_clear_and_unused(st, x1,y1,x2,y2)) return false;\n        if (!edge_clear_and_unused(st, x2,y2,x3,y3)) return false;\n        if (!edge_clear_and_unused(st, x3,y3,x4,y4)) return false;\n        if (!edge_clear_and_unused(st, x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void apply(State& st, const Op& op) const {\n        st.dot[op.x1][op.y1] = 1;\n        st.dots.push_back({op.x1, op.y1});\n        st.wsum += weight(op.x1, op.y1);\n        mark_edge(st, op.x1, op.y1, op.x2, op.y2);\n        mark_edge(st, op.x2, op.y2, op.x3, op.y3);\n        mark_edge(st, op.x3, op.y3, op.x4, op.y4);\n        mark_edge(st, op.x4, op.y4, op.x1, op.y1);\n        st.ops.push_back(op);\n    }\n\n    long long final_score_value(const State& st) const {\n        long long num = st.wsum;\n        double val = 1e6 * (double)(N * N) / (double)M * (double)num / (double)Ssum;\n        return llround(val);\n    }\n\n    // Enumerate candidates from triples/structure of existing points.\n    vector<Candidate> enumerate_candidates(const State& st, int mode, mt19937& rng, int capDots) const {\n        vector<Candidate> cand;\n        vector<pair<int,int>> pts = st.dots;\n\n        if ((int)pts.size() > capDots) {\n            shuffle(pts.begin(), pts.end(), rng);\n            pts.resize(capDots);\n        }\n\n        // group by x/y and diagonals for quicker generation\n        unordered_map<int, vector<int>> byX, byY, byD1, byD2;\n        byX.reserve(2 * pts.size() + 10);\n        byY.reserve(2 * pts.size() + 10);\n        byD1.reserve(2 * pts.size() + 10); // x-y\n        byD2.reserve(2 * pts.size() + 10); // x+y\n\n        for (auto [x, y] : pts) {\n            byX[x].push_back(y);\n            byY[y].push_back(x);\n            byD1[x - y].push_back(x); // store x\n            byD2[x + y].push_back(x); // store x\n        }\n\n        auto score_op = [&](const Op& op) -> double {\n            int w = weight(op.x1, op.y1);\n            int l1 = max(abs(op.x2-op.x1), abs(op.y2-op.y1));\n            int l2 = max(abs(op.x4-op.x1), abs(op.y4-op.y1));\n            int per = l1 + l2;\n\n            // estimated future potential: more outward is good, but small rectangles often unlock chains\n            double noise = uniform_real_distribution<double>(0.0, 1e-6)(rng);\n\n            if (mode == 0) return 2000.0 * w - 180.0 * per + noise;           // balanced\n            if (mode == 1) return 1200.0 * w - 300.0 * per + noise;           // small-first\n            if (mode == 2) return 3500.0 * w - 120.0 * per + noise;           // weight-heavy\n            if (mode == 3) return 1800.0 * w - 220.0 * per + 100.0*(w>weight(c,c)) + noise; // outward bias\n            return 2000.0 * w - 180.0 * per + noise;\n        };\n\n        // Axis-aligned:\n        // choose p2 and p4 sharing row/col with missing p1, with p3 existing.\n        for (auto [x2, y2] : pts) {\n            auto itx = byX.find(x2);\n            auto ity = byY.find(y2);\n            if (itx == byX.end() || ity == byY.end()) continue;\n\n            // Sample combinations to limit work\n            auto ys = itx->second;\n            auto xs = ity->second;\n            if ((int)ys.size() > 20) {\n                shuffle(ys.begin(), ys.end(), rng);\n                ys.resize(20);\n            }\n            if ((int)xs.size() > 20) {\n                shuffle(xs.begin(), xs.end(), rng);\n                xs.resize(20);\n            }\n\n            for (int y4 : ys) {\n                if (y4 == y2) continue;\n                for (int x1 : xs) {\n                    if (x1 == x2) continue;\n                    int y1 = y4;\n                    int x4 = x2, x3 = x1, y3 = y2;\n                    // Rectangle: p1=(x1,y1), p2=(x2,y1)? Need reorder carefully.\n\n                    // We want p2,p3,p4 occupied and p1 empty with order p1->p2->p3->p4.\n                    // Use occupied corners: A=(x2,y2), B=(x2,y4), C=(x1,y2), missing D=(x1,y4)\n                    // valid order D,B,A,C\n                    if (!inside(x1, y1)) continue;\n                    if (!st.dot[x2][y4] || !st.dot[x1][y2]) continue;\n                    Op op {x1,y1, x2,y4, x2,y2, x1,y2};\n                    if (legal_rect(st, op)) cand.push_back({score_op(op), op});\n                }\n            }\n        }\n\n        // Rotated 45-degree rectangles:\n        // For occupied p2 and p4 around missing p1:\n        // if a = p2-p1, b = p4-p1 perpendicular and |a_x|=|a_y|, |b_x|=|b_y|\n        // then p3 = p1+a+b.\n        for (auto [x2, y2] : pts) {\n            // p4 candidates on the perpendicular diagonals crossing (x2,y2)\n            // enumerate small set from matching diagonal families\n            // If a=(d,d) then b=(-d,d) or (d,-d). So p4 relative relation to p2 creates axis alignment in transformed basis.\n            // We directly construct by another occupied point p4 and infer p1.\n            for (auto [x4, y4] : pts) {\n                if (x2 == x4 && y2 == y4) continue;\n                int vx = x4 - x2, vy = y4 - y2;\n                // Diagonally opposite corners relation in rotated rectangle:\n                // p2 and p4 are adjacent-from-p1 points, so vectors a and b are perpendicular diag vectors.\n                // Thus both are diagonal vectors and dot(a,b)=0.\n                // infer p1 from a=p2-p1, b=p4-p1 => p1 = ?\n                // easier: require midpoint and square-like transformed basis not straightforward.\n                // Instead use p1 = p2 - rot90(b) where b=p4-p1 unknown, so use local vector generation around p2.\n            }\n        }\n\n        // Better rotated enumeration by vector from occupied point:\n        for (auto [x2, y2] : pts) {\n            // sample diagonal edge vectors\n            for (int d = 1; d <= min(8, N); d++) {\n                static const int sx[4] = {1,1,-1,-1};\n                static const int sy[4] = {1,-1,1,-1};\n                for (int k = 0; k < 4; k++) {\n                    int ax = sx[k] * d, ay = sy[k] * d;\n                    // p2 = p1 + a => p1 = p2 - a\n                    int x1 = x2 - ax, y1 = y2 - ay;\n                    // b = (-ay, ax)\n                    int bx = -ay, by = ax;\n                    int x4 = x1 + bx, y4 = y1 + by;\n                    int x3 = x2 + bx, y3 = y2 + by;\n                    Op op{x1,y1,x2,y2,x3,y3,x4,y4};\n                    if (inside(x1,y1) && inside(x3,y3) && inside(x4,y4) && legal_rect(st, op)) {\n                        cand.push_back({score_op(op), op});\n                    }\n                    // other perpendicular\n                    bx = ay; by = -ax;\n                    x4 = x1 + bx; y4 = y1 + by;\n                    x3 = x2 + bx; y3 = y2 + by;\n                    op = Op{x1,y1,x2,y2,x3,y3,x4,y4};\n                    if (inside(x1,y1) && inside(x3,y3) && inside(x4,y4) && legal_rect(st, op)) {\n                        cand.push_back({score_op(op), op});\n                    }\n                }\n            }\n        }\n\n        // Deduplicate by new point + shape\n        sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b){\n            if (a.op.x1 != b.op.x1) return a.op.x1 < b.op.x1;\n            if (a.op.y1 != b.op.y1) return a.op.y1 < b.op.y1;\n            if (a.op.x2 != b.op.x2) return a.op.x2 < b.op.x2;\n            if (a.op.y2 != b.op.y2) return a.op.y2 < b.op.y2;\n            if (a.op.x3 != b.op.x3) return a.op.x3 < b.op.x3;\n            if (a.op.y3 != b.op.y3) return a.op.y3 < b.op.y3;\n            if (a.op.x4 != b.op.x4) return a.op.x4 < b.op.x4;\n            if (a.op.y4 != b.op.y4) return a.op.y4 < b.op.y4;\n            return a.score > b.score;\n        });\n        vector<Candidate> uniq;\n        uniq.reserve(cand.size());\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (i == 0 ||\n                memcmp(&cand[i].op, &cand[i-1].op, sizeof(Op)) != 0) {\n                uniq.push_back(cand[i]);\n            }\n        }\n\n        sort(uniq.begin(), uniq.end(), [](const Candidate& a, const Candidate& b){\n            return a.score > b.score;\n        });\n        if ((int)uniq.size() > 300) uniq.resize(300);\n        return uniq;\n    }\n\n    State run_one(int mode, uint64_t seed, double timeLimit, const Timer& timer) const {\n        mt19937 rng((uint32_t)seed);\n        State st = initial_state();\n\n        int stagnation = 0;\n        while (timer.elapsed() < timeLimit) {\n            int capDots = (timer.elapsed() < timeLimit * 0.6 ? 220 : 140);\n            auto cand = enumerate_candidates(st, mode, rng, capDots);\n            bool moved = false;\n\n            int tryCount = min<int>(cand.size(), 40);\n            for (int i = 0; i < tryCount; i++) {\n                int idx;\n                if (mode == 1) {\n                    idx = i; // small-first deterministic\n                } else {\n                    int span = min<int>(tryCount, 8 + stagnation);\n                    idx = uniform_int_distribution<int>(0, max(0, span - 1))(rng);\n                }\n                if (idx >= (int)cand.size()) continue;\n                if (legal_rect(st, cand[idx].op)) {\n                    apply(st, cand[idx].op);\n                    moved = true;\n                    stagnation = 0;\n                    break;\n                }\n            }\n\n            if (!moved) {\n                stagnation++;\n                if (stagnation >= 3) break;\n            }\n        }\n        return st;\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    vector<pair<int,int>> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].first >> pts[i].second;\n\n    Timer timer;\n    Solver solver(N, M, pts);\n\n    vector<int> modes = {0, 1, 2, 3};\n    Solver::State best = solver.initial_state();\n    long long bestScore = solver.final_score_value(best);\n\n    // Multi-start within time budget\n    int iter = 0;\n    while (timer.elapsed() < 4.7) {\n        int mode = modes[iter % modes.size()];\n        uint64_t seed = 1234567ULL + 10007ULL * iter + 998244353ULL * mode;\n        double remain = 4.75 - timer.elapsed();\n        if (remain < 0.15) break;\n        double slice = min(remain, 0.18 + 0.02 * (iter < 8));\n        auto st = solver.run_one(mode, seed, timer.elapsed() + slice, timer);\n        long long sc = solver.final_score_value(st);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = move(st);\n        }\n        iter++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (auto &op : best.ops) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << ' '\n             << op.x3 << ' ' << op.y3 << ' '\n             << op.x4 << ' ' << op.y4 << '\\n';\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\n\nstruct Pos {\n    int r, c;\n};\n\nstruct Board {\n    uint8_t a[N][N];\n\n    Board() { memset(a, 0, sizeof(a)); }\n\n    inline int occupied() const {\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cnt += (a[i][j] != 0);\n        return cnt;\n    }\n\n    inline void place_by_index(int p, int flavor) {\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) {\n                cnt++;\n                if (cnt == p) {\n                    a[i][j] = (uint8_t)flavor;\n                    return;\n                }\n            }\n        }\n        assert(false);\n    }\n\n    inline vector<Pos> empty_cells_ordered() const {\n        vector<Pos> res;\n        res.reserve(100 - occupied());\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) res.push_back({i, j});\n        }\n        return res;\n    }\n\n    inline Board tilted(char dir) const {\n        Board b;\n        if (dir == 'L') {\n            for (int i = 0; i < N; i++) {\n                int t = 0;\n                for (int j = 0; j < N; j++) if (a[i][j]) b.a[i][t++] = a[i][j];\n            }\n        } else if (dir == 'R') {\n            for (int i = 0; i < N; i++) {\n                int t = N - 1;\n                for (int j = N - 1; j >= 0; j--) if (a[i][j]) b.a[i][t--] = a[i][j];\n            }\n        } else if (dir == 'F') {\n            for (int j = 0; j < N; j++) {\n                int t = 0;\n                for (int i = 0; i < N; i++) if (a[i][j]) b.a[t++][j] = a[i][j];\n            }\n        } else if (dir == 'B') {\n            for (int j = 0; j < N; j++) {\n                int t = N - 1;\n                for (int i = N - 1; i >= 0; i--) if (a[i][j]) b.a[t--][j] = a[i][j];\n            }\n        } else {\n            assert(false);\n        }\n        return b;\n    }\n\n    inline long long component_square_sum() const {\n        bool vis[N][N];\n        memset(vis, 0, sizeof(vis));\n        static const int dr[4] = {-1, 1, 0, 0};\n        static const int dc[4] = {0, 0, -1, 1};\n        long long res = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (!a[i][j] || vis[i][j]) continue;\n            int col = a[i][j];\n            int sz = 0;\n            queue<pair<int,int>> q;\n            q.push({i,j});\n            vis[i][j] = true;\n            while (!q.empty()) {\n                auto [r,c] = q.front(); q.pop();\n                sz++;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (!vis[nr][nc] && a[nr][nc] == col) {\n                        vis[nr][nc] = true;\n                        q.push({nr,nc});\n                    }\n                }\n            }\n            res += 1LL * sz * sz;\n        }\n        return res;\n    }\n};\n\nstruct Solver {\n    vector<int> f;\n    int totalCnt[4]{};\n    Pos anchor[4];\n    mt19937 rng;\n\n    Solver(const vector<int>& flavors) : f(flavors), rng(123456789) {\n        for (int x : f) totalCnt[x]++;\n        choose_anchors();\n    }\n\n    void choose_anchors() {\n        // Use 3 distinct corners, assigning larger flavors farther apart.\n        vector<Pos> corners = {{0,0}, {0,9}, {9,0}, {9,9}};\n        vector<int> ord = {1,2,3};\n        sort(ord.begin(), ord.end(), [&](int x, int y) { return totalCnt[x] > totalCnt[y]; });\n\n        long long best = LLONG_MIN;\n        array<int,3> bestIdx = {0,1,2};\n        for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (j != i)\n        for (int k = 0; k < 4; k++) if (k != i && k != j) {\n            auto dist = [&](Pos a, Pos b) {\n                return abs(a.r - b.r) + abs(a.c - b.c);\n            };\n            long long s = 0;\n            s += 1LL * totalCnt[ord[0]] * totalCnt[ord[1]] * dist(corners[i], corners[j]);\n            s += 1LL * totalCnt[ord[0]] * totalCnt[ord[2]] * dist(corners[i], corners[k]);\n            s += 1LL * totalCnt[ord[1]] * totalCnt[ord[2]] * dist(corners[j], corners[k]);\n            if (s > best) {\n                best = s;\n                bestIdx = {i,j,k};\n            }\n        }\n        anchor[ord[0]] = corners[bestIdx[0]];\n        anchor[ord[1]] = corners[bestIdx[1]];\n        anchor[ord[2]] = corners[bestIdx[2]];\n    }\n\n    double evaluate(const Board& b, int turn) const {\n        double score = 0.0;\n\n        // True objective proxy\n        long long comp = b.component_square_sum();\n        score += 3000.0 * comp;\n\n        // Neighbor interactions\n        int sameAdj = 0, diffAdj = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j]) {\n            if (i + 1 < N && b.a[i+1][j]) {\n                if (b.a[i+1][j] == b.a[i][j]) sameAdj++;\n                else diffAdj++;\n            }\n            if (j + 1 < N && b.a[i][j+1]) {\n                if (b.a[i][j+1] == b.a[i][j]) sameAdj++;\n                else diffAdj++;\n            }\n        }\n        score += 280.0 * sameAdj;\n        score -= 180.0 * diffAdj;\n\n        // Per-flavor compactness and separation\n        for (int col = 1; col <= 3; col++) {\n            int cnt = 0;\n            int minr = N, maxr = -1, minc = N, maxc = -1;\n            long long sumDistAnchor = 0;\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j] == col) {\n                cnt++;\n                minr = min(minr, i);\n                maxr = max(maxr, i);\n                minc = min(minc, j);\n                maxc = max(maxc, j);\n                sumDistAnchor += abs(i - anchor[col].r) + abs(j - anchor[col].c);\n            }\n            if (cnt > 0) {\n                int area = (maxr - minr + 1) * (maxc - minc + 1);\n                // Compact blobs are good\n                score -= 25.0 * area;\n                // Mild anchor guidance, especially early\n                double w = (turn <= 35 ? 20.0 : turn <= 70 ? 12.0 : 5.0);\n                score -= w * sumDistAnchor;\n            }\n        }\n\n        // Row/column purity\n        for (int i = 0; i < N; i++) {\n            int cnt[4] = {};\n            for (int j = 0; j < N; j++) cnt[b.a[i][j]]++;\n            score += 18.0 * (cnt[1]*cnt[1] + cnt[2]*cnt[2] + cnt[3]*cnt[3]);\n        }\n        for (int j = 0; j < N; j++) {\n            int cnt[4] = {};\n            for (int i = 0; i < N; i++) cnt[b.a[i][j]]++;\n            score += 18.0 * (cnt[1]*cnt[1] + cnt[2]*cnt[2] + cnt[3]*cnt[3]);\n        }\n\n        // Reward border packing a little, useful under repeated compressions\n        int border = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j]) {\n            if (i == 0 || i == 9 || j == 0 || j == 9) border++;\n        }\n        score += 10.0 * border;\n\n        return score;\n    }\n\n    vector<int> sample_indices(int m, int limit) {\n        vector<int> ids;\n        if (m <= limit) {\n            ids.resize(m);\n            iota(ids.begin(), ids.end(), 0);\n            return ids;\n        }\n\n        // deterministic spread + a few pseudo-random points\n        set<int> used;\n        for (int s = 0; s < limit / 2; s++) {\n            int idx = (long long)s * m / max(1, limit / 2);\n            idx = min(idx, m - 1);\n            used.insert(idx);\n        }\n        while ((int)used.size() < limit) {\n            used.insert((int)(rng() % m));\n        }\n        ids.assign(used.begin(), used.end());\n        return ids;\n    }\n\n    struct Node {\n        Board b;\n        double val;\n    };\n\n    double rollout_value(const Board& start, int turn) {\n        // Simulate expected future using beam search with sampled insertions.\n        // turn = current real turn (1-based), board is after applying a candidate current move.\n        // Future starts from turn+1.\n        if (turn >= 100) return evaluate(start, turn);\n\n        int rem = 100 - turn;\n        int depth, beamW, sampleW;\n        if (turn <= 25) {\n            depth = 5; beamW = 10; sampleW = 3;\n        } else if (turn <= 60) {\n            depth = 6; beamW = 12; sampleW = 4;\n        } else if (turn <= 85) {\n            depth = 7; beamW = 10; sampleW = 4;\n        } else {\n            depth = min(10, rem);\n            beamW = 8;\n            sampleW = 5;\n        }\n        depth = min(depth, rem);\n\n        static const char dirs[4] = {'F','B','L','R'};\n        vector<Node> beam;\n        beam.push_back({start, evaluate(start, turn)});\n\n        for (int d = 0; d < depth; d++) {\n            int futureTurn = turn + d + 1;       // actual turn index of inserted candy\n            int flavor = f[futureTurn - 1];      // 0-based\n            vector<Node> cand;\n            cand.reserve(beam.size() * sampleW * 4);\n\n            for (const Node& node : beam) {\n                vector<Pos> empties = node.b.empty_cells_ordered();\n                int m = (int)empties.size();\n                if (m == 0) {\n                    cand.push_back(node);\n                    continue;\n                }\n\n                vector<int> ids = sample_indices(m, min(sampleW, m));\n                for (int id : ids) {\n                    Board placed = node.b;\n                    placed.a[empties[id].r][empties[id].c] = (uint8_t)flavor;\n\n                    for (char mv : dirs) {\n                        Board nb = placed.tilted(mv);\n                        double v = evaluate(nb, futureTurn);\n                        // tiny stabilization bias\n                        if (mv == 'F') v += 0.02;\n                        else if (mv == 'L') v += 0.015;\n                        else if (mv == 'R') v += 0.01;\n                        cand.push_back({nb, v});\n                    }\n                }\n            }\n\n            if (cand.empty()) break;\n\n            nth_element(cand.begin(), cand.begin() + min((int)cand.size(), beamW), cand.end(),\n                        [](const Node& x, const Node& y){ return x.val > y.val; });\n            if ((int)cand.size() > beamW) cand.resize(beamW);\n            beam.swap(cand);\n        }\n\n        double best = -1e100;\n        for (const auto& node : beam) best = max(best, node.val);\n        return best;\n    }\n\n    char decide(const Board& board, int turn) {\n        static const char dirs[4] = {'F','B','L','R'};\n\n        char bestDir = 'F';\n        double bestScore = -1e100;\n\n        // Search intensity by phase\n        bool doRollout = true;\n        if (turn <= 8) doRollout = false; // early state too random, greedy is okay\n\n        for (char d : dirs) {\n            Board tb = board.tilted(d);\n            double sc = evaluate(tb, turn);\n\n            if (doRollout) {\n                double rv = rollout_value(tb, turn);\n                // Mix local and future estimates\n                double alpha;\n                if (turn <= 25) alpha = 0.35;\n                else if (turn <= 70) alpha = 0.25;\n                else alpha = 0.15;\n                sc = alpha * sc + (1.0 - alpha) * rv;\n            }\n\n            // tie-break\n            if (d == 'F') sc += 0.003;\n            else if (d == 'L') sc += 0.002;\n            else if (d == 'R') sc += 0.001;\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = d;\n            }\n        }\n        return bestDir;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Solver solver(f);\n    Board board;\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        board.place_by_index(p, f[t - 1]);\n        char ans = solver.decide(board, t);\n        board = board.tilted(ans);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC016 - heuristic solution\n\nIdea\n----\nVertex labels are lost, so we should use graph features invariant under permutation.\nA simple and fairly strong invariant is the sorted degree sequence.\n\nConstruction:\n- Use one common N.\n- For each graph G_k, create a threshold graph:\n    choose x_k \"dominant\" vertices connected to all others,\n    and the remaining vertices isolated among themselves.\n  Then degree multiset is:\n    x_k vertices of degree N-1\n    N-x_k vertices of degree x_k\n  This is uniquely determined by x_k (except tiny degeneracies avoided by N>=4).\n- So each graph is identified by one parameter x_k.\n\nDecoding:\n- From received H, compute degree sequence, sort it.\n- Compare against the expected noisy degree distributions of every codeword x_k.\n- Since each edge flips independently with probability eps, each vertex degree is approximately:\n    original_degree * (1-eps) + (N-1-original_degree) * eps\n  We score a candidate by sum of squared errors to the sorted expected degrees.\n- Also compare edge count likelihood as auxiliary score.\n\nChoosing N and codewords:\n- Need M distinct graphs. We only have N+1 possible x values, so N >= M-1.\n- To improve robustness, spread codewords across [0, N].\n- Since score has 1/N penalty, use the minimum N that allows spacing:\n    N = min(100, max(4, M-1))\n  Then just set x_k = k.\nThis is simple, safe, and fast.\n\nThis is not state-of-the-art, but robust and compact.\n*/\n\nstatic string make_graph_threshold(int N, int x) {\n    // Vertices [0, x) are dominant: connected to everyone else.\n    // Vertices [x, N) have no edges among themselves.\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            char c = (i < x || j < x) ? '1' : '0';\n            s.push_back(c);\n        }\n    }\n    return s;\n}\n\nstatic vector<int> degree_sequence_from_string(int N, const string& g) {\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 (g[p++] == '1') {\n                deg[i]++;\n                deg[j]++;\n            }\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    int N = max(4, M - 1);\n    N = min(N, 100);\n\n    vector<int> xs(M);\n    for (int k = 0; k < M; ++k) xs[k] = k; // since N >= M-1\n\n    vector<string> graphs(M);\n    vector<vector<double>> exp_deg_sorted(M, vector<double>(N));\n    vector<double> exp_edges(M);\n\n    for (int k = 0; k < M; ++k) {\n        int x = xs[k];\n        graphs[k] = make_graph_threshold(N, x);\n\n        double d_small = x * (1.0 - eps) + (N - 1 - x) * eps;\n        double d_big = (N - 1) * (1.0 - eps); // since original degree N-1\n        int cnt_small = N - x, cnt_big = x;\n\n        for (int i = 0; i < cnt_small; ++i) exp_deg_sorted[k][i] = d_small;\n        for (int i = 0; i < cnt_big; ++i) exp_deg_sorted[k][cnt_small + i] = d_big;\n\n        double m0 = 1.0 * x * (2 * N - x - 1) / 2.0; // #edges in threshold graph\n        double total = 1.0 * N * (N - 1) / 2.0;\n        exp_edges[k] = m0 * (1.0 - eps) + (total - m0) * eps;\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\n        vector<int> deg = degree_sequence_from_string(N, H);\n        int edges = 0;\n        for (char c : H) if (c == '1') edges++;\n\n        int best = 0;\n        double best_score = 1e100;\n\n        for (int k = 0; k < M; ++k) {\n            double sse = 0.0;\n            for (int i = 0; i < N; ++i) {\n                double diff = deg[i] - exp_deg_sorted[k][i];\n                sse += diff * diff;\n            }\n            double ediff = edges - exp_edges[k];\n            double score = sse + 0.5 * ediff * ediff;\n            if (score < best_score) {\n                best_score = 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    int cell;\n    double imp = 0.0;\n};\n\nstatic const long long INF64 = (1LL << 60);\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>>> g(N); // to, edge id\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        g[u].push_back({v, i});\n        g[v].push_back({u, i});\n    }\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n    // ---- Build geometric cells from edge midpoints ----\n    // Coarse grid. Since coordinates are in [0,1000], 6x6 or 7x7 works well.\n    const int G = 6;\n    auto get_cell = [&](double x, double y) {\n        int gx = min(G - 1, max(0, (int)(x * G / 1001.0)));\n        int gy = min(G - 1, max(0, (int)(y * G / 1001.0)));\n        return gy * G + gx;\n    };\n    int C = G * G;\n    for (int i = 0; i < M; i++) {\n        double mx = (xs[edges[i].u] + xs[edges[i].v]) * 0.5;\n        double my = (ys[edges[i].u] + ys[edges[i].v]) * 0.5;\n        edges[i].cell = get_cell(mx, my);\n    }\n\n    // ---- Approximate edge importance by sampled shortest path trees ----\n    vector<double> imp(M, 0.0);\n    vector<double> vcen(N, 0.0);\n\n    // Sample roots: far-spread by coordinates + random-ish deterministic picks.\n    vector<int> roots;\n    roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n    roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n    roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n    roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n\n    // Add a few deterministic pseudo-random roots.\n    int S = min(24, max(8, 2 * D));\n    for (int t = 0; (int)roots.size() < S; t++) {\n        int r = (int)((1LL * t * 911382323 + 972663749) % N);\n        roots.push_back(r);\n    }\n    sort(roots.begin(), roots.end());\n    roots.erase(unique(roots.begin(), roots.end()), roots.end());\n\n    vector<long long> dist(N);\n    vector<int> parent_e(N), parent_v(N);\n\n    auto dijkstra = [&](int s) {\n        fill(dist.begin(), dist.end(), INF64);\n        fill(parent_e.begin(), parent_e.end(), -1);\n        fill(parent_v.begin(), parent_v.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        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    parent_e[to] = ei;\n                    parent_v[to] = v;\n                    pq.push({nd, to});\n                } else if (nd == dist[to]) {\n                    // Tie-breaking: prefer larger weight slightly less, then edge id\n                    if (parent_e[to] == -1 || ei < parent_e[to]) {\n                        parent_e[to] = ei;\n                        parent_v[to] = v;\n                    }\n                }\n            }\n        }\n    };\n\n    for (int s : roots) {\n        if (timer.elapsed() > 1.8) break;\n        dijkstra(s);\n        double sumd = 0.0;\n        for (int i = 0; i < N; i++) {\n            if (dist[i] < INF64 / 4) sumd += dist[i];\n        }\n        double inv = (sumd > 0 ? 1.0 / sumd : 0.0);\n\n        for (int v = 0; v < N; v++) {\n            if (v == s) continue;\n            if (parent_e[v] != -1) {\n                // Edge used in one SPT; weighted by closeness from root.\n                double add = 1.0 + 3.0 * (1.0 - dist[v] * inv);\n                imp[parent_e[v]] += add;\n            }\n            if (dist[v] < INF64 / 4) {\n                vcen[v] += (1.0 - dist[v] * inv);\n            }\n        }\n    }\n\n    // Add static features: edge length and endpoint degree/centrality\n    for (int i = 0; i < M; i++) {\n        int u = edges[i].u, v = edges[i].v;\n        double val = imp[i];\n        val += 0.15 * (double)g[u].size();\n        val += 0.15 * (double)g[v].size();\n        val += 1.2 * (vcen[u] + vcen[v]);\n        val += 0.000002 * edges[i].w; // very small length effect\n        edges[i].imp = val;\n    }\n\n    // ---- Greedy assignment ----\n    vector<int> ord(M);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n        return edges[a].w > edges[b].w;\n    });\n\n    vector<int> day_of(M, -1); // 0-based\n    vector<int> load(D, 0);\n    vector<double> day_imp(D, 0.0);\n\n    vector<vector<int>> cell_cnt(D, vector<int>(C, 0));\n    vector<vector<int>> vday_cnt(D, vector<int>(N, 0));\n\n    auto day_cost_insert = [&](int day, int ei) -> double {\n        const Edge &e = edges[ei];\n        int u = e.u, v = e.v, c = e.cell;\n        double cost = 0.0;\n        cost += 7.0 * load[day];\n        cost += 4.5 * cell_cnt[day][c];\n        cost += 3.0 * (vday_cnt[day][u] + vday_cnt[day][v]);\n        cost += 0.22 * day_imp[day];\n        cost += 0.9 * e.imp * (double)load[day] / max(1, K);\n        return cost;\n    };\n\n    for (int ei : ord) {\n        double best = 1e100;\n        int bestd = -1;\n        for (int d = 0; d < D; d++) {\n            if (load[d] >= K) continue;\n            double c = day_cost_insert(d, ei);\n            if (c < best) {\n                best = c;\n                bestd = d;\n            }\n        }\n        if (bestd == -1) {\n            // Should not happen, but fallback.\n            bestd = min_element(load.begin(), load.end()) - load.begin();\n        }\n        day_of[ei] = bestd;\n        load[bestd]++;\n        day_imp[bestd] += edges[ei].imp;\n        cell_cnt[bestd][edges[ei].cell]++;\n        vday_cnt[bestd][edges[ei].u]++;\n        vday_cnt[bestd][edges[ei].v]++;\n    }\n\n    // ---- Surrogate score for local search ----\n    auto delta_move = [&](int ei, int from, int to) -> double {\n        if (from == to) return 0.0;\n        const Edge &e = edges[ei];\n        int c = e.cell, u = e.u, v = e.v;\n\n        auto contrib = [&](int d, int sign) -> double {\n            // sign = -1 remove, +1 add\n            double res = 0.0;\n\n            int oldLoad = load[d];\n            int newLoad = oldLoad + sign;\n            res += 3.5 * (1LL * newLoad * newLoad - 1LL * oldLoad * oldLoad);\n\n            int oldCell = cell_cnt[d][c];\n            int newCell = oldCell + sign;\n            res += 5.0 * (1LL * newCell * newCell - 1LL * oldCell * oldCell);\n\n            int oldu = vday_cnt[d][u];\n            int newu = oldu + sign;\n            res += 2.2 * (1LL * newu * newu - 1LL * oldu * oldu);\n\n            int oldv = vday_cnt[d][v];\n            int newv = oldv + sign;\n            res += 2.2 * (1LL * newv * newv - 1LL * oldv * oldv);\n\n            double oldImp = day_imp[d];\n            double newImp = oldImp + sign * e.imp;\n            res += 0.018 * (newImp * newImp - oldImp * oldImp);\n\n            return res;\n        };\n\n        return contrib(from, -1) + contrib(to, +1);\n    };\n\n    auto apply_move = [&](int ei, int from, int to) {\n        const Edge &e = edges[ei];\n        load[from]--;\n        day_imp[from] -= e.imp;\n        cell_cnt[from][e.cell]--;\n        vday_cnt[from][e.u]--;\n        vday_cnt[from][e.v]--;\n\n        load[to]++;\n        day_imp[to] += e.imp;\n        cell_cnt[to][e.cell]++;\n        vday_cnt[to][e.u]++;\n        vday_cnt[to][e.v]++;\n\n        day_of[ei] = to;\n    };\n\n    // ---- Local search: random moves and swaps ----\n    mt19937 rng(712367821);\n    vector<vector<int>> by_day(D);\n    for (int i = 0; i < M; i++) by_day[day_of[i]].push_back(i);\n\n    auto rebuild_by_day = [&]() {\n        for (int d = 0; d < D; d++) by_day[d].clear();\n        for (int i = 0; i < M; i++) by_day[day_of[i]].push_back(i);\n    };\n\n    int iter = 0;\n    while (timer.elapsed() < 5.7) {\n        iter++;\n        if ((iter & 255) == 0) rebuild_by_day();\n\n        if ((rng() & 1) == 0) {\n            // move\n            int ei = rng() % M;\n            int from = day_of[ei];\n            int to = rng() % D;\n            if (from == to || load[to] >= K) continue;\n            double dlt = delta_move(ei, from, to);\n            if (dlt < 0.0 || (rng() % 1000 == 0)) {\n                apply_move(ei, from, to);\n            }\n        } else {\n            // swap\n            int e1 = rng() % M;\n            int d1 = day_of[e1];\n            int d2 = rng() % D;\n            if (d1 == d2 || by_day[d2].empty()) continue;\n            int e2 = by_day[d2][rng() % by_day[d2].size()];\n            int cur1 = day_of[e1], cur2 = day_of[e2];\n            if (cur1 == cur2) continue;\n\n            double dlt = delta_move(e1, cur1, cur2) + delta_move(e2, cur2, cur1);\n\n            // small correction because after first move counts change; good enough as surrogate\n            if (dlt < 0.0 || (rng() % 3000 == 0)) {\n                apply_move(e1, cur1, cur2);\n                apply_move(e2, cur2, cur1);\n            }\n        }\n    }\n\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << day_of[i] + 1;\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DX[6] = {1,-1,0,0,0,0};\nstatic const int DY[6] = {0,0,1,-1,0,0};\nstatic const int DZ[6] = {0,0,0,0,1,-1};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next_u32() % (uint32_t)(r - l + 1));\n    }\n    double next_double() {\n        return (double)next_u32() / (double)UINT32_MAX;\n    }\n} rng;\n\nstruct P3 {\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    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int i = 0; i < D; i++) cin >> f[t][i];\n        for (int i = 0; i < D; i++) cin >> r[t][i];\n    }\n\n    auto idx = [&](int x, int y, int z) -> int {\n        return (x * D + y) * D + z;\n    };\n    auto inside = [&](int x, int y, int z) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D && 0 <= z && z < D;\n    };\n\n    int N3 = D * D * D;\n\n    // All 24 proper rotations of cube generated as permutations+signs with det=1.\n    struct Rot {\n        int p[3]; // new coords are from old p[k]\n        int s[3]; // signs\n    };\n    vector<Rot> rots;\n    {\n        vector<int> perm = {0,1,2};\n        do {\n            for (int sx : {-1,1}) for (int sy : {-1,1}) for (int sz : {-1,1}) {\n                int sign_perm = 1;\n                for (int i = 0; i < 3; i++) for (int j = i+1; j < 3; j++) {\n                    if (perm[i] > perm[j]) sign_perm *= -1;\n                }\n                int det = sign_perm * sx * sy * sz;\n                if (det == 1) {\n                    Rot rt;\n                    rt.p[0]=perm[0]; rt.p[1]=perm[1]; rt.p[2]=perm[2];\n                    rt.s[0]=sx; rt.s[1]=sy; rt.s[2]=sz;\n                    rots.push_back(rt);\n                }\n            }\n        } while (next_permutation(perm.begin(), perm.end()));\n    }\n\n    auto rotate_point = [&](const P3& a, const Rot& rt) -> P3 {\n        int v[3] = {a.x, a.y, a.z};\n        return P3{\n            rt.s[0] * v[rt.p[0]],\n            rt.s[1] * v[rt.p[1]],\n            rt.s[2] * v[rt.p[2]]\n        };\n    };\n\n    auto canonical_signature = [&](const vector<P3>& cells) -> string {\n        vector<P3> pts = cells;\n        string best;\n        bool first = true;\n        for (const auto& rt : rots) {\n            vector<array<int,3>> q;\n            q.reserve(pts.size());\n            int minx = 1e9, miny = 1e9, minz = 1e9;\n            for (auto &p : pts) {\n                P3 t = rotate_point(p, rt);\n                minx = min(minx, t.x);\n                miny = min(miny, t.y);\n                minz = min(minz, t.z);\n                q.push_back({t.x, t.y, t.z});\n            }\n            for (auto &a : q) {\n                a[0] -= minx;\n                a[1] -= miny;\n                a[2] -= minz;\n            }\n            sort(q.begin(), q.end());\n            string s;\n            s.reserve(q.size() * 10);\n            for (auto &a : q) {\n                s += to_string(a[0]);\n                s += ',';\n                s += to_string(a[1]);\n                s += ',';\n                s += to_string(a[2]);\n                s += ';';\n            }\n            if (first || s < best) {\n                best = s;\n                first = false;\n            }\n        }\n        return best;\n    };\n\n    auto build_object = [&](int cur, const vector<char>& refOcc, const vector<char>& selfHint) -> vector<char> {\n        vector<char> occ(N3, 0);\n\n        for (int z = 0; z < D; z++) {\n            vector<int> X, Y;\n            for (int x = 0; x < D; x++) if (f[cur][z][x] == '1') X.push_back(x);\n            for (int y = 0; y < D; y++) if (r[cur][z][y] == '1') Y.push_back(y);\n            int a = (int)X.size(), b = (int)Y.size();\n            if (a == 0 || b == 0) continue;\n\n            int need = max(a, b);\n\n            vector<pair<int,int>> bestCells;\n            long long bestScore = LLONG_MIN;\n\n            int trials = 60;\n            if (D <= 7) trials = 120;\n            else if (D <= 10) trials = 90;\n\n            for (int tr = 0; tr < trials; tr++) {\n                vector<int> px = X, py = Y;\n                shuffle(px.begin(), px.end(), std::mt19937(rng.next_u32()));\n                shuffle(py.begin(), py.end(), std::mt19937(rng.next_u32()));\n\n                vector<pair<int,int>> cells;\n                vector<int> usedX(a, 0), usedY(b, 0);\n\n                int m = min(a, b);\n                for (int i = 0; i < m; i++) {\n                    int x = px[i], y = py[i];\n                    cells.push_back({x, y});\n                }\n\n                if (a > b) {\n                    // choose one y to connect remaining x\n                    int bestj = py[0];\n                    long long localBest = LLONG_MIN;\n                    for (int candY : Y) {\n                        long long sc = 0;\n                        for (int i = b; i < a; i++) {\n                            int x = px[i];\n                            int id = idx(x, candY, z);\n                            sc += refOcc[id] ? 20 : 0;\n                            sc += selfHint[id] ? 8 : 0;\n                            if (z > 0 && occ[idx(x, candY, z-1)]) sc += 6;\n                            if (z + 1 < D && selfHint[idx(x, candY, z+1)]) sc += 2;\n                        }\n                        if (sc > localBest) localBest = sc, bestj = candY;\n                    }\n                    for (int i = b; i < a; i++) cells.push_back({px[i], bestj});\n                } else if (b > a) {\n                    int besti = px[0];\n                    long long localBest = LLONG_MIN;\n                    for (int candX : X) {\n                        long long sc = 0;\n                        for (int j = a; j < b; j++) {\n                            int y = py[j];\n                            int id = idx(candX, y, z);\n                            sc += refOcc[id] ? 20 : 0;\n                            sc += selfHint[id] ? 8 : 0;\n                            if (z > 0 && occ[idx(candX, y, z-1)]) sc += 6;\n                            if (z + 1 < D && selfHint[idx(candX, y, z+1)]) sc += 2;\n                        }\n                        if (sc > localBest) localBest = sc, besti = candX;\n                    }\n                    for (int j = a; j < b; j++) cells.push_back({besti, py[j]});\n                }\n\n                // Ensure exact cover of X and Y\n                // Score this candidate\n                long long score = 0;\n                unordered_set<int> S;\n                S.reserve(cells.size() * 2 + 10);\n                for (auto [x, y] : cells) {\n                    int id = idx(x, y, z);\n                    S.insert(id);\n                    if (refOcc[id]) score += 50;\n                    if (selfHint[id]) score += 20;\n                    if (z > 0 && occ[idx(x, y, z-1)]) score += 16;\n                    if (z + 1 < D && selfHint[idx(x, y, z+1)]) score += 4;\n                }\n                // In-layer adjacency bonus\n                for (auto [x, y] : cells) {\n                    int cnt = 0;\n                    if (x > 0 && S.count(idx(x-1, y, z))) cnt++;\n                    if (x + 1 < D && S.count(idx(x+1, y, z))) cnt++;\n                    if (y > 0 && S.count(idx(x, y-1, z))) cnt++;\n                    if (y + 1 < D && S.count(idx(x, y+1, z))) cnt++;\n                    score += 5LL * cnt;\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestCells = cells;\n                }\n            }\n\n            for (auto [x, y] : bestCells) occ[idx(x, y, z)] = 1;\n        }\n\n        return occ;\n    };\n\n    // Initial hint: direct deterministic sparse construction\n    auto initial_build = [&](int t) -> vector<char> {\n        vector<char> occ(N3, 0);\n        for (int z = 0; z < D; z++) {\n            vector<int> X, Y;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') X.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') Y.push_back(y);\n            int a = (int)X.size(), b = (int)Y.size();\n            if (a == 0 || b == 0) continue;\n            if (a <= b) {\n                for (int i = 0; i < a; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = a; i < b; i++) occ[idx(X[0], Y[i], z)] = 1;\n            } else {\n                for (int i = 0; i < b; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = b; i < a; i++) occ[idx(X[i], Y[0], z)] = 1;\n            }\n        }\n        return occ;\n    };\n\n    vector<char> occ0 = initial_build(0);\n    vector<char> occ1 = initial_build(1);\n\n    auto overlap_score = [&](const vector<char>& a, const vector<char>& b) -> int {\n        int s = 0;\n        for (int i = 0; i < N3; i++) if (a[i] && b[i]) s++;\n        return s;\n    };\n\n    // Alternate refinement\n    for (int iter = 0; iter < 6; iter++) {\n        auto n0 = build_object(0, occ1, occ0);\n        auto n1 = build_object(1, n0, occ1);\n        int oldv = overlap_score(occ0, occ1);\n        int newv = overlap_score(n0, n1);\n        if (newv >= oldv) {\n            occ0.swap(n0);\n            occ1.swap(n1);\n        } else {\n            auto m1 = build_object(1, occ0, occ1);\n            auto m0 = build_object(0, m1, occ0);\n            int altv = overlap_score(m0, m1);\n            if (altv > oldv) {\n                occ0.swap(m0);\n                occ1.swap(m1);\n            }\n        }\n    }\n\n    // Extract connected components for each object\n    struct Component {\n        vector<int> ids;   // global voxel ids\n        string sig;\n    };\n\n    auto get_components = [&](const vector<char>& occ) -> vector<Component> {\n        vector<Component> comps;\n        vector<char> vis(N3, 0);\n        for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n            int s = idx(x, y, z);\n            if (!occ[s] || vis[s]) continue;\n            queue<int> q;\n            q.push(s);\n            vis[s] = 1;\n            vector<int> ids;\n            vector<P3> rel;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                ids.push_back(v);\n                int zz = v % D;\n                int tmp = v / D;\n                int yy = tmp % D;\n                int xx = tmp / D;\n                rel.push_back({xx, yy, zz});\n                for (int dir = 0; dir < 6; dir++) {\n                    int nx = xx + DX[dir], ny = yy + DY[dir], nz = zz + DZ[dir];\n                    if (!inside(nx, ny, nz)) continue;\n                    int to = idx(nx, ny, nz);\n                    if (occ[to] && !vis[to]) {\n                        vis[to] = 1;\n                        q.push(to);\n                    }\n                }\n            }\n            // normalize positions by translation before signature\n            int minx = 1e9, miny = 1e9, minz = 1e9;\n            for (auto &p : rel) {\n                minx = min(minx, p.x);\n                miny = min(miny, p.y);\n                minz = min(minz, p.z);\n            }\n            for (auto &p : rel) {\n                p.x -= minx;\n                p.y -= miny;\n                p.z -= minz;\n            }\n            Component c;\n            c.ids = move(ids);\n            c.sig = canonical_signature(rel);\n            comps.push_back(move(c));\n        }\n        return comps;\n    };\n\n    auto comps0 = get_components(occ0);\n    auto comps1 = get_components(occ1);\n\n    // Match equal-shape components greedily by signature, largest first\n    unordered_map<string, vector<int>> mp0, mp1;\n    mp0.reserve(comps0.size() * 2 + 10);\n    mp1.reserve(comps1.size() * 2 + 10);\n\n    for (int i = 0; i < (int)comps0.size(); i++) mp0[comps0[i].sig].push_back(i);\n    for (int i = 0; i < (int)comps1.size(); i++) mp1[comps1[i].sig].push_back(i);\n\n    for (auto &kv : mp0) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b){\n            return comps0[a].ids.size() > comps0[b].ids.size();\n        });\n    }\n    for (auto &kv : mp1) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b){\n            return comps1[a].ids.size() > comps1[b].ids.size();\n        });\n    }\n\n    vector<int> voxelLab0(N3, 0), voxelLab1(N3, 0);\n    int nBlocks = 0;\n\n    unordered_set<string> keys;\n    keys.reserve(mp0.size() + mp1.size() + 10);\n    for (auto &kv : mp0) keys.insert(kv.first);\n    for (auto &kv : mp1) keys.insert(kv.first);\n\n    for (const string &sig : keys) {\n        auto it0 = mp0.find(sig);\n        auto it1 = mp1.find(sig);\n        vector<int> *v0 = (it0 == mp0.end() ? nullptr : &it0->second);\n        vector<int> *v1 = (it1 == mp1.end() ? nullptr : &it1->second);\n\n        int c0 = v0 ? (int)v0->size() : 0;\n        int c1 = v1 ? (int)v1->size() : 0;\n        int m = min(c0, c1);\n\n        for (int i = 0; i < m; i++) {\n            ++nBlocks;\n            for (int id : comps0[(*v0)[i]].ids) voxelLab0[id] = nBlocks;\n            for (int id : comps1[(*v1)[i]].ids) voxelLab1[id] = nBlocks;\n        }\n        if (v0) {\n            for (int i = m; i < c0; i++) {\n                ++nBlocks;\n                for (int id : comps0[(*v0)[i]].ids) voxelLab0[id] = nBlocks;\n            }\n        }\n        if (v1) {\n            for (int i = m; i < c1; i++) {\n                ++nBlocks;\n                for (int id : comps1[(*v1)[i]].ids) voxelLab1[id] = nBlocks;\n            }\n        }\n    }\n\n    cout << nBlocks << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << voxelLab0[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << voxelLab1[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v;\n    int w;\n};\n\nstruct DijkstraResult {\n    vector<ll> dist;\n    vector<int> prev_v;\n    vector<int> prev_e;\n};\n\nstatic inline ll sqll(ll x) { return x * x; }\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    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); // (to, edge_id)\n    for (int i = 0; i < M; i++) {\n        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        g[u].push_back({v, i});\n        g[v].push_back({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    // Precompute squared distances station -> resident, sorted order for each station.\n    vector<vector<pair<ll,int>>> station_res(N);\n    vector<vector<int>> reqR(N, vector<int>(K));\n    for (int i = 0; i < N; i++) {\n        station_res[i].reserve(K);\n        for (int k = 0; k < K; k++) {\n            ll dx = (ll)x[i] - a[k];\n            ll dy = (ll)y[i] - b[k];\n            ll d2 = dx*dx + dy*dy;\n            station_res[i].push_back({d2, k});\n            int r = (int)ceil(sqrt((long double)d2));\n            if (r > 5000) r = 5001; // impossible\n            reqR[i][k] = r;\n        }\n        sort(station_res[i].begin(), station_res[i].end());\n    }\n\n    auto dijkstra = [&](int s) -> DijkstraResult {\n        vector<ll> dist(N, INF64);\n        vector<int> prev_v(N, -1), prev_e(N, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                ll nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    prev_v[to] = v;\n                    prev_e[to] = ei;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        return {dist, prev_v, prev_e};\n    };\n\n    // APSP by Dijkstra from each vertex\n    vector<vector<ll>> allDist(N, vector<ll>(N, INF64));\n    vector<vector<int>> allPrevV(N), allPrevE(N);\n    for (int s = 0; s < N; s++) {\n        auto res = dijkstra(s);\n        allDist[s] = move(res.dist);\n        allPrevV[s] = move(res.prev_v);\n        allPrevE[s] = move(res.prev_e);\n    }\n\n    auto build_edges_from_terminals = [&](const vector<int>& terminals) {\n        // terminals should include root 0 if non-empty? we'll include internally.\n        vector<int> ts = terminals;\n        sort(ts.begin(), ts.end());\n        ts.erase(unique(ts.begin(), ts.end()), ts.end());\n        if (find(ts.begin(), ts.end(), 0) == ts.end()) ts.insert(ts.begin(), 0);\n\n        int T = (int)ts.size();\n        vector<ll> mincost(T, INF64);\n        vector<int> parent(T, -1);\n        vector<char> used(T, 0);\n        mincost[0] = 0;\n        for (int it = 0; it < T; it++) {\n            int v = -1;\n            for (int i = 0; i < T; i++) if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int to = 0; to < T; to++) if (!used[to]) {\n                ll w = allDist[ts[v]][ts[to]];\n                if (w < mincost[to]) {\n                    mincost[to] = w;\n                    parent[to] = v;\n                }\n            }\n        }\n\n        vector<char> edge_on(M, 0);\n        vector<char> vert_on(N, 0);\n        vert_on[0] = 1;\n\n        for (int i = 1; i < T; i++) {\n            int a_v = ts[i];\n            int b_v = ts[parent[i]];\n            // Reconstruct shortest path from a_v to b_v using Dijkstra tree rooted at a_v\n            // allPrev arrays for source a_v\n            int cur = b_v;\n            // Need path b_v -> a_v through prev from source a_v\n            while (cur != a_v) {\n                int ei = allPrevE[a_v][cur];\n                int pv = allPrevV[a_v][cur];\n                if (ei < 0 || pv < 0) break; // should not happen\n                edge_on[ei] = 1;\n                vert_on[cur] = 1;\n                vert_on[pv] = 1;\n                cur = pv;\n            }\n        }\n        return pair(edge_on, vert_on);\n    };\n\n    auto greedy_cover = [&](const vector<int>& usableStations, double alpha, bool useConnPenalty) {\n        vector<char> covered(K, 0);\n        vector<int> P(N, 0);\n        vector<int> selectedStations;\n        int coveredCnt = 0;\n\n        vector<char> usable(N, 0);\n        for (int v : usableStations) usable[v] = 1;\n\n        while (coveredCnt < K) {\n            double bestScore = -1.0;\n            int bestV = -1;\n            int bestR = -1;\n            int gain = 0;\n\n            for (int v = 0; v < N; v++) if (usable[v]) {\n                int uncov = 0;\n                int lastR = -1;\n                int bestLocalGain = 0;\n                int bestLocalR = -1;\n                double stationPenalty = useConnPenalty ? alpha * (double)allDist[0][v] : 0.0;\n\n                for (auto [d2, rid] : station_res[v]) {\n                    int r = (int)ceil(sqrt((long double)d2));\n                    if (r > 5000) break;\n                    if (!covered[rid]) uncov++;\n                    if (r != lastR) {\n                        if (uncov > 0) {\n                            double cost = (double)r * (double)r + stationPenalty;\n                            double score = (double)uncov / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                                gain = uncov;\n                            }\n                        }\n                        lastR = r;\n                    } else {\n                        if (uncov > 0) {\n                            double cost = (double)r * (double)r + stationPenalty;\n                            double score = (double)uncov / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                                gain = uncov;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) {\n                // Fallback: assign each uncovered resident to nearest usable station\n                for (int k = 0; k < K; k++) if (!covered[k]) {\n                    int bv = -1, br = 5001;\n                    for (int v = 0; v < N; v++) if (usable[v]) {\n                        int r = reqR[v][k];\n                        if (r <= 5000 && r < br) {\n                            br = r; bv = v;\n                        }\n                    }\n                    if (bv != -1) {\n                        P[bv] = max(P[bv], br);\n                        covered[k] = 1;\n                        coveredCnt++;\n                    }\n                }\n                break;\n            }\n\n            if (P[bestV] < bestR) {\n                if (P[bestV] == 0) selectedStations.push_back(bestV);\n                P[bestV] = bestR;\n            }\n\n            for (auto [d2, rid] : station_res[bestV]) {\n                int r = (int)ceil(sqrt((long double)d2));\n                if (r > bestR) break;\n                if (!covered[rid]) {\n                    covered[rid] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        // cleanup selected list\n        sort(selectedStations.begin(), selectedStations.end());\n        selectedStations.erase(unique(selectedStations.begin(), selectedStations.end()), selectedStations.end());\n\n        ll powerCost = 0;\n        for (int i = 0; i < N; i++) powerCost += 1LL * P[i] * P[i];\n        return tuple<vector<int>, vector<int>, ll>(P, selectedStations, powerCost);\n    };\n\n    auto compute_score_cost = [&](const vector<int>& P, const vector<char>& edge_on) {\n        ll S = 0;\n        for (int i = 0; i < N; i++) S += 1LL * P[i] * P[i];\n        for (int i = 0; i < M; i++) if (edge_on[i]) S += edges[i].w;\n        return S;\n    };\n\n    vector<int> bestP(N, 0);\n    vector<char> bestB(M, 0);\n    ll bestS = INF64;\n\n    vector<double> alphas = {0.0, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0};\n\n    vector<int> allStations(N);\n    iota(allStations.begin(), allStations.end(), 0);\n\n    for (double alpha : alphas) {\n        // Phase 1: coarse greedy over all stations with connection proxy\n        auto [P1, terms1, powerCost1] = greedy_cover(allStations, alpha, true);\n\n        // Connect selected stations\n        auto [edge_on1, vert_on1] = build_edges_from_terminals(terms1);\n\n        vector<int> reachableStations;\n        for (int i = 0; i < N; i++) if (vert_on1[i]) reachableStations.push_back(i);\n\n        // Phase 2: re-cover using all reachable stations, no connection penalty\n        auto [P2, terms2, powerCost2] = greedy_cover(reachableStations, 0.0, false);\n\n        // Reconnect only actually used powered stations\n        vector<int> positiveStations;\n        for (int i = 0; i < N; i++) if (P2[i] > 0) positiveStations.push_back(i);\n        auto [edge_on2, vert_on2] = build_edges_from_terminals(positiveStations);\n\n        // Prune edges: keep only subtree needed for root and positive stations inside chosen subgraph\n        vector<vector<pair<int,int>>> sg(N);\n        for (int i = 0; i < M; i++) if (edge_on2[i]) {\n            int u = edges[i].u, v = edges[i].v;\n            sg[u].push_back({v, i});\n            sg[v].push_back({u, i});\n        }\n\n        vector<char> needV(N, 0);\n        needV[0] = 1;\n        for (int i = 0; i < N; i++) if (P2[i] > 0) needV[i] = 1;\n\n        vector<char> keepE(M, 0), vis(N, 0);\n        function<bool(int,int)> dfs = [&](int v, int pe) -> bool {\n            vis[v] = 1;\n            bool need = needV[v];\n            for (auto [to, ei] : sg[v]) {\n                if (ei == pe) continue;\n                if (!vis[to]) {\n                    if (dfs(to, ei)) {\n                        keepE[ei] = 1;\n                        need = true;\n                    }\n                }\n            }\n            return need;\n        };\n        dfs(0, -1);\n\n        ll S = compute_score_cost(P2, keepE);\n        if (S < bestS) {\n            bestS = S;\n            bestP = P2;\n            bestB = keepE;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestB[i] ? 1 : 0);\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc021":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nAHC021-like heuristic.\n\nIdea:\n- We want a heap order on triangular grid:\n    a[x][y] < a[x+1][y], a[x+1][y+1]\n- We construct it top-down.\n- Target set for row x is the smallest T(x+1) values, where T(r)=r*(r+1)/2.\n  Thus row 0 should contain smallest 1 value, rows 0..1 smallest 3 values, etc.\n- For each row x and position y, place the smallest remaining value among rows x..N-1\n  into (x,y), processing y from left to right.\n- A ball can be moved upward by repeated swaps with one of its two parents.\n  We use a shortest path in the triangular graph restricted to rows <= current row.\n  Since N=30, BFS per placement is cheap enough.\n\nThis is not optimal, but usually reaches a valid state well within 10000 moves.\n*/\n\nstatic constexpr int N = 30;\nstatic constexpr int MAXK = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; i++) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; j++) cin >> a[i][j];\n    }\n\n    vector<pair<int,int>> pos(465);\n    for (int i = 0; i < N; i++) for (int j = 0; j <= i; j++) pos[a[i][j]] = {i, j};\n\n    vector<Op> ops;\n    ops.reserve(MAXK);\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y <= x;\n    };\n\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        if ((int)ops.size() >= MAXK) return;\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    };\n\n    auto neighbors = [&](int x, int y) {\n        array<pair<int,int>, 6> cand = {{\n            {x-1, y-1}, {x-1, y},\n            {x, y-1},   {x, y+1},\n            {x+1, y},   {x+1, y+1}\n        }};\n        vector<pair<int,int>> res;\n        for (auto [nx, ny] : cand) if (inside(nx, ny)) res.push_back({nx, ny});\n        return res;\n    };\n\n    // shortest path between two cells in the triangular graph\n    auto get_path = [&](pair<int,int> s, pair<int,int> t) {\n        static int dist[N][N];\n        static pair<int,int> pre[N][N];\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j <= i; j++) {\n                dist[i][j] = -1;\n                pre[i][j] = {-1,-1};\n            }\n        }\n        queue<pair<int,int>> q;\n        dist[s.first][s.second] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            auto [x,y] = q.front(); q.pop();\n            if (x == t.first && y == t.second) break;\n            for (auto [nx,ny] : neighbors(x,y)) {\n                if (dist[nx][ny] != -1) continue;\n                dist[nx][ny] = dist[x][y] + 1;\n                pre[nx][ny] = {x,y};\n                q.push({nx,ny});\n            }\n        }\n        vector<pair<int,int>> path;\n        if (dist[t.first][t.second] == -1) return path;\n        pair<int,int> cur = t;\n        while (!(cur == s)) {\n            path.push_back(cur);\n            cur = pre[cur.first][cur.second];\n        }\n        path.push_back(s);\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    // Greedy top-down construction\n    vector<char> fixedv(465, 0);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if ((int)ops.size() >= MAXK) break;\n\n            // choose minimum-valued ball among cells not fixed yet, restricted to rows >= x\n            int bestVal = INT_MAX;\n            pair<int,int> bestPos = {-1,-1};\n\n            for (int i = x; i < N; i++) {\n                int j0 = (i == x ? y : 0);\n                for (int j = j0; j <= i; j++) {\n                    int v = a[i][j];\n                    if (!fixedv[v] && v < bestVal) {\n                        bestVal = v;\n                        bestPos = {i,j};\n                    }\n                }\n            }\n\n            if (bestPos.first == -1) continue;\n\n            // move bestPos to (x,y) along a shortest path\n            auto path = get_path(bestPos, {x,y});\n            if (path.empty()) continue;\n\n            // swap backwards along path so target ball moves forward to destination\n            for (int k = 0; k + 1 < (int)path.size(); k++) {\n                // We want ball at path[k] to move to path[k+1] if traversing from source to target,\n                // so execute swaps in reverse order.\n            }\n            for (int k = (int)path.size() - 1; k >= 1; k--) {\n                auto [x1,y1] = path[k];\n                auto [x2,y2] = path[k-1];\n                if ((int)ops.size() >= MAXK) break;\n                do_swap(x1,y1,x2,y2);\n            }\n\n            fixedv[bestVal] = 1;\n        }\n        if ((int)ops.size() >= MAXK) break;\n    }\n\n    // Local improvement: bubble up inversions while possible within move budget.\n    // If parent > child, swap them; this reduces E locally.\n    bool updated = true;\n    while (updated && (int)ops.size() < MAXK) {\n        updated = false;\n        for (int x = N - 2; x >= 0; x--) {\n            for (int y = 0; y <= x; y++) {\n                if ((int)ops.size() >= MAXK) break;\n                if (a[x][y] > a[x+1][y]) {\n                    do_swap(x, y, x+1, y);\n                    updated = true;\n                }\n                if ((int)ops.size() >= MAXK) break;\n                if (a[x][y] > a[x+1][y+1]) {\n                    do_swap(x, y, x+1, y+1);\n                    updated = true;\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    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nHeuristic idea\n\nWe must place containers online (arrival order unknown; label revealed on arrival),\nsubject to current empties maintaining reachability from entrance.\n\nAfter all placements, we may choose any feasible retrieval order where each next\ncontainer must be currently reachable from entrance through empty cells.\n\nKey observation:\nIf we place containers in a reverse topological order of some rooted spanning tree\nof free cells (excluding entrance), then every placement is feasible, and later\nretrieval in root-to-leaf order is always feasible.\nSo if each cell has a fixed \"retrieval priority\" rank, and we always assign newly\narrived containers to cells according to their label (smaller label => earlier\nretrieval rank), retrieval sequence becomes approximately sorted by labels.\n\nConstruction:\n- Build BFS tree from entrance over all usable cells.\n- Sort cells by depth descending; this is a valid online placement order:\n  placing only on deepest remaining cells preserves reachability of all empty cells.\n- Retrieval order is reverse of that: depth ascending.\n- To improve quality, within each depth layer, use subtree size / local geometry tie-breaks,\n  and map labels to ranks among currently free cells by quantile:\n    choose k = floor(label * remaining_cells / total_labels)\n    and place in k-th cell of retrieval-order among free cells.\nThis approximates storing smaller labels closer to entrance.\n\nSince total cells <= 80, simple recomputation is fine.\n*/\n\nstruct Pos {\n    int i, j;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<int>> obstacle(D, vector<int>(D, 0));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = 1;\n    }\n\n    const int ei = 0, ej = (D - 1) / 2;\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D;\n    };\n\n    vector<Pos> dirs = {{1,0},{-1,0},{0,1},{0,-1}};\n\n    // Enumerate usable cells (non-obstacle, non-entrance)\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<Pos> cells;\n    for (int i = 0; i < D; ++i) for (int j = 0; j < D; ++j) {\n        if (i == ei && j == ej) continue;\n        if (obstacle[i][j]) continue;\n        id[i][j] = (int)cells.size();\n        cells.push_back({i,j});\n    }\n    int M = (int)cells.size(); // number of containers total\n\n    // BFS tree from entrance\n    vector<int> depth(M, -1), parent(M, -1);\n    queue<pair<int,int>> q;\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    q.push({ei, ej});\n    vis[ei][ej] = 1;\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (auto d : dirs) {\n            int nx = x + d.i, ny = y + d.j;\n            if (!inside(nx, ny) || vis[nx][ny] || obstacle[nx][ny]) continue;\n            vis[nx][ny] = 1;\n            q.push({nx, ny});\n            if (!(nx == ei && ny == ej)) {\n                int v = id[nx][ny];\n                depth[v] = (x == ei && y == ej) ? 1 : depth[id[x][y]] + 1;\n                if (x == ei && y == ej) parent[v] = -1;\n                else parent[v] = id[x][y];\n            }\n        }\n    }\n\n    // children and subtree sizes\n    vector<vector<int>> children(M);\n    for (int v = 0; v < M; ++v) if (parent[v] != -1) children[parent[v]].push_back(v);\n\n    vector<int> sub(M, 1);\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n    for (int v : order) {\n        if (parent[v] != -1) sub[parent[v]] += sub[v];\n    }\n\n    // Static retrieval preference order:\n    // smaller depth first; among same depth, larger subtree first; then centrality / coordinates\n    vector<int> retrieval_order(M);\n    iota(retrieval_order.begin(), retrieval_order.end(), 0);\n    sort(retrieval_order.begin(), retrieval_order.end(), [&](int a, int b) {\n        if (depth[a] != depth[b]) return depth[a] < depth[b];\n        if (sub[a] != sub[b]) return sub[a] > sub[b];\n        int ca = abs(cells[a].j - ej);\n        int cb = abs(cells[b].j - ej);\n        if (ca != cb) return ca < cb;\n        if (cells[a].i != cells[b].i) return cells[a].i < cells[b].i;\n        return cells[a].j < cells[b].j;\n    });\n\n    // Placement order corresponding to reverse retrieval order\n    vector<int> placement_order = retrieval_order;\n    reverse(placement_order.begin(), placement_order.end());\n\n    vector<int> label_at_cell(M, -1);\n    vector<int> cell_of_label(M, -1);\n    vector<int> occupied(M, 0);\n\n    // For online placement:\n    // among currently free cells, consider them in retrieval_order;\n    // choose quantile by label among all labels [0, M-1].\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        vector<int> free_retrieval;\n        free_retrieval.reserve(M - step);\n        for (int v : retrieval_order) {\n            if (!occupied[v]) free_retrieval.push_back(v);\n        }\n\n        int rem = (int)free_retrieval.size();\n        int idx = (long long)t * rem / M;\n        if (idx >= rem) idx = rem - 1;\n\n        int chosen = free_retrieval[idx];\n\n        occupied[chosen] = 1;\n        label_at_cell[chosen] = t;\n        cell_of_label[t] = chosen;\n\n        cout << cells[chosen].i << ' ' << cells[chosen].j << '\\n';\n        cout.flush();\n    }\n\n    // Retrieval phase:\n    // Output occupied cells in retrieval_order. This is feasible because\n    // retrieval_order is root-to-leaf in the BFS tree.\n    for (int v : retrieval_order) {\n        cout << cells[v].i << ' ' << cells[v].j << '\\n';\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXC = 100;\n\nstruct Solver {\n    int n, m;\n    vector<vector<int>> a;\n    bool origAdj[MAXC + 1][MAXC + 1]{};\n    bool canTouchZero[MAXC + 1]{};\n    int edgeCnt[MAXC + 1][MAXC + 1]{}; // undirected adjacency existence count by side contacts\n    int colorCells[MAXC + 1]{};\n    mt19937 rng{(uint32_t)chrono::steady_clock::now().time_since_epoch().count()};\n\n    bool inside(int i, int j) const {\n        return 0 <= i && i < n && 0 <= j && j < n;\n    }\n\n    void addEdgeCount(int x, int y, int delta) {\n        if (x == y) return;\n        edgeCnt[x][y] += delta;\n        edgeCnt[y][x] += delta;\n    }\n\n    void buildOriginalInfo(const vector<vector<int>>& orig) {\n        memset(origAdj, 0, sizeof(origAdj));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = orig[i][j];\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    origAdj[0][c] = origAdj[c][0] = true;\n                }\n                if (i + 1 < n) {\n                    int d = orig[i + 1][j];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n                if (j + 1 < n) {\n                    int d = orig[i][j + 1];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n            }\n        }\n        for (int c = 1; c <= m; c++) canTouchZero[c] = origAdj[0][c];\n    }\n\n    void buildCurrentEdgeCounts() {\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(colorCells, 0, sizeof(colorCells));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) colorCells[a[i][j]]++;\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = a[i][j];\n                if (i == 0) addEdgeCount(0, c, 1);\n                if (i == n - 1) addEdgeCount(0, c, 1);\n                if (j == 0) addEdgeCount(0, c, 1);\n                if (j == n - 1) addEdgeCount(0, c, 1);\n                if (i + 1 < n) addEdgeCount(c, a[i + 1][j], 1);\n                if (j + 1 < n) addEdgeCount(c, a[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool adjacencyStillValidAround(const vector<int>& touchedColors) {\n        vector<int> colors = touchedColors;\n        sort(colors.begin(), colors.end());\n        colors.erase(unique(colors.begin(), colors.end()), colors.end());\n\n        // Since only edges incident to touched colors can change, check those rows.\n        for (int x : colors) {\n            for (int y = 0; y <= m; y++) {\n                bool now = edgeCnt[x][y] > 0;\n                if (now != origAdj[x][y]) return false;\n            }\n        }\n        return true;\n    }\n\n    bool connectedColorAfterRemoval(int color, int si, int sj) {\n        if (color == 0) return true;\n        if (colorCells[color] == 0) return false;\n\n        int total = colorCells[color];\n        queue<pair<int,int>> q;\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        bool found = false;\n        for (int d = 0; d < 4 && !found; d++) {\n            static const int di[4] = {-1, 1, 0, 0};\n            static const int dj[4] = {0, 0, -1, 1};\n            int ni = si + di[d], nj = sj + dj[d];\n            if (inside(ni, nj) && a[ni][nj] == color) {\n                q.push({ni, nj});\n                vis[ni][nj] = true;\n                found = true;\n            }\n        }\n        if (!found) return total == 0;\n\n        int cnt = 0;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != color) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == total;\n    }\n\n    bool zeroConnected() {\n        if (colorCells[0] == 0) return true;\n        queue<pair<int,int>> q;\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (a[i][j] == 0 && (i == 0 || i == n - 1 || j == 0 || j == n - 1)) {\n                    q.push({i, j});\n                    vis[i][j] = true;\n                }\n            }\n        }\n        if (q.empty()) return false;\n\n        int cnt = 0;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != 0) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[0];\n    }\n\n    int sameDeg(int i, int j) const {\n        int c = a[i][j], s = 0;\n        if (i > 0 && a[i - 1][j] == c) s++;\n        if (i + 1 < n && a[i + 1][j] == c) s++;\n        if (j > 0 && a[i][j - 1] == c) s++;\n        if (j + 1 < n && a[i][j + 1] == c) s++;\n        return s;\n    }\n\n    bool tryErase(int i, int j) {\n        int old = a[i][j];\n        if (old == 0) return false;\n        if (!canTouchZero[old]) return false;\n        if (colorCells[old] <= 1) return false;\n\n        // New 0 cell may touch only colors already adjacent to 0 in the original.\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            int c = inside(ni, nj) ? a[ni][nj] : 0;\n            if (c != 0 && !canTouchZero[c]) return false;\n        }\n\n        vector<pair<int,int>> modifiedEdges;\n        auto applyLocalDelta = [&](int x, int y, int val, int sign) {\n            if (x == y) return;\n            addEdgeCount(x, y, sign);\n            modifiedEdges.push_back({x, y});\n        };\n\n        // Remove old incidences\n        if (i == 0) applyLocalDelta(0, old, 1, -1);\n        if (i == n - 1) applyLocalDelta(0, old, 1, -1);\n        if (j == 0) applyLocalDelta(0, old, 1, -1);\n        if (j == n - 1) applyLocalDelta(0, old, 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)) applyLocalDelta(old, a[ni][nj], 1, -1);\n        }\n\n        a[i][j] = 0;\n        colorCells[old]--;\n        colorCells[0]++;\n\n        // Add new incidences\n        if (i == 0) applyLocalDelta(0, 0, 1, +1);\n        if (i == n - 1) applyLocalDelta(0, 0, 1, +1);\n        if (j == 0) applyLocalDelta(0, 0, 1, +1);\n        if (j == n - 1) applyLocalDelta(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)) applyLocalDelta(0, a[ni][nj], 1, +1);\n        }\n\n        vector<int> touched = {0, old};\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            touched.push_back(inside(ni, nj) ? a[ni][nj] : 0);\n        }\n\n        bool ok = true;\n        if (!connectedColorAfterRemoval(old, i, j)) ok = false;\n        if (ok && !zeroConnected()) ok = false;\n        if (ok && !adjacencyStillValidAround(touched)) ok = false;\n\n        if (!ok) {\n            // rollback\n            // remove new incidences\n            if (i == 0) addEdgeCount(0, 0, 0);\n            if (i == n - 1) addEdgeCount(0, 0, 0);\n            if (j == 0) addEdgeCount(0, 0, 0);\n            if (j == n - 1) addEdgeCount(0, 0, 0);\n\n            // Easier safe rollback: rebuild counts.\n            a[i][j] = old;\n            colorCells[old]++;\n            colorCells[0]--;\n            buildCurrentEdgeCounts();\n            return false;\n        }\n\n        return true;\n    }\n\n    void solve() {\n        cin >> n >> m;\n        vector<vector<int>> orig(n, vector<int>(n));\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> orig[i][j];\n\n        buildOriginalInfo(orig);\n        a = orig;\n        buildCurrentEdgeCounts();\n\n        auto start = chrono::steady_clock::now();\n\n        vector<pair<array<int,3>, pair<int,int>>> cand;\n        for (int pass = 0; pass < 50; pass++) {\n            cand.clear();\n            for (int i = 0; i < n; i++) {\n                for (int j = 0; j < n; j++) {\n                    int c = a[i][j];\n                    if (c == 0 || !canTouchZero[c]) continue;\n                    int sd = sameDeg(i, j);\n                    int border = (i == 0 || i == n - 1 || j == 0 || j == n - 1) ? 0 : 1;\n                    int rnd = (int)(rng() & 1023);\n                    cand.push_back({{sd, border, rnd}, {i, j}});\n                }\n            }\n\n            sort(cand.begin(), cand.end(), [](const auto& lhs, const auto& rhs) {\n                return lhs.first < rhs.first;\n            });\n\n            bool improved = false;\n            for (auto &e : cand) {\n                auto [i, j] = e.second;\n                if (a[i][j] == 0) continue;\n                if (tryErase(i, j)) improved = true;\n\n                auto now = chrono::steady_clock::now();\n                if (chrono::duration<double>(now - start).count() > 1.95) break;\n            }\n\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.95) break;\n            if (!improved) break;\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    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used_queries = 0;\n\n    // compare weight(a) ? weight(b)\n    // return -1 if a<b, 0 if a=b, 1 if a>b\n    int cmp_item(int a, int b) {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        used_queries++;\n        if (s == \"<\") return -1;\n        if (s == \">\") return 1;\n        return 0;\n    }\n\n    void dummy_query(int a, int b) {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        used_queries++;\n    }\n\n    vector<int> approximate_sort_items() {\n        vector<int> ord;\n        ord.reserve(N);\n        ord.push_back(0);\n\n        for (int x = 1; x < N; x++) {\n            if (used_queries >= Q) {\n                ord.push_back(x);\n                continue;\n            }\n\n            int l = 0, r = (int)ord.size();\n            // binary insertion while budget remains\n            while (l < r && used_queries < Q) {\n                int m = (l + r) >> 1;\n                int c = cmp_item(x, ord[m]);\n                if (c == -1) {\n                    r = m;\n                } else {\n                    l = m + 1;\n                }\n            }\n            ord.insert(ord.begin() + l, x);\n        }\n        return ord; // light -> heavy approximately\n    }\n\n    vector<int> build_initial_assignment(const vector<int>& ord, const vector<double>& pw) {\n        vector<int> assign(N, 0);\n        vector<double> load(D, 0.0);\n\n        // process heavy -> light\n        for (int idx = N - 1; idx >= 0; --idx) {\n            int item = ord[idx];\n            int best = 0;\n            for (int d = 1; d < D; d++) {\n                if (load[d] < load[best]) best = d;\n            }\n            assign[item] = best;\n            load[best] += pw[item];\n        }\n        return assign;\n    }\n\n    double objective(const vector<int>& assign, const vector<double>& pw) {\n        vector<double> load(D, 0.0);\n        for (int i = 0; i < N; i++) load[assign[i]] += pw[i];\n        double mean = 0.0;\n        for (double x : load) mean += x;\n        mean /= D;\n        double var = 0.0;\n        for (double x : load) {\n            double t = x - mean;\n            var += t * t;\n        }\n        var /= D;\n        return var;\n    }\n\n    vector<double> get_loads(const vector<int>& assign, const vector<double>& pw) {\n        vector<double> load(D, 0.0);\n        for (int i = 0; i < N; i++) load[assign[i]] += pw[i];\n        return load;\n    }\n\n    void local_improve(vector<int>& assign, const vector<double>& pw) {\n        double cur = objective(assign, pw);\n\n        // several rounds of move / swap local search\n        for (int iter = 0; iter < 6; iter++) {\n            bool improved = false;\n\n            // move: try moving heavy pseudo-weight items first\n            vector<int> items(N);\n            iota(items.begin(), items.end(), 0);\n            sort(items.begin(), items.end(), [&](int a, int b) {\n                return pw[a] > pw[b];\n            });\n\n            auto load = get_loads(assign, pw);\n\n            for (int item : items) {\n                int from = assign[item];\n                for (int to = 0; to < D; to++) {\n                    if (to == from) continue;\n\n                    // quick estimate by checking max-min gap tendency\n                    double old_from = load[from], old_to = load[to];\n                    double nw_from = old_from - pw[item];\n                    double nw_to = old_to + pw[item];\n\n                    // if this cannot possibly help much, skip some cases\n                    double old_gap = max(old_from, old_to) - min(old_from, old_to);\n                    double new_gap = max(nw_from, nw_to) - min(nw_from, nw_to);\n                    if (new_gap > old_gap + 1e-9) continue;\n\n                    int old = assign[item];\n                    assign[item] = to;\n                    double nxt = objective(assign, pw);\n                    if (nxt + 1e-12 < cur) {\n                        cur = nxt;\n                        load = get_loads(assign, pw);\n                        improved = true;\n                        from = to;\n                    } else {\n                        assign[item] = old;\n                    }\n                }\n            }\n\n            // swap\n            for (int a = 0; a < N; a++) {\n                for (int b = a + 1; b < N; b++) {\n                    if (assign[a] == assign[b]) continue;\n                    swap(assign[a], assign[b]);\n                    double nxt = objective(assign, pw);\n                    if (nxt + 1e-12 < cur) {\n                        cur = nxt;\n                        improved = true;\n                    } else {\n                        swap(assign[a], assign[b]);\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        // 1) approximate sort by interactive singleton comparisons\n        vector<int> ord = approximate_sort_items(); // light -> heavy\n\n        // 2) consume remaining queries exactly\n        while (used_queries < Q) {\n            int a = 0, b = min(1, N - 1);\n            if (a == b) { // impossible under constraints N>=30, but keep safe\n                a = 0; b = 0;\n            }\n            dummy_query(a, b);\n        }\n\n        // 3) pseudo-weight from rank\n        // stronger emphasis on heavy items than linear rank\n        vector<double> pw(N, 1.0);\n        for (int r = 0; r < N; r++) {\n            int item = ord[r];\n            double x = (double)(r + 1);\n            pw[item] = x * x; // quadratic emphasis\n        }\n\n        // 4) greedy assignment\n        vector<int> assign = build_initial_assignment(ord, pw);\n\n        // 5) local improvement\n        local_improve(assign, pw);\n\n        // 6) output final partition\n        for (int i = 0; i < N; i++) {\n            if (i) cout << ' ';\n            cout << assign[i];\n        }\n        cout << '\\n';\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    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct State {\n    vector<vector<int>> st; // bottom -> top\n};\n\nstruct Solver {\n    int n, m;\n    State cur;\n    vector<pair<int,int>> ans; // (v, i), i=0 => remove\n    long long energy = 0;\n\n    Solver() {\n        cin >> n >> m;\n        cur.st.assign(m, {});\n        for (int i = 0; i < m; i++) {\n            cur.st[i].resize(n / m);\n            for (int j = 0; j < n / m; j++) cin >> cur.st[i][j];\n        }\n    }\n\n    pair<int,int> find_box(const State& S, int x) const {\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < (int)S.st[i].size(); j++) {\n                if (S.st[i][j] == x) return {i, j};\n            }\n        }\n        return {-1, -1};\n    }\n\n    int min_in_stack(const vector<int>& v) const {\n        if (v.empty()) return 1e9;\n        int mn = 1e9;\n        for (int x : v) mn = min(mn, x);\n        return mn;\n    }\n\n    int min_top_window(const vector<int>& v, int w = 6) const {\n        if (v.empty()) return 1e9;\n        int mn = 1e9;\n        int sz = (int)v.size();\n        for (int i = max(0, sz - w); i < sz; i++) mn = min(mn, v[i]);\n        return mn;\n    }\n\n    void apply_move(State& S, int from, int pos, int to) const {\n        vector<int> moved(S.st[from].begin() + pos, S.st[from].end());\n        S.st[from].erase(S.st[from].begin() + pos, S.st[from].end());\n        for (int x : moved) S.st[to].push_back(x);\n    }\n\n    void do_move(int from, int pos, int to) {\n        int v = cur.st[from][pos];\n        int k = (int)cur.st[from].size() - pos;\n        ans.push_back({v, to + 1});\n        energy += k + 1;\n        apply_move(cur, from, pos, to);\n    }\n\n    void do_remove(int need) {\n        auto [s, p] = find_box(cur, need);\n        ans.push_back({need, 0});\n        cur.st[s].pop_back();\n    }\n\n    long long evaluate_state(const State& S, int need) const {\n        // Lower penalty is better.\n        // Focus on next W boxes.\n        const int W = 16;\n        long long penalty = 0;\n\n        // Small structural preference:\n        // stacks with small minima should be kept shorter / more accessible.\n        for (int s = 0; s < m; s++) {\n            int mn = min_in_stack(S.st[s]);\n            int h = (int)S.st[s].size();\n            if (mn < 1e9) {\n                penalty += 2LL * max(0, 30 - mn) * h;\n            }\n        }\n\n        for (int x = need; x <= min(n, need + W - 1); x++) {\n            auto [s, p] = find_box(S, x);\n            if (s == -1) continue; // already removed in trial? normally not\n            int above = (int)S.st[s].size() - 1 - p;\n            int w = (need + W - x); // nearer boxes more important\n\n            penalty += 120LL * w * above;\n\n            // Penalize urgent small boxes lying above x.\n            for (int i = p + 1; i < (int)S.st[s].size(); i++) {\n                int y = S.st[s][i];\n                if (y <= x + 8) penalty += 35LL * w;\n                else if (y <= x + 20) penalty += 10LL * w;\n                else penalty += 2LL * w;\n            }\n\n            // Slightly penalize tall stack for urgent target.\n            penalty += 4LL * w * (int)S.st[s].size();\n        }\n\n        return penalty;\n    }\n\n    vector<int> candidate_cut_positions(const State& S, int s, int need_pos) const {\n        vector<int> cand;\n        int top = (int)S.st[s].size() - 1;\n        if (need_pos == top) return cand;\n\n        int start = need_pos + 1;\n\n        // whole blocker suffix\n        cand.push_back(start);\n\n        // record minima in blockers\n        int best = 1e9;\n        for (int i = start; i <= top; i++) {\n            if (S.st[s][i] < best) {\n                best = S.st[s][i];\n                cand.push_back(i);\n            }\n        }\n\n        // a few top-side cuts can help aggregate large boxes\n        if (top - start + 1 >= 2) cand.push_back(top);\n        if (top - start + 1 >= 3) cand.push_back(top - 1);\n        if (top - start + 1 >= 4) cand.push_back(top - 2);\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    }\n\n    long long move_bias_score(const State& S, int to, int moved_min, int moved_sz) const {\n        const auto& stk = S.st[to];\n        int mn_all = min_in_stack(stk);\n        int mn_top = min_top_window(stk, 6);\n        int h = (int)stk.size();\n\n        long long score = 0;\n        score -= 50LL * h;\n        score -= 12LL * (h + moved_sz);\n\n        if (stk.empty()) score -= 0;\n        else {\n            if (mn_all < moved_min) score += 2500;\n            if (mn_top < moved_min) score += 1800;\n            score -= 3LL * mn_all;\n            score -= 2LL * mn_top;\n        }\n        return score;\n    }\n\n    tuple<int,int,long long> choose_best_move(int need) const {\n        auto [s, p] = find_box(cur, need);\n        vector<int> cuts = candidate_cut_positions(cur, s, p);\n\n        long long bestScore = (1LL << 62);\n        int bestPos = -1;\n        int bestTo = -1;\n\n        // Lightly detect stacks containing next urgent boxes and discourage burying them.\n        int forbid1 = -1, forbid2 = -1, forbid3 = -1;\n        if (need + 1 <= n) forbid1 = find_box(cur, need + 1).first;\n        if (need + 2 <= n) forbid2 = find_box(cur, need + 2).first;\n        if (need + 3 <= n) forbid3 = find_box(cur, need + 3).first;\n\n        for (int pos : cuts) {\n            int moved_min = 1e9;\n            for (int i = pos; i < (int)cur.st[s].size(); i++) moved_min = min(moved_min, cur.st[s][i]);\n            int moved_sz = (int)cur.st[s].size() - pos;\n\n            // preselect candidate destinations by static quality\n            vector<pair<long long,int>> dsts;\n            for (int to = 0; to < m; to++) {\n                if (to == s) continue;\n                long long b = move_bias_score(cur, to, moved_min, moved_sz);\n                if (to == forbid1) b += 2000;\n                if (to == forbid2) b += 1200;\n                if (to == forbid3) b += 600;\n                dsts.push_back({b, to});\n            }\n            sort(dsts.begin(), dsts.end());\n\n            // Simulate only top few destinations\n            int LIM = min<int>(4, dsts.size());\n            for (int it = 0; it < LIM; it++) {\n                int to = dsts[it].second;\n                State T = cur;\n                apply_move(T, s, pos, to);\n\n                long long val = evaluate_state(T, need);\n\n                // Actual move cost matters too\n                val += 18LL * (moved_sz + 1);\n\n                // tiny tie-breaker: prefer fewer moved boxes\n                val += moved_sz;\n\n                if (val < bestScore) {\n                    bestScore = val;\n                    bestPos = pos;\n                    bestTo = to;\n                }\n            }\n        }\n\n        return {bestPos, bestTo, bestScore};\n    }\n\n    void solve() {\n        for (int need = 1; need <= n; need++) {\n            while (true) {\n                auto [s, p] = find_box(cur, need);\n                if (p == (int)cur.st[s].size() - 1) {\n                    do_remove(need);\n                    break;\n                }\n\n                auto [bestPos, bestTo, _] = choose_best_move(need);\n                if (bestPos == -1 || bestTo == -1) {\n                    // Fallback: move whole blocker suffix to shortest other stack\n                    int pos = p + 1;\n                    int to = -1;\n                    int besth = 1e9;\n                    for (int j = 0; j < m; j++) {\n                        if (j == s) continue;\n                        if ((int)cur.st[j].size() < besth) {\n                            besth = (int)cur.st[j].size();\n                            to = j;\n                        }\n                    }\n                    do_move(s, pos, to);\n                } else {\n                    do_move(s, bestPos, bestTo);\n                }\n\n                if ((int)ans.size() > 4900) {\n                    // emergency greedy finish\n                    while (true) {\n                        auto [ss, pp] = find_box(cur, need);\n                        if (pp == (int)cur.st[ss].size() - 1) {\n                            do_remove(need);\n                            break;\n                        }\n                        int pos = pp + 1;\n                        int to = -1;\n                        int besth = 1e9;\n                        for (int j = 0; j < m; j++) {\n                            if (j == ss) continue;\n                            if ((int)cur.st[j].size() < besth) {\n                                besth = (int)cur.st[j].size();\n                                to = j;\n                            }\n                        }\n                        do_move(ss, pos, to);\n                    }\n                    break;\n                }\n            }\n        }\n\n        for (auto &op : ans) {\n            cout << op.first << ' ' << op.second << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc027":"#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\nstatic const int DI[4] = {-1, 1, 0, 0};\nstatic const int DJ[4] = {0, 0, -1, 1};\nstatic const char DC[4] = {'U', 'D', 'L', 'R'};\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    vector<string> h(N - 1), vstr(N);\n    for (int i = 0; i < N - 1; i++) cin >> h[i];\n    for (int i = 0; i < N; i++) cin >> vstr[i];\n    vector<vector<int>> d2(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> d2[i][j];\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<int>> adj(V);\n    vector<vector<char>> adjDir(V);\n\n    auto add_edge = [&](int a, int b, char c) {\n        adj[a].push_back(b);\n        adjDir[a].push_back(c);\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = id(i, j);\n            if (i > 0 && h[i - 1][j] == '0') add_edge(u, id(i - 1, j), 'U');\n            if (i + 1 < N && h[i][j] == '0') add_edge(u, id(i + 1, j), 'D');\n            if (j > 0 && vstr[i][j - 1] == '0') add_edge(u, id(i, j - 1), 'L');\n            if (j + 1 < N && vstr[i][j] == '0') add_edge(u, id(i, j + 1), 'R');\n        }\n    }\n\n    vector<int> dirt(V);\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) dirt[id(i,j)] = d2[i][j];\n\n    auto rev = [&](char c) -> char {\n        if (c == 'U') return 'D';\n        if (c == 'D') return 'U';\n        if (c == 'L') return 'R';\n        return 'L';\n    };\n\n    // Precompute shortest path parents from every source.\n    // parentDir[s][t] = direction used to move from parent toward t in BFS tree rooted at s.\n    // parentNode[s][t] = predecessor of t on shortest path from s.\n    vector<vector<short>> dist(V, vector<short>(V, -1));\n    vector<vector<short>> parent(V, vector<short>(V, -1));\n    vector<vector<char>> parentDir(V, vector<char>(V, '?'));\n\n    {\n        vector<int> q(V);\n        for (int s = 0; s < V; s++) {\n            int ql = 0, qr = 0;\n            q[qr++] = s;\n            dist[s][s] = 0;\n            parent[s][s] = s;\n            while (ql < qr) {\n                int u = q[ql++];\n                // Prefer high-d cells as BFS tie-break for path reconstruction quality.\n                vector<int> ord(adj[u].size());\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int va = adj[u][a], vb = adj[u][b];\n                    if (dirt[va] != dirt[vb]) return dirt[va] > dirt[vb];\n                    return va < vb;\n                });\n                for (int idx : ord) {\n                    int w = adj[u][idx];\n                    if (dist[s][w] == -1) {\n                        dist[s][w] = dist[s][u] + 1;\n                        parent[s][w] = u;\n                        parentDir[s][w] = adjDir[u][idx];\n                        q[qr++] = w;\n                    }\n                }\n            }\n        }\n    }\n\n    auto get_path = [&](int s, int t) -> string {\n        if (s == t) return \"\";\n        string revpath;\n        int cur = t;\n        while (cur != s) {\n            revpath.push_back(parentDir[s][cur]);\n            cur = parent[s][cur];\n        }\n        reverse(revpath.begin(), revpath.end());\n        return revpath;\n    };\n\n    auto route_from_order = [&](const vector<int>& ord) -> string {\n        string route;\n        int cur = 0;\n        for (int x : ord) {\n            string p = get_path(cur, x);\n            route += p;\n            cur = x;\n        }\n        route += get_path(cur, 0);\n        return route;\n    };\n\n    auto score_route = [&](const string& route) -> long long {\n        int L = (int)route.size();\n        if (L <= 0 || L > 100000) return (long long)4e18;\n\n        vector<vector<int>> visits(V);\n        int cur = 0;\n        for (int t = 1; t <= L; t++) {\n            char c = route[t - 1];\n            auto [i, j] = pos(cur);\n            int ni = i, nj = j;\n            if (c == 'U') ni--;\n            else if (c == 'D') ni++;\n            else if (c == 'L') nj--;\n            else nj++;\n            cur = id(ni, nj);\n            visits[cur].push_back(t);\n        }\n        if (cur != 0) return (long long)4e18;\n        visits[0].insert(visits[0].begin(), 0);\n\n        long double total = 0;\n        for (int u = 0; u < V; u++) {\n            if (visits[u].empty()) return (long long)4e18;\n            long long s = 0;\n            auto &vec = visits[u];\n            for (int i = 0; i + 1 < (int)vec.size(); i++) {\n                long long g = vec[i + 1] - vec[i];\n                s += g * (g - 1) / 2;\n            }\n            long long g = L - vec.back() + vec[0];\n            s += g * (g - 1) / 2;\n            total += (long double)dirt[u] * (long double)s;\n        }\n        return llround(total / (long double)L);\n    };\n\n    auto route_len_from_order = [&](const vector<int>& ord) -> int {\n        int cur = 0;\n        int ans = 0;\n        for (int x : ord) {\n            ans += dist[cur][x];\n            cur = x;\n        }\n        ans += dist[cur][0];\n        return ans;\n    };\n\n    auto normalize_order = [&](vector<int> ord) -> vector<int> {\n        vector<int> seen(V, 0), out;\n        out.reserve(V - 1);\n        for (int x : ord) {\n            if (x == 0) continue;\n            if (!seen[x]) {\n                seen[x] = 1;\n                out.push_back(x);\n            }\n        }\n        for (int x = 1; x < V; x++) if (!seen[x]) out.push_back(x);\n        return out;\n    };\n\n    vector<int> base_cells;\n    for (int x = 1; x < V; x++) base_cells.push_back(x);\n\n    vector<vector<int>> candidates;\n\n    // 1) Row snake\n    {\n        vector<int> ord;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) ord.push_back(id(i,j));\n            else for (int j = N - 1; j >= 0; j--) ord.push_back(id(i,j));\n        }\n        candidates.push_back(normalize_order(ord));\n        reverse(ord.begin(), ord.end());\n        candidates.push_back(normalize_order(ord));\n    }\n\n    // 2) Column snake\n    {\n        vector<int> ord;\n        for (int j = 0; j < N; j++) {\n            if (j % 2 == 0) for (int i = 0; i < N; i++) ord.push_back(id(i,j));\n            else for (int i = N - 1; i >= 0; i--) ord.push_back(id(i,j));\n        }\n        candidates.push_back(normalize_order(ord));\n        reverse(ord.begin(), ord.end());\n        candidates.push_back(normalize_order(ord));\n    }\n\n    // 3) Sort by weighted geometry\n    {\n        vector<int> ord = base_cells;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            long long ka = 1LL * (ai + aj) * 1000000LL - dirt[a];\n            long long kb = 1LL * (bi + bj) * 1000000LL - dirt[b];\n            return ka < kb;\n        });\n        candidates.push_back(normalize_order(ord));\n    }\n    {\n        vector<int> ord = base_cells;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            long long ka = 1LL * (ai - aj + 100) * 1000000LL - dirt[a];\n            long long kb = 1LL * (bi - bj + 100) * 1000000LL - dirt[b];\n            return ka < kb;\n        });\n        candidates.push_back(normalize_order(ord));\n    }\n\n    // 4) DFS order from high-d biased spanning tree\n    auto make_tree_dfs_order = [&](double alpha, int mode) {\n        const double INF = 1e100;\n        vector<double> dd(V, INF);\n        vector<int> par(V, -1);\n        using P = pair<double,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n        dd[0] = 0;\n        pq.push({0,0});\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top();\n            pq.pop();\n            if (cd != dd[u]) continue;\n            vector<int> ord(adj[u].size());\n            iota(ord.begin(), ord.end(), 0);\n            sort(ord.begin(), ord.end(), [&](int x, int y) {\n                int a = adj[u][x], b = adj[u][y];\n                if (dirt[a] != dirt[b]) return dirt[a] > dirt[b];\n                return a < b;\n            });\n            for (int idx : ord) {\n                int to = adj[u][idx];\n                double cost = 1.0 / pow((double)dirt[to], alpha);\n                double nd = cd + cost;\n                if (nd + 1e-12 < dd[to]) {\n                    dd[to] = nd;\n                    par[to] = u;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        vector<vector<int>> tree(V);\n        for (int x = 1; x < V; x++) tree[par[x]].push_back(x);\n        for (int u = 0; u < V; u++) {\n            sort(tree[u].begin(), tree[u].end(), [&](int a, int b) {\n                auto [ai, aj] = pos(a);\n                auto [bi, bj] = pos(b);\n                if (dirt[a] != dirt[b]) return dirt[a] > dirt[b];\n                if (mode == 0) return dist[0][a] < dist[0][b];\n                if (mode == 1) return ai != bi ? ai < bi : aj < bj;\n                return aj != bj ? aj < bj : ai < bi;\n            });\n        }\n        vector<int> ord;\n        function<void(int)> dfs = [&](int u) {\n            if (u != 0) ord.push_back(u);\n            for (int ch : tree[u]) dfs(ch);\n        };\n        dfs(0);\n        return normalize_order(ord);\n    };\n\n    for (double alpha : {0.2, 0.4, 0.7, 1.0}) {\n        for (int mode = 0; mode < 3; mode++) {\n            candidates.push_back(make_tree_dfs_order(alpha, mode));\n        }\n    }\n\n    // 5) Greedy nearest with weight bias\n    auto greedy_order = [&](double beta, int seedMode) {\n        vector<int> rem = base_cells;\n        vector<char> used(V, 0);\n        vector<int> ord;\n        ord.reserve(V - 1);\n        int cur = 0;\n\n        int first = -1;\n        if (seedMode == 0) {\n            int best = -1;\n            double bestVal = -1e100;\n            for (int x : rem) {\n                double val = log((double)dirt[x]) * beta - dist[cur][x];\n                if (val > bestVal) bestVal = val, best = x;\n            }\n            first = best;\n        }\n        if (first != -1) {\n            ord.push_back(first);\n            used[first] = 1;\n            cur = first;\n        }\n\n        for (int step = (first != -1); step < V - 1; step++) {\n            int best = -1;\n            double bestVal = -1e100;\n            for (int x = 1; x < V; x++) if (!used[x]) {\n                // favor heavy and close cells\n                double val = beta * log((double)dirt[x]) - dist[cur][x];\n                // mild bias to not drift too far from origin too early\n                val -= 0.05 * dist[0][x];\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = x;\n                }\n            }\n            ord.push_back(best);\n            used[best] = 1;\n            cur = best;\n        }\n        return ord;\n    };\n\n    for (double beta : {1.0, 1.5, 2.0, 2.5}) {\n        candidates.push_back(greedy_order(beta, 0));\n    }\n\n    // Evaluate initial candidates\n    string bestRoute;\n    long long bestScore = (long long)4e18;\n    vector<int> bestOrder;\n\n    auto try_order = [&](const vector<int>& ord, bool build_exact = true) {\n        int L = route_len_from_order(ord);\n        if (L > 100000) return;\n        string route;\n        long long sc;\n        if (build_exact) {\n            route = route_from_order(ord);\n            sc = score_route(route);\n        } else {\n            route = route_from_order(ord);\n            sc = score_route(route);\n        }\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n            bestOrder = ord;\n        }\n    };\n\n    for (auto &ord : candidates) {\n        if (timer.elapsed() > 1.0) break;\n        try_order(ord);\n    }\n\n    // Local search on best few candidates by route length\n    vector<pair<int,int>> orderRank;\n    for (int i = 0; i < (int)candidates.size(); i++) {\n        orderRank.push_back({route_len_from_order(candidates[i]), i});\n    }\n    sort(orderRank.begin(), orderRank.end());\n\n    mt19937 rng(712367821);\n\n    auto delta_len_reverse = [&](const vector<int>& ord, int l, int r) -> int {\n        int m = ord.size();\n        int a_prev = (l == 0 ? 0 : ord[l - 1]);\n        int a = ord[l];\n        int b = ord[r];\n        int b_next = (r + 1 == m ? 0 : ord[r + 1]);\n\n        int oldCost = dist[a_prev][a] + dist[b][b_next];\n        int newCost = dist[a_prev][b] + dist[a][b_next];\n        return newCost - oldCost;\n    };\n\n    int elite = min(6, (int)orderRank.size());\n    for (int ei = 0; ei < elite; ei++) {\n        if (timer.elapsed() > 1.75) break;\n        vector<int> ord = candidates[orderRank[ei].second];\n        int curLen = route_len_from_order(ord);\n\n        // exact initial\n        try_order(ord);\n\n        int iter = 0;\n        while (timer.elapsed() < 1.85 && iter < 4000) {\n            iter++;\n            int m = ord.size();\n            int l = rng() % m;\n            int r = rng() % m;\n            if (l > r) swap(l, r);\n            if (l == r) continue;\n\n            int dlen = delta_len_reverse(ord, l, r);\n            bool accept = false;\n            if (dlen < 0) accept = true;\n            else {\n                // occasionally accept non-improving move for diversification\n                int thr = (iter < 1000 ? 1 : 0);\n                if (dlen <= thr && (rng() & 7) == 0) accept = true;\n            }\n            if (!accept) continue;\n\n            reverse(ord.begin() + l, ord.begin() + r + 1);\n            curLen += dlen;\n\n            if (curLen > 100000) continue;\n\n            if ((iter % 150) == 0) {\n                try_order(ord);\n            }\n        }\n        try_order(ord);\n    }\n\n    // Fallback\n    if (bestRoute.empty()) {\n        vector<int> ord;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) ord.push_back(id(i,j));\n            else for (int j = N - 1; j >= 0; j--) ord.push_back(id(i,j));\n        }\n        ord = normalize_order(ord);\n        bestRoute = route_from_order(ord);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#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        auto ed = chrono::steady_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstatic const int INF = 1e9;\n\nstruct Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n    vector<string> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    // Positions of each letter\n    vector<vector<Pos>> pos(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            pos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    // Precompute min movement distances between letters\n    int bestDist[26][26];\n    int startDist[26];\n    for (int c = 0; c < 26; c++) {\n        startDist[c] = INF;\n        for (auto &p : pos[c]) {\n            startDist[c] = min(startDist[c], abs(si - p.x) + abs(sj - p.y));\n        }\n    }\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            int d = INF;\n            for (auto &p : pos[a]) for (auto &q : pos[b]) {\n                d = min(d, abs(p.x - q.x) + abs(p.y - q.y));\n            }\n            bestDist[a][b] = d;\n        }\n    }\n\n    // Overlap matrix\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++) if (i != j) {\n            int best = 0;\n            for (int k = 1; k <= 4; k++) {\n                bool ok = true;\n                for (int x = 0; x < k; x++) {\n                    if (t[i][5 - k + x] != t[j][x]) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) best = k;\n            }\n            ov[i][j] = best;\n        }\n    }\n\n    auto approx_word_cost = [&](const string &s) -> int {\n        int c0 = s[0] - 'A';\n        int cost = startDist[c0] + 1;\n        for (int i = 1; i < (int)s.size(); i++) {\n            int a = s[i - 1] - 'A';\n            int b = s[i] - 'A';\n            cost += bestDist[a][b] + 1;\n        }\n        return cost;\n    };\n\n    auto approx_append_cost = [&](char lastc, const string &add) -> int {\n        if (add.empty()) return 0;\n        int cost = bestDist[lastc - 'A'][add[0] - 'A'] + 1;\n        for (int i = 1; i < (int)add.size(); i++) {\n            cost += bestDist[add[i - 1] - 'A'][add[i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    mt19937 rng(712367821);\n\n    auto build_string_from_order = [&](const vector<int> &ord) -> string {\n        if (ord.empty()) return \"\";\n        string s = t[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            int o = ov[ord[i - 1]][ord[i]];\n            s += t[ord[i]].substr(o);\n        }\n        return s;\n    };\n\n    auto approx_score_order = [&](const vector<int> &ord) -> long long {\n        if (ord.empty()) return (long long)4e18;\n        string s = build_string_from_order(ord);\n        // approximate total typing cost\n        long long cost = approx_word_cost(string(1, s[0]));\n        // fix because approx_word_cost on 1-char works but let's do direct full:\n        cost = startDist[s[0] - 'A'] + 1;\n        for (int i = 1; i < (int)s.size(); i++) {\n            cost += bestDist[s[i - 1] - 'A'][s[i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    auto greedy_build = [&](int start, double overlap_w, double move_w, int topk_random) {\n        vector<int> ord;\n        vector<char> used(M, 0);\n        ord.reserve(M);\n        ord.push_back(start);\n        used[start] = 1;\n        int cur = start;\n        for (int step = 1; step < M; step++) {\n            vector<pair<double,int>> cand;\n            cand.reserve(M);\n            for (int nx = 0; nx < M; nx++) if (!used[nx]) {\n                int o = ov[cur][nx];\n                string add = t[nx].substr(o);\n                int move = approx_append_cost(t[cur][4], add);\n                double sc = overlap_w * o - move_w * move;\n                // tiny tie breaker\n                sc += 1e-6 * (rng() % 1000);\n                cand.push_back({sc, nx});\n            }\n            sort(cand.begin(), cand.end(), [&](auto &a, auto &b) {\n                return a.first > b.first;\n            });\n            int choose_idx = 0;\n            if ((int)cand.size() > 1 && topk_random > 1) {\n                int lim = min(topk_random, (int)cand.size());\n                choose_idx = rng() % lim;\n            }\n            int nx = cand[choose_idx].second;\n            used[nx] = 1;\n            ord.push_back(nx);\n            cur = nx;\n        }\n        return ord;\n    };\n\n    vector<int> best_order;\n    long long best_approx = (long long)4e18;\n\n    // candidate starts\n    vector<pair<int,int>> startRank;\n    for (int i = 0; i < M; i++) {\n        int val = -startDist[t[i][0] - 'A'];\n        startRank.push_back({val, i});\n    }\n    sort(startRank.begin(), startRank.end(), greater<>());\n\n    // Multi-start randomized greedy\n    int trials = 0;\n    while (timer.elapsed() < 1.2) {\n        int sidx;\n        if (trials < 30) sidx = startRank[trials % min(M, 30)].second;\n        else sidx = rng() % M;\n\n        double overlap_w = 10.0 + (rng() % 900) / 100.0; // 10.0 .. 18.99\n        double move_w = 0.6 + (rng() % 120) / 100.0;     // 0.6 .. 1.79\n        int topk = 1 + (rng() % 4);\n\n        auto ord = greedy_build(sidx, overlap_w, move_w, topk);\n        long long sc = approx_score_order(ord);\n        if (sc < best_approx) {\n            best_approx = sc;\n            best_order = ord;\n        }\n        trials++;\n    }\n\n    // Simple local search on order using approximate score\n    auto try_improve = [&](vector<int> ord) {\n        long long curScore = approx_score_order(ord);\n        bool improved = true;\n        while (improved && timer.elapsed() < 1.75) {\n            improved = false;\n\n            // random relocate\n            for (int it = 0; it < 80 && timer.elapsed() < 1.75; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                auto tmp = ord;\n                int v = tmp[i];\n                tmp.erase(tmp.begin() + i);\n                tmp.insert(tmp.begin() + j, v);\n                long long ns = approx_score_order(tmp);\n                if (ns < curScore) {\n                    ord.swap(tmp);\n                    curScore = ns;\n                    improved = true;\n                }\n            }\n\n            // random swap\n            for (int it = 0; it < 80 && timer.elapsed() < 1.75; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                auto tmp = ord;\n                swap(tmp[i], tmp[j]);\n                long long ns = approx_score_order(tmp);\n                if (ns < curScore) {\n                    ord.swap(tmp);\n                    curScore = ns;\n                    improved = true;\n                }\n            }\n        }\n        return make_pair(ord, curScore);\n    };\n\n    if (!best_order.empty()) {\n        auto improved = try_improve(best_order);\n        if (improved.second < best_approx) {\n            best_order = improved.first;\n            best_approx = improved.second;\n        }\n    }\n\n    string S = build_string_from_order(best_order);\n\n    // Exact DP for minimal typing path on the board for S\n    int L = (int)S.size();\n    vector<vector<int>> candIdx(L);\n    for (int i = 0; i < L; i++) {\n        int c = S[i] - 'A';\n        candIdx[i].resize(pos[c].size());\n        iota(candIdx[i].begin(), candIdx[i].end(), 0);\n    }\n\n    vector<vector<int>> dp(L), pre(L);\n    {\n        int c = S[0] - 'A';\n        int sz = pos[c].size();\n        dp[0].assign(sz, INF);\n        pre[0].assign(sz, -1);\n        for (int j = 0; j < sz; j++) {\n            auto &p = pos[c][j];\n            dp[0][j] = abs(si - p.x) + abs(sj - p.y) + 1;\n        }\n    }\n\n    for (int i = 1; i < L; i++) {\n        int pc = S[i - 1] - 'A';\n        int cc = S[i] - 'A';\n        int psz = pos[pc].size();\n        int csz = pos[cc].size();\n        dp[i].assign(csz, INF);\n        pre[i].assign(csz, -1);\n        for (int v = 0; v < csz; v++) {\n            auto &q = pos[cc][v];\n            int best = INF, bestu = -1;\n            for (int u = 0; u < psz; u++) {\n                auto &p = pos[pc][u];\n                int val = dp[i - 1][u] + abs(p.x - q.x) + abs(p.y - q.y) + 1;\n                if (val < best) {\n                    best = val;\n                    bestu = u;\n                }\n            }\n            dp[i][v] = best;\n            pre[i][v] = bestu;\n        }\n    }\n\n    int lastIdx = 0;\n    for (int j = 1; j < (int)dp[L - 1].size(); j++) {\n        if (dp[L - 1][j] < dp[L - 1][lastIdx]) lastIdx = j;\n    }\n\n    vector<Pos> ans(L);\n    int curIdx = lastIdx;\n    for (int i = L - 1; i >= 0; i--) {\n        int c = S[i] - 'A';\n        ans[i] = pos[c][curIdx];\n        if (i > 0) curIdx = pre[i][curIdx];\n    }\n\n    // Output operations\n    // Number of operations = |S| <= 5000 safely\n    for (auto &p : ans) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<int> drillMaskIdx; // indices t such that this placement covers drilledList[t]\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    int h = 0, w = 0;\n    vector<Placement> plc;\n};\n\nstruct Solver {\n    int N, M;\n    double eps;\n    vector<Field> fields;\n\n    int maxOps, ops = 0;\n    vector<int> drilled;      // -1 unknown, else exact reserve\n    vector<int> drilledList;  // cell ids\n    vector<char> hasOil;      // final after full drilling fallback\n\n    Solver() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> M >> eps;\n        fields.resize(M);\n        for (int m = 0; m < M; m++) {\n            int d;\n            cin >> d;\n            fields[m].shape.resize(d);\n            int hi = 0, hj = 0;\n            for (int k = 0; k < d; k++) {\n                int i, j;\n                cin >> i >> j;\n                fields[m].shape[k] = {i, j};\n                hi = max(hi, i);\n                hj = max(hj, j);\n            }\n            fields[m].h = hi + 1;\n            fields[m].w = hj + 1;\n        }\n\n        maxOps = 2 * N * N;\n        drilled.assign(N * N, -1);\n        hasOil.assign(N * N, 0);\n\n        buildPlacements();\n    }\n\n    inline int id(int i, int j) const { return i * N + j; }\n    inline pair<int,int> rc(int c) const { return {c / N, c % N}; }\n\n    void buildPlacements() {\n        for (int m = 0; m < M; m++) {\n            auto &f = fields[m];\n            for (int di = 0; di + f.h <= N; di++) {\n                for (int dj = 0; dj + f.w <= N; dj++) {\n                    Placement p;\n                    for (auto [i, j] : f.shape) {\n                        p.cells.push_back(id(di + i, dj + j));\n                    }\n                    f.plc.push_back(move(p));\n                }\n            }\n        }\n    }\n\n    int drillCell(int c) {\n        auto [i, j] = rc(c);\n        cout << \"q 1 \" << i << \" \" << j << '\\n';\n        cout.flush();\n        int x;\n        cin >> x;\n        ++ops;\n        if (drilled[c] == -1) drilledList.push_back(c);\n        drilled[c] = x;\n        if (x > 0) hasOil[c] = 1;\n        return x;\n    }\n\n    bool answerCells(const vector<int>& cells) {\n        cout << \"a \" << cells.size();\n        for (int c : cells) {\n            auto [i, j] = rc(c);\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << '\\n';\n        cout.flush();\n        int res;\n        cin >> res;\n        ++ops;\n        return res == 1;\n    }\n\n    // ---------- Exact search for small instances ----------\n\n    vector<vector<int>> feasible;   // feasible placements per field under zero-cells only\n    vector<int> order;\n    vector<int> remainCanCover;     // flattened [pos * D + t]\n    vector<int> curSum;\n    vector<int> chosen;\n    vector<int> solChosen;\n    int solutionsFound = 0;\n    int dfsNodeBudget = 200000;     // hard cap for safety\n    int dfsNodes = 0;\n\n    bool placementCompatibleWithZero(int m, int pidx) {\n        for (int c : fields[m].plc[pidx].cells) {\n            if (drilled[c] == 0) return false;\n        }\n        return true;\n    }\n\n    void prepareSearch() {\n        int D = (int)drilledList.size();\n\n        feasible.assign(M, {});\n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                if (placementCompatibleWithZero(m, p)) {\n                    feasible[m].push_back(p);\n                }\n            }\n        }\n\n        order.resize(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return feasible[a].size() < feasible[b].size();\n        });\n\n        for (int m = 0; m < M; m++) {\n            for (int pidx : feasible[m]) {\n                auto &pl = fields[m].plc[pidx];\n                pl.drillMaskIdx.clear();\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    // linear scan over cells of shape; shapes are small enough\n                    for (int x : pl.cells) {\n                        if (x == c) {\n                            pl.drillMaskIdx.push_back(t);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        remainCanCover.assign((M + 1) * max(1, D), 0);\n        if (D > 0) {\n            for (int pos = M - 1; pos >= 0; pos--) {\n                int m = order[pos];\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    int can = 0;\n                    for (int pidx : feasible[m]) {\n                        for (int x : fields[m].plc[pidx].cells) {\n                            if (x == c) {\n                                can = 1;\n                                goto done;\n                            }\n                        }\n                    }\n                done:\n                    remainCanCover[pos * D + t] = remainCanCover[(pos + 1) * D + t] + can;\n                }\n            }\n        }\n\n        curSum.assign(D, 0);\n        chosen.assign(M, -1);\n        solChosen.clear();\n        solutionsFound = 0;\n        dfsNodes = 0;\n    }\n\n    void dfsSearch(int pos) {\n        if (solutionsFound >= 2) return;\n        if (++dfsNodes > dfsNodeBudget) return;\n\n        int D = (int)drilledList.size();\n        if (pos == M) {\n            for (int t = 0; t < D; t++) {\n                if (curSum[t] != drilled[drilledList[t]]) return;\n            }\n            ++solutionsFound;\n            if (solutionsFound == 1) solChosen = chosen;\n            return;\n        }\n\n        int m = order[pos];\n\n        // Try placements in heuristic order: match positive drilled cells more\n        vector<pair<int,int>> cand;\n        cand.reserve(feasible[m].size());\n        for (int pidx : feasible[m]) {\n            int score = 0;\n            for (int t : fields[m].plc[pidx].drillMaskIdx) {\n                if (drilled[drilledList[t]] > 0) score++;\n                else score -= 1000;\n            }\n            cand.push_back({-score, pidx});\n        }\n        sort(cand.begin(), cand.end());\n\n        for (auto [_, pidx] : cand) {\n            auto &pl = fields[m].plc[pidx];\n            bool ok = true;\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]++;\n            }\n\n            for (int t = 0; t < D; t++) {\n                int target = drilled[drilledList[t]];\n                if (curSum[t] > target) { ok = false; break; }\n                int rem = remainCanCover[(pos + 1) * D + t];\n                if (curSum[t] + rem < target) { ok = false; break; }\n            }\n\n            if (ok) {\n                chosen[m] = pidx;\n                dfsSearch(pos + 1);\n                chosen[m] = -1;\n            }\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]--;\n            }\n\n            if (solutionsFound >= 2 || dfsNodes > dfsNodeBudget) return;\n        }\n    }\n\n    bool tryExactSolve(vector<int>& ansCells, bool requireUnique) {\n        prepareSearch();\n\n        for (int m = 0; m < M; m++) {\n            if (feasible[m].empty()) return false;\n        }\n\n        dfsSearch(0);\n\n        if (dfsNodes > dfsNodeBudget) return false;\n        if (solutionsFound == 0) return false;\n        if (requireUnique && solutionsFound != 1) return false;\n\n        vector<char> used(N * N, 0);\n        for (int m = 0; m < M; m++) {\n            int pidx = solChosen[m];\n            if (pidx < 0) return false;\n            for (int c : fields[m].plc[pidx].cells) used[c] = 1;\n        }\n\n        for (int c : drilledList) {\n            if ((drilled[c] == 0 && used[c]) || (drilled[c] > 0 && !used[c])) {\n                return false;\n            }\n        }\n\n        ansCells.clear();\n        for (int c = 0; c < N * N; c++) if (used[c]) ansCells.push_back(c);\n        return true;\n    }\n\n    // ---------- Strategy ----------\n\n    vector<int> informativeOrder() {\n        // deterministic spread: checkerboard center-first-ish\n        vector<int> cells;\n        cells.reserve(N * N);\n        vector<pair<int,int>> tmp;\n        double ci = (N - 1) / 2.0, cj = (N - 1) / 2.0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int parity = (i + j) & 1;\n                int dist = (int)(1000 * (abs(i - ci) + abs(j - cj)));\n                tmp.push_back({parity * 100000 + dist, id(i, j)});\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        for (auto &x : tmp) cells.push_back(x.second);\n        return cells;\n    }\n\n    void fullDrillFallback() {\n        for (int c = 0; c < N * N && ops < maxOps - 1; c++) {\n            if (drilled[c] == -1) drillCell(c);\n        }\n        vector<int> ans;\n        for (int c = 0; c < N * N; c++) if (drilled[c] > 0) ans.push_back(c);\n        answerCells(ans);\n    }\n\n    void solve() {\n        // Only attempt exact reasoning when likely cheap.\n        long long totalPlacements = 0;\n        for (int m = 0; m < M; m++) totalPlacements += fields[m].plc.size();\n\n        bool useSearch = (M <= 8 && totalPlacements <= 700);\n\n        if (!useSearch) {\n            fullDrillFallback();\n            return;\n        }\n\n        // Small-instance mode:\n        // Drill a modest number of informative cells, trying to pin down unique placement combo.\n        vector<int> orderCells = informativeOrder();\n        int initialDrills = min<int>(N * N, max(12, N));\n\n        for (int t = 0; t < initialDrills && ops < maxOps - 1; t++) {\n            int c = orderCells[t];\n            if (drilled[c] == -1) drillCell(c);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // If not yet unique, continue a bit more adaptively: drill cells appearing often in candidate answer.\n        for (int extra = initialDrills; extra < min(N * N, initialDrills + 20) && ops < maxOps - 1; extra++) {\n            int best = -1, bestScore = -1;\n\n            for (int c = 0; c < N * N; c++) if (drilled[c] == -1) {\n                int score = 0;\n                for (int m = 0; m < M; m++) {\n                    for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                        if (!placementCompatibleWithZero(m, p)) continue;\n                        for (int x : fields[m].plc[p].cells) {\n                            if (x == c) { score++; break; }\n                        }\n                    }\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = c;\n                }\n            }\n\n            if (best == -1) break;\n            drillCell(best);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // Fallback: guaranteed correct\n        fullDrillFallback();\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic const int W = 1000;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int W_in, D, N;\n    cin >> W_in >> D >> 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    // We use a static vertical partition:\n    // rectangle k = [0,W] x [prefix[k], prefix[k+1]]\n    // area = 1000 * width[k], width[k] integer, sum width = 1000.\n    //\n    // Optimize widths greedily by marginal penalty reduction.\n\n    vector<int> width(N, 1);\n    int remaining = W - N; // extra width units to distribute\n\n    // gain[k][t]: reduction in total missing area (not *100) when capacity of k\n    // increases from 1000*t to 1000*(t+1), where current width = t.\n    // Since width starts from 1, t >= 1 in use. But precompute for t=0..999.\n    vector<vector<int>> gain(N, vector<int>(W, 0));\n\n    for (int k = 0; k < N; k++) {\n        for (int t = 0; t < W; t++) {\n            int c0 = W * t;       // 1000 * t\n            int c1 = W * (t + 1); // 1000 * (t+1)\n            ll g = 0;\n            for (int d = 0; d < D; d++) {\n                int x = a[d][k];\n                int before = max(0, x - c0);\n                int after  = max(0, x - c1);\n                g += (before - after);\n            }\n            gain[k][t] = (int)g;\n        }\n    }\n\n    // Priority queue of current marginal gains.\n    using T = pair<int,int>; // gain, k\n    priority_queue<T> pq;\n    for (int k = 0; k < N; k++) {\n        pq.push({gain[k][1], k}); // next gain when width 1 -> 2\n    }\n\n    while (remaining > 0) {\n        auto [g, k] = pq.top(); pq.pop();\n        int t = width[k];\n        // stale check\n        int realg = (t < W ? gain[k][t] : 0);\n        if (g != realg) {\n            pq.push({realg, k});\n            continue;\n        }\n        width[k]++;\n        remaining--;\n        t = width[k];\n        pq.push({(t < W ? gain[k][t] : 0), k});\n    }\n\n    // Build coordinates\n    vector<int> pref(N + 1, 0);\n    for (int k = 0; k < N; k++) pref[k + 1] = pref[k] + width[k];\n\n    // Output same layout every day, giving zero partition transition cost.\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            int i0 = 0, j0 = pref[k], i1 = W, j1 = pref[k + 1];\n            cout << i0 << ' ' << j0 << ' ' << i1 << ' ' << j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 9;\nstatic constexpr int P = 7;\nstatic constexpr int MOD = 998244353;\nstatic constexpr int MAXA = 20 * 7 * 7;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() { st = chrono::steady_clock::now(); }\n    double elapsed_ms() const {\n        return chrono::duration<double, milli>(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 next_int(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nstruct Action {\n    int m, p, q;\n    int idx[9];\n    int add[9];\n};\n\nstruct Move {\n    int m, p, q;\n};\n\nusing Board = array<int, 81>;\n\nstatic inline long long cell_gain(int cur, int add) {\n    int sum = cur + add;\n    return (sum >= MOD) ? (long long)add - MOD : (long long)add;\n}\n\nstatic inline long long action_gain(const Board& b, const Action& a) {\n    long long g = 0;\n    for (int k = 0; k < 9; k++) g += cell_gain(b[a.idx[k]], a.add[k]);\n    return g;\n}\n\nstatic inline void apply_action(Board& b, const Action& a) {\n    for (int k = 0; k < 9; k++) {\n        int &v = b[a.idx[k]];\n        v += a.add[k];\n        if (v >= MOD) v -= MOD;\n    }\n}\n\nstruct Candidate {\n    long long gain;\n    int act;\n};\n\nstruct Node {\n    Board b;\n    long long score;          // accumulated gain from initial board\n    long long eval;           // score + heuristic\n    vector<unsigned short> seq; // action ids\n};\n\nstatic vector<Action> actions;\n\nvector<Candidate> top_actions(const Board& b, int need, int random_extra = 0) {\n    vector<Candidate> v;\n    v.reserve(actions.size());\n    for (int i = 0; i < (int)actions.size(); i++) {\n        long long g = action_gain(b, actions[i]);\n        if (g > 0) v.push_back({g, i});\n    }\n    if (v.empty()) return v;\n\n    int keep = min((int)v.size(), max(need, need + random_extra));\n    nth_element(v.begin(), v.begin() + keep - 1, v.end(), [](const Candidate& x, const Candidate& y) {\n        return x.gain > y.gain;\n    });\n    v.resize(keep);\n    sort(v.begin(), v.end(), [](const Candidate& x, const Candidate& y) {\n        if (x.gain != y.gain) return x.gain > y.gain;\n        return x.act < y.act;\n    });\n\n    if ((int)v.size() > need) {\n        // Randomly keep some among the tail to diversify\n        vector<Candidate> res;\n        res.reserve(need);\n        int fixed = max(1, need / 2);\n        for (int i = 0; i < min(fixed, (int)v.size()); i++) res.push_back(v[i]);\n        while ((int)res.size() < need) {\n            int idx = rng.next_int(fixed, (int)v.size() - 1);\n            res.push_back(v[idx]);\n            swap(v[idx], v.back());\n            v.pop_back();\n            if (fixed >= (int)v.size()) break;\n        }\n        while ((int)res.size() < need && (int)res.size() < (int)v.size()) {\n            res.push_back(v[res.size()]);\n        }\n        return res;\n    }\n    return v;\n}\n\nlong long best_single_gain(const Board& b) {\n    long long best = 0;\n    for (const auto& a : actions) {\n        long long g = action_gain(b, a);\n        if (g > best) best = g;\n    }\n    return best;\n}\n\nvector<Move> greedy_complete(Board b, int remain, bool randomize=false) {\n    vector<Move> seq;\n    seq.reserve(remain);\n\n    for (int step = 0; step < remain; step++) {\n        vector<Candidate> cand = top_actions(b, randomize ? 12 : 24, randomize ? 24 : 0);\n        if (cand.empty()) break;\n\n        long long bestEval = LLONG_MIN;\n        int bestAct = -1;\n\n        for (auto &c : cand) {\n            Board nb = b;\n            apply_action(nb, actions[c.act]);\n\n            long long g2 = 0;\n            // one-step lookahead\n            for (const auto& a : actions) {\n                long long x = action_gain(nb, a);\n                if (x > g2) g2 = x;\n            }\n\n            long long eval = c.gain + g2;\n            if (randomize) {\n                eval += (long long)(rng.next_int(0, 1000)); // tiny noise\n            }\n            if (eval > bestEval) {\n                bestEval = eval;\n                bestAct = c.act;\n            }\n        }\n\n        if (bestAct < 0) break;\n        apply_action(b, actions[bestAct]);\n        seq.push_back({actions[bestAct].m, actions[bestAct].p, actions[bestAct].q});\n    }\n    return seq;\n}\n\nvector<Move> solve_once(const Board& initial, double time_limit_ms, const Timer& timer) {\n    // Beam search for prefix\n    int BEAM_WIDTH = 40;\n    int BRANCH = 12;\n    int DEPTH = 10;\n\n    vector<Node> beam, nxt;\n    beam.reserve(BEAM_WIDTH);\n    nxt.reserve(BEAM_WIDTH * BRANCH);\n\n    Node root;\n    root.b = initial;\n    root.score = 0;\n    root.eval = 0;\n    beam.push_back(root);\n\n    for (int d = 0; d < DEPTH; d++) {\n        if (timer.elapsed_ms() > time_limit_ms * 0.55) break;\n\n        nxt.clear();\n        for (const auto& node : beam) {\n            auto cand = top_actions(node.b, BRANCH, 12);\n            if (cand.empty()) {\n                nxt.push_back(node);\n                continue;\n            }\n            for (auto &c : cand) {\n                Node child;\n                child.b = node.b;\n                apply_action(child.b, actions[c.act]);\n                child.score = node.score + c.gain;\n                child.seq = node.seq;\n                child.seq.push_back((unsigned short)c.act);\n\n                long long h = best_single_gain(child.b);\n                child.eval = child.score + h;\n                nxt.push_back(std::move(child));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        int keep = min((int)nxt.size(), BEAM_WIDTH);\n        nth_element(nxt.begin(), nxt.begin() + keep - 1, nxt.end(), [](const Node& a, const Node& b) {\n            if (a.eval != b.eval) return a.eval > b.eval;\n            return a.score > b.score;\n        });\n        nxt.resize(keep);\n        sort(nxt.begin(), nxt.end(), [](const Node& a, const Node& b) {\n            if (a.eval != b.eval) return a.eval > b.eval;\n            return a.score > b.score;\n        });\n        beam.swap(nxt);\n    }\n\n    long long bestTotalGain = LLONG_MIN;\n    vector<Move> bestAns;\n\n    int candidates_from_beam = min((int)beam.size(), 8);\n    for (int i = 0; i < candidates_from_beam; i++) {\n        if (timer.elapsed_ms() > time_limit_ms * 0.9) break;\n\n        Board b = initial;\n        vector<Move> ans;\n        long long gainSum = 0;\n\n        for (auto act_id : beam[i].seq) {\n            long long g = action_gain(b, actions[act_id]);\n            if (g <= 0) break;\n            apply_action(b, actions[act_id]);\n            gainSum += g;\n            ans.push_back({actions[act_id].m, actions[act_id].p, actions[act_id].q});\n        }\n\n        auto tail = greedy_complete(b, 81 - (int)ans.size(), true);\n        for (auto &mv : tail) ans.push_back(mv);\n\n        // recompute exact gain of ans\n        b = initial;\n        gainSum = 0;\n        for (auto &mv : ans) {\n            int act_id = -1;\n            // encode from (m,p,q)\n            act_id = mv.m * 49 + mv.p * 7 + mv.q;\n            long long g = action_gain(b, actions[act_id]);\n            if (g <= 0) break;\n            apply_action(b, actions[act_id]);\n            gainSum += g;\n        }\n\n        if (gainSum > bestTotalGain) {\n            bestTotalGain = gainSum;\n            bestAns = ans;\n        }\n    }\n\n    // Also try pure greedy/randomized completions directly\n    while (timer.elapsed_ms() < time_limit_ms) {\n        Board b = initial;\n        auto ans = greedy_complete(b, 81, true);\n\n        long long gainSum = 0;\n        b = initial;\n        for (auto &mv : ans) {\n            int act_id = mv.m * 49 + mv.p * 7 + mv.q;\n            long long g = action_gain(b, actions[act_id]);\n            if (g <= 0) break;\n            apply_action(b, actions[act_id]);\n            gainSum += g;\n        }\n\n        if (gainSum > bestTotalGain) {\n            bestTotalGain = gainSum;\n            bestAns = ans;\n        }\n    }\n\n    return bestAns;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin, Min, Kin;\n    cin >> Nin >> Min >> Kin;\n\n    Board initial{};\n    for (int i = 0; i < Nin; i++) {\n        for (int j = 0; j < Nin; j++) {\n            cin >> initial[i * N + j];\n        }\n    }\n\n    vector<array<array<int,3>,3>> stamps(Min);\n    for (int m = 0; m < Min; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    actions.clear();\n    actions.reserve(Min * 49);\n    for (int m = 0; m < Min; m++) {\n        for (int p = 0; p < 7; p++) {\n            for (int q = 0; q < 7; q++) {\n                Action a;\n                a.m = m;\n                a.p = p;\n                a.q = q;\n                int t = 0;\n                for (int i = 0; i < 3; i++) {\n                    for (int j = 0; j < 3; j++) {\n                        a.idx[t] = (p + i) * 9 + (q + j);\n                        a.add[t] = stamps[m][i][j];\n                        t++;\n                    }\n                }\n                actions.push_back(a);\n            }\n        }\n    }\n\n    Timer timer;\n    // Leave some safety margin\n    double limit_ms = 1850.0;\n\n    vector<Move> ans = solve_once(initial, limit_ms, timer);\n    if ((int)ans.size() > Kin) ans.resize(Kin);\n\n    cout << ans.size() << '\\n';\n    for (auto &mv : ans) {\n        cout << mv.m << ' ' << mv.p << ' ' << mv.q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n; // always 5\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<string> ans(N);\n\n    auto add_turn = [&](char c0, char c1='.', char c2='.', char c3='.', char c4='.') {\n        ans[0].push_back(c0);\n        ans[1].push_back(c1);\n        ans[2].push_back(c2);\n        ans[3].push_back(c3);\n        ans[4].push_back(c4);\n    };\n\n    // Bomb all small cranes immediately.\n    add_turn('.', 'B', 'B', 'B', 'B');\n\n    vector<int> ptr(N, 0);         // next unseen container in each receiving row\n    vector<int> need(N);           // next required container for each dispatch row\n    for (int r = 0; r < N; r++) need[r] = r * N;\n\n    int cr = 0, cc = 0;            // large crane position\n    int delivered = 0;\n\n    auto move_large = [&](int tr, int tc) {\n        while (cr < tr) { add_turn('D'); cr++; }\n        while (cr > tr) { add_turn('U'); cr--; }\n        while (cc < tc) { add_turn('R'); cc++; }\n        while (cc > tc) { add_turn('L'); cc--; }\n    };\n\n    while (delivered < N * N) {\n        int bestRow = -1;\n        int bestDist = 1e9;\n        int bestX = -1;\n\n        for (int i = 0; i < N; i++) {\n            if (ptr[i] >= N) continue;\n            int x = A[i][ptr[i]];\n            int gr = x / N;\n            if (x == need[gr]) {\n                int dist = abs(cr - i) + abs(cc - 0);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestRow = i;\n                    bestX = x;\n                }\n            }\n        }\n\n        // This should not happen, but for safety:\n        // if no currently front container is \"deliverable\", just take the nearest front one.\n        // This keeps the program producing a valid answer.\n        if (bestRow == -1) {\n            for (int i = 0; i < N; i++) {\n                if (ptr[i] >= N) continue;\n                int x = A[i][ptr[i]];\n                int dist = abs(cr - i) + abs(cc - 0);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    bestRow = i;\n                    bestX = x;\n                }\n            }\n        }\n\n        // Move to receiving gate\n        move_large(bestRow, 0);\n\n        // Pick the front container\n        add_turn('P');\n        ptr[bestRow]++;\n\n        // Deliver to its correct dispatch gate\n        int goalRow = bestX / N;\n        move_large(goalRow, N - 1);\n        add_turn('Q');\n\n        // If delivered in-order to correct gate, advance need.\n        if (bestX == need[goalRow]) need[goalRow]++;\n        delivered++;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (ans[i].empty()) ans[i] = \".\";\n        cout << ans[i] << '\\n';\n    }\n\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int TURN_LIMIT = 100000;\n\nstruct Solver {\n    int N;\n    vector<vector<int>> h;\n    vector<string> ops;\n    int x = 0, y = 0;\n    ll load = 0;\n\n    Solver(int n, vector<vector<int>> hh) : N(n), h(move(hh)) {}\n\n    inline int dist(int x1, int y1, int x2, int y2) const {\n        return abs(x1 - x2) + abs(y1 - y2);\n    }\n\n    void emit(const string& s) {\n        if ((int)ops.size() < TURN_LIMIT) ops.push_back(s);\n    }\n\n    void move_one(char c) {\n        emit(string(1, c));\n        if (c == 'U') --x;\n        else if (c == 'D') ++x;\n        else if (c == 'L') --y;\n        else if (c == 'R') ++y;\n    }\n\n    void move_to(int nx, int ny) {\n        while (x < nx && (int)ops.size() < TURN_LIMIT) move_one('D');\n        while (x > nx && (int)ops.size() < TURN_LIMIT) move_one('U');\n        while (y < ny && (int)ops.size() < TURN_LIMIT) move_one('R');\n        while (y > ny && (int)ops.size() < TURN_LIMIT) move_one('L');\n    }\n\n    void pickup(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"+\" + to_string(d));\n        h[x][y] -= d;\n        load += d;\n    }\n\n    void dropoff(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"-\" + to_string(d));\n        h[x][y] += d;\n        load -= d;\n    }\n\n    bool all_zero() const {\n        if (load != 0) return false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (h[i][j] != 0) return false;\n        return true;\n    }\n\n    pair<int,int> find_best_positive() {\n        ll bestScore = (1LL << 60);\n        pair<int,int> best = {-1, -1};\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (h[i][j] <= 0) continue;\n                int d = dist(x, y, i, j);\n                int amt = h[i][j];\n\n                // Strong preference for close and large supply.\n                ll score = 100LL * d - 3LL * amt;\n\n                // Mild tie-breaking toward larger amount / closer position.\n                if (score < bestScore ||\n                    (score == bestScore && amt > h[best.first][best.second])) {\n                    bestScore = score;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    }\n\n    pair<int,int> find_best_negative() {\n        ll bestScore = (1LL << 60);\n        pair<int,int> best = {-1, -1};\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (h[i][j] >= 0) continue;\n                int d = dist(x, y, i, j);\n                int need = -h[i][j];\n                int tr = (int)min<ll>(load, need);\n\n                // Movement with load is expensive; prioritize close negatives.\n                // Also prefer larger effective unloading.\n                ll score = (100LL + load) * d - 2LL * tr;\n\n                if (score < bestScore ||\n                    (score == bestScore && need > -h[best.first][best.second])) {\n                    bestScore = score;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    }\n\n    int count_positive() const {\n        int c = 0;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (h[i][j] > 0) ++c;\n        return c;\n    }\n\n    int count_negative() const {\n        int c = 0;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (h[i][j] < 0) ++c;\n        return c;\n    }\n\n    void solve() {\n        // Main greedy transport loop\n        while ((int)ops.size() < TURN_LIMIT - 1000) {\n            if (all_zero()) break;\n\n            if (load == 0) {\n                auto [px, py] = find_best_positive();\n                if (px == -1) break; // safety\n                move_to(px, py);\n                if (h[x][y] > 0) pickup(h[x][y]);\n            } else {\n                auto [nx, ny] = find_best_negative();\n                if (nx == -1) {\n                    // Safety: if somehow there is no negative but load remains,\n                    // try to find any zero/positive? This should not happen if sums are valid.\n                    break;\n                }\n                move_to(nx, ny);\n                if (h[x][y] < 0) {\n                    int d = (int)min<ll>(load, -h[x][y]);\n                    dropoff(d);\n                }\n            }\n        }\n\n        // Fallback cleanup by snake traversal if still unfinished.\n        // This improves robustness.\n        if (!all_zero() && (int)ops.size() < TURN_LIMIT - 1000) {\n            vector<pair<int,int>> ord;\n            for (int i = 0; i < N; ++i) {\n                if (i % 2 == 0) {\n                    for (int j = 0; j < N; ++j) ord.push_back({i, j});\n                } else {\n                    for (int j = N - 1; j >= 0; --j) ord.push_back({i, j});\n                }\n            }\n\n            auto process_here = [&]() {\n                if (h[x][y] > 0) pickup(h[x][y]);\n                else if (h[x][y] < 0) {\n                    int d = (int)min<ll>(load, -h[x][y]);\n                    dropoff(d);\n                }\n            };\n\n            for (int rep = 0; rep < 10 && !all_zero() && (int)ops.size() < TURN_LIMIT - 1000; ++rep) {\n                if (rep % 2 == 0) {\n                    for (auto [i, j] : ord) {\n                        move_to(i, j);\n                        process_here();\n                    }\n                } else {\n                    for (int k = (int)ord.size() - 1; k >= 0; --k) {\n                        auto [i, j] = ord[k];\n                        move_to(i, j);\n                        process_here();\n                    }\n                }\n            }\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> h[i][j];\n        }\n    }\n\n    Solver solver(N, h);\n    solver.solve();\n\n    for (const string& s : solver.ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 6;\nstatic constexpr int M = 15;\nstatic constexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nstatic constexpr int CELL_COUNT = N * N;           // 36\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { // [l, r)\n        return l + (int)(next_u32() % (uint32_t)(r - l));\n    }\n    double next_double() {\n        return (double)next_u32() / 4294967296.0;\n    }\n} rng;\n\nstruct Seed {\n    array<int, M> x{};\n    int sum = 0;\n};\n\nstatic inline double sqr(double x) { return x * x; }\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    vector<Seed> seeds(SEED_COUNT);\n    for (int i = 0; i < SEED_COUNT; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    auto cell_id = [&](int r, int c) { return r * N + c; };\n\n    vector<vector<int>> nbr(CELL_COUNT);\n    vector<pair<int,int>> edges;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int v = cell_id(r, c);\n            if (r + 1 < N) {\n                int u = cell_id(r + 1, c);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n            if (c + 1 < N) {\n                int u = cell_id(r, c + 1);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n        }\n    }\n\n    vector<int> degree(CELL_COUNT);\n    for (int i = 0; i < CELL_COUNT; i++) degree[i] = (int)nbr[i].size();\n\n    vector<int> cell_order(CELL_COUNT);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (degree[a] != degree[b]) return degree[a] > degree[b];\n        int ra = a / N, ca = a % N;\n        int rb = b / N, cb = b % N;\n        int da = abs(ra - 2) + abs(ca - 2);\n        int db = abs(rb - 2) + abs(cb - 2);\n        return da < db;\n    });\n\n    for (int turn = 0; turn < T; turn++) {\n        // ----- turn-aware weights -----\n        double phase = (double)turn / max(1, T - 1); // 0..1\n        // early: diversity, late: sum\n        double W_SUM = 1.0 + 1.6 * phase;\n        double W_TOP = 1.2 - 0.5 * phase;\n        double W_COVER = 1.4 - 0.8 * phase;\n        double W_PAIR_ENV = 1.0 + 0.6 * phase;\n        double W_PAIR_SUM = 0.15 + 0.35 * phase;\n        double W_CELL = 0.35 + 0.45 * phase;\n\n        // ----- global coordinate statistics -----\n        array<int, M> gmax{};\n        array<double, M> gmean{};\n        gmax.fill(0);\n        gmean.fill(0.0);\n        for (int l = 0; l < M; l++) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                gmax[l] = max(gmax[l], seeds[i].x[l]);\n                gmean[l] += seeds[i].x[l];\n            }\n            gmean[l] /= SEED_COUNT;\n        }\n\n        array<double, M> dimWeight{};\n        for (int l = 0; l < M; l++) {\n            // emphasize dimensions with large maxima and where elite values matter\n            dimWeight[l] = 1.0 + 0.02 * gmax[l];\n        }\n\n        // ----- rich seed score -----\n        vector<double> seedScore(SEED_COUNT, 0.0);\n        vector<double> eliteScore(SEED_COUNT, 0.0); // \"specialist importance\"\n        for (int i = 0; i < SEED_COUNT; i++) {\n            double sc = W_SUM * seeds[i].sum;\n            double es = 0.0;\n            for (int l = 0; l < M; l++) {\n                double x = seeds[i].x[l];\n                double rel = (gmax[l] == 0 ? 0.0 : x / gmax[l]);\n                sc += W_TOP * dimWeight[l] * rel * x * 0.35;\n                // sharp bonus near dimension max\n                double nearTop = max(0.0, rel - 0.75);\n                es += dimWeight[l] * nearTop * nearTop * 100.0;\n            }\n            seedScore[i] = sc + 0.4 * es;\n            eliteScore[i] = es;\n        }\n\n        // ----- candidate ordering -----\n        vector<int> ord(SEED_COUNT);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabs(seedScore[a] - seedScore[b]) > 1e-9) return seedScore[a] > seedScore[b];\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n\n        // ----- select 36 seeds: core by score + diverse fill by coordinate coverage -----\n        vector<int> chosen;\n        vector<int> usedSeed(SEED_COUNT, 0);\n\n        int core = 20; // stronger core than before, but leave room for specialists\n        for (int i = 0; i < core; i++) {\n            chosen.push_back(ord[i]);\n            usedSeed[ord[i]] = 1;\n        }\n\n        array<int, M> coverMax{};\n        coverMax.fill(0);\n        for (int s : chosen) {\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[s].x[l]);\n        }\n\n        while ((int)chosen.size() < CELL_COUNT) {\n            int best = -1;\n            double bestGain = -1e100;\n\n            for (int i = 0; i < SEED_COUNT; i++) if (!usedSeed[i]) {\n                double gain = 0.18 * seedScore[i] + 0.30 * eliteScore[i];\n                for (int l = 0; l < M; l++) {\n                    int inc = max(0, seeds[i].x[l] - coverMax[l]);\n                    gain += W_COVER * dimWeight[l] * inc;\n                }\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = i;\n                }\n            }\n\n            chosen.push_back(best);\n            usedSeed[best] = 1;\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[best].x[l]);\n        }\n\n        // local indices [0,35]\n        vector<int> localToSeed = chosen;\n\n        static int envScore[CELL_COUNT][CELL_COUNT];\n        static int sumScore[CELL_COUNT][CELL_COUNT];\n        static int syScore[CELL_COUNT][CELL_COUNT];\n\n        for (int i = 0; i < CELL_COUNT; i++) {\n            envScore[i][i] = sumScore[i][i] = syScore[i][i] = 0;\n            for (int j = i + 1; j < CELL_COUNT; j++) {\n                int a = localToSeed[i], b = localToSeed[j];\n                int env = 0;\n                int ss = seeds[a].sum + seeds[b].sum;\n                int syn = 0;\n                for (int l = 0; l < M; l++) {\n                    int xa = seeds[a].x[l], xb = seeds[b].x[l];\n                    env += max(xa, xb);\n\n                    // synergy bonus: high if both together cover the max well, especially if one is strong where the other is not\n                    int mn = min(xa, xb), mx = max(xa, xb);\n                    syn += mx - mn / 3;\n                }\n                envScore[i][j] = envScore[j][i] = env;\n                sumScore[i][j] = sumScore[j][i] = ss;\n                syScore[i][j] = syScore[j][i] = syn;\n            }\n        }\n\n        vector<double> localSeedCellWeight(CELL_COUNT);\n        for (int i = 0; i < CELL_COUNT; i++) {\n            int s = localToSeed[i];\n            localSeedCellWeight[i] = 0.65 * seeds[s].sum + 0.35 * eliteScore[s];\n        }\n\n        auto objective_edge = [&](int a, int b) -> double {\n            return W_PAIR_ENV * envScore[a][b] + W_PAIR_SUM * sumScore[a][b] + 0.25 * syScore[a][b];\n        };\n\n        auto placementScore = [&](const vector<int>& pl) -> double {\n            double res = 0.0;\n            for (auto [u, v] : edges) res += objective_edge(pl[u], pl[v]);\n            for (int c = 0; c < CELL_COUNT; c++) {\n                res += W_CELL * degree[c] * localSeedCellWeight[pl[c]];\n            }\n            return res;\n        };\n\n        auto deltaSwap = [&](const vector<int>& pl, int a, int b) -> double {\n            if (a == b) return 0.0;\n            int sa = pl[a], sb = pl[b];\n            double before = 0.0, after = 0.0;\n\n            // cell weight term\n            before += W_CELL * degree[a] * localSeedCellWeight[sa];\n            before += W_CELL * degree[b] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[a] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[b] * localSeedCellWeight[sa];\n\n            vector<int> vs;\n            vs.push_back(a);\n            vs.push_back(b);\n            for (int x : nbr[a]) vs.push_back(x);\n            for (int x : nbr[b]) vs.push_back(x);\n            sort(vs.begin(), vs.end());\n            vs.erase(unique(vs.begin(), vs.end()), vs.end());\n\n            set<pair<int,int>> es;\n            for (int u : vs) for (int v : nbr[u]) if (u < v) es.insert({u, v});\n\n            for (auto [u, v] : es) {\n                int pu = pl[u], pv = pl[v];\n                before += objective_edge(pu, pv);\n\n                if (u == a) pu = sb;\n                else if (u == b) pu = sa;\n                if (v == a) pv = sb;\n                else if (v == b) pv = sa;\n                after += objective_edge(pu, pv);\n            }\n\n            return after - before;\n        };\n\n        auto make_greedy = [&](bool randomized) -> vector<int> {\n            vector<int> place(CELL_COUNT, -1);\n            vector<int> used(CELL_COUNT, 0);\n\n            for (int step = 0; step < CELL_COUNT; step++) {\n                int cell = cell_order[step];\n\n                vector<pair<double,int>> cand;\n                cand.reserve(CELL_COUNT);\n                for (int si = 0; si < CELL_COUNT; si++) if (!used[si]) {\n                    double sc = W_CELL * degree[cell] * localSeedCellWeight[si];\n\n                    // adjacency with already placed neighbors\n                    for (int nb : nbr[cell]) {\n                        if (place[nb] != -1) sc += objective_edge(si, place[nb]);\n                    }\n\n                    // slight center preference\n                    int r = cell / N, c = cell % N;\n                    int md = abs(r - 2) + abs(c - 2);\n                    sc -= 0.7 * md * (0.35 * seeds[localToSeed[si]].sum + 0.1 * eliteScore[localToSeed[si]]);\n\n                    cand.push_back({sc, si});\n                }\n\n                sort(cand.begin(), cand.end(), greater<>());\n                int take = 0;\n                if (randomized) {\n                    int lim = min<int>(4, cand.size());\n                    take = rng.next_int(0, lim);\n                }\n                int bestSeed = cand[take].second;\n                place[cell] = bestSeed;\n                used[bestSeed] = 1;\n            }\n\n            // hill climbing\n            double cur = placementScore(place);\n            bool improved = true;\n            for (int it = 0; it < 10 && improved; it++) {\n                improved = false;\n\n                // random order pairs + full sweep flavor\n                vector<int> cells(CELL_COUNT);\n                iota(cells.begin(), cells.end(), 0);\n                shuffle(cells.begin(), cells.end(), std::mt19937(rng.next_u32()));\n\n                for (int xi = 0; xi < CELL_COUNT; xi++) {\n                    int a = cells[xi];\n                    double bestD = 0.0;\n                    int bestB = -1;\n                    for (int yi = xi + 1; yi < CELL_COUNT; yi++) {\n                        int b = cells[yi];\n                        double d = deltaSwap(place, a, b);\n                        if (d > bestD) {\n                            bestD = d;\n                            bestB = b;\n                        }\n                    }\n                    if (bestB != -1) {\n                        swap(place[a], place[bestB]);\n                        cur += bestD;\n                        improved = true;\n                    }\n                }\n            }\n\n            return place;\n        };\n\n        // multi-start\n        vector<int> bestPlace;\n        double bestScore = -1e100;\n\n        int trials = 10;\n        for (int tcase = 0; tcase < trials; tcase++) {\n            bool randomized = (tcase > 0);\n            auto pl = make_greedy(randomized);\n            double sc = placementScore(pl);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPlace = pl;\n            }\n        }\n\n        // output original seed indices\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (c) cout << ' ';\n                cout << localToSeed[bestPlace[cell_id(r, c)]];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // read next generation\n        for (int i = 0; i < SEED_COUNT; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int DX[4] = {0, 1, 0, -1}; // R,D,L,U in (row,col)\nstatic const int DY[4] = {1, 0, -1, 0};\nstatic const char DIRC[4] = {'R', 'D', 'L', 'U'};\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    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    // Star arm: root + K leaves, all length 1.\n    int K = max(1, V - 1);\n    int Vp = K + 1;\n\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << 1 << '\\n';\n    }\n\n    int rx = N / 2, ry = N / 2;\n    cout << rx << ' ' << ry << '\\n';\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    vector<int> dir(K, 0);     // current direction of each leaf\n    vector<int> hold(K, 0);    // whether leaf holds one takoyaki\n\n    auto is_surplus = [&](int x, int y) -> bool {\n        return s[x][y] == '1' && t[x][y] == '0';\n    };\n    auto is_deficit = [&](int x, int y) -> bool {\n        return s[x][y] == '0' && t[x][y] == '1';\n    };\n\n    auto remaining = [&]() -> int {\n        int diff = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (s[i][j] != t[i][j]) diff++;\n        }\n        return diff / 2;\n    };\n\n    auto count_hold = [&]() -> int {\n        int c = 0;\n        for (int v : hold) c += v;\n        return c;\n    };\n\n    // For a root position, count adjacent surplus/deficit cells.\n    auto neighborhood_info = [&](int x, int y) {\n        array<int, 4> kind{}; // 0 none, 1 surplus, 2 deficit\n        int cs = 0, cd = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + DX[d], ny = y + DY[d];\n            if (!inb(nx, ny)) continue;\n            if (is_surplus(nx, ny)) {\n                kind[d] = 1;\n                cs++;\n            } else if (is_deficit(nx, ny)) {\n                kind[d] = 2;\n                cd++;\n            }\n        }\n        return pair<int,int>(cs, cd);\n    };\n\n    auto manhattan_step = [&](int tx, int ty) -> int {\n        if (rx < tx) return 1; // D\n        if (rx > tx) return 3; // U\n        if (ry < ty) return 0; // R\n        if (ry > ty) return 2; // L\n        return -1;\n    };\n\n    // Find best root center for pick/place.\n    // mode=0 pick, mode=1 place.\n    auto best_center = [&](int mode) -> Pos {\n        int bestScore = -1e9;\n        Pos best{rx, ry};\n\n        int hcnt = count_hold();\n        int ecnt = K - hcnt;\n\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            int cnt = 0;\n            for (int d = 0; d < 4; d++) {\n                int nx = x + DX[d], ny = y + DY[d];\n                if (!inb(nx, ny)) continue;\n                if (mode == 0 && is_surplus(nx, ny)) cnt++;\n                if (mode == 1 && is_deficit(nx, ny)) cnt++;\n            }\n            if (mode == 0) cnt = min(cnt, ecnt);\n            else cnt = min(cnt, hcnt);\n\n            int dist = abs(x - rx) + abs(y - ry);\n            int score = cnt * 1000 - dist * 10;\n\n            // small preference to remain if equally good\n            if (x == rx && y == ry) score += 3;\n\n            // if carrying, place centers are more important\n            if (mode == 1) score += 1;\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = {x, y};\n            }\n        }\n        return best;\n    };\n\n    // If no good center with adjacent targets, move toward nearest relevant cell's adjacent center.\n    auto nearest_center_from_cells = [&](int mode) -> Pos {\n        int bestDist = 1e9;\n        Pos best{rx, ry};\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            bool ok = (mode == 0 ? is_surplus(i, j) : is_deficit(i, j));\n            if (!ok) continue;\n            for (int d = 0; d < 4; d++) {\n                int x = i - DX[d], y = j - DY[d];\n                if (!inb(x, y)) continue;\n                int dist = abs(x - rx) + abs(y - ry);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    best = {x, y};\n                }\n            }\n        }\n        return best;\n    };\n\n    vector<string> answer;\n    const int TURN_LIMIT = 100000;\n\n    for (int turn = 0; turn < TURN_LIMIT; turn++) {\n        if (remaining() == 0) break;\n\n        int hcnt = count_hold();\n        int ecnt = K - hcnt;\n\n        // Decide strategic target center.\n        // If holding enough, prioritize place. If empty, prioritize pick.\n        Pos target = {rx, ry};\n\n        auto placeBest = best_center(1);\n        auto pickBest = best_center(0);\n\n        auto eval_center_count = [&](Pos p, int mode) -> int {\n            int cnt = 0;\n            for (int d = 0; d < 4; d++) {\n                int nx = p.x + DX[d], ny = p.y + DY[d];\n                if (!inb(nx, ny)) continue;\n                if (mode == 0 && is_surplus(nx, ny)) cnt++;\n                if (mode == 1 && is_deficit(nx, ny)) cnt++;\n            }\n            return cnt;\n        };\n\n        int placeCnt = eval_center_count(placeBest, 1);\n        int pickCnt = eval_center_count(pickBest, 0);\n\n        if (hcnt > 0 && placeCnt > 0) {\n            target = placeBest;\n        } else if (ecnt > 0 && pickCnt > 0) {\n            target = pickBest;\n        } else if (hcnt > 0) {\n            target = nearest_center_from_cells(1);\n        } else {\n            target = nearest_center_from_cells(0);\n        }\n\n        // Movement\n        string cmd(2 * Vp, '.');\n        int mv = manhattan_step(target.x, target.y);\n        if (mv != -1) {\n            int nx = rx + DX[mv], ny = ry + DY[mv];\n            if (inb(nx, ny)) {\n                rx = nx;\n                ry = ny;\n                cmd[0] = DIRC[mv];\n            }\n        }\n\n        // After movement, greedily assign adjacent directions.\n        // First assign holding leaves to deficits.\n        // Then assign empty leaves to surplus.\n        // This gives immediate service whenever possible.\n\n        vector<int> leafTargetDir(K, -1);\n        vector<int> dirUsed(4, -1);\n\n        // Gather available deficit/surplus dirs\n        vector<int> deficitDirs, surplusDirs;\n        for (int d = 0; d < 4; d++) {\n            int x = rx + DX[d], y = ry + DY[d];\n            if (!inb(x, y)) continue;\n            if (is_deficit(x, y)) deficitDirs.push_back(d);\n            if (is_surplus(x, y)) surplusDirs.push_back(d);\n        }\n\n        // Assign holders to deficits\n        int idx = 0;\n        for (int i = 0; i < K && idx < (int)deficitDirs.size(); i++) {\n            if (!hold[i]) continue;\n            int d = deficitDirs[idx++];\n            leafTargetDir[i] = d;\n            dirUsed[d] = i;\n        }\n\n        // Assign empties to surplus\n        idx = 0;\n        for (int i = 0; i < K && idx < (int)surplusDirs.size(); i++) {\n            if (hold[i]) continue;\n            while (idx < (int)surplusDirs.size() && dirUsed[surplusDirs[idx]] != -1) idx++;\n            if (idx >= (int)surplusDirs.size()) break;\n            int d = surplusDirs[idx++];\n            leafTargetDir[i] = d;\n            dirUsed[d] = i;\n        }\n\n        // Opportunistic second priority:\n        // If some holding leaf has no place target, let it rotate toward a deficit if any remains unassigned next turn;\n        // similarly for empty leaf.\n        // Here we simply keep current direction if unused.\n\n        // Rotate each leaf at most 90 degrees.\n        for (int i = 0; i < K; i++) {\n            int td = leafTargetDir[i];\n            if (td == -1) continue;\n            int cur = dir[i];\n            int diff = (td - cur + 4) % 4;\n            if (diff == 0) {\n                cmd[1 + i] = '.';\n            } else if (diff == 1) {\n                cmd[1 + i] = 'R';\n                dir[i] = (dir[i] + 1) & 3;\n            } else if (diff == 3) {\n                cmd[1 + i] = 'L';\n                dir[i] = (dir[i] + 3) & 3;\n            } else {\n                // opposite: choose one direction deterministically\n                cmd[1 + i] = 'R';\n                dir[i] = (dir[i] + 1) & 3;\n            }\n        }\n\n        // Action phase in vertex order.\n        for (int i = 0; i < K; i++) {\n            int x = rx + DX[dir[i]];\n            int y = ry + DY[dir[i]];\n            if (!inb(x, y)) continue;\n\n            if (hold[i]) {\n                if (is_deficit(x, y)) {\n                    s[x][y] = '1';\n                    hold[i] = 0;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            } else {\n                if (is_surplus(x, y)) {\n                    s[x][y] = '0';\n                    hold[i] = 1;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            }\n        }\n\n        answer.push_back(cmd);\n    }\n\n    for (auto &row : answer) cout << row << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct Candidate {\n    ll score = LLONG_MIN;              // sum of grid cell weights\n    vector<pair<int,int>> poly;        // polygon vertices\n    bool valid = false;\n};\n\nstatic inline long long pack64(int a, int b) {\n    return ( (long long)a << 32 ) ^ (unsigned int)b;\n}\n\nstruct BuildResult {\n    bool ok = false;\n    vector<pair<int,int>> poly;\n};\n\nBuildResult build_polygon_from_selected(const vector<unsigned char>& sel, int H, int W, int ox, int oy, int D) {\n    // Selected cell (r,c) corresponds to grid cell [ox+c, oy+r] in cell coordinates.\n\n    struct Edge {\n        int x1, y1, x2, y2;\n        bool operator==(const Edge& o) const {\n            return x1==o.x1 && y1==o.y1 && x2==o.x2 && y2==o.y2;\n        }\n    };\n    struct EdgeHash {\n        size_t operator()(Edge const& e) const noexcept {\n            size_t h = 0;\n            auto mix = [&](int v) {\n                h ^= std::hash<long long>{}((long long)v + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2));\n            };\n            mix(e.x1); mix(e.y1); mix(e.x2); mix(e.y2);\n            return h;\n        }\n    };\n\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    unordered_set<Edge, EdgeHash> S;\n    S.reserve(H * W * 2);\n\n    auto toggle = [&](Edge e) {\n        Edge rev{e.x2, e.y2, e.x1, e.y1};\n        auto it = S.find(rev);\n        if (it != S.end()) S.erase(it);\n        else S.insert(e);\n    };\n\n    int selected_count = 0;\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) if (sel[id(r,c)]) {\n            selected_count++;\n            int gx = ox + c;\n            int gy = oy + r;\n            int x = gx * D;\n            int y = gy * D;\n            toggle({x, y, x + D, y});\n            toggle({x + D, y, x + D, y + D});\n            toggle({x + D, y + D, x, y + D});\n            toggle({x, y + D, x, y});\n        }\n    }\n    if (selected_count == 0 || S.empty()) return {};\n\n    unordered_map<long long, vector<pair<int,int>>> out;\n    out.reserve(S.size() * 2);\n    auto pkey = [&](int x, int y) { return pack64(x, y); };\n\n    for (auto &e : S) {\n        out[pkey(e.x1, e.y1)].push_back({e.x2, e.y2});\n    }\n\n    auto edgekey = [&](int x1, int y1, int x2, int y2) {\n        uint64_t h = 1469598103934665603ULL;\n        auto add = [&](uint64_t v) {\n            h ^= v + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n        };\n        add((uint32_t)x1); add((uint32_t)y1); add((uint32_t)x2); add((uint32_t)y2);\n        return (long long)h;\n    };\n\n    unordered_set<long long> used;\n    used.reserve(S.size() * 2);\n\n    int cycles = 0;\n    vector<pair<int,int>> best;\n\n    for (auto &e : S) {\n        long long ek = edgekey(e.x1, e.y1, e.x2, e.y2);\n        if (used.count(ek)) continue;\n\n        cycles++;\n        vector<pair<int,int>> cur;\n        int sx = e.x1, sy = e.y1;\n        int cx = e.x1, cy = e.y1;\n        int nx = e.x2, ny = e.y2;\n        cur.push_back({cx, cy});\n\n        while (true) {\n            long long ck = edgekey(cx, cy, nx, ny);\n            if (used.count(ck)) break;\n            used.insert(ck);\n            cx = nx; cy = ny;\n            cur.push_back({cx, cy});\n            if (cx == sx && cy == sy) break;\n\n            auto it = out.find(pkey(cx, cy));\n            if (it == out.end()) return {};\n            int cnt = 0;\n            pair<int,int> nxt;\n            for (auto &to : it->second) {\n                long long nk = edgekey(cx, cy, to.first, to.second);\n                if (!used.count(nk)) {\n                    cnt++;\n                    nxt = to;\n                }\n            }\n            if (cnt != 1) return {};\n            nx = nxt.first;\n            ny = nxt.second;\n        }\n\n        if (!cur.empty() && cur.front() == cur.back()) cur.pop_back();\n        if (cur.size() > best.size()) best = move(cur);\n    }\n\n    if ((int)used.size() != (int)S.size()) return {};\n    if (cycles != 1) return {};\n\n    // compress collinear\n    vector<pair<int,int>> poly;\n    int m = (int)best.size();\n    for (int i = 0; i < m; i++) {\n        auto p0 = best[(i - 1 + m) % m];\n        auto p1 = best[i];\n        auto p2 = best[(i + 1) % m];\n        int dx1 = (p1.first > p0.first) - (p1.first < p0.first);\n        int dy1 = (p1.second > p0.second) - (p1.second < p0.second);\n        int dx2 = (p2.first > p1.first) - (p2.first < p1.first);\n        int dy2 = (p2.second > p1.second) - (p2.second < p1.second);\n        if (dx1 == dx2 && dy1 == dy2) continue;\n        poly.push_back(p1);\n    }\n\n    if ((int)poly.size() < 4 || (int)poly.size() > 1000) return {};\n    {\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != (int)poly.size()) return {};\n    }\n    for (auto &p : poly) {\n        if (p.first < 0 || p.first > 100000 || p.second < 0 || p.second > 100000) return {};\n    }\n\n    return {true, poly};\n}\n\nstruct GridData {\n    int D;\n    int minx, maxx, miny, maxy;\n    int ox, oy; // origin in cell coordinates\n    int W, H;\n    vector<int> w; // H*W\n};\n\nGridData build_grid(const vector<Point>& mac, const vector<Point>& sar, int D) {\n    int minx = 1e9, miny = 1e9, maxx = -1, maxy = -1;\n    auto upd = [&](const Point& p) {\n        int gx = p.x / D, gy = p.y / D;\n        minx = min(minx, gx);\n        maxx = max(maxx, gx);\n        miny = min(miny, gy);\n        maxy = max(maxy, gy);\n    };\n    for (auto &p : mac) upd(p);\n    for (auto &p : sar) upd(p);\n\n    GridData g;\n    g.D = D;\n    g.minx = minx; g.maxx = maxx;\n    g.miny = miny; g.maxy = maxy;\n    g.ox = minx; g.oy = miny;\n    g.W = maxx - minx + 1;\n    g.H = maxy - miny + 1;\n    g.w.assign(g.H * g.W, 0);\n\n    auto id = [&](int r, int c) { return r * g.W + c; };\n    for (auto &p : mac) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r,c)]++;\n    }\n    for (auto &p : sar) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r,c)]--;\n    }\n    return g;\n}\n\nCandidate try_best_rectangle(const GridData& g) {\n    Candidate best;\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    // O(H^2 * W)\n    vector<int> col(W);\n\n    for (int top = 0; top < H; top++) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < H; bot++) {\n            int height_cells = bot - top + 1;\n            for (int c = 0; c < W; c++) col[c] += g.w[id(bot, c)];\n\n            // max subarray with width constraint from perimeter\n            // perimeter = 2*((height+width)*D) <= 4e5\n            int max_wh = 200000 / D - height_cells;\n            if (max_wh <= 0) continue;\n            int max_width = min(W, max_wh);\n\n            // Kadane with max length constraint: since W small, brute start-end is okay enough\n            ll curBest = LLONG_MIN;\n            int bestL = -1, bestR = -1;\n\n            // O(W^2), still acceptable because W ~ <= 90\n            for (int l = 0; l < W; l++) {\n                ll s = 0;\n                for (int r = l; r < W && r - l + 1 <= max_width; r++) {\n                    s += col[r];\n                    if (s > curBest) {\n                        curBest = s;\n                        bestL = l;\n                        bestR = r;\n                    }\n                }\n            }\n\n            if (bestL == -1 || curBest == LLONG_MIN) continue;\n            if (curBest <= best.score) continue;\n\n            int x0 = (g.ox + bestL) * D;\n            int x1 = (g.ox + bestR + 1) * D;\n            int y0 = (g.oy + top) * D;\n            int y1 = (g.oy + bot + 1) * D;\n            if (x0 < 0 || x1 > 100000 || y0 < 0 || y1 > 100000) continue;\n            if (2LL * ((x1 - x0) + (y1 - y0)) > 400000LL) continue;\n\n            vector<pair<int,int>> poly = {\n                {x0, y0}, {x1, y0}, {x1, y1}, {x0, y1}\n            };\n            best.score = curBest;\n            best.poly = move(poly);\n            best.valid = true;\n        }\n    }\n    return best;\n}\n\nCandidate try_greedy_region(const GridData& g, const vector<double>& penalties) {\n    Candidate best;\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    vector<int> order(H * W);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b) {\n        if (g.w[a] != g.w[b]) return g.w[a] > g.w[b];\n        return a < b;\n    });\n\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    int maxSeeds = min(24, H * W);\n\n    for (double pen : penalties) {\n        for (int si = 0; si < maxSeeds; si++) {\n            int seed = order[si];\n            if (g.w[seed] <= 0 && si >= 8) break;\n\n            vector<unsigned char> sel(H * W, 0), seen(H * W, 0);\n            vector<int> ver(H * W, 0);\n\n            ll score = 0;\n            int perim_edges = 0;\n\n            auto neigh_sel = [&](int v) {\n                int r = v / W, c = v % W;\n                int cnt = 0;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (0 <= nr && nr < H && 0 <= nc && nc < W && sel[id(nr,nc)]) cnt++;\n                }\n                return cnt;\n            };\n\n            struct Node {\n                double pri;\n                int v, ver;\n                bool operator<(const Node& o) const { return pri < o.pri; }\n            };\n            priority_queue<Node> pq;\n\n            auto push_frontier = [&](int v) {\n                if (sel[v]) return;\n                seen[v] = 1;\n                int ns = neigh_sel(v);\n                if (ns == 0) return;\n                int de = 4 - 2 * ns;\n                // stronger encouragement for filled compact shapes\n                double pri = g.w[v] * 12.0 - pen * de + ns * 2.0;\n                pq.push({pri, v, ++ver[v]});\n            };\n\n            auto add_cell = [&](int v) {\n                sel[v] = 1;\n                score += g.w[v];\n                int ns = neigh_sel(v);\n                int de = 4 - 2 * ns;\n                perim_edges += de;\n\n                int r = v / W, c = v % W;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                        int u = id(nr, nc);\n                        if (!sel[u]) push_frontier(u);\n                    }\n                }\n            };\n\n            add_cell(seed);\n\n            {\n                int r = seed / W, c = seed % W;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                        push_frontier(id(nr, nc));\n                    }\n                }\n            }\n\n            int perim_limit = 400000 / D;\n            int iter = 0, iter_limit = H * W * 3;\n\n            while (!pq.empty() && iter < iter_limit) {\n                iter++;\n                auto cur = pq.top(); pq.pop();\n                int v = cur.v;\n                if (sel[v]) continue;\n                if (cur.ver != ver[v]) continue;\n\n                int ns = neigh_sel(v);\n                if (ns == 0) continue;\n                int de = 4 - 2 * ns;\n                if (perim_edges + de > perim_limit) continue;\n\n                // Accept if beneficial enough.\n                // Allow some negative / zero cells for bridging when strongly attached.\n                double gain = g.w[v] * 12.0 - pen * de + ns * 2.0;\n                bool ok = false;\n                if (gain >= 0) ok = true;\n                else if (g.w[v] >= 0 && ns >= 2 && gain >= -2.0) ok = true;\n                else if (g.w[v] == -1 && ns >= 3 && gain >= -1.0) ok = true;\n\n                if (!ok) continue;\n                add_cell(v);\n            }\n\n            if (score <= best.score) continue;\n\n            auto br = build_polygon_from_selected(sel, H, W, g.ox, g.oy, D);\n            if (!br.ok) continue;\n\n            // perimeter check from polygon\n            ll peri = 0;\n            int m = (int)br.poly.size();\n            for (int i = 0; i < m; i++) {\n                auto a = br.poly[i];\n                auto b = br.poly[(i+1)%m];\n                peri += llabs(a.first - b.first) + llabs(a.second - b.second);\n            }\n            if (peri > 400000) continue;\n            if ((int)br.poly.size() > 1000) continue;\n\n            best.score = score;\n            best.poly = move(br.poly);\n            best.valid = true;\n        }\n    }\n\n    return best;\n}\n\nvector<pair<int,int>> fallback_polygon() {\n    return {{0,0},{1,0},{1,1},{0,1}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> mac(N), sar(N);\n    for (int i = 0; i < N; i++) cin >> mac[i].x >> mac[i].y;\n    for (int i = 0; i < N; i++) cin >> sar[i].x >> sar[i].y;\n\n    vector<int> Ds = {1200, 1600, 2000, 2500, 3200};\n\n    Candidate answer;\n\n    for (int D : Ds) {\n        GridData g = build_grid(mac, sar, D);\n\n        // Rectangle baseline\n        Candidate rect = try_best_rectangle(g);\n        if (rect.valid && rect.score > answer.score) answer = rect;\n\n        // Greedy connected region with different perimeter penalties\n        vector<double> penalties = {1.5, 2.0, 2.5, 3.0, 4.0};\n        Candidate poly = try_greedy_region(g, penalties);\n        if (poly.valid && poly.score > answer.score) answer = poly;\n    }\n\n    vector<pair<int,int>> out = answer.valid ? answer.poly : fallback_polygon();\n\n    // final safety\n    if ((int)out.size() < 4 || (int)out.size() > 1000) out = fallback_polygon();\n    {\n        set<pair<int,int>> st(out.begin(), out.end());\n        if ((int)st.size() != (int)out.size()) out = fallback_polygon();\n    }\n    for (auto &p : out) {\n        p.first = max(0, min(100000, p.first));\n        p.second = max(0, min(100000, p.second));\n    }\n\n    cout << out.size() << '\\n';\n    for (auto &p : out) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Op {\n    int p;\n    int r;\n    char d;\n    int b;\n};\n\nstruct Rect {\n    int w, h;\n};\n\nstruct Candidate {\n    vector<Op> ops;\n    long long estW = 0, estH = 0, estScore = (1LL << 60);\n    string tag;\n};\n\nstatic long long INF64 = (1LL << 62);\n\nstruct Solver {\n    int N, T, sigma;\n    vector<Rect> a;\n    vector<Candidate> pool;\n    mt19937 rng;\n\n    Solver() : rng(712367821) {}\n\n    // Build vertical columns from contiguous groups [l..r)\n    // first rect of each column is anchored next to previous column's first rect\n    // subsequent rects in same column are anchored to the column's first rect\n    Candidate build_columns(const vector<pair<int,int>>& groups, int mode, const string& tag) {\n        // mode:\n        // 0: width=min, height=max\n        // 1: no rotation\n        // 2: width=max, height=min\n        Candidate c;\n        c.tag = tag;\n\n        vector<int> firsts;\n        firsts.reserve(groups.size());\n\n        long long totalW = 0;\n        long long totalH = 0;\n\n        for (int gi = 0; gi < (int)groups.size(); gi++) {\n            auto [l, r] = groups[gi];\n            long long colW = 0, colH = 0;\n            int first = l;\n            firsts.push_back(first);\n\n            for (int i = l; i < r; i++) {\n                int w = a[i].w, h = a[i].h;\n                int rot = 0;\n                int ww = w, hh = h;\n                if (mode == 0) {\n                    // make width smaller\n                    if (w > h) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                } else if (mode == 1) {\n                    rot = 0;\n                    ww = w; hh = h;\n                } else {\n                    // make width larger\n                    if (w < h) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                }\n\n                int b;\n                if (i == l) {\n                    b = (gi == 0 ? -1 : firsts[gi - 1]);\n                } else {\n                    b = first;\n                }\n                c.ops.push_back({i, rot, 'U', b});\n                colW = max<long long>(colW, ww);\n                colH += hh;\n            }\n            totalW += colW;\n            totalH = max(totalH, colH);\n        }\n\n        c.estW = totalW;\n        c.estH = totalH;\n        c.estScore = totalW + totalH;\n        return c;\n    }\n\n    // Build horizontal rows from contiguous groups [l..r)\n    Candidate build_rows(const vector<pair<int,int>>& groups, int mode, const string& tag) {\n        // mode:\n        // 0: height=min\n        // 1: no rotation\n        // 2: height=max\n        Candidate c;\n        c.tag = tag;\n\n        vector<int> firsts;\n        firsts.reserve(groups.size());\n\n        long long totalW = 0;\n        long long totalH = 0;\n\n        for (int gi = 0; gi < (int)groups.size(); gi++) {\n            auto [l, r] = groups[gi];\n            long long rowW = 0, rowH = 0;\n            int first = l;\n            firsts.push_back(first);\n\n            for (int i = l; i < r; i++) {\n                int w = a[i].w, h = a[i].h;\n                int rot = 0;\n                int ww = w, hh = h;\n                if (mode == 0) {\n                    // make height smaller\n                    if (h > w) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                } else if (mode == 1) {\n                    rot = 0;\n                    ww = w; hh = h;\n                } else {\n                    // make height larger\n                    if (h < w) {\n                        rot = 1;\n                        ww = h; hh = w;\n                    }\n                }\n\n                int b;\n                if (i == l) {\n                    b = (gi == 0 ? -1 : firsts[gi - 1]);\n                } else {\n                    b = first;\n                }\n                c.ops.push_back({i, rot, 'L', b});\n                rowW += ww;\n                rowH = max<long long>(rowH, hh);\n            }\n            totalW = max(totalW, rowW);\n            totalH += rowH;\n        }\n\n        c.estW = totalW;\n        c.estH = totalH;\n        c.estScore = totalW + totalH;\n        return c;\n    }\n\n    vector<pair<int,int>> split_equal(int k) {\n        vector<pair<int,int>> groups;\n        for (int g = 0; g < k; g++) {\n            int l = (long long)N * g / k;\n            int r = (long long)N * (g + 1) / k;\n            if (l < r) groups.push_back({l, r});\n        }\n        return groups;\n    }\n\n    vector<pair<int,int>> split_balanced_columns(int k, int mode) {\n        // balance estimated column heights\n        vector<long long> val(N);\n        for (int i = 0; i < N; i++) {\n            int w = a[i].w, h = a[i].h;\n            if (mode == 0) val[i] = max(w, h);\n            else if (mode == 1) val[i] = h;\n            else val[i] = min(w, h);\n        }\n        long long sum = 0;\n        for (auto x : val) sum += x;\n        long long target = max(1LL, (sum + k - 1) / k);\n\n        vector<pair<int,int>> groups;\n        int l = 0;\n        long long cur = 0;\n        for (int i = 0; i < N; i++) {\n            if ((int)groups.size() < k - 1 && i > l && cur + val[i] > target) {\n                groups.push_back({l, i});\n                l = i;\n                cur = 0;\n            }\n            cur += val[i];\n        }\n        if (l < N) groups.push_back({l, N});\n        return groups;\n    }\n\n    vector<pair<int,int>> split_balanced_rows(int k, int mode) {\n        // balance estimated row widths\n        vector<long long> val(N);\n        for (int i = 0; i < N; i++) {\n            int w = a[i].w, h = a[i].h;\n            if (mode == 0) val[i] = max(w, h);\n            else if (mode == 1) val[i] = w;\n            else val[i] = min(w, h);\n        }\n        long long sum = 0;\n        for (auto x : val) sum += x;\n        long long target = max(1LL, (sum + k - 1) / k);\n\n        vector<pair<int,int>> groups;\n        int l = 0;\n        long long cur = 0;\n        for (int i = 0; i < N; i++) {\n            if ((int)groups.size() < k - 1 && i > l && cur + val[i] > target) {\n                groups.push_back({l, i});\n                l = i;\n                cur = 0;\n            }\n            cur += val[i];\n        }\n        if (l < N) groups.push_back({l, N});\n        return groups;\n    }\n\n    void generate_pool() {\n        pool.clear();\n\n        int K = min(N, 12);\n\n        for (int mode = 0; mode < 3; mode++) {\n            {\n                auto g = split_equal(1);\n                pool.push_back(build_columns(g, mode, \"col_eq_1_m\" + to_string(mode)));\n                pool.push_back(build_rows(g, mode, \"row_eq_1_m\" + to_string(mode)));\n            }\n\n            for (int k = 2; k <= K; k++) {\n                {\n                    auto g = split_equal(k);\n                    pool.push_back(build_columns(g, mode, \"col_eq_\" + to_string(k) + \"_m\" + to_string(mode)));\n                    pool.push_back(build_rows(g, mode, \"row_eq_\" + to_string(k) + \"_m\" + to_string(mode)));\n                }\n                {\n                    auto g = split_balanced_columns(k, mode);\n                    pool.push_back(build_columns(g, mode, \"col_bal_\" + to_string(k) + \"_m\" + to_string(mode)));\n                }\n                {\n                    auto g = split_balanced_rows(k, mode);\n                    pool.push_back(build_rows(g, mode, \"row_bal_\" + to_string(k) + \"_m\" + to_string(mode)));\n                }\n            }\n        }\n\n        // Deduplicate by operation sequence hash\n        unordered_set<string> seen;\n        vector<Candidate> uniq;\n        for (auto &c : pool) {\n            string key;\n            key.reserve(c.ops.size() * 10);\n            for (auto &op : c.ops) {\n                key += to_string(op.p);\n                key += ',';\n                key += char('0' + op.r);\n                key += ',';\n                key += op.d;\n                key += ',';\n                key += to_string(op.b);\n                key += ';';\n            }\n            if (seen.insert(key).second) uniq.push_back(c);\n        }\n        pool.swap(uniq);\n\n        sort(pool.begin(), pool.end(), [&](const Candidate& x, const Candidate& y) {\n            if (x.estScore != y.estScore) return x.estScore < y.estScore;\n            return x.tag < y.tag;\n        });\n    }\n\n    void output_candidate(const Candidate& c) {\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n    }\n\n    void solve() {\n        cin >> N >> T >> sigma;\n        a.resize(N);\n        for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n        generate_pool();\n\n        vector<int> order(pool.size());\n        iota(order.begin(), order.end(), 0);\n\n        // We will send best-estimated candidates first.\n        // Then recycle top few if T is larger.\n        int topReuse = min<int>(10, pool.size());\n\n        long long bestMeasured = INF64;\n        int bestIdx = 0;\n\n        for (int t = 0; t < T; t++) {\n            int idx;\n            if (t < (int)pool.size()) {\n                idx = t;\n            } else {\n                // Reuse one of top candidates, slightly preferring current measured best\n                if (t % 3 == 0) idx = bestIdx;\n                else idx = (t - (int)pool.size()) % topReuse;\n            }\n\n            // Optional comment line for local visualizer\n            // judge ignores lines beginning with '#'\n            cout << \"# \" << pool[idx].tag << \" est=\" << pool[idx].estW << \"+\" << pool[idx].estH\n                 << \"=\" << pool[idx].estScore << '\\n';\n\n            output_candidate(pool[idx]);\n\n            long long Wm, Hm;\n            cin >> Wm >> Hm;\n            long long sm = Wm + Hm;\n            if (sm < bestMeasured) {\n                bestMeasured = sm;\n                bestIdx = idx;\n            }\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}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Candidate {\n    int depth;   // target depth\n    int beauty;\n    int parent;\n    int v;\n    bool operator<(const Candidate& other) const {\n        if (depth != other.depth) return depth < other.depth;      // max depth first\n        if (beauty != other.beauty) return beauty < other.beauty;  // then large beauty\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, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<pair<int,int>> edges(M);\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n\n    vector<pair<int,int>> coord(N);\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        coord[i] = {x, y};\n    }\n\n    // -------- Initial construction --------\n    // Idea:\n    // - small A vertices are better as roots / shallow scaffold\n    // - use a global candidate PQ that prefers deeper assignment and larger A\n    vector<int> parent(N, -2); // -2 = unassigned, -1 = root\n    vector<int> depth(N, -1);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (A[a] != A[b]) return A[a] < A[b];\n        return a < b;\n    });\n\n    priority_queue<Candidate> pq;\n\n    auto add_frontier = [&](int u) {\n        if (depth[u] >= H) return;\n        for (int v : g[u]) {\n            if (parent[v] == -2) {\n                pq.push(Candidate{depth[u] + 1, A[v], u, v});\n            }\n        }\n    };\n\n    // Start from several low-beauty roots gradually.\n    int ptr = 0;\n    while (true) {\n        while (ptr < N && parent[ord[ptr]] != -2) ptr++;\n        if (ptr == N) break;\n\n        int r = ord[ptr];\n        parent[r] = -1;\n        depth[r] = 0;\n        add_frontier(r);\n\n        // Expand as much as possible with current frontier.\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n            int v = cur.v, p = cur.parent;\n            if (parent[v] != -2) continue;\n            if (parent[p] == -2) continue;\n            if (depth[p] + 1 != cur.depth) continue;\n            if (cur.depth > H) continue;\n\n            parent[v] = p;\n            depth[v] = cur.depth;\n            add_frontier(v);\n\n            // If everything assigned, done.\n            // (No need to check here, outer loop handles it.)\n        }\n    }\n\n    // Safety fallback\n    for (int i = 0; i < N; i++) {\n        if (parent[i] == -2) {\n            parent[i] = -1;\n            depth[i] = 0;\n        }\n    }\n\n    // -------- Data structures for local improvement --------\n    vector<vector<int>> children(N);\n    vector<int> tin(N), tout(N), subSum(N), subHeight(N);\n    int timer = 0;\n\n    function<void()> rebuild = [&]() {\n        for (int i = 0; i < N; i++) children[i].clear();\n        for (int v = 0; v < N; v++) {\n            if (parent[v] >= 0) children[parent[v]].push_back(v);\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            }\n        }\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (int v : children[u]) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n\n        timer = 0;\n        function<void(int)> dfs = [&](int u) {\n            tin[u] = timer++;\n            subSum[u] = A[u];\n            subHeight[u] = 0;\n            for (int v : children[u]) {\n                dfs(v);\n                subSum[u] += subSum[v];\n                subHeight[u] = max(subHeight[u], subHeight[v] + 1);\n            }\n            tout[u] = timer;\n        };\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) dfs(i);\n        }\n    };\n\n    auto is_ancestor = [&](int a, int b) -> bool {\n        return tin[a] <= tin[b] && tout[b] <= tout[a];\n    };\n\n    rebuild();\n\n    auto score_est = [&]() -> long long {\n        long long s = 1;\n        for (int i = 0; i < N; i++) s += 1LL * (depth[i] + 1) * A[i];\n        return s;\n    };\n\n    // -------- Local improvement: subtree reparenting --------\n    // Move subtree v under neighboring u if gain positive and valid.\n    // Since H is small and N=1000, full rebuild after successful move is acceptable.\n    long long bestScore = score_est();\n\n    bool improved = true;\n    int rounds = 0;\n    while (improved && rounds < 30) {\n        improved = false;\n        rounds++;\n\n        // Try promising vertices first: larger subtree weight and larger A.\n        vector<int> vs(N);\n        iota(vs.begin(), vs.end(), 0);\n        sort(vs.begin(), vs.end(), [&](int a, int b) {\n            long long wa = 1LL * subSum[a] * 100 + A[a];\n            long long wb = 1LL * subSum[b] * 100 + A[b];\n            if (wa != wb) return wa > wb;\n            return a < b;\n        });\n\n        for (int v : vs) {\n            int bestParent = -3;\n            int bestNewDepth = depth[v];\n\n            for (int u : g[v]) {\n                if (u == parent[v]) continue;\n                // Cannot attach under own descendant.\n                if (is_ancestor(v, u)) continue;\n\n                int nd = depth[u] + 1;\n                if (nd <= depth[v]) continue; // only improving moves\n                if (nd + subHeight[v] > H) continue; // subtree must fit\n\n                if (nd > bestNewDepth) {\n                    bestNewDepth = nd;\n                    bestParent = u;\n                }\n            }\n\n            if (bestParent != -3) {\n                int oldParent = parent[v];\n                parent[v] = bestParent;\n                rebuild();\n                long long sc = score_est();\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    improved = true;\n                } else {\n                    // revert\n                    parent[v] = oldParent;\n                    rebuild();\n                }\n            }\n        }\n    }\n\n    // -------- Final validity repair (just in case) --------\n    // Ensure depth <= H and no invalid parent remains. If any issue, make root.\n    rebuild();\n    for (int i = 0; i < N; i++) {\n        if (depth[i] < 0 || depth[i] > H) {\n            parent[i] = -1;\n        }\n    }\n    rebuild();\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nstruct Candidate {\n    char d;\n    int p;\n    int k;\n    int removed;\n    bool valid = false;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<string> b(n);\n    for (int i = 0; i < n; i++) cin >> b[i];\n\n    vector<Op> ans;\n\n    auto count_oni = [&]() -> int {\n        int c = 0;\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) c += (b[i][j] == 'x');\n        return c;\n    };\n\n    auto do_move = [&](char d, int p) {\n        ans.push_back({d, p});\n        if (d == 'L') {\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            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            for (int i = 0; i + 1 < n; i++) b[i][p] = b[i + 1][p];\n            b[n - 1][p] = '.';\n        } else if (d == 'D') {\n            for (int i = n - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n            b[0][p] = '.';\n        }\n    };\n\n    auto safe_no_fuku_above = [&](int i, int j) -> bool {\n        for (int r = 0; r < i; r++) if (b[r][j] == 'o') return false;\n        return true;\n    };\n    auto safe_no_fuku_below = [&](int i, int j) -> bool {\n        for (int r = i + 1; r < n; r++) if (b[r][j] == 'o') return false;\n        return true;\n    };\n    auto safe_no_fuku_left = [&](int i, int j) -> bool {\n        for (int c = 0; c < j; c++) if (b[i][c] == 'o') return false;\n        return true;\n    };\n    auto safe_no_fuku_right = [&](int i, int j) -> bool {\n        for (int c = j + 1; c < n; c++) if (b[i][c] == 'o') return false;\n        return true;\n    };\n\n    auto better = [&](const Candidate& a, const Candidate& c) -> bool {\n        if (!c.valid) return true;\n        // maximize removed / k\n        long long lhs = 1LL * a.removed * c.k;\n        long long rhs = 1LL * c.removed * a.k;\n        if (lhs != rhs) return lhs > rhs;\n        if (a.removed != c.removed) return a.removed > c.removed;\n        if (a.k != c.k) return a.k < c.k;\n        if (a.d != c.d) return a.d < c.d;\n        return a.p < c.p;\n    };\n\n    auto find_best_candidate = [&]() -> Candidate {\n        Candidate best;\n\n        // Rows: Left / Right\n        for (int i = 0; i < n; i++) {\n            // Left\n            int safe = 0;\n            while (safe < n && b[i][safe] != 'o') safe++;\n            int removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[i][k - 1] == 'x') removed++;\n                Candidate cand{'L', i, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n\n            // Right\n            safe = 0;\n            while (safe < n && b[i][n - 1 - safe] != 'o') safe++;\n            removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[i][n - k] == 'x') removed++;\n                Candidate cand{'R', i, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n        }\n\n        // Columns: Up / Down\n        for (int j = 0; j < n; j++) {\n            // Up\n            int safe = 0;\n            while (safe < n && b[safe][j] != 'o') safe++;\n            int removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[k - 1][j] == 'x') removed++;\n                Candidate cand{'U', j, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n\n            // Down\n            safe = 0;\n            while (safe < n && b[n - 1 - safe][j] != 'o') safe++;\n            removed = 0;\n            for (int k = 1; k <= safe; k++) {\n                if (b[n - k][j] == 'x') removed++;\n                Candidate cand{'D', j, k, removed, removed > 0};\n                if (cand.valid && better(cand, best)) best = cand;\n            }\n        }\n\n        return best;\n    };\n\n    // Greedy sweeps:\n    // Use only clearly beneficial candidates to avoid wasting move budget.\n    while (true) {\n        Candidate best = find_best_candidate();\n        if (!best.valid) break;\n\n        // Conservative acceptance rule:\n        // - always accept if removes at least 2 Oni\n        // - or removes 1 Oni with cost 1\n        if (!(best.removed >= 2 || (best.removed == 1 && best.k == 1))) break;\n\n        if ((int)ans.size() + best.k > 4 * n * n) break;\n        for (int t = 0; t < best.k; t++) do_move(best.d, best.p);\n    }\n\n    // Fallback: remove remaining Oni one by one with restore.\n    while (count_oni() > 0) {\n        bool done = false;\n        for (int i = 0; i < n && !done; i++) {\n            for (int j = 0; j < n && !done; j++) {\n                if (b[i][j] != 'x') continue;\n\n                if (safe_no_fuku_above(i, j)) {\n                    int need = i + 1;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('U', j);\n                    for (int t = 0; t < need; t++) do_move('D', j);\n                    done = true;\n                } else if (safe_no_fuku_below(i, j)) {\n                    int need = n - i;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('D', j);\n                    for (int t = 0; t < need; t++) do_move('U', j);\n                    done = true;\n                } else if (safe_no_fuku_left(i, j)) {\n                    int need = j + 1;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('L', i);\n                    for (int t = 0; t < need; t++) do_move('R', i);\n                    done = true;\n                } else if (safe_no_fuku_right(i, j)) {\n                    int need = n - j;\n                    if ((int)ans.size() + 2 * need > 4 * n * n) break;\n                    for (int t = 0; t < need; t++) do_move('R', i);\n                    for (int t = 0; t < need; t++) do_move('L', i);\n                    done = true;\n                } else {\n                    // Guaranteed not to happen by problem statement.\n                }\n            }\n        }\n        if (!done) break;\n    }\n\n    // Output operations\n    // The algorithm is designed to stay within the limit.\n    if ((int)ans.size() > 4 * n * n) {\n        ans.resize(4 * n * n);\n    }\n    for (auto &op : ans) {\n        cout << op.d << ' ' << op.p << '\\n';\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, L;\n    cin >> N >> L;\n    vector<int> T(N);\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    vector<int> a(N), b(N);\n\n    // Sort by target descending\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    // Number of hubs: small constant for simplicity and stability\n    int K = 12;\n    K = min(K, N);\n\n    vector<int> hubs(ord.begin(), ord.begin() + K);\n    vector<int> leaves(ord.begin() + K, ord.end());\n\n    vector<char> isHub(N, false);\n    for (int h : hubs) isHub[h] = true;\n\n    // Hub cycle: odd -> self, even -> next hub\n    for (int i = 0; i < K; ++i) {\n        int h = hubs[i];\n        int nxt = hubs[(i + 1) % K];\n        a[h] = h;\n        b[h] = nxt;\n    }\n\n    // Assign each leaf to a hub greedily by current assigned load\n    vector<long long> load(N, 0);\n    for (int h : hubs) load[h] = 0;\n\n    vector<int> parent(N, hubs[0]);\n    for (int x : leaves) {\n        int besth = hubs[0];\n        long long bestv = load[besth];\n        for (int h : hubs) {\n            if (load[h] < bestv) {\n                bestv = load[h];\n                besth = h;\n            }\n        }\n        parent[x] = besth;\n        load[besth] += T[x];\n    }\n\n    // Leaves: one-shot to assigned hub\n    for (int x : leaves) {\n        a[x] = parent[x];\n        b[x] = parent[x];\n    }\n\n    // Small refinement:\n    // Redirect some hub even-edges to leaves with larger targets, then leaf returns to next hub.\n    // This lets leaves receive recurring visits.\n    //\n    // For hub h_i:\n    //   odd -> h_i\n    //   even -> chosen leaf of h_i, or next hub if none\n    // leaf x:\n    //   both -> next hub after parent\n    //\n    // Since only one leaf can be attached directly per hub in this manner,\n    // choose the largest-target leaf assigned to each hub.\n\n    vector<vector<int>> group(N);\n    for (int x : leaves) group[parent[x]].push_back(x);\n    for (int h : hubs) {\n        sort(group[h].begin(), group[h].end(), [&](int x, int y) {\n            if (T[x] != T[y]) return T[x] > T[y];\n            return x < y;\n        });\n    }\n\n    for (int i = 0; i < K; ++i) {\n        int h = hubs[i];\n        int nxt = hubs[(i + 1) % K];\n        if (!group[h].empty()) {\n            int x = group[h][0];\n            b[h] = x;\n            a[x] = nxt;\n            b[x] = nxt;\n            for (int j = 1; j < (int)group[h].size(); ++j) {\n                int y = group[h][j];\n                a[y] = nxt;\n                b[y] = nxt;\n            }\n        }\n    }\n\n    // Output\n    for (int i = 0; i < N; ++i) {\n        cout << a[i] << ' ' << b[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    int n;\n    vector<int> p, sz;\n    DSU(int n = 0) { init(n); }\n    void init(int n_) {\n        n = n_;\n        p.resize(n);\n        sz.assign(n, 1);\n        iota(p.begin(), p.end(), 0);\n    }\n    int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (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 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\nstatic inline long long part1by1(unsigned x) {\n    long long n = x;\n    n = (n | (n << 16)) & 0x0000FFFF0000FFFFLL;\n    n = (n | (n << 8)) & 0x00FF00FF00FF00FFLL;\n    n = (n | (n << 4)) & 0x0F0F0F0F0F0F0F0FLL;\n    n = (n | (n << 2)) & 0x3333333333333333LL;\n    n = (n | (n << 1)) & 0x5555555555555555LL;\n    return n;\n}\n\nstatic inline long long morton_key(int x, int y) {\n    return (part1by1((unsigned)x) << 1) | part1by1((unsigned)y);\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    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<int> cx(N), cy(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    auto est_dist = [&](int a, int b) -> int {\n        long long dx = (long long)cx[a] - cx[b];\n        long long dy = (long long)cy[a] - cy[b];\n        return (int)floor(sqrt((double)(dx * dx + dy * dy)));\n    };\n\n    // Initial grouping by Morton order.\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        long long ka = morton_key(cx[a], cy[a]);\n        long long kb = morton_key(cx[b], cy[b]);\n        if (ka != kb) return ka < kb;\n        if (cx[a] != cx[b]) return cx[a] < cx[b];\n        return cy[a] < cy[b];\n    });\n\n    vector<vector<int>> groups(M);\n    {\n        int ptr = 0;\n        for (int i = 0; i < M; i++) {\n            groups[i].assign(ord.begin() + ptr, ord.begin() + ptr + G[i]);\n            ptr += G[i];\n        }\n    }\n\n    // Approximate MST cost for a small group using Prim on estimated distances.\n    auto approx_mst_cost = [&](const vector<int>& vs) -> long long {\n        int n = (int)vs.size();\n        if (n <= 1) return 0;\n        const int INF = 1e9;\n        vector<int> minc(n, INF);\n        vector<char> used(n, 0);\n        minc[0] = 0;\n        long long res = 0;\n        for (int it = 0; it < n; it++) {\n            int v = -1;\n            for (int i = 0; i < n; i++) {\n                if (!used[i] && (v == -1 || minc[i] < minc[v])) v = i;\n            }\n            used[v] = 1;\n            res += minc[v];\n            for (int to = 0; to < n; to++) if (!used[to]) {\n                int w = est_dist(vs[v], vs[to]);\n                if (w < minc[to]) minc[to] = w;\n            }\n        }\n        return res;\n    };\n\n    // Small local swap improvement between adjacent groups.\n    for (int pass = 0; pass < 2; pass++) {\n        for (int gi = 0; gi + 1 < M; gi++) {\n            auto &A = groups[gi], &B = groups[gi + 1];\n            if (A.empty() || B.empty()) continue;\n\n            long long base = approx_mst_cost(A) + approx_mst_cost(B);\n            long long best = base;\n            int besta = -1, bestb = -1;\n\n            int sa = (int)A.size(), sb = (int)B.size();\n            vector<int> candA, candB;\n            for (int i = max(0, sa - 5); i < sa; i++) candA.push_back(i);\n            for (int i = 0; i < min(sb, 5); i++) candB.push_back(i);\n\n            for (int ia : candA) for (int ib : candB) {\n                vector<int> nA = A, nB = B;\n                swap(nA[ia], nB[ib]);\n                long long val = approx_mst_cost(nA) + approx_mst_cost(nB);\n                if (val < best) {\n                    best = val;\n                    besta = ia;\n                    bestb = ib;\n                }\n            }\n            if (besta != -1) {\n                swap(A[besta], B[bestb]);\n            }\n        }\n    }\n\n    // Query budget allocation.\n    vector<vector<pair<int,int>>> queried_edges(M);\n    int used_queries = 0;\n\n    auto do_query = [&](const vector<int>& subset) -> vector<pair<int,int>> {\n        cout << \"? \" << subset.size();\n        for (int v : subset) cout << ' ' << v;\n        cout << '\\n';\n        cout.flush();\n        vector<pair<int,int>> ret;\n        for (int i = 0; i < (int)subset.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    // Prioritize larger groups for queries.\n    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n    sort(gids.begin(), gids.end(), [&](int a, int b) {\n        return groups[a].size() > groups[b].size();\n    });\n\n    for (int id : gids) {\n        if (used_queries >= Q) break;\n        auto &g = groups[id];\n        int sz = (int)g.size();\n        if (sz <= 1) continue;\n\n        int block = min(L, sz);\n        if (block < 2) continue;\n\n        // overlapping blocks\n        int step = max(1, block / 2);\n        for (int s = 0; s < sz && used_queries < Q; s += step) {\n            int e = min(sz, s + block);\n            if (e - s < 2) break;\n            if (e - s < 2) continue;\n            vector<int> subset(g.begin() + s, g.begin() + e);\n            auto ret = do_query(subset);\n            for (auto &p : ret) queried_edges[id].push_back(p);\n            used_queries++;\n            if (e == sz) break;\n        }\n    }\n\n    // Build final trees.\n    vector<vector<pair<int,int>>> answer_edges(M);\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        if (sz <= 1) continue;\n\n        unordered_map<int,int> lid;\n        lid.reserve(sz * 2);\n        for (int i = 0; i < sz; i++) lid[g[i]] = i;\n\n        vector<Edge> cand;\n        cand.reserve(sz * 10);\n\n        // queried edges\n        {\n            set<pair<int,int>> seen;\n            for (auto [a, b] : queried_edges[gi]) {\n                if (!lid.count(a) || !lid.count(b)) continue;\n                if (a > b) swap(a, b);\n                if (seen.insert({a, b}).second) {\n                    cand.push_back({a, b, est_dist(a, b)});\n                }\n            }\n        }\n\n        // k nearest neighbors by estimated center distance\n        int k = min(6, sz - 1);\n        for (int i = 0; i < sz; i++) {\n            vector<pair<int,int>> nei;\n            nei.reserve(sz - 1);\n            for (int j = 0; j < sz; j++) if (i != j) {\n                nei.push_back({est_dist(g[i], g[j]), g[j]});\n            }\n            nth_element(nei.begin(), nei.begin() + k, nei.end());\n            for (int t = 0; t < k; t++) {\n                int a = g[i], b = nei[t].second;\n                if (a > b) swap(a, b);\n                cand.push_back({a, b, nei[t].first});\n            }\n        }\n\n        // dedup\n        sort(cand.begin(), cand.end(), [&](const Edge& a, const Edge& b) {\n            if (a.u != b.u) return a.u < b.u;\n            if (a.v != b.v) return a.v < b.v;\n            return a.w < b.w;\n        });\n        vector<Edge> uniq;\n        for (auto &e : cand) {\n            if (e.u == e.v) continue;\n            if (uniq.empty() || uniq.back().u != e.u || uniq.back().v != e.v) uniq.push_back(e);\n        }\n        cand.swap(uniq);\n\n        sort(cand.begin(), cand.end());\n\n        DSU dsu(N);\n        vector<pair<int,int>> tree;\n        tree.reserve(sz - 1);\n\n        for (auto &e : cand) {\n            if (dsu.unite(e.u, e.v)) {\n                tree.push_back({e.u, e.v});\n                if ((int)tree.size() == sz - 1) break;\n            }\n        }\n\n        // Fallback: connect remaining components greedily\n        while ((int)tree.size() < sz - 1) {\n            int bu = -1, bv = -1, bw = INT_MAX;\n            for (int i = 0; i < sz; i++) for (int j = i + 1; j < sz; j++) {\n                int a = g[i], b = g[j];\n                if (dsu.find(a) == dsu.find(b)) continue;\n                int w = est_dist(a, b);\n                if (w < bw) {\n                    bw = w; bu = a; bv = b;\n                }\n            }\n            if (bu == -1) break;\n            dsu.unite(bu, bv);\n            tree.push_back({bu, bv});\n        }\n\n        answer_edges[gi] = move(tree);\n    }\n\n    // Final output\n    cout << \"!\\n\";\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < (int)groups[i].size(); j++) {\n            if (j) cout << ' ';\n            cout << groups[i][j];\n        }\n        cout << '\\n';\n        for (auto [a, b] : answer_edges[i]) {\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\nstatic const int N = 20;\nstatic const int INF = 1e9;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar DCH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nstruct Solver {\n    int M;\n    vector<Pos> pts;\n    vector<vector<int>> block;\n    vector<Action> ans;\n    Pos cur;\n\n    Solver(int M_, vector<Pos> pts_) : M(M_), pts(move(pts_)) {\n        block.assign(N, vector<int>(N, 0));\n        cur = pts[0];\n    }\n\n    // BFS path using only moves avoiding blocks\n    vector<int> bfs_move_dirs(Pos s, Pos g, const vector<vector<int>>& blk) {\n        vector<vector<int>> dist(N, vector<int>(N, -1));\n        vector<vector<pair<Pos,int>>> par(N, vector<pair<Pos,int>>(N, {{-1,-1}, -1}));\n        queue<Pos> q;\n        dist[s.r][s.c] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            auto v = q.front(); q.pop();\n            if (v == g) break;\n            for (int d = 0; d < 4; d++) {\n                int nr = v.r + dr[d], nc = v.c + dc[d];\n                if (!inside(nr, nc) || blk[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[v.r][v.c] + 1;\n                par[nr][nc] = {v, d};\n                q.push({nr, nc});\n            }\n        }\n        if (dist[g.r][g.c] == -1) return {};\n        vector<int> dirs;\n        Pos x = g;\n        while (x != s) {\n            auto [p, d] = par[x.r][x.c];\n            dirs.push_back(d);\n            x = p;\n        }\n        reverse(dirs.begin(), dirs.end());\n        return dirs;\n    }\n\n    pair<Pos,int> slide_result(Pos s, int d, const vector<vector<int>>& blk) {\n        int r = s.r, c = s.c;\n        while (true) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc) || blk[nr][nc]) break;\n            r = nr; c = nc;\n        }\n        return {{r, c}, (r != s.r || c != s.c)};\n    }\n\n    bool can_stop_at(Pos s, Pos g, int &dir_out) {\n        if (s.r == g.r) {\n            if (s.c < g.c) {\n                int d = 3;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            } else if (s.c > g.c) {\n                int d = 2;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            }\n        }\n        if (s.c == g.c) {\n            if (s.r < g.r) {\n                int d = 1;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            } else if (s.r > g.r) {\n                int d = 0;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            }\n        }\n        return false;\n    }\n\n    void apply_move_dir(int d) {\n        int nr = cur.r + dr[d], nc = cur.c + dc[d];\n        if (!inside(nr, nc) || block[nr][nc]) return; // safety\n        ans.push_back({'M', DCH[d]});\n        cur = {nr, nc};\n    }\n\n    void apply_slide_dir(int d) {\n        ans.push_back({'S', DCH[d]});\n        cur = slide_result(cur, d, block).first;\n    }\n\n    void apply_alter_dir(int d) {\n        int nr = cur.r + dr[d], nc = cur.c + dc[d];\n        if (!inside(nr, nc)) return; // safety\n        ans.push_back({'A', DCH[d]});\n        block[nr][nc] ^= 1;\n    }\n\n    int dir_between_adj(Pos a, Pos b) {\n        for (int d = 0; d < 4; d++) {\n            if (a.r + dr[d] == b.r && a.c + dc[d] == b.c) return d;\n        }\n        return -1;\n    }\n\n    struct Plan {\n        int cost = INF;\n        vector<Action> acts;\n        vector<pair<Pos,int>> toggles; // (cell, final toggled once)\n    };\n\n    void relax(Plan &best, const Plan &cand) {\n        if (cand.cost < best.cost) best = cand;\n    }\n\n    Plan pure_move_plan(Pos s, Pos g) {\n        Plan p;\n        auto dirs = bfs_move_dirs(s, g, block);\n        if (dirs.empty() && s != g) return p;\n        p.cost = (int)dirs.size();\n        for (int d : dirs) p.acts.push_back({'M', DCH[d]});\n        return p;\n    }\n\n    Plan direct_slide_plan(Pos s, Pos g) {\n        Plan p;\n        int d;\n        if (can_stop_at(s, g, d)) {\n            p.cost = 1;\n            p.acts.push_back({'S', DCH[d]});\n        }\n        return p;\n    }\n\n    // Move to x then slide to g\n    Plan move_then_slide(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d;\n        if (!can_stop_at(x, g, d)) return p;\n        auto dirs = bfs_move_dirs(s, x, block);\n        if (dirs.empty() && s != x) return p;\n        p.cost = (int)dirs.size() + 1;\n        for (int dd : dirs) p.acts.push_back({'M', DCH[dd]});\n        p.acts.push_back({'S', DCH[d]});\n        return p;\n    }\n\n    // Slide to x then move to g\n    Plan slide_then_move(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d = -1;\n        if (s.r == x.r) {\n            if (s.c < x.c) d = 3;\n            else if (s.c > x.c) d = 2;\n        } else if (s.c == x.c) {\n            if (s.r < x.r) d = 1;\n            else if (s.r > x.r) d = 0;\n        }\n        if (d == -1) return p;\n        auto res = slide_result(s, d, block);\n        if (res.first != x) return p;\n        auto dirs = bfs_move_dirs(x, g, block);\n        if (dirs.empty() && x != g) return p;\n        p.cost = 1 + (int)dirs.size();\n        p.acts.push_back({'S', DCH[d]});\n        for (int dd : dirs) p.acts.push_back({'M', DCH[dd]});\n        return p;\n    }\n\n    Plan slide_then_slide(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d1 = -1, d2 = -1;\n        if (s.r == x.r) {\n            if (s.c < x.c) d1 = 3;\n            else if (s.c > x.c) d1 = 2;\n        } else if (s.c == x.c) {\n            if (s.r < x.r) d1 = 1;\n            else if (s.r > x.r) d1 = 0;\n        }\n        if (d1 == -1) return p;\n        if (slide_result(s, d1, block).first != x) return p;\n        if (!can_stop_at(x, g, d2)) return p;\n        p.cost = 2;\n        p.acts.push_back({'S', DCH[d1]});\n        p.acts.push_back({'S', DCH[d2]});\n        return p;\n    }\n\n    // Create one stopper adjacent beyond g, then slide from aligned position x\n    Plan create_stopper_and_slide(Pos s, Pos g) {\n        Plan best;\n        for (int d = 0; d < 4; d++) {\n            int br = g.r + dr[d], bc = g.c + dc[d]; // blocker cell\n            if (!inside(br, bc)) continue;           // border already acts as stopper, no need here\n            if (block[br][bc]) continue;             // already blocked -> direct existing-block cases handled elsewhere\n\n            int sd = d ^ 1; // need to slide toward g from opposite side\n            // x must be on same line as g, and slide from x in sd must stop at g after placing block at (br,bc)\n            // Enumerate all possible x on that ray.\n            for (int k = 1; ; k++) {\n                int xr = g.r + dr[sd] * k;\n                int xc = g.c + dc[sd] * k;\n                if (!inside(xr, xc)) break;\n                if (block[xr][xc]) break; // can't stand there\n                Pos x{xr, xc};\n\n                // Need path s -> some y adjacent to blocker cell, place block, then path to x, then slide.\n                for (int ad = 0; ad < 4; ad++) {\n                    int yr = br - dr[ad], yc = bc - dc[ad];\n                    if (!inside(yr, yc) || block[yr][yc]) continue;\n                    Pos y{yr, yc};\n                    if (y.r == br && y.c == bc) continue;\n\n                    auto path1 = bfs_move_dirs(s, y, block);\n                    if (path1.empty() && s != y) continue;\n\n                    auto blk2 = block;\n                    blk2[br][bc] = 1;\n                    auto path2 = bfs_move_dirs(y, x, blk2);\n                    if (path2.empty() && y != x) continue;\n\n                    // verify slide with new block\n                    int dslide = -1;\n                    if (x.r == g.r) {\n                        if (x.c < g.c) dslide = 3;\n                        else if (x.c > g.c) dslide = 2;\n                    } else if (x.c == g.c) {\n                        if (x.r < g.r) dslide = 1;\n                        else if (x.r > g.r) dslide = 0;\n                    }\n                    if (dslide == -1) continue;\n\n                    // simulate on blk2\n                    int rr = x.r, cc = x.c;\n                    while (true) {\n                        int nr = rr + dr[dslide], nc = cc + dc[dslide];\n                        if (!inside(nr, nc) || blk2[nr][nc]) break;\n                        rr = nr; cc = nc;\n                    }\n                    if (rr != g.r || cc != g.c) continue;\n\n                    Plan p;\n                    p.cost = (int)path1.size() + 1 + (int)path2.size() + 1;\n                    for (int dd : path1) p.acts.push_back({'M', DCH[dd]});\n                    p.acts.push_back({'A', DCH[ad]});\n                    for (int dd : path2) p.acts.push_back({'M', DCH[dd]});\n                    p.acts.push_back({'S', DCH[dslide]});\n                    p.toggles.push_back({{br, bc}, 1});\n                    relax(best, p);\n                }\n            }\n        }\n        return best;\n    }\n\n    void execute_plan(const Plan &p) {\n        for (auto act : p.acts) {\n            if (act.a == 'M') {\n                int d = string(\"UDLR\").find(act.d);\n                apply_move_dir(d);\n            } else if (act.a == 'S') {\n                int d = string(\"UDLR\").find(act.d);\n                apply_slide_dir(d);\n            } else {\n                int d = string(\"UDLR\").find(act.d);\n                apply_alter_dir(d);\n            }\n        }\n    }\n\n    void solve() {\n        for (int idx = 1; idx < M; idx++) {\n            Pos g = pts[idx];\n            Plan best = pure_move_plan(cur, g);\n\n            relax(best, direct_slide_plan(cur, g));\n\n            for (int r = 0; r < N; r++) for (int c = 0; c < N; c++) {\n                if (block[r][c]) continue;\n                Pos x{r, c};\n                relax(best, move_then_slide(cur, x, g));\n                relax(best, slide_then_move(cur, x, g));\n                relax(best, slide_then_slide(cur, x, g));\n            }\n\n            relax(best, create_stopper_and_slide(cur, g));\n\n            if (best.cost >= INF) {\n                best = pure_move_plan(cur, g);\n            }\n\n            execute_plan(best);\n\n            // safety fallback if not reached due to any inconsistency\n            if (cur != g) {\n                auto dirs = bfs_move_dirs(cur, g, block);\n                for (int d : dirs) apply_move_dir(d);\n            }\n\n            // if target cell somehow blocked (shouldn't happen if reached), unblock from adjacent later if needed.\n            // We guarantee current cell is unblocked because moves/slides can't end on blocked cell.\n        }\n\n        // Hard safety: ensure action count not excessive; if somehow too large, truncate is invalid.\n        // But this heuristic should stay comfortably below 1600.\n        for (auto &x : ans) {\n            cout << x.a << ' ' << x.d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N_in, M;\n    cin >> N_in >> M;\n    vector<Pos> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].r >> pts[i].c;\n\n    Solver solver(M, pts);\n    solver.solve();\n    return 0;\n}"},"4":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int LIM = 10000;\n\nstruct Input {\n    int x, y, r;\n};\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nstatic inline bool overlap1D(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstatic inline bool overlap2D(const Rect& p, const Rect& q) {\n    return overlap1D(p.a, p.c, q.a, q.c) && overlap1D(p.b, p.d, q.b, q.d);\n}\n\nstatic inline long long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\nstatic inline double sat(long long s, long long r) {\n    double t = (double)min(s, r) / (double)max(s, r);\n    double u = 1.0 - t;\n    return 1.0 - u * u;\n}\n\nstruct Move {\n    int idx = -1;\n    Rect nr{};\n    double gain = -1e100;\n    bool valid = false;\n};\n\nstruct Solver {\n    int n;\n    vector<Input> in;\n    mt19937 rng;\n    vector<double> density_priority;\n\n    Solver(int n_, vector<Input> in_) : n(n_), in(std::move(in_)) {\n        rng.seed((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n        build_density_priority();\n    }\n\n    void build_density_priority() {\n        density_priority.assign(n, 0.0);\n        for (int i = 0; i < n; i++) {\n            int lx = in[i].x + 1;\n            int rx = LIM - in[i].x;\n            int dy = in[i].y + 1;\n            int uy = LIM - in[i].y;\n\n            for (int j = 0; j < n; j++) if (i != j) {\n                if (in[j].x < in[i].x) lx = min(lx, in[i].x - in[j].x);\n                if (in[j].x > in[i].x) rx = min(rx, in[j].x - in[i].x);\n                if (in[j].y < in[i].y) dy = min(dy, in[i].y - in[j].y);\n                if (in[j].y > in[i].y) uy = min(uy, in[j].y - in[i].y);\n            }\n\n            double free_est = 1.0 * (lx + rx) * (dy + uy);\n            density_priority[i] = (double)in[i].r / max(1.0, free_est);\n        }\n    }\n\n    double score_one(int i, const Rect& r) const {\n        return sat(area(r), in[i].r);\n    }\n\n    double total_score(const vector<Rect>& rects) const {\n        double res = 0.0;\n        for (int i = 0; i < n; i++) res += score_one(i, rects[i]);\n        return res;\n    }\n\n    bool contains_point(int i, const Rect& r) const {\n        return r.a <= in[i].x && in[i].x < r.c && r.b <= in[i].y && in[i].y < r.d;\n    }\n\n    bool legal_shape(const Rect& r) const {\n        return 0 <= r.a && r.a < r.c && r.c <= LIM && 0 <= r.b && r.b < r.d && r.d <= LIM;\n    }\n\n    bool can_place(const vector<Rect>& rects, int i, const Rect& nr) const {\n        if (!legal_shape(nr)) return false;\n        if (!contains_point(i, nr)) return false;\n        for (int j = 0; j < n; j++) {\n            if (j == i) continue;\n            if (overlap2D(nr, rects[j])) return false;\n        }\n        return true;\n    }\n\n    int max_left(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && q.c <= r.a) bound = max(bound, q.c);\n        }\n        return r.a - bound;\n    }\n\n    int max_right(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && r.c <= q.a) bound = min(bound, q.a);\n        }\n        return bound - r.c;\n    }\n\n    int max_down(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && q.d <= r.b) bound = max(bound, q.d);\n        }\n        return r.b - bound;\n    }\n\n    int max_up(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && r.d <= q.b) bound = min(bound, q.b);\n        }\n        return bound - r.d;\n    }\n\n    Move best_move_for(const vector<Rect>& rects, int i) const {\n        const Rect& cur = rects[i];\n        long long curA = area(cur);\n        long long target = in[i].r;\n        double curScore = score_one(i, cur);\n\n        int L = max_left(rects, i);\n        int R = max_right(rects, i);\n        int D = max_down(rects, i);\n        int U = max_up(rects, i);\n\n        Move best;\n\n        auto upd = [&](const Rect& nr) {\n            if (!can_place(rects, i, nr)) return;\n            double g = score_one(i, nr) - curScore;\n            if (g > best.gain) {\n                best = {i, nr, g, true};\n            }\n        };\n\n        auto collect_1d = [&](int lim, int unit) {\n            vector<int> cand;\n            if (lim <= 0) return cand;\n            cand.push_back(1);\n            cand.push_back(lim);\n            cand.push_back(max(1, lim / 2));\n            cand.push_back(min(lim, 2));\n            cand.push_back(min(lim, 4));\n            cand.push_back(min(lim, 8));\n            if (curA < target) {\n                int need = (int)((target - curA + unit - 1) / unit);\n                for (int d = -3; d <= 3; d++) {\n                    int t = need + d;\n                    if (1 <= t && t <= lim) cand.push_back(t);\n                }\n            }\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n            return cand;\n        };\n\n        int w = cur.c - cur.a;\n        int h = cur.d - cur.b;\n\n        // 1-edge expansion\n        auto candH = collect_1d(max(L, R), h);\n        auto candW = collect_1d(max(D, U), w);\n\n        for (int t : candH) {\n            if (t <= L) { Rect nr = cur; nr.a -= t; upd(nr); }\n            if (t <= R) { Rect nr = cur; nr.c += t; upd(nr); }\n        }\n        for (int t : candW) {\n            if (t <= D) { Rect nr = cur; nr.b -= t; upd(nr); }\n            if (t <= U) { Rect nr = cur; nr.d += t; upd(nr); }\n        }\n\n        // 2-edge symmetric expansions (horizontal / vertical)\n        {\n            vector<pair<int,int>> pairs;\n            if (L > 0 || R > 0) {\n                int lim = L + R;\n                vector<int> cand = collect_1d(lim, h);\n                for (int tot : cand) {\n                    int l = min(L, tot / 2);\n                    int r = min(R, tot - l);\n                    if (l + r < tot) {\n                        int rem = tot - (l + r);\n                        int addL = min(L - l, rem);\n                        l += addL;\n                        r += min(R - r, rem - addL);\n                    }\n                    if (l + r == tot && tot > 0) {\n                        Rect nr = cur;\n                        nr.a -= l;\n                        nr.c += r;\n                        upd(nr);\n                    }\n                }\n            }\n            if (D > 0 || U > 0) {\n                int lim = D + U;\n                vector<int> cand = collect_1d(lim, w);\n                for (int tot : cand) {\n                    int d = min(D, tot / 2);\n                    int u = min(U, tot - d);\n                    if (d + u < tot) {\n                        int rem = tot - (d + u);\n                        int addD = min(D - d, rem);\n                        d += addD;\n                        u += min(U - u, rem - addD);\n                    }\n                    if (d + u == tot && tot > 0) {\n                        Rect nr = cur;\n                        nr.b -= d;\n                        nr.d += u;\n                        upd(nr);\n                    }\n                }\n            }\n        }\n\n        // 2-edge cross expansions\n        auto small_set = [&](int lim) {\n            vector<int> v;\n            if (lim <= 0) return v;\n            v.push_back(1);\n            v.push_back(min(lim, 2));\n            v.push_back(min(lim, 4));\n            v.push_back(lim);\n            v.push_back(max(1, lim / 2));\n            sort(v.begin(), v.end());\n            v.erase(unique(v.begin(), v.end()), v.end());\n            return v;\n        };\n\n        vector<int> cL = small_set(L), cR = small_set(R), cD = small_set(D), cU = small_set(U);\n        for (int xl : cL) for (int yd : cD) {\n            Rect nr = cur; nr.a -= xl; nr.b -= yd; upd(nr);\n        }\n        for (int xl : cL) for (int yu : cU) {\n            Rect nr = cur; nr.a -= xl; nr.d += yu; upd(nr);\n        }\n        for (int xr : cR) for (int yd : cD) {\n            Rect nr = cur; nr.c += xr; nr.b -= yd; upd(nr);\n        }\n        for (int xr : cR) for (int yu : cU) {\n            Rect nr = cur; nr.c += xr; nr.d += yu; upd(nr);\n        }\n\n        return best;\n    }\n\n    bool apply_best_for(vector<Rect>& rects, int i) const {\n        Move mv = best_move_for(rects, i);\n        if (mv.valid && mv.gain > 1e-15) {\n            rects[i] = mv.nr;\n            return true;\n        }\n        return false;\n    }\n\n    bool best_improvement_step(vector<Rect>& rects) const {\n        Move best;\n        for (int i = 0; i < n; i++) {\n            Move mv = best_move_for(rects, i);\n            if (mv.valid && mv.gain > best.gain) best = mv;\n        }\n        if (best.valid && best.gain > 1e-15) {\n            rects[best.idx] = best.nr;\n            return true;\n        }\n        return false;\n    }\n\n    void micro_adjust(vector<Rect>& rects, const vector<int>& ord) const {\n        for (int i : ord) {\n            Rect cur = rects[i];\n            double curScore = score_one(i, cur);\n            double bestGain = 1e-18;\n            Rect bestRect = cur;\n\n            auto try_one = [&](const Rect& nr) {\n                if (!can_place(rects, i, nr)) return;\n                double g = score_one(i, nr) - curScore;\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestRect = nr;\n                }\n            };\n\n            int L = max_left(rects, i);\n            int R = max_right(rects, i);\n            int D = max_down(rects, i);\n            int U = max_up(rects, i);\n\n            if (L >= 1) { Rect nr = cur; nr.a--; try_one(nr); }\n            if (R >= 1) { Rect nr = cur; nr.c++; try_one(nr); }\n            if (D >= 1) { Rect nr = cur; nr.b--; try_one(nr); }\n            if (U >= 1) { Rect nr = cur; nr.d++; try_one(nr); }\n\n            // a few 2-edge tiny moves\n            if (L >= 1 && D >= 1) { Rect nr = cur; nr.a--; nr.b--; try_one(nr); }\n            if (L >= 1 && U >= 1) { Rect nr = cur; nr.a--; nr.d++; try_one(nr); }\n            if (R >= 1 && D >= 1) { Rect nr = cur; nr.c++; nr.b--; try_one(nr); }\n            if (R >= 1 && U >= 1) { Rect nr = cur; nr.c++; nr.d++; try_one(nr); }\n\n            if (bestGain > 1e-15) rects[i] = bestRect;\n        }\n    }\n\n    vector<int> make_order(int mode) {\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n\n        if (mode == 0) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) {\n                return in[i].r > in[j].r;\n            });\n        } else if (mode == 1) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) {\n                return in[i].r < in[j].r;\n            });\n        } else if (mode == 2) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) {\n                return density_priority[i] > density_priority[j];\n            });\n        } else {\n            shuffle(ord.begin(), ord.end(), rng);\n        }\n        return ord;\n    }\n\n    vector<Rect> run_one_strategy(int mode, double end_time, chrono::steady_clock::time_point global_start) {\n        vector<Rect> rects(n);\n        for (int i = 0; i < n; i++) rects[i] = {in[i].x, in[i].y, in[i].x + 1, in[i].y + 1};\n\n        vector<int> ord = make_order(mode);\n\n        // phase 1: ordered greedy\n        for (int pass = 0; pass < 6; pass++) {\n            for (int i : ord) apply_best_for(rects, i);\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) return rects;\n        }\n\n        // phase 2: a few best-improvement steps\n        for (int rep = 0; rep < 30; rep++) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) return rects;\n            if (!best_improvement_step(rects)) break;\n        }\n\n        // phase 3: random passes\n        vector<int> rnd(n);\n        iota(rnd.begin(), rnd.end(), 0);\n        int idle = 0;\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) break;\n\n            shuffle(rnd.begin(), rnd.end(), rng);\n            bool updated = false;\n            for (int i : rnd) {\n                if (apply_best_for(rects, i)) updated = true;\n            }\n            if (!updated) {\n                idle++;\n                if (idle >= 5) break;\n            } else {\n                idle = 0;\n            }\n        }\n\n        // phase 4: micro\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) break;\n            shuffle(rnd.begin(), rnd.end(), rng);\n            micro_adjust(rects, rnd);\n        }\n\n        return rects;\n    }\n\n    vector<Rect> best_rects;\n\n    void solve() {\n        auto start = chrono::steady_clock::now();\n        best_rects.assign(n, {0,0,1,1});\n        double best_score = -1e100;\n\n        vector<int> modes = {0, 2, 3, 1, 3, 2, 3, 0};\n        int T = (int)modes.size();\n\n        for (int t = 0; t < T; t++) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > 4.93) break;\n\n            double remain = 4.97 - elapsed;\n            int left = T - t;\n            double slice = max(0.20, remain / left);\n\n            auto rects = run_one_strategy(modes[t], elapsed + slice, start);\n            double sc = total_score(rects);\n            if (sc > best_score) {\n                best_score = sc;\n                best_rects = rects;\n            }\n        }\n    }\n\n    void output() const {\n        for (int i = 0; i < n; i++) {\n            cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n                 << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Input> in(n);\n    for (int i = 0; i < n; i++) cin >> in[i].x >> in[i].y >> in[i].r;\n\n    Solver solver(n, in);\n    solver.solve();\n    solver.output();\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { return l + (int)(next_u32() % (uint32_t)(r - l)); }\n    double next_double() { return (double)next_u32() / (double)UINT32_MAX; }\n};\n\nstruct Param {\n    double w_gain;\n    double w_future;\n    double w_reach;\n    double w_mob;\n    double w_dead;\n    double w_small;\n    double look2;\n    double noise;\n    int bfs_depth;\n    int bfs_cap;\n};\n\nstruct EvalResult {\n    double future_score;\n    int reach_cnt;\n    int frontier_sum;\n};\n\nstruct Cand {\n    int dir;\n    int ni, nj;\n    double score;\n};\n\nint si, sj;\nint tid[N][N];\nint p[N][N];\nint tile_cnt;\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 inb(int i, int j) {\n    return 0 <= i && i < N && 0 <= j && j < N;\n}\n\nint vis_stamp[N][N];\nint dista[N][N];\nint cur_stamp = 1;\n\nEvalResult bfs_eval(int si, int sj, const vector<unsigned char>& usedTile, int depth_limit, int node_cap) {\n    ++cur_stamp;\n    if (cur_stamp == INT_MAX) {\n        memset(vis_stamp, 0, sizeof(vis_stamp));\n        cur_stamp = 1;\n    }\n\n    static const double decay[64] = {\n        1.0,\n        0.94, 0.88, 0.83, 0.78, 0.73, 0.69, 0.65,\n        0.61, 0.57, 0.54, 0.51, 0.48, 0.45, 0.42, 0.40,\n        0.38, 0.36, 0.34, 0.32, 0.30, 0.28, 0.27, 0.26,\n        0.25, 0.24, 0.23, 0.22, 0.21, 0.20, 0.19, 0.18,\n        0.17, 0.16, 0.15, 0.145, 0.14, 0.135, 0.13, 0.125,\n        0.12, 0.115, 0.11, 0.105, 0.10, 0.095, 0.09, 0.085,\n        0.08, 0.075, 0.07, 0.065, 0.06, 0.055, 0.05, 0.045,\n        0.04, 0.038, 0.036, 0.034, 0.032, 0.03, 0.028, 0.026\n    };\n\n    queue<pair<int,int>> q;\n    q.push({si, sj});\n    vis_stamp[si][sj] = cur_stamp;\n    dista[si][sj] = 0;\n\n    double future_score = 0.0;\n    int reach_cnt = 0;\n    int frontier_sum = 0;\n\n    while (!q.empty() && reach_cnt < node_cap) {\n        auto [i, j] = q.front();\n        q.pop();\n        int d = dista[i][j];\n        ++reach_cnt;\n\n        if (d > 0) future_score += p[i][j] * decay[min(d, 63)];\n\n        int local_frontier = 0;\n        if (d < depth_limit) {\n            for (int k = 0; k < 4; ++k) {\n                int ni = i + di[k], nj = j + dj[k];\n                if (!inb(ni, nj)) continue;\n                if (usedTile[tid[ni][nj]]) continue;\n                ++local_frontier;\n                if (vis_stamp[ni][nj] == cur_stamp) continue;\n                vis_stamp[ni][nj] = cur_stamp;\n                dista[ni][nj] = d + 1;\n                q.push({ni, nj});\n            }\n        }\n        frontier_sum += local_frontier;\n    }\n\n    return {future_score, reach_cnt, frontier_sum};\n}\n\ndouble eval_move(int ni, int nj, int step_id, const vector<unsigned char>& usedTile, const Param& par) {\n    int mob = 0;\n    int mask = 0;\n    for (int k = 0; k < 4; ++k) {\n        int xi = ni + di[k], xj = nj + dj[k];\n        if (!inb(xi, xj)) continue;\n        if (usedTile[tid[xi][xj]]) continue;\n        ++mob;\n        mask |= (1 << k);\n    }\n\n    EvalResult e = bfs_eval(ni, nj, usedTile, par.bfs_depth, par.bfs_cap);\n\n    double dead_pen = 0.0;\n    if (mob == 0) dead_pen = 1.0;\n    else if (mob == 1 && step_id < 1000) dead_pen = 0.6;\n    else if (mob == 2 && step_id < 800) {\n        bool opposite =\n            (mask == ((1 << 0) | (1 << 1))) ||\n            (mask == ((1 << 2) | (1 << 3)));\n        if (opposite) dead_pen = 0.2;\n    }\n\n    double small_pen = 0.0;\n    if (e.reach_cnt <= 8 && step_id < 1200) small_pen += (9 - e.reach_cnt);\n    if (e.reach_cnt <= 3 && step_id < 1200) small_pen += 5.0;\n\n    double sc = 0.0;\n    sc += par.w_gain * p[ni][nj];\n    sc += par.w_future * e.future_score;\n    sc += par.w_reach * e.reach_cnt;\n    sc += par.w_mob * mob;\n    sc += 0.12 * e.frontier_sum;\n    sc -= par.w_dead * dead_pen;\n    sc -= par.w_small * small_pen;\n    return sc;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    int mx = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tid[i][j];\n            mx = max(mx, tid[i][j]);\n        }\n    }\n    tile_cnt = mx + 1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> p[i][j];\n    }\n\n    vector<Param> params = {\n        {1.00, 0.090, 1.20, 10.0, 26.0, 2.8, 0.35, 1.3, 11, 130},\n        {1.08, 0.080, 1.05,  8.0, 23.0, 2.5, 0.32, 1.5, 10, 120},\n        {0.94, 0.100, 1.30, 12.0, 29.0, 3.0, 0.38, 1.1, 12, 140},\n        {1.15, 0.072, 0.95,  7.0, 21.0, 2.3, 0.28, 1.7, 10, 110},\n        {0.98, 0.095, 1.15, 11.0, 27.0, 2.7, 0.36, 1.2, 12, 135}\n    };\n\n    Timer timer;\n    XorShift rng;\n\n    string best_path;\n    int best_score = p[si][sj];\n\n    vector<unsigned char> usedTile(tile_cnt, 0);\n\n    while (timer.elapsed() < 1.90) {\n        Param par = params[rng.next_int(0, (int)params.size())];\n        par.w_gain += (rng.next_double() - 0.5) * 0.08;\n        par.w_future += (rng.next_double() - 0.5) * 0.015;\n        par.w_reach += (rng.next_double() - 0.5) * 0.15;\n        par.w_mob += (rng.next_double() - 0.5) * 1.5;\n        par.w_dead += (rng.next_double() - 0.5) * 4.0;\n        par.w_small += (rng.next_double() - 0.5) * 0.5;\n\n        fill(usedTile.begin(), usedTile.end(), 0);\n\n        int ci = si, cj = sj;\n        int score = p[ci][cj];\n        string path;\n        usedTile[tid[ci][cj]] = 1;\n\n        while (true) {\n            vector<Cand> cand;\n            int step_id = (int)path.size();\n\n            for (int d = 0; d < 4; ++d) {\n                int ni = ci + di[d], nj = cj + dj[d];\n                if (!inb(ni, nj)) continue;\n                int nt = tid[ni][nj];\n                if (usedTile[nt]) continue;\n\n                usedTile[nt] = 1;\n                double sc = eval_move(ni, nj, step_id, usedTile, par);\n                usedTile[nt] = 0;\n\n                cand.push_back({d, ni, nj, sc});\n            }\n\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n                return a.score > b.score;\n            });\n\n            // selective cheap 2-ply lookahead for top candidates\n            int K = min(3, (int)cand.size());\n            for (int idx = 0; idx < K; ++idx) {\n                int d1 = cand[idx].dir;\n                int n1i = cand[idx].ni, n1j = cand[idx].nj;\n                int t1 = tid[n1i][n1j];\n\n                usedTile[t1] = 1;\n\n                double best2 = -1e100;\n                bool has2 = false;\n                for (int d2 = 0; d2 < 4; ++d2) {\n                    int n2i = n1i + di[d2], n2j = n1j + dj[d2];\n                    if (!inb(n2i, n2j)) continue;\n                    int t2 = tid[n2i][n2j];\n                    if (usedTile[t2]) continue;\n\n                    usedTile[t2] = 1;\n                    double sc2 = eval_move(n2i, n2j, step_id + 1, usedTile, par);\n                    usedTile[t2] = 0;\n\n                    best2 = max(best2, sc2);\n                    has2 = true;\n                }\n\n                if (has2) cand[idx].score += par.look2 * best2;\n\n                usedTile[t1] = 0;\n            }\n\n            sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n                return a.score > b.score;\n            });\n\n            int pick = 0;\n            if ((int)cand.size() >= 2 && rng.next_double() < 0.10) pick = 1;\n            if ((int)cand.size() >= 3 && rng.next_double() < 0.02) pick = 2;\n\n            int d = cand[pick].dir;\n            ci += di[d];\n            cj += dj[d];\n            usedTile[tid[ci][cj]] = 1;\n            path.push_back(dc[d]);\n            score += p[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    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HN = 29; // horizontal edges per row\nstatic constexpr int VN = 29; // vertical edges per col\nstatic constexpr double INIT_COST = 5000.0;\nstatic constexpr double MIN_COST = 500.0;\nstatic constexpr double MAX_COST = 9500.0;\n\nstruct EdgeRef {\n    bool horiz; // true: h[i][j] between (i,j) and (i,j+1), false: v[i][j] between (i,j) and (i+1,j)\n    int i, j;\n};\n\nstruct Solver {\n    // current local edge estimates\n    double h_est[N][HN];\n    double v_est[VN][N];\n\n    // traversal stats\n    double h_sum[N][HN], v_sum[VN][N];\n    int h_cnt[N][HN], v_cnt[VN][N];\n\n    // segmented priors\n    double h_prior[N][HN];\n    double v_prior[VN][N];\n\n    int turn = 0;\n\n    Solver() {\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = INIT_COST;\n                h_sum[i][j] = 0.0;\n                h_cnt[i][j] = 0;\n                h_prior[i][j] = INIT_COST;\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = INIT_COST;\n                v_sum[i][j] = 0.0;\n                v_cnt[i][j] = 0;\n                v_prior[i][j] = INIT_COST;\n            }\n        }\n    }\n\n    static double clamp_cost(double x) {\n        if (x < MIN_COST) return MIN_COST;\n        if (x > MAX_COST) return MAX_COST;\n        return x;\n    }\n\n    // Fit 1-or-2 segment piecewise constant model to each row/column using current local estimates.\n    void rebuild_priors() {\n        // Horizontal rows: 29 values each\n        for (int i = 0; i < N; i++) {\n            double a[HN];\n            for (int j = 0; j < HN; j++) a[j] = h_est[i][j];\n\n            // Prefix sums for SSE\n            double ps[HN + 1] = {}, ps2[HN + 1] = {};\n            for (int j = 0; j < HN; j++) {\n                ps[j + 1] = ps[j] + a[j];\n                ps2[j + 1] = ps2[j] + a[j] * a[j];\n            }\n            auto seg_cost = [&](int l, int r) -> pair<double,double> { // [l,r)\n                double s = ps[r] - ps[l];\n                double s2 = ps2[r] - ps2[l];\n                int len = r - l;\n                double mean = s / len;\n                double cost = s2 - 2 * mean * s + len * mean * mean;\n                return {cost, mean};\n            };\n\n            // one segment\n            auto [bestCost1, mean1] = seg_cost(0, HN);\n            double bestCost = bestCost1;\n            int bestSplit = -1;\n            double bestL = mean1, bestR = mean1;\n\n            // two segments\n            for (int sp = 1; sp < HN; sp++) {\n                auto [c1, m1] = seg_cost(0, sp);\n                auto [c2, m2] = seg_cost(sp, HN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestL = m1;\n                    bestR = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int j = 0; j < HN; j++) h_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int j = 0; j < bestSplit; j++) h_prior[i][j] = clamp_cost(bestL);\n                for (int j = bestSplit; j < HN; j++) h_prior[i][j] = clamp_cost(bestR);\n            }\n        }\n\n        // Vertical columns: 29 values each for each col\n        for (int j = 0; j < N; j++) {\n            double a[VN];\n            for (int i = 0; i < VN; i++) a[i] = v_est[i][j];\n\n            double ps[VN + 1] = {}, ps2[VN + 1] = {};\n            for (int i = 0; i < VN; i++) {\n                ps[i + 1] = ps[i] + a[i];\n                ps2[i + 1] = ps2[i] + a[i] * a[i];\n            }\n            auto seg_cost = [&](int l, int r) -> pair<double,double> {\n                double s = ps[r] - ps[l];\n                double s2 = ps2[r] - ps2[l];\n                int len = r - l;\n                double mean = s / len;\n                double cost = s2 - 2 * mean * s + len * mean * mean;\n                return {cost, mean};\n            };\n\n            auto [bestCost1, mean1] = seg_cost(0, VN);\n            double bestCost = bestCost1;\n            int bestSplit = -1;\n            double bestU = mean1, bestD = mean1;\n\n            for (int sp = 1; sp < VN; sp++) {\n                auto [c1, m1] = seg_cost(0, sp);\n                auto [c2, m2] = seg_cost(sp, VN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestU = m1;\n                    bestD = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int i = 0; i < VN; i++) v_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int i = 0; i < bestSplit; i++) v_prior[i][j] = clamp_cost(bestU);\n                for (int i = bestSplit; i < VN; i++) v_prior[i][j] = clamp_cost(bestD);\n            }\n        }\n    }\n\n    double blended_h(int i, int j) const {\n        // Early: stronger prior. Later: stronger local.\n        double alpha = min(0.85, 0.15 + 0.7 * turn / 1000.0); // weight of local\n        return alpha * h_est[i][j] + (1.0 - alpha) * h_prior[i][j];\n    }\n\n    double blended_v(int i, int j) const {\n        double alpha = min(0.85, 0.15 + 0.7 * turn / 1000.0);\n        return alpha * v_est[i][j] + (1.0 - alpha) * v_prior[i][j];\n    }\n\n    int vid(int i, int j) const { return i * N + j; }\n    pair<int,int> pos(int id) const { return {id / N, id % N}; }\n\n    pair<string, vector<EdgeRef>> shortest_path(int si, int sj, int ti, int tj) {\n        const int V = N * N;\n        vector<double> dist(V, 1e100);\n        vector<int> prev(V, -1);\n        vector<char> prevMove(V, '?');\n\n        using P = pair<double,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        int s = vid(si, sj), t = vid(ti, tj);\n        dist[s] = 0;\n        pq.push({0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == t) break;\n            auto [i, j] = pos(u);\n\n            // U\n            if (i > 0) {\n                int ni = i - 1, nj = j;\n                int v = vid(ni, nj);\n                double w = blended_v(ni, nj);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'U';\n                    pq.push({dist[v], v});\n                }\n            }\n            // D\n            if (i + 1 < N) {\n                int ni = i + 1, nj = j;\n                int v = vid(ni, nj);\n                double w = blended_v(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'D';\n                    pq.push({dist[v], v});\n                }\n            }\n            // L\n            if (j > 0) {\n                int ni = i, nj = j - 1;\n                int v = vid(ni, nj);\n                double w = blended_h(i, nj);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'L';\n                    pq.push({dist[v], v});\n                }\n            }\n            // R\n            if (j + 1 < N) {\n                int ni = i, nj = j + 1;\n                int v = vid(ni, nj);\n                double w = blended_h(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    prevMove[v] = 'R';\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        string path;\n        vector<EdgeRef> edges_rev;\n        int cur = t;\n        while (cur != s) {\n            char mv = prevMove[cur];\n            path.push_back(mv);\n            auto [i, j] = pos(cur);\n            if (mv == 'U') {\n                // prev = (i+1, j), traversed vertical edge at (i, j)\n                edges_rev.push_back({false, i, j});\n            } else if (mv == 'D') {\n                // prev = (i-1, j), traversed vertical edge at (i-1, j)\n                edges_rev.push_back({false, i - 1, j});\n            } else if (mv == 'L') {\n                // prev = (i, j+1), traversed horizontal edge at (i, j)\n                edges_rev.push_back({true, i, j});\n            } else if (mv == 'R') {\n                // prev = (i, j-1), traversed horizontal edge at (i, j - 1)\n                edges_rev.push_back({true, i, j - 1});\n            } else {\n                // Should never happen\n                break;\n            }\n            cur = prev[cur];\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges_rev.begin(), edges_rev.end());\n        return {path, edges_rev};\n    }\n\n    double path_pred_cost(const vector<EdgeRef>& edges) const {\n        double s = 0.0;\n        for (auto &e : edges) {\n            if (e.horiz) s += blended_h(e.i, e.j);\n            else s += blended_v(e.i, e.j);\n        }\n        return s;\n    }\n\n    void update_from_feedback(const vector<EdgeRef>& edges, int observed) {\n        if (edges.empty()) return;\n\n        double pred = path_pred_cost(edges);\n        pred = max(pred, 1.0);\n        double ratio = observed / pred;\n\n        // multiplicative-noise robust clipping\n        ratio = max(0.8, min(1.25, ratio));\n\n        int L = (int)edges.size();\n        double avg_obs = 1.0 * observed / L;\n\n        // learning rates\n        double lr_mult = (turn < 100 ? 0.22 : turn < 300 ? 0.16 : 0.12);\n        double lr_avg  = (turn < 100 ? 0.050 : 0.030);\n\n        for (auto &e : edges) {\n            if (e.horiz) {\n                double cur = h_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = avg_obs;\n                double nv = cur * (1.0 - lr_mult) + target1 * lr_mult;\n                nv = nv * (1.0 - lr_avg) + target2 * lr_avg;\n                nv = clamp_cost(nv);\n\n                h_est[e.i][e.j] = nv;\n                h_sum[e.i][e.j] += avg_obs;\n                h_cnt[e.i][e.j] += 1;\n            } else {\n                double cur = v_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = avg_obs;\n                double nv = cur * (1.0 - lr_mult) + target1 * lr_mult;\n                nv = nv * (1.0 - lr_avg) + target2 * lr_avg;\n                nv = clamp_cost(nv);\n\n                v_est[e.i][e.j] = nv;\n                v_sum[e.i][e.j] += avg_obs;\n                v_cnt[e.i][e.j] += 1;\n            }\n        }\n\n        // gentle denoising toward empirical means if enough samples\n        for (auto &e : edges) {\n            if (e.horiz) {\n                if (h_cnt[e.i][e.j] >= 3) {\n                    double mean = h_sum[e.i][e.j] / h_cnt[e.i][e.j];\n                    h_est[e.i][e.j] = clamp_cost(0.9 * h_est[e.i][e.j] + 0.1 * mean);\n                }\n            } else {\n                if (v_cnt[e.i][e.j] >= 3) {\n                    double mean = v_sum[e.i][e.j] / v_cnt[e.i][e.j];\n                    v_est[e.i][e.j] = clamp_cost(0.9 * v_est[e.i][e.j] + 0.1 * mean);\n                }\n            }\n        }\n\n        // rebuild segmented priors every turn; cheap enough\n        rebuild_priors();\n\n        // global smoothing toward prior\n        double smooth = (turn < 150 ? 0.06 : 0.03);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = clamp_cost((1.0 - smooth) * h_est[i][j] + smooth * h_prior[i][j]);\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = clamp_cost((1.0 - smooth) * v_est[i][j] + smooth * v_prior[i][j]);\n            }\n        }\n    }\n\n    void solve() {\n        rebuild_priors();\n\n        for (turn = 0; turn < 1000; turn++) {\n            int si, sj, ti, tj;\n            cin >> si >> sj >> ti >> tj;\n\n            auto [path, edges] = shortest_path(si, sj, ti, tj);\n            cout << path << '\\n';\n            cout.flush();\n\n            int observed;\n            cin >> observed;\n\n            update_from_feedback(edges, observed);\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}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\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 rand01() {\n        return (next() >> 11) * (1.0 / (1ull << 53));\n    }\n} rng;\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 Pattern {\n    string s;\n    int w;\n};\n\nstruct Candidate {\n    string line;               // length 20\n    vector<uint64_t> bits;     // covered unique patterns\n    int coverWeight = 0;       // sum of weights of covered unique patterns\n};\n\nint Nin, M;\nvector<Pattern> pats;\nint P;\n\ninline int cid(char c) { return c - 'A'; }\n\nbool contains_cyclic_line(const string& line, const string& s) {\n    int L = (int)s.size();\n    for (int st = 0; st < N; st++) {\n        bool ok = true;\n        for (int k = 0; k < L; k++) {\n            if (line[(st + k) % N] != s[k]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n    return false;\n}\n\nstring minimal_rotation(string s) {\n    // Booth O(n^2) is fine for n=20, but implement simple O(n^2)\n    string best = s;\n    for (int i = 1; i < (int)s.size(); i++) {\n        string t = s.substr(i) + s.substr(0, i);\n        if (t < best) best = t;\n    }\n    return best;\n}\n\nint overlap_suffix_prefix(const string& a, const string& b) {\n    int mx = min((int)a.size(), (int)b.size());\n    for (int k = mx; k >= 1; k--) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[(int)a.size() - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nbool is_substring_noncyclic(const string& a, const string& b) {\n    // is a substring of b\n    return b.find(a) != string::npos;\n}\n\nstring fill_to_20(const string& base, const vector<Pattern>& pats, bool randomize) {\n    if ((int)base.size() >= N) return base.substr(0, N);\n    string s = base;\n    while ((int)s.size() < N) {\n        array<long long, 8> score{};\n        score.fill(1);\n        int pos = (int)s.size();\n        for (auto &p : pats) {\n            const string& t = p.s;\n            for (int st = max(0, pos - (int)t.size() + 1); st <= pos; st++) {\n                int k = pos - st;\n                if (st < 0 || k < 0 || k >= (int)t.size()) continue;\n                bool ok = true;\n                for (int i = 0; i < pos - st; i++) {\n                    if (st + i < (int)s.size() && s[st + i] != t[i]) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) score[cid(t[k])] += p.w;\n            }\n        }\n        int bestc = 0;\n        if (randomize && rng.rand01() < 0.25) {\n            long long sum = 0;\n            for (int c = 0; c < 8; c++) sum += score[c];\n            long long r = rng.next() % sum;\n            long long acc = 0;\n            for (int c = 0; c < 8; c++) {\n                acc += score[c];\n                if (r < acc) { bestc = c; break; }\n            }\n        } else {\n            for (int c = 1; c < 8; c++) if (score[c] > score[bestc]) bestc = c;\n        }\n        s.push_back(char('A' + bestc));\n    }\n    return s;\n}\n\nCandidate make_candidate(const string& line) {\n    Candidate c;\n    c.line = minimal_rotation(line);\n    c.bits.assign((P + 63) >> 6, 0ULL);\n    int sw = 0;\n    for (int i = 0; i < P; i++) {\n        if (contains_cyclic_line(c.line, pats[i].s)) {\n            c.bits[i >> 6] |= 1ULL << (i & 63);\n            sw += pats[i].w;\n        }\n    }\n    c.coverWeight = sw;\n    return c;\n}\n\nvector<Candidate> generate_candidates(double time_limit) {\n    Timer timer;\n    vector<Candidate> cands;\n    unordered_set<string> seen;\n    seen.reserve(4096);\n\n    auto add_candidate = [&](const string& raw) {\n        string line = minimal_rotation(raw.substr(0, N));\n        if (seen.insert(line).second) {\n            cands.push_back(make_candidate(line));\n        }\n    };\n\n    // sort patterns by value\n    vector<int> ord(P);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        long long va = 1LL * pats[a].w * (int)pats[a].s.size() * (int)pats[a].s.size();\n        long long vb = 1LL * pats[b].w * (int)pats[b].s.size() * (int)pats[b].s.size();\n        if (va != vb) return va > vb;\n        return pats[a].s.size() > pats[b].s.size();\n    });\n\n    // deterministic top seeds\n    int topSeeds = min(P, 120);\n    for (int si = 0; si < topSeeds; si++) {\n        string cur = pats[ord[si]].s;\n        vector<int> used(P, 0);\n        used[ord[si]] = 1;\n\n        while ((int)cur.size() < N) {\n            long long bestScore = -1;\n            int bestj = -1;\n            bool bestAppend = true;\n            int bestOv = 0;\n\n            for (int t = 0; t < min(P, 200); t++) {\n                int j = ord[t];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = true;\n                        bestOv = ov1;\n                    }\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = false;\n                        bestOv = ov2;\n                    }\n                }\n            }\n\n            if (bestj == -1) break;\n            used[bestj] = 1;\n            const string& s = pats[bestj].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (bestAppend) cur += s.substr(bestOv);\n            else cur = s + cur.substr(bestOv);\n        }\n        add_candidate(fill_to_20(cur, pats, false));\n    }\n\n    // randomized builds\n    while (timer.elapsed() < time_limit) {\n        int seed = ord[rng.randint(0, min(P, 80) - 1)];\n        string cur = pats[seed].s;\n        vector<int> used(P, 0);\n        used[seed] = 1;\n\n        int steps = rng.randint(8, 20);\n        for (int step = 0; step < steps && (int)cur.size() < N; step++) {\n            vector<pair<long long, tuple<int,bool,int>>> opts;\n            int pool = min(P, 180);\n            for (int it = 0; it < pool; it++) {\n                int j = ord[it];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, true, ov1}});\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, false, ov2}});\n                }\n            }\n            if (opts.empty()) break;\n            nth_element(opts.begin(),\n                        opts.begin() + min<int>(opts.size(), 5) - 1,\n                        opts.end(),\n                        [&](auto& a, auto& b){ return a.first > b.first; });\n            int pick = rng.randint(0, min<int>(opts.size(), 5) - 1);\n            auto [sc, tup] = opts[pick];\n            auto [j, app, ov] = tup;\n            used[j] = 1;\n            const string& s = pats[j].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (app) cur += s.substr(ov);\n            else cur = s + cur.substr(ov);\n        }\n        add_candidate(fill_to_20(cur, pats, true));\n    }\n\n    // single-pattern direct cyclic fills\n    for (int i = 0; i < min(P, 100); i++) {\n        add_candidate(fill_to_20(pats[ord[i]].s, pats, true));\n    }\n\n    return cands;\n}\n\nint total_weight_from_count(const vector<int>& cnt) {\n    int s = 0;\n    for (int i = 0; i < P; i++) if (cnt[i] > 0) s += pats[i].w;\n    return s;\n}\n\nvector<int> greedy_select_rows(const vector<Candidate>& cands) {\n    int C = (int)cands.size();\n    vector<int> selected;\n    vector<int> cnt(P, 0);\n    vector<char> used(C, 0);\n\n    for (int iter = 0; iter < N; iter++) {\n        int best = -1;\n        long long bestGain = -1;\n\n        for (int i = 0; i < C; i++) if (!used[i]) {\n            long long gain = 0;\n            for (int p = 0; p < P; p++) {\n                if (cnt[p] == 0) {\n                    if ((cands[i].bits[p >> 6] >> (p & 63)) & 1ULL) gain += pats[p].w;\n                }\n            }\n            // slight diversity bonus\n            gain += cands[i].coverWeight / 50;\n            if (gain > bestGain) {\n                bestGain = gain;\n                best = i;\n            }\n        }\n\n        if (best == -1) best = 0;\n        used[best] = 1;\n        selected.push_back(best);\n        for (int p = 0; p < P; p++) {\n            if ((cands[best].bits[p >> 6] >> (p & 63)) & 1ULL) cnt[p]++;\n        }\n    }\n    return selected;\n}\n\nint evaluate_grid(const vector<string>& g) {\n    vector<string> cols(N, string(N, 'A'));\n    for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) cols[j][i] = g[i][j];\n\n    int score = 0;\n    for (int p = 0; p < P; p++) {\n        bool ok = false;\n        for (int i = 0; i < N && !ok; i++) if (contains_cyclic_line(g[i], pats[p].s)) ok = true;\n        for (int j = 0; j < N && !ok; j++) if (contains_cyclic_line(cols[j], pats[p].s)) ok = true;\n        if (ok) score += pats[p].w;\n    }\n    return score;\n}\n\nvector<string> rows_from_selection(const vector<Candidate>& cands, const vector<int>& sel) {\n    vector<string> g(N);\n    for (int i = 0; i < N; i++) g[i] = cands[sel[i]].line;\n    return g;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> Nin >> M;\n    vector<string> input(M);\n    for (int i = 0; i < M; i++) cin >> input[i];\n\n    unordered_map<string, int> mp;\n    mp.reserve(M * 2);\n    for (auto &s : input) mp[s]++;\n\n    pats.clear();\n    pats.reserve(mp.size());\n    for (auto &kv : mp) pats.push_back({kv.first, kv.second});\n    P = (int)pats.size();\n\n    sort(pats.begin(), pats.end(), [&](const Pattern& a, const Pattern& b) {\n        long long va = 1LL * a.w * (int)a.s.size() * (int)a.s.size();\n        long long vb = 1LL * b.w * (int)b.s.size() * (int)b.s.size();\n        if (va != vb) return va > vb;\n        if (a.s.size() != b.s.size()) return a.s.size() > b.s.size();\n        return a.s < b.s;\n    });\n\n    Timer allTimer;\n\n    // Phase 1: generate candidate lines\n    auto cands = generate_candidates(0.9);\n    if (cands.empty()) {\n        string s(N, 'A');\n        for (int i = 0; i < N; i++) cout << s << '\\n';\n        return 0;\n    }\n\n    // Phase 2: select 20 rows greedily\n    auto sel = greedy_select_rows(cands);\n    vector<string> bestGrid = rows_from_selection(cands, sel);\n    int bestScore = evaluate_grid(bestGrid);\n\n    // Phase 3: row replacement local improvement\n    {\n        vector<int> curSel = sel;\n        vector<string> curGrid = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 1.6) {\n            int pos = rng.randint(0, N - 1);\n            int candId = rng.randint(0, (int)cands.size() - 1);\n\n            int old = curSel[pos];\n            if (old == candId) continue;\n            curSel[pos] = candId;\n            curGrid[pos] = cands[candId].line;\n\n            int sc = evaluate_grid(curGrid);\n            if (sc >= curScore || rng.rand01() < 0.01) {\n                curScore = sc;\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestGrid = curGrid;\n                }\n            } else {\n                curSel[pos] = old;\n                curGrid[pos] = cands[old].line;\n            }\n        }\n    }\n\n    // Phase 4: cell-wise hill climbing\n    {\n        vector<string> cur = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 2.95) {\n            int i = rng.randint(0, N - 1);\n            int j = rng.randint(0, N - 1);\n            char oldc = cur[i][j];\n\n            char bestc = oldc;\n            int localBest = curScore;\n\n            array<int, 8> perm{};\n            iota(perm.begin(), perm.end(), 0);\n            shuffle(perm.begin(), perm.end(), std::mt19937((uint32_t)rng.next()));\n\n            int tries = 4;\n            for (int t = 0; t < tries; t++) {\n                char nc = char('A' + perm[t]);\n                if (nc == oldc) continue;\n                cur[i][j] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc > localBest || (sc == localBest && rng.rand01() < 0.05)) {\n                    localBest = sc;\n                    bestc = nc;\n                }\n            }\n\n            cur[i][j] = bestc;\n            curScore = localBest;\n\n            if (curScore > bestScore) {\n                bestScore = curScore;\n                bestGrid = cur;\n            }\n\n            // rare random kick\n            if (rng.rand01() < 0.01) {\n                int x = rng.randint(0, N - 1), y = rng.randint(0, N - 1);\n                char nc = char('A' + rng.randint(0, 7));\n                char bak = cur[x][y];\n                cur[x][y] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc >= curScore || rng.rand01() < 0.2) {\n                    curScore = sc;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestGrid = cur;\n                    }\n                } else {\n                    cur[x][y] = bak;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << bestGrid[i] << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int INF = 1e9;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\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    vector<string> C(N);\n    for (int i = 0; i < N; i++) cin >> C[i];\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n    auto road = [&](int x, int y) -> bool {\n        return inb(x, y) && C[x][y] != '#';\n    };\n    auto w = [&](int x, int y) -> int {\n        return C[x][y] - '0';\n    };\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n\n    vector<Pos> roads;\n    vector<vector<int>> rid(N, vector<int>(N, -1));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (road(i, j)) {\n            rid[i][j] = (int)roads.size();\n            roads.push_back({i, j});\n        }\n    }\n    int R = (int)roads.size();\n\n    vector<vector<int>> deg(N, vector<int>(N, 0));\n    for (auto &p : roads) {\n        int d = 0;\n        for (int k = 0; k < 4; k++) if (road(p.x + dx[k], p.y + dy[k])) d++;\n        deg[p.x][p.y] = d;\n    }\n\n    auto is_corner = [&](int x, int y) -> bool {\n        if (!road(x, y) || deg[x][y] != 2) return false;\n        bool ud = road(x - 1, y) && road(x + 1, y);\n        bool lr = road(x, y - 1) && road(x, y + 1);\n        return !(ud || lr);\n    };\n    auto is_important = [&](int x, int y) -> bool {\n        if (x == si && y == sj) return true;\n        if (deg[x][y] != 2) return true;\n        return is_corner(x, y);\n    };\n\n    vector<Pos> cand;\n    vector<vector<int>> cid(N, vector<int>(N, -1));\n\n    auto add_candidate = [&](int x, int y) {\n        if (!road(x, y)) return;\n        if (cid[x][y] != -1) return;\n        cid[x][y] = (int)cand.size();\n        cand.push_back({x, y});\n    };\n\n    for (auto &p : roads) if (is_important(p.x, p.y)) add_candidate(p.x, p.y);\n\n    // sample corridor cells\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (!road(i, j)) { j++; continue; }\n            int k = j;\n            while (k < N && road(i, k)) k++;\n            int len = k - j;\n            if (len >= 6) {\n                for (int y = j + 2; y <= k - 3; y += 3) {\n                    if (deg[i][y] == 2 && !is_corner(i, y)) add_candidate(i, y);\n                }\n            }\n            j = k;\n        }\n    }\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (!road(i, j)) { i++; continue; }\n            int k = i;\n            while (k < N && road(k, j)) k++;\n            int len = k - i;\n            if (len >= 6) {\n                for (int x = i + 2; x <= k - 3; x += 3) {\n                    if (deg[x][j] == 2 && !is_corner(x, j)) add_candidate(x, j);\n                }\n            }\n            i = k;\n        }\n    }\n\n    add_candidate(si, sj);\n    int M = (int)cand.size();\n    int start = cid[si][sj];\n\n    // visible cells for each candidate\n    vector<vector<int>> visible(M);\n    for (int id = 0; id < M; id++) {\n        auto [x, y] = cand[id];\n        vector<int> tmp;\n        tmp.push_back(rid[x][y]);\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x, ny = y;\n            while (true) {\n                nx += dx[dir];\n                ny += dy[dir];\n                if (!road(nx, ny)) break;\n                tmp.push_back(rid[nx][ny]);\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());\n        visible[id] = move(tmp);\n    }\n\n    // Useful candidate order helpers\n    vector<int> baseDist(M);\n    for (int i = 0; i < M; i++) {\n        baseDist[i] = abs(cand[i].x - si) + abs(cand[i].y - sj);\n    }\n\n    auto full_cover = [&](const vector<int>& tar) -> bool {\n        vector<char> cov(R, 0);\n        for (int id : tar) {\n            for (int r : visible[id]) cov[r] = 1;\n        }\n        for (int i = 0; i < R; i++) if (!cov[i]) return false;\n        return true;\n    };\n\n    XorShift rng;\n    vector<int> bestTargets;\n    int bestTargetCount = INF;\n\n    // multi-start randomized greedy cover\n    int TRIALS = 20;\n    for (int trial = 0; trial < TRIALS; trial++) {\n        vector<char> cov(R, 0), chosen(M, 0);\n        int covCnt = 0;\n        vector<int> tar;\n        tar.push_back(start);\n        chosen[start] = 1;\n        for (int r : visible[start]) if (!cov[r]) cov[r] = 1, covCnt++;\n\n        double alpha = 1.5 + 2.0 * rng.next_double();\n\n        while (covCnt < R) {\n            int best = -1;\n            double bestScore = -1e100;\n\n            // sample all candidates, randomized score\n            for (int id = 0; id < M; id++) {\n                if (chosen[id]) continue;\n                int gain = 0;\n                for (int r : visible[id]) gain += !cov[r];\n                if (gain == 0) continue;\n\n                double score = gain * 1000.0 - alpha * baseDist[id];\n                score += rng.next_double() * 200.0;\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = id;\n                }\n            }\n\n            if (best == -1) break;\n            chosen[best] = 1;\n            tar.push_back(best);\n            for (int r : visible[best]) if (!cov[r]) cov[r] = 1, covCnt++;\n        }\n\n        // redundancy pruning\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = 0; i < (int)tar.size(); i++) {\n                if (tar[i] == start) continue;\n                vector<int> nxt;\n                nxt.reserve(tar.size() - 1);\n                for (int j = 0; j < (int)tar.size(); j++) if (j != i) nxt.push_back(tar[j]);\n                if (full_cover(nxt)) {\n                    tar.swap(nxt);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n\n        if ((int)tar.size() < bestTargetCount) {\n            bestTargetCount = (int)tar.size();\n            bestTargets = tar;\n        }\n    }\n\n    vector<int> targets = bestTargets;\n    sort(targets.begin(), targets.end());\n    targets.erase(unique(targets.begin(), targets.end()), targets.end());\n    int T = (int)targets.size();\n\n    vector<int> idxOfCand(M, -1);\n    for (int i = 0; i < T; i++) idxOfCand[targets[i]] = i;\n    int sidx = idxOfCand[start];\n\n    int NN = N * N;\n    auto vid = [&](int x, int y) { return x * N + y; };\n\n    // Dijkstra from each target\n    vector<vector<int>> distT(T, vector<int>(NN, INF));\n    vector<vector<int>> parentT(T, vector<int>(NN, -1));\n\n    for (int ti = 0; ti < T; ti++) {\n        auto [sx, sy] = cand[targets[ti]];\n        int s = vid(sx, sy);\n        priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n        distT[ti][s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != distT[ti][v]) continue;\n            int x = v / N, y = v % N;\n            for (int k = 0; k < 4; k++) {\n                int nx = x + dx[k], ny = y + dy[k];\n                if (!road(nx, ny)) continue;\n                int nv = vid(nx, ny);\n                int nd = cd + w(nx, ny);\n                if (nd < distT[ti][nv]) {\n                    distT[ti][nv] = nd;\n                    parentT[ti][nv] = v;\n                    pq.push({nd, nv});\n                }\n            }\n        }\n    }\n\n    vector<vector<int>> d(T, vector<int>(T, INF));\n    for (int i = 0; i < T; i++) {\n        for (int j = 0; j < T; j++) {\n            auto [x, y] = cand[targets[j]];\n            d[i][j] = distT[i][vid(x, y)];\n        }\n    }\n\n    auto build_tour = [&](int mode) {\n        vector<int> others;\n        for (int i = 0; i < T; i++) if (i != sidx) others.push_back(i);\n\n        vector<int> tour;\n        if (others.empty()) {\n            return vector<int>{sidx, sidx};\n        }\n\n        int first = others[0];\n        if (mode == 0) {\n            int best = INF;\n            for (int x : others) {\n                int val = d[sidx][x] + d[x][sidx];\n                if (val < best) best = val, first = x;\n            }\n        } else {\n            first = others[rng.next_int(0, (int)others.size() - 1)];\n        }\n\n        tour = {sidx, first, sidx};\n        vector<char> used(T, 0);\n        used[sidx] = 1;\n        used[first] = 1;\n\n        while (true) {\n            int bestx = -1, bestpos = -1;\n            long long bestinc = (1LL << 60);\n            bool found = false;\n\n            for (int x : others) if (!used[x]) {\n                for (int i = 0; i + 1 < (int)tour.size(); i++) {\n                    int a = tour[i], b = tour[i + 1];\n                    long long inc = (long long)d[a][x] + d[x][b] - d[a][b];\n                    if (mode == 1) inc += rng.next_int(0, 20);\n                    if (inc < bestinc) {\n                        bestinc = inc;\n                        bestx = x;\n                        bestpos = i + 1;\n                        found = true;\n                    }\n                }\n            }\n            if (!found) break;\n            used[bestx] = 1;\n            tour.insert(tour.begin() + bestpos, bestx);\n        }\n        return tour;\n    };\n\n    auto tour_cost = [&](const vector<int>& tr) -> long long {\n        long long res = 0;\n        for (int i = 0; i + 1 < (int)tr.size(); i++) res += d[tr[i]][tr[i + 1]];\n        return res;\n    };\n\n    auto improve_tour = [&](vector<int>& tour) {\n        bool improved = true;\n        int rounds = 0;\n        while (improved && rounds < 8) {\n            improved = false;\n            rounds++;\n\n            // 2-opt\n            for (int i = 1; i + 2 < (int)tour.size(); i++) {\n                for (int j = i + 1; j + 1 < (int)tour.size(); j++) {\n                    int a = tour[i - 1], b = tour[i];\n                    int c = tour[j], e = tour[j + 1];\n                    long long before = (long long)d[a][b] + d[c][e];\n                    long long after  = (long long)d[a][c] + d[b][e];\n                    if (after < before) {\n                        reverse(tour.begin() + i, tour.begin() + j + 1);\n                        improved = true;\n                    }\n                }\n            }\n\n            // relocate\n            for (int i = 1; i + 1 < (int)tour.size(); i++) {\n                int x = tour[i];\n                long long rem = (long long)d[tour[i - 1]][x] + d[x][tour[i + 1]] - d[tour[i - 1]][tour[i + 1]];\n                int bestPos = -1;\n                long long bestDelta = 0;\n                for (int j = 0; j + 1 < (int)tour.size(); j++) {\n                    if (j == i || j + 1 == i) continue;\n                    long long add = (long long)d[tour[j]][x] + d[x][tour[j + 1]] - d[tour[j]][tour[j + 1]];\n                    long long delta = add - rem;\n                    if (delta < bestDelta) {\n                        bestDelta = delta;\n                        bestPos = j;\n                    }\n                }\n                if (bestPos != -1) {\n                    vector<int> nt = tour;\n                    nt.erase(nt.begin() + i);\n                    int ins = bestPos + 1;\n                    if (bestPos >= i) ins--;\n                    nt.insert(nt.begin() + ins, x);\n                    tour.swap(nt);\n                    improved = true;\n                    break;\n                }\n            }\n\n            // swap\n            for (int i = 1; i + 1 < (int)tour.size() && !improved; i++) {\n                for (int j = i + 1; j + 1 < (int)tour.size(); j++) {\n                    vector<int> nt = tour;\n                    swap(nt[i], nt[j]);\n                    if (tour_cost(nt) < tour_cost(tour)) {\n                        tour.swap(nt);\n                        improved = true;\n                        break;\n                    }\n                }\n            }\n        }\n    };\n\n    vector<int> bestTour;\n    long long bestTourCost = (1LL << 60);\n\n    for (int mode = 0; mode < 6; mode++) {\n        vector<int> tr = build_tour(mode % 2);\n        improve_tour(tr);\n        long long cst = tour_cost(tr);\n        if (cst < bestTourCost) {\n            bestTourCost = cst;\n            bestTour = tr;\n        }\n    }\n\n    // Route-aware target deletion\n    auto covered_by_target_indices = [&](const vector<int>& tarIdx) -> bool {\n        vector<char> cov(R, 0);\n        for (int ti : tarIdx) {\n            int cid0 = targets[ti];\n            for (int r : visible[cid0]) cov[r] = 1;\n        }\n        for (int i = 0; i < R; i++) if (!cov[i]) return false;\n        return true;\n    };\n\n    {\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            for (int i = 1; i + 1 < (int)bestTour.size(); i++) {\n                int x = bestTour[i];\n                if (x == sidx) continue;\n                vector<int> ntour;\n                for (int j = 0; j < (int)bestTour.size(); j++) if (j != i) ntour.push_back(bestTour[j]);\n\n                vector<int> uniqNodes = ntour;\n                sort(uniqNodes.begin(), uniqNodes.end());\n                uniqNodes.erase(unique(uniqNodes.begin(), uniqNodes.end()), uniqNodes.end());\n\n                if (!covered_by_target_indices(uniqNodes)) continue;\n\n                long long oldc = tour_cost(bestTour);\n                long long newc = tour_cost(ntour);\n                if (newc < oldc) {\n                    bestTour.swap(ntour);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n    }\n\n    auto restore_path = [&](int fromIdx, int toIdx) -> vector<Pos> {\n        auto [tx, ty] = cand[targets[toIdx]];\n        int cur = vid(tx, ty);\n        int s = vid(cand[targets[fromIdx]].x, cand[targets[fromIdx]].y);\n        vector<int> rev;\n        while (cur != s) {\n            rev.push_back(cur);\n            cur = parentT[fromIdx][cur];\n            if (cur == -1) return {};\n        }\n        reverse(rev.begin(), rev.end());\n        vector<Pos> path;\n        for (int v : rev) path.push_back({v / N, v % N});\n        return path;\n    };\n\n    string ans;\n    int cx = si, cy = sj;\n    auto emit_step = [&](int nx, int ny) {\n        if (nx == cx - 1 && ny == cy) ans.push_back('U');\n        else if (nx == cx + 1 && ny == cy) ans.push_back('D');\n        else if (nx == cx && ny == cy - 1) ans.push_back('L');\n        else if (nx == cx && ny == cy + 1) ans.push_back('R');\n        cx = nx;\n        cy = ny;\n    };\n\n    for (int i = 0; i + 1 < (int)bestTour.size(); i++) {\n        auto path = restore_path(bestTour[i], bestTour[i + 1]);\n        for (auto &p : path) emit_step(p.x, p.y);\n    }\n\n    // Validate\n    {\n        int x = si, y = sj;\n        bool ok = true;\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n            else ok = false;\n            if (!inb(x, y) || !road(x, y)) ok = false;\n        }\n        if (x != si || y != sj) ok = false;\n        if (!ok) ans.clear();\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskInfo {\n    vector<int> d;\n    int diff_sum = 0;\n    int priority = 1; // longest path to sink\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<TaskInfo> tasks(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].d.resize(K);\n        int s = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n            s += tasks[i].d[k];\n        }\n        tasks[i].diff_sum = s;\n    }\n\n    vector<vector<int>> out(N), in(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        in[v].push_back(u);\n    }\n\n    // Static priority = longest path to sink\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int to : out[i]) best = max(best, tasks[to].priority);\n        tasks[i].priority = best + 1;\n    }\n\n    // State\n    // task_state: 0 not started, 1 in progress, 2 done\n    vector<int> task_state(N, 0);\n    vector<int> rem_pre(N);\n    for (int i = 0; i < N; ++i) rem_pre[i] = (int)in[i].size();\n\n    vector<int> member_task(M, -1);\n    vector<int> member_start(M, -1);\n\n    // Skill estimates\n    vector<vector<double>> est(M, vector<double>(K, 20.0));\n    vector<int> obs_cnt(M, 0);\n\n    // For updates when a member finishes a task\n    auto predicted_deficit = [&](int task_id, int member_id) -> double {\n        double w = 0.0;\n        const auto &d = tasks[task_id].d;\n        const auto &s = est[member_id];\n        for (int k = 0; k < K; ++k) {\n            if (d[k] > s[k]) w += d[k] - s[k];\n        }\n        return w;\n    };\n\n    auto predicted_time = [&](int task_id, int member_id) -> double {\n        return max(1.0, predicted_deficit(task_id, member_id));\n    };\n\n    auto update_estimate = [&](int member_id, int task_id, int duration) {\n        // target deficit estimate\n        // conservative estimate due to noise and lower bound at 1\n        double target = (duration <= 1 ? 0.0 : (double)duration - 1.0);\n\n        const auto &d = tasks[task_id].d;\n        auto &s = est[member_id];\n\n        for (int iter = 0; iter < 3; ++iter) {\n            double pred = 0.0;\n            for (int k = 0; k < K; ++k) {\n                if (d[k] > s[k]) pred += d[k] - s[k];\n            }\n            double diff = target - pred; // positive => skills too high, negative => too low\n\n            double lr = 0.45 / (1.0 + 0.08 * obs_cnt[member_id]);\n            if (fabs(diff) < 0.5) break;\n\n            if (diff < 0) {\n                // Predicted deficit too large => estimated skills too low => increase skills\n                // Focus on dimensions where d[k] > s[k]\n                double total_gap = 0.0;\n                for (int k = 0; k < K; ++k) total_gap += max(0.0, (double)d[k] - s[k]);\n                if (total_gap < 1e-9) total_gap = 1.0;\n                double need = -diff * lr;\n                for (int k = 0; k < K; ++k) {\n                    double gap = max(0.0, (double)d[k] - s[k]);\n                    if (gap <= 0) continue;\n                    s[k] += need * (gap / total_gap);\n                    if (s[k] > 80.0) s[k] = 80.0;\n                }\n            } else {\n                // Predicted deficit too small => estimated skills too high => decrease a bit\n                // Decrease dimensions relevant to this task.\n                double total_rel = 0.0;\n                for (int k = 0; k < K; ++k) total_rel += d[k] + 1.0;\n                double need = diff * lr * 0.6;\n                for (int k = 0; k < K; ++k) {\n                    double dec = need * ((d[k] + 1.0) / total_rel);\n                    s[k] -= dec;\n                    if (s[k] < 0.0) s[k] = 0.0;\n                }\n            }\n        }\n\n        obs_cnt[member_id]++;\n    };\n\n    int day = 0;\n    int completed_tasks = 0;\n\n    while (true) {\n        day++;\n\n        // Ready tasks\n        vector<int> ready;\n        ready.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 0 && rem_pre[i] == 0) ready.push_back(i);\n        }\n\n        // Sort ready tasks by importance\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (tasks[a].priority != tasks[b].priority) return tasks[a].priority > tasks[b].priority;\n            if (tasks[a].diff_sum != tasks[b].diff_sum) return tasks[a].diff_sum > tasks[b].diff_sum;\n            return a < b;\n        });\n\n        // Candidate truncation\n        const int LIMIT = 180;\n        if ((int)ready.size() > LIMIT) ready.resize(LIMIT);\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) if (member_task[j] == -1) free_members.push_back(j);\n\n        vector<pair<int,int>> assignments;\n        vector<char> used_task(N, 0), used_member(M, 0);\n\n        // Greedy global pair selection\n        while (true) {\n            double bestScore = -1e100;\n            int bestMem = -1, bestTask = -1;\n\n            for (int j : free_members) {\n                if (used_member[j]) continue;\n                for (int t : ready) {\n                    if (used_task[t]) continue;\n\n                    double pt = predicted_time(t, j);\n                    // Exploration: lightly favor less-observed members early\n                    double explore = (obs_cnt[j] < 5 ? (5 - obs_cnt[j]) * 3.0 : 0.0);\n\n                    // Strong emphasis on precedence-critical tasks\n                    double score =\n                        1000.0 * tasks[t].priority\n                        + 2.0 * tasks[t].diff_sum\n                        - 25.0 * pt\n                        + explore;\n\n                    // Mild bonus for assigning very hard tasks to seemingly strong members\n                    if (obs_cnt[j] >= 3) {\n                        double strength = 0.0;\n                        for (int k = 0; k < K; ++k) strength += est[j][k];\n                        score += 0.02 * strength;\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestMem = j;\n                        bestTask = t;\n                    }\n                }\n            }\n\n            if (bestMem == -1) break;\n\n            used_member[bestMem] = 1;\n            used_task[bestTask] = 1;\n            assignments.push_back({bestMem, bestTask});\n\n            task_state[bestTask] = 1;\n            member_task[bestMem] = bestTask;\n            member_start[bestMem] = day;\n        }\n\n        // Output today's assignments\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << (mem + 1) << ' ' << (task + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        // Optional visualization comments of estimated skills\n        // Keep disabled in judge for speed/noise. Uncomment if desired.\n        /*\n        for (int j = 0; j < M; ++j) {\n            cout << \"#s \" << (j + 1);\n            for (int k = 0; k < K; ++k) cout << ' ' << (int)round(est[j][k]);\n            cout << '\\n';\n        }\n        cout.flush();\n        */\n\n        string first;\n        if (!(cin >> first)) return 0;\n        if (first == \"-1\") {\n            return 0;\n        }\n\n        int n = stoi(first);\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int mem : finished) {\n            int task = member_task[mem];\n            if (task == -1) continue; // safety\n\n            int duration = day - member_start[mem] + 1;\n            update_estimate(mem, task, duration);\n\n            task_state[task] = 2;\n            completed_tasks++;\n\n            member_task[mem] = -1;\n            member_start[mem] = -1;\n\n            for (int to : out[task]) {\n                rem_pre[to]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 1000;\nstatic constexpr int M = 50;\nstatic constexpr int DEPOT_X = 400;\nstatic constexpr int DEPOT_Y = 400;\n\nstruct Order {\n    int a, b, c, d;\n    int id; // 1-indexed for output\n};\n\nstruct Pt {\n    int x, y;\n};\n\nstatic inline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\nstatic inline int mdist(const Pt& p, const Pt& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstruct Solver {\n    vector<Order> ord;\n    mt19937 rng;\n\n    Solver() : ord(N) {\n        rng.seed((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    }\n\n    double elapsed_ms(chrono::steady_clock::time_point st) {\n        return chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now() - st).count() / 1000.0;\n    }\n\n    Pt rest_pt(int idx) const { return {ord[idx].a, ord[idx].b}; }\n    Pt dest_pt(int idx) const { return {ord[idx].c, ord[idx].d}; }\n\n    int route_cost(const vector<int>& sel, const vector<int>& pord, const vector<int>& dord) const {\n        Pt cur{DEPOT_X, DEPOT_Y};\n        int cost = 0;\n        for (int pos : pord) {\n            Pt nxt = rest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        for (int pos : dord) {\n            Pt nxt = dest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        cost += mdist(cur, Pt{DEPOT_X, DEPOT_Y});\n        return cost;\n    }\n\n    vector<int> nearest_order_restaurant(const vector<int>& sel) const {\n        vector<int> rem(M);\n        iota(rem.begin(), rem.end(), 0);\n        vector<int> res;\n        res.reserve(M);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        vector<char> used(M, false);\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = 1e9;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                Pt p = rest_pt(sel[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(best);\n            cur = rest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    vector<int> nearest_order_destination_from(const vector<int>& sel, const Pt& start) const {\n        vector<int> res;\n        res.reserve(M);\n        Pt cur = start;\n        vector<char> used(M, false);\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = 1e9;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                Pt p = dest_pt(sel[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(best);\n            cur = dest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    void improve_two_opt_pick(const vector<int>& sel, vector<int>& pord, const vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    auto getP = [&](int idx) -> Pt {\n                        if (idx < 0) return Pt{DEPOT_X, DEPOT_Y};\n                        if (idx >= M) return dest_pt(sel[dord[0]]);\n                        return rest_pt(sel[pord[idx]]);\n                    };\n                    Pt A = getP(l - 1);\n                    Pt B = getP(l);\n                    Pt C = getP(r);\n                    Pt D = getP(r + 1);\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(pord.begin() + l, pord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void improve_two_opt_del(const vector<int>& sel, const vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    auto getD = [&](int idx) -> Pt {\n                        if (idx < 0) return rest_pt(sel[pord.back()]);\n                        if (idx >= M) return Pt{DEPOT_X, DEPOT_Y};\n                        return dest_pt(sel[dord[idx]]);\n                    };\n                    Pt A = getD(l - 1);\n                    Pt B = getD(l);\n                    Pt C = getD(r);\n                    Pt D = getD(r + 1);\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(dord.begin() + l, dord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void improve_swaps(const vector<int>& sel, vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            // pickup swaps\n            for (int i = 0; i < M; ++i) {\n                for (int j = i + 1; j < M; ++j) {\n                    int cur = route_cost(sel, pord, dord);\n                    swap(pord[i], pord[j]);\n                    int nw = route_cost(sel, pord, dord);\n                    if (nw < cur) {\n                        improved = true;\n                    } else {\n                        swap(pord[i], pord[j]);\n                    }\n                }\n            }\n            // delivery swaps\n            for (int i = 0; i < M; ++i) {\n                for (int j = i + 1; j < M; ++j) {\n                    int cur = route_cost(sel, pord, dord);\n                    swap(dord[i], dord[j]);\n                    int nw = route_cost(sel, pord, dord);\n                    if (nw < cur) {\n                        improved = true;\n                    } else {\n                        swap(dord[i], dord[j]);\n                    }\n                }\n            }\n        }\n    }\n\n    pair<vector<int>, pair<vector<int>, vector<int>>> build_initial_from_pool(const vector<int>& pool) {\n        vector<int> sel;\n        sel.reserve(M);\n\n        // Greedy selection on restaurant proximity, with a simple order-level score.\n        vector<char> used(N, false);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        for (int it = 0; it < M; ++it) {\n            int best = -1;\n            int bestScore = 1e9;\n            for (int idx : pool) if (!used[idx]) {\n                const auto& o = ord[idx];\n                int score =\n                    mdist(cur.x, cur.y, o.a, o.b) +\n                    mdist(o.a, o.b, o.c, o.d) / 3 +\n                    mdist(o.c, o.d, DEPOT_X, DEPOT_Y) / 3;\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = idx;\n                }\n            }\n            if (best == -1) break;\n            used[best] = true;\n            sel.push_back(best);\n            cur = rest_pt(best);\n        }\n\n        // if pool smaller somehow, fill from global\n        if ((int)sel.size() < M) {\n            vector<pair<int,int>> all;\n            all.reserve(N);\n            for (int i = 0; i < N; ++i) if (!used[i]) {\n                int base = mdist(ord[i].a, ord[i].b, DEPOT_X, DEPOT_Y)\n                         + mdist(ord[i].a, ord[i].b, ord[i].c, ord[i].d)\n                         + mdist(ord[i].c, ord[i].d, DEPOT_X, DEPOT_Y);\n                all.push_back({base, i});\n            }\n            sort(all.begin(), all.end());\n            for (auto &p : all) {\n                if ((int)sel.size() >= M) break;\n                used[p.second] = true;\n                sel.push_back(p.second);\n            }\n        }\n\n        auto pord = nearest_order_restaurant(sel);\n        Pt lastPick = rest_pt(sel[pord.back()]);\n        auto dord = nearest_order_destination_from(sel, lastPick);\n\n        improve_two_opt_pick(sel, pord, dord);\n        improve_two_opt_del(sel, pord, dord);\n        improve_swaps(sel, pord, dord);\n\n        return {sel, {pord, dord}};\n    }\n\n    void solve() {\n        for (int i = 0; i < N; ++i) {\n            cin >> ord[i].a >> ord[i].b >> ord[i].c >> ord[i].d;\n            ord[i].id = i + 1;\n        }\n\n        auto st = chrono::steady_clock::now();\n\n        vector<pair<int,int>> ranked;\n        ranked.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            int base =\n                mdist(ord[i].a, ord[i].b, DEPOT_X, DEPOT_Y) +\n                mdist(ord[i].a, ord[i].b, ord[i].c, ord[i].d) +\n                mdist(ord[i].c, ord[i].d, DEPOT_X, DEPOT_Y);\n            ranked.push_back({base, i});\n        }\n        sort(ranked.begin(), ranked.end());\n\n        int bestCost = INT_MAX;\n        vector<int> bestSel, bestP, bestD;\n\n        vector<int> poolSizes = {50, 60, 80, 100, 150, 200, 300};\n\n        for (int K : poolSizes) {\n            if (elapsed_ms(st) > 700) break;\n            K = min(K, N);\n            vector<int> pool;\n            pool.reserve(K);\n            for (int i = 0; i < K; ++i) pool.push_back(ranked[i].second);\n\n            auto init = build_initial_from_pool(pool);\n            auto sel = init.first;\n            auto pord = init.second.first;\n            auto dord = init.second.second;\n            int cost = route_cost(sel, pord, dord);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSel = sel;\n                bestP = pord;\n                bestD = dord;\n            }\n        }\n\n        // Improvement by replacement from good candidates / random candidates.\n        vector<int> topPool;\n        {\n            int K = 250;\n            for (int i = 0; i < K; ++i) topPool.push_back(ranked[i].second);\n        }\n\n        auto rebuild_orders = [&](const vector<int>& sel) {\n            auto pord = nearest_order_restaurant(sel);\n            auto dord = nearest_order_destination_from(sel, rest_pt(sel[pord.back()]));\n            improve_two_opt_pick(sel, pord, dord);\n            improve_two_opt_del(sel, pord, dord);\n            improve_swaps(sel, pord, dord);\n            return pair<vector<int>, vector<int>>(pord, dord);\n        };\n\n        while (elapsed_ms(st) < 1900) {\n            vector<int> sel = bestSel;\n\n            vector<char> inSel(N, false);\n            for (int x : sel) inSel[x] = true;\n\n            int outPos = uniform_int_distribution<int>(0, M - 1)(rng);\n            int inIdx;\n            if (uniform_int_distribution<int>(0, 99)(rng) < 80) {\n                inIdx = topPool[uniform_int_distribution<int>(0, (int)topPool.size() - 1)(rng)];\n            } else {\n                inIdx = uniform_int_distribution<int>(0, N - 1)(rng);\n            }\n            if (inSel[inIdx]) continue;\n\n            sel[outPos] = inIdx;\n\n            auto [pord, dord] = rebuild_orders(sel);\n            int cost = route_cost(sel, pord, dord);\n            if (cost < bestCost) {\n                bestCost = cost;\n                bestSel = move(sel);\n                bestP = move(pord);\n                bestD = move(dord);\n            }\n        }\n\n        // Output\n        cout << M;\n        for (int idx : bestSel) cout << ' ' << ord[idx].id;\n        cout << '\\n';\n\n        vector<Pt> route;\n        route.reserve(2 * M + 2);\n        route.push_back({DEPOT_X, DEPOT_Y});\n        for (int pos : bestP) route.push_back(rest_pt(bestSel[pos]));\n        for (int pos : bestD) route.push_back(dest_pt(bestSel[pos]));\n        route.push_back({DEPOT_X, DEPOT_Y});\n\n        cout << route.size();\n        for (auto &p : route) cout << ' ' << p.x << ' ' << p.y;\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}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n) { 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 same(int a, int b) { return find(a) == find(b); }\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, d;\n};\n\nstruct KEdge {\n    int w;\n    int type; // 0=accepted, 1=current, 2=future\n    int u, v;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return type < other.type;\n    }\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return (int)llround(sqrt((double)(dx * dx + dy * dy)));\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next_u32() % (uint32_t)(r - l + 1));\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<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    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v, rounded_dist(x[u], y[u], x[v], y[v])};\n    }\n\n    vector<int> state(M, -1); // -1 undecided, 0 rejected, 1 accepted\n    DSU accepted(N);\n    XorShift rng;\n\n    auto feasible_without_current = [&](int cur) -> bool {\n        DSU dsu(N);\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            } else if (j > cur && state[j] == -1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            }\n        }\n        return dsu.same(edges[cur].u, edges[cur].v);\n    };\n\n    auto deterministic_mst_include = [&](int cur, int lcur) -> bool {\n        vector<KEdge> es;\n        es.reserve(M);\n\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                es.push_back({0, 0, edges[j].u, edges[j].v});\n            } else if (j == cur) {\n                es.push_back({lcur, 1, edges[j].u, edges[j].v});\n            } else if (j > cur && state[j] == -1) {\n                es.push_back({2 * edges[j].d, 2, edges[j].u, edges[j].v});\n            }\n        }\n\n        sort(es.begin(), es.end());\n        DSU dsu(N);\n        for (auto &e : es) {\n            if (dsu.unite(e.u, e.v)) {\n                if (e.type == 1) return true;\n            }\n        }\n        return false;\n    };\n\n    auto sampled_mst_inclusion_count = [&](int cur, int lcur, int samples) -> int {\n        int cnt = 0;\n        vector<KEdge> es;\n        es.reserve(M);\n\n        for (int s = 0; s < samples; s++) {\n            es.clear();\n            for (int j = 0; j < M; j++) {\n                if (state[j] == 1) {\n                    es.push_back({0, 0, edges[j].u, edges[j].v});\n                } else if (j == cur) {\n                    es.push_back({lcur, 1, edges[j].u, edges[j].v});\n                } else if (j > cur && state[j] == -1) {\n                    int d = edges[j].d;\n                    int w = rng.next_int(d, 3 * d);\n                    es.push_back({w, 2, edges[j].u, edges[j].v});\n                }\n            }\n\n            sort(es.begin(), es.end());\n            DSU dsu(N);\n            bool used = false;\n            for (auto &e : es) {\n                if (dsu.unite(e.u, e.v)) {\n                    if (e.type == 1) {\n                        used = true;\n                        break;\n                    }\n                }\n            }\n            if (used) cnt++;\n        }\n        return cnt;\n    };\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n        int ans = 0;\n\n        if (accepted.same(u, v)) {\n            ans = 0;\n        } else if (!feasible_without_current(i)) {\n            ans = 1;\n        } else {\n            bool det_in = deterministic_mst_include(i, l);\n\n            // Revert near the first/best version, then use MC only for borderline cases.\n            if (det_in) {\n                if (l <= 2 * d) {\n                    ans = 1;\n                } else if (l >= (int)(2.35 * d)) {\n                    int c = sampled_mst_inclusion_count(i, l, 5);\n                    ans = (c >= 4 ? 1 : 0);\n                } else {\n                    int c = sampled_mst_inclusion_count(i, l, 3);\n                    ans = (c >= 1 ? 1 : 0);\n                }\n            } else {\n                if (l <= (int)(1.55 * d)) {\n                    int c = sampled_mst_inclusion_count(i, l, 5);\n                    ans = (c >= 3 ? 1 : 0);\n                } else {\n                    ans = 0;\n                }\n            }\n        }\n\n        state[i] = ans;\n        if (ans) accepted.unite(u, v);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int BOARD = 30;\nstatic const int TURNS = 300;\n\nstruct Pet {\n    int x, y, t;\n};\nstruct Human {\n    int x, y;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\nbool wall_[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar MCH[4] = {'U', 'D', 'L', 'R'};\nchar BCH[4] = {'u', 'd', 'l', 'r'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nint move_dir(char c) {\n    for (int d = 0; d < 4; d++) if (MCH[d] == c) return d;\n    return -1;\n}\nint build_dir(char c) {\n    for (int d = 0; d < 4; d++) if (BCH[d] == c) return d;\n    return -1;\n}\n\nbool pet_at[31][31];\nbool human_at[31][31];\n\nbool adj_pet(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && pet_at[nx][ny]) return true;\n    }\n    return false;\n}\n\nbool can_block_startturn(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (pet_at[x][y]) return false;\n    if (human_at[x][y]) return false;\n    if (adj_pet(x, y)) return false;\n    return true;\n}\n\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nstruct Role {\n    // 0 builder, 1 camper\n    int type;\n    int tx, ty;\n};\n\nvector<Role> roles;\nvector<int> builderCols;\n\npair<int,int> bfs_next_step(\n    int sx, int sy, int tx, int ty,\n    const vector<vector<int>>& blocked_future\n) {\n    if (sx == tx && sy == ty) return {sx, sy};\n\n    static int dist[31][31];\n    static pair<int,int> pre[31][31];\n    for (int i = 1; i <= 30; i++) for (int j = 1; j <= 30; j++) {\n        dist[i][j] = -1;\n        pre[i][j] = {-1, -1};\n    }\n\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    dist[sx][sy] = 0;\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (wall_[nx][ny]) continue;\n            if (blocked_future[nx][ny]) continue;\n            if (dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            pre[nx][ny] = {x, y};\n            q.push({nx, ny});\n        }\n    }\n\n    if (dist[tx][ty] == -1) return {sx, sy};\n\n    int cx = tx, cy = ty;\n    while (pre[cx][cy] != make_pair(sx, sy)) {\n        auto p = pre[cx][cy];\n        if (p.first == -1) return {sx, sy};\n        cx = p.first;\n        cy = p.second;\n    }\n    return {cx, cy};\n}\n\nchar move_toward_safe(\n    int id, int tx, int ty,\n    const vector<vector<int>>& blocked_future,\n    const vector<pair<int,int>>& reserved_moves\n) {\n    int sx = humans[id].x, sy = humans[id].y;\n    auto [nx, ny] = bfs_next_step(sx, sy, tx, ty, blocked_future);\n    if (nx != sx || ny != sy) {\n        bool conflict = false;\n        for (int j = 0; j < id; j++) {\n            if (reserved_moves[j] == make_pair(nx, ny)) {\n                conflict = true;\n                break;\n            }\n        }\n        if (!conflict) {\n            for (int d = 0; d < 4; d++) {\n                if (sx + dx[d] == nx && sy + dy[d] == ny) return MCH[d];\n            }\n        }\n    }\n\n    int bestd = 1e9, bestdir = -1;\n    for (int d = 0; d < 4; d++) {\n        int xx = sx + dx[d], yy = sy + dy[d];\n        if (!inside(xx, yy)) continue;\n        if (wall_[xx][yy]) continue;\n        if (blocked_future[xx][yy]) continue;\n        bool used = false;\n        for (int j = 0; j < id; j++) {\n            if (reserved_moves[j] == make_pair(xx, yy)) {\n                used = true;\n                break;\n            }\n        }\n        if (used) continue;\n        int score = manhattan(xx, yy, tx, ty);\n        if (score < bestd) {\n            bestd = score;\n            bestdir = d;\n        }\n    }\n    if (bestdir == -1) return '.';\n    return MCH[bestdir];\n}\n\nint count_pets_in_rows(int r1, int r2) {\n    int c = 0;\n    for (auto &p : pets) if (r1 <= p.x && p.x <= r2) c++;\n    return c;\n}\n\nint count_line_built(int row) {\n    int c = 0;\n    for (int y = 1; y <= 30; y++) if (wall_[row][y]) c++;\n    return c;\n}\n\nint nearest_unbuilt_col(int row, int y) {\n    int bestCol = y, bestDist = 1e9;\n    for (int yy = 1; yy <= 30; yy++) {\n        if (!wall_[row][yy]) {\n            int d = abs(yy - y);\n            if (d < bestDist) {\n                bestDist = d;\n                bestCol = yy;\n            }\n        }\n    }\n    return bestCol;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n    for (int i = 0; i < N; i++) cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; i++) cin >> humans[i].x >> humans[i].y;\n\n    memset(wall_, 0, sizeof(wall_));\n\n    roles.assign(M, {0, 15, 15});\n    builderCols.assign(M, 15);\n\n    // Reserve one camper for diversification.\n    // Choose the human farthest from center among all.\n    int camper = -1;\n    int bestv = -1;\n    for (int i = 0; i < M; i++) {\n        int v = manhattan(humans[i].x, humans[i].y, 15, 15);\n        if (v > bestv) {\n            bestv = v;\n            camper = i;\n        }\n    }\n    if (camper != -1) {\n        vector<pair<int,int>> corners = {{2,2},{2,29},{29,2},{29,29}};\n        pair<int,int> best = corners[0];\n        int bd = 1e9;\n        for (auto c : corners) {\n            int d = manhattan(humans[camper].x, humans[camper].y, c.first, c.second);\n            if (d < bd) {\n                bd = d;\n                best = c;\n            }\n        }\n        roles[camper] = {1, best.first, best.second};\n    }\n\n    // builder target columns: evenly spaced\n    vector<int> builderIds;\n    for (int i = 0; i < M; i++) if (i != camper) builderIds.push_back(i);\n    int B = max(1, (int)builderIds.size());\n    for (int k = 0; k < B; k++) {\n        int id = builderIds[k];\n        int col = 2 + (27 * k) / max(1, B - 1);\n        builderCols[id] = col;\n    }\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        memset(pet_at, 0, sizeof(pet_at));\n        memset(human_at, 0, sizeof(human_at));\n        for (auto &p : pets) pet_at[p.x][p.y] = true;\n        for (auto &h : humans) human_at[h.x][h.y] = true;\n\n        // Dynamic side selection by current pet distribution.\n        int topPets = count_pets_in_rows(1, 15);\n        int bottomPets = count_pets_in_rows(16, 30);\n        bool secureTop = (topPets <= bottomPets);\n\n        // If securing top, humans stand on row 15 and build row 16.\n        // Else, stand on row 16 and build row 15.\n        int standRow = secureTop ? 15 : 16;\n        int barrierRow = secureTop ? 16 : 15;\n\n        string ans(M, '.');\n        vector<vector<int>> blocked_future(31, vector<int>(31, 0));\n        vector<pair<int,int>> reserved_moves(M, {-1, -1});\n\n        int built = count_line_built(barrierRow);\n        bool phaseSeal = (built >= 20 || turn >= 180);\n\n        // Phase 1: builders try to block barrier cells if already aligned.\n        for (int i = 0; i < M; i++) {\n            if (roles[i].type != 0) continue;\n            int x = humans[i].x, y = humans[i].y;\n            if (x != standRow) continue;\n\n            int bd = (barrierRow == x + 1 ? 1 : (barrierRow == x - 1 ? 0 : -1));\n            if (bd == -1) continue;\n\n            // Prefer own target column, otherwise nearest unbuilt.\n            vector<int> candCols;\n            candCols.push_back(builderCols[i]);\n            int nearCol = nearest_unbuilt_col(barrierRow, y);\n            if (nearCol != builderCols[i]) candCols.push_back(nearCol);\n            candCols.push_back(y);\n\n            bool done = false;\n            for (int ty : candCols) {\n                if (ty != y) continue;\n                int bx = x + dx[bd], by = y + dy[bd];\n                if (!inside(bx, by)) continue;\n                if (blocked_future[bx][by]) continue;\n                if (can_block_startturn(bx, by)) {\n                    ans[i] = BCH[bd];\n                    blocked_future[bx][by] = 1;\n                    done = true;\n                    break;\n                }\n            }\n            if (done) continue;\n        }\n\n        // Phase 2: moves\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n\n            int x = humans[i].x, y = humans[i].y;\n\n            if (roles[i].type == 1) {\n                // Camper: go to corner, then try inward blocking.\n                if (manhattan(x, y, roles[i].tx, roles[i].ty) <= 1) {\n                    vector<int> pref;\n                    if (x <= 2) pref.push_back(1);\n                    if (x >= 29) pref.push_back(0);\n                    if (y <= 2) pref.push_back(3);\n                    if (y >= 29) pref.push_back(2);\n\n                    bool done = false;\n                    for (int d : pref) {\n                        int bx = x + dx[d], by = y + dy[d];\n                        if (!inside(bx, by)) continue;\n                        if (blocked_future[bx][by]) continue;\n                        if (can_block_startturn(bx, by)) {\n                            ans[i] = BCH[d];\n                            blocked_future[bx][by] = 1;\n                            done = true;\n                            break;\n                        }\n                    }\n                    if (done) continue;\n                }\n\n                char c = move_toward_safe(i, roles[i].tx, roles[i].ty, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            // builder movement\n            if (x != standRow) {\n                char c = move_toward_safe(i, standRow, y, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            // standing row behavior\n            int targetCol = builderCols[i];\n\n            if (!phaseSeal) {\n                // before line is mostly built: spread to assigned columns / nearest gap\n                if (!wall_[barrierRow][y] && !blocked_future[barrierRow][y]) {\n                    // already at a useful column\n                    ans[i] = '.';\n                    continue;\n                }\n                int gapCol = nearest_unbuilt_col(barrierRow, y);\n                if (abs(gapCol - y) < abs(targetCol - y)) targetCol = gapCol;\n\n                char c = move_toward_safe(i, standRow, targetCol, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n            } else {\n                // after line mostly built: outer humans drift to ends to help sealing\n                int endCol;\n                if (y <= 15) endCol = 1;\n                else endCol = 30;\n\n                // if current column still unbuilt, hold position\n                if (!wall_[barrierRow][y] && !blocked_future[barrierRow][y]) {\n                    ans[i] = '.';\n                    continue;\n                }\n\n                char c = move_toward_safe(i, standRow, endCol, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n            }\n        }\n\n        // Final legality sanitizer\n        {\n            set<pair<int,int>> used;\n            for (int i = 0; i < M; i++) {\n                int md = move_dir(ans[i]);\n                if (md == -1) continue;\n                int nx = humans[i].x + dx[md], ny = humans[i].y + dy[md];\n                bool bad = false;\n                if (!inside(nx, ny)) bad = true;\n                if (!bad && wall_[nx][ny]) bad = true;\n                if (!bad && blocked_future[nx][ny]) bad = true;\n                if (!bad && used.count({nx, ny})) bad = true;\n                if (bad) ans[i] = '.';\n                else used.insert({nx, ny});\n            }\n        }\n\n        cout << ans << '\\n';\n        cout.flush();\n\n        // Apply human actions to local state\n        for (int i = 0; i < M; i++) {\n            int md = move_dir(ans[i]);\n            int bd = build_dir(ans[i]);\n\n            if (md != -1) {\n                int nx = humans[i].x + dx[md], ny = humans[i].y + dy[md];\n                if (inside(nx, ny) && !wall_[nx][ny] && !blocked_future[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            } else if (bd != -1) {\n                int bx = humans[i].x + dx[bd], by = humans[i].y + dy[bd];\n                if (inside(bx, by) && can_block_startturn(bx, by)) {\n                    wall_[bx][by] = true;\n                }\n            }\n        }\n\n        // Read pet moves and update positions\n        for (int i = 0; i < N; i++) {\n            string s;\n            cin >> s;\n            if (!cin) return 0;\n            if (s == \".\") continue;\n            for (char c : s) {\n                int d = move_dir(c);\n                if (d == -1) continue;\n                int nx = pets[i].x + dx[d], ny = pets[i].y + dy[d];\n                if (inside(nx, ny) && !wall_[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - 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 l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nint si, sj, ti, tj;\ndouble pforget;\nstring hs[H];\nstring vs[H - 1];\n\ninline int id(int i, int j) { return i * W + j; }\ninline pair<int,int> pos(int v) { return {v / W, v % W}; }\n\nint nxt[N][4]; // U,D,L,R\nchar dirch[4] = {'U','D','L','R'};\nint di[4] = {-1,1,0,0};\nint dj[4] = {0,0,-1,1};\n\nint targetDist[N];\nint targetNextDir[N]; // one step on shortest path to target, -1 for target/unreachable\nvector<int> revAdj[N];\n\ndouble eval_string(const string &s) {\n    vector<double> cur(N, 0.0), nxtp(N, 0.0);\n    int s0 = id(si, sj);\n    int tg = id(ti, tj);\n    cur[s0] = 1.0;\n    double ans = 0.0;\n    for (int t = 1; t <= (int)s.size(); t++) {\n        fill(nxtp.begin(), nxtp.end(), 0.0);\n        int d;\n        char c = s[t - 1];\n        if (c == 'U') d = 0;\n        else if (c == 'D') d = 1;\n        else if (c == 'L') d = 2;\n        else d = 3;\n\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == tg) {\n                ans += pr * (401 - t);\n                continue;\n            }\n            nxtp[v] += pr * pforget;\n            int to = nxt[v][d];\n            nxtp[to] += pr * (1.0 - pforget);\n        }\n        cur.swap(nxtp);\n    }\n    // if already at target after all commands, not counted later; failure gives 0\n    return ans;\n}\n\nvector<int> bfs_dist_from_target() {\n    vector<int> dist(N, (int)1e9);\n    queue<int> q;\n    int tg = id(ti, tj);\n    dist[tg] = 0;\n    q.push(tg);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        auto [i, j] = pos(v);\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    return dist;\n}\n\nstring shortest_path_lexi() {\n    int S = id(si, sj), T = id(ti, tj);\n    vector<int> dist(N, (int)1e9), par(N, -1), pard(N, -1);\n    queue<int> q;\n    dist[S] = 0;\n    q.push(S);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        if (v == T) break;\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            if (to == v) continue;\n            if (dist[to] > dist[v] + 1) {\n                dist[to] = dist[v] + 1;\n                par[to] = v;\n                pard[to] = d;\n                q.push(to);\n            }\n        }\n    }\n    string res;\n    int cur = T;\n    while (cur != S) {\n        res.push_back(dirch[pard[cur]]);\n        cur = par[cur];\n    }\n    reverse(res.begin(), res.end());\n    return res;\n}\n\nstring shortest_path_target_greedy_randomized() {\n    // randomized shortest path using targetDist\n    int cur = id(si, sj), tg = id(ti, tj);\n    string s;\n    while (cur != tg) {\n        vector<int> cand;\n        int best = targetDist[cur];\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[cur][d];\n            if (to == cur) continue;\n            if (targetDist[to] + 1 == targetDist[cur]) cand.push_back(d);\n        }\n        if (cand.empty()) break;\n        int d = cand[rng.next_int(0, (int)cand.size() - 1)];\n        s.push_back(dirch[d]);\n        cur = nxt[cur][d];\n    }\n    return s;\n}\n\nstring repeat_each(const string &base, int k) {\n    string s;\n    for (char c : base) {\n        for (int i = 0; i < k; i++) {\n            if ((int)s.size() < MAXL) s.push_back(c);\n        }\n    }\n    return s;\n}\n\nstring build_attractor_suffix(int len) {\n    // Construct a generic target-directed suffix:\n    // at each step choose direction that decreases shortest distance for the largest total mass\n    // approximated by global usefulness count.\n    vector<array<int,4>> improve(N);\n    for (int v = 0; v < N; v++) {\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            improve[v][d] = (targetDist[to] < targetDist[v]) ? 1 : 0;\n        }\n    }\n    string suf;\n    vector<double> cur(N, 0.0), nxtp(N, 0.0);\n    cur[id(si, sj)] = 1.0;\n    int tg = id(ti, tj);\n\n    // First simulate empty prefix? Here we just choose a good generic suffix via rolling optimization.\n    for (int step = 0; step < len; step++) {\n        double bestScore = -1;\n        int bestD = 0;\n        for (int d = 0; d < 4; d++) {\n            double sc = 0;\n            for (int v = 0; v < N; v++) {\n                if (v == tg) continue;\n                sc += cur[v] * improve[v][d];\n            }\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestD = d;\n            }\n        }\n        suf.push_back(dirch[bestD]);\n\n        fill(nxtp.begin(), nxtp.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == tg) {\n                nxtp[v] += pr;\n                continue;\n            }\n            nxtp[v] += pr * pforget;\n            int to = nxt[v][bestD];\n            nxtp[to] += pr * (1.0 - pforget);\n        }\n        cur.swap(nxtp);\n    }\n    return suf;\n}\n\nstring build_candidate_from_base(const string &base) {\n    string best = base;\n    double bestVal = eval_string(best);\n\n    for (int k = 1; k <= 8; k++) {\n        string s = repeat_each(base, k);\n        int rem = MAXL - (int)s.size();\n        if (rem > 0) {\n            string suf = build_attractor_suffix(rem);\n            s += suf;\n        }\n        double val = eval_string(s);\n        if (val > bestVal) {\n            bestVal = val;\n            best = s;\n        }\n    }\n    return best;\n}\n\nstring mutate(const string &s) {\n    string t = s;\n    int op = rng.next_int(0, 99);\n\n    if (op < 30 && !t.empty()) {\n        // change one char\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n    } else if (op < 55 && (int)t.size() < MAXL) {\n        // insert\n        int i = rng.next_int(0, (int)t.size());\n        char c = dirch[rng.next_int(0, 3)];\n        t.insert(t.begin() + i, c);\n    } else if (op < 70 && !t.empty()) {\n        // erase\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t.erase(t.begin() + i);\n    } else if (op < 85 && !t.empty()) {\n        // duplicate segment\n        int l = rng.next_int(0, (int)t.size() - 1);\n        int r = rng.next_int(l, min((int)t.size() - 1, l + 7));\n        string seg = t.substr(l, r - l + 1);\n        if ((int)t.size() + (int)seg.size() <= MAXL) {\n            int pos = rng.next_int(0, (int)t.size());\n            t.insert(pos, seg);\n        }\n    } else if (!t.empty()) {\n        // local target-biased rewrite\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n        if (i + 1 < (int)t.size() && rng.next_double() < 0.5) t[i + 1] = dirch[rng.next_int(0, 3)];\n    }\n\n    if ((int)t.size() > MAXL) t.resize(MAXL);\n    return t;\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 < H; i++) cin >> hs[i];\n    for (int i = 0; i < H - 1; i++) cin >> vs[i];\n\n    for (int i = 0; i < H; i++) for (int j = 0; j < W; j++) {\n        int v = id(i, j);\n        // U\n        if (i == 0 || vs[i - 1][j] == '1') nxt[v][0] = v;\n        else nxt[v][0] = id(i - 1, j);\n        // D\n        if (i == H - 1 || vs[i][j] == '1') nxt[v][1] = v;\n        else nxt[v][1] = id(i + 1, j);\n        // L\n        if (j == 0 || hs[i][j - 1] == '1') nxt[v][2] = v;\n        else nxt[v][2] = id(i, j - 1);\n        // R\n        if (j == W - 1 || hs[i][j] == '1') nxt[v][3] = v;\n        else nxt[v][3] = id(i, j + 1);\n    }\n\n    auto dist = bfs_dist_from_target();\n    for (int v = 0; v < N; v++) targetDist[v] = dist[v];\n\n    for (int v = 0; v < N; v++) {\n        targetNextDir[v] = -1;\n        int best = targetDist[v];\n        for (int d = 0; d < 4; d++) {\n            int to = nxt[v][d];\n            if (to != v && targetDist[to] < best) {\n                best = targetDist[to];\n                targetNextDir[v] = d;\n            }\n        }\n    }\n\n    Timer timer;\n\n    vector<string> seeds;\n    string sp = shortest_path_lexi();\n    seeds.push_back(sp);\n    for (int it = 0; it < 20; it++) {\n        seeds.push_back(shortest_path_target_greedy_randomized());\n    }\n\n    string best = sp;\n    double bestVal = eval_string(best);\n\n    for (auto &base : seeds) {\n        string cand = build_candidate_from_base(base);\n        double val = eval_string(cand);\n        if (val > bestVal) {\n            bestVal = val;\n            best = cand;\n        }\n    }\n\n    // Simulated annealing / hill climbing\n    string cur = best;\n    double curVal = bestVal;\n\n    const double TL = 1.92;\n    int iter = 0;\n    while (true) {\n        double tm = timer.elapsed();\n        if (tm > TL) break;\n        iter++;\n\n        string nxts = mutate(cur);\n        double nv = eval_string(nxts);\n\n        double progress = tm / TL;\n        double temp = 30.0 * (1.0 - progress) + 1e-6;\n        double diff = nv - curVal;\n        if (diff >= 0 || rng.next_double() < exp(diff / temp)) {\n            cur = nxts;\n            curVal = nv;\n            if (nv > bestVal) {\n                bestVal = nv;\n                best = nxts;\n            }\n        }\n\n        // occasional restart near best\n        if ((iter % 500) == 0 && rng.next_double() < 0.3) {\n            cur = best;\n            curVal = bestVal;\n        }\n    }\n\n    if (best.empty()) best = sp;\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n    cout << best << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int NN = N * N;\n\nstatic const int di[4] = {0, -1, 0, 1}; // L U R D\nstatic const int dj[4] = {-1, 0, 1, 0};\n\nstatic const int TO[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\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\ninline int rotTile(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (t <= 3) t = (t + 1) & 3;\n        else if (t <= 5) t = 9 - t;   // 4 <-> 5\n        else t = 13 - t;              // 6 <-> 7\n    }\n    return t;\n}\n\ninline int maskOfTile(int t) {\n    int m = 0;\n    for (int d = 0; d < 4; d++) if (TO[t][d] != -1) m |= (1 << d);\n    return m;\n}\n\nstruct Solver {\n    array<string, N> s;\n    int base[N][N];\n    int rotTileId[N][N][4];\n    int rotMask[N][N][4];\n    mt19937 rng;\n\n    Solver() : rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void readInput() {\n        for (int i = 0; i < N; i++) {\n            cin >> s[i];\n            for (int j = 0; j < N; j++) {\n                base[i][j] = s[i][j] - '0';\n                for (int r = 0; r < 4; r++) {\n                    rotTileId[i][j][r] = rotTile(base[i][j], r);\n                    rotMask[i][j][r] = maskOfTile(rotTileId[i][j][r]);\n                }\n            }\n        }\n    }\n\n    long long exactScore(const array<unsigned char, NN>& rot) {\n        static int tile[N][N];\n        static unsigned char vis[N][N][4];\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            tile[i][j] = rotTileId[i][j][rot[i * N + j]];\n        }\n        memset(vis, 0, sizeof(vis));\n\n        int best1 = 0, best2 = 0;\n\n        for (int si = 0; si < N; si++) for (int sj = 0; sj < N; sj++) for (int sd = 0; sd < 4; sd++) {\n            if (vis[si][sj][sd]) continue;\n\n            int i = si, j = sj, d = sd, len = 0;\n            bool ok = true;\n\n            while (true) {\n                if (vis[i][j][d]) {\n                    ok = false;\n                    break;\n                }\n                vis[i][j][d] = 1;\n\n                int d2 = TO[tile[i][j]][d];\n                if (d2 == -1) {\n                    ok = false;\n                    break;\n                }\n                i += di[d2];\n                j += dj[d2];\n                if (i < 0 || i >= N || j < 0 || j >= N) {\n                    ok = false;\n                    break;\n                }\n                d = (d2 + 2) & 3;\n                ++len;\n                if (i == si && j == sj && d == sd) break;\n                if (len > 4 * NN + 10) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) {\n                if (len > best1) {\n                    best2 = best1;\n                    best1 = len;\n                } else if (len > best2) {\n                    best2 = len;\n                }\n            }\n        }\n\n        if (best2 == 0) return 0;\n        return 1LL * best1 * best2;\n    }\n\n    inline int cellContribution(const array<unsigned char, NN>& rot, int i, int j) const {\n        int m = rotMask[i][j][rot[i * N + j]];\n        int sc = 0;\n\n        if (j + 1 < N) {\n            int m2 = rotMask[i][j + 1][rot[i * N + (j + 1)]];\n            int a = (m >> 2) & 1, b = (m2 >> 0) & 1;\n            if (a && b) sc += 1;\n        } else {\n            if ((m >> 2) & 1) sc -= 1;\n        }\n\n        if (i + 1 < N) {\n            int m2 = rotMask[i + 1][j][rot[(i + 1) * N + j]];\n            int a = (m >> 3) & 1, b = (m2 >> 1) & 1;\n            if (a && b) sc += 1;\n        } else {\n            if ((m >> 3) & 1) sc -= 1;\n        }\n\n        if (j == 0 && ((m >> 0) & 1)) sc -= 1;\n        if (i == 0 && ((m >> 1) & 1)) sc -= 1;\n\n        return sc;\n    }\n\n    int localScore(const array<unsigned char, NN>& rot) const {\n        int sc = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) sc += cellContribution(rot, i, j);\n        return sc;\n    }\n\n    inline int affectedLocal1(const array<unsigned char, NN>& rot, int i, int j) const {\n        int sc = 0;\n        for (int ni = max(0, i - 1); ni <= min(N - 1, i + 1); ni++) {\n            for (int nj = max(0, j - 1); nj <= min(N - 1, j + 1); nj++) {\n                sc += cellContribution(rot, ni, nj);\n            }\n        }\n        return sc;\n    }\n\n    inline int affectedLocal2x2(const array<unsigned char, NN>& rot, int i, int j) const {\n        int sc = 0;\n        for (int ni = max(0, i - 1); ni <= min(N - 1, i + 2); ni++) {\n            for (int nj = max(0, j - 1); nj <= min(N - 1, j + 2); nj++) {\n                sc += cellContribution(rot, ni, nj);\n            }\n        }\n        return sc;\n    }\n\n    array<unsigned char, NN> makeInitial(int type) {\n        array<unsigned char, NN> rot{};\n        if (type == 0) {\n            rot.fill(0);\n        } else if (type == 1) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = (i + j) & 3;\n        } else if (type == 2) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = i & 3;\n        } else if (type == 3) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = j & 3;\n        } else {\n            for (int k = 0; k < NN; k++) rot[k] = rng() & 3;\n        }\n        return rot;\n    }\n\n    void optimizeLocal(array<unsigned char, NN>& rot, Timer& timer, double endTime) {\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n\n        while (timer.elapsed() < endTime) {\n            bool improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int idx : ord) {\n                if (timer.elapsed() >= endTime) return;\n                int i = idx / N, j = idx % N;\n                int before = affectedLocal1(rot, i, j);\n                unsigned char old = rot[idx];\n                int bestDelta = 0;\n                unsigned char bestR = old;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int delta = affectedLocal1(rot, i, j) - before;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = old;\n                if (bestDelta > 0) {\n                    rot[idx] = bestR;\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n    }\n\n    // Softly force a rectangle perimeter loop\n    void seedRectangle(array<unsigned char, NN>& rot, int r1, int c1, int r2, int c2) {\n        auto needMask = [&](int i, int j) -> int {\n            bool top = (i == r1), bottom = (i == r2), left = (j == c1), right = (j == c2);\n            if (top && left) return (1 << 2) | (1 << 3);      // R,D\n            if (top && right) return (1 << 0) | (1 << 3);     // L,D\n            if (bottom && left) return (1 << 1) | (1 << 2);   // U,R\n            if (bottom && right) return (1 << 1) | (1 << 0);  // U,L\n            if (top || bottom) return (1 << 0) | (1 << 2);    // L,R\n            if (left || right) return (1 << 1) | (1 << 3);    // U,D\n            return 0;\n        };\n\n        vector<pair<int,int>> cells;\n        for (int j = c1; j <= c2; j++) cells.push_back({r1, j});\n        for (int i = r1 + 1; i <= r2; i++) cells.push_back({i, c2});\n        for (int j = c2 - 1; j >= c1; j--) cells.push_back({r2, j});\n        for (int i = r2 - 1; i > r1; i--) cells.push_back({i, c1});\n\n        for (auto [i, j] : cells) {\n            int idx = i * N + j;\n            int target = needMask(i, j);\n            int bestVal = -1e9;\n            unsigned char bestR = rot[idx];\n            for (unsigned char nr = 0; nr < 4; nr++) {\n                int m = rotMask[i][j][nr];\n                int fit = 0;\n                // reward exact target match strongly, partial match weakly\n                fit += 6 * (__builtin_popcount((unsigned)(m & target)));\n                fit -= 4 * (__builtin_popcount((unsigned)(m & (~target))));\n                unsigned char old = rot[idx];\n                rot[idx] = nr;\n                fit += affectedLocal1(rot, i, j);\n                rot[idx] = old;\n                if (fit > bestVal) {\n                    bestVal = fit;\n                    bestR = nr;\n                }\n            }\n            rot[idx] = bestR;\n        }\n    }\n\n    void tryRectangleSeeds(array<unsigned char, NN>& bestRot, long long& bestScore, Timer& timer, double endTime) {\n        array<unsigned char, NN> baseRot = bestRot;\n\n        vector<tuple<int,int,int,int>> rects;\n        // deterministic candidate rectangles\n        for (int h : {10, 12, 14, 16, 18, 20, 22, 24}) {\n            for (int w : {10, 12, 14, 16, 18, 20, 22, 24}) {\n                int r1 = (N - h) / 2;\n                int c1 = (N - w) / 2;\n                int r2 = r1 + h - 1;\n                int c2 = c1 + w - 1;\n                if (r1 >= 0 && c1 >= 0 && r2 < N && c2 < N) rects.push_back({r1, c1, r2, c2});\n            }\n        }\n        // random rectangles\n        for (int t = 0; t < 40; t++) {\n            int r1 = rng() % (N - 6);\n            int c1 = rng() % (N - 6);\n            int r2 = r1 + 5 + (rng() % (N - r1 - 5));\n            int c2 = c1 + 5 + (rng() % (N - c1 - 5));\n            rects.push_back({r1, c1, r2, c2});\n        }\n\n        shuffle(rects.begin(), rects.end(), rng);\n\n        for (auto [r1, c1, r2, c2] : rects) {\n            if (timer.elapsed() >= endTime) return;\n            auto rot = baseRot;\n            seedRectangle(rot, r1, c1, r2, c2);\n            optimizeLocal(rot, timer, min(endTime, timer.elapsed() + 0.02));\n            long long sc = exactScore(rot);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestRot = rot;\n            }\n        }\n    }\n\n    void optimize2x2(array<unsigned char, NN>& rot, long long& curScore, Timer& timer, double endTime) {\n        vector<pair<int,int>> blocks;\n        for (int i = 0; i + 1 < N; i++) for (int j = 0; j + 1 < N; j++) blocks.push_back({i, j});\n\n        while (timer.elapsed() < endTime) {\n            shuffle(blocks.begin(), blocks.end(), rng);\n            bool improved = false;\n\n            for (auto [i, j] : blocks) {\n                if (timer.elapsed() >= endTime) return;\n\n                int before = affectedLocal2x2(rot, i, j);\n                int ids[4] = {i * N + j, i * N + (j + 1), (i + 1) * N + j, (i + 1) * N + (j + 1)};\n                unsigned char old[4] = {rot[ids[0]], rot[ids[1]], rot[ids[2]], rot[ids[3]]};\n\n                struct Cand {\n                    int localDelta;\n                    unsigned char r0, r1, r2, r3;\n                };\n                vector<Cand> cand;\n                cand.reserve(256);\n\n                for (unsigned char a = 0; a < 4; a++) for (unsigned char b = 0; b < 4; b++)\n                for (unsigned char c = 0; c < 4; c++) for (unsigned char d = 0; d < 4; d++) {\n                    rot[ids[0]] = a; rot[ids[1]] = b; rot[ids[2]] = c; rot[ids[3]] = d;\n                    int after = affectedLocal2x2(rot, i, j);\n                    cand.push_back({after - before, a, b, c, d});\n                }\n\n                rot[ids[0]] = old[0]; rot[ids[1]] = old[1]; rot[ids[2]] = old[2]; rot[ids[3]] = old[3];\n                nth_element(cand.begin(), cand.begin() + min<int>(8, cand.size()), cand.end(),\n                            [](const Cand& x, const Cand& y){ return x.localDelta > y.localDelta; });\n\n                long long bestSc = curScore;\n                int bestLocal = -1e9;\n                unsigned char br[4] = {old[0], old[1], old[2], old[3]};\n\n                int lim = min<int>(8, cand.size());\n                for (int t = 0; t < lim; t++) {\n                    auto &x = cand[t];\n                    if (x.localDelta < -1) continue;\n                    rot[ids[0]] = x.r0; rot[ids[1]] = x.r1; rot[ids[2]] = x.r2; rot[ids[3]] = x.r3;\n                    long long sc = exactScore(rot);\n                    if (sc > bestSc || (sc == bestSc && x.localDelta > bestLocal)) {\n                        bestSc = sc;\n                        bestLocal = x.localDelta;\n                        br[0] = x.r0; br[1] = x.r1; br[2] = x.r2; br[3] = x.r3;\n                    }\n                }\n\n                rot[ids[0]] = br[0]; rot[ids[1]] = br[1]; rot[ids[2]] = br[2]; rot[ids[3]] = br[3];\n                if (bestSc > curScore) {\n                    curScore = bestSc;\n                    improved = true;\n                } else {\n                    // revert if unchanged\n                    rot[ids[0]] = old[0]; rot[ids[1]] = old[1]; rot[ids[2]] = old[2]; rot[ids[3]] = old[3];\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void optimizeExact1(array<unsigned char, NN>& rot, long long& bestSc, Timer& timer, double endTime) {\n        bestSc = exactScore(rot);\n\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n\n        while (timer.elapsed() < endTime) {\n            bool improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n\n            for (int idx : ord) {\n                if (timer.elapsed() >= endTime) return;\n                int i = idx / N, j = idx % N;\n                int beforeLocal = affectedLocal1(rot, i, j);\n                unsigned char old = rot[idx];\n\n                long long moveBest = bestSc;\n                int moveBestLocal = -1e9;\n                unsigned char bestR = old;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int localDelta = affectedLocal1(rot, i, j) - beforeLocal;\n                    if (localDelta >= -1) {\n                        long long sc = exactScore(rot);\n                        if (sc > moveBest || (sc == moveBest && localDelta > moveBestLocal)) {\n                            moveBest = sc;\n                            moveBestLocal = localDelta;\n                            bestR = nr;\n                        }\n                    }\n                }\n\n                rot[idx] = old;\n                if (bestR != old) {\n                    rot[idx] = bestR;\n                    bestSc = moveBest;\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void solve() {\n        Timer timer;\n        const double TL = 1.95;\n\n        array<unsigned char, NN> globalBest = makeInitial(0);\n        long long globalBestScore = exactScore(globalBest);\n\n        int trial = 0;\n        while (timer.elapsed() < TL) {\n            auto rot = makeInitial(trial < 4 ? trial : 4);\n            double rem = TL - timer.elapsed();\n            if (rem <= 0.0) break;\n\n            // Phase 1: local optimization\n            optimizeLocal(rot, timer, min(TL, timer.elapsed() + min(0.12, rem * 0.35)));\n\n            long long sc = exactScore(rot);\n            if (sc > globalBestScore) {\n                globalBestScore = sc;\n                globalBest = rot;\n            }\n\n            // Phase 2: rectangle seeding from a good base\n            if (timer.elapsed() < TL) {\n                auto rectBase = rot;\n                long long rectSc = sc;\n                tryRectangleSeeds(rectBase, rectSc, timer, min(TL, timer.elapsed() + 0.30));\n                if (rectSc > sc) {\n                    rot = rectBase;\n                    sc = rectSc;\n                }\n                if (sc > globalBestScore) {\n                    globalBestScore = sc;\n                    globalBest = rot;\n                }\n            }\n\n            // Phase 3: 2x2 block optimization\n            if (timer.elapsed() < TL) {\n                optimize2x2(rot, sc, timer, min(TL, timer.elapsed() + 0.45));\n                if (sc > globalBestScore) {\n                    globalBestScore = sc;\n                    globalBest = rot;\n                }\n            }\n\n            // Phase 4: exact 1-cell refinement\n            if (timer.elapsed() < TL) {\n                optimizeExact1(rot, sc, timer, min(TL, timer.elapsed() + 0.25));\n                if (sc > globalBestScore) {\n                    globalBestScore = sc;\n                    globalBest = rot;\n                }\n            }\n\n            trial++;\n        }\n\n        string ans(NN, '0');\n        for (int i = 0; i < NN; i++) ans[i] = char('0' + globalBest[i]);\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.readInput();\n    solver.solve();\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\nstatic constexpr int DI[4] = {-1, 1, 0, 0};\nstatic constexpr int DJ[4] = {0, 0, -1, 1};\nstatic constexpr char DC[4] = {'U', 'D', 'L', 'R'};\n\nint N, Tlim;\nvector<unsigned char> init_board;\nint init_empty;\n\ninline int opp(int d) { return d ^ 1; }\n\ninline int c2d(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\ninline bool can_move(int empty_pos, int d) {\n    int i = empty_pos / N, j = empty_pos % N;\n    int ni = i + DI[d], nj = j + DJ[d];\n    return 0 <= ni && ni < N && 0 <= nj && nj < N;\n}\n\ninline void apply_move(vector<unsigned char>& board, int& empty_pos, int d) {\n    int ei = empty_pos / N, ej = empty_pos % N;\n    int ni = ei + DI[d], nj = ej + DJ[d];\n    int np = ni * N + nj;\n    swap(board[empty_pos], board[np]);\n    empty_pos = np;\n}\n\nstruct Eval {\n    int largestTree;\n    int matchedEdges;\n    int largestComponent;\n    int cyclePenalty; // sum over components max(0, e-(v-1))\n};\n\nEval evaluate_board_detail(const vector<unsigned char>& board) {\n    int V = N * N;\n    static int g[100][4];\n    static int deg[100];\n    static unsigned char alive[100];\n    static unsigned char vis[100];\n\n    for (int p = 0; p < V; ++p) {\n        deg[p] = 0;\n        alive[p] = (board[p] != 0);\n        vis[p] = 0;\n    }\n\n    auto has = [&](int mask, int bit) -> bool { return (mask & bit) != 0; };\n\n    int matchedEdges = 0;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int p = i * N + j;\n            if (!alive[p]) continue;\n            int m = board[p];\n            if (i + 1 < N) {\n                int q = (i + 1) * N + j;\n                if (alive[q] && has(m, 8) && has(board[q], 2)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                    ++matchedEdges;\n                }\n            }\n            if (j + 1 < N) {\n                int q = i * N + (j + 1);\n                if (alive[q] && has(m, 4) && has(board[q], 1)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                    ++matchedEdges;\n                }\n            }\n        }\n    }\n\n    int largestTree = 0;\n    int largestComponent = 0;\n    int cyclePenalty = 0;\n\n    int q[100];\n    for (int s = 0; s < V; ++s) {\n        if (!alive[s] || vis[s]) continue;\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = 1;\n        int vc = 0;\n        int sumdeg = 0;\n        while (head < tail) {\n            int v = q[head++];\n            ++vc;\n            sumdeg += deg[v];\n            for (int k = 0; k < deg[v]; ++k) {\n                int to = g[v][k];\n                if (!vis[to]) {\n                    vis[to] = 1;\n                    q[tail++] = to;\n                }\n            }\n        }\n        int ec = sumdeg / 2;\n        largestComponent = max(largestComponent, vc);\n        if (ec == vc - 1) largestTree = max(largestTree, vc);\n        if (ec > vc - 1) cyclePenalty += ec - (vc - 1);\n    }\n\n    return {largestTree, matchedEdges, largestComponent, cyclePenalty};\n}\n\nstruct Candidate {\n    string ops;\n    int bestLen = 0;\n    Eval bestEval{0, 0, 0, 0};\n};\n\ninline bool better_eval(const Eval& a, const Eval& b) {\n    if (a.largestTree != b.largestTree) return a.largestTree > b.largestTree;\n    if (a.matchedEdges != b.matchedEdges) return a.matchedEdges > b.matchedEdges;\n    if (a.largestComponent != b.largestComponent) return a.largestComponent > b.largestComponent;\n    if (a.cyclePenalty != b.cyclePenalty) return a.cyclePenalty < b.cyclePenalty;\n    return false;\n}\n\ninline bool better_cand(const Candidate& a, const Candidate& b) {\n    if (better_eval(a.bestEval, b.bestEval)) return true;\n    if (better_eval(b.bestEval, a.bestEval)) return false;\n    return a.bestLen < b.bestLen;\n}\n\nmt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\nvoid replay_prefix(const string& ops, int upto, vector<unsigned char>& board, int& empty, int& prevDir) {\n    board = init_board;\n    empty = init_empty;\n    prevDir = -1;\n    for (int i = 0; i < upto; ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) break;\n        apply_move(board, empty, d);\n        prevDir = d;\n    }\n}\n\nCandidate evaluate_sequence(const string& ops) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n\n    Candidate res;\n    res.ops = ops;\n    res.bestLen = 0;\n    res.bestEval = evaluate_board_detail(board);\n\n    for (int i = 0; i < (int)ops.size(); ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) {\n            res.ops.resize(i);\n            break;\n        }\n        apply_move(board, empty, d);\n\n        // evaluate every step; board is small\n        Eval e = evaluate_board_detail(board);\n        if (better_eval(e, res.bestEval) ||\n            (!better_eval(res.bestEval, e) && i + 1 < res.bestLen)) {\n            res.bestEval = e;\n            res.bestLen = i + 1;\n        }\n    }\n    return res;\n}\n\nstring random_legal_suffix(int empty, int maxAdd, int prevDir = -1, bool prefer_no_back = true) {\n    string s;\n    s.reserve(maxAdd);\n    for (int step = 0; step < maxAdd; ++step) {\n        int cand[4], cnt = 0;\n        for (int d = 0; d < 4; ++d) {\n            if (!can_move(empty, d)) continue;\n            if (prefer_no_back && prevDir != -1 && d == opp(prevDir)) continue;\n            cand[cnt++] = d;\n        }\n        if (cnt == 0) {\n            for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n        }\n        int d = cand[rng() % cnt];\n        s.push_back(DC[d]);\n        int ei = empty / N, ej = empty % N;\n        int ni = ei + DI[d], nj = ej + DJ[d];\n        empty = ni * N + nj;\n        prevDir = d;\n    }\n    return s;\n}\n\nint greedy_choose_move(const vector<unsigned char>& board, int empty, int prevDir) {\n    // Try all legal moves and choose the one with best immediate heuristic.\n    Eval bestE{-1, -1, -1, (int)1e9};\n    int bestD = -1;\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) {\n        if (!can_move(empty, d)) continue;\n        cand[cnt++] = d;\n    }\n    shuffle(cand, cand + cnt, rng);\n\n    for (int ii = 0; ii < cnt; ++ii) {\n        int d = cand[ii];\n        vector<unsigned char> nb = board;\n        int ne = empty;\n        apply_move(nb, ne, d);\n        Eval e = evaluate_board_detail(nb);\n\n        // slight preference against immediate undo if comparable\n        if (bestD == -1 || better_eval(e, bestE) ||\n            (!better_eval(bestE, e) && prevDir != -1 && bestD == opp(prevDir) && d != opp(prevDir))) {\n            bestE = e;\n            bestD = d;\n        }\n    }\n    return bestD;\n}\n\nCandidate make_random_candidate() {\n    uniform_int_distribution<int> lenDist(0, Tlim);\n    int L = lenDist(rng);\n    string ops = random_legal_suffix(init_empty, L, -1, true);\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_cut_regrow(const Candidate& base) {\n    int L = (int)base.ops.size();\n    int cut;\n    if (L == 0) cut = 0;\n    else {\n        int mode = rng() % 4;\n        if (mode == 0) {\n            uniform_int_distribution<int> dist(0, L);\n            cut = dist(rng);\n        } else if (mode == 1) {\n            int lo = max(0, base.bestLen - 12);\n            int hi = min(L, base.bestLen + 12);\n            uniform_int_distribution<int> dist(lo, hi);\n            cut = dist(rng);\n        } else if (mode == 2) {\n            uniform_int_distribution<int> dist(0, min(L, base.bestLen));\n            cut = dist(rng);\n        } else {\n            cut = base.bestLen;\n        }\n    }\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, cut, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, cut);\n    int rem = Tlim - cut;\n    uniform_int_distribution<int> addDist(0, rem);\n    int add = addDist(rng);\n\n    if ((rng() % 100) < 45) {\n        // greedy rollout suffix\n        for (int step = 0; step < add; ++step) {\n            int d;\n            if ((rng() % 100) < 70) d = greedy_choose_move(board, empty, prevDir);\n            else {\n                int cand[4], cnt = 0;\n                for (int k = 0; k < 4; ++k) {\n                    if (!can_move(empty, k)) continue;\n                    if (prevDir != -1 && k == opp(prevDir)) continue;\n                    cand[cnt++] = k;\n                }\n                if (cnt == 0) for (int k = 0; k < 4; ++k) if (can_move(empty, k)) cand[cnt++] = k;\n                d = cand[rng() % cnt];\n            }\n            ops.push_back(DC[d]);\n            apply_move(board, empty, d);\n            prevDir = d;\n        }\n    } else {\n        ops += random_legal_suffix(empty, add, prevDir, true);\n    }\n\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_edit(const Candidate& base) {\n    if (base.ops.empty()) return make_random_candidate();\n    int L = (int)base.ops.size();\n    int pos = rng() % L;\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, pos, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, pos);\n\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n    shuffle(cand, cand + cnt, rng);\n\n    int chosen = cand[0];\n    if ((rng() % 100) < 70) {\n        Eval bestE{-1, -1, -1, (int)1e9};\n        for (int ii = 0; ii < cnt; ++ii) {\n            int d = cand[ii];\n            vector<unsigned char> nb = board;\n            int ne = empty;\n            apply_move(nb, ne, d);\n            Eval e = evaluate_board_detail(nb);\n            if (ii == 0 || better_eval(e, bestE)) {\n                bestE = e;\n                chosen = d;\n            }\n        }\n    }\n\n    ops.push_back(DC[chosen]);\n    apply_move(board, empty, chosen);\n    prevDir = chosen;\n\n    int remCap = Tlim - (int)ops.size();\n    int tail = remCap > 0 ? (rng() % (remCap + 1)) : 0;\n    if ((rng() % 100) < 50) {\n        for (int step = 0; step < tail; ++step) {\n            int d = ((rng() % 100) < 65) ? greedy_choose_move(board, empty, prevDir) : -1;\n            if (d == -1) {\n                int cc[4], ccnt = 0;\n                for (int k = 0; k < 4; ++k) {\n                    if (!can_move(empty, k)) continue;\n                    if (prevDir != -1 && k == opp(prevDir)) continue;\n                    cc[ccnt++] = k;\n                }\n                if (ccnt == 0) for (int k = 0; k < 4; ++k) if (can_move(empty, k)) cc[ccnt++] = k;\n                d = cc[rng() % ccnt];\n            }\n            ops.push_back(DC[d]);\n            apply_move(board, empty, d);\n            prevDir = d;\n        }\n    } else {\n        ops += random_legal_suffix(empty, tail, prevDir, true);\n    }\n\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_insert_delete(const Candidate& base) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n    int prevDir = -1;\n\n    string ops;\n    ops.reserve(Tlim);\n\n    int i = 0;\n    while (i < (int)base.ops.size() && (int)ops.size() < Tlim) {\n        if ((rng() % 100) < 10 && (int)ops.size() < Tlim) {\n            int d = ((rng() % 100) < 60) ? greedy_choose_move(board, empty, prevDir) : -1;\n            if (d == -1) {\n                int cand[4], cnt = 0;\n                for (int k = 0; k < 4; ++k) if (can_move(empty, k)) cand[cnt++] = k;\n                d = cand[rng() % cnt];\n            }\n            ops.push_back(DC[d]);\n            apply_move(board, empty, d);\n            prevDir = d;\n        }\n\n        if ((rng() % 100) < 15) {\n            ++i;\n            continue;\n        }\n\n        int d = c2d(base.ops[i]);\n        if (!can_move(empty, d)) break;\n        ops.push_back(base.ops[i]);\n        apply_move(board, empty, d);\n        prevDir = d;\n        ++i;\n    }\n\n    int rem = Tlim - (int)ops.size();\n    int add = rem > 0 ? (rng() % (min(rem, 25) + 1)) : 0;\n    if ((rng() % 100) < 50) {\n        for (int step = 0; step < add; ++step) {\n            int d = greedy_choose_move(board, empty, prevDir);\n            ops.push_back(DC[d]);\n            apply_move(board, empty, d);\n            prevDir = d;\n        }\n    } else {\n        ops += random_legal_suffix(empty, add, prevDir, true);\n    }\n\n    return evaluate_sequence(ops);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    init_board.assign(N * N, 0);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            char c = s[j];\n            int v = ('0' <= c && c <= '9') ? c - '0' : 10 + (c - 'a');\n            init_board[i * N + j] = (unsigned char)v;\n            if (v == 0) init_empty = i * N + j;\n        }\n    }\n\n    Timer timer;\n    const double TL = 2.90;\n\n    const int BEAM = 14;\n    vector<Candidate> pool;\n    pool.reserve(BEAM * 3);\n\n    Candidate best;\n    best.ops = \"\";\n    best.bestLen = 0;\n    best.bestEval = evaluate_board_detail(init_board);\n    pool.push_back(best);\n\n    while ((int)pool.size() < BEAM && timer.elapsed() < 0.35) {\n        Candidate c = make_random_candidate();\n        if (better_cand(c, best)) best = c;\n        pool.push_back(c);\n    }\n\n    auto shrink_pool = [&]() {\n        sort(pool.begin(), pool.end(), better_cand);\n        vector<Candidate> np;\n        for (auto& c : pool) {\n            bool dup = false;\n            for (auto& x : np) {\n                if (c.bestLen == x.bestLen &&\n                    c.bestEval.largestTree == x.bestEval.largestTree &&\n                    c.bestEval.matchedEdges == x.bestEval.matchedEdges &&\n                    c.ops == x.ops) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) np.push_back(c);\n            if ((int)np.size() >= BEAM) break;\n        }\n        pool.swap(np);\n        if (!pool.empty() && better_cand(pool[0], best)) best = pool[0];\n    };\n\n    shrink_pool();\n\n    while (timer.elapsed() < TL) {\n        int idx;\n        if ((rng() % 100) < 60) idx = rng() % min(5, (int)pool.size());\n        else idx = rng() % pool.size();\n\n        Candidate cand;\n        int typ = rng() % 100;\n        if (typ < 12) cand = make_random_candidate();\n        else if (typ < 54) cand = mutate_cut_regrow(pool[idx]);\n        else if (typ < 80) cand = mutate_edit(pool[idx]);\n        else cand = mutate_insert_delete(pool[idx]);\n\n        pool.push_back(cand);\n        if (better_cand(cand, best)) best = cand;\n\n        if ((int)pool.size() >= BEAM * 2) shrink_pool();\n    }\n\n    cout << best.ops.substr(0, best.bestLen) << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nstatic const long long LIM = 1000000000LL;\nstatic const double PI = acos(-1.0);\n\nstatic inline long long clampLL(long long x) {\n    return max(-LIM, min(LIM, x));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    array<int, 11> a{};\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // Exact DP for the best partition under the \"all cuts parallel\" model.\n    // dp[s][u] = best matched count using exactly s strawberries in useful pieces\n    // and exactly u useful pieces.\n    //\n    // We build it by sizes 1..10 with bounded multiplicities.\n    vector<vector<int>> dp(N + 1, vector<int>(K + 2, -1e9));\n    struct Prev {\n        short ps, pu, d;\n    };\n    vector<vector<Prev>> prv(N + 1, vector<Prev>(K + 2, {-1, -1, -1}));\n\n    dp[0][0] = 0;\n\n    for (int d = 1; d <= 10; d++) {\n        // Add up to a[d] beneficial pieces of size d.\n        for (int rep = 0; rep < a[d]; rep++) {\n            auto ndp = dp;\n            auto nprv = prv;\n            for (int s = 0; s + d <= N; s++) {\n                for (int u = 0; u + 1 <= K + 1; u++) {\n                    if (dp[s][u] < 0) continue;\n                    if (dp[s][u] + 1 > ndp[s + d][u + 1]) {\n                        ndp[s + d][u + 1] = dp[s][u] + 1;\n                        nprv[s + d][u + 1] = {(short)s, (short)u, (short)d};\n                    }\n                }\n            }\n            dp.swap(ndp);\n            prv.swap(nprv);\n        }\n    }\n\n    // Find best feasible state.\n    // If s == N, total pieces = u.\n    // If s < N, we need one leftover piece, so total pieces = u + 1 <= K+1.\n    int bestScore = -1, bestS = 0, bestU = 0;\n    for (int s = 0; s <= N; s++) {\n        for (int u = 0; u <= K + 1; u++) {\n            if (dp[s][u] < 0) continue;\n            bool ok = false;\n            if (s == N) {\n                ok = (u <= K + 1);\n            } else {\n                ok = (u + 1 <= K + 1);\n            }\n            if (!ok) continue;\n            if (dp[s][u] > bestScore) {\n                bestScore = dp[s][u];\n                bestS = s;\n                bestU = u;\n            }\n        }\n    }\n\n    // Reconstruct useful piece sizes.\n    vector<int> useful;\n    int cs = bestS, cu = bestU;\n    while (cs != 0 || cu != 0) {\n        auto pr = prv[cs][cu];\n        if (pr.d == -1) break;\n        useful.push_back(pr.d);\n        cs = pr.ps;\n        cu = pr.pu;\n    }\n    reverse(useful.begin(), useful.end());\n\n    // Add leftover if any.\n    int used = 0;\n    for (int x : useful) used += x;\n    vector<int> groups = useful;\n    if (used < N) groups.push_back(N - used);\n\n    // To be safe, pieces <= 101\n    while ((int)groups.size() > K + 1) {\n        int x = groups.back(); groups.pop_back();\n        groups.back() += x;\n    }\n\n    // Choose a fixed direction and sort by projection.\n    // Since any direction works for the parallel partition model, this is enough.\n    double theta = 0.3141592653589793; // arbitrary, not axis-aligned\n    double c = cos(theta), s = sin(theta);\n\n    vector<double> proj(N);\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    for (int i = 0; i < N; i++) {\n        proj[i] = p[i].x * c + p[i].y * s;\n    }\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (proj[i] != proj[j]) return proj[i] < proj[j];\n        return i < j;\n    });\n\n    // Place cuts between cumulative group boundaries.\n    vector<double> alphas;\n    int pref = 0;\n    for (int i = 0; i + 1 < (int)groups.size(); i++) {\n        pref += groups[i];\n        if (pref <= 0 || pref >= N) continue;\n        double t1 = proj[ord[pref - 1]];\n        double t2 = proj[ord[pref]];\n        alphas.push_back((t1 + t2) * 0.5);\n    }\n\n    cout << alphas.size() << '\\n';\n\n    const double T = 200000.0;\n    for (double alpha : alphas) {\n        // Line: c*x + s*y = alpha\n        // Point on line: alpha*(c,s)\n        // Direction vector: (-s,c)\n        double x0 = alpha * c;\n        double y0 = alpha * s;\n        double dx = -s, dy = c;\n\n        long long x1 = llround(x0 + T * dx);\n        long long y1 = llround(y0 + T * dy);\n        long long x2 = llround(x0 - T * dx);\n        long long y2 = llround(y0 - T * dy);\n\n        x1 = clampLL(x1);\n        y1 = clampLL(y1);\n        x2 = clampLL(x2);\n        y2 = clampLL(y2);\n\n        if (x1 == x2 && y1 == y2) {\n            if (x2 < LIM) x2++;\n            else x2--;\n        }\n\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\nstruct Op {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nstruct Candidate {\n    double score;\n    Op op;\n    bool operator<(const Candidate& other) const {\n        return score < other.score;\n    }\n};\n\nstruct Solver {\n    int N, M, c;\n    vector<pair<int,int>> initDots;\n    long long Ssum;\n\n    Solver(int N_, int M_, const vector<pair<int,int>>& pts) : N(N_), M(M_), initDots(pts) {\n        c = (N - 1) / 2;\n        Ssum = 0;\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            long long dx = x - c, dy = y - c;\n            Ssum += dx * dx + dy * dy + 1;\n        }\n    }\n\n    int weight(int x, int y) const {\n        int dx = x - c, dy = y - c;\n        return dx * dx + dy * dy + 1;\n    }\n\n    struct State {\n        int N;\n        vector<vector<char>> dot;\n        vector<vector<char>> usedH, usedV, usedD1, usedD2;\n        vector<pair<int,int>> dots;\n        vector<Op> ops;\n        long long wsum = 0;\n        State(int N_=0): N(N_) {}\n    };\n\n    State initial_state() const {\n        State st(N);\n        st.dot.assign(N, vector<char>(N, 0));\n        st.usedH.assign(max(0, N - 1), vector<char>(N, 0));\n        st.usedV.assign(N, vector<char>(max(0, N - 1), 0));\n        st.usedD1.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        st.usedD2.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        for (auto [x, y] : initDots) {\n            st.dot[x][y] = 1;\n            st.dots.push_back({x, y});\n            st.wsum += weight(x, y);\n        }\n        return st;\n    }\n\n    bool inside(int x, int y) const {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    }\n\n    bool getSegUsed(const State& st, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            return st.usedV[x1][y1];\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            return st.usedH[x1][y1];\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            return st.usedD1[x1][y1];\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            return st.usedD2[x1][yl];\n        }\n    }\n\n    void setSegUsed(State& st, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            st.usedV[x1][y1] = 1;\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            st.usedH[x1][y1] = 1;\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            st.usedD1[x1][y1] = 1;\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            st.usedD2[x1][yl] = 1;\n        }\n    }\n\n    bool edge_clear_and_unused(const State& st, int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            if (getSegUsed(st, x, y, nx, ny)) return false;\n            if (t + 1 < len && st.dot[nx][ny]) return false;\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void mark_edge(State& st, int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            setSegUsed(st, x, y, nx, ny);\n            x = nx; y = ny;\n        }\n    }\n\n    bool legal_rect(const State& st, const Op& op) const {\n        int x1=op.x1,y1=op.y1,x2=op.x2,y2=op.y2,x3=op.x3,y3=op.y3,x4=op.x4,y4=op.y4;\n        if (!inside(x1,y1)||!inside(x2,y2)||!inside(x3,y3)||!inside(x4,y4)) return false;\n        if (st.dot[x1][y1]) return false;\n        if (!st.dot[x2][y2] || !st.dot[x3][y3] || !st.dot[x4][y4]) return false;\n\n        auto ok_edge = [&](int ax, int ay, int bx, int by) {\n            int dx = bx - ax, dy = by - ay;\n            if (dx == 0 && dy != 0) return true;\n            if (dy == 0 && dx != 0) return true;\n            if (abs(dx) == abs(dy) && dx != 0) return true;\n            return false;\n        };\n        if (!ok_edge(x1,y1,x2,y2) || !ok_edge(x2,y2,x3,y3) ||\n            !ok_edge(x3,y3,x4,y4) || !ok_edge(x4,y4,x1,y1)) return false;\n\n        int ax = x2 - x1, ay = y2 - y1;\n        int bx = x4 - x1, by = y4 - y1;\n        if ((ax == 0 && ay == 0) || (bx == 0 && by == 0)) return false;\n        if (ax * bx + ay * by != 0) return false;\n        if (x3 != x2 + bx || y3 != y2 + by) return false;\n        if (x3 != x4 + ax || y3 != y4 + ay) return false;\n\n        if (!edge_clear_and_unused(st, x1,y1,x2,y2)) return false;\n        if (!edge_clear_and_unused(st, x2,y2,x3,y3)) return false;\n        if (!edge_clear_and_unused(st, x3,y3,x4,y4)) return false;\n        if (!edge_clear_and_unused(st, x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void apply(State& st, const Op& op) const {\n        st.dot[op.x1][op.y1] = 1;\n        st.dots.push_back({op.x1, op.y1});\n        st.wsum += weight(op.x1, op.y1);\n        mark_edge(st, op.x1, op.y1, op.x2, op.y2);\n        mark_edge(st, op.x2, op.y2, op.x3, op.y3);\n        mark_edge(st, op.x3, op.y3, op.x4, op.y4);\n        mark_edge(st, op.x4, op.y4, op.x1, op.y1);\n        st.ops.push_back(op);\n    }\n\n    long long calc_score(const State& st) const {\n        double val = 1e6 * (double)(N * N) / (double)M * (double)st.wsum / (double)Ssum;\n        return llround(val);\n    }\n\n    double eval_small(const Op& op, int mode) const {\n        int w = weight(op.x1, op.y1);\n        int l1 = max(abs(op.x2-op.x1), abs(op.y2-op.y1));\n        int l2 = max(abs(op.x4-op.x1), abs(op.y4-op.y1));\n        int per = l1 + l2;\n        int dist = abs(op.x1 - c) + abs(op.y1 - c);\n        if (mode == 0) return 800.0 * w - 350.0 * per + 15.0 * dist;\n        if (mode == 1) return 700.0 * w - 420.0 * per + 10.0 * dist;\n        if (mode == 2) return 1000.0 * w - 300.0 * per + 20.0 * dist;\n        return 850.0 * w - 360.0 * per + 18.0 * dist;\n    }\n\n    double eval_large(const Op& op, int mode, double noise=0.0) const {\n        int w = weight(op.x1, op.y1);\n        int l1 = max(abs(op.x2-op.x1), abs(op.y2-op.y1));\n        int l2 = max(abs(op.x4-op.x1), abs(op.y4-op.y1));\n        int per = l1 + l2;\n        int dist = abs(op.x1 - c) + abs(op.y1 - c);\n        if (mode == 0) return 2200.0 * w - 150.0 * per + 35.0 * dist + noise;\n        if (mode == 1) return 1800.0 * w - 200.0 * per + 25.0 * dist + noise;\n        if (mode == 2) return 3000.0 * w - 110.0 * per + 50.0 * dist + noise;\n        return 2400.0 * w - 140.0 * per + 40.0 * dist + noise;\n    }\n\n    bool closure_small(State& st, int mode, int maxLen, double endTime, const Timer& timer) const {\n        Candidate best{-1e100, {}};\n        bool found = false;\n\n        for (int x1 = 0; x1 < N; x1++) {\n            if (timer.elapsed() > endTime) break;\n            for (int y1 = 0; y1 < N; y1++) {\n                if (st.dot[x1][y1]) continue;\n\n                // axis-aligned exhaustive small\n                for (int dx = 1; dx <= maxLen; dx++) for (int dy = 1; dy <= maxLen; dy++) {\n                    Op cand[4] = {\n                        {x1,y1, x1+dx,y1, x1+dx,y1+dy, x1,y1+dy},\n                        {x1,y1, x1,y1+dy, x1-dx,y1+dy, x1-dx,y1},\n                        {x1,y1, x1-dx,y1, x1-dx,y1-dy, x1,y1-dy},\n                        {x1,y1, x1,y1-dy, x1+dx,y1-dy, x1+dx,y1}\n                    };\n                    for (int k = 0; k < 4; k++) {\n                        if (legal_rect(st, cand[k])) {\n                            double sc = eval_small(cand[k], mode);\n                            if (sc > best.score) best = {sc, cand[k]}, found = true;\n                        }\n                    }\n                }\n\n                // rotated exhaustive small\n                for (int d1 = 1; d1 <= maxLen; d1++) for (int d2 = 1; d2 <= maxLen; d2++) {\n                    static const int sgn[4][2] = {{1,1},{1,-1},{-1,1},{-1,-1}};\n                    for (int k = 0; k < 4; k++) {\n                        int ax = sgn[k][0] * d1, ay = sgn[k][1] * d1;\n                        int bx1 = -sgn[k][1] * d2, by1 =  sgn[k][0] * d2;\n                        int bx2 =  sgn[k][1] * d2, by2 = -sgn[k][0] * d2;\n                        Op op1{x1,y1, x1+ax,y1+ay, x1+ax+bx1,y1+ay+by1, x1+bx1,y1+by1};\n                        Op op2{x1,y1, x1+ax,y1+ay, x1+ax+bx2,y1+ay+by2, x1+bx2,y1+by2};\n                        if (inside(op1.x2,op1.y2)&&inside(op1.x3,op1.y3)&&inside(op1.x4,op1.y4) && legal_rect(st, op1)) {\n                            double sc = eval_small(op1, mode);\n                            if (sc > best.score) best = {sc, op1}, found = true;\n                        }\n                        if (inside(op2.x2,op2.y2)&&inside(op2.x3,op2.y3)&&inside(op2.x4,op2.y4) && legal_rect(st, op2)) {\n                            double sc = eval_small(op2, mode);\n                            if (sc > best.score) best = {sc, op2}, found = true;\n                        }\n                    }\n                }\n            }\n        }\n\n        if (found) {\n            apply(st, best.op);\n            return true;\n        }\n        return false;\n    }\n\n    vector<Candidate> enumerate_structure_candidates(const State& st, int mode, mt19937& rng, int capDots) const {\n        vector<Candidate> cand;\n        vector<pair<int,int>> pts = st.dots;\n\n        if ((int)pts.size() > capDots) {\n            sort(pts.begin(), pts.end(), [&](auto& a, auto& b){\n                return weight(a.first, a.second) > weight(b.first, b.second);\n            });\n            int keep = capDots * 3 / 4;\n            if ((int)pts.size() > keep) pts.resize(keep);\n            // add a few random ones\n            vector<pair<int,int>> rest = st.dots;\n            shuffle(rest.begin(), rest.end(), rng);\n            for (int i = 0; i < (int)rest.size() && (int)pts.size() < capDots; i++) pts.push_back(rest[i]);\n        }\n\n        unordered_map<int, vector<int>> byX, byY;\n        byX.reserve(2 * pts.size() + 10);\n        byY.reserve(2 * pts.size() + 10);\n        for (auto [x, y] : pts) {\n            byX[x].push_back(y);\n            byY[y].push_back(x);\n        }\n\n        auto add_if = [&](const Op& op) {\n            if (legal_rect(st, op)) {\n                double noise = uniform_real_distribution<double>(0.0, 1e-7)(rng);\n                cand.push_back({eval_large(op, mode, noise), op});\n            }\n        };\n\n        // Axis-aligned from occupied structures:\n        for (auto [x2, y2] : pts) {\n            auto itx = byX.find(x2);\n            auto ity = byY.find(y2);\n            if (itx == byX.end() || ity == byY.end()) continue;\n\n            auto ys = itx->second;\n            auto xs = ity->second;\n            if ((int)ys.size() > 16) {\n                shuffle(ys.begin(), ys.end(), rng);\n                ys.resize(16);\n            }\n            if ((int)xs.size() > 16) {\n                shuffle(xs.begin(), xs.end(), rng);\n                xs.resize(16);\n            }\n\n            for (int y4 : ys) {\n                if (y4 == y2) continue;\n                for (int x1 : xs) {\n                    if (x1 == x2) continue;\n                    int y1 = y4;\n                    if (!inside(x1,y1)) continue;\n                    if (!st.dot[x2][y4] || !st.dot[x1][y2]) continue;\n                    Op op{x1,y1, x2,y4, x2,y2, x1,y2};\n                    add_if(op);\n                }\n            }\n        }\n\n        // Rotated from occupied point and short/medium diagonal vectors.\n        int maxD = min(10, N - 1);\n        for (auto [x2, y2] : pts) {\n            for (int d = 1; d <= maxD; d++) {\n                static const int sx[4] = {1,1,-1,-1};\n                static const int sy[4] = {1,-1,1,-1};\n                for (int k = 0; k < 4; k++) {\n                    int ax = sx[k] * d, ay = sy[k] * d;\n                    int x1 = x2 - ax, y1 = y2 - ay;\n\n                    int bx = -ay, by = ax;\n                    Op op1{x1,y1, x2,y2, x2+bx,y2+by, x1+bx,y1+by};\n                    if (inside(op1.x1,op1.y1)&&inside(op1.x3,op1.y3)&&inside(op1.x4,op1.y4)) add_if(op1);\n\n                    bx = ay; by = -ax;\n                    Op op2{x1,y1, x2,y2, x2+bx,y2+by, x1+bx,y1+by};\n                    if (inside(op2.x1,op2.y1)&&inside(op2.x3,op2.y3)&&inside(op2.x4,op2.y4)) add_if(op2);\n                }\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b){\n            if (a.op.x1 != b.op.x1) return a.op.x1 < b.op.x1;\n            if (a.op.y1 != b.op.y1) return a.op.y1 < b.op.y1;\n            if (a.op.x2 != b.op.x2) return a.op.x2 < b.op.x2;\n            if (a.op.y2 != b.op.y2) return a.op.y2 < b.op.y2;\n            if (a.op.x3 != b.op.x3) return a.op.x3 < b.op.x3;\n            if (a.op.y3 != b.op.y3) return a.op.y3 < b.op.y3;\n            if (a.op.x4 != b.op.x4) return a.op.x4 < b.op.x4;\n            if (a.op.y4 != b.op.y4) return a.op.y4 < b.op.y4;\n            return a.score > b.score;\n        });\n\n        vector<Candidate> uniq;\n        uniq.reserve(cand.size());\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (i == 0 || memcmp(&cand[i].op, &cand[i-1].op, sizeof(Op)) != 0) uniq.push_back(cand[i]);\n        }\n\n        sort(uniq.begin(), uniq.end(), [](const Candidate& a, const Candidate& b){\n            return a.score > b.score;\n        });\n        if ((int)uniq.size() > 250) uniq.resize(250);\n        return uniq;\n    }\n\n    State run_one(int mode, uint64_t seed, double endTime, const Timer& timer) const {\n        mt19937 rng((uint32_t)seed);\n        State st = initial_state();\n\n        // Phase 1: deterministic small closure\n        int closureLimit = 1000;\n        int smallLen = (mode == 1 ? 4 : 3);\n        while (closureLimit-- > 0 && timer.elapsed() < endTime * 0.55) {\n            if (!closure_small(st, mode, smallLen, endTime * 0.55, timer)) break;\n        }\n\n        // Phase 2: broader stable greedy\n        int stagnation = 0;\n        while (timer.elapsed() < endTime) {\n            int capDots = (timer.elapsed() < endTime * 0.8 ? 220 : 160);\n            auto cand = enumerate_structure_candidates(st, mode, rng, capDots);\n\n            bool moved = false;\n            int tryCount = min<int>(cand.size(), 30);\n            for (int i = 0; i < tryCount; i++) {\n                int idx;\n                if (mode == 1) idx = i;\n                else if (mode == 0) idx = min(i / 2, tryCount - 1);\n                else idx = min((int)uniform_int_distribution<int>(0, min(7, tryCount - 1))(rng) + i / 4, tryCount - 1);\n\n                if (idx >= (int)cand.size()) continue;\n                if (legal_rect(st, cand[idx].op)) {\n                    apply(st, cand[idx].op);\n                    moved = true;\n                    stagnation = 0;\n                    break;\n                }\n            }\n\n            if (!moved) {\n                stagnation++;\n                if (stagnation >= 3) break;\n                // One more small closure attempt can unlock chains\n                if (!closure_small(st, mode, 2, endTime, timer)) {\n                    if (stagnation >= 2) break;\n                }\n            }\n        }\n\n        return st;\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    vector<pair<int,int>> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].first >> pts[i].second;\n\n    Timer timer;\n    Solver solver(N, M, pts);\n\n    auto best = solver.initial_state();\n    long long bestScore = solver.calc_score(best);\n\n    int iter = 0;\n    while (timer.elapsed() < 4.75) {\n        double remain = 4.80 - timer.elapsed();\n        if (remain < 0.12) break;\n\n        int mode = iter % 4;\n        double slice = min(remain, iter < 4 ? 0.9 : 0.55);\n        uint64_t seed = 1234567ULL + 100003ULL * iter + 10000019ULL * mode;\n\n        auto st = solver.run_one(mode, seed, timer.elapsed() + slice, timer);\n        long long sc = solver.calc_score(st);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = move(st);\n        }\n        iter++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (auto &op : best.ops) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << ' '\n             << op.x3 << ' ' << op.y3 << ' '\n             << op.x4 << ' ' << op.y4 << '\\n';\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\n\nstruct Pos {\n    int r, c;\n};\n\nstruct Board {\n    uint8_t a[N][N];\n\n    Board() { memset(a, 0, sizeof(a)); }\n\n    inline int occupied() const {\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cnt += (a[i][j] != 0);\n        return cnt;\n    }\n\n    inline void place_by_index(int p, int flavor) {\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) {\n                cnt++;\n                if (cnt == p) {\n                    a[i][j] = (uint8_t)flavor;\n                    return;\n                }\n            }\n        }\n        assert(false);\n    }\n\n    inline vector<Pos> empty_cells_ordered() const {\n        vector<Pos> res;\n        res.reserve(100 - occupied());\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) res.push_back({i, j});\n        }\n        return res;\n    }\n\n    inline Board tilted(char dir) const {\n        Board b;\n        if (dir == 'L') {\n            for (int i = 0; i < N; i++) {\n                int t = 0;\n                for (int j = 0; j < N; j++) if (a[i][j]) b.a[i][t++] = a[i][j];\n            }\n        } else if (dir == 'R') {\n            for (int i = 0; i < N; i++) {\n                int t = N - 1;\n                for (int j = N - 1; j >= 0; j--) if (a[i][j]) b.a[i][t--] = a[i][j];\n            }\n        } else if (dir == 'F') {\n            for (int j = 0; j < N; j++) {\n                int t = 0;\n                for (int i = 0; i < N; i++) if (a[i][j]) b.a[t++][j] = a[i][j];\n            }\n        } else if (dir == 'B') {\n            for (int j = 0; j < N; j++) {\n                int t = N - 1;\n                for (int i = N - 1; i >= 0; i--) if (a[i][j]) b.a[t--][j] = a[i][j];\n            }\n        } else {\n            assert(false);\n        }\n        return b;\n    }\n\n    inline long long component_square_sum() const {\n        bool vis[N][N];\n        memset(vis, 0, sizeof(vis));\n        static const int dr[4] = {-1, 1, 0, 0};\n        static const int dc[4] = {0, 0, -1, 1};\n        long long res = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (!a[i][j] || vis[i][j]) continue;\n            int col = a[i][j];\n            int sz = 0;\n            queue<pair<int,int>> q;\n            q.push({i,j});\n            vis[i][j] = true;\n            while (!q.empty()) {\n                auto [r,c] = q.front(); q.pop();\n                sz++;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (!vis[nr][nc] && a[nr][nc] == col) {\n                        vis[nr][nc] = true;\n                        q.push({nr,nc});\n                    }\n                }\n            }\n            res += 1LL * sz * sz;\n        }\n        return res;\n    }\n};\n\nstruct Solver {\n    vector<int> f;\n    int totalCnt[4]{};\n    Pos anchor[4];\n    mt19937 rng;\n\n    Solver(const vector<int>& flavors) : f(flavors), rng(123456789) {\n        for (int x : f) totalCnt[x]++;\n        choose_anchors();\n    }\n\n    void choose_anchors() {\n        // Use 3 distinct corners, assigning larger flavors farther apart.\n        vector<Pos> corners = {{0,0}, {0,9}, {9,0}, {9,9}};\n        vector<int> ord = {1,2,3};\n        sort(ord.begin(), ord.end(), [&](int x, int y) { return totalCnt[x] > totalCnt[y]; });\n\n        long long best = LLONG_MIN;\n        array<int,3> bestIdx = {0,1,2};\n        for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (j != i)\n        for (int k = 0; k < 4; k++) if (k != i && k != j) {\n            auto dist = [&](Pos a, Pos b) {\n                return abs(a.r - b.r) + abs(a.c - b.c);\n            };\n            long long s = 0;\n            s += 1LL * totalCnt[ord[0]] * totalCnt[ord[1]] * dist(corners[i], corners[j]);\n            s += 1LL * totalCnt[ord[0]] * totalCnt[ord[2]] * dist(corners[i], corners[k]);\n            s += 1LL * totalCnt[ord[1]] * totalCnt[ord[2]] * dist(corners[j], corners[k]);\n            if (s > best) {\n                best = s;\n                bestIdx = {i,j,k};\n            }\n        }\n        anchor[ord[0]] = corners[bestIdx[0]];\n        anchor[ord[1]] = corners[bestIdx[1]];\n        anchor[ord[2]] = corners[bestIdx[2]];\n    }\n\n    double evaluate(const Board& b, int turn) const {\n        double score = 0.0;\n\n        // True objective proxy\n        long long comp = b.component_square_sum();\n        score += 3000.0 * comp;\n\n        // Neighbor interactions\n        int sameAdj = 0, diffAdj = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j]) {\n            if (i + 1 < N && b.a[i+1][j]) {\n                if (b.a[i+1][j] == b.a[i][j]) sameAdj++;\n                else diffAdj++;\n            }\n            if (j + 1 < N && b.a[i][j+1]) {\n                if (b.a[i][j+1] == b.a[i][j]) sameAdj++;\n                else diffAdj++;\n            }\n        }\n        score += 280.0 * sameAdj;\n        score -= 180.0 * diffAdj;\n\n        // Per-flavor compactness and separation\n        for (int col = 1; col <= 3; col++) {\n            int cnt = 0;\n            int minr = N, maxr = -1, minc = N, maxc = -1;\n            long long sumDistAnchor = 0;\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j] == col) {\n                cnt++;\n                minr = min(minr, i);\n                maxr = max(maxr, i);\n                minc = min(minc, j);\n                maxc = max(maxc, j);\n                sumDistAnchor += abs(i - anchor[col].r) + abs(j - anchor[col].c);\n            }\n            if (cnt > 0) {\n                int area = (maxr - minr + 1) * (maxc - minc + 1);\n                // Compact blobs are good\n                score -= 25.0 * area;\n                // Mild anchor guidance, especially early\n                double w = (turn <= 35 ? 20.0 : turn <= 70 ? 12.0 : 5.0);\n                score -= w * sumDistAnchor;\n            }\n        }\n\n        // Row/column purity\n        for (int i = 0; i < N; i++) {\n            int cnt[4] = {};\n            for (int j = 0; j < N; j++) cnt[b.a[i][j]]++;\n            score += 18.0 * (cnt[1]*cnt[1] + cnt[2]*cnt[2] + cnt[3]*cnt[3]);\n        }\n        for (int j = 0; j < N; j++) {\n            int cnt[4] = {};\n            for (int i = 0; i < N; i++) cnt[b.a[i][j]]++;\n            score += 18.0 * (cnt[1]*cnt[1] + cnt[2]*cnt[2] + cnt[3]*cnt[3]);\n        }\n\n        // Reward border packing a little, useful under repeated compressions\n        int border = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j]) {\n            if (i == 0 || i == 9 || j == 0 || j == 9) border++;\n        }\n        score += 10.0 * border;\n\n        return score;\n    }\n\n    vector<int> sample_indices(int m, int limit) {\n        vector<int> ids;\n        if (m <= limit) {\n            ids.resize(m);\n            iota(ids.begin(), ids.end(), 0);\n            return ids;\n        }\n\n        // deterministic spread + a few pseudo-random points\n        set<int> used;\n        for (int s = 0; s < limit / 2; s++) {\n            int idx = (long long)s * m / max(1, limit / 2);\n            idx = min(idx, m - 1);\n            used.insert(idx);\n        }\n        while ((int)used.size() < limit) {\n            used.insert((int)(rng() % m));\n        }\n        ids.assign(used.begin(), used.end());\n        return ids;\n    }\n\n    struct Node {\n        Board b;\n        double val;\n    };\n\n    double rollout_value(const Board& start, int turn) {\n        // Simulate expected future using beam search with sampled insertions.\n        // turn = current real turn (1-based), board is after applying a candidate current move.\n        // Future starts from turn+1.\n        if (turn >= 100) return evaluate(start, turn);\n\n        int rem = 100 - turn;\n        int depth, beamW, sampleW;\n        if (turn <= 25) {\n            depth = 5; beamW = 10; sampleW = 3;\n        } else if (turn <= 60) {\n            depth = 6; beamW = 12; sampleW = 4;\n        } else if (turn <= 85) {\n            depth = 7; beamW = 10; sampleW = 4;\n        } else {\n            depth = min(10, rem);\n            beamW = 8;\n            sampleW = 5;\n        }\n        depth = min(depth, rem);\n\n        static const char dirs[4] = {'F','B','L','R'};\n        vector<Node> beam;\n        beam.push_back({start, evaluate(start, turn)});\n\n        for (int d = 0; d < depth; d++) {\n            int futureTurn = turn + d + 1;       // actual turn index of inserted candy\n            int flavor = f[futureTurn - 1];      // 0-based\n            vector<Node> cand;\n            cand.reserve(beam.size() * sampleW * 4);\n\n            for (const Node& node : beam) {\n                vector<Pos> empties = node.b.empty_cells_ordered();\n                int m = (int)empties.size();\n                if (m == 0) {\n                    cand.push_back(node);\n                    continue;\n                }\n\n                vector<int> ids = sample_indices(m, min(sampleW, m));\n                for (int id : ids) {\n                    Board placed = node.b;\n                    placed.a[empties[id].r][empties[id].c] = (uint8_t)flavor;\n\n                    for (char mv : dirs) {\n                        Board nb = placed.tilted(mv);\n                        double v = evaluate(nb, futureTurn);\n                        // tiny stabilization bias\n                        if (mv == 'F') v += 0.02;\n                        else if (mv == 'L') v += 0.015;\n                        else if (mv == 'R') v += 0.01;\n                        cand.push_back({nb, v});\n                    }\n                }\n            }\n\n            if (cand.empty()) break;\n\n            nth_element(cand.begin(), cand.begin() + min((int)cand.size(), beamW), cand.end(),\n                        [](const Node& x, const Node& y){ return x.val > y.val; });\n            if ((int)cand.size() > beamW) cand.resize(beamW);\n            beam.swap(cand);\n        }\n\n        double best = -1e100;\n        for (const auto& node : beam) best = max(best, node.val);\n        return best;\n    }\n\n    char decide(const Board& board, int turn) {\n        static const char dirs[4] = {'F','B','L','R'};\n\n        char bestDir = 'F';\n        double bestScore = -1e100;\n\n        // Search intensity by phase\n        bool doRollout = true;\n        if (turn <= 8) doRollout = false; // early state too random, greedy is okay\n\n        for (char d : dirs) {\n            Board tb = board.tilted(d);\n            double sc = evaluate(tb, turn);\n\n            if (doRollout) {\n                double rv = rollout_value(tb, turn);\n                // Mix local and future estimates\n                double alpha;\n                if (turn <= 25) alpha = 0.35;\n                else if (turn <= 70) alpha = 0.25;\n                else alpha = 0.15;\n                sc = alpha * sc + (1.0 - alpha) * rv;\n            }\n\n            // tie-break\n            if (d == 'F') sc += 0.003;\n            else if (d == 'L') sc += 0.002;\n            else if (d == 'R') sc += 0.001;\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = d;\n            }\n        }\n        return bestDir;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Solver solver(f);\n    Board board;\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n\n        board.place_by_index(p, f[t - 1]);\n        char ans = solver.decide(board, t);\n        board = board.tilted(ans);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic string make_threshold_graph(int N, int x) {\n    // vertices [0, x) are universal, [x, N) form independent set\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((i < x || j < x) ? '1' : '0');\n        }\n    }\n    return s;\n}\n\nstatic vector<int> get_sorted_degrees(int N, const string& g, int &edge_cnt) {\n    vector<int> deg(N, 0);\n    edge_cnt = 0;\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[p++] == '1') {\n                deg[i]++;\n                deg[j]++;\n                edge_cnt++;\n            }\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    // Gap between neighboring codewords in x-space.\n    // Larger gap for larger noise.\n    int gap;\n    if (eps <= 0.02) gap = 1;\n    else if (eps <= 0.05) gap = 2;\n    else if (eps <= 0.10) gap = 3;\n    else if (eps <= 0.15) gap = 4;\n    else if (eps <= 0.20) gap = 5;\n    else if (eps <= 0.25) gap = 6;\n    else if (eps <= 0.30) gap = 7;\n    else if (eps <= 0.35) gap = 8;\n    else gap = 9;\n\n    int N = (M - 1) * gap + 1;\n    N = max(N, 4);\n    N = min(N, 100);\n\n    vector<int> xs(M);\n    if (M == 1) {\n        xs[0] = 0;\n    } else {\n        for (int k = 0; k < M; k++) {\n            xs[k] = (long long)k * (N - 1) / (M - 1);\n        }\n        for (int k = 1; k < M; k++) {\n            if (xs[k] <= xs[k - 1]) xs[k] = xs[k - 1] + 1;\n        }\n        for (int k = M - 2; k >= 0; k--) {\n            if (xs[k] >= xs[k + 1]) xs[k] = xs[k + 1] - 1;\n        }\n        for (int k = 0; k < M; k++) {\n            xs[k] = max(0, min(N, xs[k]));\n        }\n    }\n\n    vector<string> G(M);\n    vector<double> exp_edges(M, 0.0);\n    vector<double> exp_low(M, 0.0), exp_high(M, 0.0);\n\n    for (int k = 0; k < M; k++) {\n        int x = xs[k];\n        G[k] = make_threshold_graph(N, x);\n\n        double m0 = 1.0 * x * (2 * N - x - 1) / 2.0;\n        double total = 1.0 * N * (N - 1) / 2.0;\n        exp_edges[k] = m0 * (1.0 - eps) + (total - m0) * eps;\n\n        exp_low[k] = x * (1.0 - eps) + (N - 1 - x) * eps;\n        exp_high[k] = (N - 1) * (1.0 - eps);\n    }\n\n    cout << N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << G[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        int edges = 0;\n        vector<int> deg = get_sorted_degrees(N, H, edges);\n\n        int best = 0;\n        double best_score = 1e100;\n\n        for (int k = 0; k < M; k++) {\n            int x = xs[k];\n            int low_cnt = N - x;\n            int high_cnt = x;\n\n            double score = 0.0;\n\n            for (int i = 0; i < low_cnt; i++) {\n                double d = deg[i] - exp_low[k];\n                score += d * d;\n            }\n            for (int i = low_cnt; i < N; i++) {\n                double d = deg[i] - exp_high[k];\n                score += d * d;\n            }\n\n            double ed = edges - exp_edges[k];\n            score += 0.6 * ed * ed;\n\n            if (score < best_score) {\n                best_score = 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\nstatic const long long INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v, w;\n    int cell;\n    double imp = 0.0;\n};\n\nstruct Solver {\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<int> xs, ys;\n    vector<vector<pair<int,int>>> g; // to, edge id\n    int G = 6, C;\n\n    Timer timer;\n    mt19937 rng{123456789};\n\n    // assignment\n    vector<int> day_of;\n    vector<int> load;\n    vector<double> day_imp;\n    vector<vector<int>> by_day;\n\n    // sampled evaluation\n    vector<int> sample_roots;\n    vector<vector<long long>> base_dist;\n    vector<double> day_score;\n    double total_score = 0.0;\n\n    int get_cell(double x, double y) {\n        int gx = min(G - 1, max(0, (int)(x * G / 1001.0)));\n        int gy = min(G - 1, max(0, (int)(y * G / 1001.0)));\n        return gy * G + gx;\n    }\n\n    void read_input() {\n        cin >> N >> M >> D >> K;\n        edges.resize(M);\n        g.assign(N, {});\n        for (int i = 0; i < M; i++) {\n            int u, v, w;\n            cin >> u >> v >> w;\n            --u; --v;\n            edges[i] = {u, v, w, -1, 0.0};\n            g[u].push_back({v, i});\n            g[v].push_back({u, i});\n        }\n        xs.resize(N);\n        ys.resize(N);\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        C = G * G;\n        for (int i = 0; i < M; i++) {\n            double mx = 0.5 * (xs[edges[i].u] + xs[edges[i].v]);\n            double my = 0.5 * (ys[edges[i].u] + ys[edges[i].v]);\n            edges[i].cell = get_cell(mx, my);\n        }\n    }\n\n    void dijkstra_normal(int s, vector<long long>& dist, vector<int>* parent_e = nullptr) {\n        dist.assign(N, INF64);\n        vector<int> pe;\n        if (parent_e) pe.assign(N, -1);\n\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 [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    if (parent_e) pe[to] = ei;\n                    pq.push({nd, to});\n                } else if (parent_e && nd == dist[to] && (pe[to] == -1 || ei < pe[to])) {\n                    pe[to] = ei;\n                }\n            }\n        }\n        if (parent_e) *parent_e = move(pe);\n    }\n\n    void dijkstra_removed_day(int s, int removed_day, vector<long long>& dist) {\n        dist.assign(N, INF64);\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 [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                if (day_of[ei] == removed_day) continue;\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    }\n\n    void compute_importance() {\n        vector<int> roots;\n        roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n        roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n        roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n        roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n        for (int t = 0; (int)roots.size() < min(24, max(8, 2 * D)); t++) {\n            int r = (int)((1LL * t * 911382323 + 972663749) % N);\n            roots.push_back(r);\n        }\n        sort(roots.begin(), roots.end());\n        roots.erase(unique(roots.begin(), roots.end()), roots.end());\n\n        vector<double> imp(M, 0.0), vcen(N, 0.0);\n        vector<long long> dist;\n        vector<int> parent_e;\n\n        for (int s : roots) {\n            if (timer.elapsed() > 1.15) break;\n            dijkstra_normal(s, dist, &parent_e);\n\n            double sumd = 0.0;\n            for (int i = 0; i < N; i++) if (dist[i] < INF64 / 4) sumd += dist[i];\n            double inv = (sumd > 0 ? 1.0 / sumd : 0.0);\n\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                if (parent_e[v] != -1) {\n                    double add = 1.0 + 3.0 * (1.0 - dist[v] * inv);\n                    imp[parent_e[v]] += add;\n                }\n                if (dist[v] < INF64 / 4) {\n                    vcen[v] += (1.0 - dist[v] * inv);\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            int u = edges[i].u, v = edges[i].v;\n            double val = imp[i];\n            val += 0.12 * g[u].size() + 0.12 * g[v].size();\n            val += 1.1 * (vcen[u] + vcen[v]);\n            val += 0.000002 * edges[i].w;\n            edges[i].imp = val;\n        }\n    }\n\n    void rebuild_by_day() {\n        by_day.assign(D, {});\n        for (int i = 0; i < M; i++) by_day[day_of[i]].push_back(i);\n    }\n\n    void build_initial_solution() {\n        day_of.assign(M, -1);\n        load.assign(D, 0);\n        day_imp.assign(D, 0.0);\n\n        vector<vector<int>> cell_cnt(D, vector<int>(C, 0));\n        vector<vector<int>> vday_cnt(D, vector<int>(N, 0));\n\n        vector<int> ord(M);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n            return edges[a].w > edges[b].w;\n        });\n\n        // Phase 1: distribute top important edges round-robin as evenly as possible\n        int topT = min(M, D * 4);\n        for (int i = 0; i < topT; i++) {\n            int ei = ord[i];\n            double best = 1e100;\n            int bestd = -1;\n            for (int d = 0; d < D; d++) {\n                if (load[d] >= K) continue;\n                auto &e = edges[ei];\n                double cost = 0.0;\n                cost += 20.0 * load[d];\n                cost += 12.0 * cell_cnt[d][e.cell];\n                cost += 8.0 * (vday_cnt[d][e.u] + vday_cnt[d][e.v]);\n                cost += 1.0 * day_imp[d];\n                if (cost < best) {\n                    best = cost;\n                    bestd = d;\n                }\n            }\n            if (bestd == -1) {\n                for (int d = 0; d < D; d++) if (load[d] < K) { bestd = d; break; }\n            }\n            day_of[ei] = bestd;\n            load[bestd]++;\n            day_imp[bestd] += edges[ei].imp;\n            cell_cnt[bestd][edges[ei].cell]++;\n            vday_cnt[bestd][edges[ei].u]++;\n            vday_cnt[bestd][edges[ei].v]++;\n        }\n\n        // Phase 2: greedy fill the rest\n        int ptr = 0;\n        for (int rank = topT; rank < M; rank++) {\n            int ei = ord[rank];\n            double best = 1e100;\n            int bestd = -1;\n\n            for (int tt = 0; tt < D; tt++) {\n                int d = (ptr + tt) % D;\n                if (load[d] >= K) continue;\n                auto &e = edges[ei];\n\n                double cost = 0.0;\n                cost += 12.0 * load[d];\n                cost += 7.0 * cell_cnt[d][e.cell];\n                cost += 4.5 * (vday_cnt[d][e.u] + vday_cnt[d][e.v]);\n                cost += 0.35 * day_imp[d];\n                cost += 0.7 * e.imp * (day_imp[d] / (1.0 + load[d]));\n\n                if (cost < best) {\n                    best = cost;\n                    bestd = d;\n                }\n            }\n            ptr = (ptr + 1) % D;\n\n            if (bestd == -1) {\n                for (int d = 0; d < D; d++) if (load[d] < K) { bestd = d; break; }\n            }\n\n            day_of[ei] = bestd;\n            load[bestd]++;\n            day_imp[bestd] += edges[ei].imp;\n            cell_cnt[bestd][edges[ei].cell]++;\n            vday_cnt[bestd][edges[ei].u]++;\n            vday_cnt[bestd][edges[ei].v]++;\n        }\n\n        rebuild_by_day();\n    }\n\n    void choose_sample_roots() {\n        sample_roots.clear();\n        sample_roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n        sample_roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n        sample_roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n        sample_roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int a, int b) {\n            return g[a].size() > g[b].size();\n        });\n        for (int i = 0; i < min(2, N); i++) sample_roots.push_back(idx[i]);\n\n        sort(sample_roots.begin(), sample_roots.end());\n        sample_roots.erase(unique(sample_roots.begin(), sample_roots.end()), sample_roots.end());\n        if ((int)sample_roots.size() > 6) sample_roots.resize(6);\n    }\n\n    void precompute_base_dist() {\n        choose_sample_roots();\n        base_dist.assign(sample_roots.size(), vector<long long>());\n        for (int i = 0; i < (int)sample_roots.size(); i++) {\n            dijkstra_normal(sample_roots[i], base_dist[i]);\n        }\n    }\n\n    double eval_day(int day) {\n        vector<long long> dist;\n        double sum = 0.0;\n        for (int si = 0; si < (int)sample_roots.size(); si++) {\n            dijkstra_removed_day(sample_roots[si], day, dist);\n            for (int v = 0; v < N; v++) {\n                if (v == sample_roots[si]) continue;\n                long long bd = base_dist[si][v];\n                long long nd = dist[v];\n                if (nd >= INF64 / 4) nd = 1000000000LL;\n                sum += (double)(nd - bd);\n            }\n        }\n        return sum;\n    }\n\n    void init_scores() {\n        day_score.assign(D, 0.0);\n        total_score = 0.0;\n        for (int d = 0; d < D; d++) {\n            day_score[d] = eval_day(d);\n            total_score += day_score[d];\n        }\n    }\n\n    double move_surrogate(int ei, int from, int to) {\n        const auto &e = edges[ei];\n        double res = 0.0;\n        res += 20.0 * ((load[to] + 1) * (load[to] + 1) - load[to] * load[to]);\n        res -= 20.0 * (load[from] * load[from] - (load[from] - 1) * (load[from] - 1));\n        res += 0.03 * (((day_imp[to] + e.imp) * (day_imp[to] + e.imp)) - day_imp[to] * day_imp[to]);\n        res -= 0.03 * (day_imp[from] * day_imp[from] - ((day_imp[from] - e.imp) * (day_imp[from] - e.imp)));\n        return res;\n    }\n\n    void apply_move(int ei, int from, int to) {\n        day_of[ei] = to;\n        load[from]--;\n        load[to]++;\n        day_imp[from] -= edges[ei].imp;\n        day_imp[to] += edges[ei].imp;\n    }\n\n    void rollback_move(int ei, int from, int to) {\n        day_of[ei] = from;\n        load[from]++;\n        load[to]--;\n        day_imp[from] += edges[ei].imp;\n        day_imp[to] -= edges[ei].imp;\n    }\n\n    void apply_swap(int e1, int d1, int e2, int d2) {\n        day_of[e1] = d2;\n        day_of[e2] = d1;\n        day_imp[d1] += edges[e2].imp - edges[e1].imp;\n        day_imp[d2] += edges[e1].imp - edges[e2].imp;\n    }\n\n    void rollback_swap(int e1, int d1, int e2, int d2) {\n        day_of[e1] = d1;\n        day_of[e2] = d2;\n        day_imp[d1] += edges[e1].imp - edges[e2].imp;\n        day_imp[d2] += edges[e2].imp - edges[e1].imp;\n    }\n\n    void focused_improvement() {\n        // Improve worst day by trying to export some of its heaviest/most important edges.\n        for (int round = 0; round < 12 && timer.elapsed() < 4.4; round++) {\n            rebuild_by_day();\n            int worst = max_element(day_score.begin(), day_score.end()) - day_score.begin();\n            auto cand = by_day[worst];\n            if (cand.empty()) break;\n\n            sort(cand.begin(), cand.end(), [&](int a, int b) {\n                if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n                return edges[a].w > edges[b].w;\n            });\n\n            int tries = min<int>(12, cand.size());\n            bool improved = false;\n\n            for (int ii = 0; ii < tries && timer.elapsed() < 4.4; ii++) {\n                int ei = cand[ii];\n                int from = worst;\n\n                vector<int> days(D);\n                iota(days.begin(), days.end(), 0);\n                sort(days.begin(), days.end(), [&](int a, int b) {\n                    if (a == from) return false;\n                    if (b == from) return true;\n                    if (load[a] != load[b]) return load[a] < load[b];\n                    if (day_score[a] != day_score[b]) return day_score[a] < day_score[b];\n                    return day_imp[a] < day_imp[b];\n                });\n\n                for (int z = 0; z < min(D, 8) && timer.elapsed() < 4.4; z++) {\n                    int to = days[z];\n                    if (to == from || load[to] >= K) continue;\n\n                    apply_move(ei, from, to);\n                    double new_from = eval_day(from);\n                    double new_to = eval_day(to);\n                    double new_total = total_score - day_score[from] - day_score[to] + new_from + new_to;\n\n                    if (new_total < total_score) {\n                        total_score = new_total;\n                        day_score[from] = new_from;\n                        day_score[to] = new_to;\n                        improved = true;\n                        break;\n                    } else {\n                        rollback_move(ei, from, to);\n                    }\n                }\n                if (improved) break;\n            }\n            if (!improved) break;\n        }\n    }\n\n    void random_local_search() {\n        int iter = 0;\n        while (timer.elapsed() < 5.45) {\n            iter++;\n            if ((iter & 255) == 0) rebuild_by_day();\n\n            if ((rng() & 1) == 0) {\n                int ei = rng() % M;\n                int from = day_of[ei];\n                int to = rng() % D;\n                if (from == to || load[to] >= K) continue;\n\n                if (move_surrogate(ei, from, to) > 1000.0 && (rng() & 7)) continue;\n\n                apply_move(ei, from, to);\n                double new_from = eval_day(from);\n                double new_to = eval_day(to);\n                double new_total = total_score - day_score[from] - day_score[to] + new_from + new_to;\n\n                if (new_total <= total_score) {\n                    total_score = new_total;\n                    day_score[from] = new_from;\n                    day_score[to] = new_to;\n                } else {\n                    rollback_move(ei, from, to);\n                }\n            } else {\n                int d1 = rng() % D;\n                int d2 = rng() % D;\n                if (d1 == d2) continue;\n                if (by_day[d1].empty() || by_day[d2].empty()) continue;\n\n                int e1 = by_day[d1][rng() % by_day[d1].size()];\n                int e2 = by_day[d2][rng() % by_day[d2].size()];\n                if (e1 == e2) continue;\n                if (day_of[e1] != d1 || day_of[e2] != d2) continue;\n\n                double rough = move_surrogate(e1, d1, d2) + move_surrogate(e2, d2, d1);\n                if (rough > 2000.0 && (rng() & 7)) continue;\n\n                apply_swap(e1, d1, e2, d2);\n                double new_d1 = eval_day(d1);\n                double new_d2 = eval_day(d2);\n                double new_total = total_score - day_score[d1] - day_score[d2] + new_d1 + new_d2;\n\n                if (new_total <= total_score) {\n                    total_score = new_total;\n                    day_score[d1] = new_d1;\n                    day_score[d2] = new_d2;\n                } else {\n                    rollback_swap(e1, d1, e2, d2);\n                }\n            }\n        }\n    }\n\n    void repair_feasibility() {\n        rebuild_by_day();\n        vector<int> final_load(D, 0);\n        for (int i = 0; i < M; i++) final_load[day_of[i]]++;\n\n        for (int d = 0; d < D; d++) {\n            while (final_load[d] > K) {\n                int nd = -1;\n                for (int t = 0; t < D; t++) {\n                    if (final_load[t] < K) { nd = t; break; }\n                }\n                if (nd == -1) break;\n\n                bool moved = false;\n                for (int i = 0; i < M; i++) {\n                    if (day_of[i] == d) {\n                        day_of[i] = nd;\n                        final_load[d]--;\n                        final_load[nd]++;\n                        moved = true;\n                        break;\n                    }\n                }\n                if (!moved) break;\n            }\n        }\n    }\n\n    void solve() {\n        read_input();\n        compute_importance();\n        build_initial_solution();\n        precompute_base_dist();\n        init_scores();\n        focused_improvement();\n        random_local_search();\n        repair_feasibility();\n\n        for (int i = 0; i < M; i++) {\n            if (i) cout << ' ';\n            cout << day_of[i] + 1;\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}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DX6[6] = {1,-1,0,0,0,0};\nstatic const int DY6[6] = {0,0,1,-1,0,0};\nstatic const int DZ6[6] = {0,0,0,0,1,-1};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n} rng;\n\nstruct P3 {\n    int x, y, z;\n};\n\nstruct Rot {\n    int p[3];\n    int s[3];\n};\n\nstruct Piece {\n    vector<int> vox;\n    string sig;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int i = 0; i < D; i++) cin >> f[t][i];\n        for (int i = 0; i < D; i++) cin >> r[t][i];\n    }\n\n    auto idx = [&](int x, int y, int z) -> int {\n        return (x * D + y) * D + z;\n    };\n    auto inside = [&](int x, int y, int z) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D && 0 <= z && z < D;\n    };\n    auto decode = [&](int v) -> P3 {\n        int z = v % D;\n        int t = v / D;\n        int y = t % D;\n        int x = t / D;\n        return {x, y, z};\n    };\n\n    int N3 = D * D * D;\n\n    vector<Rot> rots;\n    {\n        vector<int> perm = {0,1,2};\n        do {\n            int sign_perm = 1;\n            for (int i = 0; i < 3; i++) for (int j = i + 1; j < 3; j++) {\n                if (perm[i] > perm[j]) sign_perm *= -1;\n            }\n            for (int sx : {-1, 1}) for (int sy : {-1, 1}) for (int sz : {-1, 1}) {\n                if (sign_perm * sx * sy * sz == 1) {\n                    Rot rt;\n                    rt.p[0] = perm[0];\n                    rt.p[1] = perm[1];\n                    rt.p[2] = perm[2];\n                    rt.s[0] = sx;\n                    rt.s[1] = sy;\n                    rt.s[2] = sz;\n                    rots.push_back(rt);\n                }\n            }\n        } while (next_permutation(perm.begin(), perm.end()));\n    }\n\n    auto rotate_point = [&](const P3& a, const Rot& rt) -> P3 {\n        int v[3] = {a.x, a.y, a.z};\n        return P3{\n            rt.s[0] * v[rt.p[0]],\n            rt.s[1] * v[rt.p[1]],\n            rt.s[2] * v[rt.p[2]]\n        };\n    };\n\n    auto canonical_signature_from_vox = [&](const vector<int>& vox) -> string {\n        vector<P3> cells;\n        cells.reserve(vox.size());\n        int minx = 1e9, miny = 1e9, minz = 1e9;\n        for (int v : vox) {\n            auto p = decode(v);\n            minx = min(minx, p.x);\n            miny = min(miny, p.y);\n            minz = min(minz, p.z);\n            cells.push_back(p);\n        }\n        for (auto &p : cells) {\n            p.x -= minx;\n            p.y -= miny;\n            p.z -= minz;\n        }\n\n        string best;\n        bool first = true;\n        for (const auto& rt : rots) {\n            vector<array<int,3>> q;\n            q.reserve(cells.size());\n            int bx = 1e9, by = 1e9, bz = 1e9;\n            for (auto &p : cells) {\n                P3 t = rotate_point(p, rt);\n                bx = min(bx, t.x);\n                by = min(by, t.y);\n                bz = min(bz, t.z);\n                q.push_back({t.x, t.y, t.z});\n            }\n            for (auto &a : q) {\n                a[0] -= bx;\n                a[1] -= by;\n                a[2] -= bz;\n            }\n            sort(q.begin(), q.end());\n            string s;\n            s.reserve(q.size() * 12);\n            for (auto &a : q) {\n                s += to_string(a[0]);\n                s.push_back(',');\n                s += to_string(a[1]);\n                s.push_back(',');\n                s += to_string(a[2]);\n                s.push_back(';');\n            }\n            if (first || s < best) {\n                best = move(s);\n                first = false;\n            }\n        }\n        return best;\n    };\n\n    auto initial_build = [&](int t) -> vector<char> {\n        vector<char> occ(N3, 0);\n        for (int z = 0; z < D; z++) {\n            vector<int> X, Y;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') X.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') Y.push_back(y);\n            int a = (int)X.size(), b = (int)Y.size();\n            if (a == 0 || b == 0) continue;\n            if (a <= b) {\n                for (int i = 0; i < a; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = a; i < b; i++) occ[idx(X[0], Y[i], z)] = 1;\n            } else {\n                for (int i = 0; i < b; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = b; i < a; i++) occ[idx(X[i], Y[0], z)] = 1;\n            }\n        }\n        return occ;\n    };\n\n    auto build_object = [&](int cur, const vector<char>& refOcc, const vector<char>& selfHint) -> vector<char> {\n        vector<char> occ(N3, 0);\n\n        for (int z = 0; z < D; z++) {\n            vector<int> X, Y;\n            for (int x = 0; x < D; x++) if (f[cur][z][x] == '1') X.push_back(x);\n            for (int y = 0; y < D; y++) if (r[cur][z][y] == '1') Y.push_back(y);\n            int a = (int)X.size(), b = (int)Y.size();\n            if (a == 0 || b == 0) continue;\n\n            vector<pair<int,int>> bestCells;\n            long long bestScore = LLONG_MIN;\n\n            int trials = (D <= 7 ? 140 : (D <= 10 ? 100 : 70));\n            for (int tr = 0; tr < trials; tr++) {\n                vector<int> px = X, py = Y;\n                shuffle(px.begin(), px.end(), std::mt19937(rng.next_u32()));\n                shuffle(py.begin(), py.end(), std::mt19937(rng.next_u32()));\n\n                vector<pair<int,int>> cells;\n                int m = min(a, b);\n                for (int i = 0; i < m; i++) cells.push_back({px[i], py[i]});\n\n                if (a > b) {\n                    int bestY = Y[0];\n                    long long bestYScore = LLONG_MIN;\n                    for (int candY : Y) {\n                        long long sc = 0;\n                        for (int i = b; i < a; i++) {\n                            int x = px[i];\n                            int id = idx(x, candY, z);\n                            if (refOcc[id]) sc += 24;\n                            if (selfHint[id]) sc += 12;\n                            if (z > 0 && occ[idx(x, candY, z-1)]) sc += 10;\n                            if (z + 1 < D && selfHint[idx(x, candY, z+1)]) sc += 4;\n                        }\n                        if (sc > bestYScore) bestYScore = sc, bestY = candY;\n                    }\n                    for (int i = b; i < a; i++) cells.push_back({px[i], bestY});\n                } else if (b > a) {\n                    int bestX = X[0];\n                    long long bestXScore = LLONG_MIN;\n                    for (int candX : X) {\n                        long long sc = 0;\n                        for (int j = a; j < b; j++) {\n                            int y = py[j];\n                            int id = idx(candX, y, z);\n                            if (refOcc[id]) sc += 24;\n                            if (selfHint[id]) sc += 12;\n                            if (z > 0 && occ[idx(candX, y, z-1)]) sc += 10;\n                            if (z + 1 < D && selfHint[idx(candX, y, z+1)]) sc += 4;\n                        }\n                        if (sc > bestXScore) bestXScore = sc, bestX = candX;\n                    }\n                    for (int j = a; j < b; j++) cells.push_back({bestX, py[j]});\n                }\n\n                unordered_set<int> S;\n                S.reserve(cells.size() * 2 + 10);\n                long long score = 0;\n                for (auto [x, y] : cells) {\n                    int id = idx(x, y, z);\n                    S.insert(id);\n                    if (refOcc[id]) score += 60;\n                    if (selfHint[id]) score += 25;\n                    if (z > 0 && occ[idx(x, y, z-1)]) score += 18;\n                    if (z + 1 < D && selfHint[idx(x, y, z+1)]) score += 5;\n                }\n                for (auto [x, y] : cells) {\n                    int cnt = 0;\n                    if (x > 0 && S.count(idx(x-1, y, z))) cnt++;\n                    if (x + 1 < D && S.count(idx(x+1, y, z))) cnt++;\n                    if (y > 0 && S.count(idx(x, y-1, z))) cnt++;\n                    if (y + 1 < D && S.count(idx(x, y+1, z))) cnt++;\n                    score += 7LL * cnt;\n                }\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    bestCells = move(cells);\n                }\n            }\n\n            for (auto [x, y] : bestCells) occ[idx(x, y, z)] = 1;\n        }\n        return occ;\n    };\n\n    auto overlap_score = [&](const vector<char>& a, const vector<char>& b) -> int {\n        int s = 0;\n        for (int i = 0; i < N3; i++) if (a[i] && b[i]) s++;\n        return s;\n    };\n\n    vector<char> occ0 = initial_build(0);\n    vector<char> occ1 = initial_build(1);\n\n    for (int iter = 0; iter < 8; iter++) {\n        auto n0 = build_object(0, occ1, occ0);\n        auto n1 = build_object(1, n0, occ1);\n        int cur = overlap_score(occ0, occ1);\n        int nxt = overlap_score(n0, n1);\n        if (nxt >= cur) {\n            occ0.swap(n0);\n            occ1.swap(n1);\n        } else {\n            auto m1 = build_object(1, occ0, occ1);\n            auto m0 = build_object(0, m1, occ0);\n            int alt = overlap_score(m0, m1);\n            if (alt > cur) {\n                occ0.swap(m0);\n                occ1.swap(m1);\n            }\n        }\n    }\n\n    auto extract_straight_runs = [&](vector<char>& alive, vector<Piece>& pieces) {\n        while (true) {\n            int bestLen = 0;\n            vector<int> bestVox;\n\n            for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n                int s = idx(x, y, z);\n                if (!alive[s]) continue;\n\n                if (x == 0 || !alive[idx(x-1, y, z)]) {\n                    vector<int> cur;\n                    for (int nx = x; nx < D && alive[idx(nx, y, z)]; nx++) cur.push_back(idx(nx, y, z));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n                if (y == 0 || !alive[idx(x, y-1, z)]) {\n                    vector<int> cur;\n                    for (int ny = y; ny < D && alive[idx(x, ny, z)]; ny++) cur.push_back(idx(x, ny, z));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n                if (z == 0 || !alive[idx(x, y, z-1)]) {\n                    vector<int> cur;\n                    for (int nz = z; nz < D && alive[idx(x, y, nz)]; nz++) cur.push_back(idx(x, y, nz));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n            }\n\n            if (bestLen < 2) break;\n\n            Piece pc;\n            pc.vox = bestVox;\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n            for (int v : bestVox) alive[v] = 0;\n        }\n    };\n\n    auto get_neighbors_alive = [&](const vector<char>& alive, int v, vector<int>& nbrs) {\n        nbrs.clear();\n        auto p = decode(v);\n        for (int dir = 0; dir < 6; dir++) {\n            int nx = p.x + DX6[dir];\n            int ny = p.y + DY6[dir];\n            int nz = p.z + DZ6[dir];\n            if (!inside(nx, ny, nz)) continue;\n            int to = idx(nx, ny, nz);\n            if (alive[to]) nbrs.push_back(to);\n        }\n    };\n\n    auto bfs_farthest = [&](const vector<char>& alive, int start, const vector<int>* restrictSet,\n                            vector<int>& parent, vector<int>& dist, const vector<int>& mark) -> int {\n        fill(parent.begin(), parent.end(), -1);\n        fill(dist.begin(), dist.end(), -1);\n        queue<int> q;\n        q.push(start);\n        dist[start] = 0;\n        int best = start;\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            if (dist[v] > dist[best]) best = v;\n            auto p = decode(v);\n            for (int dir = 0; dir < 6; dir++) {\n                int nx = p.x + DX6[dir];\n                int ny = p.y + DY6[dir];\n                int nz = p.z + DZ6[dir];\n                if (!inside(nx, ny, nz)) continue;\n                int to = idx(nx, ny, nz);\n                if (!alive[to]) continue;\n                if (restrictSet && !mark[to]) continue;\n                if (dist[to] == -1) {\n                    dist[to] = dist[v] + 1;\n                    parent[to] = v;\n                    q.push(to);\n                }\n            }\n        }\n        return best;\n    };\n\n    auto extract_paths = [&](vector<char>& alive, vector<Piece>& pieces) {\n        vector<char> vis(N3, 0);\n        vector<int> comp;\n        vector<int> parent(N3), dist(N3), mark(N3, 0);\n\n        while (true) {\n            int seed = -1;\n            for (int i = 0; i < N3; i++) if (alive[i]) { seed = i; break; }\n            if (seed == -1) break;\n\n            // find one connected component in alive\n            comp.clear();\n            queue<int> q;\n            q.push(seed);\n            vis.assign(N3, 0);\n            vis[seed] = 1;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                comp.push_back(v);\n                auto p = decode(v);\n                for (int dir = 0; dir < 6; dir++) {\n                    int nx = p.x + DX6[dir];\n                    int ny = p.y + DY6[dir];\n                    int nz = p.z + DZ6[dir];\n                    if (!inside(nx, ny, nz)) continue;\n                    int to = idx(nx, ny, nz);\n                    if (alive[to] && !vis[to]) {\n                        vis[to] = 1;\n                        q.push(to);\n                    }\n                }\n            }\n\n            if ((int)comp.size() <= 1) {\n                break; // path extraction can't improve singleton-only tail much\n            }\n\n            for (int v : comp) mark[v] = 1;\n\n            bool extracted_any = false;\n            while (true) {\n                int start = -1;\n                int bestDeg = 100;\n                for (int v : comp) if (alive[v]) {\n                    int deg = 0;\n                    auto p = decode(v);\n                    for (int dir = 0; dir < 6; dir++) {\n                        int nx = p.x + DX6[dir];\n                        int ny = p.y + DY6[dir];\n                        int nz = p.z + DZ6[dir];\n                        if (!inside(nx, ny, nz)) continue;\n                        int to = idx(nx, ny, nz);\n                        if (alive[to] && mark[to]) deg++;\n                    }\n                    if (deg < bestDeg) {\n                        bestDeg = deg;\n                        start = v;\n                    }\n                }\n                if (start == -1) break;\n\n                int a = bfs_farthest(alive, start, &comp, parent, dist, mark);\n                int b = bfs_farthest(alive, a, &comp, parent, dist, mark);\n                if (dist[b] < 1) break; // path length 1 voxel only\n\n                vector<int> path;\n                for (int v = b; v != -1; v = parent[v]) path.push_back(v);\n\n                if ((int)path.size() < 2) break;\n\n                Piece pc;\n                pc.vox = path;\n                pc.sig = canonical_signature_from_vox(pc.vox);\n                pieces.push_back(move(pc));\n                for (int v : path) alive[v] = 0;\n                extracted_any = true;\n\n                bool hasMore = false;\n                for (int v : comp) if (alive[v]) { hasMore = true; break; }\n                if (!hasMore) break;\n            }\n\n            for (int v : comp) mark[v] = 0;\n            if (!extracted_any) {\n                // if nothing extracted from this component, zero out mark and continue\n                // residual handling will take care later\n                // but to avoid looping on same seed, remove one voxel from consideration here? no:\n                // outer loop will revisit, so break and let residual phase handle all\n                break;\n            }\n        }\n    };\n\n    auto residual_components = [&](const vector<char>& alive, vector<Piece>& pieces) {\n        vector<char> vis(N3, 0);\n        for (int i = 0; i < N3; i++) {\n            if (!alive[i] || vis[i]) continue;\n            queue<int> q;\n            q.push(i);\n            vis[i] = 1;\n            vector<int> vox;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                vox.push_back(v);\n                auto p = decode(v);\n                for (int dir = 0; dir < 6; dir++) {\n                    int nx = p.x + DX6[dir];\n                    int ny = p.y + DY6[dir];\n                    int nz = p.z + DZ6[dir];\n                    if (!inside(nx, ny, nz)) continue;\n                    int to = idx(nx, ny, nz);\n                    if (alive[to] && !vis[to]) {\n                        vis[to] = 1;\n                        q.push(to);\n                    }\n                }\n            }\n            Piece pc;\n            pc.vox = move(vox);\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n        }\n    };\n\n    auto decompose = [&](const vector<char>& occ) -> vector<Piece> {\n        vector<char> alive = occ;\n        vector<Piece> pieces;\n\n        extract_straight_runs(alive, pieces);\n        extract_paths(alive, pieces);\n        residual_components(alive, pieces);\n\n        return pieces;\n    };\n\n    auto pieces0 = decompose(occ0);\n    auto pieces1 = decompose(occ1);\n\n    unordered_map<string, vector<int>> mp0, mp1;\n    mp0.reserve(pieces0.size() * 2 + 10);\n    mp1.reserve(pieces1.size() * 2 + 10);\n\n    for (int i = 0; i < (int)pieces0.size(); i++) mp0[pieces0[i].sig].push_back(i);\n    for (int i = 0; i < (int)pieces1.size(); i++) mp1[pieces1[i].sig].push_back(i);\n\n    for (auto &kv : mp0) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            return pieces0[a].vox.size() > pieces0[b].vox.size();\n        });\n    }\n    for (auto &kv : mp1) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            return pieces1[a].vox.size() > pieces1[b].vox.size();\n        });\n    }\n\n    vector<int> ans0(N3, 0), ans1(N3, 0);\n    int nBlocks = 0;\n\n    unordered_set<string> keys;\n    keys.reserve(mp0.size() + mp1.size() + 10);\n    for (auto &kv : mp0) keys.insert(kv.first);\n    for (auto &kv : mp1) keys.insert(kv.first);\n\n    for (const string &sig : keys) {\n        auto it0 = mp0.find(sig);\n        auto it1 = mp1.find(sig);\n        vector<int>* v0 = (it0 == mp0.end() ? nullptr : &it0->second);\n        vector<int>* v1 = (it1 == mp1.end() ? nullptr : &it1->second);\n\n        int c0 = v0 ? (int)v0->size() : 0;\n        int c1 = v1 ? (int)v1->size() : 0;\n        int m = min(c0, c1);\n\n        for (int i = 0; i < m; i++) {\n            ++nBlocks;\n            for (int id : pieces0[(*v0)[i]].vox) ans0[id] = nBlocks;\n            for (int id : pieces1[(*v1)[i]].vox) ans1[id] = nBlocks;\n        }\n        if (v0) {\n            for (int i = m; i < c0; i++) {\n                ++nBlocks;\n                for (int id : pieces0[(*v0)[i]].vox) ans0[id] = nBlocks;\n            }\n        }\n        if (v1) {\n            for (int i = m; i < c1; i++) {\n                ++nBlocks;\n                for (int id : pieces1[(*v1)[i]].vox) ans1[id] = nBlocks;\n            }\n        }\n    }\n\n    cout << nBlocks << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << ans0[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << ans1[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v, w;\n};\n\nstruct DijkstraResult {\n    vector<ll> dist;\n    vector<int> prev_v;\n    vector<int> prev_e;\n};\n\nstatic inline ll sqrll(ll x) { return x * x; }\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        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        g[u].push_back({v, i});\n        g[v].push_back({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    // reqR[v][k] = minimum radius needed; 5001 if impossible\n    vector<vector<unsigned short>> reqR(N, vector<unsigned short>(K));\n    vector<vector<pair<unsigned short,int>>> sortedReq(N);\n\n    for (int v = 0; v < N; v++) {\n        sortedReq[v].reserve(K);\n        for (int k = 0; k < K; k++) {\n            ll dx = (ll)x[v] - a[k];\n            ll dy = (ll)y[v] - b[k];\n            long double d = sqrt((long double)dx * dx + (long double)dy * dy);\n            int r = (int)ceill(d - 1e-12L);\n            if (r > 5000) r = 5001;\n            reqR[v][k] = (unsigned short)r;\n            if (r <= 5000) sortedReq[v].push_back({(unsigned short)r, k});\n        }\n        sort(sortedReq[v].begin(), sortedReq[v].end());\n    }\n\n    auto dijkstra = [&](int s) -> DijkstraResult {\n        vector<ll> dist(N, INF64);\n        vector<int> prev_v(N, -1), prev_e(N, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top();\n            pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                ll nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    prev_v[to] = v;\n                    prev_e[to] = ei;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        return {dist, prev_v, prev_e};\n    };\n\n    vector<vector<ll>> allDist(N, vector<ll>(N));\n    vector<vector<int>> allPrevV(N), allPrevE(N);\n    for (int s = 0; s < N; s++) {\n        auto res = dijkstra(s);\n        allDist[s] = move(res.dist);\n        allPrevV[s] = move(res.prev_v);\n        allPrevE[s] = move(res.prev_e);\n    }\n\n    auto reconstruct_path = [&](int s, int t, vector<char>& edge_on, vector<char>& vert_on, vector<int>* addedVerts = nullptr) {\n        int cur = t;\n        while (cur != s) {\n            int ei = allPrevE[s][cur];\n            int pv = allPrevV[s][cur];\n            if (ei < 0 || pv < 0) break;\n            edge_on[ei] = 1;\n            if (!vert_on[cur]) {\n                vert_on[cur] = 1;\n                if (addedVerts) addedVerts->push_back(cur);\n            }\n            if (!vert_on[pv]) {\n                vert_on[pv] = 1;\n                if (addedVerts) addedVerts->push_back(pv);\n            }\n            cur = pv;\n        }\n    };\n\n    auto build_network_from_terminals = [&](const vector<int>& terminals) {\n        vector<int> ts = terminals;\n        ts.push_back(0);\n        sort(ts.begin(), ts.end());\n        ts.erase(unique(ts.begin(), ts.end()), ts.end());\n\n        int T = (int)ts.size();\n        vector<ll> mincost(T, INF64);\n        vector<int> parent(T, -1);\n        vector<char> used(T, 0);\n        mincost[0] = 0;\n\n        for (int it = 0; it < T; it++) {\n            int v = -1;\n            for (int i = 0; i < T; i++) if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int to = 0; to < T; to++) if (!used[to]) {\n                ll w = allDist[ts[v]][ts[to]];\n                if (w < mincost[to]) {\n                    mincost[to] = w;\n                    parent[to] = v;\n                }\n            }\n        }\n\n        vector<char> edge_on(M, 0), vert_on(N, 0);\n        vert_on[0] = 1;\n        for (int i = 1; i < T; i++) {\n            reconstruct_path(ts[i], ts[parent[i]], edge_on, vert_on);\n        }\n        return pair(edge_on, vert_on);\n    };\n\n    auto prune_edges = [&](const vector<char>& edge_on, const vector<int>& P) {\n        vector<vector<pair<int,int>>> sg(N);\n        for (int i = 0; i < M; i++) if (edge_on[i]) {\n            int u = edges[i].u, v = edges[i].v;\n            sg[u].push_back({v, i});\n            sg[v].push_back({u, i});\n        }\n\n        vector<char> needV(N, 0), vis(N, 0), keepE(M, 0);\n        needV[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) needV[i] = 1;\n\n        function<bool(int,int)> dfs = [&](int v, int pe) -> bool {\n            vis[v] = 1;\n            bool need = needV[v];\n            for (auto [to, ei] : sg[v]) {\n                if (ei == pe) continue;\n                if (!vis[to]) {\n                    if (dfs(to, ei)) {\n                        keepE[ei] = 1;\n                        need = true;\n                    }\n                }\n            }\n            return need;\n        };\n        dfs(0, -1);\n        return keepE;\n    };\n\n    auto calc_cost = [&](const vector<int>& P, const vector<char>& edge_on) -> ll {\n        ll S = 0;\n        for (int i = 0; i < N; i++) S += 1LL * P[i] * P[i];\n        for (int i = 0; i < M; i++) if (edge_on[i]) S += edges[i].w;\n        return S;\n    };\n\n    auto assign_best = [&](const vector<int>& stations) {\n        vector<int> P(N, 0);\n        if (stations.empty()) return P;\n        for (int k = 0; k < K; k++) {\n            int bestV = -1;\n            int bestR = 5001;\n            for (int v : stations) {\n                int r = reqR[v][k];\n                if (r < bestR) {\n                    bestR = r;\n                    bestV = v;\n                }\n            }\n            if (bestV != -1 && bestR <= 5000) {\n                P[bestV] = max(P[bestV], bestR);\n            }\n        }\n        return P;\n    };\n\n    auto one_pass_delete = [&](vector<int> P) {\n        vector<int> stations;\n        for (int i = 0; i < N; i++) if (P[i] > 0) stations.push_back(i);\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n\n            sort(stations.begin(), stations.end(), [&](int lhs, int rhs) {\n                return P[lhs] < P[rhs];\n            });\n\n            for (int idx = 0; idx < (int)stations.size(); idx++) {\n                int rem = stations[idx];\n                vector<int> cand;\n                cand.reserve(stations.size() - 1);\n                for (int v : stations) if (v != rem) cand.push_back(v);\n                if (cand.empty()) continue;\n\n                bool ok = true;\n                for (int k = 0; k < K; k++) {\n                    int bestR = 5001;\n                    for (int v : cand) {\n                        int r = reqR[v][k];\n                        if (r < bestR) bestR = r;\n                    }\n                    if (bestR > 5000) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n\n                vector<int> newP = assign_best(cand);\n                ll oldPower = 0, newPower = 0;\n                for (int i = 0; i < N; i++) oldPower += 1LL * P[i] * P[i];\n                for (int i = 0; i < N; i++) newPower += 1LL * newP[i] * newP[i];\n\n                if (newPower <= oldPower) {\n                    P.swap(newP);\n                    stations.swap(cand);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        return P;\n    };\n\n    auto greedy_construct = [&](double beta) {\n        vector<int> P(N, 0);\n        vector<char> covered(K, 0);\n        int coveredCnt = 0;\n\n        vector<char> connectedV(N, 0), edge_on(M, 0), vert_on(N, 0);\n        connectedV[0] = 1;\n        vert_on[0] = 1;\n        vector<int> terminals;\n\n        vector<ll> connCost(N, INF64);\n        for (int v = 0; v < N; v++) connCost[v] = allDist[0][v];\n\n        while (coveredCnt < K) {\n            int bestV = -1, bestR = -1;\n            double bestScore = -1.0;\n\n            for (int v = 0; v < N; v++) {\n                int gain = 0;\n                int prevR = -1;\n                double penalty = beta * (double)connCost[v];\n\n                for (auto [r, k] : sortedReq[v]) {\n                    if (!covered[k]) gain++;\n                    if (r != prevR) {\n                        if (gain > 0) {\n                            double cost = 1.0 * r * r + penalty;\n                            double score = (double)gain / cost;\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                        prevR = r;\n                    } else {\n                        if (gain > 0) {\n                            double cost = 1.0 * r * r + penalty;\n                            double score = (double)gain / cost;\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) break;\n\n            if (P[bestV] == 0) terminals.push_back(bestV);\n            P[bestV] = max(P[bestV], bestR);\n\n            for (auto [r, k] : sortedReq[bestV]) {\n                if (r > bestR) break;\n                if (!covered[k]) {\n                    covered[k] = 1;\n                    coveredCnt++;\n                }\n            }\n\n            if (!connectedV[bestV]) {\n                ll best = INF64;\n                int bestSrc = -1;\n                for (int s = 0; s < N; s++) if (connectedV[s]) {\n                    if (allDist[s][bestV] < best) {\n                        best = allDist[s][bestV];\n                        bestSrc = s;\n                    }\n                }\n                vector<int> addedVerts;\n                reconstruct_path(bestSrc, bestV, edge_on, vert_on, &addedVerts);\n                for (int vtx : addedVerts) connectedV[vtx] = 1;\n                connectedV[0] = 1;\n\n                // incremental update of connection costs\n                for (int nv : addedVerts) {\n                    for (int v = 0; v < N; v++) {\n                        if (allDist[nv][v] < connCost[v]) connCost[v] = allDist[nv][v];\n                    }\n                }\n            }\n        }\n\n        return tuple<vector<int>, vector<int>, vector<char>, vector<char>>(P, terminals, edge_on, vert_on);\n    };\n\n    auto recalc_cover_on_reachable = [&](const vector<char>& reachable) {\n        vector<int> P(N, 0);\n        vector<char> covered(K, 0);\n        int coveredCnt = 0;\n        vector<int> stations;\n\n        while (coveredCnt < K) {\n            int bestV = -1, bestR = -1;\n            double bestScore = -1.0;\n\n            for (int v = 0; v < N; v++) if (reachable[v]) {\n                int gain = 0;\n                int prevR = -1;\n                for (auto [r, k] : sortedReq[v]) {\n                    if (!covered[k]) gain++;\n                    if (r != prevR) {\n                        if (gain > 0) {\n                            double cost = 1.0 * r * r;\n                            double score = (double)gain / cost;\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                        prevR = r;\n                    } else {\n                        if (gain > 0) {\n                            double cost = 1.0 * r * r;\n                            double score = (double)gain / cost;\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) break;\n\n            if (P[bestV] == 0) stations.push_back(bestV);\n            P[bestV] = max(P[bestV], bestR);\n\n            for (auto [r, k] : sortedReq[bestV]) {\n                if (r > bestR) break;\n                if (!covered[k]) {\n                    covered[k] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        // exact tighten by best assignment among used stations\n        P = assign_best(stations);\n        return P;\n    };\n\n    ll bestCost = INF64;\n    vector<int> bestP(N, 0);\n    vector<char> bestB(M, 0);\n\n    const double betas[] = {0.10, 0.20, 0.35, 0.60};\n\n    for (double beta : betas) {\n        auto [P0, terminals0, edge0, vert0] = greedy_construct(beta);\n\n        auto [edge1, vert1] = build_network_from_terminals(terminals0);\n\n        vector<int> P1 = recalc_cover_on_reachable(vert1);\n\n        P1 = one_pass_delete(P1);\n\n        vector<int> powered;\n        for (int i = 0; i < N; i++) if (P1[i] > 0) powered.push_back(i);\n\n        auto [edge2, vert2] = build_network_from_terminals(powered);\n        auto edge3 = prune_edges(edge2, P1);\n\n        ll cost = calc_cost(P1, edge3);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestP = P1;\n            bestB = edge3;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestB[i] ? 1 : 0);\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 V = 465;\nstatic constexpr int MAXK = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; i++) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; j++) cin >> a[i][j];\n    }\n\n    vector<pair<int,int>> pos(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j <= i; j++) {\n            pos[a[i][j]] = {i, j};\n        }\n    }\n\n    vector<Op> ops;\n    ops.reserve(MAXK);\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y <= x;\n    };\n\n    auto neighbors = [&](int x, int y) {\n        array<pair<int,int>, 6> cand = {{\n            {x-1, y-1}, {x-1, y},\n            {x, y-1},   {x, y+1},\n            {x+1, y},   {x+1, y+1}\n        }};\n        vector<pair<int,int>> res;\n        for (auto [nx, ny] : cand) if (inside(nx, ny)) res.push_back({nx, ny});\n        return res;\n    };\n\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        if ((int)ops.size() >= MAXK) return;\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    };\n\n    auto get_path = [&](pair<int,int> s, pair<int,int> t) {\n        static int dist[N][N];\n        static pair<int,int> pre[N][N];\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j <= i; j++) {\n                dist[i][j] = -1;\n                pre[i][j] = {-1, -1};\n            }\n        }\n        queue<pair<int,int>> q;\n        dist[s.first][s.second] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            if (x == t.first && y == t.second) break;\n            for (auto [nx, ny] : neighbors(x, y)) {\n                if (dist[nx][ny] != -1) continue;\n                dist[nx][ny] = dist[x][y] + 1;\n                pre[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n        vector<pair<int,int>> path;\n        if (dist[t.first][t.second] == -1) return path;\n        pair<int,int> cur = t;\n        while (!(cur == s)) {\n            path.push_back(cur);\n            cur = pre[cur.first][cur.second];\n        }\n        path.push_back(s);\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    // Initial constructive phase: same spirit as the best previous version.\n    vector<char> fixedv(V, 0);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if ((int)ops.size() >= MAXK) break;\n\n            int bestVal = INT_MAX;\n            pair<int,int> bestPos = {-1, -1};\n\n            for (int i = x; i < N; i++) {\n                int j0 = (i == x ? y : 0);\n                for (int j = j0; j <= i; j++) {\n                    int v = a[i][j];\n                    if (!fixedv[v] && v < bestVal) {\n                        bestVal = v;\n                        bestPos = {i, j};\n                    }\n                }\n            }\n\n            if (bestPos.first == -1) continue;\n\n            auto path = get_path(bestPos, {x, y});\n            if (path.empty()) continue;\n\n            // Execute reversely so the chosen ball moves to target.\n            for (int k = (int)path.size() - 1; k >= 1; k--) {\n                if ((int)ops.size() >= MAXK) break;\n                auto [x1, y1] = path[k];\n                auto [x2, y2] = path[k - 1];\n                do_swap(x1, y1, x2, y2);\n            }\n\n            fixedv[bestVal] = 1;\n        }\n        if ((int)ops.size() >= MAXK) break;\n    }\n\n    auto total_bad = [&]() -> int {\n        int bad = 0;\n        for (int x = 0; x < N - 1; x++) {\n            for (int y = 0; y <= x; y++) {\n                if (a[x][y] > a[x+1][y]) bad++;\n                if (a[x][y] > a[x+1][y+1]) bad++;\n            }\n        }\n        return bad;\n    };\n\n    auto local_bad = [&](int x, int y) -> int {\n        int me = a[x][y];\n        int bad = 0;\n        if (x > 0) {\n            if (y > 0 && a[x-1][y-1] > me) bad++;\n            if (y < x && a[x-1][y] > me) bad++;\n        }\n        if (x + 1 < N) {\n            if (me > a[x+1][y]) bad++;\n            if (me > a[x+1][y+1]) bad++;\n        }\n        return bad;\n    };\n\n    // Stronger local repair:\n    // choose the adjacent swap with maximum local gain, repeat.\n    while ((int)ops.size() < MAXK) {\n        int bestGain = 0;\n        int bx1 = -1, by1 = -1, bx2 = -1, by2 = -1;\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y <= x; y++) {\n                for (auto [nx, ny] : neighbors(x, y)) {\n                    if (x > nx || (x == nx && y >= ny)) continue; // consider each edge once\n                    int before = local_bad(x, y) + local_bad(nx, ny);\n                    swap(a[x][y], a[nx][ny]);\n                    int after = local_bad(x, y) + local_bad(nx, ny);\n                    swap(a[x][y], a[nx][ny]);\n                    int gain = before - after;\n                    if (gain > bestGain) {\n                        bestGain = gain;\n                        bx1 = x; by1 = y; bx2 = nx; by2 = ny;\n                    }\n                }\n            }\n        }\n\n        if (bestGain <= 0) break;\n        do_swap(bx1, by1, bx2, by2);\n    }\n\n    // Additional deterministic heap-fix passes.\n    // Often helps if some inversions remain after greedy max-gain phase.\n    bool updated = true;\n    while (updated && (int)ops.size() < MAXK) {\n        updated = false;\n        for (int x = N - 2; x >= 0; x--) {\n            for (int y = 0; y <= x; y++) {\n                if ((int)ops.size() >= MAXK) break;\n                int cur = a[x][y];\n                int c1 = a[x+1][y];\n                int c2 = a[x+1][y+1];\n\n                if (cur > c1 || cur > c2) {\n                    if (c1 < c2) {\n                        do_swap(x, y, x+1, y);\n                    } else {\n                        do_swap(x, y, x+1, y+1);\n                    }\n                    updated = true;\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    return 0;\n}","toyota2023summer-final":"#include <bits/stdc++.h>\nusing namespace std;\n\n/*\nHeuristic idea\n\nWe must place containers online (arrival order unknown; label revealed on arrival),\nsubject to current empties maintaining reachability from entrance.\n\nAfter all placements, we may choose any feasible retrieval order where each next\ncontainer must be currently reachable from entrance through empty cells.\n\nKey observation:\nIf we place containers in a reverse topological order of some rooted spanning tree\nof free cells (excluding entrance), then every placement is feasible, and later\nretrieval in root-to-leaf order is always feasible.\nSo if each cell has a fixed \"retrieval priority\" rank, and we always assign newly\narrived containers to cells according to their label (smaller label => earlier\nretrieval rank), retrieval sequence becomes approximately sorted by labels.\n\nConstruction:\n- Build BFS tree from entrance over all usable cells.\n- Sort cells by depth descending; this is a valid online placement order:\n  placing only on deepest remaining cells preserves reachability of all empty cells.\n- Retrieval order is reverse of that: depth ascending.\n- To improve quality, within each depth layer, use subtree size / local geometry tie-breaks,\n  and map labels to ranks among currently free cells by quantile:\n    choose k = floor(label * remaining_cells / total_labels)\n    and place in k-th cell of retrieval-order among free cells.\nThis approximates storing smaller labels closer to entrance.\n\nSince total cells <= 80, simple recomputation is fine.\n*/\n\nstruct Pos {\n    int i, j;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n    vector<vector<int>> obstacle(D, vector<int>(D, 0));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = 1;\n    }\n\n    const int ei = 0, ej = (D - 1) / 2;\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D;\n    };\n\n    vector<Pos> dirs = {{1,0},{-1,0},{0,1},{0,-1}};\n\n    // Enumerate usable cells (non-obstacle, non-entrance)\n    vector<vector<int>> id(D, vector<int>(D, -1));\n    vector<Pos> cells;\n    for (int i = 0; i < D; ++i) for (int j = 0; j < D; ++j) {\n        if (i == ei && j == ej) continue;\n        if (obstacle[i][j]) continue;\n        id[i][j] = (int)cells.size();\n        cells.push_back({i,j});\n    }\n    int M = (int)cells.size(); // number of containers total\n\n    // BFS tree from entrance\n    vector<int> depth(M, -1), parent(M, -1);\n    queue<pair<int,int>> q;\n    vector<vector<int>> vis(D, vector<int>(D, 0));\n    q.push({ei, ej});\n    vis[ei][ej] = 1;\n\n    while (!q.empty()) {\n        auto [x, y] = q.front(); q.pop();\n        for (auto d : dirs) {\n            int nx = x + d.i, ny = y + d.j;\n            if (!inside(nx, ny) || vis[nx][ny] || obstacle[nx][ny]) continue;\n            vis[nx][ny] = 1;\n            q.push({nx, ny});\n            if (!(nx == ei && ny == ej)) {\n                int v = id[nx][ny];\n                depth[v] = (x == ei && y == ej) ? 1 : depth[id[x][y]] + 1;\n                if (x == ei && y == ej) parent[v] = -1;\n                else parent[v] = id[x][y];\n            }\n        }\n    }\n\n    // children and subtree sizes\n    vector<vector<int>> children(M);\n    for (int v = 0; v < M; ++v) if (parent[v] != -1) children[parent[v]].push_back(v);\n\n    vector<int> sub(M, 1);\n    vector<int> order(M);\n    iota(order.begin(), order.end(), 0);\n    sort(order.begin(), order.end(), [&](int a, int b){ return depth[a] > depth[b]; });\n    for (int v : order) {\n        if (parent[v] != -1) sub[parent[v]] += sub[v];\n    }\n\n    // Static retrieval preference order:\n    // smaller depth first; among same depth, larger subtree first; then centrality / coordinates\n    vector<int> retrieval_order(M);\n    iota(retrieval_order.begin(), retrieval_order.end(), 0);\n    sort(retrieval_order.begin(), retrieval_order.end(), [&](int a, int b) {\n        if (depth[a] != depth[b]) return depth[a] < depth[b];\n        if (sub[a] != sub[b]) return sub[a] > sub[b];\n        int ca = abs(cells[a].j - ej);\n        int cb = abs(cells[b].j - ej);\n        if (ca != cb) return ca < cb;\n        if (cells[a].i != cells[b].i) return cells[a].i < cells[b].i;\n        return cells[a].j < cells[b].j;\n    });\n\n    // Placement order corresponding to reverse retrieval order\n    vector<int> placement_order = retrieval_order;\n    reverse(placement_order.begin(), placement_order.end());\n\n    vector<int> label_at_cell(M, -1);\n    vector<int> cell_of_label(M, -1);\n    vector<int> occupied(M, 0);\n\n    // For online placement:\n    // among currently free cells, consider them in retrieval_order;\n    // choose quantile by label among all labels [0, M-1].\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        vector<int> free_retrieval;\n        free_retrieval.reserve(M - step);\n        for (int v : retrieval_order) {\n            if (!occupied[v]) free_retrieval.push_back(v);\n        }\n\n        int rem = (int)free_retrieval.size();\n        int idx = (long long)t * rem / M;\n        if (idx >= rem) idx = rem - 1;\n\n        int chosen = free_retrieval[idx];\n\n        occupied[chosen] = 1;\n        label_at_cell[chosen] = t;\n        cell_of_label[t] = chosen;\n\n        cout << cells[chosen].i << ' ' << cells[chosen].j << '\\n';\n        cout.flush();\n    }\n\n    // Retrieval phase:\n    // Output occupied cells in retrieval_order. This is feasible because\n    // retrieval_order is root-to-leaf in the BFS tree.\n    for (int v : retrieval_order) {\n        cout << cells[v].i << ' ' << cells[v].j << '\\n';\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXC = 100;\n\nstruct Solver {\n    int n, m;\n    vector<vector<int>> orig, a, bestA;\n    bool origAdj[MAXC + 1][MAXC + 1]{};\n    bool canTouchZero[MAXC + 1]{};\n    int edgeCnt[MAXC + 1][MAXC + 1]{};\n    int colorCells[MAXC + 1]{};\n    mt19937 rng{(uint32_t)chrono::steady_clock::now().time_since_epoch().count()};\n\n    bool inside(int i, int j) const {\n        return 0 <= i && i < n && 0 <= j && j < n;\n    }\n\n    void addEdge(int x, int y, int d) {\n        if (x == y) return;\n        edgeCnt[x][y] += d;\n        edgeCnt[y][x] += d;\n    }\n\n    void buildOriginalInfo() {\n        memset(origAdj, 0, sizeof(origAdj));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = orig[i][j];\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    origAdj[0][c] = origAdj[c][0] = true;\n                }\n                if (i + 1 < n) {\n                    int d = orig[i + 1][j];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n                if (j + 1 < n) {\n                    int d = orig[i][j + 1];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n            }\n        }\n        for (int c = 1; c <= m; c++) canTouchZero[c] = origAdj[0][c];\n    }\n\n    void rebuildState() {\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(colorCells, 0, sizeof(colorCells));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                colorCells[a[i][j]]++;\n            }\n        }\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = a[i][j];\n                if (i == 0) addEdge(0, c, 1);\n                if (i == n - 1) addEdge(0, c, 1);\n                if (j == 0) addEdge(0, c, 1);\n                if (j == n - 1) addEdge(0, c, 1);\n                if (i + 1 < n) addEdge(c, a[i + 1][j], 1);\n                if (j + 1 < n) addEdge(c, a[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool checkAdjRows(const vector<int>& rows) {\n        vector<int> rs = rows;\n        sort(rs.begin(), rs.end());\n        rs.erase(unique(rs.begin(), rs.end()), rs.end());\n        for (int x : rs) {\n            for (int y = 0; y <= m; y++) {\n                bool now = edgeCnt[x][y] > 0;\n                if (now != origAdj[x][y]) return false;\n            }\n        }\n        return true;\n    }\n\n    bool connectedColor(int color) {\n        if (color == 0) return zeroConnected();\n        if (colorCells[color] == 0) return false;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        bool found = false;\n        for (int i = 0; i < n && !found; i++) {\n            for (int j = 0; j < n && !found; j++) {\n                if (a[i][j] == color) {\n                    q.push({i, j});\n                    vis[i][j] = true;\n                    found = true;\n                }\n            }\n        }\n\n        int cnt = 0;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != color) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[color];\n    }\n\n    bool connectedColorLocalHint(int color, int hi, int hj) {\n        if (color == 0) return zeroConnected();\n        if (colorCells[color] == 0) return false;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        bool found = false;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int d = 0; d < 4 && !found; d++) {\n            int ni = hi + di[d], nj = hj + dj[d];\n            if (inside(ni, nj) && a[ni][nj] == color) {\n                q.push({ni, nj});\n                vis[ni][nj] = true;\n                found = true;\n            }\n        }\n        if (!found) {\n            // maybe the component exists elsewhere\n            for (int i = 0; i < n && !found; i++) {\n                for (int j = 0; j < n && !found; j++) {\n                    if (a[i][j] == color) {\n                        q.push({i, j});\n                        vis[i][j] = true;\n                        found = true;\n                    }\n                }\n            }\n        }\n\n        int cnt = 0;\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != color) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[color];\n    }\n\n    bool zeroConnected() {\n        if (colorCells[0] == 0) return true;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        for (int i = 0; i < n; i++) {\n            if (a[i][0] == 0 && !vis[i][0]) vis[i][0] = true, q.push({i, 0});\n            if (a[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 (a[0][j] == 0 && !vis[0][j]) vis[0][j] = true, q.push({0, j});\n            if (a[n - 1][j] == 0 && !vis[n - 1][j]) vis[n - 1][j] = true, q.push({n - 1, j});\n        }\n        if (q.empty()) return false;\n\n        int cnt = 0;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != 0) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[0];\n    }\n\n    int sameDeg(int i, int j) const {\n        int c = a[i][j], s = 0;\n        if (i > 0 && a[i - 1][j] == c) s++;\n        if (i + 1 < n && a[i + 1][j] == c) s++;\n        if (j > 0 && a[i][j - 1] == c) s++;\n        if (j + 1 < n && a[i][j + 1] == c) s++;\n        return s;\n    }\n\n    int zeroNbrs(int i, int j) const {\n        int s = 0;\n        if (i == 0 || a[i - 1][j] == 0) s++;\n        if (i == n - 1 || a[i + 1][j] == 0) s++;\n        if (j == 0 || a[i][j - 1] == 0) s++;\n        if (j == n - 1 || a[i][j + 1] == 0) s++;\n        return s;\n    }\n\n    vector<int> neighborhoodColors(int i, int j, int oldc, int newc) {\n        vector<int> v = {oldc, newc, 0};\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            v.push_back(inside(ni, nj) ? a[ni][nj] : 0);\n        }\n        sort(v.begin(), v.end());\n        v.erase(unique(v.begin(), v.end()), v.end());\n        return v;\n    }\n\n    void applyCellChangeCounts(int i, int j, int oldc, int newc, int sign) {\n        // sign = -1 means remove current contribution of oldc at (i,j)\n        // sign = +1 means add contribution of newc at (i,j)\n        if (i == 0) addEdge(0, (sign == -1 ? oldc : newc), sign);\n        if (i == n - 1) addEdge(0, (sign == -1 ? oldc : newc), sign);\n        if (j == 0) addEdge(0, (sign == -1 ? oldc : newc), sign);\n        if (j == n - 1) addEdge(0, (sign == -1 ? oldc : newc), sign);\n\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\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 oth = a[ni][nj];\n            addEdge((sign == -1 ? oldc : newc), oth, sign);\n        }\n    }\n\n    bool tryChange(int i, int j, int newc) {\n        int oldc = a[i][j];\n        if (oldc == newc) return false;\n        if (oldc != 0 && colorCells[oldc] <= 1) return false;\n\n        if (newc == 0) {\n            if (!canTouchZero[oldc]) return false;\n            static const int di[4] = {-1, 1, 0, 0};\n            static const int dj[4] = {0, 0, -1, 1};\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                int c = inside(ni, nj) ? a[ni][nj] : 0;\n                if (c != 0 && !canTouchZero[c]) return false;\n            }\n        } else {\n            // newc must be a color present in 4-neighborhood typically.\n            // Also if any zero is adjacent after recolor, newc must be able to touch zero.\n            if ((i == 0 || i == n - 1 || j == 0 || j == n - 1) && !canTouchZero[newc]) return false;\n            if (i > 0 && a[i - 1][j] == 0 && !canTouchZero[newc]) return false;\n            if (i + 1 < n && a[i + 1][j] == 0 && !canTouchZero[newc]) return false;\n            if (j > 0 && a[i][j - 1] == 0 && !canTouchZero[newc]) return false;\n            if (j + 1 < n && a[i][j + 1] == 0 && !canTouchZero[newc]) return false;\n        }\n\n        applyCellChangeCounts(i, j, oldc, newc, -1);\n\n        a[i][j] = newc;\n        colorCells[oldc]--;\n        colorCells[newc]++;\n\n        applyCellChangeCounts(i, j, oldc, newc, +1);\n\n        auto touched = neighborhoodColors(i, j, oldc, newc);\n\n        bool ok = true;\n        if (oldc != 0 && !connectedColorLocalHint(oldc, i, j)) ok = false;\n        if (ok && newc != 0 && !connectedColorLocalHint(newc, i, j)) ok = false;\n        if (ok && (oldc == 0 || newc == 0) && !zeroConnected()) ok = false;\n        if (ok && !checkAdjRows(touched)) ok = false;\n\n        if (!ok) {\n            a[i][j] = oldc;\n            rebuildState();\n            return false;\n        }\n        return true;\n    }\n\n    bool erasePass() {\n        vector<pair<array<int,4>, pair<int,int>>> cand;\n        cand.reserve(n * n);\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = a[i][j];\n                if (c == 0 || !canTouchZero[c]) continue;\n                int sd = sameDeg(i, j);\n                int zn = zeroNbrs(i, j);\n                int border = (i == 0 || i == n - 1 || j == 0 || j == n - 1) ? 0 : 1;\n                int rnd = (int)(rng() & 1023);\n                cand.push_back({{sd, -zn, border, rnd}, {i, j}});\n            }\n        }\n        sort(cand.begin(), cand.end(),\n             [](const auto& a, const auto& b) { return a.first < b.first; });\n\n        bool improved = false;\n        for (auto &e : cand) {\n            auto [i, j] = e.second;\n            if (a[i][j] == 0) continue;\n            if (tryChange(i, j, 0)) improved = true;\n        }\n        return improved;\n    }\n\n    bool recolorPass() {\n        vector<tuple<array<int,4>, int, int, int>> moves;\n        moves.reserve(n * n * 2);\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int oldc = a[i][j];\n                if (oldc == 0) continue;\n\n                set<int> neigh;\n                if (i > 0 && a[i - 1][j] != oldc && a[i - 1][j] != 0) neigh.insert(a[i - 1][j]);\n                if (i + 1 < n && a[i + 1][j] != oldc && a[i + 1][j] != 0) neigh.insert(a[i + 1][j]);\n                if (j > 0 && a[i][j - 1] != oldc && a[i][j - 1] != 0) neigh.insert(a[i][j - 1]);\n                if (j + 1 < n && a[i][j + 1] != oldc && a[i][j + 1] != 0) neigh.insert(a[i][j + 1]);\n\n                int sd = sameDeg(i, j);\n                int zn = zeroNbrs(i, j);\n                for (int nc : neigh) {\n                    // prioritize cells that are thin and close to zero\n                    int sameToNew = 0;\n                    if (i > 0 && a[i - 1][j] == nc) sameToNew++;\n                    if (i + 1 < n && a[i + 1][j] == nc) sameToNew++;\n                    if (j > 0 && a[i][j - 1] == nc) sameToNew++;\n                    if (j + 1 < n && a[i][j + 1] == nc) sameToNew++;\n                    int rnd = (int)(rng() & 1023);\n                    moves.push_back({{sd, -sameToNew, -zn, rnd}, i, j, nc});\n                }\n            }\n        }\n\n        sort(moves.begin(), moves.end(),\n             [](const auto& a, const auto& b) { return get<0>(a) < get<0>(b); });\n\n        bool improved = false;\n        int beforeZero = colorCells[0];\n\n        for (auto &mv : moves) {\n            int i = get<1>(mv), j = get<2>(mv), nc = get<3>(mv);\n            if (a[i][j] == 0 || a[i][j] == nc) continue;\n            // Only keep recolor if it is legal and likely useful.\n            int oldc = a[i][j];\n            if (!tryChange(i, j, nc)) continue;\n\n            // Very simple utility filter:\n            // keep if it increased zero-neighbor exposure or reduced local old-color degree.\n            int gain = zeroNbrs(i, j);\n            int keep = gain;\n            if (keep >= 1 || sameDeg(i, j) >= 2) {\n                improved = true;\n            } else {\n                // rollback if not promising enough\n                tryChange(i, j, oldc);\n            }\n        }\n\n        return improved || colorCells[0] > beforeZero;\n    }\n\n    int score() const {\n        return colorCells[0] + 1;\n    }\n\n    void solve() {\n        cin >> n >> m;\n        orig.assign(n, vector<int>(n));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) cin >> orig[i][j];\n        }\n\n        buildOriginalInfo();\n        a = orig;\n        rebuildState();\n        bestA = a;\n        int bestScore = score();\n\n        auto start = chrono::steady_clock::now();\n        int phase = 0;\n\n        while (true) {\n            phase++;\n            bool any = false;\n\n            any |= erasePass();\n            int sc = score();\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestA = a;\n            }\n\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.90) break;\n\n            any |= recolorPass();\n            sc = score();\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestA = a;\n            }\n\n            now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.90) break;\n\n            any |= erasePass();\n            sc = score();\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestA = a;\n            }\n\n            now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.90) break;\n\n            if (!any) break;\n\n            // occasional reshuffle/rebuild for stability\n            if (phase % 3 == 0) rebuildState();\n        }\n\n        a = bestA;\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    }\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}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    vector<int> assign_;\n    vector<int> rank_pos_;\n\n    // ---------------- interactive ----------------\n\n    int cmp_single(int a, int b) {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        ++used;\n        if (s == \"<\") return -1;\n        if (s == \">\") return 1;\n        return 0;\n    }\n\n    void dummy_query() {\n        int a = 0, b = 1;\n        if (b >= N) b = 0;\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        ++used;\n    }\n\n    // ---------------- approximate sort ----------------\n\n    vector<int> budgeted_insertion_sort_items(int budget) {\n        vector<int> ord;\n        ord.reserve(N);\n        ord.push_back(0);\n\n        for (int x = 1; x < N; ++x) {\n            if (used >= budget) {\n                ord.push_back(x);\n                continue;\n            }\n            int l = 0, r = (int)ord.size();\n            while (l < r && used < budget) {\n                int m = (l + r) >> 1;\n                int c = cmp_single(x, ord[m]);\n                if (c < 0) r = m;\n                else l = m + 1;\n            }\n            ord.insert(ord.begin() + l, x);\n        }\n        return ord; // light -> heavy\n    }\n\n    vector<double> build_pseudo_weights(const vector<int>& ord) {\n        vector<double> pw(N);\n        rank_pos_.assign(N, 0);\n        for (int i = 0; i < N; ++i) rank_pos_[ord[i]] = i;\n\n        // exponential-like hidden distribution => use exponential rank mapping\n        const double alpha = 5.0;\n        for (int i = 0; i < N; ++i) {\n            double t = (rank_pos_[i] + 0.5) / N; // (0,1)\n            pw[i] = exp(alpha * t);\n        }\n        return pw;\n    }\n\n    // ---------------- assignment helpers ----------------\n\n    vector<int> initial_assign(const vector<int>& ord, const vector<double>& pw) {\n        vector<int> ret(N, 0);\n        vector<double> load(D, 0.0);\n\n        for (int idx = N - 1; idx >= 0; --idx) {\n            int item = ord[idx];\n            int best = 0;\n            for (int d = 1; d < D; ++d) {\n                if (load[d] < load[best]) best = d;\n            }\n            ret[item] = best;\n            load[best] += pw[item];\n        }\n        return ret;\n    }\n\n    vector<double> calc_loads(const vector<int>& asg, const vector<double>& pw) {\n        vector<double> load(D, 0.0);\n        for (int i = 0; i < N; ++i) load[asg[i]] += pw[i];\n        return load;\n    }\n\n    double objective(const vector<int>& asg, const vector<double>& pw) {\n        auto load = calc_loads(asg, pw);\n        double mean = 0.0;\n        for (double x : load) mean += x;\n        mean /= D;\n        double var = 0.0;\n        for (double x : load) {\n            double y = x - mean;\n            var += y * y;\n        }\n        return var / D;\n    }\n\n    // ---------------- local search ----------------\n\n    void local_search(vector<int>& asg, const vector<double>& pw) {\n        double cur = objective(asg, pw);\n\n        vector<int> items(N);\n        iota(items.begin(), items.end(), 0);\n\n        // heavy-first is often useful\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            return pw[a] > pw[b];\n        });\n\n        for (int phase = 0; phase < 8; ++phase) {\n            bool improved = false;\n\n            // best single move\n            {\n                auto load = calc_loads(asg, pw);\n                double best_delta = 0.0;\n                int best_item = -1, best_to = -1;\n\n                for (int item : items) {\n                    int from = asg[item];\n                    for (int to = 0; to < D; ++to) {\n                        if (to == from) continue;\n\n                        double old_from = load[from], old_to = load[to];\n                        double new_from = old_from - pw[item];\n                        double new_to = old_to + pw[item];\n\n                        // quick pair contribution approximation\n                        double before = old_from * old_from + old_to * old_to;\n                        double after = new_from * new_from + new_to * new_to;\n                        double delta = after - before;\n\n                        if (delta < best_delta) {\n                            best_delta = delta;\n                            best_item = item;\n                            best_to = to;\n                        }\n                    }\n                }\n\n                if (best_item != -1) {\n                    int old = asg[best_item];\n                    asg[best_item] = best_to;\n                    double nxt = objective(asg, pw);\n                    if (nxt + 1e-12 < cur) {\n                        cur = nxt;\n                        improved = true;\n                    } else {\n                        asg[best_item] = old;\n                    }\n                }\n            }\n\n            if (improved) continue;\n\n            // best swap among candidate items\n            // restrict candidates to top heavy + some light for speed/diversity\n            vector<int> cand;\n            int K = min(N, 28);\n            for (int i = 0; i < K; ++i) cand.push_back(items[i]);\n            for (int i = max(K, N - 12); i < N; ++i) cand.push_back(items[i]);\n            sort(cand.begin(), cand.end());\n            cand.erase(unique(cand.begin(), cand.end()), cand.end());\n\n            double best_gain = 0.0;\n            int besta = -1, bestb = -1;\n\n            auto load = calc_loads(asg, pw);\n\n            for (int ia = 0; ia < (int)cand.size(); ++ia) {\n                int a = cand[ia];\n                int ga = asg[a];\n                for (int ib = ia + 1; ib < (int)cand.size(); ++ib) {\n                    int b = cand[ib];\n                    int gb = asg[b];\n                    if (ga == gb) continue;\n\n                    double olda = load[ga], oldb = load[gb];\n                    double newa = olda - pw[a] + pw[b];\n                    double newb = oldb - pw[b] + pw[a];\n\n                    double before = olda * olda + oldb * oldb;\n                    double after = newa * newa + newb * newb;\n                    double delta = after - before;\n                    if (delta < best_gain) {\n                        best_gain = delta;\n                        besta = a;\n                        bestb = b;\n                    }\n                }\n            }\n\n            if (besta != -1) {\n                swap(asg[besta], asg[bestb]);\n                double nxt = objective(asg, pw);\n                if (nxt + 1e-12 < cur) {\n                    cur = nxt;\n                    improved = true;\n                } else {\n                    swap(asg[besta], asg[bestb]);\n                }\n            }\n\n            if (improved) continue;\n\n            // targeted balancing: move one item from heaviest pseudo-bin to lightest pseudo-bin\n            {\n                auto load2 = calc_loads(asg, pw);\n                int hi = max_element(load2.begin(), load2.end()) - load2.begin();\n                int lo = min_element(load2.begin(), load2.end()) - load2.begin();\n\n                double best_abs = fabs(load2[hi] - load2[lo]);\n                int best_item = -1;\n\n                for (int i = 0; i < N; ++i) {\n                    if (asg[i] != hi) continue;\n                    double nh = load2[hi] - pw[i];\n                    double nl = load2[lo] + pw[i];\n                    double val = fabs(nh - nl);\n                    if (val < best_abs) {\n                        best_abs = val;\n                        best_item = i;\n                    }\n                }\n\n                if (best_item != -1) {\n                    int old = asg[best_item];\n                    asg[best_item] = lo;\n                    double nxt = objective(asg, pw);\n                    if (nxt + 1e-12 < cur) {\n                        cur = nxt;\n                        improved = true;\n                    } else {\n                        asg[best_item] = old;\n                    }\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    // ---------------- solve ----------------\n\n    void solve() {\n        cin >> N >> D >> Q;\n\n        // Use almost all budget for ranking; reserve a tiny amount just for safety.\n        int reserve = 2;\n        int sort_budget = max(0, Q - reserve);\n\n        vector<int> ord = budgeted_insertion_sort_items(sort_budget);\n        vector<double> pw = build_pseudo_weights(ord);\n\n        vector<int> asg = initial_assign(ord, pw);\n        local_search(asg, pw);\n\n        while (used < Q) dummy_query();\n\n        for (int i = 0; i < N; ++i) {\n            if (i) cout << ' ';\n            cout << asg[i];\n        }\n        cout << '\\n';\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    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Node {\n    vector<vector<int>> st;                  // bottom -> top\n    vector<pair<int,int>> ops;               // (v, to+1)\n    int cost = 0;                            // actual move energy so far\n    long long score = 0;                     // cost + heuristic\n};\n\nstruct Solver {\n    int n, m;\n    vector<vector<int>> init_st;\n    vector<pair<int,int>> answer;\n\n    Solver() {\n        cin >> n >> m;\n        init_st.assign(m, {});\n        for (int i = 0; i < m; i++) {\n            init_st[i].resize(n / m);\n            for (int j = 0; j < n / m; j++) cin >> init_st[i][j];\n        }\n    }\n\n    pair<int,int> find_box(const vector<vector<int>>& st, int x) const {\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < (int)st[i].size(); j++) {\n                if (st[i][j] == x) return {i, j};\n            }\n        }\n        return {-1, -1};\n    }\n\n    int min_in_stack(const vector<int>& v) const {\n        if (v.empty()) return (int)1e9;\n        int mn = (int)1e9;\n        for (int x : v) mn = min(mn, x);\n        return mn;\n    }\n\n    int min_top_window(const vector<int>& v, int w = 6) const {\n        if (v.empty()) return (int)1e9;\n        int mn = (int)1e9;\n        int sz = (int)v.size();\n        for (int i = max(0, sz - w); i < sz; i++) mn = min(mn, v[i]);\n        return mn;\n    }\n\n    void apply_move(vector<vector<int>>& st, int from, int pos, int to) const {\n        vector<int> moved(st[from].begin() + pos, st[from].end());\n        st[from].erase(st[from].begin() + pos, st[from].end());\n        st[to].insert(st[to].end(), moved.begin(), moved.end());\n    }\n\n    long long heuristic(const vector<vector<int>>& st, int need) const {\n        const int W = 18;\n        long long penalty = 0;\n\n        // Evaluate upcoming boxes\n        for (int x = need; x <= min(n, need + W - 1); x++) {\n            auto [s, p] = find_box(st, x);\n            if (s == -1) continue;\n            int above = (int)st[s].size() - 1 - p;\n            int w = need + W - x; // near future boxes are important\n\n            penalty += 140LL * w * above;\n            penalty += 5LL * w * (int)st[s].size();\n\n            // Penalize urgent blockers above x\n            for (int i = p + 1; i < (int)st[s].size(); i++) {\n                int y = st[s][i];\n                if (y <= x + 5) penalty += 55LL * w;\n                else if (y <= x + 12) penalty += 20LL * w;\n                else if (y <= x + 25) penalty += 6LL * w;\n                else penalty += 1LL * w;\n            }\n        }\n\n        // Structural preference: stacks with small minima should not become huge\n        for (int s = 0; s < m; s++) {\n            int mn = min_in_stack(st[s]);\n            int h = (int)st[s].size();\n            if (mn < (int)1e9) {\n                int urg = max(0, 40 - mn);\n                penalty += 3LL * urg * h;\n            }\n        }\n\n        return penalty;\n    }\n\n    vector<int> candidate_cut_positions(const vector<vector<int>>& st, int s, int need_pos) const {\n        vector<int> cand;\n        int top = (int)st[s].size() - 1;\n        if (need_pos == top) return cand;\n        int start = need_pos + 1;\n\n        // whole blocker suffix\n        cand.push_back(start);\n\n        // record minima among blockers\n        int best = (int)1e9;\n        for (int i = start; i <= top; i++) {\n            if (st[s][i] < best) {\n                best = st[s][i];\n                cand.push_back(i);\n            }\n        }\n\n        // a few top-side cuts\n        cand.push_back(top);\n        if (top - 1 >= start) cand.push_back(top - 1);\n        if (top - 2 >= start) cand.push_back(top - 2);\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    }\n\n    long long destination_bias(const vector<vector<int>>& st, int to, int moved_min, int moved_sz) const {\n        int mn_all = min_in_stack(st[to]);\n        int mn_top = min_top_window(st[to], 6);\n        int h = (int)st[to].size();\n\n        long long val = 0;\n        val += 60LL * h;\n        val += 10LL * (h + moved_sz);\n\n        if (!st[to].empty()) {\n            if (mn_all < moved_min) val += 2800;\n            if (mn_top < moved_min) val += 1800;\n            val += 2LL * max(0, 80 - mn_all);\n            val += 2LL * max(0, 80 - mn_top);\n        }\n        return val; // lower is better\n    }\n\n    vector<int> candidate_destinations(const vector<vector<int>>& st, int from, int moved_min, int moved_sz, int need) const {\n        vector<pair<long long,int>> cand;\n        int forbid1 = -1, forbid2 = -1, forbid3 = -1;\n        if (need + 1 <= n) forbid1 = find_box(st, need + 1).first;\n        if (need + 2 <= n) forbid2 = find_box(st, need + 2).first;\n        if (need + 3 <= n) forbid3 = find_box(st, need + 3).first;\n\n        for (int to = 0; to < m; to++) {\n            if (to == from) continue;\n            long long v = destination_bias(st, to, moved_min, moved_sz);\n            if (to == forbid1) v += 1500;\n            if (to == forbid2) v += 800;\n            if (to == forbid3) v += 400;\n            cand.push_back({v, to});\n        }\n        sort(cand.begin(), cand.end());\n\n        vector<int> res;\n        int LIM = min<int>(4, cand.size());\n        for (int i = 0; i < LIM; i++) res.push_back(cand[i].second);\n        return res;\n    }\n\n    string encode_state(const vector<vector<int>>& st) const {\n        string s;\n        s.reserve(512);\n        for (int i = 0; i < m; i++) {\n            for (int x : st[i]) {\n                s.push_back(char(x));\n                s.push_back(char(x >> 8));\n            }\n            s.push_back('#');\n        }\n        return s;\n    }\n\n    vector<pair<int,int>> expose_with_beam(vector<vector<int>> current, int need) const {\n        auto [ss, pp] = find_box(current, need);\n        if (pp == (int)current[ss].size() - 1) return {};\n\n        const int BEAM_WIDTH = 12;\n        const int MAX_DEPTH = 4;\n\n        Node root;\n        root.st = current;\n        root.cost = 0;\n        root.score = heuristic(root.st, need);\n\n        vector<Node> beam{root};\n        Node best_terminal;\n        bool found_terminal = false;\n        long long best_terminal_key = (1LL << 62);\n\n        for (int depth = 0; depth < MAX_DEPTH; depth++) {\n            vector<Node> nxt;\n            unordered_map<string, long long> bestSeen;\n\n            for (const auto& node : beam) {\n                auto [s, p] = find_box(node.st, need);\n                if (p == (int)node.st[s].size() - 1) {\n                    long long key = 1000LL * node.cost + heuristic(node.st, need);\n                    if (key < best_terminal_key) {\n                        best_terminal_key = key;\n                        best_terminal = node;\n                        found_terminal = true;\n                    }\n                    continue;\n                }\n\n                vector<int> cuts = candidate_cut_positions(node.st, s, p);\n                for (int pos : cuts) {\n                    int moved_sz = (int)node.st[s].size() - pos;\n                    int moved_min = (int)1e9;\n                    for (int i = pos; i < (int)node.st[s].size(); i++) {\n                        moved_min = min(moved_min, node.st[s][i]);\n                    }\n\n                    vector<int> dsts = candidate_destinations(node.st, s, moved_min, moved_sz, need);\n                    for (int to : dsts) {\n                        Node child = node;\n                        int v = child.st[s][pos];\n                        apply_move(child.st, s, pos, to);\n                        child.ops.push_back({v, to + 1});\n                        child.cost += moved_sz + 1;\n\n                        long long h = heuristic(child.st, need);\n                        child.score = 900LL * child.cost + h;\n\n                        // If need became top, reward strongly\n                        auto [ns, np] = find_box(child.st, need);\n                        if (np == (int)child.st[ns].size() - 1) child.score -= 50000;\n\n                        string key = encode_state(child.st);\n                        auto it = bestSeen.find(key);\n                        if (it == bestSeen.end() || child.score < it->second) {\n                            bestSeen[key] = child.score;\n                            nxt.push_back(std::move(child));\n                        }\n                    }\n                }\n            }\n\n            if (nxt.empty()) break;\n\n            sort(nxt.begin(), nxt.end(), [](const Node& a, const Node& b) {\n                if (a.score != b.score) return a.score < b.score;\n                return a.cost < b.cost;\n            });\n            if ((int)nxt.size() > BEAM_WIDTH) nxt.resize(BEAM_WIDTH);\n            beam = std::move(nxt);\n        }\n\n        // Final check beam nodes too\n        for (const auto& node : beam) {\n            auto [s, p] = find_box(node.st, need);\n            if (p == (int)node.st[s].size() - 1) {\n                long long key = 1000LL * node.cost + heuristic(node.st, need);\n                if (key < best_terminal_key) {\n                    best_terminal_key = key;\n                    best_terminal = node;\n                    found_terminal = true;\n                }\n            }\n        }\n\n        if (found_terminal) return best_terminal.ops;\n\n        // Fallback: choose best single-step move\n        auto [s, p] = find_box(current, need);\n        vector<int> cuts = candidate_cut_positions(current, s, p);\n\n        long long bestScore = (1LL << 62);\n        pair<int,int> bestMove = {-1, -1};\n\n        for (int pos : cuts) {\n            int moved_sz = (int)current[s].size() - pos;\n            int moved_min = (int)1e9;\n            for (int i = pos; i < (int)current[s].size(); i++) moved_min = min(moved_min, current[s][i]);\n            vector<int> dsts = candidate_destinations(current, s, moved_min, moved_sz, need);\n            for (int to : dsts) {\n                auto st2 = current;\n                apply_move(st2, s, pos, to);\n                long long val = 1000LL * (moved_sz + 1) + heuristic(st2, need);\n                if (val < bestScore) {\n                    bestScore = val;\n                    bestMove = {pos, to};\n                }\n            }\n        }\n\n        if (bestMove.first != -1) {\n            int v = current[s][bestMove.first];\n            return {{v, bestMove.second + 1}};\n        }\n\n        // Very safe fallback\n        int pos = p + 1, to = -1, besth = (int)1e9;\n        for (int j = 0; j < m; j++) if (j != s) {\n            if ((int)current[j].size() < besth) {\n                besth = (int)current[j].size();\n                to = j;\n            }\n        }\n        int v = current[s][pos];\n        return {{v, to + 1}};\n    }\n\n    void solve() {\n        vector<vector<int>> st = init_st;\n\n        auto apply_real_move = [&](int v, int to1based) {\n            int to = to1based - 1;\n            auto [s, p] = find_box(st, v);\n            answer.push_back({v, to1based});\n            apply_move(st, s, p, to);\n        };\n\n        auto remove_real = [&](int need) {\n            auto [s, p] = find_box(st, need);\n            answer.push_back({need, 0});\n            st[s].pop_back();\n        };\n\n        for (int need = 1; need <= n; need++) {\n            while (true) {\n                auto [s, p] = find_box(st, need);\n                if (p == (int)st[s].size() - 1) {\n                    remove_real(need);\n                    break;\n                }\n\n                auto ops = expose_with_beam(st, need);\n                if (ops.empty()) {\n                    // should mean already exposed, but loop handles it\n                    continue;\n                }\n\n                for (auto [v, to] : ops) {\n                    apply_real_move(v, to);\n                    if ((int)answer.size() > 4900) break;\n                }\n\n                if ((int)answer.size() > 4900) {\n                    // emergency finish with very simple strategy\n                    while (true) {\n                        auto [ss, pp] = find_box(st, need);\n                        if (pp == (int)st[ss].size() - 1) {\n                            remove_real(need);\n                            break;\n                        }\n                        int pos = pp + 1;\n                        int v = st[ss][pos];\n                        int to = -1, besth = (int)1e9;\n                        for (int j = 0; j < m; j++) {\n                            if (j == ss) continue;\n                            if ((int)st[j].size() < besth) {\n                                besth = (int)st[j].size();\n                                to = j;\n                            }\n                        }\n                        answer.push_back({v, to + 1});\n                        apply_move(st, ss, pos, to);\n                    }\n                    break;\n                }\n            }\n        }\n\n        for (auto [v, i] : answer) {\n            cout << v << ' ' << i << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc027":"#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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N;\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    vector<vector<int>> d2(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> d2[i][j];\n\n    const 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++) dirt[id(i,j)] = d2[i][j];\n\n    vector<vector<int>> adj(V);\n    vector<vector<char>> adjDir(V);\n\n    auto add_edge = [&](int a, int b, char c) {\n        adj[a].push_back(b);\n        adjDir[a].push_back(c);\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = id(i, j);\n            if (i > 0 && h[i - 1][j] == '0') add_edge(u, id(i - 1, j), 'U');\n            if (i + 1 < N && h[i][j] == '0') add_edge(u, id(i + 1, j), 'D');\n            if (j > 0 && v[i][j - 1] == '0') add_edge(u, id(i, j - 1), 'L');\n            if (j + 1 < N && v[i][j] == '0') add_edge(u, id(i, j + 1), 'R');\n        }\n    }\n\n    // BFS from every node\n    vector<vector<short>> dist(V, vector<short>(V, -1));\n    vector<vector<short>> parent(V, vector<short>(V, -1));\n    vector<vector<char>> parentDir(V, vector<char>(V, '?'));\n\n    {\n        vector<int> q(V);\n        for (int s = 0; s < V; s++) {\n            int ql = 0, qr = 0;\n            q[qr++] = s;\n            dist[s][s] = 0;\n            parent[s][s] = s;\n            while (ql < qr) {\n                int u = q[ql++];\n\n                vector<int> ord(adj[u].size());\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int va = adj[u][a], vb = adj[u][b];\n                    if (dirt[va] != dirt[vb]) return dirt[va] > dirt[vb];\n                    return va < vb;\n                });\n\n                for (int idx : ord) {\n                    int to = adj[u][idx];\n                    if (dist[s][to] == -1) {\n                        dist[s][to] = dist[s][u] + 1;\n                        parent[s][to] = u;\n                        parentDir[s][to] = adjDir[u][idx];\n                        q[qr++] = to;\n                    }\n                }\n            }\n        }\n    }\n\n    auto get_path = [&](int s, int t) -> string {\n        if (s == t) return \"\";\n        string revp;\n        int cur = t;\n        while (cur != s) {\n            revp.push_back(parentDir[s][cur]);\n            cur = parent[s][cur];\n        }\n        reverse(revp.begin(), revp.end());\n        return revp;\n    };\n\n    auto build_route = [&](const vector<int>& seq) -> string {\n        string route;\n        int cur = 0;\n        for (int x : seq) {\n            route += get_path(cur, x);\n            cur = x;\n        }\n        route += get_path(cur, 0);\n        return route;\n    };\n\n    auto route_len = [&](const vector<int>& seq) -> int {\n        int cur = 0, len = 0;\n        for (int x : seq) {\n            len += dist[cur][x];\n            cur = x;\n        }\n        len += dist[cur][0];\n        return len;\n    };\n\n    auto score_route = [&](const string& route) -> long long {\n        int L = (int)route.size();\n        if (L <= 0 || L > 100000) return (long long)4e18;\n\n        vector<vector<int>> visits(V);\n        int cur = 0;\n        for (int t = 1; t <= L; t++) {\n            auto [i, j] = pos(cur);\n            char c = route[t - 1];\n            if (c == 'U') --i;\n            else if (c == 'D') ++i;\n            else if (c == 'L') --j;\n            else ++j;\n            cur = id(i, j);\n            visits[cur].push_back(t);\n        }\n        if (cur != 0) return (long long)4e18;\n\n        visits[0].insert(visits[0].begin(), 0);\n\n        long double total = 0;\n        for (int u = 0; u < V; u++) {\n            if (visits[u].empty()) return (long long)4e18;\n            long long sum = 0;\n            auto &vec = visits[u];\n            for (int i = 0; i + 1 < (int)vec.size(); i++) {\n                long long g = vec[i + 1] - vec[i];\n                sum += g * (g - 1) / 2;\n            }\n            long long g = L - vec.back() + vec[0];\n            sum += g * (g - 1) / 2;\n            total += (long double)dirt[u] * (long double)sum;\n        }\n        return llround(total / (long double)L);\n    };\n\n    auto normalize_unique = [&](vector<int> seq) {\n        vector<char> seen(V, 0);\n        vector<int> out;\n        out.reserve(V - 1);\n        for (int x : seq) {\n            if (x == 0) continue;\n            if (!seen[x]) {\n                seen[x] = 1;\n                out.push_back(x);\n            }\n        }\n        for (int x = 1; x < V; x++) if (!seen[x]) out.push_back(x);\n        return out;\n    };\n\n    string bestRoute;\n    long long bestScore = (long long)4e18;\n    vector<int> bestSeq;\n\n    auto try_seq = [&](const vector<int>& seq) {\n        int len = route_len(seq);\n        if (len <= 0 || len > 100000) return;\n        string route = build_route(seq);\n        long long sc = score_route(route);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n            bestSeq = seq;\n        }\n    };\n\n    vector<vector<int>> baseCandidates;\n\n    // row snake\n    {\n        vector<int> seq;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) seq.push_back(id(i,j));\n            else for (int j = N - 1; j >= 0; j--) seq.push_back(id(i,j));\n        }\n        seq = normalize_unique(seq);\n        baseCandidates.push_back(seq);\n        reverse(seq.begin(), seq.end());\n        baseCandidates.push_back(seq);\n    }\n    // col snake\n    {\n        vector<int> seq;\n        for (int j = 0; j < N; j++) {\n            if (j % 2 == 0) for (int i = 0; i < N; i++) seq.push_back(id(i,j));\n            else for (int i = N - 1; i >= 0; i--) seq.push_back(id(i,j));\n        }\n        seq = normalize_unique(seq);\n        baseCandidates.push_back(seq);\n        reverse(seq.begin(), seq.end());\n        baseCandidates.push_back(seq);\n    }\n\n    // weighted geometric orders\n    {\n        vector<int> seq;\n        for (int x = 1; x < V; x++) seq.push_back(x);\n        sort(seq.begin(), seq.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            double ka = ai + aj - 0.003 * dirt[a];\n            double kb = bi + bj - 0.003 * dirt[b];\n            return ka < kb;\n        });\n        baseCandidates.push_back(seq);\n    }\n    {\n        vector<int> seq;\n        for (int x = 1; x < V; x++) seq.push_back(x);\n        sort(seq.begin(), seq.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            double ka = aj + ai - 0.003 * dirt[a];\n            double kb = bj + bi - 0.003 * dirt[b];\n            return ka < kb;\n        });\n        reverse(seq.begin(), seq.end());\n        baseCandidates.push_back(seq);\n    }\n\n    // greedy unique\n    auto greedy_unique = [&](double beta, double gamma) {\n        vector<char> used(V, 0);\n        vector<int> seq;\n        seq.reserve(V - 1);\n        int cur = 0;\n        for (int step = 0; step < V - 1; step++) {\n            int best = -1;\n            double bestVal = -1e100;\n            for (int x = 1; x < V; x++) if (!used[x]) {\n                double val = beta * log((double)dirt[x]) - dist[cur][x] - gamma * dist[0][x];\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = x;\n                }\n            }\n            used[best] = 1;\n            seq.push_back(best);\n            cur = best;\n        }\n        return seq;\n    };\n\n    for (double beta : {1.2, 1.5, 1.8, 2.2, 2.8}) {\n        for (double gamma : {0.0, 0.03, 0.07}) {\n            baseCandidates.push_back(greedy_unique(beta, gamma));\n        }\n    }\n\n    // tree-like DFS order\n    auto tree_order = [&](double alpha) {\n        const double INF = 1e100;\n        vector<double> ds(V, INF);\n        vector<int> par(V, -1);\n        priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n        ds[0] = 0;\n        pq.push({0, 0});\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top();\n            pq.pop();\n            if (cd != ds[u]) continue;\n            for (int to : adj[u]) {\n                double nd = cd + 1.0 / pow((double)dirt[to], alpha);\n                if (nd + 1e-12 < ds[to]) {\n                    ds[to] = nd;\n                    par[to] = u;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        vector<vector<int>> ch(V);\n        for (int x = 1; x < V; x++) ch[par[x]].push_back(x);\n        for (int u = 0; u < V; u++) {\n            sort(ch[u].begin(), ch[u].end(), [&](int a, int b) {\n                if (dirt[a] != dirt[b]) return dirt[a] > dirt[b];\n                return dist[0][a] < dist[0][b];\n            });\n        }\n        vector<int> seq;\n        function<void(int)> dfs = [&](int u) {\n            if (u != 0) seq.push_back(u);\n            for (int x : ch[u]) dfs(x);\n        };\n        dfs(0);\n        return seq;\n    };\n\n    for (double alpha : {0.2, 0.4, 0.7, 1.0}) {\n        baseCandidates.push_back(tree_order(alpha));\n    }\n\n    // Evaluate base candidates\n    vector<pair<long long,int>> ranked;\n    for (int i = 0; i < (int)baseCandidates.size(); i++) {\n        if (timer.elapsed() > 0.75) break;\n        try_seq(baseCandidates[i]);\n        ranked.push_back({bestScore, i}); // loose ranking; enough to keep count\n    }\n\n    // Also score each explicitly to rank better\n    vector<pair<long long,int>> scoredBases;\n    for (int i = 0; i < (int)baseCandidates.size(); i++) {\n        if (timer.elapsed() > 1.00) break;\n        string r = build_route(baseCandidates[i]);\n        long long sc = score_route(r);\n        scoredBases.push_back({sc, i});\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = r;\n            bestSeq = baseCandidates[i];\n        }\n    }\n    sort(scoredBases.begin(), scoredBases.end());\n\n    // top heavy cells for reinsertion\n    vector<int> heavy;\n    for (int x = 1; x < V; x++) heavy.push_back(x);\n    sort(heavy.begin(), heavy.end(), [&](int a, int b) {\n        double sa = dirt[a] / (double)(dist[0][a] + 1);\n        double sb = dirt[b] / (double)(dist[0][b] + 1);\n        if (fabs(sa - sb) > 1e-12) return sa > sb;\n        return dirt[a] > dirt[b];\n    });\n    if ((int)heavy.size() > 32) heavy.resize(32);\n\n    auto insert_cost = [&](const vector<int>& seq, int p, int x) -> int {\n        int prev = (p == 0 ? 0 : seq[p - 1]);\n        int next = (p == (int)seq.size() ? 0 : seq[p]);\n        return dist[prev][x] + dist[x][next] - dist[prev][next];\n    };\n\n    // Score-guided insertion search on best few bases\n    int elite = min(5, (int)scoredBases.size());\n    for (int ei = 0; ei < elite && timer.elapsed() < 1.92; ei++) {\n        vector<int> seq = baseCandidates[scoredBases[ei].second];\n        string route = build_route(seq);\n        long long curScore = score_route(route);\n        int curLen = route_len(seq);\n\n        if (curScore < bestScore) {\n            bestScore = curScore;\n            bestRoute = route;\n            bestSeq = seq;\n        }\n\n        bool improved = true;\n        int rounds = 0;\n        while (improved && timer.elapsed() < 1.92 && rounds < 6) {\n            improved = false;\n            rounds++;\n\n            vector<int> posCand;\n            int M = seq.size();\n            int samples = min(M + 1, 40);\n            for (int k = 0; k < samples; k++) {\n                int p = (long long)k * (M + 1) / samples;\n                posCand.push_back(p);\n            }\n            sort(posCand.begin(), posCand.end());\n            posCand.erase(unique(posCand.begin(), posCand.end()), posCand.end());\n\n            long long bestLocalScore = curScore;\n            vector<int> bestLocalSeq = seq;\n\n            // Try inserting important cells\n            for (int x : heavy) {\n                if (timer.elapsed() > 1.92) break;\n                for (int p : posCand) {\n                    int add = insert_cost(seq, p, x);\n                    if (curLen + add > 100000) continue;\n                    if (add > 30) continue; // avoid too-expensive detours\n\n                    vector<int> cand = seq;\n                    cand.insert(cand.begin() + p, x);\n\n                    string r = build_route(cand);\n                    long long sc = score_route(r);\n                    if (sc < bestLocalScore) {\n                        bestLocalScore = sc;\n                        bestLocalSeq.swap(cand);\n                    }\n                }\n            }\n\n            // Try one reversal-based diversification too\n            mt19937 rng(1234567 + ei * 100 + rounds);\n            for (int it = 0; it < 12 && timer.elapsed() < 1.92; it++) {\n                int l = rng() % seq.size();\n                int r = rng() % seq.size();\n                if (l > r) swap(l, r);\n                if (l == r) continue;\n                vector<int> cand = seq;\n                reverse(cand.begin() + l, cand.begin() + r + 1);\n                if (route_len(cand) > 100000) continue;\n                string rstr = build_route(cand);\n                long long sc = score_route(rstr);\n                if (sc < bestLocalScore) {\n                    bestLocalScore = sc;\n                    bestLocalSeq.swap(cand);\n                }\n            }\n\n            if (bestLocalScore < curScore) {\n                seq.swap(bestLocalSeq);\n                curLen = route_len(seq);\n                curScore = bestLocalScore;\n                improved = true;\n                if (curScore < bestScore) {\n                    bestScore = curScore;\n                    bestSeq = seq;\n                    bestRoute = build_route(seq);\n                }\n            }\n        }\n    }\n\n    // fallback\n    if (bestRoute.empty()) {\n        vector<int> seq;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) seq.push_back(id(i,j));\n            else for (int j = N - 1; j >= 0; j--) seq.push_back(id(i,j));\n        }\n        seq = normalize_unique(seq);\n        bestRoute = build_route(seq);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#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 Pos {\n    int x, y;\n};\n\nstatic const int INF = 1e9;\n\nint overlap5(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    Timer timer;\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    // Board positions by letter\n    vector<vector<Pos>> pos(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            pos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    // Approx movement distances\n    int startDist[26];\n    int bestDist[26][26];\n    for (int c = 0; c < 26; c++) {\n        startDist[c] = INF;\n        for (auto &p : pos[c]) {\n            startDist[c] = min(startDist[c], abs(si - p.x) + abs(sj - p.y));\n        }\n    }\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            int d = INF;\n            for (auto &p : pos[a]) for (auto &q : pos[b]) {\n                d = min(d, abs(p.x - q.x) + abs(p.y - q.y));\n            }\n            bestDist[a][b] = d;\n        }\n    }\n\n    // Overlap matrix and append lengths\n    vector<vector<int>> ov(M, vector<int>(M, 0));\n    vector<vector<int>> addLen(M, vector<int>(M, 5));\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) if (i != j) {\n            ov[i][j] = overlap5(t[i], t[j]);\n            addLen[i][j] = 5 - ov[i][j];\n        }\n    }\n\n    auto build_string = [&](const vector<int>& ord) -> string {\n        string s = t[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            s += t[ord[i]].substr(ov[ord[i - 1]][ord[i]]);\n        }\n        return s;\n    };\n\n    auto approx_type_cost_string = [&](const string& s) -> long long {\n        long long cost = startDist[s[0] - 'A'] + 1;\n        for (int i = 1; i < (int)s.size(); i++) {\n            cost += bestDist[s[i - 1] - 'A'][s[i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    auto score_order = [&](const vector<int>& ord) -> long long {\n        string s = build_string(ord);\n        return (long long)s.size() * 1000 + approx_type_cost_string(s);\n    };\n\n    // Construct initial order by best insertion\n    auto make_initial_order = [&](int seedStart) -> vector<int> {\n        vector<int> unused;\n        vector<char> used(M, 0);\n        for (int i = 0; i < M; i++) if (i != seedStart) unused.push_back(i);\n        vector<int> ord = {seedStart};\n        used[seedStart] = 1;\n\n        // choose second word\n        int best2 = -1;\n        long long bestVal = (1LL << 60);\n        for (int j : unused) {\n            vector<int> tmp = {seedStart, j};\n            long long val = score_order(tmp);\n            if (val < bestVal) {\n                bestVal = val;\n                best2 = j;\n            }\n        }\n        ord.push_back(best2);\n        used[best2] = 1;\n\n        // insert remaining words at best position\n        for (int rep = 2; rep < M; rep++) {\n            int bestWord = -1;\n            int bestPos = -1;\n            long long bestDelta = (1LL << 60);\n\n            for (int x = 0; x < M; x++) if (!used[x]) {\n                int L = ord.size();\n                for (int p = 0; p <= L; p++) {\n                    long long deltaLen = 0;\n                    if (L == 0) {\n                        deltaLen = 5;\n                    } else if (p == 0) {\n                        deltaLen = 5 - ov[x][ord[0]];\n                    } else if (p == L) {\n                        deltaLen = 5 - ov[ord[L - 1]][x];\n                    } else {\n                        int a = ord[p - 1];\n                        int b = ord[p];\n                        deltaLen = (5 - ov[a][x]) + (5 - ov[x][b]) - (5 - ov[a][b]);\n                    }\n\n                    // small movement-based tie break\n                    long long moveTie = 0;\n                    if (p == 0) {\n                        moveTie += bestDist[t[x][4] - 'A'][t[ord[0]][ov[x][ord[0]]] - 'A'];\n                    } else if (p == L) {\n                        moveTie += bestDist[t[ord[L - 1]][4] - 'A'][t[x][ov[ord[L - 1]][x]] - 'A'];\n                    }\n\n                    long long val = deltaLen * 1000 + moveTie;\n                    if (val < bestDelta) {\n                        bestDelta = val;\n                        bestWord = x;\n                        bestPos = p;\n                    }\n                }\n            }\n\n            ord.insert(ord.begin() + bestPos, bestWord);\n            used[bestWord] = 1;\n        }\n\n        return ord;\n    };\n\n    vector<int> bestOrder;\n    long long bestScore = (1LL << 60);\n\n    // multi-start using good first-word candidates\n    vector<pair<int,int>> starters;\n    for (int i = 0; i < M; i++) {\n        int c = t[i][0] - 'A';\n        int approx = startDist[c];\n        for (int k = 1; k < 5; k++) approx += bestDist[t[i][k - 1] - 'A'][t[i][k] - 'A'];\n        starters.push_back({approx, i});\n    }\n    sort(starters.begin(), starters.end());\n\n    int trials = min(M, 24);\n    for (int z = 0; z < trials && timer.elapsed() < 1.1; z++) {\n        int st = starters[z].second;\n        auto ord = make_initial_order(st);\n        long long sc = score_order(ord);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestOrder = ord;\n        }\n    }\n\n    // Local search: relocate and adjacent swap\n    auto improve_order = [&](vector<int> ord) -> vector<int> {\n        long long curScore = score_order(ord);\n        bool improved = true;\n        mt19937 rng(1234567);\n\n        while (improved && timer.elapsed() < 1.8) {\n            improved = false;\n\n            // random relocate\n            for (int it = 0; it < 200 && timer.elapsed() < 1.8; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                vector<int> tmp = ord;\n                int v = tmp[i];\n                tmp.erase(tmp.begin() + i);\n                tmp.insert(tmp.begin() + j, v);\n                long long ns = score_order(tmp);\n                if (ns < curScore) {\n                    ord.swap(tmp);\n                    curScore = ns;\n                    improved = true;\n                }\n            }\n\n            // adjacent swap sweep\n            for (int i = 0; i + 1 < M && timer.elapsed() < 1.8; i++) {\n                vector<int> tmp = ord;\n                swap(tmp[i], tmp[i + 1]);\n                long long ns = score_order(tmp);\n                if (ns < curScore) {\n                    ord.swap(tmp);\n                    curScore = ns;\n                    improved = true;\n                }\n            }\n        }\n        return ord;\n    };\n\n    bestOrder = improve_order(bestOrder);\n\n    string S = build_string(bestOrder);\n\n    // Safety: this should always hold by a huge margin\n    if ((int)S.size() > 5000) {\n        // Extremely unlikely; fallback to simple concatenation would also be <= 1000\n        S.clear();\n        for (int i = 0; i < M; i++) S += t[i];\n        if ((int)S.size() > 5000) S.resize(5000); // unreachable in this problem (200*5=1000)\n    }\n\n    // Exact DP for optimal coordinates for the chosen string\n    int L = (int)S.size();\n    vector<vector<int>> dp(L), pre(L);\n\n    {\n        int c = S[0] - 'A';\n        int sz = pos[c].size();\n        dp[0].assign(sz, INF);\n        pre[0].assign(sz, -1);\n        for (int j = 0; j < sz; j++) {\n            dp[0][j] = abs(si - pos[c][j].x) + abs(sj - pos[c][j].y) + 1;\n        }\n    }\n\n    for (int i = 1; i < L; i++) {\n        int pc = S[i - 1] - 'A';\n        int cc = S[i] - 'A';\n        int psz = pos[pc].size();\n        int csz = pos[cc].size();\n        dp[i].assign(csz, INF);\n        pre[i].assign(csz, -1);\n\n        for (int v = 0; v < csz; v++) {\n            int best = INF, bestu = -1;\n            for (int u = 0; u < psz; u++) {\n                int val = dp[i - 1][u]\n                        + abs(pos[pc][u].x - pos[cc][v].x)\n                        + abs(pos[pc][u].y - pos[cc][v].y) + 1;\n                if (val < best) {\n                    best = val;\n                    bestu = u;\n                }\n            }\n            dp[i][v] = best;\n            pre[i][v] = bestu;\n        }\n    }\n\n    int last = 0;\n    for (int j = 1; j < (int)dp[L - 1].size(); j++) {\n        if (dp[L - 1][j] < dp[L - 1][last]) last = j;\n    }\n\n    vector<Pos> ans(L);\n    int cur = last;\n    for (int i = L - 1; i >= 0; i--) {\n        int c = S[i] - 'A';\n        ans[i] = pos[c][cur];\n        if (i > 0) cur = pre[i][cur];\n    }\n\n    for (auto &p : ans) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<int> drillMaskIdx; // indices t such that this placement covers drilledList[t]\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    int h = 0, w = 0;\n    vector<Placement> plc;\n};\n\nstruct Solver {\n    int N, M;\n    double eps;\n    vector<Field> fields;\n\n    int maxOps, ops = 0;\n    vector<int> drilled;      // -1 unknown, else exact reserve\n    vector<int> drilledList;  // cell ids\n    vector<char> hasOil;      // final after full drilling fallback\n\n    Solver() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> M >> eps;\n        fields.resize(M);\n        for (int m = 0; m < M; m++) {\n            int d;\n            cin >> d;\n            fields[m].shape.resize(d);\n            int hi = 0, hj = 0;\n            for (int k = 0; k < d; k++) {\n                int i, j;\n                cin >> i >> j;\n                fields[m].shape[k] = {i, j};\n                hi = max(hi, i);\n                hj = max(hj, j);\n            }\n            fields[m].h = hi + 1;\n            fields[m].w = hj + 1;\n        }\n\n        maxOps = 2 * N * N;\n        drilled.assign(N * N, -1);\n        hasOil.assign(N * N, 0);\n\n        buildPlacements();\n    }\n\n    inline int id(int i, int j) const { return i * N + j; }\n    inline pair<int,int> rc(int c) const { return {c / N, c % N}; }\n\n    void buildPlacements() {\n        for (int m = 0; m < M; m++) {\n            auto &f = fields[m];\n            for (int di = 0; di + f.h <= N; di++) {\n                for (int dj = 0; dj + f.w <= N; dj++) {\n                    Placement p;\n                    for (auto [i, j] : f.shape) {\n                        p.cells.push_back(id(di + i, dj + j));\n                    }\n                    f.plc.push_back(move(p));\n                }\n            }\n        }\n    }\n\n    int drillCell(int c) {\n        auto [i, j] = rc(c);\n        cout << \"q 1 \" << i << \" \" << j << '\\n';\n        cout.flush();\n        int x;\n        cin >> x;\n        ++ops;\n        if (drilled[c] == -1) drilledList.push_back(c);\n        drilled[c] = x;\n        if (x > 0) hasOil[c] = 1;\n        return x;\n    }\n\n    bool answerCells(const vector<int>& cells) {\n        cout << \"a \" << cells.size();\n        for (int c : cells) {\n            auto [i, j] = rc(c);\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << '\\n';\n        cout.flush();\n        int res;\n        cin >> res;\n        ++ops;\n        return res == 1;\n    }\n\n    // ---------- Exact search for small instances ----------\n\n    vector<vector<int>> feasible;   // feasible placements per field under zero-cells only\n    vector<int> order;\n    vector<int> remainCanCover;     // flattened [pos * D + t]\n    vector<int> curSum;\n    vector<int> chosen;\n    vector<int> solChosen;\n    int solutionsFound = 0;\n    int dfsNodeBudget = 200000;     // hard cap for safety\n    int dfsNodes = 0;\n\n    bool placementCompatibleWithZero(int m, int pidx) {\n        for (int c : fields[m].plc[pidx].cells) {\n            if (drilled[c] == 0) return false;\n        }\n        return true;\n    }\n\n    void prepareSearch() {\n        int D = (int)drilledList.size();\n\n        feasible.assign(M, {});\n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                if (placementCompatibleWithZero(m, p)) {\n                    feasible[m].push_back(p);\n                }\n            }\n        }\n\n        order.resize(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return feasible[a].size() < feasible[b].size();\n        });\n\n        for (int m = 0; m < M; m++) {\n            for (int pidx : feasible[m]) {\n                auto &pl = fields[m].plc[pidx];\n                pl.drillMaskIdx.clear();\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    // linear scan over cells of shape; shapes are small enough\n                    for (int x : pl.cells) {\n                        if (x == c) {\n                            pl.drillMaskIdx.push_back(t);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        remainCanCover.assign((M + 1) * max(1, D), 0);\n        if (D > 0) {\n            for (int pos = M - 1; pos >= 0; pos--) {\n                int m = order[pos];\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    int can = 0;\n                    for (int pidx : feasible[m]) {\n                        for (int x : fields[m].plc[pidx].cells) {\n                            if (x == c) {\n                                can = 1;\n                                goto done;\n                            }\n                        }\n                    }\n                done:\n                    remainCanCover[pos * D + t] = remainCanCover[(pos + 1) * D + t] + can;\n                }\n            }\n        }\n\n        curSum.assign(D, 0);\n        chosen.assign(M, -1);\n        solChosen.clear();\n        solutionsFound = 0;\n        dfsNodes = 0;\n    }\n\n    void dfsSearch(int pos) {\n        if (solutionsFound >= 2) return;\n        if (++dfsNodes > dfsNodeBudget) return;\n\n        int D = (int)drilledList.size();\n        if (pos == M) {\n            for (int t = 0; t < D; t++) {\n                if (curSum[t] != drilled[drilledList[t]]) return;\n            }\n            ++solutionsFound;\n            if (solutionsFound == 1) solChosen = chosen;\n            return;\n        }\n\n        int m = order[pos];\n\n        // Try placements in heuristic order: match positive drilled cells more\n        vector<pair<int,int>> cand;\n        cand.reserve(feasible[m].size());\n        for (int pidx : feasible[m]) {\n            int score = 0;\n            for (int t : fields[m].plc[pidx].drillMaskIdx) {\n                if (drilled[drilledList[t]] > 0) score++;\n                else score -= 1000;\n            }\n            cand.push_back({-score, pidx});\n        }\n        sort(cand.begin(), cand.end());\n\n        for (auto [_, pidx] : cand) {\n            auto &pl = fields[m].plc[pidx];\n            bool ok = true;\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]++;\n            }\n\n            for (int t = 0; t < D; t++) {\n                int target = drilled[drilledList[t]];\n                if (curSum[t] > target) { ok = false; break; }\n                int rem = remainCanCover[(pos + 1) * D + t];\n                if (curSum[t] + rem < target) { ok = false; break; }\n            }\n\n            if (ok) {\n                chosen[m] = pidx;\n                dfsSearch(pos + 1);\n                chosen[m] = -1;\n            }\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]--;\n            }\n\n            if (solutionsFound >= 2 || dfsNodes > dfsNodeBudget) return;\n        }\n    }\n\n    bool tryExactSolve(vector<int>& ansCells, bool requireUnique) {\n        prepareSearch();\n\n        for (int m = 0; m < M; m++) {\n            if (feasible[m].empty()) return false;\n        }\n\n        dfsSearch(0);\n\n        if (dfsNodes > dfsNodeBudget) return false;\n        if (solutionsFound == 0) return false;\n        if (requireUnique && solutionsFound != 1) return false;\n\n        vector<char> used(N * N, 0);\n        for (int m = 0; m < M; m++) {\n            int pidx = solChosen[m];\n            if (pidx < 0) return false;\n            for (int c : fields[m].plc[pidx].cells) used[c] = 1;\n        }\n\n        for (int c : drilledList) {\n            if ((drilled[c] == 0 && used[c]) || (drilled[c] > 0 && !used[c])) {\n                return false;\n            }\n        }\n\n        ansCells.clear();\n        for (int c = 0; c < N * N; c++) if (used[c]) ansCells.push_back(c);\n        return true;\n    }\n\n    // ---------- Strategy ----------\n\n    vector<int> informativeOrder() {\n        // deterministic spread: checkerboard center-first-ish\n        vector<int> cells;\n        cells.reserve(N * N);\n        vector<pair<int,int>> tmp;\n        double ci = (N - 1) / 2.0, cj = (N - 1) / 2.0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int parity = (i + j) & 1;\n                int dist = (int)(1000 * (abs(i - ci) + abs(j - cj)));\n                tmp.push_back({parity * 100000 + dist, id(i, j)});\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        for (auto &x : tmp) cells.push_back(x.second);\n        return cells;\n    }\n\n    void fullDrillFallback() {\n        for (int c = 0; c < N * N && ops < maxOps - 1; c++) {\n            if (drilled[c] == -1) drillCell(c);\n        }\n        vector<int> ans;\n        for (int c = 0; c < N * N; c++) if (drilled[c] > 0) ans.push_back(c);\n        answerCells(ans);\n    }\n\n    void solve() {\n        // Only attempt exact reasoning when likely cheap.\n        long long totalPlacements = 0;\n        for (int m = 0; m < M; m++) totalPlacements += fields[m].plc.size();\n\n        bool useSearch = (M <= 8 && totalPlacements <= 700);\n\n        if (!useSearch) {\n            fullDrillFallback();\n            return;\n        }\n\n        // Small-instance mode:\n        // Drill a modest number of informative cells, trying to pin down unique placement combo.\n        vector<int> orderCells = informativeOrder();\n        int initialDrills = min<int>(N * N, max(12, N));\n\n        for (int t = 0; t < initialDrills && ops < maxOps - 1; t++) {\n            int c = orderCells[t];\n            if (drilled[c] == -1) drillCell(c);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // If not yet unique, continue a bit more adaptively: drill cells appearing often in candidate answer.\n        for (int extra = initialDrills; extra < min(N * N, initialDrills + 20) && ops < maxOps - 1; extra++) {\n            int best = -1, bestScore = -1;\n\n            for (int c = 0; c < N * N; c++) if (drilled[c] == -1) {\n                int score = 0;\n                for (int m = 0; m < M; m++) {\n                    for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                        if (!placementCompatibleWithZero(m, p)) continue;\n                        for (int x : fields[m].plc[p].cells) {\n                            if (x == c) { score++; break; }\n                        }\n                    }\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = c;\n                }\n            }\n\n            if (best == -1) break;\n            drillCell(best);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // Fallback: guaranteed correct\n        fullDrillFallback();\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const int W = 1000;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nstruct Layout {\n    ll penalty = (1LL << 62); // only shortage penalty; transition cost = 0\n    vector<Rect> rects;\n};\n\nstatic inline ll miss_with_cap(const vector<int>& vals, int cap) {\n    ll s = 0;\n    for (int x : vals) if (x > cap) s += (x - cap);\n    return s;\n}\n\nstatic pair<ll, vector<int>> optimize_strip(\n    const vector<vector<int>>& a_by_k, int l, int r, int h\n) {\n    int m = r - l;\n    vector<int> width(m, 1);\n    int rem = W - m;\n\n    // gain[z][t] = reduction in shortage if width goes t -> t+1\n    vector<vector<int>> gain(m, vector<int>(W, 0));\n    for (int z = 0; z < m; z++) {\n        const auto& vals = a_by_k[l + z];\n        for (int t = 0; t < W; t++) {\n            int c0 = h * t;\n            int c1 = h * (t + 1);\n            int g = 0;\n            for (int x : vals) {\n                int before = max(0, x - c0);\n                int after  = max(0, x - c1);\n                g += before - after;\n            }\n            gain[z][t] = g;\n        }\n    }\n\n    using T = pair<int,int>; // gain, z\n    priority_queue<T> pq;\n    for (int z = 0; z < m; z++) pq.push({gain[z][1], z});\n\n    while (rem > 0) {\n        auto [g, z] = pq.top(); pq.pop();\n        int t = width[z];\n        int realg = (t < W ? gain[z][t] : 0);\n        if (g != realg) {\n            pq.push({realg, z});\n            continue;\n        }\n        width[z]++;\n        rem--;\n        t = width[z];\n        pq.push({(t < W ? gain[z][t] : 0), z});\n    }\n\n    // Local improvement: move 1 width unit from i to j if improves.\n    vector<ll> curmiss(m);\n    for (int z = 0; z < m; z++) curmiss[z] = miss_with_cap(a_by_k[l + z], h * width[z]);\n\n    bool improved = true;\n    for (int iter = 0; iter < 3 && improved; iter++) {\n        improved = false;\n        ll best_delta = 0;\n        int bi = -1, bj = -1;\n        for (int i = 0; i < m; i++) {\n            if (width[i] <= 1) continue;\n            int cap_i_old = h * width[i];\n            int cap_i_new = h * (width[i] - 1);\n            ll newmiss_i = miss_with_cap(a_by_k[l + i], cap_i_new);\n            for (int j = 0; j < m; j++) if (i != j) {\n                int cap_j_new = h * (width[j] + 1);\n                ll newmiss_j = miss_with_cap(a_by_k[l + j], cap_j_new);\n                ll delta = (newmiss_i + newmiss_j) - (curmiss[i] + curmiss[j]);\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    bi = i;\n                    bj = j;\n                }\n            }\n        }\n        if (best_delta < 0) {\n            width[bi]--;\n            width[bj]++;\n            curmiss[bi] = miss_with_cap(a_by_k[l + bi], h * width[bi]);\n            curmiss[bj] = miss_with_cap(a_by_k[l + bj], h * width[bj]);\n            improved = true;\n        }\n    }\n\n    ll miss = 0;\n    for (int z = 0; z < m; z++) miss += curmiss[z];\n    return {miss, width};\n}\n\n// orientation = 0:\n//   horizontal strips, vertical cuts inside\n// orientation = 1:\n//   vertical strips, horizontal cuts inside\nstatic Layout build_layout(\n    const vector<vector<int>>& a_by_k,\n    const vector<int>& cuts,\n    int orientation\n) {\n    int N = (int)a_by_k.size();\n    int R = (int)cuts.size() - 1;\n\n    Layout res;\n    res.rects.assign(N, {0,0,1,1});\n\n    vector<ll> group_sum(R, 0);\n    ll total = 0;\n    for (int g = 0; g < R; g++) {\n        int l = cuts[g], r = cuts[g + 1];\n        ll s = 0;\n        for (int k = l; k < r; k++) {\n            for (int x : a_by_k[k]) s += x;\n        }\n        group_sum[g] = s;\n        total += s;\n    }\n    if (total == 0) total = 1;\n\n    vector<int> h(R, 1);\n    vector<pair<double,int>> frac;\n    frac.reserve(R);\n    int used = 0;\n    for (int g = 0; g < R; g++) {\n        double ideal = (double)W * (double)group_sum[g] / (double)total;\n        int base = max(1, (int)floor(ideal));\n        h[g] = base;\n        used += base;\n        frac.push_back({ideal - base, g});\n    }\n\n    if (used > W) {\n        vector<int> ord(R);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int x, int y) { return h[x] > h[y]; });\n        int need = used - W;\n        for (int g : ord) {\n            int dec = min(need, h[g] - 1);\n            h[g] -= dec;\n            need -= dec;\n            if (need == 0) break;\n        }\n        if (need > 0) return res;\n    } else if (used < W) {\n        int need = W - used;\n        sort(frac.begin(), frac.end(), greater<>());\n        for (int i = 0; i < need; i++) h[frac[i % R].second]++;\n    }\n\n    vector<vector<int>> widths(R);\n    ll miss = 0;\n    for (int g = 0; g < R; g++) {\n        int l = cuts[g], r = cuts[g + 1];\n        auto [mcur, wcur] = optimize_strip(a_by_k, l, r, h[g]);\n        miss += mcur;\n        widths[g] = move(wcur);\n    }\n\n    int pos_outer = 0;\n    for (int g = 0; g < R; g++) {\n        int l = cuts[g], r = cuts[g + 1];\n        int outer2 = pos_outer + h[g];\n        int pos_inner = 0;\n        for (int z = 0; z < r - l; z++) {\n            int inner2 = pos_inner + widths[g][z];\n            if (orientation == 0) {\n                res.rects[l + z] = {pos_outer, pos_inner, outer2, inner2};\n            } else {\n                res.rects[l + z] = {pos_inner, pos_outer, inner2, outer2};\n            }\n            pos_inner = inner2;\n        }\n        pos_outer = outer2;\n    }\n\n    res.penalty = miss * 100;\n    return res;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Win, D, N;\n    cin >> Win >> 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    vector<vector<int>> a_by_k(N, vector<int>(D));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) a_by_k[k][d] = a[d][k];\n    }\n\n    vector<ll> agg(N, 0), pref(N + 1, 0);\n    for (int k = 0; k < N; k++) {\n        for (int d = 0; d < D; d++) agg[k] += a[d][k];\n        pref[k + 1] = pref[k] + agg[k];\n    }\n\n    auto balanced_cuts = [&](int R) {\n        vector<int> cuts;\n        cuts.push_back(0);\n        for (int t = 1; t < R; t++) {\n            ll target = pref[N] * t / R;\n            int pos = (int)(lower_bound(pref.begin(), pref.end(), target) - pref.begin());\n            pos = max(pos, cuts.back() + 1);\n            pos = min(pos, N - (R - t));\n            cuts.push_back(pos);\n        }\n        cuts.push_back(N);\n        return cuts;\n    };\n\n    auto equal_cuts = [&](int R) {\n        vector<int> cuts(R + 1);\n        cuts[0] = 0;\n        cuts[R] = N;\n        for (int t = 1; t < R; t++) cuts[t] = (int)((ll)N * t / R);\n        for (int t = 1; t < R; t++) cuts[t] = max(cuts[t], cuts[t - 1] + 1);\n        for (int t = R - 1; t >= 1; t--) cuts[t] = min(cuts[t], cuts[t + 1] - 1);\n        return cuts;\n    };\n\n    Layout best;\n    best.penalty = (1LL << 62);\n\n    int maxR = min(N, 6);\n    for (int R = 1; R <= maxR; R++) {\n        vector<vector<int>> candidates;\n\n        if (R == 1) {\n            candidates.push_back({0, N});\n        } else {\n            auto b = balanced_cuts(R);\n            auto e = equal_cuts(R);\n            candidates.push_back(b);\n            candidates.push_back(e);\n\n            // small perturbations of balanced cuts\n            for (int idx = 1; idx < R; idx++) {\n                for (int dlt : {-1, +1}) {\n                    vector<int> c = b;\n                    c[idx] += dlt;\n                    bool ok = true;\n                    for (int i = 1; i < R; i++) {\n                        if (!(c[i-1] < c[i] && c[i] < c[i+1])) ok = false;\n                    }\n                    if (ok) candidates.push_back(c);\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        for (const auto& cuts : candidates) {\n            for (int orientation = 0; orientation < 2; orientation++) {\n                Layout cur = build_layout(a_by_k, cuts, orientation);\n                if (cur.penalty < best.penalty) best = move(cur);\n            }\n        }\n    }\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const auto& r = best.rects[k];\n            cout << r.i0 << ' ' << r.j0 << ' ' << r.i1 << ' ' << r.j1 << '\\n';\n        }\n    }\n\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 9;\nstatic constexpr int POS = 7;\nstatic constexpr int MOD = 998244353;\nstatic constexpr int K = 81;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double ms() const {\n        return chrono::duration<double, milli>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct RNG {\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    double rand01() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nusing Board = array<int, 81>;\n\nstruct Action {\n    int m, p, q;\n    int idx[9];\n    int add[9];\n};\n\nstruct Candidate {\n    long long gain;\n    int act;\n};\n\nstruct Node {\n    Board b;\n    long long score;\n    long long eval;\n    vector<unsigned short> seq;\n};\n\nvector<Action> actions;\n\nstatic inline long long cell_gain(int cur, int add) {\n    int s = cur + add;\n    return (s >= MOD) ? (long long)add - MOD : (long long)add;\n}\n\nstatic inline long long action_gain(const Board& b, int act) {\n    const auto& a = actions[act];\n    long long g = 0;\n    for (int i = 0; i < 9; i++) g += cell_gain(b[a.idx[i]], a.add[i]);\n    return g;\n}\n\nstatic inline void apply_action(Board& b, int act) {\n    const auto& a = actions[act];\n    for (int i = 0; i < 9; i++) {\n        int &v = b[a.idx[i]];\n        v += a.add[i];\n        if (v >= MOD) v -= MOD;\n    }\n}\n\nlong long best_single_gain(const Board& b) {\n    long long best = 0;\n    for (int i = 0; i < (int)actions.size(); i++) {\n        long long g = action_gain(b, i);\n        if (g > best) best = g;\n    }\n    return best;\n}\n\nvector<Candidate> top_actions(const Board& b, int need, int random_pool_extra = 0) {\n    vector<Candidate> cand;\n    cand.reserve(actions.size());\n    for (int i = 0; i < (int)actions.size(); i++) {\n        long long g = action_gain(b, i);\n        if (g > 0) cand.push_back({g, i});\n    }\n    if (cand.empty()) return cand;\n\n    int keep = min((int)cand.size(), max(need, need + random_pool_extra));\n    nth_element(cand.begin(), cand.begin() + keep - 1, cand.end(),\n        [](const Candidate& a, const Candidate& b) { return a.gain > b.gain; });\n    cand.resize(keep);\n    sort(cand.begin(), cand.end(),\n        [](const Candidate& a, const Candidate& b) {\n            if (a.gain != b.gain) return a.gain > b.gain;\n            return a.act < b.act;\n        });\n\n    if ((int)cand.size() <= need) return cand;\n\n    vector<Candidate> res;\n    res.reserve(need);\n\n    int fixed = max(1, need / 2);\n    for (int i = 0; i < fixed; i++) res.push_back(cand[i]);\n\n    vector<int> ids;\n    for (int i = fixed; i < (int)cand.size(); i++) ids.push_back(i);\n    while ((int)res.size() < need && !ids.empty()) {\n        int j = rng.randint(0, (int)ids.size() - 1);\n        res.push_back(cand[ids[j]]);\n        ids[j] = ids.back();\n        ids.pop_back();\n    }\n    return res;\n}\n\npair<long long, Board> eval_sequence(const Board& init, const vector<int>& seq) {\n    Board b = init;\n    long long score = 0;\n    for (int act : seq) {\n        long long g = action_gain(b, act);\n        if (g <= 0) break;\n        apply_action(b, act);\n        score += g;\n    }\n    return {score, b};\n}\n\nvector<int> greedy_complete(Board b, int remain, bool randomized = true) {\n    vector<int> seq;\n    seq.reserve(remain);\n    for (int step = 0; step < remain; step++) {\n        auto cand = top_actions(b, randomized ? 14 : 24, randomized ? 18 : 0);\n        if (cand.empty()) break;\n\n        long long bestEval = LLONG_MIN;\n        int bestAct = -1;\n\n        for (auto &c : cand) {\n            Board nb = b;\n            apply_action(nb, c.act);\n            long long h1 = best_single_gain(nb);\n            long long eval = c.gain + h1;\n\n            if (randomized) {\n                // Mild randomization to diversify runs\n                eval += rng.randint(0, 2000);\n            }\n\n            if (eval > bestEval) {\n                bestEval = eval;\n                bestAct = c.act;\n            }\n        }\n\n        if (bestAct < 0) break;\n        apply_action(b, bestAct);\n        seq.push_back(bestAct);\n    }\n    return seq;\n}\n\nvector<int> construct_solution(const Board& initial, const Timer& timer, double deadline_ms) {\n    int BEAM_WIDTH = 56;\n    int BRANCH = 14;\n    int DEPTH = 12;\n\n    vector<Node> beam, nxt;\n    beam.reserve(BEAM_WIDTH);\n    nxt.reserve(BEAM_WIDTH * BRANCH);\n\n    Node root;\n    root.b = initial;\n    root.score = 0;\n    root.eval = 0;\n    beam.push_back(root);\n\n    for (int d = 0; d < DEPTH; d++) {\n        if (timer.ms() > deadline_ms) break;\n        nxt.clear();\n\n        for (const auto& node : beam) {\n            auto cand = top_actions(node.b, BRANCH, 16);\n            if (cand.empty()) {\n                nxt.push_back(node);\n                continue;\n            }\n\n            for (auto &c : cand) {\n                Node child;\n                child.b = node.b;\n                apply_action(child.b, c.act);\n                child.score = node.score + c.gain;\n                child.seq = node.seq;\n                child.seq.push_back((unsigned short)c.act);\n\n                // heuristic = current score + best next gain + small diversity\n                long long h = best_single_gain(child.b);\n                child.eval = child.score + h + rng.randint(0, 1000);\n                nxt.push_back(std::move(child));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        int keep = min((int)nxt.size(), BEAM_WIDTH);\n        nth_element(nxt.begin(), nxt.begin() + keep - 1, nxt.end(),\n            [](const Node& a, const Node& b) {\n                if (a.eval != b.eval) return a.eval > b.eval;\n                return a.score > b.score;\n            });\n        nxt.resize(keep);\n        sort(nxt.begin(), nxt.end(),\n            [](const Node& a, const Node& b) {\n                if (a.eval != b.eval) return a.eval > b.eval;\n                return a.score > b.score;\n            });\n        beam.swap(nxt);\n    }\n\n    long long bestScore = -1;\n    vector<int> bestSeq;\n\n    int use = min(10, (int)beam.size());\n    for (int i = 0; i < use; i++) {\n        if (timer.ms() > deadline_ms) break;\n        vector<int> seq;\n        seq.reserve(K);\n        for (auto x : beam[i].seq) seq.push_back((int)x);\n\n        auto [prefixScore, b] = eval_sequence(initial, seq);\n        auto tail = greedy_complete(b, K - (int)seq.size(), true);\n        seq.insert(seq.end(), tail.begin(), tail.end());\n\n        auto [score, _] = eval_sequence(initial, seq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(seq);\n        }\n    }\n\n    while (timer.ms() < deadline_ms) {\n        auto seq = greedy_complete(initial, K, true);\n        auto [score, _] = eval_sequence(initial, seq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(seq);\n        }\n    }\n\n    return bestSeq;\n}\n\nvoid rebuild_prefix_data(const Board& initial, const vector<int>& seq, vector<Board>& pref, vector<long long>& scr) {\n    pref.assign(seq.size() + 1, Board{});\n    scr.assign(seq.size() + 1, 0);\n    pref[0] = initial;\n\n    int real_len = 0;\n    for (int i = 0; i < (int)seq.size(); i++) {\n        pref[i + 1] = pref[i];\n        long long g = action_gain(pref[i + 1], seq[i]);\n        if (g <= 0) break;\n        apply_action(pref[i + 1], seq[i]);\n        scr[i + 1] = scr[i] + g;\n        real_len = i + 1;\n    }\n\n    pref.resize(real_len + 1);\n    scr.resize(real_len + 1);\n}\n\nvector<int> rebuild_from_prefix(const Board& initial, const vector<int>& prefix) {\n    Board b = initial;\n    vector<int> seq;\n    seq.reserve(K);\n\n    for (int act : prefix) {\n        long long g = action_gain(b, act);\n        if (g <= 0) return seq;\n        apply_action(b, act);\n        seq.push_back(act);\n    }\n\n    auto tail = greedy_complete(b, K - (int)seq.size(), true);\n    seq.insert(seq.end(), tail.begin(), tail.end());\n    return seq;\n}\n\nvoid local_improve(const Board& initial, vector<int>& bestSeq, long long& bestScore,\n                   const Timer& timer, double deadline_ms) {\n    vector<Board> pref;\n    vector<long long> scr;\n    rebuild_prefix_data(initial, bestSeq, pref, scr);\n\n    auto try_update = [&](vector<int>& candSeq) {\n        auto [score, _] = eval_sequence(initial, candSeq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(candSeq);\n            rebuild_prefix_data(initial, bestSeq, pref, scr);\n            return true;\n        }\n        return false;\n    };\n\n    while (timer.ms() < deadline_ms) {\n        int len = (int)pref.size() - 1;\n        if (len <= 0) break;\n\n        int mode = rng.randint(0, 99);\n\n        // 1) Rebuild suffix from t\n        if (mode < 30) {\n            int t = rng.randint(0, len);\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            auto cand = rebuild_from_prefix(initial, prefix);\n            try_update(cand);\n        }\n        // 2) Replace one move at t\n        else if (mode < 75) {\n            int t = rng.randint(0, len - 1);\n            Board b = pref[t];\n            auto candActs = top_actions(b, 10, 12);\n            if (candActs.empty()) continue;\n\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            long long localBest = bestScore;\n            vector<int> localSeq;\n\n            for (auto &ca : candActs) {\n                if (timer.ms() > deadline_ms) break;\n                vector<int> seq = prefix;\n                seq.push_back(ca.act);\n\n                Board nb = b;\n                long long g = action_gain(nb, ca.act);\n                if (g <= 0) continue;\n                apply_action(nb, ca.act);\n\n                auto tail = greedy_complete(nb, K - (int)seq.size(), true);\n                seq.insert(seq.end(), tail.begin(), tail.end());\n\n                auto [score, _] = eval_sequence(initial, seq);\n                if (score > localBest) {\n                    localBest = score;\n                    localSeq = std::move(seq);\n                }\n            }\n\n            if (!localSeq.empty()) {\n                bestScore = localBest;\n                bestSeq = std::move(localSeq);\n                rebuild_prefix_data(initial, bestSeq, pref, scr);\n            }\n        }\n        // 3) Replace two moves at t,t+1 with small 2-step search\n        else {\n            int t = rng.randint(0, max(0, len - 1));\n            Board b = pref[t];\n            auto firsts = top_actions(b, 6, 8);\n            if (firsts.empty()) continue;\n\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            long long localBest = bestScore;\n            vector<int> localSeq;\n\n            for (auto &c1 : firsts) {\n                if (timer.ms() > deadline_ms) break;\n                Board b1 = b;\n                long long g1 = action_gain(b1, c1.act);\n                if (g1 <= 0) continue;\n                apply_action(b1, c1.act);\n\n                auto seconds = top_actions(b1, 5, 6);\n                if (seconds.empty()) {\n                    vector<int> seq = prefix;\n                    seq.push_back(c1.act);\n                    auto tail = greedy_complete(b1, K - (int)seq.size(), true);\n                    seq.insert(seq.end(), tail.begin(), tail.end());\n                    auto [score, _] = eval_sequence(initial, seq);\n                    if (score > localBest) {\n                        localBest = score;\n                        localSeq = std::move(seq);\n                    }\n                    continue;\n                }\n\n                for (auto &c2 : seconds) {\n                    if (timer.ms() > deadline_ms) break;\n                    Board b2 = b1;\n                    long long g2 = action_gain(b2, c2.act);\n                    if (g2 <= 0) continue;\n                    apply_action(b2, c2.act);\n\n                    vector<int> seq = prefix;\n                    seq.push_back(c1.act);\n                    seq.push_back(c2.act);\n\n                    auto tail = greedy_complete(b2, K - (int)seq.size(), true);\n                    seq.insert(seq.end(), tail.begin(), tail.end());\n\n                    auto [score, _] = eval_sequence(initial, seq);\n                    if (score > localBest) {\n                        localBest = score;\n                        localSeq = std::move(seq);\n                    }\n                }\n            }\n\n            if (!localSeq.empty()) {\n                bestScore = localBest;\n                bestSeq = std::move(localSeq);\n                rebuild_prefix_data(initial, bestSeq, pref, scr);\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin, Min, Kin;\n    cin >> Nin >> Min >> Kin;\n\n    Board initial{};\n    for (int i = 0; i < Nin; i++) {\n        for (int j = 0; j < Nin; j++) {\n            cin >> initial[i * N + j];\n        }\n    }\n\n    vector<array<array<int, 3>, 3>> stamps(Min);\n    for (int m = 0; m < Min; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    actions.clear();\n    actions.reserve(Min * POS * POS);\n    for (int m = 0; m < Min; m++) {\n        for (int p = 0; p < POS; p++) {\n            for (int q = 0; q < POS; q++) {\n                Action a;\n                a.m = m;\n                a.p = p;\n                a.q = q;\n                int t = 0;\n                for (int i = 0; i < 3; i++) {\n                    for (int j = 0; j < 3; j++) {\n                        a.idx[t] = (p + i) * N + (q + j);\n                        a.add[t] = stamps[m][i][j];\n                        t++;\n                    }\n                }\n                actions.push_back(a);\n            }\n        }\n    }\n\n    Timer timer;\n    const double TOTAL_MS = 1850.0;\n\n    long long bestScore = -1;\n    vector<int> bestSeq;\n\n    // Multi-start constructive phase\n    while (timer.ms() < TOTAL_MS * 0.50) {\n        auto seq = construct_solution(initial, timer, TOTAL_MS * 0.50);\n        auto [score, _] = eval_sequence(initial, seq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(seq);\n        }\n    }\n\n    // Fallback\n    if (bestSeq.empty()) {\n        bestSeq = greedy_complete(initial, K, false);\n        bestScore = eval_sequence(initial, bestSeq).first;\n    }\n\n    // Strong local improvement phase\n    local_improve(initial, bestSeq, bestScore, timer, TOTAL_MS);\n\n    if ((int)bestSeq.size() > Kin) bestSeq.resize(Kin);\n\n    cout << bestSeq.size() << '\\n';\n    for (int act : bestSeq) {\n        const auto& a = actions[act];\n        cout << a.m << ' ' << a.p << ' ' << a.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int TOTAL = 25;\n\n// Beam width: can be tuned.\nstatic constexpr int BEAM_WIDTH = 600;\n\nstruct Node {\n    array<uint8_t, N> ptr{};                 // extracted count per input row\n    array<uint8_t, N> outCnt{};              // dispatched count per output row\n    array<array<uint8_t, N>, N> outSeq{};    // exact dispatched sequence per output row\n    uint8_t cr = 0, cc = 0;                  // large crane position\n    uint8_t delivered = 0;\n    int turns = 0;\n    int inv = 0;\n    int prev = -1;                           // index in previous layer\n    uint8_t actionRow = 0;                   // chosen input row from prev -> this\n};\n\nstatic inline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstatic inline int inversion_add(const Node& nd, int outRow, int x) {\n    int add = 0;\n    for (int i = 0; i < nd.outCnt[outRow]; i++) {\n        if ((int)nd.outSeq[outRow][i] > x) add++;\n    }\n    return add;\n}\n\nstatic inline long long node_score(const Node& nd) {\n    return (long long)nd.turns + 100LL * nd.inv;\n}\n\nstatic inline long long optimistic_remaining(const Node& nd, const vector<vector<int>>& A) {\n    int rem = TOTAL - nd.delivered;\n    if (rem == 0) return 0;\n\n    // Base lower bound: each remaining job needs at least P,Q and 4 horizontal moves\n    long long lb = 6LL * rem;\n\n    // Plus at least distance from current position to some remaining source gate.\n    int bestToAnySrc = 100;\n    for (int i = 0; i < N; i++) {\n        if (nd.ptr[i] < N) {\n            bestToAnySrc = min(bestToAnySrc, manhattan(nd.cr, nd.cc, i, 0));\n        }\n    }\n    if (bestToAnySrc < 100) lb += bestToAnySrc;\n\n    // Very weak inversion optimism: zero additional inversions.\n    (void)A;\n    return lb;\n}\n\nstatic inline long long eval_node(const Node& nd, const vector<vector<int>>& A) {\n    return node_score(nd) + optimistic_remaining(nd, A);\n}\n\nstatic Node apply_action(const Node& cur, const vector<vector<int>>& A, int inRow) {\n    Node nxt = cur;\n    int x = A[inRow][cur.ptr[inRow]];\n    int outRow = x / N;\n\n    nxt.turns += manhattan(cur.cr, cur.cc, inRow, 0);\n    nxt.cr = inRow; nxt.cc = 0;\n\n    nxt.turns += 1; // P\n    nxt.ptr[inRow]++;\n\n    nxt.turns += manhattan(nxt.cr, nxt.cc, outRow, N - 1);\n    nxt.cr = outRow; nxt.cc = N - 1;\n\n    nxt.turns += 1; // Q\n\n    nxt.inv += inversion_add(cur, outRow, x);\n    nxt.outSeq[outRow][nxt.outCnt[outRow]++] = (uint8_t)x;\n    nxt.delivered++;\n\n    return nxt;\n}\n\n// A compact-ish signature for dedup.\n// We intentionally omit full output sequence; this means dedup is approximate.\n// To compensate, we keep the better score only. In practice this works well.\nstatic unsigned long long signature(const Node& nd) {\n    unsigned long long x = 0;\n    for (int i = 0; i < N; i++) x = x * 6 + nd.ptr[i];\n    for (int i = 0; i < N; i++) x = x * 6 + nd.outCnt[i];\n    x = x * 5 + nd.cr;\n    x = x * 5 + nd.cc;\n    return x;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> 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<vector<Node>> layers(TOTAL + 1);\n    layers[0].push_back(Node());\n\n    for (int depth = 0; depth < TOTAL; depth++) {\n        vector<Node> cand;\n        cand.reserve(layers[depth].size() * N);\n\n        for (int idx = 0; idx < (int)layers[depth].size(); idx++) {\n            const Node& cur = layers[depth][idx];\n            for (int inRow = 0; inRow < N; inRow++) {\n                if (cur.ptr[inRow] >= N) continue;\n                Node nxt = apply_action(cur, A, inRow);\n                nxt.prev = idx;\n                nxt.actionRow = (uint8_t)inRow;\n                cand.push_back(std::move(nxt));\n            }\n        }\n\n        // Pre-prune by eval score\n        vector<int> ord(cand.size());\n        iota(ord.begin(), ord.end(), 0);\n        nth_element(ord.begin(),\n                    ord.begin() + min((int)ord.size(), BEAM_WIDTH * 3),\n                    ord.end(),\n                    [&](int a, int b) {\n                        long long ea = eval_node(cand[a], A);\n                        long long eb = eval_node(cand[b], A);\n                        if (ea != eb) return ea < eb;\n                        return node_score(cand[a]) < node_score(cand[b]);\n                    });\n        int keepPre = min((int)ord.size(), BEAM_WIDTH * 3);\n\n        unordered_map<unsigned long long, int> bestIdx;\n        bestIdx.reserve(keepPre * 2 + 1);\n        vector<Node> nxtLayer;\n        nxtLayer.reserve(BEAM_WIDTH);\n\n        auto better = [&](const Node& a, const Node& b) {\n            long long sa = node_score(a), sb = node_score(b);\n            if (sa != sb) return sa < sb;\n            // tie-break: less turns, then fewer inversions\n            if (a.turns != b.turns) return a.turns < b.turns;\n            return a.inv < b.inv;\n        };\n\n        for (int t = 0; t < keepPre; t++) {\n            Node& nd = cand[ord[t]];\n            unsigned long long sig = signature(nd);\n            auto it = bestIdx.find(sig);\n            if (it == bestIdx.end()) {\n                bestIdx[sig] = (int)nxtLayer.size();\n                nxtLayer.push_back(nd);\n            } else {\n                if (better(nd, nxtLayer[it->second])) {\n                    nxtLayer[it->second] = nd;\n                }\n            }\n        }\n\n        sort(nxtLayer.begin(), nxtLayer.end(), [&](const Node& a, const Node& b) {\n            long long ea = eval_node(a, A);\n            long long eb = eval_node(b, A);\n            if (ea != eb) return ea < eb;\n            long long sa = node_score(a), sb = node_score(b);\n            if (sa != sb) return sa < sb;\n            return a.turns < b.turns;\n        });\n        if ((int)nxtLayer.size() > BEAM_WIDTH) nxtLayer.resize(BEAM_WIDTH);\n\n        layers[depth + 1] = std::move(nxtLayer);\n    }\n\n    // Choose best terminal node by true score.\n    int bestIdx = 0;\n    for (int i = 1; i < (int)layers[TOTAL].size(); i++) {\n        if (node_score(layers[TOTAL][i]) < node_score(layers[TOTAL][bestIdx])) {\n            bestIdx = i;\n        }\n    }\n\n    // Reconstruct chosen input rows.\n    vector<int> plan;\n    plan.reserve(TOTAL);\n    int idx = bestIdx;\n    for (int depth = TOTAL; depth >= 1; depth--) {\n        const Node& nd = layers[depth][idx];\n        plan.push_back(nd.actionRow);\n        idx = nd.prev;\n    }\n    reverse(plan.begin(), plan.end());\n\n    // Generate actual output strings.\n    vector<string> ans(N);\n\n    auto add_turn = [&](char c0, char c1='.', char c2='.', char c3='.', char c4='.') {\n        ans[0].push_back(c0);\n        ans[1].push_back(c1);\n        ans[2].push_back(c2);\n        ans[3].push_back(c3);\n        ans[4].push_back(c4);\n    };\n\n    // Safest setting: only large crane is active.\n    add_turn('.', 'B', 'B', 'B', 'B');\n\n    int cr = 0, cc = 0;\n    array<int, N> ptr{};\n    ptr.fill(0);\n\n    auto move_large = [&](int tr, int tc) {\n        while (cr < tr) { add_turn('D'); cr++; }\n        while (cr > tr) { add_turn('U'); cr--; }\n        while (cc < tc) { add_turn('R'); cc++; }\n        while (cc > tc) { add_turn('L'); cc--; }\n    };\n\n    for (int inRow : plan) {\n        int x = A[inRow][ptr[inRow]];\n        int outRow = x / N;\n\n        move_large(inRow, 0);\n        add_turn('P');\n        ptr[inRow]++;\n\n        move_large(outRow, N - 1);\n        add_turn('Q');\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (ans[i].empty()) ans[i] = \".\";\n        cout << ans[i] << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int TURN_LIMIT = 100000;\nstatic constexpr ll INF64 = (1LL << 60);\n\nstruct Result {\n    vector<string> ops;\n    ll cost = INF64;\n    bool finished = false;\n};\n\nstruct Simulator {\n    int N;\n    vector<vector<int>> h;\n    int x = 0, y = 0;\n    ll load = 0;\n    ll cost = 0;\n    vector<string> ops;\n    int cap;\n\n    Simulator(int n, const vector<vector<int>>& init_h, int cap_)\n        : N(n), h(init_h), cap(cap_) {}\n\n    inline int dist(int x1, int y1, int x2, int y2) const {\n        return abs(x1 - x2) + abs(y1 - y2);\n    }\n\n    bool can_continue(int reserve = 0) const {\n        return (int)ops.size() < TURN_LIMIT - reserve;\n    }\n\n    void emit(const string& s) {\n        if ((int)ops.size() < TURN_LIMIT) ops.push_back(s);\n    }\n\n    void move_one(char c) {\n        emit(string(1, c));\n        cost += 100 + load;\n        if (c == 'U') --x;\n        else if (c == 'D') ++x;\n        else if (c == 'L') --y;\n        else if (c == 'R') ++y;\n    }\n\n    void move_to(int nx, int ny) {\n        while (x < nx && (int)ops.size() < TURN_LIMIT) move_one('D');\n        while (x > nx && (int)ops.size() < TURN_LIMIT) move_one('U');\n        while (y < ny && (int)ops.size() < TURN_LIMIT) move_one('R');\n        while (y > ny && (int)ops.size() < TURN_LIMIT) move_one('L');\n    }\n\n    void pickup(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"+\" + to_string(d));\n        cost += d;\n        h[x][y] -= d;\n        load += d;\n    }\n\n    void dropoff(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"-\" + to_string(d));\n        cost += d;\n        h[x][y] += d;\n        load -= d;\n    }\n\n    bool all_zero() const {\n        if (load != 0) return false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (h[i][j] != 0) return false;\n        return true;\n    }\n\n    pair<int,int> find_best_positive() const {\n        ll bestScore = INF64;\n        pair<int,int> best = {-1, -1};\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (h[i][j] <= 0) continue;\n                int d = dist(x, y, i, j);\n                int amt = h[i][j];\n                ll score = 100LL * d - 3LL * amt;\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    }\n\n    pair<int,int> find_best_negative() const {\n        ll bestScore = INF64;\n        pair<int,int> best = {-1, -1};\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (h[i][j] >= 0) continue;\n                int d = dist(x, y, i, j);\n                int need = -h[i][j];\n                int tr = (int)min<ll>(load, need);\n                ll score = (100LL + load) * d - 2LL * tr;\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    }\n\n    void snake_cleanup() {\n        vector<pair<int,int>> ord;\n        for (int i = 0; i < N; ++i) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; ++j) ord.push_back({i, j});\n            } else {\n                for (int j = N - 1; j >= 0; --j) ord.push_back({i, j});\n            }\n        }\n\n        auto process_here = [&]() {\n            if (h[x][y] > 0) {\n                int d = (cap >= 1000000 ? h[x][y] : min(h[x][y], cap));\n                pickup(d);\n            } else if (h[x][y] < 0) {\n                int d = (int)min<ll>(load, -h[x][y]);\n                dropoff(d);\n            }\n        };\n\n        for (int rep = 0; rep < 10 && !all_zero() && can_continue(1000); ++rep) {\n            if (rep % 2 == 0) {\n                for (auto [i, j] : ord) {\n                    move_to(i, j);\n                    process_here();\n                }\n            } else {\n                for (int k = (int)ord.size() - 1; k >= 0; --k) {\n                    auto [i, j] = ord[k];\n                    move_to(i, j);\n                    process_here();\n                }\n            }\n        }\n    }\n\n    Result run() {\n        while (can_continue(1000)) {\n            if (all_zero()) break;\n\n            if (load == 0) {\n                auto [px, py] = find_best_positive();\n                if (px == -1) break;\n                move_to(px, py);\n                if (h[x][y] > 0) {\n                    int d = (cap >= 1000000 ? h[x][y] : min(h[x][y], cap));\n                    pickup(d);\n                }\n            } else {\n                auto [nx, ny] = find_best_negative();\n                if (nx == -1) break;\n                move_to(nx, ny);\n                if (h[x][y] < 0) {\n                    int d = (int)min<ll>(load, -h[x][y]);\n                    dropoff(d);\n                }\n            }\n        }\n\n        if (!all_zero() && can_continue(1000)) {\n            snake_cleanup();\n        }\n\n        Result res;\n        res.ops = ops;\n        res.cost = cost;\n        res.finished = all_zero();\n        return res;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> h[i][j];\n    }\n\n    // Candidate loading caps.\n    // 1e9-like value means \"load all\".\n    vector<int> caps = {15, 25, 40, 70, 1000000};\n\n    Result best;\n    best.cost = INF64;\n    best.finished = false;\n\n    for (int cap : caps) {\n        Simulator sim(N, h, cap);\n        Result cur = sim.run();\n\n        // Prefer finished solutions; among them choose minimum cost.\n        // If none finished (unlikely), choose minimum cost anyway.\n        if (cur.finished && !best.finished) {\n            best = move(cur);\n        } else if (cur.finished == best.finished && cur.cost < best.cost) {\n            best = move(cur);\n        }\n    }\n\n    for (const string& s : best.ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 6;\nstatic constexpr int M = 15;\nstatic constexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nstatic constexpr int CELL_COUNT = N * N;           // 36\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { // [l, r)\n        return l + (int)(next_u32() % (uint32_t)(r - l));\n    }\n    double next_double() {\n        return (double)next_u32() / 4294967296.0;\n    }\n} rng;\n\nstruct Seed {\n    array<int, M> x{};\n    int sum = 0;\n};\n\nstatic inline double sqr(double x) { return x * x; }\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    vector<Seed> seeds(SEED_COUNT);\n    for (int i = 0; i < SEED_COUNT; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    auto cell_id = [&](int r, int c) { return r * N + c; };\n\n    vector<vector<int>> nbr(CELL_COUNT);\n    vector<pair<int,int>> edges;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int v = cell_id(r, c);\n            if (r + 1 < N) {\n                int u = cell_id(r + 1, c);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n            if (c + 1 < N) {\n                int u = cell_id(r, c + 1);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n        }\n    }\n\n    vector<int> degree(CELL_COUNT);\n    for (int i = 0; i < CELL_COUNT; i++) degree[i] = (int)nbr[i].size();\n\n    vector<int> cell_order(CELL_COUNT);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (degree[a] != degree[b]) return degree[a] > degree[b];\n        int ra = a / N, ca = a % N;\n        int rb = b / N, cb = b % N;\n        int da = abs(ra - 2) + abs(ca - 2);\n        int db = abs(rb - 2) + abs(cb - 2);\n        return da < db;\n    });\n\n    for (int turn = 0; turn < T; turn++) {\n        // ----- turn-aware weights -----\n        double phase = (double)turn / max(1, T - 1); // 0..1\n        // early: diversity, late: sum\n        double W_SUM = 1.0 + 1.6 * phase;\n        double W_TOP = 1.2 - 0.5 * phase;\n        double W_COVER = 1.4 - 0.8 * phase;\n        double W_PAIR_ENV = 1.0 + 0.6 * phase;\n        double W_PAIR_SUM = 0.15 + 0.35 * phase;\n        double W_CELL = 0.35 + 0.45 * phase;\n\n        // ----- global coordinate statistics -----\n        array<int, M> gmax{};\n        array<double, M> gmean{};\n        gmax.fill(0);\n        gmean.fill(0.0);\n        for (int l = 0; l < M; l++) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                gmax[l] = max(gmax[l], seeds[i].x[l]);\n                gmean[l] += seeds[i].x[l];\n            }\n            gmean[l] /= SEED_COUNT;\n        }\n\n        array<double, M> dimWeight{};\n        for (int l = 0; l < M; l++) {\n            // emphasize dimensions with large maxima and where elite values matter\n            dimWeight[l] = 1.0 + 0.02 * gmax[l];\n        }\n\n        // ----- rich seed score -----\n        vector<double> seedScore(SEED_COUNT, 0.0);\n        vector<double> eliteScore(SEED_COUNT, 0.0); // \"specialist importance\"\n        for (int i = 0; i < SEED_COUNT; i++) {\n            double sc = W_SUM * seeds[i].sum;\n            double es = 0.0;\n            for (int l = 0; l < M; l++) {\n                double x = seeds[i].x[l];\n                double rel = (gmax[l] == 0 ? 0.0 : x / gmax[l]);\n                sc += W_TOP * dimWeight[l] * rel * x * 0.35;\n                // sharp bonus near dimension max\n                double nearTop = max(0.0, rel - 0.75);\n                es += dimWeight[l] * nearTop * nearTop * 100.0;\n            }\n            seedScore[i] = sc + 0.4 * es;\n            eliteScore[i] = es;\n        }\n\n        // ----- candidate ordering -----\n        vector<int> ord(SEED_COUNT);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabs(seedScore[a] - seedScore[b]) > 1e-9) return seedScore[a] > seedScore[b];\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n\n        // ----- select 36 seeds: core by score + diverse fill by coordinate coverage -----\n        vector<int> chosen;\n        vector<int> usedSeed(SEED_COUNT, 0);\n\n        int core = 20; // stronger core than before, but leave room for specialists\n        for (int i = 0; i < core; i++) {\n            chosen.push_back(ord[i]);\n            usedSeed[ord[i]] = 1;\n        }\n\n        array<int, M> coverMax{};\n        coverMax.fill(0);\n        for (int s : chosen) {\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[s].x[l]);\n        }\n\n        while ((int)chosen.size() < CELL_COUNT) {\n            int best = -1;\n            double bestGain = -1e100;\n\n            for (int i = 0; i < SEED_COUNT; i++) if (!usedSeed[i]) {\n                double gain = 0.18 * seedScore[i] + 0.30 * eliteScore[i];\n                for (int l = 0; l < M; l++) {\n                    int inc = max(0, seeds[i].x[l] - coverMax[l]);\n                    gain += W_COVER * dimWeight[l] * inc;\n                }\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = i;\n                }\n            }\n\n            chosen.push_back(best);\n            usedSeed[best] = 1;\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[best].x[l]);\n        }\n\n        // local indices [0,35]\n        vector<int> localToSeed = chosen;\n\n        static int envScore[CELL_COUNT][CELL_COUNT];\n        static int sumScore[CELL_COUNT][CELL_COUNT];\n        static int syScore[CELL_COUNT][CELL_COUNT];\n\n        for (int i = 0; i < CELL_COUNT; i++) {\n            envScore[i][i] = sumScore[i][i] = syScore[i][i] = 0;\n            for (int j = i + 1; j < CELL_COUNT; j++) {\n                int a = localToSeed[i], b = localToSeed[j];\n                int env = 0;\n                int ss = seeds[a].sum + seeds[b].sum;\n                int syn = 0;\n                for (int l = 0; l < M; l++) {\n                    int xa = seeds[a].x[l], xb = seeds[b].x[l];\n                    env += max(xa, xb);\n\n                    // synergy bonus: high if both together cover the max well, especially if one is strong where the other is not\n                    int mn = min(xa, xb), mx = max(xa, xb);\n                    syn += mx - mn / 3;\n                }\n                envScore[i][j] = envScore[j][i] = env;\n                sumScore[i][j] = sumScore[j][i] = ss;\n                syScore[i][j] = syScore[j][i] = syn;\n            }\n        }\n\n        vector<double> localSeedCellWeight(CELL_COUNT);\n        for (int i = 0; i < CELL_COUNT; i++) {\n            int s = localToSeed[i];\n            localSeedCellWeight[i] = 0.65 * seeds[s].sum + 0.35 * eliteScore[s];\n        }\n\n        auto objective_edge = [&](int a, int b) -> double {\n            return W_PAIR_ENV * envScore[a][b] + W_PAIR_SUM * sumScore[a][b] + 0.25 * syScore[a][b];\n        };\n\n        auto placementScore = [&](const vector<int>& pl) -> double {\n            double res = 0.0;\n            for (auto [u, v] : edges) res += objective_edge(pl[u], pl[v]);\n            for (int c = 0; c < CELL_COUNT; c++) {\n                res += W_CELL * degree[c] * localSeedCellWeight[pl[c]];\n            }\n            return res;\n        };\n\n        auto deltaSwap = [&](const vector<int>& pl, int a, int b) -> double {\n            if (a == b) return 0.0;\n            int sa = pl[a], sb = pl[b];\n            double before = 0.0, after = 0.0;\n\n            // cell weight term\n            before += W_CELL * degree[a] * localSeedCellWeight[sa];\n            before += W_CELL * degree[b] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[a] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[b] * localSeedCellWeight[sa];\n\n            vector<int> vs;\n            vs.push_back(a);\n            vs.push_back(b);\n            for (int x : nbr[a]) vs.push_back(x);\n            for (int x : nbr[b]) vs.push_back(x);\n            sort(vs.begin(), vs.end());\n            vs.erase(unique(vs.begin(), vs.end()), vs.end());\n\n            set<pair<int,int>> es;\n            for (int u : vs) for (int v : nbr[u]) if (u < v) es.insert({u, v});\n\n            for (auto [u, v] : es) {\n                int pu = pl[u], pv = pl[v];\n                before += objective_edge(pu, pv);\n\n                if (u == a) pu = sb;\n                else if (u == b) pu = sa;\n                if (v == a) pv = sb;\n                else if (v == b) pv = sa;\n                after += objective_edge(pu, pv);\n            }\n\n            return after - before;\n        };\n\n        auto make_greedy = [&](bool randomized) -> vector<int> {\n            vector<int> place(CELL_COUNT, -1);\n            vector<int> used(CELL_COUNT, 0);\n\n            for (int step = 0; step < CELL_COUNT; step++) {\n                int cell = cell_order[step];\n\n                vector<pair<double,int>> cand;\n                cand.reserve(CELL_COUNT);\n                for (int si = 0; si < CELL_COUNT; si++) if (!used[si]) {\n                    double sc = W_CELL * degree[cell] * localSeedCellWeight[si];\n\n                    // adjacency with already placed neighbors\n                    for (int nb : nbr[cell]) {\n                        if (place[nb] != -1) sc += objective_edge(si, place[nb]);\n                    }\n\n                    // slight center preference\n                    int r = cell / N, c = cell % N;\n                    int md = abs(r - 2) + abs(c - 2);\n                    sc -= 0.7 * md * (0.35 * seeds[localToSeed[si]].sum + 0.1 * eliteScore[localToSeed[si]]);\n\n                    cand.push_back({sc, si});\n                }\n\n                sort(cand.begin(), cand.end(), greater<>());\n                int take = 0;\n                if (randomized) {\n                    int lim = min<int>(4, cand.size());\n                    take = rng.next_int(0, lim);\n                }\n                int bestSeed = cand[take].second;\n                place[cell] = bestSeed;\n                used[bestSeed] = 1;\n            }\n\n            // hill climbing\n            double cur = placementScore(place);\n            bool improved = true;\n            for (int it = 0; it < 10 && improved; it++) {\n                improved = false;\n\n                // random order pairs + full sweep flavor\n                vector<int> cells(CELL_COUNT);\n                iota(cells.begin(), cells.end(), 0);\n                shuffle(cells.begin(), cells.end(), std::mt19937(rng.next_u32()));\n\n                for (int xi = 0; xi < CELL_COUNT; xi++) {\n                    int a = cells[xi];\n                    double bestD = 0.0;\n                    int bestB = -1;\n                    for (int yi = xi + 1; yi < CELL_COUNT; yi++) {\n                        int b = cells[yi];\n                        double d = deltaSwap(place, a, b);\n                        if (d > bestD) {\n                            bestD = d;\n                            bestB = b;\n                        }\n                    }\n                    if (bestB != -1) {\n                        swap(place[a], place[bestB]);\n                        cur += bestD;\n                        improved = true;\n                    }\n                }\n            }\n\n            return place;\n        };\n\n        // multi-start\n        vector<int> bestPlace;\n        double bestScore = -1e100;\n\n        int trials = 10;\n        for (int tcase = 0; tcase < trials; tcase++) {\n            bool randomized = (tcase > 0);\n            auto pl = make_greedy(randomized);\n            double sc = placementScore(pl);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPlace = pl;\n            }\n        }\n\n        // output original seed indices\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (c) cout << ' ';\n                cout << localToSeed[bestPlace[cell_id(r, c)]];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // read next generation\n        for (int i = 0; i < SEED_COUNT; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int DX[4] = {0, 1, 0, -1}; // R,D,L,U in (row,col)\nstatic const int DY[4] = {1, 0, -1, 0};\nstatic const char DIRC[4] = {'R', 'D', 'L', 'U'};\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    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    // Star arm: root + K leaves, all length 1.\n    int K = max(1, V - 1);\n    int Vp = K + 1;\n\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << 1 << '\\n';\n    }\n\n    int rx = N / 2, ry = N / 2;\n    cout << rx << ' ' << ry << '\\n';\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    vector<int> dir(K, 0);     // current direction of each leaf\n    vector<int> hold(K, 0);    // whether leaf holds one takoyaki\n\n    auto is_surplus = [&](int x, int y) -> bool {\n        return s[x][y] == '1' && t[x][y] == '0';\n    };\n    auto is_deficit = [&](int x, int y) -> bool {\n        return s[x][y] == '0' && t[x][y] == '1';\n    };\n\n    auto remaining = [&]() -> int {\n        int diff = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (s[i][j] != t[i][j]) diff++;\n        }\n        return diff / 2;\n    };\n\n    auto count_hold = [&]() -> int {\n        int c = 0;\n        for (int v : hold) c += v;\n        return c;\n    };\n\n    // For a root position, count adjacent surplus/deficit cells.\n    auto neighborhood_info = [&](int x, int y) {\n        array<int, 4> kind{}; // 0 none, 1 surplus, 2 deficit\n        int cs = 0, cd = 0;\n        for (int d = 0; d < 4; d++) {\n            int nx = x + DX[d], ny = y + DY[d];\n            if (!inb(nx, ny)) continue;\n            if (is_surplus(nx, ny)) {\n                kind[d] = 1;\n                cs++;\n            } else if (is_deficit(nx, ny)) {\n                kind[d] = 2;\n                cd++;\n            }\n        }\n        return pair<int,int>(cs, cd);\n    };\n\n    auto manhattan_step = [&](int tx, int ty) -> int {\n        if (rx < tx) return 1; // D\n        if (rx > tx) return 3; // U\n        if (ry < ty) return 0; // R\n        if (ry > ty) return 2; // L\n        return -1;\n    };\n\n    // Find best root center for pick/place.\n    // mode=0 pick, mode=1 place.\n    auto best_center = [&](int mode) -> Pos {\n        int bestScore = -1e9;\n        Pos best{rx, ry};\n\n        int hcnt = count_hold();\n        int ecnt = K - hcnt;\n\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            int cnt = 0;\n            for (int d = 0; d < 4; d++) {\n                int nx = x + DX[d], ny = y + DY[d];\n                if (!inb(nx, ny)) continue;\n                if (mode == 0 && is_surplus(nx, ny)) cnt++;\n                if (mode == 1 && is_deficit(nx, ny)) cnt++;\n            }\n            if (mode == 0) cnt = min(cnt, ecnt);\n            else cnt = min(cnt, hcnt);\n\n            int dist = abs(x - rx) + abs(y - ry);\n            int score = cnt * 1000 - dist * 10;\n\n            // small preference to remain if equally good\n            if (x == rx && y == ry) score += 3;\n\n            // if carrying, place centers are more important\n            if (mode == 1) score += 1;\n\n            if (score > bestScore) {\n                bestScore = score;\n                best = {x, y};\n            }\n        }\n        return best;\n    };\n\n    // If no good center with adjacent targets, move toward nearest relevant cell's adjacent center.\n    auto nearest_center_from_cells = [&](int mode) -> Pos {\n        int bestDist = 1e9;\n        Pos best{rx, ry};\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            bool ok = (mode == 0 ? is_surplus(i, j) : is_deficit(i, j));\n            if (!ok) continue;\n            for (int d = 0; d < 4; d++) {\n                int x = i - DX[d], y = j - DY[d];\n                if (!inb(x, y)) continue;\n                int dist = abs(x - rx) + abs(y - ry);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    best = {x, y};\n                }\n            }\n        }\n        return best;\n    };\n\n    vector<string> answer;\n    const int TURN_LIMIT = 100000;\n\n    for (int turn = 0; turn < TURN_LIMIT; turn++) {\n        if (remaining() == 0) break;\n\n        int hcnt = count_hold();\n        int ecnt = K - hcnt;\n\n        // Decide strategic target center.\n        // If holding enough, prioritize place. If empty, prioritize pick.\n        Pos target = {rx, ry};\n\n        auto placeBest = best_center(1);\n        auto pickBest = best_center(0);\n\n        auto eval_center_count = [&](Pos p, int mode) -> int {\n            int cnt = 0;\n            for (int d = 0; d < 4; d++) {\n                int nx = p.x + DX[d], ny = p.y + DY[d];\n                if (!inb(nx, ny)) continue;\n                if (mode == 0 && is_surplus(nx, ny)) cnt++;\n                if (mode == 1 && is_deficit(nx, ny)) cnt++;\n            }\n            return cnt;\n        };\n\n        int placeCnt = eval_center_count(placeBest, 1);\n        int pickCnt = eval_center_count(pickBest, 0);\n\n        if (hcnt > 0 && placeCnt > 0) {\n            target = placeBest;\n        } else if (ecnt > 0 && pickCnt > 0) {\n            target = pickBest;\n        } else if (hcnt > 0) {\n            target = nearest_center_from_cells(1);\n        } else {\n            target = nearest_center_from_cells(0);\n        }\n\n        // Movement\n        string cmd(2 * Vp, '.');\n        int mv = manhattan_step(target.x, target.y);\n        if (mv != -1) {\n            int nx = rx + DX[mv], ny = ry + DY[mv];\n            if (inb(nx, ny)) {\n                rx = nx;\n                ry = ny;\n                cmd[0] = DIRC[mv];\n            }\n        }\n\n        // After movement, greedily assign adjacent directions.\n        // First assign holding leaves to deficits.\n        // Then assign empty leaves to surplus.\n        // This gives immediate service whenever possible.\n\n        vector<int> leafTargetDir(K, -1);\n        vector<int> dirUsed(4, -1);\n\n        // Gather available deficit/surplus dirs\n        vector<int> deficitDirs, surplusDirs;\n        for (int d = 0; d < 4; d++) {\n            int x = rx + DX[d], y = ry + DY[d];\n            if (!inb(x, y)) continue;\n            if (is_deficit(x, y)) deficitDirs.push_back(d);\n            if (is_surplus(x, y)) surplusDirs.push_back(d);\n        }\n\n        // Assign holders to deficits\n        int idx = 0;\n        for (int i = 0; i < K && idx < (int)deficitDirs.size(); i++) {\n            if (!hold[i]) continue;\n            int d = deficitDirs[idx++];\n            leafTargetDir[i] = d;\n            dirUsed[d] = i;\n        }\n\n        // Assign empties to surplus\n        idx = 0;\n        for (int i = 0; i < K && idx < (int)surplusDirs.size(); i++) {\n            if (hold[i]) continue;\n            while (idx < (int)surplusDirs.size() && dirUsed[surplusDirs[idx]] != -1) idx++;\n            if (idx >= (int)surplusDirs.size()) break;\n            int d = surplusDirs[idx++];\n            leafTargetDir[i] = d;\n            dirUsed[d] = i;\n        }\n\n        // Opportunistic second priority:\n        // If some holding leaf has no place target, let it rotate toward a deficit if any remains unassigned next turn;\n        // similarly for empty leaf.\n        // Here we simply keep current direction if unused.\n\n        // Rotate each leaf at most 90 degrees.\n        for (int i = 0; i < K; i++) {\n            int td = leafTargetDir[i];\n            if (td == -1) continue;\n            int cur = dir[i];\n            int diff = (td - cur + 4) % 4;\n            if (diff == 0) {\n                cmd[1 + i] = '.';\n            } else if (diff == 1) {\n                cmd[1 + i] = 'R';\n                dir[i] = (dir[i] + 1) & 3;\n            } else if (diff == 3) {\n                cmd[1 + i] = 'L';\n                dir[i] = (dir[i] + 3) & 3;\n            } else {\n                // opposite: choose one direction deterministically\n                cmd[1 + i] = 'R';\n                dir[i] = (dir[i] + 1) & 3;\n            }\n        }\n\n        // Action phase in vertex order.\n        for (int i = 0; i < K; i++) {\n            int x = rx + DX[dir[i]];\n            int y = ry + DY[dir[i]];\n            if (!inb(x, y)) continue;\n\n            if (hold[i]) {\n                if (is_deficit(x, y)) {\n                    s[x][y] = '1';\n                    hold[i] = 0;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            } else {\n                if (is_surplus(x, y)) {\n                    s[x][y] = '0';\n                    hold[i] = 1;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            }\n        }\n\n        answer.push_back(cmd);\n    }\n\n    for (auto &row : answer) cout << row << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct GridData {\n    int D;\n    int ox, oy;\n    int W, H;\n    vector<int> w;\n};\n\nstruct Candidate {\n    ll score = LLONG_MIN;\n    vector<unsigned char> sel;\n    int H = 0, W = 0, ox = 0, oy = 0, D = 0;\n    vector<pair<int,int>> poly;\n    bool valid = false;\n};\n\nstatic inline long long pack64(int a, int b) {\n    return ((long long)a << 32) ^ (unsigned int)b;\n}\n\nstatic inline int mdist(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nGridData build_grid(const vector<Point>& mac, const vector<Point>& sar, int D) {\n    int minx = 1e9, miny = 1e9, maxx = -1, maxy = -1;\n    auto upd = [&](const Point& p) {\n        int gx = p.x / D, gy = p.y / D;\n        minx = min(minx, gx);\n        maxx = max(maxx, gx);\n        miny = min(miny, gy);\n        maxy = max(maxy, gy);\n    };\n    for (auto &p : mac) upd(p);\n    for (auto &p : sar) upd(p);\n\n    GridData g;\n    g.D = D;\n    g.ox = minx;\n    g.oy = miny;\n    g.W = maxx - minx + 1;\n    g.H = maxy - miny + 1;\n    g.w.assign(g.H * g.W, 0);\n\n    auto id = [&](int r, int c) { return r * g.W + c; };\n\n    for (auto &p : mac) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r,c)]++;\n    }\n    for (auto &p : sar) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r,c)]--;\n    }\n    return g;\n}\n\nll compute_score(const vector<unsigned char>& sel, const GridData& g) {\n    ll s = 0;\n    for (int i = 0; i < (int)sel.size(); i++) if (sel[i]) s += g.w[i];\n    return s;\n}\n\nint compute_perim_edges(const vector<unsigned char>& sel, int H, int W) {\n    auto id = [&](int r, int c) { return r * W + c; };\n    int pe = 0;\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) if (sel[id(r,c)]) {\n            if (r == 0 || !sel[id(r-1,c)]) pe++;\n            if (r+1 == H || !sel[id(r+1,c)]) pe++;\n            if (c == 0 || !sel[id(r,c-1)]) pe++;\n            if (c+1 == W || !sel[id(r,c+1)]) pe++;\n        }\n    }\n    return pe;\n}\n\nbool is_connected_after_removal(const vector<unsigned char>& sel, int H, int W, int rem) {\n    int total = 0, start = -1;\n    for (int i = 0; i < H * W; i++) {\n        if (i == rem) continue;\n        if (sel[i]) {\n            total++;\n            start = i;\n        }\n    }\n    if (total <= 1) return true;\n\n    vector<unsigned char> vis(H * W, 0);\n    queue<int> q;\n    q.push(start);\n    vis[start] = 1;\n    int cnt = 1;\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1,0,1,0};\n    const int dc[4] = {0,1,0,-1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int r = v / W, c = v % W;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                int u = id(nr, nc);\n                if (u == rem || !sel[u] || vis[u]) continue;\n                vis[u] = 1;\n                q.push(u);\n                cnt++;\n            }\n        }\n    }\n    return cnt == total;\n}\n\nstruct BuildResult {\n    bool ok = false;\n    vector<pair<int,int>> poly;\n};\n\nBuildResult build_polygon_from_selected(const vector<unsigned char>& sel, int H, int W, int ox, int oy, int D) {\n    struct Edge {\n        int x1, y1, x2, y2;\n        bool operator==(const Edge& o) const {\n            return x1==o.x1 && y1==o.y1 && x2==o.x2 && y2==o.y2;\n        }\n    };\n    struct EdgeHash {\n        size_t operator()(Edge const& e) const noexcept {\n            uint64_t h = 1469598103934665603ULL;\n            auto add = [&](uint64_t v) {\n                h ^= v + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n            };\n            add((uint32_t)e.x1); add((uint32_t)e.y1); add((uint32_t)e.x2); add((uint32_t)e.y2);\n            return (size_t)h;\n        }\n    };\n\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    unordered_set<Edge, EdgeHash> S;\n    S.reserve(H * W * 2);\n\n    auto toggle = [&](Edge e) {\n        Edge rev{e.x2, e.y2, e.x1, e.y1};\n        auto it = S.find(rev);\n        if (it != S.end()) S.erase(it);\n        else S.insert(e);\n    };\n\n    int cntSel = 0;\n    for (int r = 0; r < H; r++) {\n        for (int c = 0; c < W; c++) if (sel[id(r,c)]) {\n            cntSel++;\n            int gx = ox + c, gy = oy + r;\n            int x = gx * D, y = gy * D;\n            toggle({x, y, x + D, y});\n            toggle({x + D, y, x + D, y + D});\n            toggle({x + D, y + D, x, y + D});\n            toggle({x, y + D, x, y});\n        }\n    }\n    if (cntSel == 0 || S.empty()) return {};\n\n    unordered_map<long long, vector<pair<int,int>>> out;\n    out.reserve(S.size() * 2);\n    auto pkey = [&](int x, int y) { return pack64(x, y); };\n    for (auto &e : S) out[pkey(e.x1, e.y1)].push_back({e.x2, e.y2});\n\n    auto ekey = [&](int x1, int y1, int x2, int y2) {\n        uint64_t h = 1469598103934665603ULL;\n        auto add = [&](uint64_t v) {\n            h ^= v + 0x9e3779b97f4a7c15ULL + (h<<6) + (h>>2);\n        };\n        add((uint32_t)x1); add((uint32_t)y1); add((uint32_t)x2); add((uint32_t)y2);\n        return (long long)h;\n    };\n\n    unordered_set<long long> used;\n    used.reserve(S.size() * 2);\n\n    int cycles = 0;\n    vector<pair<int,int>> best;\n\n    for (auto &e : S) {\n        long long k0 = ekey(e.x1, e.y1, e.x2, e.y2);\n        if (used.count(k0)) continue;\n\n        cycles++;\n        vector<pair<int,int>> cur;\n        int sx = e.x1, sy = e.y1;\n        int cx = e.x1, cy = e.y1;\n        int nx = e.x2, ny = e.y2;\n        cur.push_back({cx, cy});\n\n        while (true) {\n            long long kk = ekey(cx, cy, nx, ny);\n            if (used.count(kk)) break;\n            used.insert(kk);\n\n            cx = nx; cy = ny;\n            cur.push_back({cx, cy});\n            if (cx == sx && cy == sy) break;\n\n            auto it = out.find(pkey(cx, cy));\n            if (it == out.end()) return {};\n            int cnt = 0;\n            pair<int,int> nxt;\n            for (auto &to : it->second) {\n                long long nk = ekey(cx, cy, to.first, to.second);\n                if (!used.count(nk)) {\n                    cnt++;\n                    nxt = to;\n                }\n            }\n            if (cnt != 1) return {};\n            nx = nxt.first;\n            ny = nxt.second;\n        }\n\n        if (!cur.empty() && cur.front() == cur.back()) cur.pop_back();\n        if (cur.size() > best.size()) best = move(cur);\n    }\n\n    if ((int)used.size() != (int)S.size()) return {};\n    if (cycles != 1) return {};\n\n    vector<pair<int,int>> poly;\n    int m = (int)best.size();\n    for (int i = 0; i < m; i++) {\n        auto p0 = best[(i - 1 + m) % m];\n        auto p1 = best[i];\n        auto p2 = best[(i + 1) % m];\n        int dx1 = (p1.first > p0.first) - (p1.first < p0.first);\n        int dy1 = (p1.second > p0.second) - (p1.second < p0.second);\n        int dx2 = (p2.first > p1.first) - (p2.first < p1.first);\n        int dy2 = (p2.second > p1.second) - (p2.second < p1.second);\n        if (dx1 == dx2 && dy1 == dy2) continue;\n        poly.push_back(p1);\n    }\n\n    if ((int)poly.size() < 4 || (int)poly.size() > 1000) return {};\n    {\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != (int)poly.size()) return {};\n    }\n\n    ll peri = 0;\n    for (int i = 0; i < (int)poly.size(); i++) peri += mdist(poly[i], poly[(i+1)%poly.size()]);\n    if (peri > 400000) return {};\n\n    for (auto &p : poly) {\n        if (p.first < 0 || p.first > 100000 || p.second < 0 || p.second > 100000) return {};\n    }\n\n    return {true, poly};\n}\n\nCandidate make_candidate_from_sel(const GridData& g, const vector<unsigned char>& sel) {\n    Candidate c;\n    c.H = g.H; c.W = g.W; c.ox = g.ox; c.oy = g.oy; c.D = g.D;\n    c.sel = sel;\n    c.score = compute_score(sel, g);\n    c.valid = true;\n    return c;\n}\n\nCandidate candidate_from_rectangle(const GridData& g) {\n    Candidate best;\n    best.H = g.H; best.W = g.W; best.ox = g.ox; best.oy = g.oy; best.D = g.D;\n\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    vector<int> col(W);\n    for (int top = 0; top < H; top++) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < H; bot++) {\n            int hc = bot - top + 1;\n            for (int c = 0; c < W; c++) col[c] += g.w[id(bot, c)];\n\n            int max_wh = 200000 / D - hc;\n            if (max_wh <= 0) continue;\n            int maxWidth = min(W, max_wh);\n\n            ll curBest = LLONG_MIN;\n            int bestL = -1, bestR = -1;\n            for (int l = 0; l < W; l++) {\n                ll s = 0;\n                for (int r = l; r < W && r - l + 1 <= maxWidth; r++) {\n                    s += col[r];\n                    if (s > curBest) {\n                        curBest = s;\n                        bestL = l;\n                        bestR = r;\n                    }\n                }\n            }\n            if (bestL == -1 || curBest <= best.score) continue;\n\n            vector<unsigned char> sel(H * W, 0);\n            for (int r = top; r <= bot; r++) {\n                for (int c = bestL; c <= bestR; c++) sel[id(r,c)] = 1;\n            }\n            best.score = curBest;\n            best.sel = move(sel);\n            best.valid = true;\n        }\n    }\n    return best;\n}\n\nCandidate candidate_from_threshold(const GridData& g, int T) {\n    int H = g.H, W = g.W;\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    vector<unsigned char> good(H * W, 0), vis(H * W, 0);\n    for (int i = 0; i < H * W; i++) if (g.w[i] >= T) good[i] = 1;\n\n    const int dr[4] = {-1,0,1,0};\n    const int dc[4] = {0,1,0,-1};\n\n    ll bestScore = LLONG_MIN;\n    vector<unsigned char> bestSel(H * W, 0);\n\n    for (int s = 0; s < H * W; s++) {\n        if (!good[s] || vis[s]) continue;\n        queue<int> q;\n        vector<int> comp;\n        q.push(s);\n        vis[s] = 1;\n        ll sc = 0;\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            comp.push_back(v);\n            sc += g.w[v];\n            int r = v / W, c = v % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                    int u = id(nr,nc);\n                    if (good[u] && !vis[u]) {\n                        vis[u] = 1;\n                        q.push(u);\n                    }\n                }\n            }\n        }\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            fill(bestSel.begin(), bestSel.end(), 0);\n            for (int v : comp) bestSel[v] = 1;\n        }\n    }\n\n    Candidate c;\n    c.H = g.H; c.W = g.W; c.ox = g.ox; c.oy = g.oy; c.D = g.D;\n    if (bestScore == LLONG_MIN) return c;\n    c.score = bestScore;\n    c.sel = move(bestSel);\n    c.valid = true;\n    return c;\n}\n\nCandidate candidate_from_greedy(const GridData& g, double pen, int maxSeeds = 18) {\n    Candidate best;\n    best.H = g.H; best.W = g.W; best.ox = g.ox; best.oy = g.oy; best.D = g.D;\n\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1,0,1,0};\n    const int dc[4] = {0,1,0,-1};\n\n    vector<int> ord(H * W);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (g.w[a] != g.w[b]) return g.w[a] > g.w[b];\n        return a < b;\n    });\n\n    maxSeeds = min(maxSeeds, H * W);\n\n    for (int si = 0; si < maxSeeds; si++) {\n        int seed = ord[si];\n        if (g.w[seed] <= 0 && si >= 6) break;\n\n        vector<unsigned char> sel(H * W, 0);\n        vector<int> ver(H * W, 0);\n\n        ll score = 0;\n        int perim_edges = 0;\n        int perim_limit = 400000 / D;\n\n        auto neigh_sel = [&](int v) {\n            int r = v / W, c = v % W;\n            int cnt = 0;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W && sel[id(nr,nc)]) cnt++;\n            }\n            return cnt;\n        };\n\n        struct Node {\n            double pri;\n            int v, ver;\n            bool operator<(const Node& o) const { return pri < o.pri; }\n        };\n        priority_queue<Node> pq;\n\n        auto push = [&](int v) {\n            if (sel[v]) return;\n            int ns = neigh_sel(v);\n            if (ns == 0) return;\n            int de = 4 - 2 * ns;\n            double pri = g.w[v] * 12.0 - pen * de + ns * 2.0;\n            pq.push({pri, v, ++ver[v]});\n        };\n\n        auto add = [&](int v) {\n            int ns = neigh_sel(v);\n            int de = 4 - 2 * ns;\n            sel[v] = 1;\n            score += g.w[v];\n            perim_edges += de;\n\n            int r = v / W, c = v % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                    int u = id(nr,nc);\n                    if (!sel[u]) push(u);\n                }\n            }\n        };\n\n        add(seed);\n        {\n            int r = seed / W, c = seed % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) push(id(nr,nc));\n            }\n        }\n\n        int iter = 0, iterLimit = H * W * 4;\n        while (!pq.empty() && iter < iterLimit) {\n            iter++;\n            auto cur = pq.top(); pq.pop();\n            int v = cur.v;\n            if (sel[v] || cur.ver != ver[v]) continue;\n\n            int ns = neigh_sel(v);\n            if (ns == 0) continue;\n            int de = 4 - 2 * ns;\n            if (perim_edges + de > perim_limit) continue;\n\n            double gain = g.w[v] * 12.0 - pen * de + ns * 2.0;\n            bool ok = false;\n            if (gain >= 0) ok = true;\n            else if (g.w[v] >= 0 && ns >= 2 && gain >= -2.0) ok = true;\n            else if (g.w[v] == -1 && ns >= 3 && gain >= -1.0) ok = true;\n\n            if (!ok) continue;\n            add(v);\n        }\n\n        if (score > best.score) {\n            best.score = score;\n            best.sel = move(sel);\n            best.valid = true;\n        }\n    }\n\n    return best;\n}\n\nvoid local_improve(Candidate& cand, const GridData& g, int rounds) {\n    if (!cand.valid) return;\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1,0,1,0};\n    const int dc[4] = {0,1,0,-1};\n\n    auto &sel = cand.sel;\n    ll score = compute_score(sel, g);\n    int perim_edges = compute_perim_edges(sel, H, W);\n    int perim_limit = 400000 / D;\n\n    auto neigh_sel = [&](int v) {\n        int r = v / W, c = v % W;\n        int cnt = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W && sel[id(nr,nc)]) cnt++;\n        }\n        return cnt;\n    };\n\n    auto boundary_selected = [&](int v) {\n        if (!sel[v]) return false;\n        int r = v / W, c = v % W;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!(0 <= nr && nr < H && 0 <= nc && nc < W)) return true;\n            if (!sel[id(nr,nc)]) return true;\n        }\n        return false;\n    };\n\n    auto frontier_unselected = [&](int v) {\n        if (sel[v]) return false;\n        return neigh_sel(v) > 0;\n    };\n\n    for (int step = 0; step < rounds; step++) {\n        double bestMerit = 0.0;\n        int bestType = 0; // +1 add, -1 remove\n        int bestV = -1;\n        int bestDE = 0;\n        ll bestDS = 0;\n\n        for (int v = 0; v < H * W; v++) {\n            if (!sel[v]) {\n                if (!frontier_unselected(v)) continue;\n                int ns = neigh_sel(v);\n                int de = 4 - 2 * ns;\n                if (perim_edges + de > perim_limit) continue;\n                ll ds = g.w[v];\n                double merit = ds * 12.0 - de * 2.5 + ns * 1.5;\n                if (merit > bestMerit) {\n                    bestMerit = merit;\n                    bestType = +1;\n                    bestV = v;\n                    bestDE = de;\n                    bestDS = ds;\n                }\n            } else {\n                if (!boundary_selected(v)) continue;\n                int ns = neigh_sel(v);\n                int de = -4 + 2 * ns;\n                ll ds = -g.w[v];\n                double merit = ds * 12.0 - de * 2.5;\n                if (merit <= bestMerit) continue;\n                if (ns >= 2 && !is_connected_after_removal(sel, H, W, v)) continue;\n                if (perim_edges + de > perim_limit) continue;\n\n                bestMerit = merit;\n                bestType = -1;\n                bestV = v;\n                bestDE = de;\n                bestDS = ds;\n            }\n        }\n\n        if (bestType == 0) break;\n        if (bestType == +1) sel[bestV] = 1;\n        else sel[bestV] = 0;\n        score += bestDS;\n        perim_edges += bestDE;\n    }\n\n    cand.score = score;\n}\n\nvoid morph_cleanup(Candidate& cand, const GridData& g, int passes) {\n    if (!cand.valid) return;\n\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1,0,1,0};\n    const int dc[4] = {0,1,0,-1};\n\n    auto &sel = cand.sel;\n    int perim_limit = 400000 / D;\n\n    auto neigh_sel = [&](const vector<unsigned char>& cur, int v) {\n        int r = v / W, c = v % W;\n        int cnt = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W && cur[id(nr,nc)]) cnt++;\n        }\n        return cnt;\n    };\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed = false;\n        vector<unsigned char> nxt = sel;\n        int pe = compute_perim_edges(sel, H, W);\n\n        // Fill strong concavities\n        for (int v = 0; v < H * W; v++) if (!sel[v]) {\n            int ns = neigh_sel(sel, v);\n            if (ns >= 3) {\n                int de = 4 - 2 * ns;\n                if (pe + de <= perim_limit) {\n                    if (g.w[v] >= -1 || ns == 4) {\n                        nxt[v] = 1;\n                        pe += de;\n                        changed = true;\n                    }\n                }\n            }\n        }\n\n        sel.swap(nxt);\n        nxt = sel;\n        pe = compute_perim_edges(sel, H, W);\n\n        // Remove thin weak spikes\n        for (int v = 0; v < H * W; v++) if (sel[v]) {\n            int ns = neigh_sel(sel, v);\n            if (ns <= 1 && g.w[v] <= 0) {\n                if (ns >= 2 && !is_connected_after_removal(sel, H, W, v)) continue;\n                int de = -4 + 2 * ns;\n                if (pe + de <= perim_limit) {\n                    nxt[v] = 0;\n                    pe += de;\n                    changed = true;\n                }\n            }\n        }\n\n        sel.swap(nxt);\n        if (!changed) break;\n    }\n\n    cand.score = compute_score(sel, g);\n}\n\nbool finalize_candidate(Candidate& cand, const GridData& g) {\n    if (!cand.valid) return false;\n    auto br = build_polygon_from_selected(cand.sel, g.H, g.W, g.ox, g.oy, g.D);\n    if (!br.ok) {\n        cand.valid = false;\n        return false;\n    }\n    cand.poly = move(br.poly);\n    cand.score = compute_score(cand.sel, g);\n    cand.valid = true;\n    return true;\n}\n\nvector<pair<int,int>> fallback_polygon() {\n    return {{0,0},{1,0},{1,1},{0,1}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> mac(N), sar(N);\n    for (int i = 0; i < N; i++) cin >> mac[i].x >> mac[i].y;\n    for (int i = 0; i < N; i++) cin >> sar[i].x >> sar[i].y;\n\n    vector<int> Ds = {1000, 1200, 1600, 2000, 2500, 3200};\n\n    Candidate best;\n\n    auto consider = [&](Candidate c, const GridData& g) {\n        if (!c.valid) return;\n\n        local_improve(c, g, 60);\n        morph_cleanup(c, g, 4);\n        local_improve(c, g, 60);\n\n        if (!finalize_candidate(c, g)) return;\n        if (c.score > best.score) best = move(c);\n    };\n\n    for (int D : Ds) {\n        GridData g = build_grid(mac, sar, D);\n\n        consider(candidate_from_rectangle(g), g);\n\n        for (int T : {2, 1}) {\n            consider(candidate_from_threshold(g, T), g);\n        }\n\n        for (double pen : {1.5, 2.0, 2.5, 3.0, 4.0}) {\n            consider(candidate_from_greedy(g, pen, 18), g);\n        }\n    }\n\n    vector<pair<int,int>> out = best.valid ? best.poly : fallback_polygon();\n\n    if ((int)out.size() < 4 || (int)out.size() > 1000) out = fallback_polygon();\n    {\n        set<pair<int,int>> st(out.begin(), out.end());\n        if ((int)st.size() != (int)out.size()) out = fallback_polygon();\n    }\n    for (auto &p : out) {\n        p.first = max(0, min(100000, p.first));\n        p.second = max(0, min(100000, p.second));\n    }\n\n    cout << out.size() << '\\n';\n    for (auto &p : out) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Rect {\n    int w, h;\n};\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct Candidate {\n    vector<Op> ops;\n    ll estW = 0, estH = 0, estScore = (1LL << 60);\n    int family = 0; // 0=columns, 1=rows\n    int mode = 0;\n    int k = 1;\n    string tag;\n};\n\nstruct Solver {\n    int N, T, sigma;\n    vector<Rect> a;\n    vector<Candidate> pool;\n\n    void get_dims(int i, int mode, bool forColumn, int &rot, int &ww, int &hh) {\n        int w = a[i].w, h = a[i].h;\n        rot = 0;\n        ww = w;\n        hh = h;\n\n        auto apply_rot = [&](bool flag) {\n            if (flag) {\n                rot = 1;\n                ww = h;\n                hh = w;\n            }\n        };\n\n        if (mode == 0) {\n            // minimize cross size\n            if (forColumn) apply_rot(w > h); // minimize width\n            else apply_rot(h > w);           // minimize height\n        } else if (mode == 1) {\n            // as is\n        } else if (mode == 2) {\n            // maximize cross size\n            if (forColumn) apply_rot(w < h); // maximize width\n            else apply_rot(h < w);           // maximize height\n        } else if (mode == 3) {\n            // maximize stacking-direction size\n            if (forColumn) apply_rot(h < w); // maximize height\n            else apply_rot(w < h);           // maximize width\n        } else {\n            // minimize stacking-direction size\n            if (forColumn) apply_rot(h > w); // minimize height\n            else apply_rot(w > h);           // minimize width\n        }\n    }\n\n    struct GroupScore {\n        ll major = 0;\n        ll minor = 0;\n    };\n\n    GroupScore eval_group(int l, int r, int mode, bool forColumn) {\n        GroupScore gs;\n        if (!(0 <= l && l < r && r <= N)) return gs;\n\n        if (forColumn) {\n            ll mxw = 0, sumh = 0;\n            for (int i = l; i < r; i++) {\n                int rot, ww, hh;\n                get_dims(i, mode, true, rot, ww, hh);\n                mxw = max<ll>(mxw, ww);\n                sumh += hh;\n            }\n            gs.major = mxw; // width\n            gs.minor = sumh; // height\n        } else {\n            ll sumw = 0, mxh = 0;\n            for (int i = l; i < r; i++) {\n                int rot, ww, hh;\n                get_dims(i, mode, false, rot, ww, hh);\n                sumw += ww;\n                mxh = max<ll>(mxh, hh);\n            }\n            gs.major = sumw; // width\n            gs.minor = mxh;  // height\n        }\n        return gs;\n    }\n\n    bool valid_groups(const vector<pair<int,int>>& groups) {\n        if (groups.empty()) return false;\n        if (groups[0].first != 0) return false;\n        if (groups.back().second != N) return false;\n        for (int i = 0; i < (int)groups.size(); i++) {\n            auto [l, r] = groups[i];\n            if (!(0 <= l && l < r && r <= N)) return false;\n            if (i && groups[i-1].second != l) return false;\n        }\n        return true;\n    }\n\n    ll eval_partition(const vector<pair<int,int>>& groups, int mode, bool forColumn, ll &outW, ll &outH) {\n        if (!valid_groups(groups)) {\n            outW = outH = (ll)4e18;\n            return (ll)4e18;\n        }\n\n        if (forColumn) {\n            ll totalW = 0, totalH = 0;\n            for (auto [l, r] : groups) {\n                auto gs = eval_group(l, r, mode, true);\n                totalW += gs.major;\n                totalH = max(totalH, gs.minor);\n            }\n            outW = totalW;\n            outH = totalH;\n        } else {\n            ll totalW = 0, totalH = 0;\n            for (auto [l, r] : groups) {\n                auto gs = eval_group(l, r, mode, false);\n                totalW = max(totalW, gs.major);\n                totalH += gs.minor;\n            }\n            outW = totalW;\n            outH = totalH;\n        }\n        return outW + outH;\n    }\n\n    vector<pair<int,int>> groups_equal(int k) {\n        vector<pair<int,int>> groups;\n        int l = 0;\n        for (int g = 0; g < k; g++) {\n            int r = (ll)N * (g + 1) / k;\n            if (r <= l) r = l + 1;\n            if (g == k - 1) r = N;\n            groups.push_back({l, r});\n            l = r;\n        }\n        // If N < k, compress, but actually k <= N in our use\n        while (!groups.empty() && groups.back().first == groups.back().second) groups.pop_back();\n        if (!groups.empty()) groups.back().second = N;\n        // normalize contiguity\n        vector<pair<int,int>> ng;\n        int cur = 0;\n        for (auto [l2, r2] : groups) {\n            if (cur >= N) break;\n            l2 = cur;\n            r2 = max(r2, l2 + 1);\n            r2 = min(r2, N);\n            ng.push_back({l2, r2});\n            cur = r2;\n        }\n        if (!ng.empty()) ng.back().second = N;\n        return ng;\n    }\n\n    vector<pair<int,int>> groups_balanced(int k, int mode, bool forColumn) {\n        vector<ll> weight(N);\n        for (int i = 0; i < N; i++) {\n            int rot, ww, hh;\n            get_dims(i, mode, forColumn, rot, ww, hh);\n            weight[i] = forColumn ? hh : ww;\n        }\n\n        ll total = 0;\n        for (ll x : weight) total += x;\n\n        vector<pair<int,int>> groups;\n        int l = 0;\n        ll pref = 0;\n        for (int g = 1; g < k; g++) {\n            ll target = total * g / k;\n            int r = l;\n            while (r < N - (k - g) && pref + weight[r] <= target) {\n                pref += weight[r];\n                r++;\n            }\n            if (r <= l) r = l + 1;\n            groups.push_back({l, r});\n            l = r;\n        }\n        groups.push_back({l, N});\n\n        if (!valid_groups(groups)) {\n            return groups_equal(k);\n        }\n        return groups;\n    }\n\n    void local_improve(vector<pair<int,int>>& groups, int mode, bool forColumn) {\n        if ((int)groups.size() <= 1) return;\n        if (!valid_groups(groups)) return;\n\n        ll curW, curH;\n        ll curScore = eval_partition(groups, mode, forColumn, curW, curH);\n\n        bool improved = true;\n        int iter = 30;\n        while (improved && iter--) {\n            improved = false;\n            for (int i = 0; i + 1 < (int)groups.size(); i++) {\n                auto [l1, r1] = groups[i];\n                auto [l2, r2] = groups[i + 1];\n                // boundary is r1 == l2\n                int bd = r1;\n\n                int bestBd = bd;\n                ll bestScore = curScore;\n\n                // try moving boundary by \u00b11, keeping both groups non-empty\n                for (int nb = max(l1 + 1, bd - 1); nb <= min(r2 - 1, bd + 1); nb++) {\n                    if (nb == bd) continue;\n                    auto ng = groups;\n                    ng[i] = {l1, nb};\n                    ng[i + 1] = {nb, r2};\n                    if (!valid_groups(ng)) continue;\n                    ll w, h;\n                    ll sc = eval_partition(ng, mode, forColumn, w, h);\n                    if (sc < bestScore) {\n                        bestScore = sc;\n                        bestBd = nb;\n                    }\n                }\n\n                if (bestBd != bd) {\n                    groups[i].second = bestBd;\n                    groups[i + 1].first = bestBd;\n                    curScore = bestScore;\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    Candidate build_candidate(const vector<pair<int,int>>& groups, int mode, bool forColumn, const string& tag) {\n        Candidate c;\n        c.family = forColumn ? 0 : 1;\n        c.mode = mode;\n        c.k = (int)groups.size();\n        c.tag = tag;\n\n        ll W, H;\n        c.estScore = eval_partition(groups, mode, forColumn, W, H);\n        c.estW = W;\n        c.estH = H;\n\n        vector<int> firsts;\n        for (int g = 0; g < (int)groups.size(); g++) {\n            auto [l, r] = groups[g];\n            int first = l;\n            firsts.push_back(first);\n            for (int i = l; i < r; i++) {\n                int rot, ww, hh;\n                get_dims(i, mode, forColumn, rot, ww, hh);\n                int b;\n                if (i == l) {\n                    b = (g == 0 ? -1 : firsts[g - 1]);\n                } else {\n                    b = first;\n                }\n                c.ops.push_back({i, rot, forColumn ? 'U' : 'L', b});\n            }\n        }\n\n        // Final safety check\n        for (int idx = 0; idx < (int)c.ops.size(); idx++) {\n            auto &op = c.ops[idx];\n            if (!(0 <= op.p && op.p < N)) {\n                // impossible fallback\n                c.ops.clear();\n                for (int i = 0; i < N; i++) c.ops.push_back({i, 0, 'U', -1});\n                break;\n            }\n            if (!(op.b == -1 || (0 <= op.b && op.b < op.p))) {\n                c.ops.clear();\n                for (int i = 0; i < N; i++) c.ops.push_back({i, 0, 'U', -1});\n                break;\n            }\n        }\n\n        return c;\n    }\n\n    void try_add(vector<pair<int,int>> groups, int mode, bool forColumn, const string& prefix) {\n        if (!valid_groups(groups)) return;\n        local_improve(groups, mode, forColumn);\n        if (!valid_groups(groups)) return;\n        pool.push_back(build_candidate(\n            groups, mode, forColumn,\n            prefix + \"_k\" + to_string((int)groups.size()) + \"_m\" + to_string(mode)\n        ));\n    }\n\n    void build_pool() {\n        pool.clear();\n\n        int K = min(N, 14);\n        int MODES = 5;\n\n        for (int mode = 0; mode < MODES; mode++) {\n            for (int k = 1; k <= K; k++) {\n                try_add(groups_equal(k), mode, true, \"col_eq\");\n                try_add(groups_equal(k), mode, false, \"row_eq\");\n                if (k >= 2) {\n                    try_add(groups_balanced(k, mode, true), mode, true, \"col_bal\");\n                    try_add(groups_balanced(k, mode, false), mode, false, \"row_bal\");\n                }\n            }\n        }\n\n        // deduplicate by exact sequence\n        unordered_set<string> seen;\n        vector<Candidate> uniq;\n        for (auto &c : pool) {\n            string key;\n            key.reserve(c.ops.size() * 12);\n            for (auto &op : c.ops) {\n                key += to_string(op.p);\n                key += ',';\n                key += char('0' + op.r);\n                key += ',';\n                key += op.d;\n                key += ',';\n                key += to_string(op.b);\n                key += ';';\n            }\n            if (seen.insert(key).second) uniq.push_back(c);\n        }\n        pool.swap(uniq);\n\n        sort(pool.begin(), pool.end(), [&](const Candidate& x, const Candidate& y) {\n            if (x.estScore != y.estScore) return x.estScore < y.estScore;\n            if (x.family != y.family) return x.family < y.family;\n            if (x.k != y.k) return x.k < y.k;\n            return x.mode < y.mode;\n        });\n\n        if (pool.empty()) {\n            Candidate c;\n            c.family = 0;\n            c.mode = 1;\n            c.k = 1;\n            c.tag = \"fallback\";\n            c.estW = c.estH = c.estScore = 0;\n            for (int i = 0; i < N; i++) c.ops.push_back({i, 0, 'U', -1});\n            pool.push_back(c);\n        }\n    }\n\n    void print_candidate(const Candidate& c) {\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n    }\n\n    void solve() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> T >> sigma;\n        a.resize(N);\n        for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n        build_pool();\n\n        vector<int> trialOrder;\n        vector<vector<bool>> used(2, vector<bool>(N + 1, false));\n        for (int i = 0; i < (int)pool.size(); i++) {\n            auto &c = pool[i];\n            if (!used[c.family][c.k]) {\n                used[c.family][c.k] = true;\n                trialOrder.push_back(i);\n            }\n            if ((int)trialOrder.size() >= min(T, 24)) break;\n        }\n        for (int i = 0; i < (int)pool.size() && (int)trialOrder.size() < min(T, 48); i++) {\n            bool exists = false;\n            for (int x : trialOrder) if (x == i) { exists = true; break; }\n            if (!exists) trialOrder.push_back(i);\n        }\n\n        ll bestMeasured = (1LL << 60);\n        int bestIdx = 0;\n\n        for (int t = 0; t < T; t++) {\n            int idx;\n            if (t < (int)trialOrder.size()) {\n                idx = trialOrder[t];\n            } else {\n                const Candidate &bc = pool[bestIdx];\n                vector<int> near;\n                for (int i = 0; i < (int)pool.size(); i++) {\n                    const Candidate &x = pool[i];\n                    if (x.family == bc.family && abs(x.k - bc.k) <= 2) near.push_back(i);\n                }\n                if (near.empty()) idx = bestIdx;\n                else idx = near[(t - (int)trialOrder.size()) % near.size()];\n            }\n\n            cout << \"# \" << pool[idx].tag\n                 << \" est=\" << pool[idx].estW << \"+\" << pool[idx].estH\n                 << \"=\" << pool[idx].estScore << \"\\n\";\n            print_candidate(pool[idx]);\n\n            ll Wm, Hm;\n            cin >> Wm >> Hm;\n            ll sm = Wm + Hm;\n            if (sm < bestMeasured) {\n                bestMeasured = sm;\n                bestIdx = idx;\n            }\n        }\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Candidate {\n    int depth;   // target depth\n    int beauty;\n    int parent;\n    int v;\n    bool operator<(const Candidate& other) const {\n        if (depth != other.depth) return depth < other.depth;      // max depth first\n        if (beauty != other.beauty) return beauty < other.beauty;  // then large beauty\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, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<pair<int,int>> edges(M);\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n\n    vector<pair<int,int>> coord(N);\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        coord[i] = {x, y};\n    }\n\n    // -------- Initial construction --------\n    // Idea:\n    // - small A vertices are better as roots / shallow scaffold\n    // - use a global candidate PQ that prefers deeper assignment and larger A\n    vector<int> parent(N, -2); // -2 = unassigned, -1 = root\n    vector<int> depth(N, -1);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (A[a] != A[b]) return A[a] < A[b];\n        return a < b;\n    });\n\n    priority_queue<Candidate> pq;\n\n    auto add_frontier = [&](int u) {\n        if (depth[u] >= H) return;\n        for (int v : g[u]) {\n            if (parent[v] == -2) {\n                pq.push(Candidate{depth[u] + 1, A[v], u, v});\n            }\n        }\n    };\n\n    // Start from several low-beauty roots gradually.\n    int ptr = 0;\n    while (true) {\n        while (ptr < N && parent[ord[ptr]] != -2) ptr++;\n        if (ptr == N) break;\n\n        int r = ord[ptr];\n        parent[r] = -1;\n        depth[r] = 0;\n        add_frontier(r);\n\n        // Expand as much as possible with current frontier.\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n            int v = cur.v, p = cur.parent;\n            if (parent[v] != -2) continue;\n            if (parent[p] == -2) continue;\n            if (depth[p] + 1 != cur.depth) continue;\n            if (cur.depth > H) continue;\n\n            parent[v] = p;\n            depth[v] = cur.depth;\n            add_frontier(v);\n\n            // If everything assigned, done.\n            // (No need to check here, outer loop handles it.)\n        }\n    }\n\n    // Safety fallback\n    for (int i = 0; i < N; i++) {\n        if (parent[i] == -2) {\n            parent[i] = -1;\n            depth[i] = 0;\n        }\n    }\n\n    // -------- Data structures for local improvement --------\n    vector<vector<int>> children(N);\n    vector<int> tin(N), tout(N), subSum(N), subHeight(N);\n    int timer = 0;\n\n    function<void()> rebuild = [&]() {\n        for (int i = 0; i < N; i++) children[i].clear();\n        for (int v = 0; v < N; v++) {\n            if (parent[v] >= 0) children[parent[v]].push_back(v);\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            }\n        }\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (int v : children[u]) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n\n        timer = 0;\n        function<void(int)> dfs = [&](int u) {\n            tin[u] = timer++;\n            subSum[u] = A[u];\n            subHeight[u] = 0;\n            for (int v : children[u]) {\n                dfs(v);\n                subSum[u] += subSum[v];\n                subHeight[u] = max(subHeight[u], subHeight[v] + 1);\n            }\n            tout[u] = timer;\n        };\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) dfs(i);\n        }\n    };\n\n    auto is_ancestor = [&](int a, int b) -> bool {\n        return tin[a] <= tin[b] && tout[b] <= tout[a];\n    };\n\n    rebuild();\n\n    auto score_est = [&]() -> long long {\n        long long s = 1;\n        for (int i = 0; i < N; i++) s += 1LL * (depth[i] + 1) * A[i];\n        return s;\n    };\n\n    // -------- Local improvement: subtree reparenting --------\n    // Move subtree v under neighboring u if gain positive and valid.\n    // Since H is small and N=1000, full rebuild after successful move is acceptable.\n    long long bestScore = score_est();\n\n    bool improved = true;\n    int rounds = 0;\n    while (improved && rounds < 30) {\n        improved = false;\n        rounds++;\n\n        // Try promising vertices first: larger subtree weight and larger A.\n        vector<int> vs(N);\n        iota(vs.begin(), vs.end(), 0);\n        sort(vs.begin(), vs.end(), [&](int a, int b) {\n            long long wa = 1LL * subSum[a] * 100 + A[a];\n            long long wb = 1LL * subSum[b] * 100 + A[b];\n            if (wa != wb) return wa > wb;\n            return a < b;\n        });\n\n        for (int v : vs) {\n            int bestParent = -3;\n            int bestNewDepth = depth[v];\n\n            for (int u : g[v]) {\n                if (u == parent[v]) continue;\n                // Cannot attach under own descendant.\n                if (is_ancestor(v, u)) continue;\n\n                int nd = depth[u] + 1;\n                if (nd <= depth[v]) continue; // only improving moves\n                if (nd + subHeight[v] > H) continue; // subtree must fit\n\n                if (nd > bestNewDepth) {\n                    bestNewDepth = nd;\n                    bestParent = u;\n                }\n            }\n\n            if (bestParent != -3) {\n                int oldParent = parent[v];\n                parent[v] = bestParent;\n                rebuild();\n                long long sc = score_est();\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    improved = true;\n                } else {\n                    // revert\n                    parent[v] = oldParent;\n                    rebuild();\n                }\n            }\n        }\n    }\n\n    // -------- Final validity repair (just in case) --------\n    // Ensure depth <= H and no invalid parent remains. If any issue, make root.\n    rebuild();\n    for (int i = 0; i < N; i++) {\n        if (depth[i] < 0 || depth[i] > H) {\n            parent[i] = -1;\n        }\n    }\n    rebuild();\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int TOPK = 10;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nstruct FallbackAction {\n    int i, j;\n    char dir;\n    int len;\n};\n\nstruct CheapCand {\n    char d;\n    int p;\n    int k;\n    int removed;\n};\n\nstruct EvalCand {\n    char d;\n    int p;\n    int k;\n    int gain;\n    int removed;\n    bool valid = false;\n};\n\nstatic inline void apply_move(vector<string>& b, char d, int p) {\n    int n = (int)b.size();\n    if (d == 'L') {\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        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        for (int i = 0; i + 1 < n; i++) b[i][p] = b[i + 1][p];\n        b[n - 1][p] = '.';\n    } else if (d == 'D') {\n        for (int i = n - 1; i >= 1; i--) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n}\n\nstatic inline int safe_limit(const vector<string>& b, char d, int p) {\n    int n = (int)b.size();\n    int safe = 0;\n    if (d == 'L') {\n        while (safe < n && b[p][safe] != 'o') safe++;\n    } else if (d == 'R') {\n        while (safe < n && b[p][n - 1 - safe] != 'o') safe++;\n    } else if (d == 'U') {\n        while (safe < n && b[safe][p] != 'o') safe++;\n    } else if (d == 'D') {\n        while (safe < n && b[n - 1 - safe][p] != 'o') safe++;\n    }\n    return safe;\n}\n\nstatic inline int fallback_cost_and_plan(\n    const vector<string>& b,\n    vector<FallbackAction>* plan = nullptr\n) {\n    int n = (int)b.size();\n    int total = 0;\n    if (plan) plan->clear();\n\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            if (b[i][j] != 'x') continue;\n\n            int best = INT_MAX;\n            char bestDir = '?';\n            int bestLen = -1;\n\n            bool ok = true;\n            for (int r = 0; r < i; r++) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int c = 2 * (i + 1);\n                if (c < best) best = c, bestDir = 'U', bestLen = i + 1;\n            }\n\n            ok = true;\n            for (int r = i + 1; r < n; r++) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int c = 2 * (n - i);\n                if (c < best) best = c, bestDir = 'D', bestLen = n - i;\n            }\n\n            ok = true;\n            for (int c = 0; c < j; c++) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int cc = 2 * (j + 1);\n                if (cc < best) best = cc, bestDir = 'L', bestLen = j + 1;\n            }\n\n            ok = true;\n            for (int c = j + 1; c < n; c++) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int cc = 2 * (n - j);\n                if (cc < best) best = cc, bestDir = 'R', bestLen = n - j;\n            }\n\n            total += best;\n            if (plan) plan->push_back({i, j, bestDir, bestLen});\n        }\n    }\n\n    return total;\n}\n\nstatic inline bool cheap_better(const CheapCand& a, const CheapCand& b) {\n    // maximize removed / k\n    long long lhs = 1LL * a.removed * b.k;\n    long long rhs = 1LL * b.removed * a.k;\n    if (lhs != rhs) return lhs > rhs;\n    if (a.removed != b.removed) return a.removed > b.removed;\n    if (a.k != b.k) return a.k < b.k;\n    if (a.d != b.d) return a.d < b.d;\n    return a.p < b.p;\n}\n\nstatic inline bool eval_better(const EvalCand& a, const EvalCand& b) {\n    if (!b.valid) return true;\n    if (a.gain != b.gain) return a.gain > b.gain;\n    if (a.k != b.k) return a.k < b.k;\n    if (a.removed != b.removed) return a.removed > b.removed;\n    if (a.d != b.d) return a.d < b.d;\n    return a.p < b.p;\n}\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<Op> ans;\n\n    auto push_topk = [&](vector<CheapCand>& vec, CheapCand cand) {\n        vec.push_back(cand);\n        int m = (int)vec.size();\n        while (m > 1 && cheap_better(vec[m - 1], vec[m - 2])) {\n            swap(vec[m - 1], vec[m - 2]);\n            --m;\n        }\n        if ((int)vec.size() > TOPK) vec.pop_back();\n    };\n\n    while (true) {\n        int curCost = fallback_cost_and_plan(board, nullptr);\n\n        vector<CheapCand> shortlist;\n        const char dirs[4] = {'L', 'R', 'U', 'D'};\n\n        // Collect top-K cheap candidates\n        for (char d : dirs) {\n            for (int p = 0; p < n; p++) {\n                int lim = safe_limit(board, d, p);\n                if (lim == 0) continue;\n\n                int removed = 0;\n                for (int k = 1; k <= lim; k++) {\n                    if (d == 'L') {\n                        if (board[p][k - 1] == 'x') removed++;\n                    } else if (d == 'R') {\n                        if (board[p][n - k] == 'x') removed++;\n                    } else if (d == 'U') {\n                        if (board[k - 1][p] == 'x') removed++;\n                    } else {\n                        if (board[n - k][p] == 'x') removed++;\n                    }\n\n                    if (removed == 0) continue;\n\n                    // Mild pruning: usually useful cases\n                    if (!(removed >= 2 || k == 1)) continue;\n\n                    push_topk(shortlist, {d, p, k, removed});\n                }\n            }\n        }\n\n        EvalCand bestEval;\n        for (auto &cc : shortlist) {\n            vector<string> tmp = board;\n            for (int t = 0; t < cc.k; t++) apply_move(tmp, cc.d, cc.p);\n            int newCost = fallback_cost_and_plan(tmp, nullptr);\n            int gain = curCost - (cc.k + newCost);\n            EvalCand ec{cc.d, cc.p, cc.k, gain, cc.removed, gain > 0};\n            if (ec.valid && eval_better(ec, bestEval)) bestEval = ec;\n        }\n\n        if (!bestEval.valid) break;\n\n        for (int t = 0; t < bestEval.k; t++) {\n            apply_move(board, bestEval.d, bestEval.p);\n            ans.push_back({bestEval.d, bestEval.p});\n        }\n    }\n\n    // Exact fallback finish\n    vector<FallbackAction> plan;\n    fallback_cost_and_plan(board, &plan);\n\n    for (auto &ac : plan) {\n        if (ac.dir == 'U') {\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'U', ac.j);\n                ans.push_back({'U', ac.j});\n            }\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'D', ac.j);\n                ans.push_back({'D', ac.j});\n            }\n        } else if (ac.dir == 'D') {\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'D', ac.j);\n                ans.push_back({'D', ac.j});\n            }\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'U', ac.j);\n                ans.push_back({'U', ac.j});\n            }\n        } else if (ac.dir == 'L') {\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'L', ac.i);\n                ans.push_back({'L', ac.i});\n            }\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'R', ac.i);\n                ans.push_back({'R', ac.i});\n            }\n        } else if (ac.dir == 'R') {\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'R', ac.i);\n                ans.push_back({'R', ac.i});\n            }\n            for (int t = 0; t < ac.len; t++) {\n                apply_move(board, 'L', ac.i);\n                ans.push_back({'L', ac.i});\n            }\n        }\n    }\n\n    if ((int)ans.size() > 4 * n * n) {\n        ans.resize(4 * n * n);\n    }\n\n    for (auto &op : ans) {\n        cout << op.d << ' ' << op.p << '\\n';\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\n\nstruct Solution {\n    array<int, MAXN> a{}, b{};\n    long long err = (1LL << 60);\n};\n\nstruct Config {\n    int K = 0;\n    vector<int> hubs;\n    vector<int> order;\n    vector<int> assigned_hub; // size N\n    vector<int> emitted_leaf; // size K, -1 if none\n};\n\nint N, L;\narray<int, MAXN> T;\n\nstatic uint64_t rng_state =\n    chrono::high_resolution_clock::now().time_since_epoch().count();\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 rnd(int l, int r) {\n    return l + (int)(rng64() % (uint64_t)(r - l + 1));\n}\n\nstatic long long evaluate_solution(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    array<int, MAXN> cnt{};\n    int cur = 0;\n    for (int step = 0; step < L; ++step) {\n        int c = ++cnt[cur];\n        cur = (c & 1) ? a[cur] : b[cur];\n    }\n    long long err = 0;\n    for (int i = 0; i < N; ++i) err += llabs((long long)cnt[i] - T[i]);\n    return err;\n}\n\nstatic Solution build_from_config(const Config& cfg) {\n    Solution sol;\n    vector<int> pos(N, -1);\n    vector<char> is_hub(N, false);\n    for (int h : cfg.hubs) is_hub[h] = true;\n    for (int i = 0; i < cfg.K; ++i) pos[cfg.order[i]] = i;\n\n    for (int i = 0; i < N; ++i) sol.a[i] = sol.b[i] = i;\n\n    for (int i = 0; i < cfg.K; ++i) {\n        int h = cfg.order[i];\n        int nxt = cfg.order[(i + 1) % cfg.K];\n        sol.a[h] = h;\n        sol.b[h] = (cfg.emitted_leaf[i] == -1 ? nxt : cfg.emitted_leaf[i]);\n    }\n\n    for (int x = 0; x < N; ++x) {\n        if (is_hub[x]) continue;\n        int h = cfg.assigned_hub[x];\n        int p = pos[h];\n        int nxt = cfg.order[(p + 1) % cfg.K];\n        sol.a[x] = nxt;\n        sol.b[x] = nxt;\n    }\n\n    sol.err = evaluate_solution(sol.a, sol.b);\n    return sol;\n}\n\nstatic Config make_initial_config(const vector<int>& hubs, const vector<int>& order, int mode_assign, int mode_emit) {\n    Config cfg;\n    cfg.K = (int)hubs.size();\n    cfg.hubs = hubs;\n    cfg.order = order;\n    cfg.assigned_hub.assign(N, order[0]);\n    cfg.emitted_leaf.assign(cfg.K, -1);\n\n    vector<char> is_hub(N, false);\n    for (int h : hubs) is_hub[h] = true;\n\n    vector<int> pos(N, -1);\n    for (int i = 0; i < cfg.K; ++i) pos[order[i]] = i;\n\n    vector<int> leaves;\n    for (int i = 0; i < N; ++i) if (!is_hub[i]) leaves.push_back(i);\n\n    vector<long long> load(N, 0);\n    for (int h : hubs) load[h] = T[h];\n\n    vector<int> leaf_sorted = leaves;\n    sort(leaf_sorted.begin(), leaf_sorted.end(), [&](int x, int y) {\n        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    // Assign leaves to hubs\n    for (int x : leaf_sorted) {\n        int best_h = hubs[0];\n        long long best_score = (1LL << 60);\n        for (int h : hubs) {\n            long long score = 0;\n            if (mode_assign == 0) {\n                score = load[h];\n            } else if (mode_assign == 1) {\n                score = load[h] + pos[h] * 50LL;\n            } else {\n                score = load[h] + (long long)abs(pos[h] - cfg.K / 2) * 50LL;\n            }\n            if (score < best_score) {\n                best_score = score;\n                best_h = h;\n            }\n        }\n        cfg.assigned_hub[x] = best_h;\n        load[best_h] += T[x];\n    }\n\n    vector<vector<int>> group(N);\n    for (int x : leaves) group[cfg.assigned_hub[x]].push_back(x);\n    for (int h : hubs) {\n        sort(group[h].begin(), group[h].end(), [&](int x, int y) {\n            if (T[x] != T[y]) return T[x] > T[y];\n            return x < y;\n        });\n    }\n\n    // Choose emitted leaf per hub\n    for (int i = 0; i < cfg.K; ++i) {\n        int h = order[i];\n        if (group[h].empty()) continue;\n\n        if (mode_emit == 0) {\n            cfg.emitted_leaf[i] = -1;\n        } else if (mode_emit == 1) {\n            cfg.emitted_leaf[i] = group[h][0];\n        } else if (mode_emit == 2) {\n            if (T[group[h][0]] * 2 >= T[h]) cfg.emitted_leaf[i] = group[h][0];\n        } else if (mode_emit == 3) {\n            cfg.emitted_leaf[i] = group[h].size() >= 2 ? group[h][1] : group[h][0];\n        } else {\n            long long bestd = (1LL << 60);\n            int bestx = -1;\n            for (int x : group[h]) {\n                long long d = llabs(2LL * T[x] - (long long)T[h]);\n                if (d < bestd) {\n                    bestd = d;\n                    bestx = x;\n                }\n            }\n            cfg.emitted_leaf[i] = bestx;\n        }\n    }\n\n    return cfg;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    auto time_start = chrono::high_resolution_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - time_start).count();\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        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    Solution best;\n    Config best_cfg;\n\n    // Fallback\n    {\n        int mx = ord[0];\n        array<int, MAXN> a{}, b{};\n        for (int i = 0; i < N; ++i) a[i] = b[i] = mx;\n        a[mx] = mx;\n        b[mx] = mx;\n        best.a = a;\n        best.b = b;\n        best.err = evaluate_solution(a, b);\n    }\n\n    vector<int> Ks = {4, 6, 8, 10, 12, 16, 20, 24, 32};\n\n    for (int K : Ks) {\n        if (elapsed() > 1.1) break;\n        K = min(K, N);\n        if (K <= 0) continue;\n\n        vector<int> hubs(ord.begin(), ord.begin() + K);\n\n        vector<vector<int>> orders;\n\n        // descending\n        orders.push_back(hubs);\n\n        // ascending\n        {\n            auto v = hubs;\n            reverse(v.begin(), v.end());\n            orders.push_back(v);\n        }\n\n        // alternating\n        {\n            vector<int> v;\n            int l = 0, r = K - 1;\n            while (l <= r) {\n                v.push_back(hubs[l++]);\n                if (l <= r) v.push_back(hubs[r--]);\n            }\n            orders.push_back(v);\n        }\n\n        // odd-even by target parity\n        {\n            auto v = hubs;\n            stable_sort(v.begin(), v.end(), [&](int x, int y) {\n                int px = T[x] & 1, py = T[y] & 1;\n                if (px != py) return px > py;\n                if (T[x] != T[y]) return T[x] > T[y];\n                return x < y;\n            });\n            orders.push_back(v);\n        }\n\n        for (auto& order : orders) {\n            for (int mode_assign = 0; mode_assign < 3; ++mode_assign) {\n                for (int mode_emit = 0; mode_emit < 5; ++mode_emit) {\n                    if (elapsed() > 1.25) break;\n                    Config cfg = make_initial_config(hubs, order, mode_assign, mode_emit);\n                    Solution sol = build_from_config(cfg);\n                    if (sol.err < best.err) {\n                        best = sol;\n                        best_cfg = cfg;\n                    }\n                }\n            }\n        }\n    }\n\n    // Local improvement on best config\n    if (best_cfg.K > 0) {\n        Config cur = best_cfg;\n        Solution cur_sol = build_from_config(cur);\n\n        while (elapsed() < 1.92) {\n            int op = rnd(0, 3);\n            Config nxt = cur;\n\n            if (op == 0) {\n                // swap two hubs in order\n                if (nxt.K >= 2) {\n                    int i = rnd(0, nxt.K - 1);\n                    int j = rnd(0, nxt.K - 1);\n                    if (i != j) swap(nxt.order[i], nxt.order[j]);\n                }\n            } else if (op == 1) {\n                // change emitted leaf of one hub\n                vector<char> is_hub(N, false);\n                for (int h : nxt.hubs) is_hub[h] = true;\n\n                int i = rnd(0, nxt.K - 1);\n                int h = nxt.order[i];\n\n                vector<int> cand = {-1};\n                for (int x = 0; x < N; ++x) {\n                    if (!is_hub[x] && nxt.assigned_hub[x] == h) cand.push_back(x);\n                }\n                nxt.emitted_leaf[i] = cand[rnd(0, (int)cand.size() - 1)];\n            } else if (op == 2) {\n                // reassign one leaf to another hub\n                vector<char> is_hub(N, false);\n                for (int h : nxt.hubs) is_hub[h] = true;\n\n                vector<int> leaves;\n                for (int x = 0; x < N; ++x) if (!is_hub[x]) leaves.push_back(x);\n                if (!leaves.empty()) {\n                    int x = leaves[rnd(0, (int)leaves.size() - 1)];\n                    int h = nxt.hubs[rnd(0, nxt.K - 1)];\n                    nxt.assigned_hub[x] = h;\n                }\n            } else {\n                // swap one hub with one leaf\n                vector<char> is_hub(N, false);\n                for (int h : nxt.hubs) is_hub[h] = true;\n\n                vector<int> leaves;\n                for (int x = 0; x < N; ++x) if (!is_hub[x]) leaves.push_back(x);\n                if (!leaves.empty()) {\n                    int hi = rnd(0, nxt.K - 1);\n                    int old_h = nxt.hubs[hi];\n                    int new_h = leaves[rnd(0, (int)leaves.size() - 1)];\n\n                    // replace in hubs and order\n                    nxt.hubs[hi] = new_h;\n                    for (int &v : nxt.order) if (v == old_h) { v = new_h; break; }\n\n                    // reassign all leaves previously assigned to old_h\n                    for (int x = 0; x < N; ++x) {\n                        if (x == old_h) continue;\n                        if (!count(nxt.hubs.begin(), nxt.hubs.end(), x) && nxt.assigned_hub[x] == old_h) {\n                            nxt.assigned_hub[x] = new_h;\n                        }\n                    }\n                    if ((int)nxt.assigned_hub.size() < N) nxt.assigned_hub.resize(N, new_h);\n                    nxt.assigned_hub[old_h] = new_h;\n\n                    // fix emitted leaves that might now point to a hub\n                    vector<char> new_is_hub(N, false);\n                    for (int h : nxt.hubs) new_is_hub[h] = true;\n                    for (int &x : nxt.emitted_leaf) {\n                        if (x != -1 && new_is_hub[x]) x = -1;\n                    }\n                }\n            }\n\n            Solution nxt_sol = build_from_config(nxt);\n            if (nxt_sol.err < cur_sol.err) {\n                cur = nxt;\n                cur_sol = nxt_sol;\n                if (cur_sol.err < best.err) {\n                    best = cur_sol;\n                    best_cfg = cur;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline long long part1by1(unsigned x) {\n    unsigned long long n = x;\n    n = (n | (n << 16)) & 0x0000FFFF0000FFFFULL;\n    n = (n | (n << 8)) & 0x00FF00FF00FF00FFULL;\n    n = (n | (n << 4)) & 0x0F0F0F0F0F0F0F0FULL;\n    n = (n | (n << 2)) & 0x3333333333333333ULL;\n    n = (n | (n << 1)) & 0x5555555555555555ULL;\n    return (long long)n;\n}\nstatic inline long long morton_key(int x, int y) {\n    return (part1by1((unsigned)x) << 1) | part1by1((unsigned)y);\n}\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 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    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), cx(N), cy(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    auto center_dist = [&](int a, int b) -> int {\n        long long dx = 1LL * cx[a] - cx[b];\n        long long dy = 1LL * cy[a] - cy[b];\n        return (int)floor(sqrt((double)(dx * dx + dy * dy)));\n    };\n\n    auto rect_gap_dist = [&](int a, int b) -> int {\n        int dx = 0, dy = 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        if (ry[a] < ly[b]) dy = ly[b] - ry[a];\n        else if (ry[b] < ly[a]) dy = ly[a] - ry[b];\n        return (int)floor(sqrt((double)(1LL * dx * dx + 1LL * dy * dy)));\n    };\n\n    // Hybrid estimated distance.\n    auto est_dist = [&](int a, int b) -> int {\n        int dc = center_dist(a, b);\n        int dg = rect_gap_dist(a, b);\n        // Put stronger weight on center but use gap as closeness prior.\n        return (3 * dc + 2 * dg) / 5;\n    };\n\n    auto approx_mst_cost = [&](const vector<int>& vs) -> long long {\n        int n = (int)vs.size();\n        if (n <= 1) return 0;\n        const int INF = 1e9;\n        vector<int> best(n, INF);\n        vector<char> used(n, 0);\n        best[0] = 0;\n        long long res = 0;\n        for (int it = 0; it < n; it++) {\n            int v = -1;\n            for (int i = 0; i < n; i++) {\n                if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n            }\n            used[v] = 1;\n            res += best[v];\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                int w = est_dist(vs[v], vs[j]);\n                if (w < best[j]) best[j] = w;\n            }\n        }\n        return res;\n    };\n\n    auto partition_by_order = [&](const vector<int>& ord) -> vector<vector<int>> {\n        vector<vector<int>> groups(M);\n        int ptr = 0;\n        for (int i = 0; i < M; i++) {\n            groups[i].assign(ord.begin() + ptr, ord.begin() + ptr + G[i]);\n            ptr += G[i];\n        }\n        return groups;\n    };\n\n    auto total_cost = [&](const vector<vector<int>>& groups) -> long long {\n        long long sum = 0;\n        for (auto &g : groups) sum += approx_mst_cost(g);\n        return sum;\n    };\n\n    vector<int> all(N);\n    iota(all.begin(), all.end(), 0);\n\n    vector<vector<int>> candidate_orders;\n\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cy[a] != cy[b]) return cy[a] < cy[b];\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n            if (sa != sb) return sa < sb;\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            int sa = cx[a] - cy[a], sb = cx[b] - cy[b];\n            if (sa != sb) return sa < sb;\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            long long ka = morton_key(cx[a], cy[a]);\n            long long kb = morton_key(cx[b], cy[b]);\n            if (ka != kb) return ka < kb;\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        vector<pair<pair<int,int>, int>> pts;\n        for (int v : all) pts.push_back({{cx[v] / 700, cy[v]}, v});\n        sort(pts.begin(), pts.end(), [&](auto &A, auto &B) {\n            int ba = A.first.first, bb = B.first.first;\n            if (ba != bb) return ba < bb;\n            if (ba & 1) return A.first.second > B.first.second;\n            return A.first.second < B.first.second;\n        });\n        vector<int> ord;\n        for (auto &p : pts) ord.push_back(p.second);\n        candidate_orders.push_back(ord);\n    }\n    {\n        vector<pair<pair<int,int>, int>> pts;\n        for (int v : all) pts.push_back({{cy[v] / 700, cx[v]}, v});\n        sort(pts.begin(), pts.end(), [&](auto &A, auto &B) {\n            int ba = A.first.first, bb = B.first.first;\n            if (ba != bb) return ba < bb;\n            if (ba & 1) return A.first.second > B.first.second;\n            return A.first.second < B.first.second;\n        });\n        vector<int> ord;\n        for (auto &p : pts) ord.push_back(p.second);\n        candidate_orders.push_back(ord);\n    }\n\n    vector<vector<int>> groups;\n    long long best_score = (1LL << 62);\n    for (auto &ord : candidate_orders) {\n        auto cand = partition_by_order(ord);\n        long long c = total_cost(cand);\n        if (c < best_score) {\n            best_score = c;\n            groups = move(cand);\n        }\n    }\n\n    auto try_replace_pair = [&](int gi, vector<int> A2, vector<int> B2) -> bool {\n        long long oldv = approx_mst_cost(groups[gi]) + approx_mst_cost(groups[gi + 1]);\n        long long newv = approx_mst_cost(A2) + approx_mst_cost(B2);\n        if (newv < oldv) {\n            groups[gi] = move(A2);\n            groups[gi + 1] = move(B2);\n            return true;\n        }\n        return false;\n    };\n\n    // Local improvement on adjacent pairs:\n    // 1) wider boundary swaps\n    // 2) repartition merged pair by several local orders\n    for (int pass = 0; pass < 4; pass++) {\n        bool improved = false;\n        for (int gi = 0; gi + 1 < M; gi++) {\n            auto &A = groups[gi];\n            auto &B = groups[gi + 1];\n            int sa = (int)A.size(), sb = (int)B.size();\n            if (sa == 0 || sb == 0) continue;\n\n            // 1-1 boundary swap\n            {\n                long long base = approx_mst_cost(A) + approx_mst_cost(B);\n                long long best = base;\n                int besta = -1, bestb = -1;\n\n                vector<int> candA, candB;\n                for (int i = max(0, sa - 10); i < sa; i++) candA.push_back(i);\n                for (int i = 0; i < min(sb, 10); i++) candB.push_back(i);\n\n                for (int ia : candA) for (int ib : candB) {\n                    vector<int> nA = A, nB = B;\n                    swap(nA[ia], nB[ib]);\n                    long long val = approx_mst_cost(nA) + approx_mst_cost(nB);\n                    if (val < best) {\n                        best = val;\n                        besta = ia;\n                        bestb = ib;\n                    }\n                }\n                if (besta != -1) {\n                    swap(A[besta], B[bestb]);\n                    improved = true;\n                }\n            }\n\n            // Repartition merged pair using several local orders\n            vector<int> U = A;\n            U.insert(U.end(), B.begin(), B.end());\n\n            vector<vector<int>> ords;\n            {\n                auto ord = U;\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (cx[a] != cx[b]) return cx[a] < cx[b];\n                    return cy[a] < cy[b];\n                });\n                ords.push_back(ord);\n            }\n            {\n                auto ord = U;\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    if (cy[a] != cy[b]) return cy[a] < cy[b];\n                    return cx[a] < cx[b];\n                });\n                ords.push_back(ord);\n            }\n            {\n                auto ord = U;\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n                    if (sa != sb) return sa < sb;\n                    return cx[a] < cx[b];\n                });\n                ords.push_back(ord);\n            }\n            {\n                auto ord = U;\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int sa = cx[a] - cy[a], sb = cx[b] - cy[b];\n                    if (sa != sb) return sa < sb;\n                    return cx[a] < cx[b];\n                });\n                ords.push_back(ord);\n            }\n            {\n                auto ord = U;\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    long long ka = morton_key(cx[a], cy[a]);\n                    long long kb = morton_key(cx[b], cy[b]);\n                    if (ka != kb) return ka < kb;\n                    return a < b;\n                });\n                ords.push_back(ord);\n            }\n\n            for (auto &ord : ords) {\n                vector<int> A2(ord.begin(), ord.begin() + sa);\n                vector<int> B2(ord.begin() + sa, ord.end());\n                if (try_replace_pair(gi, A2, B2)) improved = true;\n            }\n        }\n        if (!improved) break;\n        if (timer.elapsed() > 1.1) break;\n    }\n\n    // Query phase.\n    vector<vector<pair<int,int>>> queried_edges(M);\n    int used_queries = 0;\n\n    auto do_query = [&](const vector<int>& subset) -> vector<pair<int,int>> {\n        cout << \"? \" << subset.size();\n        for (int v : subset) cout << ' ' << v;\n        cout << '\\n';\n        cout.flush();\n        vector<pair<int,int>> ret;\n        ret.reserve((int)subset.size() - 1);\n        for (int i = 0; i < (int)subset.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    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n    sort(gids.begin(), gids.end(), [&](int a, int b) {\n        if (groups[a].size() != groups[b].size()) return groups[a].size() > groups[b].size();\n        return a < b;\n    });\n\n    for (int gi : gids) {\n        if (used_queries >= Q) break;\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        if (sz <= 1) continue;\n\n        vector<vector<int>> local_orders;\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            });\n            local_orders.push_back(ord);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            });\n            local_orders.push_back(ord);\n        }\n\n        int block = min(L, sz);\n        int step = max(1, block / 2);\n\n        set<vector<int>> seen;\n        for (auto &ord : local_orders) {\n            for (int s = 0; s < sz && used_queries < Q; s += step) {\n                int e = min(sz, s + block);\n                if (e - s < 2) break;\n                vector<int> subset(ord.begin() + s, ord.begin() + e);\n                sort(subset.begin(), subset.end());\n                if (!seen.insert(subset).second) {\n                    if (e == sz) break;\n                    continue;\n                }\n                auto ret = do_query(subset);\n                for (auto &p : ret) queried_edges[gi].push_back(p);\n                used_queries++;\n                if (e == sz) break;\n            }\n        }\n    }\n\n    // Final safe tree construction: full Prim per group, with query-edge bonus.\n    vector<vector<pair<int,int>>> answer_edges(M);\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        answer_edges[gi].clear();\n        if (sz <= 1) continue;\n\n        unordered_set<long long> qset;\n        qset.reserve(queried_edges[gi].size() * 2 + 1);\n        auto enc = [&](int a, int b) -> long long {\n            if (a > b) swap(a, b);\n            return 1LL * a * N + b;\n        };\n        for (auto [a, b] : queried_edges[gi]) qset.insert(enc(a, b));\n\n        const int INF = 1e9;\n        vector<int> best(sz, INF), par(sz, -1);\n        vector<char> used(sz, 0);\n        best[0] = 0;\n\n        for (int it = 0; it < sz; it++) {\n            int v = -1;\n            for (int i = 0; i < sz; i++) {\n                if (!used[i] && (v == -1 || best[i] < best[v])) v = i;\n            }\n            used[v] = 1;\n            if (par[v] != -1) answer_edges[gi].push_back({g[v], g[par[v]]});\n\n            for (int to = 0; to < sz; to++) if (!used[to]) {\n                int w = est_dist(g[v], g[to]);\n                if (qset.count(enc(g[v], g[to]))) w = max(0, w - 5);\n                if (w < best[to]) {\n                    best[to] = w;\n                    par[to] = v;\n                }\n            }\n        }\n\n        if ((int)answer_edges[gi].size() != sz - 1) {\n            answer_edges[gi].clear();\n            for (int i = 1; i < sz; i++) answer_edges[gi].push_back({g[i - 1], g[i]});\n        }\n    }\n\n    // Final safety check for exact partition.\n    vector<int> freq(N, 0);\n    bool bad = false;\n    for (int gi = 0; gi < M; gi++) {\n        if ((int)groups[gi].size() != G[gi]) bad = true;\n        for (int v : groups[gi]) {\n            if (v < 0 || v >= N) bad = true;\n            else freq[v]++;\n        }\n        if ((int)answer_edges[gi].size() != max(0, G[gi] - 1)) bad = true;\n    }\n    for (int i = 0; i < N; i++) if (freq[i] != 1) bad = true;\n\n    if (bad) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        int ptr = 0;\n        for (int gi = 0; gi < M; gi++) {\n            groups[gi].assign(ord.begin() + ptr, ord.begin() + ptr + G[gi]);\n            ptr += G[gi];\n            answer_edges[gi].clear();\n            for (int i = 1; i < G[gi]; i++) answer_edges[gi].push_back({groups[gi][i - 1], groups[gi][i]});\n        }\n    }\n\n    cout << \"!\\n\";\n    for (int gi = 0; gi < M; gi++) {\n        for (int i = 0; i < (int)groups[gi].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gi][i];\n        }\n        cout << '\\n';\n        for (auto [a, b] : answer_edges[gi]) {\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\nstatic const int N = 20;\nstatic const int INF = 1e9;\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar DCH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n};\n\nbool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nstruct Solver {\n    int M;\n    vector<Pos> pts;\n    vector<vector<int>> block;\n    vector<Action> ans;\n    Pos cur;\n\n    Solver(int M_, vector<Pos> pts_) : M(M_), pts(move(pts_)) {\n        block.assign(N, vector<int>(N, 0));\n        cur = pts[0];\n    }\n\n    // BFS path using only moves avoiding blocks\n    vector<int> bfs_move_dirs(Pos s, Pos g, const vector<vector<int>>& blk) {\n        vector<vector<int>> dist(N, vector<int>(N, -1));\n        vector<vector<pair<Pos,int>>> par(N, vector<pair<Pos,int>>(N, {{-1,-1}, -1}));\n        queue<Pos> q;\n        dist[s.r][s.c] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            auto v = q.front(); q.pop();\n            if (v == g) break;\n            for (int d = 0; d < 4; d++) {\n                int nr = v.r + dr[d], nc = v.c + dc[d];\n                if (!inside(nr, nc) || blk[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[v.r][v.c] + 1;\n                par[nr][nc] = {v, d};\n                q.push({nr, nc});\n            }\n        }\n        if (dist[g.r][g.c] == -1) return {};\n        vector<int> dirs;\n        Pos x = g;\n        while (x != s) {\n            auto [p, d] = par[x.r][x.c];\n            dirs.push_back(d);\n            x = p;\n        }\n        reverse(dirs.begin(), dirs.end());\n        return dirs;\n    }\n\n    pair<Pos,int> slide_result(Pos s, int d, const vector<vector<int>>& blk) {\n        int r = s.r, c = s.c;\n        while (true) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc) || blk[nr][nc]) break;\n            r = nr; c = nc;\n        }\n        return {{r, c}, (r != s.r || c != s.c)};\n    }\n\n    bool can_stop_at(Pos s, Pos g, int &dir_out) {\n        if (s.r == g.r) {\n            if (s.c < g.c) {\n                int d = 3;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            } else if (s.c > g.c) {\n                int d = 2;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            }\n        }\n        if (s.c == g.c) {\n            if (s.r < g.r) {\n                int d = 1;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            } else if (s.r > g.r) {\n                int d = 0;\n                auto res = slide_result(s, d, block);\n                if (res.first == g) { dir_out = d; return true; }\n            }\n        }\n        return false;\n    }\n\n    void apply_move_dir(int d) {\n        int nr = cur.r + dr[d], nc = cur.c + dc[d];\n        if (!inside(nr, nc) || block[nr][nc]) return; // safety\n        ans.push_back({'M', DCH[d]});\n        cur = {nr, nc};\n    }\n\n    void apply_slide_dir(int d) {\n        ans.push_back({'S', DCH[d]});\n        cur = slide_result(cur, d, block).first;\n    }\n\n    void apply_alter_dir(int d) {\n        int nr = cur.r + dr[d], nc = cur.c + dc[d];\n        if (!inside(nr, nc)) return; // safety\n        ans.push_back({'A', DCH[d]});\n        block[nr][nc] ^= 1;\n    }\n\n    int dir_between_adj(Pos a, Pos b) {\n        for (int d = 0; d < 4; d++) {\n            if (a.r + dr[d] == b.r && a.c + dc[d] == b.c) return d;\n        }\n        return -1;\n    }\n\n    struct Plan {\n        int cost = INF;\n        vector<Action> acts;\n        vector<pair<Pos,int>> toggles; // (cell, final toggled once)\n    };\n\n    void relax(Plan &best, const Plan &cand) {\n        if (cand.cost < best.cost) best = cand;\n    }\n\n    Plan pure_move_plan(Pos s, Pos g) {\n        Plan p;\n        auto dirs = bfs_move_dirs(s, g, block);\n        if (dirs.empty() && s != g) return p;\n        p.cost = (int)dirs.size();\n        for (int d : dirs) p.acts.push_back({'M', DCH[d]});\n        return p;\n    }\n\n    Plan direct_slide_plan(Pos s, Pos g) {\n        Plan p;\n        int d;\n        if (can_stop_at(s, g, d)) {\n            p.cost = 1;\n            p.acts.push_back({'S', DCH[d]});\n        }\n        return p;\n    }\n\n    // Move to x then slide to g\n    Plan move_then_slide(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d;\n        if (!can_stop_at(x, g, d)) return p;\n        auto dirs = bfs_move_dirs(s, x, block);\n        if (dirs.empty() && s != x) return p;\n        p.cost = (int)dirs.size() + 1;\n        for (int dd : dirs) p.acts.push_back({'M', DCH[dd]});\n        p.acts.push_back({'S', DCH[d]});\n        return p;\n    }\n\n    // Slide to x then move to g\n    Plan slide_then_move(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d = -1;\n        if (s.r == x.r) {\n            if (s.c < x.c) d = 3;\n            else if (s.c > x.c) d = 2;\n        } else if (s.c == x.c) {\n            if (s.r < x.r) d = 1;\n            else if (s.r > x.r) d = 0;\n        }\n        if (d == -1) return p;\n        auto res = slide_result(s, d, block);\n        if (res.first != x) return p;\n        auto dirs = bfs_move_dirs(x, g, block);\n        if (dirs.empty() && x != g) return p;\n        p.cost = 1 + (int)dirs.size();\n        p.acts.push_back({'S', DCH[d]});\n        for (int dd : dirs) p.acts.push_back({'M', DCH[dd]});\n        return p;\n    }\n\n    Plan slide_then_slide(Pos s, Pos x, Pos g) {\n        Plan p;\n        int d1 = -1, d2 = -1;\n        if (s.r == x.r) {\n            if (s.c < x.c) d1 = 3;\n            else if (s.c > x.c) d1 = 2;\n        } else if (s.c == x.c) {\n            if (s.r < x.r) d1 = 1;\n            else if (s.r > x.r) d1 = 0;\n        }\n        if (d1 == -1) return p;\n        if (slide_result(s, d1, block).first != x) return p;\n        if (!can_stop_at(x, g, d2)) return p;\n        p.cost = 2;\n        p.acts.push_back({'S', DCH[d1]});\n        p.acts.push_back({'S', DCH[d2]});\n        return p;\n    }\n\n    // Create one stopper adjacent beyond g, then slide from aligned position x\n    Plan create_stopper_and_slide(Pos s, Pos g) {\n        Plan best;\n        for (int d = 0; d < 4; d++) {\n            int br = g.r + dr[d], bc = g.c + dc[d]; // blocker cell\n            if (!inside(br, bc)) continue;           // border already acts as stopper, no need here\n            if (block[br][bc]) continue;             // already blocked -> direct existing-block cases handled elsewhere\n\n            int sd = d ^ 1; // need to slide toward g from opposite side\n            // x must be on same line as g, and slide from x in sd must stop at g after placing block at (br,bc)\n            // Enumerate all possible x on that ray.\n            for (int k = 1; ; k++) {\n                int xr = g.r + dr[sd] * k;\n                int xc = g.c + dc[sd] * k;\n                if (!inside(xr, xc)) break;\n                if (block[xr][xc]) break; // can't stand there\n                Pos x{xr, xc};\n\n                // Need path s -> some y adjacent to blocker cell, place block, then path to x, then slide.\n                for (int ad = 0; ad < 4; ad++) {\n                    int yr = br - dr[ad], yc = bc - dc[ad];\n                    if (!inside(yr, yc) || block[yr][yc]) continue;\n                    Pos y{yr, yc};\n                    if (y.r == br && y.c == bc) continue;\n\n                    auto path1 = bfs_move_dirs(s, y, block);\n                    if (path1.empty() && s != y) continue;\n\n                    auto blk2 = block;\n                    blk2[br][bc] = 1;\n                    auto path2 = bfs_move_dirs(y, x, blk2);\n                    if (path2.empty() && y != x) continue;\n\n                    // verify slide with new block\n                    int dslide = -1;\n                    if (x.r == g.r) {\n                        if (x.c < g.c) dslide = 3;\n                        else if (x.c > g.c) dslide = 2;\n                    } else if (x.c == g.c) {\n                        if (x.r < g.r) dslide = 1;\n                        else if (x.r > g.r) dslide = 0;\n                    }\n                    if (dslide == -1) continue;\n\n                    // simulate on blk2\n                    int rr = x.r, cc = x.c;\n                    while (true) {\n                        int nr = rr + dr[dslide], nc = cc + dc[dslide];\n                        if (!inside(nr, nc) || blk2[nr][nc]) break;\n                        rr = nr; cc = nc;\n                    }\n                    if (rr != g.r || cc != g.c) continue;\n\n                    Plan p;\n                    p.cost = (int)path1.size() + 1 + (int)path2.size() + 1;\n                    for (int dd : path1) p.acts.push_back({'M', DCH[dd]});\n                    p.acts.push_back({'A', DCH[ad]});\n                    for (int dd : path2) p.acts.push_back({'M', DCH[dd]});\n                    p.acts.push_back({'S', DCH[dslide]});\n                    p.toggles.push_back({{br, bc}, 1});\n                    relax(best, p);\n                }\n            }\n        }\n        return best;\n    }\n\n    void execute_plan(const Plan &p) {\n        for (auto act : p.acts) {\n            if (act.a == 'M') {\n                int d = string(\"UDLR\").find(act.d);\n                apply_move_dir(d);\n            } else if (act.a == 'S') {\n                int d = string(\"UDLR\").find(act.d);\n                apply_slide_dir(d);\n            } else {\n                int d = string(\"UDLR\").find(act.d);\n                apply_alter_dir(d);\n            }\n        }\n    }\n\n    void solve() {\n        for (int idx = 1; idx < M; idx++) {\n            Pos g = pts[idx];\n            Plan best = pure_move_plan(cur, g);\n\n            relax(best, direct_slide_plan(cur, g));\n\n            for (int r = 0; r < N; r++) for (int c = 0; c < N; c++) {\n                if (block[r][c]) continue;\n                Pos x{r, c};\n                relax(best, move_then_slide(cur, x, g));\n                relax(best, slide_then_move(cur, x, g));\n                relax(best, slide_then_slide(cur, x, g));\n            }\n\n            relax(best, create_stopper_and_slide(cur, g));\n\n            if (best.cost >= INF) {\n                best = pure_move_plan(cur, g);\n            }\n\n            execute_plan(best);\n\n            // safety fallback if not reached due to any inconsistency\n            if (cur != g) {\n                auto dirs = bfs_move_dirs(cur, g, block);\n                for (int d : dirs) apply_move_dir(d);\n            }\n\n            // if target cell somehow blocked (shouldn't happen if reached), unblock from adjacent later if needed.\n            // We guarantee current cell is unblocked because moves/slides can't end on blocked cell.\n        }\n\n        // Hard safety: ensure action count not excessive; if somehow too large, truncate is invalid.\n        // But this heuristic should stay comfortably below 1600.\n        for (auto &x : ans) {\n            cout << x.a << ' ' << x.d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N_in, M;\n    cin >> N_in >> M;\n    vector<Pos> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].r >> pts[i].c;\n\n    Solver solver(M, pts);\n    solver.solve();\n    return 0;\n}"},"8":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int LIM = 10000;\n\nstruct Input {\n    int x, y, r;\n};\n\nstruct Rect {\n    int a, b, c, d; // [a,c) x [b,d)\n};\n\nstruct Move {\n    int idx = -1;\n    Rect nr{};\n    double gain = -1e100;\n    bool valid = false;\n};\n\nstatic inline bool overlap1D(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstatic inline bool overlap2D(const Rect& p, const Rect& q) {\n    return overlap1D(p.a, p.c, q.a, q.c) && overlap1D(p.b, p.d, q.b, q.d);\n}\n\nstatic inline long long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\nstatic inline double sat(long long s, long long r) {\n    double t = (double)min(s, r) / (double)max(s, r);\n    double u = 1.0 - t;\n    return 1.0 - u * u;\n}\n\nstruct Solver {\n    int n;\n    vector<Input> in;\n    mt19937 rng;\n\n    vector<double> density_priority;\n    vector<int> seedL0, seedR0, seedD0, seedU0;\n    vector<int> seedL1, seedR1, seedD1, seedU1;\n    vector<Rect> best_rects;\n\n    Solver(int n_, vector<Input> in_) : n(n_), in(std::move(in_)) {\n        rng.seed((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n        build_density_priority();\n        build_seed_boxes();\n    }\n\n    void build_density_priority() {\n        density_priority.assign(n, 0.0);\n        for (int i = 0; i < n; i++) {\n            int lx = in[i].x + 1;\n            int rx = LIM - in[i].x;\n            int dy = in[i].y + 1;\n            int uy = LIM - in[i].y;\n            for (int j = 0; j < n; j++) if (i != j) {\n                if (in[j].x < in[i].x) lx = min(lx, in[i].x - in[j].x);\n                if (in[j].x > in[i].x) rx = min(rx, in[j].x - in[i].x);\n                if (in[j].y < in[i].y) dy = min(dy, in[i].y - in[j].y);\n                if (in[j].y > in[i].y) uy = min(uy, in[j].y - in[i].y);\n            }\n            double free_est = 1.0 * (lx + rx) * (dy + uy);\n            density_priority[i] = (double)in[i].r / max(1.0, free_est);\n        }\n    }\n\n    void build_seed_boxes() {\n        seedL0.assign(n, 0); seedR0.assign(n, LIM); seedD0.assign(n, 0); seedU0.assign(n, LIM);\n        seedL1.assign(n, 0); seedR1.assign(n, LIM); seedD1.assign(n, 0); seedU1.assign(n, LIM);\n\n        for (int i = 0; i < n; i++) {\n            int x = in[i].x, y = in[i].y;\n            int bestXL = -1, bestXR = LIM, bestYD = -1, bestYU = LIM;\n\n            for (int j = 0; j < n; j++) if (i != j) {\n                if (in[j].x < x) bestXL = max(bestXL, in[j].x);\n                if (in[j].x > x) bestXR = min(bestXR, in[j].x);\n                if (in[j].y < y) bestYD = max(bestYD, in[j].y);\n                if (in[j].y > y) bestYU = min(bestYU, in[j].y);\n            }\n\n            int L0 = (bestXL >= 0 ? max(0, (bestXL + x + 1) / 2) : 0);\n            int R0 = (bestXR < LIM ? min(LIM, (x + bestXR + 2) / 2) : LIM);\n            int D0 = (bestYD >= 0 ? max(0, (bestYD + y + 1) / 2) : 0);\n            int U0 = (bestYU < LIM ? min(LIM, (y + bestYU + 2) / 2) : LIM);\n\n            L0 = min(L0, x); R0 = max(R0, x + 1);\n            D0 = min(D0, y); U0 = max(U0, y + 1);\n\n            seedL0[i] = L0; seedR0[i] = R0; seedD0[i] = D0; seedU0[i] = U0;\n\n            int L1 = min(x, L0 + max(0, (x - L0) / 4));\n            int R1 = max(x + 1, R0 - max(0, (R0 - (x + 1)) / 4));\n            int D1 = min(y, D0 + max(0, (y - D0) / 4));\n            int U1 = max(y + 1, U0 - max(0, (U0 - (y + 1)) / 4));\n\n            seedL1[i] = L1; seedR1[i] = R1; seedD1[i] = D1; seedU1[i] = U1;\n        }\n    }\n\n    double score_one(int i, const Rect& r) const {\n        return sat(area(r), in[i].r);\n    }\n\n    double total_score(const vector<Rect>& rects) const {\n        double s = 0.0;\n        for (int i = 0; i < n; i++) s += score_one(i, rects[i]);\n        return s;\n    }\n\n    bool contains_point(int i, const Rect& r) const {\n        return r.a <= in[i].x && in[i].x < r.c && r.b <= in[i].y && in[i].y < r.d;\n    }\n\n    bool legal_shape(const Rect& r) const {\n        return 0 <= r.a && r.a < r.c && r.c <= LIM && 0 <= r.b && r.b < r.d && r.d <= LIM;\n    }\n\n    bool can_place(const vector<Rect>& rects, int i, const Rect& nr) const {\n        if (!legal_shape(nr)) return false;\n        if (!contains_point(i, nr)) return false;\n        for (int j = 0; j < n; j++) {\n            if (j == i) continue;\n            if (overlap2D(nr, rects[j])) return false;\n        }\n        return true;\n    }\n\n    int max_left(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && q.c <= r.a) bound = max(bound, q.c);\n        }\n        return r.a - bound;\n    }\n\n    int max_right(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && r.c <= q.a) bound = min(bound, q.a);\n        }\n        return bound - r.c;\n    }\n\n    int max_down(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && q.d <= r.b) bound = max(bound, q.d);\n        }\n        return r.b - bound;\n    }\n\n    int max_up(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && r.d <= q.b) bound = min(bound, q.b);\n        }\n        return bound - r.d;\n    }\n\n    vector<int> collect_1d_candidates(long long curA, long long target, int lim, int unit) const {\n        vector<int> cand;\n        if (lim <= 0) return cand;\n\n        auto add = [&](int x) {\n            if (1 <= x && x <= lim) cand.push_back(x);\n        };\n\n        add(1); add(2); add(4); add(8);\n        add(lim / 2); add(lim);\n\n        if (curA < target) {\n            int need = (int)((target - curA + unit - 1) / unit);\n            for (int d = -3; d <= 3; d++) add(need + d);\n            add(max(1, need / 2));\n            add(min(lim, need * 2));\n        }\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    }\n\n    Move best_move_for(const vector<Rect>& rects, int i) const {\n        const Rect& cur = rects[i];\n        long long curA = area(cur);\n        long long target = in[i].r;\n        double curScore = score_one(i, cur);\n\n        int L = max_left(rects, i);\n        int R = max_right(rects, i);\n        int D = max_down(rects, i);\n        int U = max_up(rects, i);\n\n        Move best;\n        int w = cur.c - cur.a;\n        int h = cur.d - cur.b;\n\n        auto upd = [&](const Rect& nr) {\n            if (!can_place(rects, i, nr)) return;\n            double g = score_one(i, nr) - curScore;\n            if (g > best.gain) best = {i, nr, g, true};\n        };\n\n        vector<int> candH = collect_1d_candidates(curA, target, max(L, R), h);\n        vector<int> candV = collect_1d_candidates(curA, target, max(D, U), w);\n\n        for (int t : candH) {\n            if (t <= L) { Rect nr = cur; nr.a -= t; upd(nr); }\n            if (t <= R) { Rect nr = cur; nr.c += t; upd(nr); }\n        }\n        for (int t : candV) {\n            if (t <= D) { Rect nr = cur; nr.b -= t; upd(nr); }\n            if (t <= U) { Rect nr = cur; nr.d += t; upd(nr); }\n        }\n\n        if (L + R > 0) {\n            vector<int> cand = collect_1d_candidates(curA, target, L + R, h);\n            for (int tot : cand) {\n                int l = min(L, tot / 2);\n                int r = min(R, tot - l);\n                if (l + r < tot) {\n                    int rem = tot - l - r;\n                    int addL = min(L - l, rem);\n                    l += addL;\n                    r += min(R - r, rem - addL);\n                }\n                if (l + r == tot && tot > 0) {\n                    Rect nr = cur; nr.a -= l; nr.c += r; upd(nr);\n                }\n            }\n        }\n\n        if (D + U > 0) {\n            vector<int> cand = collect_1d_candidates(curA, target, D + U, w);\n            for (int tot : cand) {\n                int d = min(D, tot / 2);\n                int u = min(U, tot - d);\n                if (d + u < tot) {\n                    int rem = tot - d - u;\n                    int addD = min(D - d, rem);\n                    d += addD;\n                    u += min(U - u, rem - addD);\n                }\n                if (d + u == tot && tot > 0) {\n                    Rect nr = cur; nr.b -= d; nr.d += u; upd(nr);\n                }\n            }\n        }\n\n        auto smalls = [&](int lim) {\n            vector<int> v;\n            if (lim <= 0) return v;\n            auto add = [&](int x) { if (1 <= x && x <= lim) v.push_back(x); };\n            add(1); add(2); add(4); add(lim / 2);\n            sort(v.begin(), v.end());\n            v.erase(unique(v.begin(), v.end()), v.end());\n            return v;\n        };\n\n        vector<int> cL = smalls(L), cR = smalls(R), cD = smalls(D), cU = smalls(U);\n        for (int x : cL) for (int y : cD) { Rect nr = cur; nr.a -= x; nr.b -= y; upd(nr); }\n        for (int x : cL) for (int y : cU) { Rect nr = cur; nr.a -= x; nr.d += y; upd(nr); }\n        for (int x : cR) for (int y : cD) { Rect nr = cur; nr.c += x; nr.b -= y; upd(nr); }\n        for (int x : cR) for (int y : cU) { Rect nr = cur; nr.c += x; nr.d += y; upd(nr); }\n\n        return best;\n    }\n\n    bool apply_best_for(vector<Rect>& rects, int i) const {\n        Move mv = best_move_for(rects, i);\n        if (mv.valid && mv.gain > 1e-15) {\n            rects[i] = mv.nr;\n            return true;\n        }\n        return false;\n    }\n\n    bool best_improvement_step(vector<Rect>& rects) const {\n        Move best;\n        for (int i = 0; i < n; i++) {\n            Move mv = best_move_for(rects, i);\n            if (mv.valid && mv.gain > best.gain) best = mv;\n        }\n        if (best.valid && best.gain > 1e-15) {\n            rects[best.idx] = best.nr;\n            return true;\n        }\n        return false;\n    }\n\n    bool tiny_trim_one(vector<Rect>& rects, int i) const {\n        const Rect cur = rects[i];\n        long long curA = area(cur);\n        if (curA <= in[i].r) return false;\n\n        double curScore = score_one(i, cur);\n        double bestGain = 1e-18;\n        Rect bestRect = cur;\n\n        auto try_trim = [&](const Rect& nr) {\n            if (!legal_shape(nr)) return;\n            if (!contains_point(i, nr)) return;\n            double g = score_one(i, nr) - curScore;\n            if (g > bestGain) {\n                bestGain = g;\n                bestRect = nr;\n            }\n        };\n\n        if (cur.a < in[i].x) { Rect nr = cur; nr.a++; try_trim(nr); }\n        if (in[i].x + 1 < cur.c) { Rect nr = cur; nr.c--; try_trim(nr); }\n        if (cur.b < in[i].y) { Rect nr = cur; nr.b++; try_trim(nr); }\n        if (in[i].y + 1 < cur.d) { Rect nr = cur; nr.d--; try_trim(nr); }\n\n        if (bestGain > 1e-15) {\n            rects[i] = bestRect;\n            return true;\n        }\n        return false;\n    }\n\n    bool tiny_reshape_one(vector<Rect>& rects, int i) const {\n        const Rect cur = rects[i];\n        double curScore = score_one(i, cur);\n        double bestGain = 1e-18;\n        Rect bestRect = cur;\n\n        auto try_rs = [&](const Rect& nr) {\n            if (!can_place(rects, i, nr)) return;\n            double g = score_one(i, nr) - curScore;\n            if (g > bestGain) {\n                bestGain = g;\n                bestRect = nr;\n            }\n        };\n\n        bool canShrinkL = cur.a < in[i].x;\n        bool canShrinkR = in[i].x + 1 < cur.c;\n        bool canShrinkD = cur.b < in[i].y;\n        bool canShrinkU = in[i].y + 1 < cur.d;\n\n        int L = max_left(rects, i), R = max_right(rects, i), D = max_down(rects, i), U = max_up(rects, i);\n\n        // area-preserving-ish 1:1 reshapes\n        if (canShrinkL && U >= 1) { Rect nr = cur; nr.a++; nr.d++; try_rs(nr); }\n        if (canShrinkL && D >= 1) { Rect nr = cur; nr.a++; nr.b--; try_rs(nr); }\n        if (canShrinkR && U >= 1) { Rect nr = cur; nr.c--; nr.d++; try_rs(nr); }\n        if (canShrinkR && D >= 1) { Rect nr = cur; nr.c--; nr.b--; try_rs(nr); }\n\n        if (canShrinkD && L >= 1) { Rect nr = cur; nr.b++; nr.a--; try_rs(nr); }\n        if (canShrinkD && R >= 1) { Rect nr = cur; nr.b++; nr.c++; try_rs(nr); }\n        if (canShrinkU && L >= 1) { Rect nr = cur; nr.d--; nr.a--; try_rs(nr); }\n        if (canShrinkU && R >= 1) { Rect nr = cur; nr.d--; nr.c++; try_rs(nr); }\n\n        // small 1:2 / 2:1 reshapes\n        if (canShrinkL && U >= 2) { Rect nr = cur; nr.a++; nr.d += 2; try_rs(nr); }\n        if (canShrinkR && U >= 2) { Rect nr = cur; nr.c--; nr.d += 2; try_rs(nr); }\n        if (canShrinkL && D >= 2) { Rect nr = cur; nr.a++; nr.b -= 2; try_rs(nr); }\n        if (canShrinkR && D >= 2) { Rect nr = cur; nr.c--; nr.b -= 2; try_rs(nr); }\n\n        if (canShrinkD && L >= 2) { Rect nr = cur; nr.b++; nr.a -= 2; try_rs(nr); }\n        if (canShrinkD && R >= 2) { Rect nr = cur; nr.b++; nr.c += 2; try_rs(nr); }\n        if (canShrinkU && L >= 2) { Rect nr = cur; nr.d--; nr.a -= 2; try_rs(nr); }\n        if (canShrinkU && R >= 2) { Rect nr = cur; nr.d--; nr.c += 2; try_rs(nr); }\n\n        if (bestGain > 1e-15) {\n            rects[i] = bestRect;\n            return true;\n        }\n        return false;\n    }\n\n    void micro_adjust(vector<Rect>& rects, const vector<int>& ord) const {\n        for (int i : ord) {\n            Rect cur = rects[i];\n            double curScore = score_one(i, cur);\n            Rect bestRect = cur;\n            double bestGain = 1e-18;\n\n            auto upd = [&](const Rect& nr) {\n                if (!can_place(rects, i, nr)) return;\n                double g = score_one(i, nr) - curScore;\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestRect = nr;\n                }\n            };\n\n            int L = max_left(rects, i), R = max_right(rects, i), D = max_down(rects, i), U = max_up(rects, i);\n            if (L >= 1) { Rect nr = cur; nr.a--; upd(nr); }\n            if (R >= 1) { Rect nr = cur; nr.c++; upd(nr); }\n            if (D >= 1) { Rect nr = cur; nr.b--; upd(nr); }\n            if (U >= 1) { Rect nr = cur; nr.d++; upd(nr); }\n            if (L >= 1 && D >= 1) { Rect nr = cur; nr.a--; nr.b--; upd(nr); }\n            if (L >= 1 && U >= 1) { Rect nr = cur; nr.a--; nr.d++; upd(nr); }\n            if (R >= 1 && D >= 1) { Rect nr = cur; nr.c++; nr.b--; upd(nr); }\n            if (R >= 1 && U >= 1) { Rect nr = cur; nr.c++; nr.d++; upd(nr); }\n\n            if (bestGain > 1e-15) rects[i] = bestRect;\n        }\n    }\n\n    vector<int> make_order(int mode, const vector<Rect>* rects = nullptr) {\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n\n        if (mode == 0) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) { return in[i].r > in[j].r; });\n        } else if (mode == 1) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) { return in[i].r < in[j].r; });\n        } else if (mode == 2) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) { return density_priority[i] > density_priority[j]; });\n        } else if (mode == 3 && rects != nullptr) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) {\n                double ai = (double)in[i].r / area((*rects)[i]);\n                double aj = (double)in[j].r / area((*rects)[j]);\n                if (fabs(ai - aj) > 1e-12) return ai > aj;\n                return in[i].r > in[j].r;\n            });\n        } else {\n            shuffle(ord.begin(), ord.end(), rng);\n        }\n        return ord;\n    }\n\n    void seed_initialize(vector<Rect>& rects, const vector<int>& ord, int seed_mode) {\n        for (int i = 0; i < n; i++) rects[i] = {in[i].x, in[i].y, in[i].x + 1, in[i].y + 1};\n\n        const vector<int> *L, *R, *D, *U;\n        if (seed_mode == 0) {\n            L = &seedL0; R = &seedR0; D = &seedD0; U = &seedU0;\n        } else {\n            L = &seedL1; R = &seedR1; D = &seedD1; U = &seedU1;\n        }\n\n        for (int idx : ord) {\n            Rect cur = rects[idx];\n            double bestScore = score_one(idx, cur);\n            Rect bestRect = cur;\n\n            int boxL = (*L)[idx], boxR = (*R)[idx], boxD = (*D)[idx], boxU = (*U)[idx];\n            int maxW = boxR - boxL;\n            int maxH = boxU - boxD;\n            long long target = in[idx].r;\n            int sq = max(1, (int)sqrt((double)target));\n\n            vector<int> widths, heights;\n            auto addv = [](vector<int>& v, int x) { if (x > 0) v.push_back(x); };\n\n            addv(widths, 1);\n            addv(widths, maxW);\n            addv(widths, min(maxW, sq / 2));\n            addv(widths, min(maxW, sq));\n            addv(widths, min(maxW, sq * 2));\n            addv(widths, min(maxW, max(1, (int)(target / max(1, maxH)))));\n            addv(widths, min(maxW, max(1, (int)sqrt((double)target * max(1, maxW) / max(1, maxH)))));\n            addv(widths, min(maxW, max(1, (int)round(sqrt((double)target)))));\n\n            addv(heights, 1);\n            addv(heights, maxH);\n            addv(heights, min(maxH, sq / 2));\n            addv(heights, min(maxH, sq));\n            addv(heights, min(maxH, sq * 2));\n            addv(heights, min(maxH, max(1, (int)(target / max(1, maxW)))));\n            addv(heights, min(maxH, max(1, (int)sqrt((double)target * max(1, maxH) / max(1, maxW)))));\n            addv(heights, min(maxH, max(1, (int)round(sqrt((double)target)))));\n\n            sort(widths.begin(), widths.end());\n            widths.erase(unique(widths.begin(), widths.end()), widths.end());\n            sort(heights.begin(), heights.end());\n            heights.erase(unique(heights.begin(), heights.end()), heights.end());\n\n            for (int w : widths) for (int h : heights) {\n                int a_min = max(boxL, in[idx].x - w + 1);\n                int a_max = min(in[idx].x, boxR - w);\n                int b_min = max(boxD, in[idx].y - h + 1);\n                int b_max = min(in[idx].y, boxU - h);\n                if (a_min > a_max || b_min > b_max) continue;\n\n                vector<int> acand = {\n                    a_min, a_max, (a_min + a_max) / 2,\n                    max(a_min, min(a_max, in[idx].x - w + 1)),\n                    max(a_min, min(a_max, in[idx].x))\n                };\n                vector<int> bcand = {\n                    b_min, b_max, (b_min + b_max) / 2,\n                    max(b_min, min(b_max, in[idx].y - h + 1)),\n                    max(b_min, min(b_max, in[idx].y))\n                };\n\n                sort(acand.begin(), acand.end());\n                acand.erase(unique(acand.begin(), acand.end()), acand.end());\n                sort(bcand.begin(), bcand.end());\n                bcand.erase(unique(bcand.begin(), bcand.end()), bcand.end());\n\n                for (int a : acand) for (int b : bcand) {\n                    Rect nr{a, b, a + w, b + h};\n                    if (!can_place(rects, idx, nr)) continue;\n                    double sc = score_one(idx, nr);\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestRect = nr;\n                    }\n                }\n            }\n\n            rects[idx] = bestRect;\n        }\n    }\n\n    void mini_polish_after_seed(vector<Rect>& rects, const vector<int>& ord) const {\n        for (int rep = 0; rep < 2; rep++) {\n            for (int i : ord) tiny_trim_one(rects, i);\n            for (int i : ord) tiny_reshape_one(rects, i);\n            for (int i : ord) {\n                Rect cur = rects[i];\n                double curScore = score_one(i, cur);\n                Rect bestRect = cur;\n                double bestGain = 1e-18;\n\n                auto upd = [&](const Rect& nr) {\n                    if (!can_place(rects, i, nr)) return;\n                    double g = score_one(i, nr) - curScore;\n                    if (g > bestGain) {\n                        bestGain = g;\n                        bestRect = nr;\n                    }\n                };\n\n                int L = max_left(rects, i), R = max_right(rects, i), D = max_down(rects, i), U = max_up(rects, i);\n                if (L >= 1) { Rect nr = cur; nr.a--; upd(nr); }\n                if (R >= 1) { Rect nr = cur; nr.c++; upd(nr); }\n                if (D >= 1) { Rect nr = cur; nr.b--; upd(nr); }\n                if (U >= 1) { Rect nr = cur; nr.d++; upd(nr); }\n                if (bestGain > 1e-15) rects[i] = bestRect;\n            }\n        }\n    }\n\n    vector<Rect> run_one_strategy(int mode, int seed_mode, bool use_seed, double end_time, chrono::steady_clock::time_point global_start) {\n        vector<Rect> rects(n);\n        vector<int> ord = make_order(mode);\n\n        if (use_seed) {\n            seed_initialize(rects, ord, seed_mode);\n            mini_polish_after_seed(rects, ord);\n        } else {\n            for (int i = 0; i < n; i++) rects[i] = {in[i].x, in[i].y, in[i].x + 1, in[i].y + 1};\n        }\n\n        for (int pass = 0; pass < 4; pass++) {\n            vector<int> use_ord = (pass % 2 == 0 ? ord : make_order(3, &rects));\n            for (int i : use_ord) apply_best_for(rects, i);\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) return rects;\n        }\n\n        for (int rep = 0; rep < 16; rep++) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) return rects;\n            if (!best_improvement_step(rects)) break;\n        }\n\n        vector<int> rnd(n);\n        iota(rnd.begin(), rnd.end(), 0);\n        int idle = 0;\n\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time * 0.90) break;\n\n            vector<int> use_ord = make_order((uniform_int_distribution<int>(0, 2)(rng) == 0 ? 3 : 4), &rects);\n            if ((int)use_ord.size() != n) {\n                use_ord.resize(n);\n                iota(use_ord.begin(), use_ord.end(), 0);\n                shuffle(use_ord.begin(), use_ord.end(), rng);\n            }\n\n            bool updated = false;\n            for (int i : use_ord) {\n                if (apply_best_for(rects, i)) updated = true;\n            }\n            if (!updated) {\n                idle++;\n                if (idle >= 4) break;\n            } else {\n                idle = 0;\n            }\n        }\n\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time * 0.985) break;\n\n            shuffle(rnd.begin(), rnd.end(), rng);\n            bool changed = false;\n            for (int i : rnd) if (tiny_trim_one(rects, i)) changed = true;\n            for (int i : rnd) if (tiny_reshape_one(rects, i)) changed = true;\n            for (int i : make_order(3, &rects)) if (apply_best_for(rects, i)) changed = true;\n            if (!changed) break;\n        }\n\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) break;\n            shuffle(rnd.begin(), rnd.end(), rng);\n            for (int i : rnd) tiny_trim_one(rects, i);\n            for (int i : rnd) tiny_reshape_one(rects, i);\n            micro_adjust(rects, rnd);\n        }\n\n        return rects;\n    }\n\n    void solve() {\n        auto start = chrono::steady_clock::now();\n        best_rects.assign(n, {0, 0, 1, 1});\n        double best_score = -1e100;\n\n        vector<tuple<int,int,bool>> configs = {\n            {0,0,true}, {2,0,true}, {3,0,true},\n            {0,1,true}, {2,1,true}, {3,1,true},\n            {0,0,false}, {2,0,false}, {1,0,true}, {4,0,true}\n        };\n\n        for (int t = 0; t < (int)configs.size(); t++) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > 4.93) break;\n\n            double remain = 4.97 - elapsed;\n            int left = (int)configs.size() - t;\n            double slice = max(0.14, remain / left);\n\n            auto [mode, seed_mode, use_seed] = configs[t];\n            auto rects = run_one_strategy(mode, seed_mode, use_seed, elapsed + slice, start);\n            double sc = total_score(rects);\n            if (sc > best_score) {\n                best_score = sc;\n                best_rects = rects;\n            }\n        }\n    }\n\n    void output() const {\n        for (int i = 0; i < n; i++) {\n            cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n                 << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Input> in(n);\n    for (int i = 0; i < n; i++) cin >> in[i].x >> in[i].y >> in[i].r;\n\n    Solver solver(n, in);\n    solver.solve();\n    solver.output();\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXC = 2500;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { return l + (int)(next_u32() % (uint32_t)(r - l)); }\n    double next_double() { return (double)next_u32() / (double)UINT32_MAX; }\n};\n\nstruct Param {\n    double w_gain;\n    double w_future;\n    double w_reach;\n    double w_mob;\n    double w_dead;\n    double w_small;\n    double look2;\n    double noise;\n    int bfs_depth;\n    int bfs_cap;\n};\n\nstruct EvalResult {\n    double future_score;\n    int reach_cnt;\n    int frontier_sum;\n};\n\nstruct Cand {\n    int dir;\n    int ni, nj;\n    double score;\n};\n\nint si, sj;\nint tid[N][N];\nint pval[N][N];\nint tile_cnt;\n\nvector<pair<int,int>> nbr[N][N];\n\nint vis_stamp[N][N];\nint dista[N][N];\nint cur_stamp = 1;\n\ninline double phase_mix(double a, double b, double c, int step) {\n    if (step < 300) {\n        double t = step / 300.0;\n        return a * (1.0 - t) + b * t;\n    } else if (step < 900) {\n        double t = (step - 300) / 600.0;\n        return b * (1.0 - t) + c * t;\n    } else {\n        return c;\n    }\n}\n\nEvalResult bfs_eval(int si0, int sj0, const vector<unsigned char>& usedTile, int depth_limit, int node_cap) {\n    ++cur_stamp;\n    if (cur_stamp == INT_MAX) {\n        memset(vis_stamp, 0, sizeof(vis_stamp));\n        cur_stamp = 1;\n    }\n\n    static const double decay[64] = {\n        1.0,\n        0.94, 0.88, 0.83, 0.78, 0.73, 0.69, 0.65,\n        0.61, 0.57, 0.54, 0.51, 0.48, 0.45, 0.42, 0.40,\n        0.38, 0.36, 0.34, 0.32, 0.30, 0.28, 0.27, 0.26,\n        0.25, 0.24, 0.23, 0.22, 0.21, 0.20, 0.19, 0.18,\n        0.17, 0.16, 0.15, 0.145, 0.14, 0.135, 0.13, 0.125,\n        0.12, 0.115, 0.11, 0.105, 0.10, 0.095, 0.09, 0.085,\n        0.08, 0.075, 0.07, 0.065, 0.06, 0.055, 0.05, 0.045,\n        0.04, 0.038, 0.036, 0.034, 0.032, 0.03, 0.028, 0.026\n    };\n\n    static pair<int,int> q[MAXC];\n    int qh = 0, qt = 0;\n    q[qt++] = {si0, sj0};\n    vis_stamp[si0][sj0] = cur_stamp;\n    dista[si0][sj0] = 0;\n\n    double future_score = 0.0;\n    int reach_cnt = 0;\n    int frontier_sum = 0;\n\n    while (qh < qt && reach_cnt < node_cap) {\n        auto [i, j] = q[qh++];\n        int d = dista[i][j];\n        ++reach_cnt;\n\n        if (d > 0) future_score += pval[i][j] * decay[min(d, 63)];\n\n        int local_frontier = 0;\n        if (d < depth_limit) {\n            for (auto [ni, nj] : nbr[i][j]) {\n                if (usedTile[tid[ni][nj]]) continue;\n                ++local_frontier;\n                if (vis_stamp[ni][nj] == cur_stamp) continue;\n                vis_stamp[ni][nj] = cur_stamp;\n                dista[ni][nj] = d + 1;\n                q[qt++] = {ni, nj};\n            }\n        }\n        frontier_sum += local_frontier;\n    }\n\n    return {future_score, reach_cnt, frontier_sum};\n}\n\ndouble eval_move(int ni, int nj, int step_id, const vector<unsigned char>& usedTile, const Param& base) {\n    int mob = 0;\n    int mask = 0;\n    for (int k = 0; k < (int)nbr[ni][nj].size(); ++k) {\n        auto [xi, xj] = nbr[ni][nj][k];\n        if (usedTile[tid[xi][xj]]) continue;\n        ++mob;\n        int dd = -1;\n        if (xi == ni - 1) dd = 0;\n        else if (xi == ni + 1) dd = 1;\n        else if (xj == nj - 1) dd = 2;\n        else dd = 3;\n        mask |= 1 << dd;\n    }\n\n    EvalResult e = bfs_eval(ni, nj, usedTile, base.bfs_depth, base.bfs_cap);\n\n    double wg = phase_mix(base.w_gain * 0.90, base.w_gain, base.w_gain * 1.20, step_id);\n    double wf = phase_mix(base.w_future * 1.20, base.w_future, base.w_future * 0.70, step_id);\n    double wr = phase_mix(base.w_reach * 1.25, base.w_reach, base.w_reach * 0.65, step_id);\n    double wm = phase_mix(base.w_mob * 1.15, base.w_mob, base.w_mob * 0.75, step_id);\n    double wd = phase_mix(base.w_dead * 1.20, base.w_dead, base.w_dead * 0.65, step_id);\n    double ws = phase_mix(base.w_small * 1.15, base.w_small, base.w_small * 0.55, step_id);\n\n    double dead_pen = 0.0;\n    if (mob == 0) dead_pen = 1.0;\n    else if (mob == 1 && step_id < 1100) dead_pen = 0.65;\n    else if (mob == 2 && step_id < 850) {\n        bool opposite =\n            (mask == ((1 << 0) | (1 << 1))) ||\n            (mask == ((1 << 2) | (1 << 3)));\n        if (opposite) dead_pen = 0.22;\n    }\n\n    double small_pen = 0.0;\n    if (e.reach_cnt <= 10 && step_id < 1200) small_pen += (11 - e.reach_cnt);\n    if (e.reach_cnt <= 4 && step_id < 1200) small_pen += 5.0;\n\n    double end_bonus = 0.0;\n    if (e.reach_cnt <= 20) end_bonus += 0.35 * pval[ni][nj];\n    if (e.reach_cnt <= 8)  end_bonus += 0.25 * mob;\n\n    double sc = 0.0;\n    sc += wg * pval[ni][nj];\n    sc += wf * e.future_score;\n    sc += wr * e.reach_cnt;\n    sc += wm * mob;\n    sc += 0.10 * e.frontier_sum;\n    sc -= wd * dead_pen;\n    sc -= ws * small_pen;\n    sc += end_bonus;\n    return sc;\n}\n\nstring regrow_suffix(\n    int ci, int cj, int start_step,\n    vector<unsigned char>& usedTile,\n    const Param& par,\n    XorShift& rng,\n    int& gained_score\n) {\n    string suffix;\n    gained_score = 0;\n\n    while (true) {\n        vector<Cand> cand;\n        int step_id = start_step + (int)suffix.size();\n\n        for (int d = 0; d < 4; ++d) {\n            int ni = ci + (d == 0 ? -1 : d == 1 ? 1 : 0);\n            int nj = cj + (d == 2 ? -1 : d == 3 ? 1 : 0);\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            int nt = tid[ni][nj];\n            if (usedTile[nt]) continue;\n\n            usedTile[nt] = 1;\n            double sc = eval_move(ni, nj, step_id, usedTile, par);\n            usedTile[nt] = 0;\n            sc += (rng.next_double() - 0.5) * par.noise;\n\n            cand.push_back({d, ni, nj, sc});\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            return a.score > b.score;\n        });\n\n        int K = min(3, (int)cand.size());\n        for (int idx = 0; idx < K; ++idx) {\n            int n1i = cand[idx].ni, n1j = cand[idx].nj;\n            int t1 = tid[n1i][n1j];\n            usedTile[t1] = 1;\n\n            double best2 = -1e100;\n            bool has2 = false;\n            for (auto [n2i, n2j] : nbr[n1i][n1j]) {\n                int t2 = tid[n2i][n2j];\n                if (usedTile[t2]) continue;\n\n                usedTile[t2] = 1;\n                double sc2 = eval_move(n2i, n2j, step_id + 1, usedTile, par);\n                usedTile[t2] = 0;\n\n                if (!has2 || sc2 > best2) best2 = sc2;\n                has2 = true;\n            }\n            if (has2) cand[idx].score += par.look2 * best2;\n            usedTile[t1] = 0;\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            return a.score > b.score;\n        });\n\n        int pick = 0;\n        double r = rng.next_double();\n        if ((int)cand.size() >= 2 && r < 0.10) pick = 1;\n        if ((int)cand.size() >= 3 && r < 0.02) pick = 2;\n\n        int d = cand[pick].dir;\n        ci += (d == 0 ? -1 : d == 1 ? 1 : 0);\n        cj += (d == 2 ? -1 : d == 3 ? 1 : 0);\n        usedTile[tid[ci][cj]] = 1;\n        suffix.push_back(\"UDLR\"[d]);\n        gained_score += pval[ci][cj];\n    }\n\n    return suffix;\n}\n\nvoid build_prefix_info(\n    const string& path,\n    vector<pair<int,int>>& pos,\n    vector<int>& pref_score,\n    vector<int>& step_value\n) {\n    int L = (int)path.size();\n    pos.assign(L + 1, {0, 0});\n    pref_score.assign(L + 1, 0);\n    step_value.assign(L + 1, 0);\n\n    int ci = si, cj = sj;\n    pos[0] = {ci, cj};\n    pref_score[0] = pval[ci][cj];\n    step_value[0] = pval[ci][cj];\n\n    for (int i = 0; i < L; ++i) {\n        char c = path[i];\n        if (c == 'U') --ci;\n        else if (c == 'D') ++ci;\n        else if (c == 'L') --cj;\n        else ++cj;\n        pos[i + 1] = {ci, cj};\n        step_value[i + 1] = pval[ci][cj];\n        pref_score[i + 1] = pref_score[i] + pval[ci][cj];\n    }\n}\n\nint choose_cut(const string& best_path, const vector<int>& step_value, XorShift& rng) {\n    int L = (int)best_path.size();\n    if (L < 20) return max(0, L / 2);\n\n    int mode = rng.next_int(0, 5);\n\n    if (mode == 0) {\n        int lo = max(1, L * 70 / 100);\n        int hi = max(lo + 1, L * 95 / 100);\n        return rng.next_int(lo, hi);\n    } else if (mode == 1) {\n        int lo = max(1, L * 45 / 100);\n        int hi = max(lo + 1, L * 75 / 100);\n        return rng.next_int(lo, hi);\n    } else if (mode == 2) {\n        int lo = max(1, L * 25 / 100);\n        int hi = max(lo + 1, L * 90 / 100);\n        return rng.next_int(lo, hi);\n    } else if (mode == 3) {\n        // more aggressive earlier cut\n        int lo = max(1, L * 15 / 100);\n        int hi = max(lo + 1, L * 50 / 100);\n        return rng.next_int(lo, hi);\n    } else {\n        int lo = max(1, L * 30 / 100);\n        int hi = max(lo + 1, L * 90 / 100);\n        int win = min(40, max(10, L / 20));\n        vector<pair<double,int>> bads;\n        for (int c = lo; c < hi; c += max(3, win / 3)) {\n            int r = min(L, c + win);\n            double avg = 0.0;\n            for (int i = c + 1; i <= r; ++i) avg += step_value[i];\n            avg /= max(1, r - c);\n            bads.push_back({avg, c});\n        }\n        sort(bads.begin(), bads.end(), [](auto& a, auto& b) { return a.first < b.first; });\n        int take = min((int)bads.size(), 5);\n        if (take == 0) return rng.next_int(lo, hi);\n        return bads[rng.next_int(0, take)].second;\n    }\n}\n\nParam perturbed_param(const Param& src, XorShift& rng) {\n    Param par = src;\n    par.w_gain += (rng.next_double() - 0.5) * 0.08;\n    par.w_future += (rng.next_double() - 0.5) * 0.015;\n    par.w_reach += (rng.next_double() - 0.5) * 0.16;\n    par.w_mob += (rng.next_double() - 0.5) * 1.6;\n    par.w_dead += (rng.next_double() - 0.5) * 4.0;\n    par.w_small += (rng.next_double() - 0.5) * 0.5;\n    par.look2 += (rng.next_double() - 0.5) * 0.06;\n    return par;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    int mx = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tid[i][j];\n            mx = max(mx, tid[i][j]);\n        }\n    }\n    tile_cnt = mx + 1;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> pval[i][j];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i > 0) nbr[i][j].push_back({i - 1, j});\n            if (i + 1 < N) nbr[i][j].push_back({i + 1, j});\n            if (j > 0) nbr[i][j].push_back({i, j - 1});\n            if (j + 1 < N) nbr[i][j].push_back({i, j + 1});\n        }\n    }\n\n    vector<Param> params = {\n        {1.00, 0.090, 1.20, 10.0, 26.0, 2.8, 0.34, 1.2, 11, 130},\n        {0.92, 0.105, 1.35, 12.5, 30.0, 3.1, 0.38, 1.0, 12, 145},\n        {1.16, 0.072, 0.92,  7.2, 21.0, 2.2, 0.28, 1.5, 10, 110},\n        {0.97, 0.098, 1.28, 11.2, 29.0, 3.0, 0.36, 1.1, 12, 140},\n        {1.05, 0.082, 1.08,  8.8, 24.0, 2.6, 0.33, 1.3, 11, 125},\n        {1.12, 0.078, 1.00,  8.0, 22.0, 2.4, 0.31, 1.4, 10, 120},\n        {0.95, 0.102, 1.30, 11.8, 28.5, 3.0, 0.37, 1.0, 12, 150},\n        {1.18, 0.068, 0.88,  6.8, 20.5, 2.1, 0.27, 1.6, 10, 105}\n    };\n\n    Timer timer;\n    XorShift rng;\n\n    string best_path;\n    int best_score = pval[si][sj];\n    vector<unsigned char> usedTile(tile_cnt, 0);\n\n    // Construction phase\n    while (timer.elapsed() < 1.00) {\n        Param par = perturbed_param(params[rng.next_int(0, 6)], rng);\n        fill(usedTile.begin(), usedTile.end(), 0);\n        int ci = si, cj = sj;\n        usedTile[tid[ci][cj]] = 1;\n        int gained = 0;\n        string path = regrow_suffix(ci, cj, 0, usedTile, par, rng, gained);\n        int score = pval[si][sj] + gained;\n\n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n        }\n    }\n\n    vector<pair<int,int>> best_pos;\n    vector<int> best_pref_score;\n    vector<int> best_step_value;\n    build_prefix_info(best_path, best_pos, best_pref_score, best_step_value);\n\n    // Improvement phase\n    while (timer.elapsed() < 1.90) {\n        int L = (int)best_path.size();\n        if (L < 20) break;\n\n        int cut = choose_cut(best_path, best_step_value, rng);\n\n        vector<unsigned char> used(tile_cnt, 0);\n        for (int i = 0; i <= cut; ++i) {\n            auto [x, y] = best_pos[i];\n            used[tid[x][y]] = 1;\n        }\n\n        auto [ci, cj] = best_pos[cut];\n        int prefix_score = best_pref_score[cut];\n        string prefix = best_path.substr(0, cut);\n\n        int tries = 2 + (rng.next_double() < 0.40 ? 1 : 0); // mostly 2, sometimes 3\n        int local_best_score = best_score;\n        string local_best_path;\n\n        for (int t = 0; t < tries; ++t) {\n            vector<unsigned char> used2 = used;\n\n            // Bias repair params toward diversity\n            int pid;\n            if (t == 0) pid = rng.next_int(0, 8);\n            else if (t == 1) pid = 6 + rng.next_int(0, 2); // repair-specialized\n            else pid = rng.next_int(0, 8);\n\n            Param par = perturbed_param(params[pid], rng);\n\n            int gained = 0;\n            string suffix = regrow_suffix(ci, cj, cut, used2, par, rng, gained);\n            int score = prefix_score + gained;\n\n            if (score > local_best_score) {\n                local_best_score = score;\n                local_best_path = prefix + suffix;\n            }\n        }\n\n        if (!local_best_path.empty() && local_best_score > best_score) {\n            best_score = local_best_score;\n            best_path = local_best_path;\n            build_prefix_info(best_path, best_pos, best_pref_score, best_step_value);\n        }\n    }\n\n    cout << best_path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HN = 29;\nstatic constexpr int VN = 29;\nstatic constexpr int V = 900;\n\nstatic constexpr double INIT_COST = 5000.0;\nstatic constexpr double MIN_COST = 500.0;\nstatic constexpr double MAX_COST = 9500.0;\n\nstruct EdgeRef {\n    bool horiz; // true: h[i][j], false: v[i][j]\n    int i, j;\n};\n\nstruct Solver {\n    double h_est[N][HN], v_est[VN][N];\n    double h_prior[N][HN], v_prior[VN][N];\n    double h_sum[N][HN], v_sum[VN][N];\n    int h_cnt[N][HN], v_cnt[VN][N];\n\n    double row_base[N], col_base[N];\n    int row_cnt[N], col_cnt[N];\n\n    int turn = 0;\n\n    Solver() {\n        for (int i = 0; i < N; i++) {\n            row_base[i] = INIT_COST;\n            col_base[i] = INIT_COST;\n            row_cnt[i] = 0;\n            col_cnt[i] = 0;\n        }\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = INIT_COST;\n                h_prior[i][j] = INIT_COST;\n                h_sum[i][j] = 0.0;\n                h_cnt[i][j] = 0;\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = INIT_COST;\n                v_prior[i][j] = INIT_COST;\n                v_sum[i][j] = 0.0;\n                v_cnt[i][j] = 0;\n            }\n        }\n    }\n\n    static double clamp_cost(double x) {\n        return max(MIN_COST, min(MAX_COST, x));\n    }\n\n    void rebuild_bases() {\n        // horizontal row base\n        for (int i = 0; i < N; i++) {\n            double sw = 0.0, s = 0.0;\n            for (int j = 0; j < HN; j++) {\n                double w = 1.0 + 0.25 * h_cnt[i][j];\n                sw += w;\n                s += w * h_est[i][j];\n            }\n            row_base[i] = clamp_cost(s / sw);\n        }\n\n        // vertical column base\n        for (int j = 0; j < N; j++) {\n            double sw = 0.0, s = 0.0;\n            for (int i = 0; i < VN; i++) {\n                double w = 1.0 + 0.25 * v_cnt[i][j];\n                sw += w;\n                s += w * v_est[i][j];\n            }\n            col_base[j] = clamp_cost(s / sw);\n        }\n    }\n\n    // weighted 1-or-2 segment fitting for rows/cols\n    void rebuild_priors() {\n        // horizontal rows\n        for (int i = 0; i < N; i++) {\n            double a[HN], w[HN];\n            for (int j = 0; j < HN; j++) {\n                a[j] = h_est[i][j];\n                w[j] = 1.0 + 0.25 * h_cnt[i][j];\n            }\n\n            double sw[HN + 1] = {}, swa[HN + 1] = {}, swa2[HN + 1] = {};\n            for (int j = 0; j < HN; j++) {\n                sw[j + 1] = sw[j] + w[j];\n                swa[j + 1] = swa[j] + w[j] * a[j];\n                swa2[j + 1] = swa2[j] + w[j] * a[j] * a[j];\n            }\n\n            auto seg = [&](int l, int r) -> pair<double,double> {\n                double W = sw[r] - sw[l];\n                double S = swa[r] - swa[l];\n                double S2 = swa2[r] - swa2[l];\n                double mean = S / W;\n                double cost = S2 - 2.0 * mean * S + mean * mean * W;\n                return {cost, mean};\n            };\n\n            auto [bestCost, mean1] = seg(0, HN);\n            int bestSplit = -1;\n            double bestL = mean1, bestR = mean1;\n\n            for (int sp = 1; sp < HN; sp++) {\n                auto [c1, m1] = seg(0, sp);\n                auto [c2, m2] = seg(sp, HN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestL = m1;\n                    bestR = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int j = 0; j < HN; j++) h_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int j = 0; j < bestSplit; j++) h_prior[i][j] = clamp_cost(bestL);\n                for (int j = bestSplit; j < HN; j++) h_prior[i][j] = clamp_cost(bestR);\n            }\n        }\n\n        // vertical columns\n        for (int j = 0; j < N; j++) {\n            double a[VN], w[VN];\n            for (int i = 0; i < VN; i++) {\n                a[i] = v_est[i][j];\n                w[i] = 1.0 + 0.25 * v_cnt[i][j];\n            }\n\n            double sw[VN + 1] = {}, swa[VN + 1] = {}, swa2[VN + 1] = {};\n            for (int i = 0; i < VN; i++) {\n                sw[i + 1] = sw[i] + w[i];\n                swa[i + 1] = swa[i] + w[i] * a[i];\n                swa2[i + 1] = swa2[i] + w[i] * a[i] * a[i];\n            }\n\n            auto seg = [&](int l, int r) -> pair<double,double> {\n                double W = sw[r] - sw[l];\n                double S = swa[r] - swa[l];\n                double S2 = swa2[r] - swa2[l];\n                double mean = S / W;\n                double cost = S2 - 2.0 * mean * S + mean * mean * W;\n                return {cost, mean};\n            };\n\n            auto [bestCost, mean1] = seg(0, VN);\n            int bestSplit = -1;\n            double bestU = mean1, bestD = mean1;\n\n            for (int sp = 1; sp < VN; sp++) {\n                auto [c1, m1] = seg(0, sp);\n                auto [c2, m2] = seg(sp, VN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestU = m1;\n                    bestD = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int i = 0; i < VN; i++) v_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int i = 0; i < bestSplit; i++) v_prior[i][j] = clamp_cost(bestU);\n                for (int i = bestSplit; i < VN; i++) v_prior[i][j] = clamp_cost(bestD);\n            }\n        }\n    }\n\n    double local_weight(int cnt) const {\n        double w = 0.10 + 0.72 * (1.0 - exp(-cnt / 5.0));\n        if (turn < 50) w *= 0.75;\n        return min(0.85, max(0.07, w));\n    }\n\n    double base_weight(int cnt) const {\n        // more helpful when local count is still small\n        double w = 0.28 * exp(-cnt / 7.0);\n        return w;\n    }\n\n    double exploration_bonus(int cnt) const {\n        if (turn >= 120) return 0.0;\n        return 220.0 / sqrt(cnt + 1.0);\n    }\n\n    double blended_h(int i, int j) const {\n        double wl = local_weight(h_cnt[i][j]);\n        double wb = base_weight(h_cnt[i][j]);\n        double wp = 1.0 - wl - wb;\n        double val = wl * h_est[i][j] + wp * h_prior[i][j] + wb * row_base[i];\n        val -= exploration_bonus(h_cnt[i][j]);\n        return clamp_cost(val);\n    }\n\n    double blended_v(int i, int j) const {\n        double wl = local_weight(v_cnt[i][j]);\n        double wb = base_weight(v_cnt[i][j]);\n        double wp = 1.0 - wl - wb;\n        double val = wl * v_est[i][j] + wp * v_prior[i][j] + wb * col_base[j];\n        val -= exploration_bonus(v_cnt[i][j]);\n        return clamp_cost(val);\n    }\n\n    int vid(int i, int j) const { return i * N + j; }\n    pair<int,int> pos(int id) const { return {id / N, id % N}; }\n\n    pair<string, vector<EdgeRef>> shortest_path(int si, int sj, int ti, int tj) {\n        static double dist[V];\n        static int prev[V];\n        static char pm[V];\n\n        for (int i = 0; i < V; i++) {\n            dist[i] = 1e100;\n            prev[i] = -1;\n            pm[i] = '?';\n        }\n\n        using P = pair<double,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        int s = vid(si, sj), t = vid(ti, tj);\n        dist[s] = 0.0;\n        pq.push({0.0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == t) break;\n\n            auto [i, j] = pos(u);\n\n            if (i > 0) {\n                int v = vid(i - 1, j);\n                double w = blended_v(i - 1, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'U';\n                    pq.push({dist[v], v});\n                }\n            }\n            if (i + 1 < N) {\n                int v = vid(i + 1, j);\n                double w = blended_v(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'D';\n                    pq.push({dist[v], v});\n                }\n            }\n            if (j > 0) {\n                int v = vid(i, j - 1);\n                double w = blended_h(i, j - 1);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'L';\n                    pq.push({dist[v], v});\n                }\n            }\n            if (j + 1 < N) {\n                int v = vid(i, j + 1);\n                double w = blended_h(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'R';\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        string path;\n        vector<EdgeRef> edges_rev;\n        int cur = t;\n        while (cur != s) {\n            char mv = pm[cur];\n            path.push_back(mv);\n            auto [i, j] = pos(cur);\n            if (mv == 'U') edges_rev.push_back({false, i, j});\n            else if (mv == 'D') edges_rev.push_back({false, i - 1, j});\n            else if (mv == 'L') edges_rev.push_back({true, i, j});\n            else if (mv == 'R') edges_rev.push_back({true, i, j - 1});\n            else break;\n            cur = prev[cur];\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges_rev.begin(), edges_rev.end());\n        return {path, edges_rev};\n    }\n\n    double path_pred_cost(const vector<EdgeRef>& edges) const {\n        double s = 0.0;\n        for (const auto &e : edges) {\n            s += e.horiz ? blended_h(e.i, e.j) : blended_v(e.i, e.j);\n        }\n        return s;\n    }\n\n    void update_from_feedback(const vector<EdgeRef>& edges, int observed) {\n        if (edges.empty()) return;\n\n        int row_used[N] = {};\n        int col_used[N] = {};\n        int h_total = 0, v_total = 0;\n\n        for (const auto &e : edges) {\n            if (e.horiz) {\n                row_used[e.i]++;\n                h_total++;\n            } else {\n                col_used[e.j]++;\n                v_total++;\n            }\n        }\n\n        double pred = path_pred_cost(edges);\n        pred = max(pred, 1.0);\n        int L = (int)edges.size();\n\n        double ratio = observed / pred;\n        ratio = max(0.83, min(1.20, ratio));\n\n        double add = (observed - pred) / L;\n        add = max(-900.0, min(900.0, add));\n\n        double lr_mul = (turn < 100 ? 0.22 : turn < 300 ? 0.16 : 0.12);\n        double lr_add = (turn < 100 ? 0.05 : turn < 300 ? 0.035 : 0.025);\n        double lr_row = (turn < 120 ? 0.030 : 0.018);\n        double lr_col = (turn < 120 ? 0.030 : 0.018);\n\n        // Row / column aggregate update\n        if (h_total > 0) {\n            for (int i = 0; i < N; i++) if (row_used[i] > 0) {\n                double frac = row_used[i] / (double)h_total;\n                double target = row_base[i] + frac * (observed - pred) / max(1, row_used[i]);\n                row_base[i] = clamp_cost((1.0 - lr_row) * row_base[i] + lr_row * target);\n                row_cnt[i] += row_used[i];\n            }\n        }\n        if (v_total > 0) {\n            for (int j = 0; j < N; j++) if (col_used[j] > 0) {\n                double frac = col_used[j] / (double)v_total;\n                double target = col_base[j] + frac * (observed - pred) / max(1, col_used[j]);\n                col_base[j] = clamp_cost((1.0 - lr_col) * col_base[j] + lr_col * target);\n                col_cnt[j] += col_used[j];\n            }\n        }\n\n        // Local edge updates\n        for (const auto &e : edges) {\n            if (e.horiz) {\n                double cur = h_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = cur + add;\n                double target3 = row_base[e.i];\n                double nv = (1.0 - lr_mul) * cur + lr_mul * target1;\n                nv = (1.0 - lr_add) * nv + lr_add * target2;\n                nv = 0.97 * nv + 0.03 * target3;\n                h_est[e.i][e.j] = clamp_cost(nv);\n\n                h_sum[e.i][e.j] += observed / (double)L;\n                h_cnt[e.i][e.j]++;\n            } else {\n                double cur = v_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = cur + add;\n                double target3 = col_base[e.j];\n                double nv = (1.0 - lr_mul) * cur + lr_mul * target1;\n                nv = (1.0 - lr_add) * nv + lr_add * target2;\n                nv = 0.97 * nv + 0.03 * target3;\n                v_est[e.i][e.j] = clamp_cost(nv);\n\n                v_sum[e.i][e.j] += observed / (double)L;\n                v_cnt[e.i][e.j]++;\n            }\n        }\n\n        // Weak empirical averaging on enough-visited edges\n        for (const auto &e : edges) {\n            if (e.horiz) {\n                if (h_cnt[e.i][e.j] >= 6) {\n                    double mean = h_sum[e.i][e.j] / h_cnt[e.i][e.j];\n                    h_est[e.i][e.j] = clamp_cost(0.95 * h_est[e.i][e.j] + 0.05 * mean);\n                }\n            } else {\n                if (v_cnt[e.i][e.j] >= 6) {\n                    double mean = v_sum[e.i][e.j] / v_cnt[e.i][e.j];\n                    v_est[e.i][e.j] = clamp_cost(0.95 * v_est[e.i][e.j] + 0.05 * mean);\n                }\n            }\n        }\n\n        // rebuild structured models\n        if (turn < 150 || turn % 5 == 4) {\n            rebuild_bases();\n            rebuild_priors();\n        }\n\n        // gentle smoothing\n        double smooth = (turn < 150 ? 0.012 : 0.006);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = clamp_cost((1.0 - smooth) * h_est[i][j] + smooth * (0.7 * h_prior[i][j] + 0.3 * row_base[i]));\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = clamp_cost((1.0 - smooth) * v_est[i][j] + smooth * (0.7 * v_prior[i][j] + 0.3 * col_base[j]));\n            }\n        }\n    }\n\n    void solve() {\n        rebuild_bases();\n        rebuild_priors();\n\n        for (turn = 0; turn < 1000; turn++) {\n            int si, sj, ti, tj;\n            cin >> si >> sj >> ti >> tj;\n\n            auto [path, edges] = shortest_path(si, sj, ti, tj);\n\n            cout << path << '\\n';\n            cout.flush();\n\n            int observed;\n            cin >> observed;\n            update_from_feedback(edges, observed);\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}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\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 rand01() {\n        return (next() >> 11) * (1.0 / (1ull << 53));\n    }\n} rng;\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 Pattern {\n    string s;\n    int w;\n};\n\nstruct Candidate {\n    string line;               // length 20\n    vector<uint64_t> bits;     // covered unique patterns\n    int coverWeight = 0;       // sum of weights of covered unique patterns\n};\n\nint Nin, M;\nvector<Pattern> pats;\nint P;\n\ninline int cid(char c) { return c - 'A'; }\n\nbool contains_cyclic_line(const string& line, const string& s) {\n    int L = (int)s.size();\n    for (int st = 0; st < N; st++) {\n        bool ok = true;\n        for (int k = 0; k < L; k++) {\n            if (line[(st + k) % N] != s[k]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n    return false;\n}\n\nstring minimal_rotation(string s) {\n    // Booth O(n^2) is fine for n=20, but implement simple O(n^2)\n    string best = s;\n    for (int i = 1; i < (int)s.size(); i++) {\n        string t = s.substr(i) + s.substr(0, i);\n        if (t < best) best = t;\n    }\n    return best;\n}\n\nint overlap_suffix_prefix(const string& a, const string& b) {\n    int mx = min((int)a.size(), (int)b.size());\n    for (int k = mx; k >= 1; k--) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[(int)a.size() - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nbool is_substring_noncyclic(const string& a, const string& b) {\n    // is a substring of b\n    return b.find(a) != string::npos;\n}\n\nstring fill_to_20(const string& base, const vector<Pattern>& pats, bool randomize) {\n    if ((int)base.size() >= N) return base.substr(0, N);\n    string s = base;\n    while ((int)s.size() < N) {\n        array<long long, 8> score{};\n        score.fill(1);\n        int pos = (int)s.size();\n        for (auto &p : pats) {\n            const string& t = p.s;\n            for (int st = max(0, pos - (int)t.size() + 1); st <= pos; st++) {\n                int k = pos - st;\n                if (st < 0 || k < 0 || k >= (int)t.size()) continue;\n                bool ok = true;\n                for (int i = 0; i < pos - st; i++) {\n                    if (st + i < (int)s.size() && s[st + i] != t[i]) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) score[cid(t[k])] += p.w;\n            }\n        }\n        int bestc = 0;\n        if (randomize && rng.rand01() < 0.25) {\n            long long sum = 0;\n            for (int c = 0; c < 8; c++) sum += score[c];\n            long long r = rng.next() % sum;\n            long long acc = 0;\n            for (int c = 0; c < 8; c++) {\n                acc += score[c];\n                if (r < acc) { bestc = c; break; }\n            }\n        } else {\n            for (int c = 1; c < 8; c++) if (score[c] > score[bestc]) bestc = c;\n        }\n        s.push_back(char('A' + bestc));\n    }\n    return s;\n}\n\nCandidate make_candidate(const string& line) {\n    Candidate c;\n    c.line = minimal_rotation(line);\n    c.bits.assign((P + 63) >> 6, 0ULL);\n    int sw = 0;\n    for (int i = 0; i < P; i++) {\n        if (contains_cyclic_line(c.line, pats[i].s)) {\n            c.bits[i >> 6] |= 1ULL << (i & 63);\n            sw += pats[i].w;\n        }\n    }\n    c.coverWeight = sw;\n    return c;\n}\n\nvector<Candidate> generate_candidates(double time_limit) {\n    Timer timer;\n    vector<Candidate> cands;\n    unordered_set<string> seen;\n    seen.reserve(4096);\n\n    auto add_candidate = [&](const string& raw) {\n        string line = minimal_rotation(raw.substr(0, N));\n        if (seen.insert(line).second) {\n            cands.push_back(make_candidate(line));\n        }\n    };\n\n    // sort patterns by value\n    vector<int> ord(P);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        long long va = 1LL * pats[a].w * (int)pats[a].s.size() * (int)pats[a].s.size();\n        long long vb = 1LL * pats[b].w * (int)pats[b].s.size() * (int)pats[b].s.size();\n        if (va != vb) return va > vb;\n        return pats[a].s.size() > pats[b].s.size();\n    });\n\n    // deterministic top seeds\n    int topSeeds = min(P, 120);\n    for (int si = 0; si < topSeeds; si++) {\n        string cur = pats[ord[si]].s;\n        vector<int> used(P, 0);\n        used[ord[si]] = 1;\n\n        while ((int)cur.size() < N) {\n            long long bestScore = -1;\n            int bestj = -1;\n            bool bestAppend = true;\n            int bestOv = 0;\n\n            for (int t = 0; t < min(P, 200); t++) {\n                int j = ord[t];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = true;\n                        bestOv = ov1;\n                    }\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = false;\n                        bestOv = ov2;\n                    }\n                }\n            }\n\n            if (bestj == -1) break;\n            used[bestj] = 1;\n            const string& s = pats[bestj].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (bestAppend) cur += s.substr(bestOv);\n            else cur = s + cur.substr(bestOv);\n        }\n        add_candidate(fill_to_20(cur, pats, false));\n    }\n\n    // randomized builds\n    while (timer.elapsed() < time_limit) {\n        int seed = ord[rng.randint(0, min(P, 80) - 1)];\n        string cur = pats[seed].s;\n        vector<int> used(P, 0);\n        used[seed] = 1;\n\n        int steps = rng.randint(8, 20);\n        for (int step = 0; step < steps && (int)cur.size() < N; step++) {\n            vector<pair<long long, tuple<int,bool,int>>> opts;\n            int pool = min(P, 180);\n            for (int it = 0; it < pool; it++) {\n                int j = ord[it];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, true, ov1}});\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, false, ov2}});\n                }\n            }\n            if (opts.empty()) break;\n            nth_element(opts.begin(),\n                        opts.begin() + min<int>(opts.size(), 5) - 1,\n                        opts.end(),\n                        [&](auto& a, auto& b){ return a.first > b.first; });\n            int pick = rng.randint(0, min<int>(opts.size(), 5) - 1);\n            auto [sc, tup] = opts[pick];\n            auto [j, app, ov] = tup;\n            used[j] = 1;\n            const string& s = pats[j].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (app) cur += s.substr(ov);\n            else cur = s + cur.substr(ov);\n        }\n        add_candidate(fill_to_20(cur, pats, true));\n    }\n\n    // single-pattern direct cyclic fills\n    for (int i = 0; i < min(P, 100); i++) {\n        add_candidate(fill_to_20(pats[ord[i]].s, pats, true));\n    }\n\n    return cands;\n}\n\nint total_weight_from_count(const vector<int>& cnt) {\n    int s = 0;\n    for (int i = 0; i < P; i++) if (cnt[i] > 0) s += pats[i].w;\n    return s;\n}\n\nvector<int> greedy_select_rows(const vector<Candidate>& cands) {\n    int C = (int)cands.size();\n    vector<int> selected;\n    vector<int> cnt(P, 0);\n    vector<char> used(C, 0);\n\n    for (int iter = 0; iter < N; iter++) {\n        int best = -1;\n        long long bestGain = -1;\n\n        for (int i = 0; i < C; i++) if (!used[i]) {\n            long long gain = 0;\n            for (int p = 0; p < P; p++) {\n                if (cnt[p] == 0) {\n                    if ((cands[i].bits[p >> 6] >> (p & 63)) & 1ULL) gain += pats[p].w;\n                }\n            }\n            // slight diversity bonus\n            gain += cands[i].coverWeight / 50;\n            if (gain > bestGain) {\n                bestGain = gain;\n                best = i;\n            }\n        }\n\n        if (best == -1) best = 0;\n        used[best] = 1;\n        selected.push_back(best);\n        for (int p = 0; p < P; p++) {\n            if ((cands[best].bits[p >> 6] >> (p & 63)) & 1ULL) cnt[p]++;\n        }\n    }\n    return selected;\n}\n\nint evaluate_grid(const vector<string>& g) {\n    vector<string> cols(N, string(N, 'A'));\n    for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) cols[j][i] = g[i][j];\n\n    int score = 0;\n    for (int p = 0; p < P; p++) {\n        bool ok = false;\n        for (int i = 0; i < N && !ok; i++) if (contains_cyclic_line(g[i], pats[p].s)) ok = true;\n        for (int j = 0; j < N && !ok; j++) if (contains_cyclic_line(cols[j], pats[p].s)) ok = true;\n        if (ok) score += pats[p].w;\n    }\n    return score;\n}\n\nvector<string> rows_from_selection(const vector<Candidate>& cands, const vector<int>& sel) {\n    vector<string> g(N);\n    for (int i = 0; i < N; i++) g[i] = cands[sel[i]].line;\n    return g;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> Nin >> M;\n    vector<string> input(M);\n    for (int i = 0; i < M; i++) cin >> input[i];\n\n    unordered_map<string, int> mp;\n    mp.reserve(M * 2);\n    for (auto &s : input) mp[s]++;\n\n    pats.clear();\n    pats.reserve(mp.size());\n    for (auto &kv : mp) pats.push_back({kv.first, kv.second});\n    P = (int)pats.size();\n\n    sort(pats.begin(), pats.end(), [&](const Pattern& a, const Pattern& b) {\n        long long va = 1LL * a.w * (int)a.s.size() * (int)a.s.size();\n        long long vb = 1LL * b.w * (int)b.s.size() * (int)b.s.size();\n        if (va != vb) return va > vb;\n        if (a.s.size() != b.s.size()) return a.s.size() > b.s.size();\n        return a.s < b.s;\n    });\n\n    Timer allTimer;\n\n    // Phase 1: generate candidate lines\n    auto cands = generate_candidates(0.9);\n    if (cands.empty()) {\n        string s(N, 'A');\n        for (int i = 0; i < N; i++) cout << s << '\\n';\n        return 0;\n    }\n\n    // Phase 2: select 20 rows greedily\n    auto sel = greedy_select_rows(cands);\n    vector<string> bestGrid = rows_from_selection(cands, sel);\n    int bestScore = evaluate_grid(bestGrid);\n\n    // Phase 3: row replacement local improvement\n    {\n        vector<int> curSel = sel;\n        vector<string> curGrid = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 1.6) {\n            int pos = rng.randint(0, N - 1);\n            int candId = rng.randint(0, (int)cands.size() - 1);\n\n            int old = curSel[pos];\n            if (old == candId) continue;\n            curSel[pos] = candId;\n            curGrid[pos] = cands[candId].line;\n\n            int sc = evaluate_grid(curGrid);\n            if (sc >= curScore || rng.rand01() < 0.01) {\n                curScore = sc;\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestGrid = curGrid;\n                }\n            } else {\n                curSel[pos] = old;\n                curGrid[pos] = cands[old].line;\n            }\n        }\n    }\n\n    // Phase 4: cell-wise hill climbing\n    {\n        vector<string> cur = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 2.95) {\n            int i = rng.randint(0, N - 1);\n            int j = rng.randint(0, N - 1);\n            char oldc = cur[i][j];\n\n            char bestc = oldc;\n            int localBest = curScore;\n\n            array<int, 8> perm{};\n            iota(perm.begin(), perm.end(), 0);\n            shuffle(perm.begin(), perm.end(), std::mt19937((uint32_t)rng.next()));\n\n            int tries = 4;\n            for (int t = 0; t < tries; t++) {\n                char nc = char('A' + perm[t]);\n                if (nc == oldc) continue;\n                cur[i][j] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc > localBest || (sc == localBest && rng.rand01() < 0.05)) {\n                    localBest = sc;\n                    bestc = nc;\n                }\n            }\n\n            cur[i][j] = bestc;\n            curScore = localBest;\n\n            if (curScore > bestScore) {\n                bestScore = curScore;\n                bestGrid = cur;\n            }\n\n            // rare random kick\n            if (rng.rand01() < 0.01) {\n                int x = rng.randint(0, N - 1), y = rng.randint(0, N - 1);\n                char nc = char('A' + rng.randint(0, 7));\n                char bak = cur[x][y];\n                cur[x][y] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc >= curScore || rng.rand01() < 0.2) {\n                    curScore = sc;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestGrid = cur;\n                    }\n                } else {\n                    cur[x][y] = bak;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << bestGrid[i] << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int INF = 1e9;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nstatic inline double now_sec() {\n    using namespace std::chrono;\n    return duration_cast<duration<double>>(steady_clock::now().time_since_epoch()).count();\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    vector<string> C(N);\n    for (int i = 0; i < N; i++) cin >> C[i];\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n    auto road = [&](int x, int y) -> bool {\n        return inb(x, y) && C[x][y] != '#';\n    };\n    auto w = [&](int x, int y) -> int {\n        return C[x][y] - '0';\n    };\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n\n    vector<Pos> roads;\n    vector<vector<int>> rid(N, vector<int>(N, -1));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (road(i, j)) {\n            rid[i][j] = (int)roads.size();\n            roads.push_back({i, j});\n        }\n    }\n    int R = (int)roads.size();\n\n    vector<vector<int>> deg(N, vector<int>(N, 0));\n    for (auto &p : roads) {\n        int d = 0;\n        for (int k = 0; k < 4; k++) if (road(p.x + dx[k], p.y + dy[k])) d++;\n        deg[p.x][p.y] = d;\n    }\n\n    auto is_corner = [&](int x, int y) -> bool {\n        if (!road(x, y) || deg[x][y] != 2) return false;\n        bool ud = road(x - 1, y) && road(x + 1, y);\n        bool lr = road(x, y - 1) && road(x, y + 1);\n        return !(ud || lr);\n    };\n    auto is_important = [&](int x, int y) -> bool {\n        if (x == si && y == sj) return true;\n        if (deg[x][y] != 2) return true;\n        return is_corner(x, y);\n    };\n\n    vector<Pos> cand;\n    vector<vector<int>> cid(N, vector<int>(N, -1));\n\n    auto add_candidate = [&](int x, int y) {\n        if (!road(x, y)) return;\n        if (cid[x][y] != -1) return;\n        cid[x][y] = (int)cand.size();\n        cand.push_back({x, y});\n    };\n\n    for (auto &p : roads) if (is_important(p.x, p.y)) add_candidate(p.x, p.y);\n\n    // corridor sampling\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (!road(i, j)) { j++; continue; }\n            int k = j;\n            while (k < N && road(i, k)) k++;\n            int len = k - j;\n            if (len >= 6) {\n                for (int y = j + 2; y <= k - 3; y += 3) add_candidate(i, y);\n            }\n            j = k;\n        }\n    }\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (!road(i, j)) { i++; continue; }\n            int k = i;\n            while (k < N && road(k, j)) k++;\n            int len = k - i;\n            if (len >= 6) {\n                for (int x = i + 2; x <= k - 3; x += 3) add_candidate(x, j);\n            }\n            i = k;\n        }\n    }\n\n    add_candidate(si, sj);\n    int M = (int)cand.size();\n    int start = cid[si][sj];\n\n    vector<vector<int>> visible(M);\n    vector<int> visScore(M);\n    for (int id = 0; id < M; id++) {\n        auto [x, y] = cand[id];\n        vector<int> tmp;\n        tmp.push_back(rid[x][y]);\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = x, ny = y;\n            while (true) {\n                nx += dx[dir];\n                ny += dy[dir];\n                if (!road(nx, ny)) break;\n                tmp.push_back(rid[nx][ny]);\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());\n        visible[id] = move(tmp);\n        visScore[id] = (int)visible[id].size();\n    }\n\n    vector<int> baseDist(M);\n    for (int i = 0; i < M; i++) baseDist[i] = abs(cand[i].x - si) + abs(cand[i].y - sj);\n\n    auto prune_targets_exact = [&](vector<int> tar) {\n        vector<int> cnt(R, 0);\n        for (int id : tar) for (int r : visible[id]) cnt[r]++;\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            vector<pair<pair<int,int>, int>> order;\n            for (int id : tar) {\n                if (id == start) continue;\n                int uniq = 0;\n                for (int r : visible[id]) if (cnt[r] == 1) uniq++;\n                order.push_back({{uniq, -baseDist[id]}, id});\n            }\n            sort(order.begin(), order.end());\n\n            for (auto &e : order) {\n                int id = e.second;\n                bool ok = true;\n                for (int r : visible[id]) {\n                    if (cnt[r] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n                for (int r : visible[id]) cnt[r]--;\n                vector<int> nt;\n                nt.reserve(tar.size() - 1);\n                for (int x : tar) if (x != id) nt.push_back(x);\n                tar.swap(nt);\n                changed = true;\n                break;\n            }\n        }\n        return tar;\n    };\n\n    XorShift rng;\n    double stime = now_sec();\n    double TL = 2.75;\n\n    vector<int> globalBestTargets;\n    vector<int> globalBestTour;\n    vector<vector<int>> globalBestParent;\n    long long globalBestCost = (1LL << 60);\n\n    auto build_solution = [&](const vector<int>& targetsInput) {\n        vector<int> targets = targetsInput;\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n\n        int T = (int)targets.size();\n        int sidx = -1;\n        for (int i = 0; i < T; i++) if (targets[i] == start) sidx = i;\n\n        int NN = N * N;\n        auto vid = [&](int x, int y) { return x * N + y; };\n\n        vector<vector<int>> distT(T, vector<int>(NN, INF));\n        vector<vector<int>> parentT(T, vector<int>(NN, -1));\n\n        for (int ti = 0; ti < T; ti++) {\n            auto [sx, sy] = cand[targets[ti]];\n            int s = vid(sx, sy);\n            priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n            distT[ti][s] = 0;\n            pq.push({0, s});\n\n            while (!pq.empty()) {\n                auto [cd, v] = pq.top(); pq.pop();\n                if (cd != distT[ti][v]) continue;\n                int x = v / N, y = v % N;\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + dx[k], ny = y + dy[k];\n                    if (!road(nx, ny)) continue;\n                    int nv = vid(nx, ny);\n                    int nd = cd + w(nx, ny);\n                    if (nd < distT[ti][nv]) {\n                        distT[ti][nv] = nd;\n                        parentT[ti][nv] = v;\n                        pq.push({nd, nv});\n                    }\n                }\n            }\n        }\n\n        vector<vector<int>> d(T, vector<int>(T, INF));\n        for (int i = 0; i < T; i++) {\n            for (int j = 0; j < T; j++) {\n                auto [x, y] = cand[targets[j]];\n                d[i][j] = distT[i][vid(x, y)];\n            }\n        }\n\n        auto tour_cost = [&](const vector<int>& tr) -> long long {\n            long long res = 0;\n            for (int i = 0; i + 1 < (int)tr.size(); i++) res += d[tr[i]][tr[i + 1]];\n            return res;\n        };\n\n        auto improve_tour = [&](vector<int>& tour) {\n            bool improved = true;\n            int loop = 0;\n            while (improved && loop < 10) {\n                improved = false;\n                loop++;\n\n                for (int i = 1; i + 2 < (int)tour.size(); i++) {\n                    for (int j = i + 1; j + 1 < (int)tour.size(); j++) {\n                        int a = tour[i - 1], b = tour[i];\n                        int c = tour[j], e = tour[j + 1];\n                        long long before = (long long)d[a][b] + d[c][e];\n                        long long after  = (long long)d[a][c] + d[b][e];\n                        if (after < before) {\n                            reverse(tour.begin() + i, tour.begin() + j + 1);\n                            improved = true;\n                        }\n                    }\n                }\n\n                for (int i = 1; i + 1 < (int)tour.size(); i++) {\n                    int x = tour[i];\n                    long long rem = (long long)d[tour[i - 1]][x] + d[x][tour[i + 1]] - d[tour[i - 1]][tour[i + 1]];\n                    int bestPos = -1;\n                    long long bestDelta = 0;\n                    for (int j = 0; j + 1 < (int)tour.size(); j++) {\n                        if (j == i || j + 1 == i) continue;\n                        long long add = (long long)d[tour[j]][x] + d[x][tour[j + 1]] - d[tour[j]][tour[j + 1]];\n                        long long delta = add - rem;\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestPos = j;\n                        }\n                    }\n                    if (bestPos != -1) {\n                        vector<int> nt = tour;\n                        nt.erase(nt.begin() + i);\n                        int ins = bestPos + 1;\n                        if (bestPos >= i) ins--;\n                        nt.insert(nt.begin() + ins, x);\n                        tour.swap(nt);\n                        improved = true;\n                        break;\n                    }\n                }\n\n                for (int i = 1; i + 1 < (int)tour.size() && !improved; i++) {\n                    for (int j = i + 1; j + 1 < (int)tour.size(); j++) {\n                        vector<int> nt = tour;\n                        swap(nt[i], nt[j]);\n                        if (tour_cost(nt) < tour_cost(tour)) {\n                            tour.swap(nt);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        };\n\n        auto build_cheapest_insertion = [&](int seedMode, bool randomized) {\n            vector<int> others;\n            for (int i = 0; i < T; i++) if (i != sidx) others.push_back(i);\n            if (others.empty()) return vector<int>{sidx, sidx};\n\n            int first = others[0];\n            if (seedMode == 0) {\n                int best = INF;\n                for (int x : others) {\n                    int val = d[sidx][x] + d[x][sidx];\n                    if (val < best) best = val, first = x;\n                }\n            } else if (seedMode == 1) {\n                int best = -1;\n                for (int x : others) {\n                    int val = d[sidx][x] + d[x][sidx];\n                    if (val > best) best = val, first = x;\n                }\n            } else {\n                first = others[rng.next_int(0, (int)others.size() - 1)];\n            }\n\n            vector<int> tour = {sidx, first, sidx};\n            vector<char> used(T, 0);\n            used[sidx] = 1;\n            used[first] = 1;\n\n            while (true) {\n                int bestx = -1, bestpos = -1;\n                long long bestinc = (1LL << 60);\n                bool found = false;\n\n                for (int x : others) if (!used[x]) {\n                    for (int i = 0; i + 1 < (int)tour.size(); i++) {\n                        int a = tour[i], b = tour[i + 1];\n                        long long inc = (long long)d[a][x] + d[x][b] - d[a][b];\n                        if (randomized) inc += rng.next_int(0, 25);\n                        if (inc < bestinc) {\n                            bestinc = inc;\n                            bestx = x;\n                            bestpos = i + 1;\n                            found = true;\n                        }\n                    }\n                }\n                if (!found) break;\n                used[bestx] = 1;\n                tour.insert(tour.begin() + bestpos, bestx);\n            }\n            improve_tour(tour);\n            return tour;\n        };\n\n        auto build_nearest_neighbor = [&](int seedMode) {\n            vector<int> others;\n            for (int i = 0; i < T; i++) if (i != sidx) others.push_back(i);\n            if (others.empty()) return vector<int>{sidx, sidx};\n\n            int cur = others[0];\n            if (seedMode == 0) {\n                int best = INF;\n                for (int x : others) if (d[sidx][x] < best) best = d[sidx][x], cur = x;\n            } else if (seedMode == 1) {\n                int best = -1;\n                for (int x : others) if (d[sidx][x] > best) best = d[sidx][x], cur = x;\n            } else {\n                cur = others[rng.next_int(0, (int)others.size() - 1)];\n            }\n\n            vector<char> used(T, 0);\n            vector<int> tour = {sidx, cur};\n            used[sidx] = used[cur] = 1;\n\n            while (true) {\n                int bestx = -1, bestd = INF;\n                for (int x : others) if (!used[x]) {\n                    if (d[cur][x] < bestd) {\n                        bestd = d[cur][x];\n                        bestx = x;\n                    }\n                }\n                if (bestx == -1) break;\n                used[bestx] = 1;\n                tour.push_back(bestx);\n                cur = bestx;\n            }\n            tour.push_back(sidx);\n            improve_tour(tour);\n            return tour;\n        };\n\n        vector<int> bestTour;\n        long long bestTourCost = (1LL << 60);\n\n        for (int rep = 0; rep < 5; rep++) {\n            auto tr = build_cheapest_insertion(rep % 3, rep & 1);\n            long long cst = tour_cost(tr);\n            if (cst < bestTourCost) bestTourCost = cst, bestTour = tr;\n        }\n        for (int rep = 0; rep < 3; rep++) {\n            auto tr = build_nearest_neighbor(rep);\n            long long cst = tour_cost(tr);\n            if (cst < bestTourCost) bestTourCost = cst, bestTour = tr;\n        }\n\n        // exact-safe post-drop\n        bool changed = true;\n        while (changed) {\n            changed = false;\n\n            vector<int> cnt(R, 0);\n            vector<char> used(T, 0);\n            for (int x : bestTour) used[x] = 1;\n            for (int i = 0; i < T; i++) if (used[i]) {\n                for (int r : visible[targets[i]]) cnt[r]++;\n            }\n\n            vector<pair<pair<int,int>, int>> order;\n            for (int pos = 1; pos + 1 < (int)bestTour.size(); pos++) {\n                int idx = bestTour[pos];\n                if (idx == sidx) continue;\n                int id = targets[idx];\n                int uniq = 0;\n                for (int r : visible[id]) if (cnt[r] == 1) uniq++;\n                order.push_back({{uniq, -baseDist[id]}, pos});\n            }\n            sort(order.begin(), order.end());\n\n            for (auto &it : order) {\n                int pos = it.second;\n                int idx = bestTour[pos];\n                int id = targets[idx];\n                bool ok = true;\n                for (int r : visible[id]) if (cnt[r] <= 1) { ok = false; break; }\n                if (!ok) continue;\n\n                vector<int> ntour;\n                for (int i = 0; i < (int)bestTour.size(); i++) if (i != pos) ntour.push_back(bestTour[i]);\n                long long nc = tour_cost(ntour);\n                if (nc < bestTourCost) {\n                    bestTour = ntour;\n                    bestTourCost = nc;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n\n        return tuple<vector<int>, vector<int>, vector<vector<int>>, long long>(targets, bestTour, parentT, bestTourCost);\n    };\n\n    int trial = 0;\n    while (now_sec() - stime < TL) {\n        trial++;\n\n        vector<char> cov(R, 0), chosen(M, 0);\n        int covCnt = 0;\n        vector<int> tar;\n\n        chosen[start] = 1;\n        tar.push_back(start);\n        for (int r : visible[start]) if (!cov[r]) cov[r] = 1, covCnt++;\n\n        double alpha = 0.7 + 2.4 * rng.next_double();\n        double beta  = 0.01 + 0.30 * rng.next_double();\n        double gamma = 0.4 + 2.2 * rng.next_double();\n\n        while (covCnt < R) {\n            int best = -1;\n            double bestScore = -1e100;\n\n            // randomized greedy\n            for (int id = 0; id < M; id++) {\n                if (chosen[id]) continue;\n                int gain = 0;\n                for (int r : visible[id]) gain += !cov[r];\n                if (gain == 0) continue;\n\n                double score = gain * 1000.0\n                             + gamma * visScore[id]\n                             - alpha * baseDist[id]\n                             - beta * (double)baseDist[id] * (double)baseDist[id]\n                             + rng.next_double() * 180.0;\n\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = id;\n                }\n            }\n\n            if (best == -1) break;\n            chosen[best] = 1;\n            tar.push_back(best);\n            for (int r : visible[best]) if (!cov[r]) cov[r] = 1, covCnt++;\n        }\n\n        if (covCnt < R) continue;\n\n        tar = prune_targets_exact(tar);\n\n        // If target count is already much worse, skip expensive route solve sometimes\n        if (!globalBestTargets.empty() && (int)tar.size() > (int)globalBestTargets.size() + 3) {\n            if (rng.next_int(0, 99) < 70) continue;\n        }\n\n        auto [targets, tour, parentT, cost] = build_solution(tar);\n\n        if (cost < globalBestCost) {\n            globalBestCost = cost;\n            globalBestTargets = targets;\n            globalBestTour = tour;\n            globalBestParent = parentT;\n        }\n    }\n\n    if (globalBestTargets.empty()) {\n        vector<int> tar = {start};\n        vector<char> cov(R, 0);\n        for (int r : visible[start]) cov[r] = 1;\n        for (int i = 0; i < M; i++) {\n            bool need = false;\n            for (int r : visible[i]) if (!cov[r]) { need = true; break; }\n            if (need) {\n                tar.push_back(i);\n                for (int r : visible[i]) cov[r] = 1;\n            }\n        }\n        tar = prune_targets_exact(tar);\n        auto [targets, tour, parentT, cost] = build_solution(tar);\n        globalBestCost = cost;\n        globalBestTargets = targets;\n        globalBestTour = tour;\n        globalBestParent = parentT;\n    }\n\n    int T = (int)globalBestTargets.size();\n    auto vid = [&](int x, int y) { return x * N + y; };\n\n    auto restore_path = [&](int fromIdx, int toIdx) -> vector<Pos> {\n        auto [tx, ty] = cand[globalBestTargets[toIdx]];\n        int cur = vid(tx, ty);\n        int s = vid(cand[globalBestTargets[fromIdx]].x, cand[globalBestTargets[fromIdx]].y);\n\n        vector<int> rev;\n        while (cur != s) {\n            rev.push_back(cur);\n            cur = globalBestParent[fromIdx][cur];\n            if (cur == -1) return {};\n        }\n        reverse(rev.begin(), rev.end());\n\n        vector<Pos> path;\n        for (int v : rev) path.push_back({v / N, v % N});\n        return path;\n    };\n\n    string ans;\n    int cx = si, cy = sj;\n\n    auto emit_step = [&](int nx, int ny) {\n        if (nx == cx - 1 && ny == cy) ans.push_back('U');\n        else if (nx == cx + 1 && ny == cy) ans.push_back('D');\n        else if (nx == cx && ny == cy - 1) ans.push_back('L');\n        else if (nx == cx && ny == cy + 1) ans.push_back('R');\n        cx = nx;\n        cy = ny;\n    };\n\n    for (int i = 0; i + 1 < (int)globalBestTour.size(); i++) {\n        auto path = restore_path(globalBestTour[i], globalBestTour[i + 1]);\n        for (auto &p : path) emit_step(p.x, p.y);\n    }\n\n    // Final exact validation\n    {\n        int x = si, y = sj;\n        bool ok = true;\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n            else ok = false;\n            if (!inb(x, y) || !road(x, y)) ok = false;\n        }\n        if (x != si || y != sj) ok = false;\n\n        vector<char> seen(R, 0);\n        x = si; y = sj;\n        auto mark_vis = [&](int px, int py) {\n            seen[rid[px][py]] = 1;\n            for (int dir = 0; dir < 4; dir++) {\n                int nx = px, ny = py;\n                while (true) {\n                    nx += dx[dir];\n                    ny += dy[dir];\n                    if (!road(nx, ny)) break;\n                    seen[rid[nx][ny]] = 1;\n                }\n            }\n        };\n        mark_vis(x, y);\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n            mark_vis(x, y);\n        }\n        for (int i = 0; i < R; i++) if (!seen[i]) ok = false;\n\n        if (!ok) ans.clear();\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskInfo {\n    vector<int> d;\n    int diff_sum = 0;\n    int priority = 1; // longest path to sink\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<TaskInfo> tasks(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].d.resize(K);\n        int s = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n            s += tasks[i].d[k];\n        }\n        tasks[i].diff_sum = s;\n    }\n\n    vector<vector<int>> out(N), in(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        in[v].push_back(u);\n    }\n\n    // Static priority = longest path to sink\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int to : out[i]) best = max(best, tasks[to].priority);\n        tasks[i].priority = best + 1;\n    }\n\n    // State\n    // task_state: 0 not started, 1 in progress, 2 done\n    vector<int> task_state(N, 0);\n    vector<int> rem_pre(N);\n    for (int i = 0; i < N; ++i) rem_pre[i] = (int)in[i].size();\n\n    vector<int> member_task(M, -1);\n    vector<int> member_start(M, -1);\n\n    // Skill estimates\n    vector<vector<double>> est(M, vector<double>(K, 20.0));\n    vector<int> obs_cnt(M, 0);\n\n    auto predicted_deficit = [&](int task_id, int member_id) -> double {\n        double w = 0.0;\n        const auto &d = tasks[task_id].d;\n        const auto &s = est[member_id];\n        for (int k = 0; k < K; ++k) {\n            if (d[k] > s[k]) w += d[k] - s[k];\n        }\n        return w;\n    };\n\n    auto predicted_time = [&](int task_id, int member_id) -> double {\n        return max(1.0, predicted_deficit(task_id, member_id));\n    };\n\n    auto update_estimate = [&](int member_id, int task_id, int duration) {\n        // target deficit estimate\n        double target = (duration <= 1 ? 0.0 : (double)duration - 1.0);\n\n        const auto &d = tasks[task_id].d;\n        auto &s = est[member_id];\n\n        for (int iter = 0; iter < 3; ++iter) {\n            double pred = 0.0;\n            for (int k = 0; k < K; ++k) {\n                if (d[k] > s[k]) pred += d[k] - s[k];\n            }\n            double diff = target - pred; // positive => prediction too optimistic\n\n            double lr = 0.45 / (1.0 + 0.08 * obs_cnt[member_id]);\n            if (fabs(diff) < 0.5) break;\n\n            if (diff < 0) {\n                // Predicted deficit too large => estimated skills too low => increase skills\n                double total_gap = 0.0;\n                for (int k = 0; k < K; ++k) total_gap += max(0.0, (double)d[k] - s[k]);\n                if (total_gap < 1e-9) total_gap = 1.0;\n                double need = -diff * lr;\n                for (int k = 0; k < K; ++k) {\n                    double gap = max(0.0, (double)d[k] - s[k]);\n                    if (gap <= 0) continue;\n                    s[k] += need * (gap / total_gap);\n                    if (s[k] > 80.0) s[k] = 80.0;\n                }\n            } else {\n                // Predicted deficit too small => estimated skills too high => decrease slightly\n                double total_rel = 0.0;\n                for (int k = 0; k < K; ++k) total_rel += d[k] + 1.0;\n                double need = diff * lr * 0.60;\n                for (int k = 0; k < K; ++k) {\n                    double dec = need * ((d[k] + 1.0) / total_rel);\n                    s[k] -= dec;\n                    if (s[k] < 0.0) s[k] = 0.0;\n                }\n            }\n        }\n\n        obs_cnt[member_id]++;\n    };\n\n    auto unlock_bonus = [&](int task_id) -> int {\n        int cnt = 0;\n        for (int to : out[task_id]) {\n            if (task_state[to] == 0 && rem_pre[to] == 1) cnt++;\n        }\n        return cnt;\n    };\n\n    int day = 0;\n\n    while (true) {\n        day++;\n\n        // Ready tasks\n        vector<int> ready;\n        ready.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 0 && rem_pre[i] == 0) ready.push_back(i);\n        }\n\n        // Sort ready tasks by importance\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (tasks[a].priority != tasks[b].priority) return tasks[a].priority > tasks[b].priority;\n            if (tasks[a].diff_sum != tasks[b].diff_sum) return tasks[a].diff_sum > tasks[b].diff_sum;\n            return a < b;\n        });\n\n        // Candidate truncation - original style\n        const int LIMIT = 180;\n        if ((int)ready.size() > LIMIT) ready.resize(LIMIT);\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) if (member_task[j] == -1) free_members.push_back(j);\n\n        vector<pair<int,int>> assignments;\n        vector<char> used_task(N, 0), used_member(M, 0);\n\n        // Greedy global pair selection\n        while (true) {\n            double bestScore = -1e100;\n            int bestMem = -1, bestTask = -1;\n\n            for (int j : free_members) {\n                if (used_member[j]) continue;\n                for (int t : ready) {\n                    if (used_task[t]) continue;\n\n                    double pt = predicted_time(t, j);\n                    double score =\n                        1000.0 * tasks[t].priority\n                        - 25.0 * pt\n                        + 2.0 * tasks[t].diff_sum\n                        + 80.0 * unlock_bonus(t);\n\n                    if (obs_cnt[j] < 5) {\n                        score += (5 - obs_cnt[j]) * 3.0;\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestMem = j;\n                        bestTask = t;\n                    }\n                }\n            }\n\n            if (bestMem == -1) break;\n\n            used_member[bestMem] = 1;\n            used_task[bestTask] = 1;\n            assignments.push_back({bestMem, bestTask});\n\n            task_state[bestTask] = 1;\n            member_task[bestMem] = bestTask;\n            member_start[bestMem] = day;\n        }\n\n        // Output today's assignments\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << (mem + 1) << ' ' << (task + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        string first;\n        if (!(cin >> first)) return 0;\n        if (first == \"-1\") {\n            return 0;\n        }\n\n        int n = stoi(first);\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int mem : finished) {\n            int task = member_task[mem];\n            if (task == -1) continue;\n\n            int duration = day - member_start[mem] + 1;\n            update_estimate(mem, task, duration);\n\n            task_state[task] = 2;\n            member_task[mem] = -1;\n            member_start[mem] = -1;\n\n            for (int to : out[task]) {\n                rem_pre[to]--;\n            }\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 1000;\nstatic constexpr int M = 50;\nstatic constexpr int DEPOT_X = 400;\nstatic constexpr int DEPOT_Y = 400;\n\nstruct Order {\n    int a, b, c, d;\n    int id;\n};\n\nstruct Pt {\n    int x, y;\n};\n\nstatic inline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\nstatic inline int mdist(const Pt& p, const Pt& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double ms() const {\n        return chrono::duration_cast<chrono::microseconds>(\n            chrono::steady_clock::now() - st\n        ).count() / 1000.0;\n    }\n};\n\nstruct Solver {\n    vector<Order> ord;\n    mt19937 rng;\n\n    Solver() : ord(N) {\n        rng.seed((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    }\n\n    Pt rest_pt(int idx) const { return {ord[idx].a, ord[idx].b}; }\n    Pt dest_pt(int idx) const { return {ord[idx].c, ord[idx].d}; }\n\n    int order_score(int i) const {\n        const auto& o = ord[i];\n        return mdist(DEPOT_X, DEPOT_Y, o.a, o.b)\n             + mdist(o.a, o.b, o.c, o.d)\n             + mdist(o.c, o.d, DEPOT_X, DEPOT_Y);\n    }\n\n    bool validate_solution(const vector<int>& sel, const vector<int>& pord, const vector<int>& dord) const {\n        if ((int)sel.size() != M) return false;\n        if ((int)pord.size() != M || (int)dord.size() != M) return false;\n\n        vector<int> cntSel(N, 0);\n        for (int x : sel) {\n            if (x < 0 || x >= N) return false;\n            cntSel[x]++;\n            if (cntSel[x] > 1) return false;\n        }\n\n        vector<int> cntP(M, 0), cntD(M, 0);\n        for (int x : pord) {\n            if (x < 0 || x >= M) return false;\n            cntP[x]++;\n        }\n        for (int x : dord) {\n            if (x < 0 || x >= M) return false;\n            cntD[x]++;\n        }\n        for (int i = 0; i < M; ++i) {\n            if (cntP[i] != 1 || cntD[i] != 1) return false;\n        }\n        return true;\n    }\n\n    int route_cost(const vector<int>& sel, const vector<int>& pord, const vector<int>& dord) const {\n        Pt cur{DEPOT_X, DEPOT_Y};\n        int cost = 0;\n        for (int pos : pord) {\n            Pt nxt = rest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        for (int pos : dord) {\n            Pt nxt = dest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        cost += mdist(cur, Pt{DEPOT_X, DEPOT_Y});\n        return cost;\n    }\n\n    vector<int> nearest_pickups(const vector<int>& sel) const {\n        vector<int> res;\n        res.reserve(M);\n        vector<char> used(M, false);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = INT_MAX;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                int d = mdist(cur, rest_pt(sel[i]));\n                if (d < bestd) {\n                    bestd = d;\n                    best = i;\n                }\n            }\n            used[best] = true;\n            res.push_back(best);\n            cur = rest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    vector<int> nearest_deliveries(const vector<int>& sel, const Pt& start) const {\n        vector<int> res;\n        res.reserve(M);\n        vector<char> used(M, false);\n        Pt cur = start;\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = INT_MAX;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                int d = mdist(cur, dest_pt(sel[i]));\n                if (d < bestd) {\n                    bestd = d;\n                    best = i;\n                }\n            }\n            used[best] = true;\n            res.push_back(best);\n            cur = dest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    void two_opt_pick(const vector<int>& sel, vector<int>& pord, const vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    Pt A = (l == 0 ? Pt{DEPOT_X, DEPOT_Y} : rest_pt(sel[pord[l - 1]]));\n                    Pt B = rest_pt(sel[pord[l]]);\n                    Pt C = rest_pt(sel[pord[r]]);\n                    Pt D = (r + 1 < M ? rest_pt(sel[pord[r + 1]]) : dest_pt(sel[dord[0]]));\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(pord.begin() + l, pord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void two_opt_del(const vector<int>& sel, const vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    Pt A = (l == 0 ? rest_pt(sel[pord.back()]) : dest_pt(sel[dord[l - 1]]));\n                    Pt B = dest_pt(sel[dord[l]]);\n                    Pt C = dest_pt(sel[dord[r]]);\n                    Pt D = (r + 1 < M ? dest_pt(sel[dord[r + 1]]) : Pt{DEPOT_X, DEPOT_Y});\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(dord.begin() + l, dord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    struct Sol {\n        vector<int> sel, pord, dord;\n        int cost = INT_MAX;\n    };\n\n    Sol build_solution(const vector<int>& sel) const {\n        Sol sol;\n        sol.sel = sel;\n        sol.pord = nearest_pickups(sel);\n        Pt lastPick = rest_pt(sel[sol.pord.back()]);\n        sol.dord = nearest_deliveries(sel, lastPick);\n\n        two_opt_pick(sol.sel, sol.pord, sol.dord);\n        two_opt_del(sol.sel, sol.pord, sol.dord);\n\n        sol.cost = route_cost(sol.sel, sol.pord, sol.dord);\n        return sol;\n    }\n\n    vector<int> sample_subset_from_pool(const vector<int>& pool, const vector<int>& score) {\n        vector<pair<int,int>> cand;\n        cand.reserve(pool.size());\n        for (int idx : pool) {\n            int noisy = score[idx] + uniform_int_distribution<int>(0, 300)(rng);\n            cand.push_back({noisy, idx});\n        }\n        nth_element(cand.begin(), cand.begin() + M, cand.end());\n        cand.resize(M);\n        vector<int> sel;\n        sel.reserve(M);\n        for (auto &p : cand) sel.push_back(p.second);\n        return sel;\n    }\n\n    void solve() {\n        for (int i = 0; i < N; ++i) {\n            cin >> ord[i].a >> ord[i].b >> ord[i].c >> ord[i].d;\n            ord[i].id = i + 1;\n        }\n\n        Timer timer;\n\n        vector<int> score(N);\n        for (int i = 0; i < N; ++i) score[i] = order_score(i);\n\n        vector<int> ranked(N);\n        iota(ranked.begin(), ranked.end(), 0);\n        sort(ranked.begin(), ranked.end(), [&](int x, int y) {\n            return score[x] < score[y];\n        });\n\n        Sol best;\n\n        auto try_candidate = [&](const vector<int>& sel) {\n            Sol sol = build_solution(sel);\n            if (!validate_solution(sol.sel, sol.pord, sol.dord)) return;\n            if (sol.cost < best.cost) best = move(sol);\n        };\n\n        // Multi-start initialization\n        vector<int> poolSizes = {50, 60, 80, 100, 150, 200, 300};\n        for (int K : poolSizes) {\n            if (timer.ms() > 800) break;\n            vector<int> pool(ranked.begin(), ranked.begin() + min(K, N));\n\n            // deterministic top M\n            {\n                vector<int> sel(pool.begin(), pool.begin() + M);\n                try_candidate(sel);\n            }\n\n            // randomized variants\n            int trials = (K <= 100 ? 6 : 4);\n            for (int t = 0; t < trials; ++t) {\n                if (timer.ms() > 1000) break;\n                auto sel = sample_subset_from_pool(pool, score);\n                try_candidate(sel);\n            }\n        }\n\n        if (best.sel.empty()) {\n            best.sel.assign(ranked.begin(), ranked.begin() + M);\n            best = build_solution(best.sel);\n        }\n\n        // Subset replacement hill climbing\n        vector<int> topPool(ranked.begin(), ranked.begin() + 300);\n        while (timer.ms() < 1900) {\n            vector<int> sel = best.sel;\n            vector<char> inSel(N, false);\n            for (int x : sel) inSel[x] = true;\n\n            int outPos = uniform_int_distribution<int>(0, M - 1)(rng);\n            int inIdx;\n            if (uniform_int_distribution<int>(0, 99)(rng) < 85) {\n                inIdx = topPool[uniform_int_distribution<int>(0, (int)topPool.size() - 1)(rng)];\n            } else {\n                inIdx = uniform_int_distribution<int>(0, N - 1)(rng);\n            }\n\n            if (inSel[inIdx]) continue;\n            sel[outPos] = inIdx;\n\n            // uniqueness check\n            {\n                vector<int> cnt(N, 0);\n                bool ok = true;\n                for (int x : sel) {\n                    cnt[x]++;\n                    if (cnt[x] > 1) { ok = false; break; }\n                }\n                if (!ok) continue;\n            }\n\n            Sol sol = build_solution(sel);\n            if (!validate_solution(sol.sel, sol.pord, sol.dord)) continue;\n            if (sol.cost < best.cost) best = move(sol);\n        }\n\n        // final fallback safety\n        if (!validate_solution(best.sel, best.pord, best.dord)) {\n            best.sel.assign(ranked.begin(), ranked.begin() + M);\n            best = build_solution(best.sel);\n        }\n\n        cout << M;\n        for (int idx : best.sel) cout << ' ' << ord[idx].id;\n        cout << '\\n';\n\n        vector<Pt> route;\n        route.reserve(2 * M + 2);\n        route.push_back({DEPOT_X, DEPOT_Y});\n        for (int pos : best.pord) route.push_back(rest_pt(best.sel[pos]));\n        for (int pos : best.dord) route.push_back(dest_pt(best.sel[pos]));\n        route.push_back({DEPOT_X, DEPOT_Y});\n\n        cout << route.size();\n        for (auto &p : route) cout << ' ' << p.x << ' ' << p.y;\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n) { 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 same(int a, int b) { return find(a) == find(b); }\n    int size(int x) { return sz[find(x)]; }\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, d;\n};\n\nstruct KEdge {\n    int w;\n    int type; // 0=accepted, 1=current, 2=future\n    int u, v;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return type < other.type;\n    }\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return (int)llround(sqrt((double)(dx * dx + dy * dy)));\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next_u32() % (uint32_t)(r - l + 1));\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v, rounded_dist(xs[u], ys[u], xs[v], ys[v])};\n    }\n\n    vector<int> state(M, -1); // -1 undecided, 0 rejected, 1 accepted\n    DSU accepted(N);\n    XorShift rng;\n\n    auto det_future_weight = [&](int d) -> int {\n        return (19 * d + 5) / 10; // about 1.9 * d\n    };\n\n    auto feasible_without_current = [&](int cur) -> bool {\n        DSU dsu(N);\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            } else if (j > cur && state[j] == -1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            }\n        }\n        return dsu.same(edges[cur].u, edges[cur].v);\n    };\n\n    auto deterministic_mst_include = [&](int cur, int lcur) -> bool {\n        vector<KEdge> es;\n        es.reserve(M);\n\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                es.push_back({0, 0, edges[j].u, edges[j].v});\n            } else if (j == cur) {\n                es.push_back({lcur, 1, edges[j].u, edges[j].v});\n            } else if (j > cur && state[j] == -1) {\n                es.push_back({det_future_weight(edges[j].d), 2, edges[j].u, edges[j].v});\n            }\n        }\n\n        sort(es.begin(), es.end());\n        DSU dsu(N);\n        for (auto &e : es) {\n            if (dsu.unite(e.u, e.v)) {\n                if (e.type == 1) return true;\n            }\n        }\n        return false;\n    };\n\n    auto sampled_mst_inclusion_count = [&](int cur, int lcur, int samples) -> int {\n        int cnt = 0;\n        vector<KEdge> es;\n        es.reserve(M);\n\n        for (int s = 0; s < samples; s++) {\n            es.clear();\n            for (int j = 0; j < M; j++) {\n                if (state[j] == 1) {\n                    es.push_back({0, 0, edges[j].u, edges[j].v});\n                } else if (j == cur) {\n                    es.push_back({lcur, 1, edges[j].u, edges[j].v});\n                } else if (j > cur && state[j] == -1) {\n                    int d = edges[j].d;\n                    int w = rng.next_int(d, 3 * d);\n                    es.push_back({w, 2, edges[j].u, edges[j].v});\n                }\n            }\n\n            sort(es.begin(), es.end());\n            DSU dsu(N);\n            bool used = false;\n            for (auto &e : es) {\n                if (dsu.unite(e.u, e.v)) {\n                    if (e.type == 1) {\n                        used = true;\n                        break;\n                    }\n                }\n            }\n            if (used) cnt++;\n        }\n        return cnt;\n    };\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n        int ans = 0;\n\n        if (accepted.same(u, v)) {\n            ans = 0;\n        } else if (!feasible_without_current(i)) {\n            ans = 1;\n        } else {\n            bool det_in = deterministic_mst_include(i, l);\n            double r = (double)l / (double)d;\n\n            int su = accepted.size(u);\n            int sv = accepted.size(v);\n            long long merge_score = 1LL * su * sv;\n\n            int big_merge_bonus = 0;\n            if (merge_score >= 4000) big_merge_bonus = 1;\n            if (merge_score >= 12000) big_merge_bonus = 2;\n\n            if (det_in) {\n                if (l <= 2 * d) {\n                    ans = 1;\n                } else if (r >= 2.35) {\n                    int c = sampled_mst_inclusion_count(i, l, 5);\n                    ans = (c + big_merge_bonus >= 4 ? 1 : 0);\n                } else {\n                    int c = sampled_mst_inclusion_count(i, l, 3);\n                    ans = (c + min(big_merge_bonus, 1) >= 1 ? 1 : 0);\n                }\n            } else {\n                if (r <= 1.35) {\n                    int c = sampled_mst_inclusion_count(i, l, 7);\n                    ans = (c + big_merge_bonus >= 4 ? 1 : 0);\n                } else if (r <= 1.50) {\n                    int c = sampled_mst_inclusion_count(i, l, 5);\n                    ans = (c + min(big_merge_bonus, 1) >= 3 ? 1 : 0);\n                } else {\n                    ans = 0;\n                }\n            }\n        }\n\n        state[i] = ans;\n        if (ans) accepted.unite(u, v);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int TURNS = 300;\n\nstruct Pet {\n    int x, y, t;\n};\nstruct Human {\n    int x, y;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\nbool wall_[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar MCH[4] = {'U', 'D', 'L', 'R'};\nchar BCH[4] = {'u', 'd', 'l', 'r'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nint move_dir(char c) {\n    for (int d = 0; d < 4; d++) if (MCH[d] == c) return d;\n    return -1;\n}\nint build_dir(char c) {\n    for (int d = 0; d < 4; d++) if (BCH[d] == c) return d;\n    return -1;\n}\n\nbool pet_at[31][31];\nbool human_at[31][31];\n\nbool adj_pet(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && pet_at[nx][ny]) return true;\n    }\n    return false;\n}\n\nbool can_block_startturn(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (pet_at[x][y]) return false;\n    if (human_at[x][y]) return false;\n    if (adj_pet(x, y)) return false;\n    return true;\n}\n\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nstruct Role {\n    // 0 builder, 1 camper\n    int type;\n    int tx, ty;\n};\n\nvector<Role> roles;\n\npair<int,int> bfs_next_step(\n    int sx, int sy, int tx, int ty,\n    const vector<vector<int>>& blocked_future\n) {\n    if (sx == tx && sy == ty) return {sx, sy};\n\n    static int dist[31][31];\n    static pair<int,int> pre[31][31];\n    for (int i = 1; i <= 30; i++) for (int j = 1; j <= 30; j++) {\n        dist[i][j] = -1;\n        pre[i][j] = {-1, -1};\n    }\n\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    dist[sx][sy] = 0;\n\n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (wall_[nx][ny]) continue;\n            if (blocked_future[nx][ny]) continue;\n            if (dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            pre[nx][ny] = {x, y};\n            q.push({nx, ny});\n        }\n    }\n\n    if (dist[tx][ty] == -1) return {sx, sy};\n\n    int cx = tx, cy = ty;\n    while (pre[cx][cy] != make_pair(sx, sy)) {\n        auto p = pre[cx][cy];\n        if (p.first == -1) return {sx, sy};\n        cx = p.first;\n        cy = p.second;\n    }\n    return {cx, cy};\n}\n\nchar move_toward_safe(\n    int id, int tx, int ty,\n    const vector<vector<int>>& blocked_future,\n    const vector<pair<int,int>>& reserved_moves\n) {\n    int sx = humans[id].x, sy = humans[id].y;\n    auto [nx, ny] = bfs_next_step(sx, sy, tx, ty, blocked_future);\n\n    if (nx != sx || ny != sy) {\n        bool ok = true;\n        for (int j = 0; j < id; j++) {\n            if (reserved_moves[j] == make_pair(nx, ny)) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) {\n            for (int d = 0; d < 4; d++) {\n                if (sx + dx[d] == nx && sy + dy[d] == ny) return MCH[d];\n            }\n        }\n    }\n\n    int bestd = 1e9, bestdir = -1;\n    for (int d = 0; d < 4; d++) {\n        int xx = sx + dx[d], yy = sy + dy[d];\n        if (!inside(xx, yy)) continue;\n        if (wall_[xx][yy]) continue;\n        if (blocked_future[xx][yy]) continue;\n        bool used = false;\n        for (int j = 0; j < id; j++) {\n            if (reserved_moves[j] == make_pair(xx, yy)) {\n                used = true;\n                break;\n            }\n        }\n        if (used) continue;\n        int val = manhattan(xx, yy, tx, ty);\n        if (val < bestd) {\n            bestd = val;\n            bestdir = d;\n        }\n    }\n    if (bestdir == -1) return '.';\n    return MCH[bestdir];\n}\n\nint count_pets_top_initial() {\n    int c = 0;\n    for (auto &p : pets) if (p.x <= 15) c++;\n    return c;\n}\n\nint count_line_built(int row) {\n    int c = 0;\n    for (int y = 1; y <= 30; y++) if (wall_[row][y]) c++;\n    return c;\n}\n\nvector<int> assign_builder_columns(const vector<int>& builderIds, int barrierRow) {\n    vector<int> gaps;\n    for (int y = 1; y <= 30; y++) if (!wall_[barrierRow][y]) gaps.push_back(y);\n\n    vector<int> target(M, 15);\n    if (gaps.empty()) return target;\n\n    vector<int> used((int)gaps.size(), 0);\n\n    for (int id : builderIds) {\n        int bestj = -1, bestd = 1e9;\n        for (int j = 0; j < (int)gaps.size(); j++) if (!used[j]) {\n            int d = abs(humans[id].y - gaps[j]);\n            if (d < bestd) {\n                bestd = d;\n                bestj = j;\n            }\n        }\n        if (bestj == -1) target[id] = humans[id].y;\n        else {\n            target[id] = gaps[bestj];\n            used[bestj] = 1;\n        }\n    }\n    return target;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n    for (int i = 0; i < N; i++) cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; i++) cin >> humans[i].x >> humans[i].y;\n\n    memset(wall_, 0, sizeof(wall_));\n\n    // Commit once to top or bottom using initial pets + gather cost.\n    int topPets = count_pets_top_initial();\n    int bottomPets = N - topPets;\n\n    int gatherTopAll = 0, gatherBottomAll = 0;\n    for (int i = 0; i < M; i++) {\n        gatherTopAll += abs(humans[i].x - 15);\n        gatherBottomAll += abs(humans[i].x - 16);\n    }\n\n    long long scoreTop = 100LL * topPets + gatherTopAll;\n    long long scoreBottom = 100LL * bottomPets + gatherBottomAll;\n\n    bool secureTop = (scoreTop <= scoreBottom);\n    int standRow = secureTop ? 15 : 16;\n    int barrierRow = secureTop ? 16 : 15;\n\n    roles.assign(M, {0, 15, 15});\n\n    // Improved camper selection:\n    // choose human with best corner utility and relatively high stand-row distance,\n    // but without sacrificing too much total builder gathering quality.\n    vector<pair<int,int>> corners = {{2,2}, {2,29}, {29,2}, {29,29}};\n    int camper = -1;\n    long long bestScore = (1LL<<60);\n    pair<int,int> camperCorner = {2,2};\n\n    for (int i = 0; i < M; i++) {\n        int distStand = abs(humans[i].x - standRow);\n        int bestCornerDist = 1e9;\n        pair<int,int> bestC = corners[0];\n        for (auto c : corners) {\n            int d = manhattan(humans[i].x, humans[i].y, c.first, c.second);\n            if (d < bestCornerDist) {\n                bestCornerDist = d;\n                bestC = c;\n            }\n        }\n        // smaller is better\n        // encourage selecting a human who is not especially valuable for main gathering,\n        // and who can reach a corner reasonably well\n        long long val = 8LL * bestCornerDist - 5LL * distStand;\n        if (val < bestScore) {\n            bestScore = val;\n            camper = i;\n            camperCorner = bestC;\n        }\n    }\n\n    if (camper != -1) {\n        roles[camper] = {1, camperCorner.first, camperCorner.second};\n    }\n\n    vector<int> builderIds;\n    for (int i = 0; i < M; i++) if (i != camper) builderIds.push_back(i);\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        memset(pet_at, 0, sizeof(pet_at));\n        memset(human_at, 0, sizeof(human_at));\n        for (auto &p : pets) pet_at[p.x][p.y] = true;\n        for (auto &h : humans) human_at[h.x][h.y] = true;\n\n        int built = count_line_built(barrierRow);\n        bool phaseSeal = (built >= 20 || turn >= 180);\n\n        vector<int> targetCol = assign_builder_columns(builderIds, barrierRow);\n\n        string ans(M, '.');\n        vector<vector<int>> blocked_future(31, vector<int>(31, 0));\n        vector<pair<int,int>> reserved_moves(M, {-1, -1});\n\n        // Phase 1: build if aligned\n        for (int i = 0; i < M; i++) {\n            if (roles[i].type != 0) continue;\n            int x = humans[i].x, y = humans[i].y;\n            if (x != standRow) continue;\n\n            int bd = (barrierRow == x + 1 ? 1 : (barrierRow == x - 1 ? 0 : -1));\n            if (bd == -1) continue;\n\n            int bx = x + dx[bd], by = y + dy[bd];\n            if (!inside(bx, by)) continue;\n            if (blocked_future[bx][by]) continue;\n            if (can_block_startturn(bx, by)) {\n                ans[i] = BCH[bd];\n                blocked_future[bx][by] = 1;\n            }\n        }\n\n        // Phase 2: move builders / camper\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n\n            int x = humans[i].x, y = humans[i].y;\n\n            if (roles[i].type == 1) {\n                if (manhattan(x, y, roles[i].tx, roles[i].ty) <= 1) {\n                    vector<int> pref;\n                    if (x <= 2) pref.push_back(1);\n                    if (x >= 29) pref.push_back(0);\n                    if (y <= 2) pref.push_back(3);\n                    if (y >= 29) pref.push_back(2);\n\n                    bool done = false;\n                    for (int d : pref) {\n                        int bx = x + dx[d], by = y + dy[d];\n                        if (!inside(bx, by)) continue;\n                        if (blocked_future[bx][by]) continue;\n                        if (can_block_startturn(bx, by)) {\n                            ans[i] = BCH[d];\n                            blocked_future[bx][by] = 1;\n                            done = true;\n                            break;\n                        }\n                    }\n                    if (done) continue;\n                }\n\n                char c = move_toward_safe(i, roles[i].tx, roles[i].ty, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            // builders\n            if (x != standRow) {\n                char c = move_toward_safe(i, standRow, y, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            if (!phaseSeal) {\n                if (!wall_[barrierRow][y] && !blocked_future[barrierRow][y]) {\n                    ans[i] = '.';\n                    continue;\n                }\n                char c = move_toward_safe(i, standRow, targetCol[i], blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n            } else {\n                // split builders toward both ends\n                int idx = 0;\n                for (int id : builderIds) {\n                    if (id == i) break;\n                    idx++;\n                }\n                int endY = (idx * 2 < (int)builderIds.size() ? 1 : 30);\n\n                if (!wall_[barrierRow][y] && !blocked_future[barrierRow][y]) {\n                    ans[i] = '.';\n                    continue;\n                }\n                char c = move_toward_safe(i, standRow, endY, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n            }\n        }\n\n        // Final legality sanitizer\n        {\n            set<pair<int,int>> used;\n            for (int i = 0; i < M; i++) {\n                int md = move_dir(ans[i]);\n                if (md == -1) continue;\n                int nx = humans[i].x + dx[md], ny = humans[i].y + dy[md];\n                bool bad = false;\n                if (!inside(nx, ny)) bad = true;\n                if (!bad && wall_[nx][ny]) bad = true;\n                if (!bad && blocked_future[nx][ny]) bad = true;\n                if (!bad && used.count({nx, ny})) bad = true;\n                if (bad) ans[i] = '.';\n                else used.insert({nx, ny});\n            }\n        }\n\n        cout << ans << '\\n';\n        cout.flush();\n\n        // Apply human actions locally\n        for (int i = 0; i < M; i++) {\n            int md = move_dir(ans[i]);\n            int bd = build_dir(ans[i]);\n\n            if (md != -1) {\n                int nx = humans[i].x + dx[md], ny = humans[i].y + dy[md];\n                if (inside(nx, ny) && !wall_[nx][ny] && !blocked_future[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            } else if (bd != -1) {\n                int bx = humans[i].x + dx[bd], by = humans[i].y + dy[bd];\n                if (inside(bx, by) && can_block_startturn(bx, by)) {\n                    wall_[bx][by] = true;\n                }\n            }\n        }\n\n        // Read pet moves\n        for (int i = 0; i < N; i++) {\n            string s;\n            cin >> s;\n            if (!cin) return 0;\n            if (s == \".\") continue;\n            for (char c : s) {\n                int d = move_dir(c);\n                if (d == -1) continue;\n                int nx = pets[i].x + dx[d], ny = pets[i].y + dy[d];\n                if (inside(nx, ny) && !wall_[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - 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 l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nint si, sj, ti, tj;\ndouble pforget;\nstring hs[H];\nstring vs[H - 1];\n\nint nxtCell[N][4];\nint distToTarget[N];\nchar dirch[4] = {'U', 'D', 'L', 'R'};\n\ninline int id(int i, int j) { return i * W + j; }\n\nint c2d(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\ndouble eval_string(const string &s) {\n    int S = id(si, sj), T = id(ti, tj);\n    vector<double> cur(N, 0.0), nx(N, 0.0);\n    cur[S] = 1.0;\n    double ans = 0.0;\n    for (int t = 1; t <= (int)s.size(); t++) {\n        int d = c2d(s[t - 1]);\n        fill(nx.begin(), nx.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == T) {\n                ans += pr * (401 - t);\n                continue;\n            }\n            nx[v] += pr * pforget;\n            nx[nxtCell[v][d]] += pr * (1.0 - pforget);\n        }\n        cur.swap(nx);\n    }\n    return ans;\n}\n\nvector<double> distribution_after(const string &s) {\n    int S = id(si, sj), T = id(ti, tj);\n    vector<double> cur(N, 0.0), nx(N, 0.0);\n    cur[S] = 1.0;\n    for (char c : s) {\n        int d = c2d(c);\n        fill(nx.begin(), nx.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == T) continue;\n            nx[v] += pr * pforget;\n            nx[nxtCell[v][d]] += pr * (1.0 - pforget);\n        }\n        cur.swap(nx);\n    }\n    return cur;\n}\n\nvoid bfs_target() {\n    fill(distToTarget, distToTarget + N, (int)1e9);\n    int T = id(ti, tj);\n    queue<int> q;\n    distToTarget[T] = 0;\n    q.push(T);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int i = v / W, j = v % W;\n        if (i > 0) {\n            int u = id(i - 1, j);\n            if (nxtCell[u][1] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n        if (i + 1 < H) {\n            int u = id(i + 1, j);\n            if (nxtCell[u][0] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n        if (j > 0) {\n            int u = id(i, j - 1);\n            if (nxtCell[u][3] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n        if (j + 1 < W) {\n            int u = id(i, j + 1);\n            if (nxtCell[u][2] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n}\n\nstring random_shortest_to_target() {\n    int S = id(si, sj), T = id(ti, tj);\n    string s;\n    int cur = S;\n    while (cur != T) {\n        vector<int> cand;\n        for (int d = 0; d < 4; d++) {\n            int to = nxtCell[cur][d];\n            if (to == cur) continue;\n            if (distToTarget[to] + 1 == distToTarget[cur]) cand.push_back(d);\n        }\n        if (cand.empty()) break;\n        int d = cand[rng.next_int(0, (int)cand.size() - 1)];\n        s.push_back(dirch[d]);\n        cur = nxtCell[cur][d];\n    }\n    return s;\n}\n\nstring repeat_each(const string &base, int k, int lim = MAXL) {\n    string s;\n    s.reserve(min(lim, (int)base.size() * k));\n    for (char c : base) {\n        for (int i = 0; i < k && (int)s.size() < lim; i++) s.push_back(c);\n    }\n    return s;\n}\n\nstring build_suffix_from_dist(vector<double> cur, int len) {\n    int T = id(ti, tj);\n    vector<double> nx(N, 0.0);\n    string suf;\n    suf.reserve(len);\n\n    for (int step = 0; step < len; step++) {\n        int bestD = 0;\n        double bestScore = -1e100;\n        for (int d = 0; d < 4; d++) {\n            double sc = 0.0;\n            for (int v = 0; v < N; v++) {\n                double pr = cur[v];\n                if (pr == 0.0) continue;\n                if (v == T) {\n                    sc += pr * 1e6;\n                    continue;\n                }\n                int to = nxtCell[v][d];\n                sc += pr * ((1.0 - pforget) * (distToTarget[v] - distToTarget[to]));\n                if (to == T) sc += pr * (1.0 - pforget) * 1000.0;\n            }\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestD = d;\n            }\n        }\n\n        suf.push_back(dirch[bestD]);\n        fill(nx.begin(), nx.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == T) {\n                nx[v] += pr;\n            } else {\n                nx[v] += pr * pforget;\n                nx[nxtCell[v][bestD]] += pr * (1.0 - pforget);\n            }\n        }\n        cur.swap(nx);\n    }\n    return suf;\n}\n\nstring build_candidate(const string &base, int totalLen, int rep) {\n    string pref = repeat_each(base, rep, totalLen);\n    if ((int)pref.size() < totalLen) {\n        auto dist = distribution_after(pref);\n        pref += build_suffix_from_dist(dist, totalLen - (int)pref.size());\n    }\n    return pref;\n}\n\nbool coordinate_optimize(string &s) {\n    int L = (int)s.size();\n    if (L == 0) return false;\n    int S = id(si, sj), T = id(ti, tj);\n\n    vector<vector<double>> pref(L + 1, vector<double>(N, 0.0));\n    vector<vector<double>> suf(L + 1, vector<double>(N, 0.0));\n\n    pref[0][S] = 1.0;\n    for (int t = 0; t < L; t++) {\n        int d = c2d(s[t]);\n        for (int v = 0; v < N; v++) {\n            double pr = pref[t][v];\n            if (pr == 0.0 || v == T) continue;\n            pref[t + 1][v] += pr * pforget;\n            int to = nxtCell[v][d];\n            if (to != T) pref[t + 1][to] += pr * (1.0 - pforget);\n        }\n    }\n\n    for (int v = 0; v < N; v++) suf[L][v] = 0.0;\n    for (int t = L - 1; t >= 0; t--) {\n        int reward = 401 - (t + 1);\n        int d = c2d(s[t]);\n        for (int v = 0; v < N; v++) {\n            if (v == T) {\n                suf[t][v] = 0.0;\n                continue;\n            }\n            int to = nxtCell[v][d];\n            double val = pforget * suf[t + 1][v];\n            if (to == T) val += (1.0 - pforget) * reward;\n            else val += (1.0 - pforget) * suf[t + 1][to];\n            suf[t][v] = val;\n        }\n    }\n\n    bool improved = false;\n    for (int t = 0; t < L; t++) {\n        int reward = 401 - (t + 1);\n        char bestC = s[t];\n        double bestVal = -1e100;\n\n        for (int d = 0; d < 4; d++) {\n            double total = 0.0;\n            for (int v = 0; v < N; v++) {\n                double pr = pref[t][v];\n                if (pr == 0.0 || v == T) continue;\n                int to = nxtCell[v][d];\n                double add = pforget * suf[t + 1][v];\n                if (to == T) add += (1.0 - pforget) * reward;\n                else add += (1.0 - pforget) * suf[t + 1][to];\n                total += pr * add;\n            }\n            if (total > bestVal) {\n                bestVal = total;\n                bestC = dirch[d];\n            }\n        }\n\n        if (bestC != s[t]) {\n            s[t] = bestC;\n            improved = true;\n        }\n    }\n    return improved;\n}\n\nstring mutate(const string &s, const vector<string> &pathPool) {\n    string t = s;\n    int op = rng.next_int(0, 99);\n\n    if (op < 16 && !t.empty()) {\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n    } else if (op < 28 && (int)t.size() < MAXL) {\n        int i = rng.next_int(0, (int)t.size());\n        t.insert(t.begin() + i, dirch[rng.next_int(0, 3)]);\n    } else if (op < 38 && !t.empty()) {\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t.erase(t.begin() + i);\n    } else if (op < 52 && !t.empty()) {\n        int l = rng.next_int(0, (int)t.size() - 1);\n        int r = rng.next_int(l, min((int)t.size() - 1, l + 7));\n        string seg = t.substr(l, r - l + 1);\n        if ((int)t.size() + (int)seg.size() <= MAXL) {\n            int pos = rng.next_int(0, (int)t.size());\n            t.insert(pos, seg);\n        }\n    } else if (op < 66 && !t.empty()) {\n        int l = rng.next_int(0, (int)t.size() - 1);\n        int r = rng.next_int(l, min((int)t.size() - 1, l + 9));\n        for (int i = l; i <= r; i++) t[i] = dirch[rng.next_int(0, 3)];\n    } else if (op < 78 && !pathPool.empty()) {\n        string seg = pathPool[rng.next_int(0, (int)pathPool.size() - 1)];\n        if (seg.empty()) seg = \"R\";\n        if ((int)seg.size() > 12) {\n            int l = rng.next_int(0, (int)seg.size() - 1);\n            int r = rng.next_int(l, min((int)seg.size() - 1, l + 11));\n            seg = seg.substr(l, r - l + 1);\n        }\n        int pos = rng.next_int(0, (int)t.size());\n        int del = min((int)t.size() - pos, rng.next_int(0, 8));\n        t.erase(pos, del);\n        if ((int)t.size() + (int)seg.size() > MAXL) seg.resize(MAXL - (int)t.size());\n        t.insert(pos, seg);\n    } else if (op < 90 && !t.empty()) {\n        int cut = rng.next_int(0, (int)t.size());\n        string pref = t.substr(0, cut);\n        auto dist = distribution_after(pref);\n        t = pref + build_suffix_from_dist(dist, MAXL - cut);\n    } else {\n        if (!t.empty()) {\n            int i = rng.next_int(0, (int)t.size() - 1);\n            char c = t[i];\n            int l = i, r = i;\n            while (l > 0 && t[l - 1] == c) l--;\n            while (r + 1 < (int)t.size() && t[r + 1] == c) r++;\n            int len = r - l + 1;\n            int newlen = max(1, min(10, len + rng.next_int(-2, 3)));\n            string rep(newlen, c);\n            t.replace(l, len, rep);\n            if ((int)t.size() > MAXL) t.resize(MAXL);\n        }\n    }\n\n    if ((int)t.size() > MAXL) t.resize(MAXL);\n    return t;\n}\n\nstruct Cand {\n    string s;\n    double val;\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 < H; i++) cin >> hs[i];\n    for (int i = 0; i < H - 1; i++) cin >> vs[i];\n\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int v = id(i, j);\n            if (i == 0 || vs[i - 1][j] == '1') nxtCell[v][0] = v;\n            else nxtCell[v][0] = id(i - 1, j);\n            if (i == H - 1 || vs[i][j] == '1') nxtCell[v][1] = v;\n            else nxtCell[v][1] = id(i + 1, j);\n            if (j == 0 || hs[i][j - 1] == '1') nxtCell[v][2] = v;\n            else nxtCell[v][2] = id(i, j - 1);\n            if (j == W - 1 || hs[i][j] == '1') nxtCell[v][3] = v;\n            else nxtCell[v][3] = id(i, j + 1);\n        }\n    }\n\n    bfs_target();\n    Timer timer;\n    const double TL = 1.95;\n\n    vector<string> pathPool;\n    for (int i = 0; i < 50; i++) pathPool.push_back(random_shortest_to_target());\n    sort(pathPool.begin(), pathPool.end());\n    pathPool.erase(unique(pathPool.begin(), pathPool.end()), pathPool.end());\n    if (pathPool.empty()) pathPool.push_back(\"\");\n\n    vector<int> lens = {60, 80, 100, 120, 140, 160, 180, 200};\n    vector<int> reps;\n    if (pforget <= 0.15) reps = {1,2,3,4};\n    else if (pforget <= 0.25) reps = {2,3,4,5};\n    else if (pforget <= 0.35) reps = {3,4,5,6};\n    else reps = {4,5,6,7,8};\n\n    vector<Cand> elite;\n    auto push_elite = [&](const string &s, double v) {\n        for (auto &e : elite) {\n            if (e.s == s) {\n                if (v > e.val) e.val = v;\n                return;\n            }\n        }\n        elite.push_back({s, v});\n        sort(elite.begin(), elite.end(), [](const Cand &a, const Cand &b) { return a.val > b.val; });\n        const int ELIM = 10;\n        if ((int)elite.size() > ELIM) elite.resize(ELIM);\n    };\n\n    // Seed generation\n    for (const string &base : pathPool) {\n        if (timer.elapsed() > 0.55) break;\n        for (int L : lens) {\n            for (int k : reps) {\n                string cand = build_candidate(base, L, k);\n                if (rng.next_double() < 0.75) coordinate_optimize(cand);\n                double v = eval_string(cand);\n                push_elite(cand, v);\n            }\n        }\n    }\n\n    if (elite.empty()) {\n        string s = pathPool[0];\n        double v = eval_string(s);\n        push_elite(s, v);\n    }\n\n    // Direct polishing on elites\n    for (int round = 0; round < 2 && timer.elapsed() < 0.85; round++) {\n        vector<Cand> now = elite;\n        for (auto &e : now) {\n            string cand = e.s;\n            bool ch = coordinate_optimize(cand);\n            double v = eval_string(cand);\n            if (v > e.val || ch) push_elite(cand, v);\n            if (timer.elapsed() >= 0.85) break;\n        }\n    }\n\n    int iter = 0;\n    while (true) {\n        double tm = timer.elapsed();\n        if (tm > TL) break;\n        iter++;\n\n        int idx = rng.next_int(0, (int)elite.size() - 1);\n        string base = elite[idx].s;\n        double baseVal = elite[idx].val;\n\n        string cand = mutate(base, pathPool);\n        if (rng.next_double() < 0.20) coordinate_optimize(cand);\n        double nv = eval_string(cand);\n\n        double progress = tm / TL;\n        double temp = 1200.0 * (1.0 - progress) + 1e-9;\n        double diff = nv - baseVal;\n\n        if (diff >= 0 || rng.next_double() < exp(diff / temp)) {\n            push_elite(cand, nv);\n        }\n\n        if ((iter % 200) == 0) {\n            string b = pathPool[rng.next_int(0, (int)pathPool.size() - 1)];\n            int L = lens[rng.next_int(0, (int)lens.size() - 1)];\n            int k = reps[rng.next_int(0, (int)reps.size() - 1)];\n            string cand2 = build_candidate(b, L, k);\n            if (rng.next_double() < 0.5) coordinate_optimize(cand2);\n            double v2 = eval_string(cand2);\n            push_elite(cand2, v2);\n        }\n    }\n\n    string best = elite[0].s;\n    double bestVal = elite[0].val;\n\n    while (timer.elapsed() < TL) {\n        string cand = best;\n        bool ch = coordinate_optimize(cand);\n        double v = eval_string(cand);\n        if (v > bestVal) {\n            bestVal = v;\n            best = cand;\n        } else if (!ch) {\n            break;\n        } else {\n            break;\n        }\n    }\n\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n    cout << best << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int NN = N * N;\n\nstatic const int di[4] = {0, -1, 0, 1}; // L U R D\nstatic const int dj[4] = {-1, 0, 1, 0};\n\nstatic const int TO[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\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\ninline int rotTile(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (t <= 3) t = (t + 1) & 3;\n        else if (t <= 5) t = 9 - t;   // 4 <-> 5\n        else t = 13 - t;              // 6 <-> 7\n    }\n    return t;\n}\n\ninline int maskOfTile(int t) {\n    int m = 0;\n    for (int d = 0; d < 4; d++) if (TO[t][d] != -1) m |= (1 << d);\n    return m;\n}\n\nstruct Solver {\n    array<string, N> s;\n    int base[N][N];\n    int rotTileId[N][N][4];\n    int rotMask[N][N][4];\n    mt19937 rng;\n\n    Solver() : rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void readInput() {\n        for (int i = 0; i < N; i++) {\n            cin >> s[i];\n            for (int j = 0; j < N; j++) {\n                base[i][j] = s[i][j] - '0';\n                for (int r = 0; r < 4; r++) {\n                    rotTileId[i][j][r] = rotTile(base[i][j], r);\n                    rotMask[i][j][r] = maskOfTile(rotTileId[i][j][r]);\n                }\n            }\n        }\n    }\n\n    long long exactScore(const array<unsigned char, NN>& rot) const {\n        static int tile[N][N];\n        static unsigned char vis[N][N][4];\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            tile[i][j] = rotTileId[i][j][rot[i * N + j]];\n        }\n        memset(vis, 0, sizeof(vis));\n\n        int best1 = 0, best2 = 0;\n\n        for (int si = 0; si < N; si++) for (int sj = 0; sj < N; sj++) for (int sd = 0; sd < 4; sd++) {\n            if (vis[si][sj][sd]) continue;\n\n            int i = si, j = sj, d = sd, len = 0;\n            bool ok = true;\n\n            while (true) {\n                if (vis[i][j][d]) {\n                    ok = false;\n                    break;\n                }\n                vis[i][j][d] = 1;\n                int d2 = TO[tile[i][j]][d];\n                if (d2 == -1) {\n                    ok = false;\n                    break;\n                }\n                i += di[d2];\n                j += dj[d2];\n                if (i < 0 || i >= N || j < 0 || j >= N) {\n                    ok = false;\n                    break;\n                }\n                d = (d2 + 2) & 3;\n                ++len;\n                if (i == si && j == sj && d == sd) break;\n                if (len > 4 * NN + 10) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) {\n                if (len > best1) {\n                    best2 = best1;\n                    best1 = len;\n                } else if (len > best2) {\n                    best2 = len;\n                }\n            }\n        }\n\n        if (best2 == 0) return 0;\n        return 1LL * best1 * best2;\n    }\n\n    inline int cellContribution(const array<unsigned char, NN>& rot, int i, int j) const {\n        int m = rotMask[i][j][rot[i * N + j]];\n        int sc = 0;\n\n        if (j + 1 < N) {\n            int m2 = rotMask[i][j + 1][rot[i * N + (j + 1)]];\n            if (((m >> 2) & 1) && ((m2 >> 0) & 1)) sc += 1;\n        } else {\n            if ((m >> 2) & 1) sc -= 1;\n        }\n\n        if (i + 1 < N) {\n            int m2 = rotMask[i + 1][j][rot[(i + 1) * N + j]];\n            if (((m >> 3) & 1) && ((m2 >> 1) & 1)) sc += 1;\n        } else {\n            if ((m >> 3) & 1) sc -= 1;\n        }\n\n        if (j == 0 && ((m >> 0) & 1)) sc -= 1;\n        if (i == 0 && ((m >> 1) & 1)) sc -= 1;\n\n        return sc;\n    }\n\n    int localScore(const array<unsigned char, NN>& rot) const {\n        int sc = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) sc += cellContribution(rot, i, j);\n        return sc;\n    }\n\n    inline int affected1(const array<unsigned char, NN>& rot, int i, int j) const {\n        int sc = 0;\n        for (int ni = max(0, i - 1); ni <= min(N - 1, i + 1); ni++) {\n            for (int nj = max(0, j - 1); nj <= min(N - 1, j + 1); nj++) {\n                sc += cellContribution(rot, ni, nj);\n            }\n        }\n        return sc;\n    }\n\n    inline int affected2x2(const array<unsigned char, NN>& rot, int i, int j) const {\n        int sc = 0;\n        for (int ni = max(0, i - 1); ni <= min(N - 1, i + 2); ni++) {\n            for (int nj = max(0, j - 1); nj <= min(N - 1, j + 2); nj++) {\n                sc += cellContribution(rot, ni, nj);\n            }\n        }\n        return sc;\n    }\n\n    array<unsigned char, NN> makeInitial(int type) {\n        array<unsigned char, NN> rot{};\n        if (type == 0) {\n            rot.fill(0);\n        } else if (type == 1) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = (i + j) & 3;\n        } else if (type == 2) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = i & 3;\n        } else if (type == 3) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = j & 3;\n        } else {\n            for (int k = 0; k < NN; k++) rot[k] = rng() & 3;\n        }\n        return rot;\n    }\n\n    void optimizeLocal(array<unsigned char, NN>& rot, Timer& timer, double endTime) {\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n\n        while (timer.elapsed() < endTime) {\n            bool improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int idx : ord) {\n                if (timer.elapsed() >= endTime) return;\n                int i = idx / N, j = idx % N;\n                int before = affected1(rot, i, j);\n                unsigned char old = rot[idx], bestR = old;\n                int bestDelta = 0;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int delta = affected1(rot, i, j) - before;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = old;\n                if (bestDelta > 0) {\n                    rot[idx] = bestR;\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n    }\n\n    vector<int> collectBadCells(const array<unsigned char, NN>& rot) {\n        vector<int> cells;\n        vector<char> used(NN, 0);\n\n        auto add = [&](int i, int j) {\n            if (i < 0 || i >= N || j < 0 || j >= N) return;\n            int idx = i * N + j;\n            if (!used[idx]) {\n                used[idx] = 1;\n                cells.push_back(idx);\n            }\n        };\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int m = rotMask[i][j][rot[i * N + j]];\n\n            if (j == 0 && ((m >> 0) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n            if (i == 0 && ((m >> 1) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n            if (j == N - 1 && ((m >> 2) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n            if (i == N - 1 && ((m >> 3) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n\n            if (j + 1 < N) {\n                int m2 = rotMask[i][j + 1][rot[i * N + (j + 1)]];\n                if (((m >> 2) & 1) != ((m2 >> 0) & 1)) {\n                    for (int a = -1; a <= 1; a++) for (int b = -1; b <= 2; b++) add(i + a, j + b);\n                }\n            }\n            if (i + 1 < N) {\n                int m2 = rotMask[i + 1][j][rot[(i + 1) * N + j]];\n                if (((m >> 3) & 1) != ((m2 >> 1) & 1)) {\n                    for (int a = -1; a <= 2; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n                }\n            }\n        }\n\n        while ((int)cells.size() < 120) {\n            int idx = (int)(rng() % NN);\n            if (!used[idx]) {\n                used[idx] = 1;\n                cells.push_back(idx);\n            }\n        }\n\n        shuffle(cells.begin(), cells.end(), rng);\n        return cells;\n    }\n\n    void targeted1Cell(array<unsigned char, NN>& rot, long long& curScore, Timer& timer, double endTime) {\n        while (timer.elapsed() < endTime) {\n            auto cells = collectBadCells(rot);\n            bool improved = false;\n\n            for (int idx : cells) {\n                if (timer.elapsed() >= endTime) return;\n                int i = idx / N, j = idx % N;\n                int beforeLocal = affected1(rot, i, j);\n                unsigned char old = rot[idx], bestR = old;\n                long long bestSc = curScore;\n                int bestLocal = -1e9;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int localDelta = affected1(rot, i, j) - beforeLocal;\n                    if (localDelta < -1) continue;\n                    long long sc = exactScore(rot);\n                    if (sc > bestSc || (sc == bestSc && localDelta > bestLocal)) {\n                        bestSc = sc;\n                        bestLocal = localDelta;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = old;\n\n                if (bestR != old) {\n                    rot[idx] = bestR;\n                    curScore = bestSc;\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void targeted2x2(array<unsigned char, NN>& rot, long long& curScore, Timer& timer, double endTime) {\n        while (timer.elapsed() < endTime) {\n            auto cells = collectBadCells(rot);\n            vector<pair<int,int>> blocks;\n            vector<char> used((N - 1) * (N - 1), 0);\n\n            for (int idx : cells) {\n                int i = idx / N, j = idx % N;\n                for (int bi = max(0, i - 1); bi <= min(N - 2, i); bi++) {\n                    for (int bj = max(0, j - 1); bj <= min(N - 2, j); bj++) {\n                        int id = bi * (N - 1) + bj;\n                        if (!used[id]) {\n                            used[id] = 1;\n                            blocks.push_back({bi, bj});\n                        }\n                    }\n                }\n            }\n            shuffle(blocks.begin(), blocks.end(), rng);\n\n            bool improved = false;\n\n            for (auto [i, j] : blocks) {\n                if (timer.elapsed() >= endTime) return;\n\n                int ids[4] = {i * N + j, i * N + (j + 1), (i + 1) * N + j, (i + 1) * N + (j + 1)};\n                unsigned char old[4] = {rot[ids[0]], rot[ids[1]], rot[ids[2]], rot[ids[3]]};\n                int before = affected2x2(rot, i, j);\n\n                struct Cand {\n                    int localDelta;\n                    unsigned char a, b, c, d;\n                };\n                vector<Cand> cand;\n                cand.reserve(256);\n\n                for (unsigned char a = 0; a < 4; a++) for (unsigned char b = 0; b < 4; b++)\n                for (unsigned char c = 0; c < 4; c++) for (unsigned char d = 0; d < 4; d++) {\n                    rot[ids[0]] = a;\n                    rot[ids[1]] = b;\n                    rot[ids[2]] = c;\n                    rot[ids[3]] = d;\n                    int delta = affected2x2(rot, i, j) - before;\n                    cand.push_back({delta, a, b, c, d});\n                }\n\n                rot[ids[0]] = old[0];\n                rot[ids[1]] = old[1];\n                rot[ids[2]] = old[2];\n                rot[ids[3]] = old[3];\n\n                sort(cand.begin(), cand.end(), [](const Cand& x, const Cand& y) {\n                    return x.localDelta > y.localDelta;\n                });\n\n                long long bestSc = curScore;\n                int bestLocal = -1e9;\n                unsigned char br[4] = {old[0], old[1], old[2], old[3]};\n\n                int lim = min<int>(10, cand.size());\n                for (int t = 0; t < lim; t++) {\n                    if (cand[t].localDelta < -1) break;\n                    rot[ids[0]] = cand[t].a;\n                    rot[ids[1]] = cand[t].b;\n                    rot[ids[2]] = cand[t].c;\n                    rot[ids[3]] = cand[t].d;\n                    long long sc = exactScore(rot);\n                    if (sc > bestSc || (sc == bestSc && cand[t].localDelta > bestLocal)) {\n                        bestSc = sc;\n                        bestLocal = cand[t].localDelta;\n                        br[0] = cand[t].a;\n                        br[1] = cand[t].b;\n                        br[2] = cand[t].c;\n                        br[3] = cand[t].d;\n                    }\n                }\n\n                rot[ids[0]] = old[0];\n                rot[ids[1]] = old[1];\n                rot[ids[2]] = old[2];\n                rot[ids[3]] = old[3];\n\n                bool changed = !(br[0] == old[0] && br[1] == old[1] && br[2] == old[2] && br[3] == old[3]);\n                if (changed) {\n                    rot[ids[0]] = br[0];\n                    rot[ids[1]] = br[1];\n                    rot[ids[2]] = br[2];\n                    rot[ids[3]] = br[3];\n                    curScore = bestSc;\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void randomKick(array<unsigned char, NN>& rot, int k) {\n        for (int t = 0; t < k; t++) {\n            int idx = (int)(rng() % NN);\n            rot[idx] = rng() & 3;\n        }\n    }\n\n    void solve() {\n        Timer timer;\n        const double TL = 1.95;\n\n        array<unsigned char, NN> globalBest = makeInitial(0);\n        long long globalBestScore = exactScore(globalBest);\n\n        int trial = 0;\n        while (timer.elapsed() < TL) {\n            array<unsigned char, NN> rot;\n            if (trial < 4) rot = makeInitial(trial);\n            else rot = makeInitial(4);\n\n            double rem = TL - timer.elapsed();\n            if (rem <= 0) break;\n\n            optimizeLocal(rot, timer, min(TL, timer.elapsed() + min(0.15, rem * 0.35)));\n\n            long long sc = exactScore(rot);\n            if (sc > globalBestScore) {\n                globalBestScore = sc;\n                globalBest = rot;\n            }\n\n            if (timer.elapsed() < TL) {\n                targeted1Cell(rot, sc, timer, min(TL, timer.elapsed() + 0.30));\n                if (sc > globalBestScore) {\n                    globalBestScore = sc;\n                    globalBest = rot;\n                }\n            }\n\n            if (timer.elapsed() < TL) {\n                targeted2x2(rot, sc, timer, min(TL, timer.elapsed() + 0.45));\n                if (sc > globalBestScore) {\n                    globalBestScore = sc;\n                    globalBest = rot;\n                }\n            }\n\n            if (timer.elapsed() < TL) {\n                auto kicked = rot;\n                randomKick(kicked, 8);\n                optimizeLocal(kicked, timer, min(TL, timer.elapsed() + 0.05));\n                long long sc2 = exactScore(kicked);\n                targeted1Cell(kicked, sc2, timer, min(TL, timer.elapsed() + 0.20));\n                if (sc2 > globalBestScore) {\n                    globalBestScore = sc2;\n                    globalBest = kicked;\n                }\n            }\n\n            trial++;\n        }\n\n        string ans(NN, '0');\n        for (int i = 0; i < NN; i++) ans[i] = char('0' + globalBest[i]);\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.readInput();\n    solver.solve();\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\nstatic constexpr int DI[4] = {-1, 1, 0, 0};\nstatic constexpr int DJ[4] = {0, 0, -1, 1};\nstatic constexpr char DC[4] = {'U', 'D', 'L', 'R'};\n\nint N, Tlim;\nvector<unsigned char> init_board;\nint init_empty;\n\ninline int opp(int d) { return d ^ 1; }\n\ninline int c2d(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\ninline bool can_move(int empty_pos, int d) {\n    int i = empty_pos / N, j = empty_pos % N;\n    int ni = i + DI[d], nj = j + DJ[d];\n    return 0 <= ni && ni < N && 0 <= nj && nj < N;\n}\n\ninline void apply_move(vector<unsigned char>& board, int& empty_pos, int d) {\n    int ei = empty_pos / N, ej = empty_pos % N;\n    int ni = ei + DI[d], nj = ej + DJ[d];\n    int np = ni * N + nj;\n    swap(board[empty_pos], board[np]);\n    empty_pos = np;\n}\n\nstruct Eval {\n    int largestTree;\n    int matchedEdges;\n    int largestComponent;\n    int cyclePenalty;\n};\n\nEval evaluate_board_detail(const vector<unsigned char>& board) {\n    int V = N * N;\n    static int g[100][4];\n    static int deg[100];\n    static unsigned char alive[100];\n    static unsigned char vis[100];\n\n    for (int p = 0; p < V; ++p) {\n        deg[p] = 0;\n        alive[p] = (board[p] != 0);\n        vis[p] = 0;\n    }\n\n    auto has = [&](int mask, int bit) -> bool { return (mask & bit) != 0; };\n\n    int matchedEdges = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int p = i * N + j;\n            if (!alive[p]) continue;\n            int m = board[p];\n            if (i + 1 < N) {\n                int q = (i + 1) * N + j;\n                if (alive[q] && has(m, 8) && has(board[q], 2)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                    ++matchedEdges;\n                }\n            }\n            if (j + 1 < N) {\n                int q = i * N + (j + 1);\n                if (alive[q] && has(m, 4) && has(board[q], 1)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                    ++matchedEdges;\n                }\n            }\n        }\n    }\n\n    int largestTree = 0;\n    int largestComponent = 0;\n    int cyclePenalty = 0;\n\n    int q[100];\n    for (int s = 0; s < V; ++s) {\n        if (!alive[s] || vis[s]) continue;\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = 1;\n        int vc = 0, sumdeg = 0;\n        while (head < tail) {\n            int v = q[head++];\n            ++vc;\n            sumdeg += deg[v];\n            for (int k = 0; k < deg[v]; ++k) {\n                int to = g[v][k];\n                if (!vis[to]) {\n                    vis[to] = 1;\n                    q[tail++] = to;\n                }\n            }\n        }\n        int ec = sumdeg / 2;\n        largestComponent = max(largestComponent, vc);\n        if (ec == vc - 1) largestTree = max(largestTree, vc);\n        if (ec > vc - 1) cyclePenalty += ec - (vc - 1);\n    }\n\n    return {largestTree, matchedEdges, largestComponent, cyclePenalty};\n}\n\ninline bool better_eval(const Eval& a, const Eval& b) {\n    if (a.largestTree != b.largestTree) return a.largestTree > b.largestTree;\n    if (a.matchedEdges != b.matchedEdges) return a.matchedEdges > b.matchedEdges;\n    if (a.largestComponent != b.largestComponent) return a.largestComponent > b.largestComponent;\n    if (a.cyclePenalty != b.cyclePenalty) return a.cyclePenalty < b.cyclePenalty;\n    return false;\n}\n\nstruct Candidate {\n    string ops;\n    int bestLen = 0;\n    Eval bestEval{0,0,0,0};\n};\n\ninline bool better_cand(const Candidate& a, const Candidate& b) {\n    if (better_eval(a.bestEval, b.bestEval)) return true;\n    if (better_eval(b.bestEval, a.bestEval)) return false;\n    return a.bestLen < b.bestLen;\n}\n\nmt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\nvoid replay_prefix(const string& ops, int upto, vector<unsigned char>& board, int& empty, int& prevDir) {\n    board = init_board;\n    empty = init_empty;\n    prevDir = -1;\n    for (int i = 0; i < upto; ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) break;\n        apply_move(board, empty, d);\n        prevDir = d;\n    }\n}\n\nCandidate evaluate_sequence(const string& ops) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n\n    Candidate res;\n    res.ops = ops;\n    res.bestLen = 0;\n    res.bestEval = evaluate_board_detail(board);\n\n    for (int i = 0; i < (int)ops.size(); ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) {\n            res.ops.resize(i);\n            break;\n        }\n        apply_move(board, empty, d);\n        Eval e = evaluate_board_detail(board);\n        if (better_eval(e, res.bestEval) ||\n            (!better_eval(res.bestEval, e) && i + 1 < res.bestLen)) {\n            res.bestEval = e;\n            res.bestLen = i + 1;\n        }\n    }\n    return res;\n}\n\nstring random_legal_suffix(int empty, int maxAdd, int prevDir = -1, bool prefer_no_back = true) {\n    string s;\n    s.reserve(maxAdd);\n    for (int step = 0; step < maxAdd; ++step) {\n        int cand[4], cnt = 0;\n        for (int d = 0; d < 4; ++d) {\n            if (!can_move(empty, d)) continue;\n            if (prefer_no_back && prevDir != -1 && d == opp(prevDir)) continue;\n            cand[cnt++] = d;\n        }\n        if (cnt == 0) {\n            for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n        }\n        int d = cand[rng() % cnt];\n        s.push_back(DC[d]);\n        int ei = empty / N, ej = empty % N;\n        int ni = ei + DI[d], nj = ej + DJ[d];\n        empty = ni * N + nj;\n        prevDir = d;\n    }\n    return s;\n}\n\nint greedy_choose_move(const vector<unsigned char>& board, int empty, int prevDir) {\n    Eval bestE{-1,-1,-1,(int)1e9};\n    int bestD = -1;\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n    shuffle(cand, cand + cnt, rng);\n\n    for (int ii = 0; ii < cnt; ++ii) {\n        int d = cand[ii];\n        vector<unsigned char> nb = board;\n        int ne = empty;\n        apply_move(nb, ne, d);\n        Eval e = evaluate_board_detail(nb);\n        if (bestD == -1 || better_eval(e, bestE) ||\n            (!better_eval(bestE, e) && prevDir != -1 && bestD == opp(prevDir) && d != opp(prevDir))) {\n            bestE = e;\n            bestD = d;\n        }\n    }\n    return bestD;\n}\n\nint greedy_choose_move2(const vector<unsigned char>& board, int empty, int prevDir) {\n    bool first = true;\n    Eval bestFirst{-1,-1,-1,(int)1e9};\n    Eval bestSecond{-1,-1,-1,(int)1e9};\n    int bestD = -1;\n\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n    shuffle(cand, cand + cnt, rng);\n\n    for (int ii = 0; ii < cnt; ++ii) {\n        int d = cand[ii];\n        vector<unsigned char> b1 = board;\n        int e1 = empty;\n        apply_move(b1, e1, d);\n        Eval eFirst = evaluate_board_detail(b1);\n\n        Eval eSecond = eFirst;\n        bool childFirst = true;\n        int cand2[4], cnt2 = 0;\n        for (int d2 = 0; d2 < 4; ++d2) {\n            if (!can_move(e1, d2)) continue;\n            cand2[cnt2++] = d2;\n        }\n        for (int jj = 0; jj < cnt2; ++jj) {\n            int d2 = cand2[jj];\n            vector<unsigned char> b2 = b1;\n            int e2 = e1;\n            apply_move(b2, e2, d2);\n            Eval eChild = evaluate_board_detail(b2);\n            if (childFirst || better_eval(eChild, eSecond)) {\n                childFirst = false;\n                eSecond = eChild;\n            }\n        }\n\n        if (first ||\n            better_eval(eSecond, bestSecond) ||\n            (!better_eval(bestSecond, eSecond) && better_eval(eFirst, bestFirst)) ||\n            (!better_eval(bestSecond, eSecond) && !better_eval(eSecond, bestSecond) &&\n             !better_eval(bestFirst, eFirst) && prevDir != -1 && bestD == opp(prevDir) && d != opp(prevDir))) {\n            first = false;\n            bestFirst = eFirst;\n            bestSecond = eSecond;\n            bestD = d;\n        }\n    }\n    return bestD;\n}\n\nstring mixed_suffix(vector<unsigned char> board, int empty, int len, int prevDir) {\n    string ops;\n    ops.reserve(len);\n    for (int step = 0; step < len; ++step) {\n        int mode = rng() % 100;\n        int d = -1;\n        if (mode < 35) {\n            d = greedy_choose_move(board, empty, prevDir);\n        } else if (mode < 55) {\n            d = greedy_choose_move2(board, empty, prevDir);\n        } else {\n            int cand[4], cnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                if (!can_move(empty, k)) continue;\n                if (prevDir != -1 && k == opp(prevDir) && mode < 85) continue;\n                cand[cnt++] = k;\n            }\n            if (cnt == 0) for (int k = 0; k < 4; ++k) if (can_move(empty, k)) cand[cnt++] = k;\n            d = cand[rng() % cnt];\n        }\n        ops.push_back(DC[d]);\n        apply_move(board, empty, d);\n        prevDir = d;\n    }\n    return ops;\n}\n\nCandidate make_random_candidate() {\n    uniform_int_distribution<int> lenDist(0, Tlim);\n    int L = lenDist(rng);\n    string ops;\n    if ((rng() % 100) < 50) ops = random_legal_suffix(init_empty, L, -1, true);\n    else ops = mixed_suffix(init_board, init_empty, L, -1);\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_cut_regrow(const Candidate& base) {\n    int L = (int)base.ops.size();\n    int cut = 0;\n    if (L > 0) {\n        int mode = rng() % 6;\n        if (mode == 0) {\n            uniform_int_distribution<int> dist(0, L);\n            cut = dist(rng);\n        } else if (mode == 1) {\n            int lo = max(0, base.bestLen - 10), hi = min(L, base.bestLen + 10);\n            uniform_int_distribution<int> dist(lo, hi);\n            cut = dist(rng);\n        } else if (mode == 2) {\n            cut = base.bestLen;\n        } else if (mode == 3) {\n            uniform_int_distribution<int> dist(max(0, base.bestLen - 30), min(L, base.bestLen + 5));\n            cut = dist(rng);\n        } else {\n            uniform_int_distribution<int> dist(0, min(L, base.bestLen));\n            cut = dist(rng);\n        }\n    }\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, cut, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, cut);\n    int rem = Tlim - cut;\n\n    int add;\n    int lenMode = rng() % 100;\n    if (lenMode < 35) add = min(rem, 5 + (int)(rng() % 20));\n    else if (lenMode < 75) add = rng() % (rem + 1);\n    else add = min(rem, max(0, base.bestLen - cut) + (int)(rng() % 25));\n\n    int genMode = rng() % 100;\n    if (genMode < 50) ops += mixed_suffix(board, empty, add, prevDir);\n    else ops += random_legal_suffix(empty, add, prevDir, true);\n\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_edit(const Candidate& base) {\n    if (base.ops.empty()) return make_random_candidate();\n    int L = (int)base.ops.size();\n    int pos = rng() % L;\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, pos, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, pos);\n\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n    shuffle(cand, cand + cnt, rng);\n\n    int chosen = cand[0];\n    int chooser = rng() % 100;\n    if (chooser < 50) {\n        Eval bestE{-1,-1,-1,(int)1e9};\n        for (int ii = 0; ii < cnt; ++ii) {\n            int d = cand[ii];\n            vector<unsigned char> nb = board;\n            int ne = empty;\n            apply_move(nb, ne, d);\n            Eval e = evaluate_board_detail(nb);\n            if (ii == 0 || better_eval(e, bestE)) {\n                bestE = e;\n                chosen = d;\n            }\n        }\n    } else if (chooser < 80) {\n        chosen = greedy_choose_move2(board, empty, prevDir);\n    }\n\n    ops.push_back(DC[chosen]);\n    apply_move(board, empty, chosen);\n    prevDir = chosen;\n\n    int remCap = Tlim - (int)ops.size();\n    int tail = remCap > 0 ? (rng() % (remCap + 1)) : 0;\n    if ((rng() % 100) < 60) ops += mixed_suffix(board, empty, tail, prevDir);\n    else ops += random_legal_suffix(empty, tail, prevDir, true);\n\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_insert_delete(const Candidate& base) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n    int prevDir = -1;\n\n    string ops;\n    ops.reserve(Tlim);\n\n    int i = 0;\n    while (i < (int)base.ops.size() && (int)ops.size() < Tlim) {\n        if ((rng() % 100) < 12 && (int)ops.size() < Tlim) {\n            int chooser = rng() % 100;\n            int d;\n            if (chooser < 45) d = greedy_choose_move(board, empty, prevDir);\n            else if (chooser < 65) d = greedy_choose_move2(board, empty, prevDir);\n            else {\n                int cand[4], cnt = 0;\n                for (int k = 0; k < 4; ++k) if (can_move(empty, k)) cand[cnt++] = k;\n                d = cand[rng() % cnt];\n            }\n            ops.push_back(DC[d]);\n            apply_move(board, empty, d);\n            prevDir = d;\n        }\n\n        if ((rng() % 100) < 16) {\n            ++i;\n            continue;\n        }\n\n        int d = c2d(base.ops[i]);\n        if (!can_move(empty, d)) break;\n        ops.push_back(base.ops[i]);\n        apply_move(board, empty, d);\n        prevDir = d;\n        ++i;\n    }\n\n    int rem = Tlim - (int)ops.size();\n    int add = rem > 0 ? (rng() % (min(rem, 30) + 1)) : 0;\n    if ((rng() % 100) < 60) ops += mixed_suffix(board, empty, add, prevDir);\n    else ops += random_legal_suffix(empty, add, prevDir, true);\n\n    return evaluate_sequence(ops);\n}\n\nCandidate intensify_bestprefix(const Candidate& base) {\n    int cut = base.bestLen;\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, cut, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, cut);\n    int rem = Tlim - cut;\n    int add = 0;\n    int mode = rng() % 100;\n    if (mode < 50) add = min(rem, 8 + (int)(rng() % 24));\n    else if (mode < 85) add = min(rem, 20 + (int)(rng() % 40));\n    else add = rng() % (rem + 1);\n\n    ops += mixed_suffix(board, empty, add, prevDir);\n    return evaluate_sequence(ops);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    init_board.assign(N * N, 0);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            char c = s[j];\n            int v = ('0' <= c && c <= '9') ? c - '0' : 10 + (c - 'a');\n            init_board[i * N + j] = (unsigned char)v;\n            if (v == 0) init_empty = i * N + j;\n        }\n    }\n\n    Timer timer;\n    const double TL = 2.90;\n\n    const int BEAM = 18;\n    vector<Candidate> pool;\n    pool.reserve(BEAM * 3);\n\n    Candidate best;\n    best.ops = \"\";\n    best.bestLen = 0;\n    best.bestEval = evaluate_board_detail(init_board);\n    pool.push_back(best);\n\n    while ((int)pool.size() < BEAM && timer.elapsed() < 0.30) {\n        Candidate c = make_random_candidate();\n        if (better_cand(c, best)) best = c;\n        pool.push_back(c);\n    }\n\n    auto shrink_pool = [&]() {\n        sort(pool.begin(), pool.end(), better_cand);\n        vector<Candidate> np;\n        for (auto& c : pool) {\n            bool dup = false;\n            for (auto& x : np) {\n                if (c.bestLen == x.bestLen &&\n                    c.bestEval.largestTree == x.bestEval.largestTree &&\n                    c.bestEval.matchedEdges == x.bestEval.matchedEdges &&\n                    c.ops == x.ops) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) np.push_back(c);\n            if ((int)np.size() >= BEAM) break;\n        }\n        pool.swap(np);\n        if (!pool.empty() && better_cand(pool[0], best)) best = pool[0];\n    };\n\n    shrink_pool();\n\n    while (timer.elapsed() < TL) {\n        int ps = pool.size();\n        int r = rng() % 100;\n        int idx;\n        if (r < 55) idx = rng() % min(6, ps);\n        else if (r < 85) idx = rng() % min(12, ps);\n        else idx = rng() % ps;\n\n        Candidate cand;\n        int typ = rng() % 100;\n        if (typ < 10) cand = make_random_candidate();\n        else if (typ < 45) cand = mutate_cut_regrow(pool[idx]);\n        else if (typ < 68) cand = mutate_edit(pool[idx]);\n        else if (typ < 86) cand = mutate_insert_delete(pool[idx]);\n        else cand = intensify_bestprefix(pool[idx]);\n\n        pool.push_back(cand);\n        if (better_cand(cand, best)) best = cand;\n\n        if ((int)pool.size() >= BEAM * 2) shrink_pool();\n    }\n\n    cout << best.ops.substr(0, best.bestLen) << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nstatic const long long LIM = 1000000000LL;\nstatic const double PI = acos(-1.0);\n\nstatic inline long long clampLL(long long x) {\n    return max(-LIM, min(LIM, x));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    array<int, 11> a{};\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // Exact DP for the best partition under the \"all cuts parallel\" model.\n    // dp[s][u] = best matched count using exactly s strawberries in useful pieces\n    // and exactly u useful pieces.\n    //\n    // We build it by sizes 1..10 with bounded multiplicities.\n    vector<vector<int>> dp(N + 1, vector<int>(K + 2, -1e9));\n    struct Prev {\n        short ps, pu, d;\n    };\n    vector<vector<Prev>> prv(N + 1, vector<Prev>(K + 2, {-1, -1, -1}));\n\n    dp[0][0] = 0;\n\n    for (int d = 1; d <= 10; d++) {\n        // Add up to a[d] beneficial pieces of size d.\n        for (int rep = 0; rep < a[d]; rep++) {\n            auto ndp = dp;\n            auto nprv = prv;\n            for (int s = 0; s + d <= N; s++) {\n                for (int u = 0; u + 1 <= K + 1; u++) {\n                    if (dp[s][u] < 0) continue;\n                    if (dp[s][u] + 1 > ndp[s + d][u + 1]) {\n                        ndp[s + d][u + 1] = dp[s][u] + 1;\n                        nprv[s + d][u + 1] = {(short)s, (short)u, (short)d};\n                    }\n                }\n            }\n            dp.swap(ndp);\n            prv.swap(nprv);\n        }\n    }\n\n    // Find best feasible state.\n    // If s == N, total pieces = u.\n    // If s < N, we need one leftover piece, so total pieces = u + 1 <= K+1.\n    int bestScore = -1, bestS = 0, bestU = 0;\n    for (int s = 0; s <= N; s++) {\n        for (int u = 0; u <= K + 1; u++) {\n            if (dp[s][u] < 0) continue;\n            bool ok = false;\n            if (s == N) {\n                ok = (u <= K + 1);\n            } else {\n                ok = (u + 1 <= K + 1);\n            }\n            if (!ok) continue;\n            if (dp[s][u] > bestScore) {\n                bestScore = dp[s][u];\n                bestS = s;\n                bestU = u;\n            }\n        }\n    }\n\n    // Reconstruct useful piece sizes.\n    vector<int> useful;\n    int cs = bestS, cu = bestU;\n    while (cs != 0 || cu != 0) {\n        auto pr = prv[cs][cu];\n        if (pr.d == -1) break;\n        useful.push_back(pr.d);\n        cs = pr.ps;\n        cu = pr.pu;\n    }\n    reverse(useful.begin(), useful.end());\n\n    // Add leftover if any.\n    int used = 0;\n    for (int x : useful) used += x;\n    vector<int> groups = useful;\n    if (used < N) groups.push_back(N - used);\n\n    // To be safe, pieces <= 101\n    while ((int)groups.size() > K + 1) {\n        int x = groups.back(); groups.pop_back();\n        groups.back() += x;\n    }\n\n    // Choose a fixed direction and sort by projection.\n    // Since any direction works for the parallel partition model, this is enough.\n    double theta = 0.3141592653589793; // arbitrary, not axis-aligned\n    double c = cos(theta), s = sin(theta);\n\n    vector<double> proj(N);\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    for (int i = 0; i < N; i++) {\n        proj[i] = p[i].x * c + p[i].y * s;\n    }\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (proj[i] != proj[j]) return proj[i] < proj[j];\n        return i < j;\n    });\n\n    // Place cuts between cumulative group boundaries.\n    vector<double> alphas;\n    int pref = 0;\n    for (int i = 0; i + 1 < (int)groups.size(); i++) {\n        pref += groups[i];\n        if (pref <= 0 || pref >= N) continue;\n        double t1 = proj[ord[pref - 1]];\n        double t2 = proj[ord[pref]];\n        alphas.push_back((t1 + t2) * 0.5);\n    }\n\n    cout << alphas.size() << '\\n';\n\n    const double T = 200000.0;\n    for (double alpha : alphas) {\n        // Line: c*x + s*y = alpha\n        // Point on line: alpha*(c,s)\n        // Direction vector: (-s,c)\n        double x0 = alpha * c;\n        double y0 = alpha * s;\n        double dx = -s, dy = c;\n\n        long long x1 = llround(x0 + T * dx);\n        long long y1 = llround(y0 + T * dy);\n        long long x2 = llround(x0 - T * dx);\n        long long y2 = llround(y0 - T * dy);\n\n        x1 = clampLL(x1);\n        y1 = clampLL(y1);\n        x2 = clampLL(x2);\n        y2 = clampLL(y2);\n\n        if (x1 == x2 && y1 == y2) {\n            if (x2 < LIM) x2++;\n            else x2--;\n        }\n\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\nstruct Op {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nstruct Candidate {\n    double score;\n    Op op;\n};\n\nstruct Solver {\n    int N, M, c;\n    vector<pair<int,int>> initDots;\n    long long Ssum;\n\n    Solver(int N_, int M_, const vector<pair<int,int>>& pts) : N(N_), M(M_), initDots(pts) {\n        c = (N - 1) / 2;\n        Ssum = 0;\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            long long dx = x - c, dy = y - c;\n            Ssum += dx * dx + dy * dy + 1;\n        }\n    }\n\n    int weight(int x, int y) const {\n        int dx = x - c, dy = y - c;\n        return dx * dx + dy * dy + 1;\n    }\n\n    struct State {\n        int N;\n        vector<vector<char>> dot;\n        vector<vector<char>> usedH, usedV, usedD1, usedD2;\n        vector<pair<int,int>> dots;\n        vector<Op> ops;\n        long long wsum = 0;\n        State(int N_=0): N(N_) {}\n    };\n\n    struct Undo {\n        vector<tuple<int,int,int>> segs; // kind, a, b\n        bool addedDot = false;\n        int x = -1, y = -1;\n        long long addW = 0;\n        bool pushedDot = false;\n        bool pushedOp = false;\n    };\n\n    State initial_state() const {\n        State st(N);\n        st.dot.assign(N, vector<char>(N, 0));\n        st.usedH.assign(max(0, N - 1), vector<char>(N, 0));\n        st.usedV.assign(N, vector<char>(max(0, N - 1), 0));\n        st.usedD1.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        st.usedD2.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        for (auto [x, y] : initDots) {\n            st.dot[x][y] = 1;\n            st.dots.push_back({x, y});\n            st.wsum += weight(x, y);\n        }\n        return st;\n    }\n\n    bool inside(int x, int y) const {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    }\n\n    bool getSegUsed(const State& st, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            return st.usedV[x1][y1];\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            return st.usedH[x1][y1];\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            return st.usedD1[x1][y1];\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            return st.usedD2[x1][yl];\n        }\n    }\n\n    void setSegUsed(State& st, Undo* ud, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            st.usedV[x1][y1] = 1;\n            if (ud) ud->segs.push_back({1, x1, y1});\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            st.usedH[x1][y1] = 1;\n            if (ud) ud->segs.push_back({0, x1, y1});\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            st.usedD1[x1][y1] = 1;\n            if (ud) ud->segs.push_back({2, x1, y1});\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            st.usedD2[x1][yl] = 1;\n            if (ud) ud->segs.push_back({3, x1, yl});\n        }\n    }\n\n    bool edge_clear_and_unused(const State& st, int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            if (getSegUsed(st, x, y, nx, ny)) return false;\n            if (t + 1 < len && st.dot[nx][ny]) return false;\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void mark_edge(State& st, int ax, int ay, int bx, int by, Undo* ud=nullptr) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            setSegUsed(st, ud, x, y, nx, ny);\n            x = nx; y = ny;\n        }\n    }\n\n    bool legal_rect(const State& st, const Op& op) const {\n        int x1=op.x1,y1=op.y1,x2=op.x2,y2=op.y2,x3=op.x3,y3=op.y3,x4=op.x4,y4=op.y4;\n        if (!inside(x1,y1)||!inside(x2,y2)||!inside(x3,y3)||!inside(x4,y4)) return false;\n        if (st.dot[x1][y1]) return false;\n        if (!st.dot[x2][y2] || !st.dot[x3][y3] || !st.dot[x4][y4]) return false;\n\n        auto ok_edge = [&](int ax, int ay, int bx, int by) {\n            int dx = bx - ax, dy = by - ay;\n            if (dx == 0 && dy != 0) return true;\n            if (dy == 0 && dx != 0) return true;\n            if (abs(dx) == abs(dy) && dx != 0) return true;\n            return false;\n        };\n        if (!ok_edge(x1,y1,x2,y2) || !ok_edge(x2,y2,x3,y3) ||\n            !ok_edge(x3,y3,x4,y4) || !ok_edge(x4,y4,x1,y1)) return false;\n\n        int ax = x2 - x1, ay = y2 - y1;\n        int bx = x4 - x1, by = y4 - y1;\n        if ((ax == 0 && ay == 0) || (bx == 0 && by == 0)) return false;\n        if (ax * bx + ay * by != 0) return false;\n        if (x3 != x2 + bx || y3 != y2 + by) return false;\n        if (x3 != x4 + ax || y3 != y4 + ay) return false;\n\n        if (!edge_clear_and_unused(st, x1,y1,x2,y2)) return false;\n        if (!edge_clear_and_unused(st, x2,y2,x3,y3)) return false;\n        if (!edge_clear_and_unused(st, x3,y3,x4,y4)) return false;\n        if (!edge_clear_and_unused(st, x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void apply(State& st, const Op& op) const {\n        st.dot[op.x1][op.y1] = 1;\n        st.dots.push_back({op.x1, op.y1});\n        st.wsum += weight(op.x1, op.y1);\n        mark_edge(st, op.x1, op.y1, op.x2, op.y2);\n        mark_edge(st, op.x2, op.y2, op.x3, op.y3);\n        mark_edge(st, op.x3, op.y3, op.x4, op.y4);\n        mark_edge(st, op.x4, op.y4, op.x1, op.y1);\n        st.ops.push_back(op);\n    }\n\n    void apply_undo(State& st, const Op& op, Undo& ud, bool recordOp=false) const {\n        ud.segs.clear();\n        ud.addedDot = true;\n        ud.x = op.x1;\n        ud.y = op.y1;\n        ud.addW = weight(op.x1, op.y1);\n\n        st.dot[op.x1][op.y1] = 1;\n        st.wsum += ud.addW;\n        st.dots.push_back({op.x1, op.y1});\n        ud.pushedDot = true;\n\n        mark_edge(st, op.x1, op.y1, op.x2, op.y2, &ud);\n        mark_edge(st, op.x2, op.y2, op.x3, op.y3, &ud);\n        mark_edge(st, op.x3, op.y3, op.x4, op.y4, &ud);\n        mark_edge(st, op.x4, op.y4, op.x1, op.y1, &ud);\n\n        if (recordOp) {\n            st.ops.push_back(op);\n            ud.pushedOp = true;\n        } else {\n            ud.pushedOp = false;\n        }\n    }\n\n    void revert(State& st, const Undo& ud) const {\n        for (int i = (int)ud.segs.size() - 1; i >= 0; i--) {\n            auto [kind, a, b] = ud.segs[i];\n            if (kind == 0) st.usedH[a][b] = 0;\n            else if (kind == 1) st.usedV[a][b] = 0;\n            else if (kind == 2) st.usedD1[a][b] = 0;\n            else st.usedD2[a][b] = 0;\n        }\n        if (ud.addedDot) {\n            st.dot[ud.x][ud.y] = 0;\n            st.wsum -= ud.addW;\n        }\n        if (ud.pushedDot) st.dots.pop_back();\n        if (ud.pushedOp) st.ops.pop_back();\n    }\n\n    long long calc_score(const State& st) const {\n        double val = 1e6 * (double)(N * N) / (double)M * (double)st.wsum / (double)Ssum;\n        return llround(val);\n    }\n\n    double eval_small(const Op& op, int mode) const {\n        int w = weight(op.x1, op.y1);\n        int l1 = max(abs(op.x2-op.x1), abs(op.y2-op.y1));\n        int l2 = max(abs(op.x4-op.x1), abs(op.y4-op.y1));\n        int per = l1 + l2;\n        int dist = abs(op.x1 - c) + abs(op.y1 - c);\n        switch (mode) {\n            case 0: return 800.0 * w - 350.0 * per + 15.0 * dist;\n            case 1: return 700.0 * w - 420.0 * per + 10.0 * dist;\n            case 2: return 1000.0 * w - 300.0 * per + 20.0 * dist;\n            case 3: return 880.0 * w - 330.0 * per + 22.0 * dist;\n            case 4: return 760.0 * w - 390.0 * per + 30.0 * dist;\n            default:return 850.0 * w - 360.0 * per + 18.0 * dist;\n        }\n    }\n\n    double eval_large(const Op& op, int mode, int opCount, double noise=0.0) const {\n        int w = weight(op.x1, op.y1);\n        int l1 = max(abs(op.x2-op.x1), abs(op.y2-op.y1));\n        int l2 = max(abs(op.x4-op.x1), abs(op.y4-op.y1));\n        int per = l1 + l2;\n        int dist = abs(op.x1 - c) + abs(op.y1 - c);\n\n        double relax = (opCount >= N / 2 ? 0.85 : 1.0);\n        if (opCount >= N) relax = 0.72;\n\n        switch (mode) {\n            case 0: return 2200.0 * w - (150.0 * relax) * per + 35.0 * dist + noise;\n            case 1: return 1800.0 * w - (200.0 * relax) * per + 25.0 * dist + noise;\n            case 2: return 3000.0 * w - (110.0 * relax) * per + 50.0 * dist + noise;\n            case 3: return 2500.0 * w - (135.0 * relax) * per + 42.0 * dist + noise;\n            case 4: return 2050.0 * w - (170.0 * relax) * per + 65.0 * dist + noise;\n            default:return 2400.0 * w - (140.0 * relax) * per + 40.0 * dist + noise;\n        }\n    }\n\n    bool closure_small(State& st, int mode, int maxLen, double endTime, const Timer& timer) const {\n        vector<Candidate> top;\n        auto push_top = [&](double sc, const Op& op) {\n            top.push_back({sc, op});\n            sort(top.begin(), top.end(), [](const Candidate& a, const Candidate& b){ return a.score > b.score; });\n            if ((int)top.size() > 8) top.pop_back();\n        };\n\n        for (int x1 = 0; x1 < N; x1++) {\n            if (timer.elapsed() > endTime) break;\n            for (int y1 = 0; y1 < N; y1++) {\n                if (st.dot[x1][y1]) continue;\n\n                for (int dx = 1; dx <= maxLen; dx++) for (int dy = 1; dy <= maxLen; dy++) {\n                    Op cand[4] = {\n                        {x1,y1, x1+dx,y1, x1+dx,y1+dy, x1,y1+dy},\n                        {x1,y1, x1,y1+dy, x1-dx,y1+dy, x1-dx,y1},\n                        {x1,y1, x1-dx,y1, x1-dx,y1-dy, x1,y1-dy},\n                        {x1,y1, x1,y1-dy, x1+dx,y1-dy, x1+dx,y1}\n                    };\n                    for (int k = 0; k < 4; k++) {\n                        if (legal_rect(st, cand[k])) push_top(eval_small(cand[k], mode), cand[k]);\n                    }\n                }\n\n                for (int d1 = 1; d1 <= maxLen; d1++) for (int d2 = 1; d2 <= maxLen; d2++) {\n                    static const int sgn[4][2] = {{1,1},{1,-1},{-1,1},{-1,-1}};\n                    for (int k = 0; k < 4; k++) {\n                        int ax = sgn[k][0] * d1, ay = sgn[k][1] * d1;\n                        int bx1 = -sgn[k][1] * d2, by1 =  sgn[k][0] * d2;\n                        int bx2 =  sgn[k][1] * d2, by2 = -sgn[k][0] * d2;\n                        Op op1{x1,y1, x1+ax,y1+ay, x1+ax+bx1,y1+ay+by1, x1+bx1,y1+by1};\n                        Op op2{x1,y1, x1+ax,y1+ay, x1+ax+bx2,y1+ay+by2, x1+bx2,y1+by2};\n                        if (inside(op1.x2,op1.y2)&&inside(op1.x3,op1.y3)&&inside(op1.x4,op1.y4) && legal_rect(st, op1)) {\n                            push_top(eval_small(op1, mode), op1);\n                        }\n                        if (inside(op2.x2,op2.y2)&&inside(op2.x3,op2.y3)&&inside(op2.x4,op2.y4) && legal_rect(st, op2)) {\n                            push_top(eval_small(op2, mode), op2);\n                        }\n                    }\n                }\n            }\n        }\n\n        if (top.empty()) return false;\n\n        double bestVal = -1e100;\n        int bestIdx = 0;\n        Undo ud1, ud2;\n        for (int i = 0; i < (int)top.size(); i++) {\n            apply_undo(st, top[i].op, ud1, false);\n            double future = 0.0;\n\n            Candidate second{-1e100, {}};\n            for (int x = max(0, top[i].op.x1 - 3); x <= min(N - 1, top[i].op.x1 + 3); x++) {\n                for (int y = max(0, top[i].op.y1 - 3); y <= min(N - 1, top[i].op.y1 + 3); y++) {\n                    if (st.dot[x][y]) continue;\n                    for (int dx = 1; dx <= 2; dx++) for (int dy = 1; dy <= 2; dy++) {\n                        Op cands[4] = {\n                            {x,y, x+dx,y, x+dx,y+dy, x,y+dy},\n                            {x,y, x,y+dy, x-dx,y+dy, x-dx,y},\n                            {x,y, x-dx,y, x-dx,y-dy, x,y-dy},\n                            {x,y, x,y-dy, x+dx,y-dy, x+dx,y}\n                        };\n                        for (int k = 0; k < 4; k++) {\n                            if (legal_rect(st, cands[k])) {\n                                double sc = eval_small(cands[k], mode);\n                                if (sc > second.score) second = {sc, cands[k]};\n                            }\n                        }\n                    }\n                }\n            }\n            if (second.score > -1e50) future = 0.35 * second.score;\n            double total = top[i].score + future;\n            if (total > bestVal) {\n                bestVal = total;\n                bestIdx = i;\n            }\n            revert(st, ud1);\n        }\n\n        apply(st, top[bestIdx].op);\n        return true;\n    }\n\n    vector<Candidate> enumerate_structure_candidates(const State& st, int mode, mt19937& rng, int capDots, int maxD) const {\n        vector<Candidate> cand;\n        vector<pair<int,int>> pts = st.dots;\n\n        if ((int)pts.size() > capDots) {\n            vector<pair<int,int>> heavy = pts;\n            sort(heavy.begin(), heavy.end(), [&](auto& a, auto& b){\n                return weight(a.first, a.second) > weight(b.first, b.second);\n            });\n            vector<pair<int,int>> sel;\n            int keep = capDots * 3 / 4;\n            keep = min(keep, (int)heavy.size());\n            for (int i = 0; i < keep; i++) sel.push_back(heavy[i]);\n\n            shuffle(pts.begin(), pts.end(), rng);\n            for (auto &p : pts) {\n                if ((int)sel.size() >= capDots) break;\n                sel.push_back(p);\n            }\n            pts.swap(sel);\n        }\n\n        unordered_map<int, vector<int>> byX, byY;\n        byX.reserve(2 * pts.size() + 10);\n        byY.reserve(2 * pts.size() + 10);\n        for (auto [x, y] : pts) {\n            byX[x].push_back(y);\n            byY[y].push_back(x);\n        }\n\n        auto add_if = [&](const Op& op) {\n            if (legal_rect(st, op)) {\n                double noise = uniform_real_distribution<double>(0.0, 1e-7)(rng);\n                cand.push_back({eval_large(op, mode, (int)st.ops.size(), noise), op});\n            }\n        };\n\n        for (auto [x2, y2] : pts) {\n            auto itx = byX.find(x2);\n            auto ity = byY.find(y2);\n            if (itx == byX.end() || ity == byY.end()) continue;\n\n            auto ys = itx->second;\n            auto xs = ity->second;\n            if ((int)ys.size() > 18) {\n                shuffle(ys.begin(), ys.end(), rng);\n                ys.resize(18);\n            }\n            if ((int)xs.size() > 18) {\n                shuffle(xs.begin(), xs.end(), rng);\n                xs.resize(18);\n            }\n\n            for (int y4 : ys) {\n                if (y4 == y2) continue;\n                for (int x1 : xs) {\n                    if (x1 == x2) continue;\n                    int y1 = y4;\n                    if (!inside(x1,y1)) continue;\n                    if (!st.dot[x2][y4] || !st.dot[x1][y2]) continue;\n                    Op op{x1,y1, x2,y4, x2,y2, x1,y2};\n                    add_if(op);\n                }\n            }\n        }\n\n        for (auto [x2, y2] : pts) {\n            for (int d = 1; d <= maxD; d++) {\n                static const int sx[4] = {1,1,-1,-1};\n                static const int sy[4] = {1,-1,1,-1};\n                for (int k = 0; k < 4; k++) {\n                    int ax = sx[k] * d, ay = sy[k] * d;\n                    int x1 = x2 - ax, y1 = y2 - ay;\n\n                    int bx = -ay, by = ax;\n                    Op op1{x1,y1, x2,y2, x2+bx,y2+by, x1+bx,y1+by};\n                    if (inside(op1.x1,op1.y1)&&inside(op1.x3,op1.y3)&&inside(op1.x4,op1.y4)) add_if(op1);\n\n                    bx = ay; by = -ax;\n                    Op op2{x1,y1, x2,y2, x2+bx,y2+by, x1+bx,y1+by};\n                    if (inside(op2.x1,op2.y1)&&inside(op2.x3,op2.y3)&&inside(op2.x4,op2.y4)) add_if(op2);\n                }\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b){\n            if (a.op.x1 != b.op.x1) return a.op.x1 < b.op.x1;\n            if (a.op.y1 != b.op.y1) return a.op.y1 < b.op.y1;\n            if (a.op.x2 != b.op.x2) return a.op.x2 < b.op.x2;\n            if (a.op.y2 != b.op.y2) return a.op.y2 < b.op.y2;\n            if (a.op.x3 != b.op.x3) return a.op.x3 < b.op.x3;\n            if (a.op.y3 != b.op.y3) return a.op.y3 < b.op.y3;\n            if (a.op.x4 != b.op.x4) return a.op.x4 < b.op.x4;\n            if (a.op.y4 != b.op.y4) return a.op.y4 < b.op.y4;\n            return a.score > b.score;\n        });\n\n        vector<Candidate> uniq;\n        uniq.reserve(cand.size());\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (i == 0 || memcmp(&cand[i].op, &cand[i-1].op, sizeof(Op)) != 0) uniq.push_back(cand[i]);\n        }\n\n        sort(uniq.begin(), uniq.end(), [](const Candidate& a, const Candidate& b){\n            return a.score > b.score;\n        });\n        if ((int)uniq.size() > 280) uniq.resize(280);\n        return uniq;\n    }\n\n    double best_followup_value(State& st, int mode, mt19937& rng, int topSecond, int maxD) const {\n        auto cand2 = enumerate_structure_candidates(st, mode, rng, 180, maxD);\n        double best = 0.0;\n        int lim = min<int>(topSecond, cand2.size());\n        for (int i = 0; i < lim; i++) {\n            if (legal_rect(st, cand2[i].op)) best = max(best, cand2[i].score);\n        }\n        return best;\n    }\n\n    bool broad_step_with_lookahead(State& st, int mode, mt19937& rng, double timeBudgetFactor, int maxD) const {\n        auto cand = enumerate_structure_candidates(st, mode, rng, 230, maxD);\n        if (cand.empty()) return false;\n\n        bool useLookahead = timeBudgetFactor > 0.18;\n        if (!useLookahead) {\n            for (int i = 0; i < min<int>(18, cand.size()); i++) {\n                if (legal_rect(st, cand[i].op)) {\n                    apply(st, cand[i].op);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        int firstLim = min<int>((timeBudgetFactor > 0.55 ? 8 : 5), cand.size());\n        int secondLim = (timeBudgetFactor > 0.55 ? 10 : 6);\n\n        double bestVal = -1e100;\n        int bestIdx = -1;\n        Undo ud;\n\n        for (int i = 0; i < firstLim; i++) {\n            if (!legal_rect(st, cand[i].op)) continue;\n            apply_undo(st, cand[i].op, ud, false);\n            double future = best_followup_value(st, mode, rng, secondLim, max(4, maxD - 2));\n            double total = cand[i].score + 0.45 * future;\n            if (total > bestVal) {\n                bestVal = total;\n                bestIdx = i;\n            }\n            revert(st, ud);\n        }\n\n        if (bestIdx == -1) {\n            for (int i = 0; i < min<int>(20, cand.size()); i++) {\n                if (legal_rect(st, cand[i].op)) {\n                    apply(st, cand[i].op);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        apply(st, cand[bestIdx].op);\n        return true;\n    }\n\n    State run_one(int mode, uint64_t seed, double endTime, const Timer& timer) const {\n        mt19937 rng((uint32_t)seed);\n        State st = initial_state();\n\n        int smallLen = (mode == 1 ? 4 : (mode == 4 ? 2 : 3));\n        int closureLimit = (mode == 4 ? 700 : 1000);\n\n        while (closureLimit-- > 0 && timer.elapsed() < endTime * 0.42) {\n            if (!closure_small(st, mode, smallLen, endTime * 0.42, timer)) break;\n        }\n\n        int stagnation = 0;\n        int maxD = (mode == 1 ? 8 : mode == 2 ? 12 : mode == 4 ? 7 : 10);\n\n        while (timer.elapsed() < endTime) {\n            double progress = timer.elapsed() / endTime;\n            bool moved = broad_step_with_lookahead(st, mode, rng, 1.0 - progress, maxD);\n\n            if (!moved) {\n                stagnation++;\n                if (stagnation >= 3) break;\n                if (!closure_small(st, mode, 2, endTime, timer)) {\n                    if (stagnation >= 2) break;\n                } else {\n                    stagnation = 0;\n                }\n            } else {\n                stagnation = 0;\n            }\n        }\n\n        return st;\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    vector<pair<int,int>> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].first >> pts[i].second;\n\n    Timer timer;\n    Solver solver(N, M, pts);\n\n    auto best = solver.initial_state();\n    long long bestScore = solver.calc_score(best);\n\n    int iter = 0;\n    const int MODE_CNT = 5;\n\n    while (timer.elapsed() < 4.82) {\n        double remain = 4.90 - timer.elapsed();\n        if (remain < 0.08) break;\n\n        int mode = iter % MODE_CNT;\n        double slice;\n        if (iter < MODE_CNT) slice = min(remain, 0.72);\n        else if (iter < 3 * MODE_CNT) slice = min(remain, 0.38);\n        else slice = min(remain, 0.22);\n\n        uint64_t seed = 1234567ULL + 100003ULL * iter + 10000019ULL * mode + 911382323ULL;\n\n        auto st = solver.run_one(mode, seed, timer.elapsed() + slice, timer);\n        long long sc = solver.calc_score(st);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = move(st);\n        }\n        iter++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (auto &op : best.ops) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << ' '\n             << op.x3 << ' ' << op.y3 << ' '\n             << op.x4 << ' ' << op.y4 << '\\n';\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\n\nstruct Pos {\n    int r, c;\n};\n\nstruct Board {\n    uint8_t a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n\n    inline void place_by_index(int p, int flavor) {\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) {\n                ++cnt;\n                if (cnt == p) {\n                    a[i][j] = (uint8_t)flavor;\n                    return;\n                }\n            }\n        }\n        assert(false);\n    }\n\n    inline vector<Pos> empty_cells_ordered() const {\n        vector<Pos> e;\n        e.reserve(100);\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) e.push_back({i, j});\n        }\n        return e;\n    }\n\n    inline Board tilted(char dir) const {\n        Board b;\n        if (dir == 'L') {\n            for (int i = 0; i < N; i++) {\n                int t = 0;\n                for (int j = 0; j < N; j++) if (a[i][j]) b.a[i][t++] = a[i][j];\n            }\n        } else if (dir == 'R') {\n            for (int i = 0; i < N; i++) {\n                int t = N - 1;\n                for (int j = N - 1; j >= 0; j--) if (a[i][j]) b.a[i][t--] = a[i][j];\n            }\n        } else if (dir == 'F') {\n            for (int j = 0; j < N; j++) {\n                int t = 0;\n                for (int i = 0; i < N; i++) if (a[i][j]) b.a[t++][j] = a[i][j];\n            }\n        } else if (dir == 'B') {\n            for (int j = 0; j < N; j++) {\n                int t = N - 1;\n                for (int i = N - 1; i >= 0; i--) if (a[i][j]) b.a[t--][j] = a[i][j];\n            }\n        } else {\n            assert(false);\n        }\n        return b;\n    }\n};\n\nstruct EvalInfo {\n    long long compSq = 0;\n    int sameAdj = 0;\n    int diffAdj = 0;\n    int compCnt[4] = {};\n    int cnt[4] = {};\n    int minr[4], maxr[4], minc[4], maxc[4];\n    int rowCnt[4][N]{};\n    int colCnt[4][N]{};\n\n    EvalInfo() {\n        for (int i = 0; i < 4; i++) {\n            minr[i] = minc[i] = N;\n            maxr[i] = maxc[i] = -1;\n        }\n    }\n};\n\nstruct Policy {\n    int type; // 0 corner, 1 hband, 2 vband\n    Pos anchor[4];\n    int bandRow[4];\n    int bandCol[4];\n};\n\nstruct Solver {\n    vector<int> f;\n    int totalCnt[4]{};\n    vector<Policy> policies;\n    mutable uint64_t seed = 88172645463393265ull;\n    mutable unordered_map<uint64_t, double> evalCacheBest;\n    mutable unordered_map<uint64_t, double> evalCachePol;\n\n    Solver(const vector<int>& flavors) : f(flavors) {\n        for (int x : f) totalCnt[x]++;\n        build_policies();\n    }\n\n    inline uint64_t next_rand() const {\n        uint64_t x = seed;\n        x ^= x << 7;\n        x ^= x >> 9;\n        seed = x;\n        return x;\n    }\n\n    inline uint64_t hash_board(const Board& b, int turn, int extra = 0) const {\n        uint64_t h = 1469598103934665603ull ^ (uint64_t)(turn * 131 + extra);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                h ^= (uint64_t)(b.a[i][j] + 1 + 7 * (i * 10 + j));\n                h *= 1099511628211ull;\n            }\n        }\n        return h;\n    }\n\n    void build_policies() {\n        vector<int> ord = {1,2,3};\n        sort(ord.begin(), ord.end(), [&](int x, int y){ return totalCnt[x] > totalCnt[y]; });\n\n        {\n            Policy p;\n            p.type = 0;\n            p.anchor[ord[0]] = {0,0};\n            p.anchor[ord[1]] = {9,9};\n            p.anchor[ord[2]] = {0,9};\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 0;\n            p.anchor[ord[0]] = {0,0};\n            p.anchor[ord[1]] = {9,9};\n            p.anchor[ord[2]] = {9,0};\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 0;\n            p.anchor[ord[0]] = {0,9};\n            p.anchor[ord[1]] = {9,0};\n            p.anchor[ord[2]] = {0,0};\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 1;\n            p.bandRow[ord[0]] = 1;\n            p.bandRow[ord[1]] = 4;\n            p.bandRow[ord[2]] = 8;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 1;\n            p.bandRow[ord[0]] = 1;\n            p.bandRow[ord[1]] = 8;\n            p.bandRow[ord[2]] = 4;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 2;\n            p.bandCol[ord[0]] = 1;\n            p.bandCol[ord[1]] = 4;\n            p.bandCol[ord[2]] = 8;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 2;\n            p.bandCol[ord[0]] = 1;\n            p.bandCol[ord[1]] = 8;\n            p.bandCol[ord[2]] = 4;\n            policies.push_back(p);\n        }\n    }\n\n    EvalInfo analyze(const Board& b) const {\n        EvalInfo er;\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int x = b.a[i][j];\n            if (!x) continue;\n            er.cnt[x]++;\n            er.minr[x] = min(er.minr[x], i);\n            er.maxr[x] = max(er.maxr[x], i);\n            er.minc[x] = min(er.minc[x], j);\n            er.maxc[x] = max(er.maxc[x], j);\n            er.rowCnt[x][i]++;\n            er.colCnt[x][j]++;\n\n            if (i + 1 < N && b.a[i+1][j]) {\n                if (b.a[i+1][j] == x) er.sameAdj++;\n                else er.diffAdj++;\n            }\n            if (j + 1 < N && b.a[i][j+1]) {\n                if (b.a[i][j+1] == x) er.sameAdj++;\n                else er.diffAdj++;\n            }\n        }\n\n        bool vis[N][N];\n        memset(vis, 0, sizeof(vis));\n        static const int dr[4] = {-1, 1, 0, 0};\n        static const int dc[4] = {0, 0, -1, 1};\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int col = b.a[i][j];\n            if (!col || vis[i][j]) continue;\n            er.compCnt[col]++;\n            int sz = 0;\n            queue<pair<int,int>> q;\n            q.push({i,j});\n            vis[i][j] = true;\n            while (!q.empty()) {\n                auto [r,c] = q.front(); q.pop();\n                ++sz;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (!vis[nr][nc] && b.a[nr][nc] == col) {\n                        vis[nr][nc] = true;\n                        q.push({nr,nc});\n                    }\n                }\n            }\n            er.compSq += 1LL * sz * sz;\n        }\n\n        return er;\n    }\n\n    double score_with_policy(const Board& b, const EvalInfo& er, int turn, int pid) const {\n        const Policy& p = policies[pid];\n        double score = 0.0;\n\n        double wComp = (turn <= 80 ? 3450.0 : 3900.0);\n        double wCompCnt = (turn <= 80 ? 175.0 : 240.0);\n        score += wComp * er.compSq;\n        score += 245.0 * er.sameAdj;\n        score -= 155.0 * er.diffAdj;\n        score -= wCompCnt * (er.compCnt[1] + er.compCnt[2] + er.compCnt[3]);\n\n        for (int c = 1; c <= 3; c++) {\n            if (er.cnt[c] == 0) continue;\n            int area = (er.maxr[c] - er.minr[c] + 1) * (er.maxc[c] - er.minc[c] + 1);\n            score -= 18.0 * area;\n            score += 14.0 * er.cnt[c] * er.cnt[c] / max(1, area);\n        }\n\n        if (p.type == 0) {\n            double w = (turn <= 25 ? 14.0 : turn <= 70 ? 7.0 : turn <= 85 ? 2.5 : 1.0);\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j]) {\n                int c = b.a[i][j];\n                score -= w * (abs(i - p.anchor[c].r) + abs(j - p.anchor[c].c));\n            }\n        } else if (p.type == 1) {\n            double wr = (turn <= 25 ? 18.0 : turn <= 70 ? 10.0 : turn <= 85 ? 4.0 : 1.5);\n            for (int c = 1; c <= 3; c++) {\n                for (int i = 0; i < N; i++) {\n                    score -= wr * er.rowCnt[c][i] * abs(i - p.bandRow[c]);\n                    score += 2.0 * er.rowCnt[c][i] * er.rowCnt[c][i];\n                }\n            }\n        } else {\n            double wc = (turn <= 25 ? 18.0 : turn <= 70 ? 10.0 : turn <= 85 ? 4.0 : 1.5);\n            for (int c = 1; c <= 3; c++) {\n                for (int j = 0; j < N; j++) {\n                    score -= wc * er.colCnt[c][j] * abs(j - p.bandCol[c]);\n                    score += 2.0 * er.colCnt[c][j] * er.colCnt[c][j];\n                }\n            }\n        }\n\n        return score;\n    }\n\n    double eval_policy(const Board& b, int turn, int pid) const {\n        uint64_t h = hash_board(b, turn, pid + 1000);\n        auto it = evalCachePol.find(h);\n        if (it != evalCachePol.end()) return it->second;\n        EvalInfo er = analyze(b);\n        double v = score_with_policy(b, er, turn, pid);\n        evalCachePol.emplace(h, v);\n        return v;\n    }\n\n    pair<double,int> eval_best_policy_with_id(const Board& b, int turn) const {\n        uint64_t h = hash_board(b, turn, -1);\n        auto it = evalCacheBest.find(h);\n        if (it != evalCacheBest.end()) {\n            // can't recover id from this cache, recompute cheaply over policy cache\n            double best = -1e100;\n            int bestId = 0;\n            for (int pid = 0; pid < (int)policies.size(); pid++) {\n                double v = eval_policy(b, turn, pid);\n                if (v > best) {\n                    best = v;\n                    bestId = pid;\n                }\n            }\n            return {best, bestId};\n        }\n\n        double best = -1e100;\n        int bestId = 0;\n        for (int pid = 0; pid < (int)policies.size(); pid++) {\n            double v = eval_policy(b, turn, pid);\n            if (v > best) {\n                best = v;\n                bestId = pid;\n            }\n        }\n        evalCacheBest.emplace(h, best);\n        return {best, bestId};\n    }\n\n    double eval_best_policy(const Board& b, int turn) const {\n        return eval_best_policy_with_id(b, turn).first;\n    }\n\n    int sampled_empty_index(int m, int mode) const {\n        if (m <= 1) return 0;\n        switch (mode % 7) {\n            case 0: return 0;\n            case 1: return m - 1;\n            case 2: return m / 2;\n            case 3: return m / 3;\n            case 4: return (2 * m) / 3;\n            case 5: return (m > 2 ? 1 : 0);\n            default: return (int)(next_rand() % m);\n        }\n    }\n\n    char greedy_move_fixed_policy(const Board& b, int turn, int pid) const {\n        static const char dirs[4] = {'F','B','L','R'};\n        char bestDir = 'F';\n        double bestScore = -1e100;\n        for (char d : dirs) {\n            Board nb = b.tilted(d);\n            double sc = eval_policy(nb, turn, pid);\n            if (d == 'F') sc += 0.003;\n            else if (d == 'L') sc += 0.002;\n            else if (d == 'R') sc += 0.001;\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = d;\n            }\n        }\n        return bestDir;\n    }\n\n    double rollout(Board b, int turn, int sampleMode, int pid) const {\n        int depth;\n        if (turn <= 20) depth = 2;\n        else if (turn <= 70) depth = 3;\n        else if (turn <= 85) depth = 4;\n        else depth = 5;\n        depth = min(depth, 100 - turn);\n\n        if (turn >= 85 && depth >= 1) {\n            int t = turn + 1;\n            int flavor = f[t - 1];\n            auto empties = b.empty_cells_ordered();\n            int m = (int)empties.size();\n            if (m == 0) return eval_policy(b, turn, pid);\n\n            double bestBranch = -1e100;\n            for (int branch = 0; branch < 2; branch++) {\n                int idx = sampled_empty_index(m, sampleMode + branch);\n                Board bb = b;\n                bb.a[empties[idx].r][empties[idx].c] = (uint8_t)flavor;\n                char mv = greedy_move_fixed_policy(bb, t, pid);\n                bb = bb.tilted(mv);\n\n                for (int step = 1; step < depth; step++) {\n                    int tt = turn + step + 1;\n                    int ff = f[tt - 1];\n                    auto e2 = bb.empty_cells_ordered();\n                    int mm = (int)e2.size();\n                    if (mm == 0) break;\n                    int idx2 = sampled_empty_index(mm, sampleMode + 2 * step + branch);\n                    bb.a[e2[idx2].r][e2[idx2].c] = (uint8_t)ff;\n                    char mv2 = greedy_move_fixed_policy(bb, tt, pid);\n                    bb = bb.tilted(mv2);\n                }\n                bestBranch = max(bestBranch, eval_policy(bb, turn + depth, pid));\n            }\n            return bestBranch;\n        }\n\n        for (int step = 0; step < depth; step++) {\n            int t = turn + step + 1;\n            int flavor = f[t - 1];\n            auto empties = b.empty_cells_ordered();\n            int m = (int)empties.size();\n            if (m == 0) break;\n            int idx = sampled_empty_index(m, sampleMode + 2 * step);\n            b.a[empties[idx].r][empties[idx].c] = (uint8_t)flavor;\n            char mv = greedy_move_fixed_policy(b, t, pid);\n            b = b.tilted(mv);\n        }\n        return eval_policy(b, turn + depth, pid);\n    }\n\n    char decide(const Board& board, int turn) const {\n        evalCacheBest.clear();\n        evalCachePol.clear();\n        evalCacheBest.reserve(256);\n        evalCachePol.reserve(1024);\n\n        static const char dirs[4] = {'F','B','L','R'};\n        char bestDir = 'F';\n        double bestScore = -1e100;\n\n        int samples;\n        if (turn <= 20) samples = 2;\n        else if (turn <= 75) samples = 3;\n        else if (turn <= 90) samples = 4;\n        else samples = 5;\n\n        for (char d : dirs) {\n            Board tb = board.tilted(d);\n            auto [immediate, pid] = eval_best_policy_with_id(tb, turn);\n\n            double sum = 0.0, mn = 1e100, mx = -1e100;\n            for (int s = 0; s < samples; s++) {\n                double v = rollout(tb, turn, s, pid);\n                sum += v;\n                mn = min(mn, v);\n                mx = max(mx, v);\n            }\n            double avg = sum / samples;\n\n            double sc;\n            if (turn <= 25) {\n                sc = 0.55 * immediate + 0.40 * avg + 0.05 * mx;\n            } else if (turn <= 70) {\n                sc = 0.35 * immediate + 0.50 * avg + 0.15 * mn;\n            } else if (turn <= 85) {\n                sc = 0.25 * immediate + 0.55 * avg + 0.20 * mn;\n            } else {\n                sc = 0.18 * immediate + 0.60 * avg + 0.22 * mn;\n            }\n\n            if (d == 'F') sc += 0.003;\n            else if (d == 'L') sc += 0.002;\n            else if (d == 'R') sc += 0.001;\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = d;\n            }\n        }\n\n        return bestDir;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Solver solver(f);\n    Board board;\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n        board.place_by_index(p, f[t - 1]);\n\n        char ans = solver.decide(board, t);\n        board = board.tilted(ans);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ull << 53));\n    }\n    uint32_t next_u32() { return (uint32_t)next_u64(); }\n    int randint(int l, int r) {\n        return l + (int)(next_u32() % (uint32_t)(r - l + 1));\n    }\n};\n\nstatic int edge_index(int N, int i, int j) {\n    return i * (2 * N - i - 1) / 2 + (j - i - 1);\n}\n\nstatic string make_threshold_graph(int N, int x) {\n    string s(N * (N - 1) / 2, '0');\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (i < x || j < x) s[edge_index(N, i, j)] = '1';\n        }\n    }\n    return s;\n}\n\nstatic vector<int> get_sorted_degrees(int N, const string& g, int& edge_cnt) {\n    vector<int> deg(N, 0);\n    edge_cnt = 0;\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[p++] == '1') {\n                deg[i]++;\n                deg[j]++;\n                edge_cnt++;\n            }\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nenum PlacementType {\n    LINEAR = 0,\n    QUAD_LOW = 1,\n    QUAD_HIGH = 2,\n    CENTER = 3\n};\n\nstruct Params {\n    double w_edge;\n    double w_split;\n};\n\nstruct Model {\n    int N, M;\n    PlacementType pt;\n    Params prm;\n    vector<int> xs;\n    vector<string> graphs;\n    vector<double> exp_edges;\n    vector<double> mu_low, mu_high;\n    vector<double> exp_pref, exp_suff;\n};\n\nstatic vector<int> build_xs(int M, int N, PlacementType pt) {\n    vector<int> xs(M, 0);\n    if (M == 1) {\n        xs[0] = 0;\n        return xs;\n    }\n\n    for (int k = 0; k < M; k++) {\n        double t = (double)k / (M - 1);\n        double y;\n        if (pt == LINEAR) {\n            y = t;\n        } else if (pt == QUAD_LOW) {\n            y = t * t;\n        } else if (pt == QUAD_HIGH) {\n            y = 1.0 - (1.0 - t) * (1.0 - t);\n        } else { // CENTER\n            y = 0.5 - 0.5 * cos(M_PI * t);\n        }\n        xs[k] = (int)llround(y * (N - 1));\n    }\n\n    for (int k = 1; k < M; k++) xs[k] = max(xs[k], xs[k - 1] + 1);\n    for (int k = M - 1; k >= 0; k--) xs[k] = min(xs[k], N);\n    for (int k = M - 2; k >= 0; k--) xs[k] = min(xs[k], xs[k + 1] - 1);\n    for (int k = 0; k < M; k++) xs[k] = max(0, min(N, xs[k]));\n    for (int k = 1; k < M; k++) {\n        if (xs[k] <= xs[k - 1]) xs[k] = min(N, xs[k - 1] + 1);\n    }\n    return xs;\n}\n\nstatic Model build_model(int M, double eps, int N, PlacementType pt, Params prm) {\n    Model md;\n    md.N = N;\n    md.M = M;\n    md.pt = pt;\n    md.prm = prm;\n    md.xs = build_xs(M, N, pt);\n    md.graphs.resize(M);\n    md.exp_edges.resize(M);\n    md.mu_low.resize(M);\n    md.mu_high.resize(M);\n    md.exp_pref.resize(M);\n    md.exp_suff.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        int x = md.xs[k];\n        md.graphs[k] = make_threshold_graph(N, x);\n\n        double muL = x * (1.0 - eps) + (N - 1 - x) * eps;\n        double muH = (N - 1) * (1.0 - eps);\n\n        md.mu_low[k] = muL;\n        md.mu_high[k] = muH;\n\n        int cut = N - x;\n        md.exp_pref[k] = cut * muL;\n        md.exp_suff[k] = x * muH;\n\n        double m0 = 1.0 * x * (2 * N - x - 1) / 2.0;\n        double total = 1.0 * N * (N - 1) / 2.0;\n        md.exp_edges[k] = m0 * (1.0 - eps) + (total - m0) * eps;\n    }\n\n    return md;\n}\n\nstatic int decode_model(const Model& md, const vector<int>& deg, int edges) {\n    int N = md.N;\n    vector<double> ps(N + 1, 0.0), ps2(N + 1, 0.0);\n    for (int i = 0; i < N; i++) {\n        ps[i + 1] = ps[i] + deg[i];\n        ps2[i + 1] = ps2[i] + 1.0 * deg[i] * deg[i];\n    }\n\n    int best = 0;\n    double bestScore = 1e100;\n\n    for (int k = 0; k < md.M; k++) {\n        int x = md.xs[k];\n        int cut = N - x;\n\n        double muL = md.mu_low[k];\n        double muH = md.mu_high[k];\n\n        double sseL = 0.0, sseH = 0.0;\n        double pref = 0.0, suff = 0.0;\n\n        if (cut > 0) {\n            double sum = ps[cut];\n            double sum2 = ps2[cut];\n            pref = sum;\n            sseL = sum2 - 2.0 * muL * sum + cut * muL * muL;\n        }\n        if (cut < N) {\n            double sum = ps[N] - ps[cut];\n            double sum2 = ps2[N] - ps2[cut];\n            suff = sum;\n            int cnt = N - cut;\n            sseH = sum2 - 2.0 * muH * sum + cnt * muH * muH;\n        }\n\n        double ed = edges - md.exp_edges[k];\n        double dp = pref - md.exp_pref[k];\n        double ds = suff - md.exp_suff[k];\n\n        double score = sseL + sseH\n                     + md.prm.w_edge * ed * ed\n                     + md.prm.w_split * (dp * dp + ds * ds) / max(1, N);\n\n        if (score < bestScore) {\n            bestScore = score;\n            best = k;\n        }\n    }\n    return best;\n}\n\nstatic int simulate_one(XorShift& rng, const Model& md, double eps, int s) {\n    int N = md.N;\n    int x = md.xs[s];\n\n    vector<int> deg(N, 0);\n    int edges = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = (i < x || j < x);\n            if (rng.next_double() < eps) e = !e;\n            if (e) {\n                deg[i]++;\n                deg[j]++;\n                edges++;\n            }\n        }\n    }\n\n    sort(deg.begin(), deg.end());\n    return decode_model(md, deg, edges);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    int base_gap;\n    if (eps <= 0.02) base_gap = 1;\n    else if (eps <= 0.05) base_gap = 2;\n    else if (eps <= 0.10) base_gap = 3;\n    else if (eps <= 0.15) base_gap = 4;\n    else if (eps <= 0.20) base_gap = 5;\n    else if (eps <= 0.25) base_gap = 6;\n    else if (eps <= 0.30) base_gap = 7;\n    else if (eps <= 0.35) base_gap = 8;\n    else base_gap = 9;\n\n    vector<int> candN;\n    for (int dg = -3; dg <= 5; dg++) {\n        int gap = max(1, base_gap + dg);\n        int N = (M - 1) * gap + 1;\n        N = max(4, min(100, N));\n        if (N >= M - 1) candN.push_back(N);\n    }\n    for (int extra : {M - 1, M + 4, M + 9, M + 14, M + 19, M + 24, 100}) {\n        int N = max(4, min(100, extra));\n        if (N >= M - 1) candN.push_back(N);\n    }\n    sort(candN.begin(), candN.end());\n    candN.erase(unique(candN.begin(), candN.end()), candN.end());\n\n    vector<PlacementType> placements = {LINEAR, QUAD_LOW, QUAD_HIGH, CENTER};\n    vector<Params> param_list = {\n        {0.20, 0.00},\n        {0.35, 0.00},\n        {0.50, 0.00},\n        {0.35, 0.05},\n        {0.35, 0.10},\n        {0.50, 0.05}\n    };\n\n    XorShift rng;\n\n    Model best_model;\n    double best_value = -1.0;\n\n    for (int N : candN) {\n        for (auto pt : placements) {\n            for (auto prm : param_list) {\n                Model md = build_model(M, eps, N, pt, prm);\n\n                int trials = 90;\n                int err = 0;\n                for (int t = 0; t < trials; t++) {\n                    int s = rng.randint(0, M - 1);\n                    int pred = simulate_one(rng, md, eps, s);\n                    if (pred != s) err++;\n                }\n\n                double val = pow(0.9, err) / N;\n                if (val > best_value) {\n                    best_value = val;\n                    best_model = std::move(md);\n                }\n            }\n        }\n    }\n\n    cout << best_model.N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << best_model.graphs[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        int edges;\n        vector<int> deg = get_sorted_degrees(best_model.N, H, edges);\n        int ans = decode_model(best_model, deg, edges);\n\n        cout << ans << '\\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\nstatic const long long INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v, w;\n    int cell;\n    double imp = 0.0;\n};\n\nstruct Solver {\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<int> xs, ys;\n    vector<vector<pair<int,int>>> g;\n    int G = 8, C;\n\n    Timer timer;\n    mt19937 rng{123456789};\n\n    vector<int> day_of;\n    vector<int> load;\n    vector<double> day_imp;\n    vector<vector<int>> by_day;\n\n    // extra state\n    vector<vector<int>> cell_cnt;   // [day][cell]\n    vector<vector<int>> vday_cnt;   // [day][vertex]\n\n    // sampled evaluation\n    vector<int> sample_roots;\n    vector<vector<long long>> base_dist;\n    vector<double> day_score;\n    double total_score = 0.0;\n\n    int get_cell(double x, double y) {\n        int gx = min(G - 1, max(0, (int)(x * G / 1001.0)));\n        int gy = min(G - 1, max(0, (int)(y * G / 1001.0)));\n        return gy * G + gx;\n    }\n\n    void read_input() {\n        cin >> N >> M >> D >> K;\n        edges.resize(M);\n        g.assign(N, {});\n        for (int i = 0; i < M; i++) {\n            int u, v, w;\n            cin >> u >> v >> w;\n            --u; --v;\n            edges[i] = {u, v, w, -1, 0.0};\n            g[u].push_back({v, i});\n            g[v].push_back({u, i});\n        }\n        xs.resize(N);\n        ys.resize(N);\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        C = G * G;\n        for (int i = 0; i < M; i++) {\n            double mx = 0.5 * (xs[edges[i].u] + xs[edges[i].v]);\n            double my = 0.5 * (ys[edges[i].u] + ys[edges[i].v]);\n            edges[i].cell = get_cell(mx, my);\n        }\n    }\n\n    void dijkstra_normal(int s, vector<long long>& dist, vector<int>* parent_e = nullptr) {\n        dist.assign(N, INF64);\n        vector<int> pe;\n        if (parent_e) pe.assign(N, -1);\n\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 [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    if (parent_e) pe[to] = ei;\n                    pq.push({nd, to});\n                } else if (parent_e && nd == dist[to] && (pe[to] == -1 || ei < pe[to])) {\n                    pe[to] = ei;\n                }\n            }\n        }\n        if (parent_e) *parent_e = move(pe);\n    }\n\n    void dijkstra_removed_day(int s, int removed_day, vector<long long>& dist) {\n        dist.assign(N, INF64);\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 [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                if (day_of[ei] == removed_day) continue;\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    }\n\n    void compute_importance() {\n        vector<int> roots;\n        roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n        roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n        roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n        roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n        for (int t = 0; (int)roots.size() < min(24, max(8, 2 * D)); t++) {\n            int r = (int)((1LL * t * 911382323 + 972663749) % N);\n            roots.push_back(r);\n        }\n        sort(roots.begin(), roots.end());\n        roots.erase(unique(roots.begin(), roots.end()), roots.end());\n\n        vector<double> imp(M, 0.0), vcen(N, 0.0);\n        vector<long long> dist;\n        vector<int> parent_e;\n\n        for (int s : roots) {\n            if (timer.elapsed() > 1.05) break;\n            dijkstra_normal(s, dist, &parent_e);\n\n            double sumd = 0.0;\n            for (int i = 0; i < N; i++) if (dist[i] < INF64 / 4) sumd += dist[i];\n            double inv = (sumd > 0 ? 1.0 / sumd : 0.0);\n\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                if (parent_e[v] != -1) {\n                    double add = 1.0 + 3.0 * (1.0 - dist[v] * inv);\n                    imp[parent_e[v]] += add;\n                }\n                if (dist[v] < INF64 / 4) {\n                    vcen[v] += (1.0 - dist[v] * inv);\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            int u = edges[i].u, v = edges[i].v;\n            double val = imp[i];\n            val += 0.10 * g[u].size() + 0.10 * g[v].size();\n            val += 1.15 * (vcen[u] + vcen[v]);\n            val += 0.000002 * edges[i].w;\n            edges[i].imp = val;\n        }\n    }\n\n    void rebuild_by_day() {\n        by_day.assign(D, {});\n        for (int i = 0; i < M; i++) by_day[day_of[i]].push_back(i);\n    }\n\n    void build_initial_solution() {\n        day_of.assign(M, -1);\n        load.assign(D, 0);\n        day_imp.assign(D, 0.0);\n        cell_cnt.assign(D, vector<int>(C, 0));\n        vday_cnt.assign(D, vector<int>(N, 0));\n\n        vector<vector<int>> cell_edges(C);\n        vector<double> cell_imp(C, 0.0);\n        for (int i = 0; i < M; i++) {\n            cell_edges[edges[i].cell].push_back(i);\n            cell_imp[edges[i].cell] += edges[i].imp;\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 cell_imp[a] > cell_imp[b];\n        });\n\n        for (int c : cells) {\n            auto &vec = cell_edges[c];\n            sort(vec.begin(), vec.end(), [&](int a, int b) {\n                if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n                return edges[a].w > edges[b].w;\n            });\n\n            int ptr = 0;\n            for (int ei : vec) {\n                double best = 1e100;\n                int bestd = -1;\n                auto &e = edges[ei];\n                for (int tt = 0; tt < D; tt++) {\n                    int d = (ptr + tt) % D;\n                    if (load[d] >= K) continue;\n\n                    double cost = 0.0;\n                    cost += 18.0 * cell_cnt[d][c];\n                    cost += 15.0 * (vday_cnt[d][e.u] + vday_cnt[d][e.v]);\n                    cost += 9.0 * load[d];\n                    cost += 0.40 * day_imp[d];\n                    cost += 0.7 * e.imp * cell_cnt[d][c];\n                    cost += 0.8 * e.imp * (vday_cnt[d][e.u] + vday_cnt[d][e.v]);\n\n                    if (cost < best) {\n                        best = cost;\n                        bestd = d;\n                    }\n                }\n                ptr = (ptr + 1) % D;\n                if (bestd == -1) {\n                    for (int d = 0; d < D; d++) if (load[d] < K) { bestd = d; break; }\n                }\n\n                day_of[ei] = bestd;\n                load[bestd]++;\n                day_imp[bestd] += e.imp;\n                cell_cnt[bestd][c]++;\n                vday_cnt[bestd][e.u]++;\n                vday_cnt[bestd][e.v]++;\n            }\n        }\n\n        rebuild_by_day();\n    }\n\n    void choose_sample_roots() {\n        sample_roots.clear();\n        sample_roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n        sample_roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n        sample_roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n        sample_roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int a, int b) {\n            return g[a].size() > g[b].size();\n        });\n        for (int i = 0; i < min(2, N); i++) sample_roots.push_back(idx[i]);\n\n        sort(sample_roots.begin(), sample_roots.end());\n        sample_roots.erase(unique(sample_roots.begin(), sample_roots.end()), sample_roots.end());\n        if ((int)sample_roots.size() > 6) sample_roots.resize(6);\n    }\n\n    void precompute_base_dist() {\n        choose_sample_roots();\n        base_dist.assign(sample_roots.size(), vector<long long>());\n        for (int i = 0; i < (int)sample_roots.size(); i++) {\n            dijkstra_normal(sample_roots[i], base_dist[i]);\n        }\n    }\n\n    double eval_day(int day) {\n        vector<long long> dist;\n        double sum = 0.0;\n        for (int si = 0; si < (int)sample_roots.size(); si++) {\n            dijkstra_removed_day(sample_roots[si], day, dist);\n            for (int v = 0; v < N; v++) {\n                if (v == sample_roots[si]) continue;\n                long long bd = base_dist[si][v];\n                long long nd = dist[v];\n                if (nd >= INF64 / 4) nd = 1000000000LL;\n                sum += (double)(nd - bd);\n            }\n        }\n        return sum;\n    }\n\n    void init_scores() {\n        day_score.assign(D, 0.0);\n        total_score = 0.0;\n        for (int d = 0; d < D; d++) {\n            day_score[d] = eval_day(d);\n            total_score += day_score[d];\n        }\n    }\n\n    void apply_move(int ei, int from, int to) {\n        const auto &e = edges[ei];\n        day_of[ei] = to;\n        load[from]--;\n        load[to]++;\n        day_imp[from] -= e.imp;\n        day_imp[to] += e.imp;\n        cell_cnt[from][e.cell]--;\n        cell_cnt[to][e.cell]++;\n        vday_cnt[from][e.u]--;\n        vday_cnt[from][e.v]--;\n        vday_cnt[to][e.u]++;\n        vday_cnt[to][e.v]++;\n    }\n\n    void rollback_move(int ei, int from, int to) {\n        const auto &e = edges[ei];\n        day_of[ei] = from;\n        load[from]++;\n        load[to]--;\n        day_imp[from] += e.imp;\n        day_imp[to] -= e.imp;\n        cell_cnt[from][e.cell]++;\n        cell_cnt[to][e.cell]--;\n        vday_cnt[from][e.u]++;\n        vday_cnt[from][e.v]++;\n        vday_cnt[to][e.u]--;\n        vday_cnt[to][e.v]--;\n    }\n\n    void apply_swap(int e1, int d1, int e2, int d2) {\n        const auto &a = edges[e1];\n        const auto &b = edges[e2];\n        day_of[e1] = d2;\n        day_of[e2] = d1;\n        day_imp[d1] += b.imp - a.imp;\n        day_imp[d2] += a.imp - b.imp;\n        cell_cnt[d1][a.cell]--;\n        cell_cnt[d1][b.cell]++;\n        cell_cnt[d2][b.cell]--;\n        cell_cnt[d2][a.cell]++;\n        vday_cnt[d1][a.u]--;\n        vday_cnt[d1][a.v]--;\n        vday_cnt[d2][a.u]++;\n        vday_cnt[d2][a.v]++;\n        vday_cnt[d2][b.u]--;\n        vday_cnt[d2][b.v]--;\n        vday_cnt[d1][b.u]++;\n        vday_cnt[d1][b.v]++;\n    }\n\n    void rollback_swap(int e1, int d1, int e2, int d2) {\n        apply_swap(e1, d2, e2, d1);\n    }\n\n    void focused_improvement() {\n        for (int round = 0; round < 16 && timer.elapsed() < 4.55; round++) {\n            rebuild_by_day();\n            int worst = max_element(day_score.begin(), day_score.end()) - day_score.begin();\n            if (by_day[worst].empty()) break;\n\n            vector<int> cand = by_day[worst];\n            sort(cand.begin(), cand.end(), [&](int a, int b) {\n                double sa = edges[a].imp\n                    + 8.0 * cell_cnt[worst][edges[a].cell]\n                    + 10.0 * (vday_cnt[worst][edges[a].u] + vday_cnt[worst][edges[a].v]);\n                double sb = edges[b].imp\n                    + 8.0 * cell_cnt[worst][edges[b].cell]\n                    + 10.0 * (vday_cnt[worst][edges[b].u] + vday_cnt[worst][edges[b].v]);\n                return sa > sb;\n            });\n\n            bool improved = false;\n            int lim = min<int>(16, cand.size());\n            for (int i = 0; i < lim && timer.elapsed() < 4.55; i++) {\n                int ei = cand[i];\n                int from = worst;\n                const auto &e = edges[ei];\n\n                vector<int> days(D);\n                iota(days.begin(), days.end(), 0);\n                sort(days.begin(), days.end(), [&](int a, int b) {\n                    if (a == from) return false;\n                    if (b == from) return true;\n                    double ca = day_score[a]\n                        + 20.0 * cell_cnt[a][e.cell]\n                        + 18.0 * (vday_cnt[a][e.u] + vday_cnt[a][e.v])\n                        + 2.0 * load[a];\n                    double cb = day_score[b]\n                        + 20.0 * cell_cnt[b][e.cell]\n                        + 18.0 * (vday_cnt[b][e.u] + vday_cnt[b][e.v])\n                        + 2.0 * load[b];\n                    return ca < cb;\n                });\n\n                for (int z = 0; z < min(D, 8) && timer.elapsed() < 4.55; z++) {\n                    int to = days[z];\n                    if (to == from || load[to] >= K) continue;\n\n                    apply_move(ei, from, to);\n                    double new_from = eval_day(from);\n                    double new_to = eval_day(to);\n                    double new_total = total_score - day_score[from] - day_score[to] + new_from + new_to;\n\n                    if (new_total < total_score) {\n                        total_score = new_total;\n                        day_score[from] = new_from;\n                        day_score[to] = new_to;\n                        improved = true;\n                        break;\n                    } else {\n                        rollback_move(ei, from, to);\n                    }\n                }\n                if (improved) break;\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void random_local_search() {\n        int iter = 0;\n        while (timer.elapsed() < 5.55) {\n            iter++;\n            if ((iter & 255) == 0) rebuild_by_day();\n\n            if ((rng() & 1) == 0) {\n                int ei = rng() % M;\n                int from = day_of[ei];\n                int to = rng() % D;\n                if (from == to || load[to] >= K) continue;\n\n                const auto &e = edges[ei];\n                double rough =\n                    8.0 * (cell_cnt[to][e.cell] - cell_cnt[from][e.cell]) +\n                    10.0 * ((vday_cnt[to][e.u] + vday_cnt[to][e.v]) - (vday_cnt[from][e.u] + vday_cnt[from][e.v])) +\n                    1.0 * (load[to] - load[from]);\n                if (rough > 4.0 && (rng() & 3)) continue;\n\n                apply_move(ei, from, to);\n                double new_from = eval_day(from);\n                double new_to = eval_day(to);\n                double new_total = total_score - day_score[from] - day_score[to] + new_from + new_to;\n\n                if (new_total <= total_score) {\n                    total_score = new_total;\n                    day_score[from] = new_from;\n                    day_score[to] = new_to;\n                } else {\n                    rollback_move(ei, from, to);\n                }\n            } else {\n                int d1 = rng() % D;\n                int d2 = rng() % D;\n                if (d1 == d2) continue;\n                if (by_day[d1].empty() || by_day[d2].empty()) continue;\n\n                int e1 = by_day[d1][rng() % by_day[d1].size()];\n                int e2 = by_day[d2][rng() % by_day[d2].size()];\n                if (e1 == e2) continue;\n                if (day_of[e1] != d1 || day_of[e2] != d2) continue;\n\n                apply_swap(e1, d1, e2, d2);\n                double new_d1 = eval_day(d1);\n                double new_d2 = eval_day(d2);\n                double new_total = total_score - day_score[d1] - day_score[d2] + new_d1 + new_d2;\n\n                if (new_total <= total_score) {\n                    total_score = new_total;\n                    day_score[d1] = new_d1;\n                    day_score[d2] = new_d2;\n                } else {\n                    rollback_swap(e1, d1, e2, d2);\n                }\n            }\n        }\n    }\n\n    void repair_feasibility() {\n        vector<int> cnt(D, 0);\n        for (int i = 0; i < M; i++) cnt[day_of[i]]++;\n        for (int d = 0; d < D; d++) {\n            while (cnt[d] > K) {\n                int nd = -1;\n                for (int t = 0; t < D; t++) if (cnt[t] < K) { nd = t; break; }\n                if (nd == -1) break;\n                for (int i = 0; i < M; i++) {\n                    if (day_of[i] == d) {\n                        day_of[i] = nd;\n                        cnt[d]--;\n                        cnt[nd]++;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    void solve() {\n        read_input();\n        compute_importance();\n        build_initial_solution();\n        precompute_base_dist();\n        init_scores();\n        focused_improvement();\n        random_local_search();\n        repair_feasibility();\n\n        for (int i = 0; i < M; i++) {\n            if (i) cout << ' ';\n            cout << day_of[i] + 1;\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}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DX6[6] = {1,-1,0,0,0,0};\nstatic const int DY6[6] = {0,0,1,-1,0,0};\nstatic const int DZ6[6] = {0,0,0,0,1,-1};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n} rng;\n\nstruct P3 {\n    int x, y, z;\n};\n\nstruct Rot {\n    int p[3];\n    int s[3];\n};\n\nstruct Piece {\n    vector<int> vox;\n    string sig;\n};\n\nstruct Candidate {\n    vector<char> occ0, occ1;\n    vector<Piece> bestP0, bestP1;\n    long long proxy = LLONG_MIN;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int i = 0; i < D; i++) cin >> f[t][i];\n        for (int i = 0; i < D; i++) cin >> r[t][i];\n    }\n\n    auto idx = [&](int x, int y, int z) -> int {\n        return (x * D + y) * D + z;\n    };\n    auto inside = [&](int x, int y, int z) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D && 0 <= z && z < D;\n    };\n    auto decode = [&](int v) -> P3 {\n        int z = v % D;\n        int t = v / D;\n        int y = t % D;\n        int x = t / D;\n        return {x, y, z};\n    };\n\n    const int N3 = D * D * D;\n\n    vector<Rot> rots;\n    {\n        vector<int> perm = {0,1,2};\n        do {\n            int sign_perm = 1;\n            for (int i = 0; i < 3; i++) for (int j = i + 1; j < 3; j++) {\n                if (perm[i] > perm[j]) sign_perm *= -1;\n            }\n            for (int sx : {-1, 1}) for (int sy : {-1, 1}) for (int sz : {-1, 1}) {\n                if (sign_perm * sx * sy * sz == 1) {\n                    Rot rt;\n                    rt.p[0] = perm[0];\n                    rt.p[1] = perm[1];\n                    rt.p[2] = perm[2];\n                    rt.s[0] = sx;\n                    rt.s[1] = sy;\n                    rt.s[2] = sz;\n                    rots.push_back(rt);\n                }\n            }\n        } while (next_permutation(perm.begin(), perm.end()));\n    }\n\n    auto rotate_point = [&](const P3& a, const Rot& rt) -> P3 {\n        int v[3] = {a.x, a.y, a.z};\n        return P3{\n            rt.s[0] * v[rt.p[0]],\n            rt.s[1] * v[rt.p[1]],\n            rt.s[2] * v[rt.p[2]]\n        };\n    };\n\n    auto canonical_signature_from_vox = [&](const vector<int>& vox) -> string {\n        vector<P3> cells;\n        cells.reserve(vox.size());\n        int minx = 1e9, miny = 1e9, minz = 1e9;\n        for (int v : vox) {\n            auto p = decode(v);\n            minx = min(minx, p.x);\n            miny = min(miny, p.y);\n            minz = min(minz, p.z);\n            cells.push_back(p);\n        }\n        for (auto &p : cells) {\n            p.x -= minx;\n            p.y -= miny;\n            p.z -= minz;\n        }\n\n        string best;\n        bool first = true;\n        for (const auto& rt : rots) {\n            vector<array<int,3>> q;\n            q.reserve(cells.size());\n            int bx = 1e9, by = 1e9, bz = 1e9;\n            for (auto &p : cells) {\n                P3 t = rotate_point(p, rt);\n                bx = min(bx, t.x);\n                by = min(by, t.y);\n                bz = min(bz, t.z);\n                q.push_back({t.x, t.y, t.z});\n            }\n            for (auto &a : q) {\n                a[0] -= bx;\n                a[1] -= by;\n                a[2] -= bz;\n            }\n            sort(q.begin(), q.end());\n            string s;\n            s.reserve(q.size() * 12);\n            for (auto &a : q) {\n                s += to_string(a[0]);\n                s.push_back(',');\n                s += to_string(a[1]);\n                s.push_back(',');\n                s += to_string(a[2]);\n                s.push_back(';');\n            }\n            if (first || s < best) {\n                best = move(s);\n                first = false;\n            }\n        }\n        return best;\n    };\n\n    auto initial_build = [&](int t) -> vector<char> {\n        vector<char> occ(N3, 0);\n        for (int z = 0; z < D; z++) {\n            vector<int> X, Y;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') X.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') Y.push_back(y);\n            int a = (int)X.size(), b = (int)Y.size();\n            if (a == 0 || b == 0) continue;\n            if (a <= b) {\n                for (int i = 0; i < a; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = a; i < b; i++) occ[idx(X[0], Y[i], z)] = 1;\n            } else {\n                for (int i = 0; i < b; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = b; i < a; i++) occ[idx(X[i], Y[0], z)] = 1;\n            }\n        }\n        return occ;\n    };\n\n    auto build_layer_variants = [&](int cur, int z, const vector<char>& refOcc, const vector<char>& selfOcc, int variants) {\n        vector<vector<pair<int,int>>> ret;\n        vector<int> X, Y;\n        for (int x = 0; x < D; x++) if (f[cur][z][x] == '1') X.push_back(x);\n        for (int y = 0; y < D; y++) if (r[cur][z][y] == '1') Y.push_back(y);\n        int a = (int)X.size(), b = (int)Y.size();\n        if (a == 0 || b == 0) {\n            ret.push_back({});\n            return ret;\n        }\n\n        for (int tr = 0; tr < variants; tr++) {\n            vector<int> px = X, py = Y;\n            shuffle(px.begin(), px.end(), std::mt19937(rng.next_u32()));\n            shuffle(py.begin(), py.end(), std::mt19937(rng.next_u32()));\n\n            vector<pair<int,int>> cells;\n            int m = min(a, b);\n            for (int i = 0; i < m; i++) cells.push_back({px[i], py[i]});\n\n            if (a > b) {\n                int bestY = Y[0];\n                long long bestYScore = LLONG_MIN;\n                for (int candY : Y) {\n                    long long sc = 0;\n                    for (int i = b; i < a; i++) {\n                        int x = px[i];\n                        int id = idx(x, candY, z);\n                        if (refOcc[id]) sc += 24;\n                        if (selfOcc[id]) sc += 12;\n                        if (z > 0 && selfOcc[idx(x, candY, z-1)]) sc += 10;\n                        if (z + 1 < D && selfOcc[idx(x, candY, z+1)]) sc += 10;\n                    }\n                    if (sc > bestYScore) bestYScore = sc, bestY = candY;\n                }\n                for (int i = b; i < a; i++) cells.push_back({px[i], bestY});\n            } else if (b > a) {\n                int bestX = X[0];\n                long long bestXScore = LLONG_MIN;\n                for (int candX : X) {\n                    long long sc = 0;\n                    for (int j = a; j < b; j++) {\n                        int y = py[j];\n                        int id = idx(candX, y, z);\n                        if (refOcc[id]) sc += 24;\n                        if (selfOcc[id]) sc += 12;\n                        if (z > 0 && selfOcc[idx(candX, y, z-1)]) sc += 10;\n                        if (z + 1 < D && selfOcc[idx(candX, y, z+1)]) sc += 10;\n                    }\n                    if (sc > bestXScore) bestXScore = sc, bestX = candX;\n                }\n                for (int j = a; j < b; j++) cells.push_back({bestX, py[j]});\n            }\n\n            ret.push_back(move(cells));\n        }\n        return ret;\n    };\n\n    auto choose_best_layer = [&](int cur, int z, const vector<char>& refOcc, const vector<char>& selfHint, const vector<char>& builtPrefix, int variants) {\n        auto candLayers = build_layer_variants(cur, z, refOcc, selfHint, variants);\n        long long bestScore = LLONG_MIN;\n        vector<pair<int,int>> best;\n        for (auto &cells : candLayers) {\n            unordered_set<int> S;\n            S.reserve(cells.size() * 2 + 10);\n            long long score = 0;\n            for (auto [x, y] : cells) {\n                int id = idx(x, y, z);\n                S.insert(id);\n                if (refOcc[id]) score += 60;\n                if (selfHint[id]) score += 25;\n                if (z > 0 && builtPrefix[idx(x, y, z-1)]) score += 18;\n                if (z + 1 < D && selfHint[idx(x, y, z+1)]) score += 5;\n            }\n            for (auto [x, y] : cells) {\n                int cnt = 0;\n                if (x > 0 && S.count(idx(x-1, y, z))) cnt++;\n                if (x + 1 < D && S.count(idx(x+1, y, z))) cnt++;\n                if (y > 0 && S.count(idx(x, y-1, z))) cnt++;\n                if (y + 1 < D && S.count(idx(x, y+1, z))) cnt++;\n                score += 7LL * cnt;\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                best = cells;\n            }\n        }\n        return best;\n    };\n\n    auto build_object = [&](int cur, const vector<char>& refOcc, const vector<char>& selfHint, int intensity) -> vector<char> {\n        vector<char> occ(N3, 0);\n        int baseTrials = (D <= 7 ? 80 : (D <= 10 ? 55 : 35));\n        int variants = baseTrials + intensity;\n        for (int z = 0; z < D; z++) {\n            auto best = choose_best_layer(cur, z, refOcc, selfHint, occ, variants);\n            for (auto [x, y] : best) occ[idx(x, y, z)] = 1;\n        }\n        return occ;\n    };\n\n    auto extract_rectangles = [&](vector<char>& alive, vector<Piece>& pieces) {\n        while (true) {\n            int bestArea = 0;\n            vector<int> bestVox;\n\n            for (int z = 0; z < D; z++) {\n                for (int x1 = 0; x1 < D; x1++) for (int y1 = 0; y1 < D; y1++) {\n                    if (!alive[idx(x1, y1, z)]) continue;\n                    for (int x2 = x1; x2 < D; x2++) {\n                        bool ok = true;\n                        for (int y = y1; y < D; y++) {\n                            if (!alive[idx(x2, y, z)]) { ok = false; break; }\n                            if (!ok) break;\n                            int area = (x2 - x1 + 1) * (y - y1 + 1);\n                            if (area <= bestArea) continue;\n                            bool full = true;\n                            vector<int> vox;\n                            vox.reserve(area);\n                            for (int xx = x1; xx <= x2 && full; xx++) {\n                                for (int yy = y1; yy <= y; yy++) {\n                                    int id = idx(xx, yy, z);\n                                    if (!alive[id]) { full = false; break; }\n                                    vox.push_back(id);\n                                }\n                            }\n                            if (full) {\n                                bestArea = area;\n                                bestVox = move(vox);\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestArea < 2) break;\n            Piece pc;\n            pc.vox = bestVox;\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n            for (int v : bestVox) alive[v] = 0;\n        }\n    };\n\n    auto extract_straight_runs = [&](vector<char>& alive, vector<Piece>& pieces) {\n        while (true) {\n            int bestLen = 0;\n            vector<int> bestVox;\n            for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n                int s = idx(x, y, z);\n                if (!alive[s]) continue;\n\n                if (x == 0 || !alive[idx(x-1, y, z)]) {\n                    vector<int> cur;\n                    for (int nx = x; nx < D && alive[idx(nx, y, z)]; nx++) cur.push_back(idx(nx, y, z));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n                if (y == 0 || !alive[idx(x, y-1, z)]) {\n                    vector<int> cur;\n                    for (int ny = y; ny < D && alive[idx(x, ny, z)]; ny++) cur.push_back(idx(x, ny, z));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n                if (z == 0 || !alive[idx(x, y, z-1)]) {\n                    vector<int> cur;\n                    for (int nz = z; nz < D && alive[idx(x, y, nz)]; nz++) cur.push_back(idx(x, y, nz));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n            }\n\n            if (bestLen < 2) break;\n            Piece pc;\n            pc.vox = bestVox;\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n            for (int v : bestVox) alive[v] = 0;\n        }\n    };\n\n    auto extract_paths = [&](vector<char>& alive, vector<Piece>& pieces) {\n        vector<char> vis(N3, 0);\n        vector<int> parent(N3), dist(N3), mark(N3, 0);\n\n        auto bfs_farthest = [&](int start) -> int {\n            fill(parent.begin(), parent.end(), -1);\n            fill(dist.begin(), dist.end(), -1);\n            queue<int> q;\n            q.push(start);\n            dist[start] = 0;\n            int best = start;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                if (dist[v] > dist[best]) best = v;\n                auto p = decode(v);\n                for (int dir = 0; dir < 6; dir++) {\n                    int nx = p.x + DX6[dir];\n                    int ny = p.y + DY6[dir];\n                    int nz = p.z + DZ6[dir];\n                    if (!inside(nx, ny, nz)) continue;\n                    int to = idx(nx, ny, nz);\n                    if (!alive[to] || !mark[to] || dist[to] != -1) continue;\n                    dist[to] = dist[v] + 1;\n                    parent[to] = v;\n                    q.push(to);\n                }\n            }\n            return best;\n        };\n\n        bool progress = true;\n        while (progress) {\n            progress = false;\n            vis.assign(N3, 0);\n            for (int s = 0; s < N3; s++) {\n                if (!alive[s] || vis[s]) continue;\n\n                vector<int> comp;\n                queue<int> q;\n                q.push(s);\n                vis[s] = 1;\n                while (!q.empty()) {\n                    int v = q.front(); q.pop();\n                    comp.push_back(v);\n                    auto p = decode(v);\n                    for (int dir = 0; dir < 6; dir++) {\n                        int nx = p.x + DX6[dir];\n                        int ny = p.y + DY6[dir];\n                        int nz = p.z + DZ6[dir];\n                        if (!inside(nx, ny, nz)) continue;\n                        int to = idx(nx, ny, nz);\n                        if (alive[to] && !vis[to]) {\n                            vis[to] = 1;\n                            q.push(to);\n                        }\n                    }\n                }\n\n                if ((int)comp.size() < 2) continue;\n                for (int v : comp) mark[v] = 1;\n                int a = bfs_farthest(comp[0]);\n                int b = bfs_farthest(a);\n\n                if (dist[b] >= 1) {\n                    vector<int> path;\n                    for (int v = b; v != -1; v = parent[v]) path.push_back(v);\n                    if ((int)path.size() >= 2) {\n                        Piece pc;\n                        pc.vox = path;\n                        pc.sig = canonical_signature_from_vox(pc.vox);\n                        pieces.push_back(move(pc));\n                        for (int v : path) alive[v] = 0;\n                        progress = true;\n                    }\n                }\n                for (int v : comp) mark[v] = 0;\n            }\n        }\n    };\n\n    auto residual_components = [&](const vector<char>& alive, vector<Piece>& pieces) {\n        vector<char> vis(N3, 0);\n        for (int s = 0; s < N3; s++) {\n            if (!alive[s] || vis[s]) continue;\n            queue<int> q;\n            q.push(s);\n            vis[s] = 1;\n            vector<int> vox;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                vox.push_back(v);\n                auto p = decode(v);\n                for (int dir = 0; dir < 6; dir++) {\n                    int nx = p.x + DX6[dir];\n                    int ny = p.y + DY6[dir];\n                    int nz = p.z + DZ6[dir];\n                    if (!inside(nx, ny, nz)) continue;\n                    int to = idx(nx, ny, nz);\n                    if (alive[to] && !vis[to]) {\n                        vis[to] = 1;\n                        q.push(to);\n                    }\n                }\n            }\n            Piece pc;\n            pc.vox = move(vox);\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n        }\n    };\n\n    enum DecompMode {\n        STRAIGHT_PATH_RESID = 0,\n        PATH_STRAIGHT_RESID = 1,\n        COMPONENT_ONLY = 2,\n        RECT_STRAIGHT_PATH_RESID = 3,\n        RECT_RESID = 4\n    };\n\n    auto decompose = [&](const vector<char>& occ, int mode) -> vector<Piece> {\n        vector<char> alive = occ;\n        vector<Piece> pieces;\n        if (mode == STRAIGHT_PATH_RESID) {\n            extract_straight_runs(alive, pieces);\n            extract_paths(alive, pieces);\n            residual_components(alive, pieces);\n        } else if (mode == PATH_STRAIGHT_RESID) {\n            extract_paths(alive, pieces);\n            extract_straight_runs(alive, pieces);\n            residual_components(alive, pieces);\n        } else if (mode == COMPONENT_ONLY) {\n            residual_components(alive, pieces);\n        } else if (mode == RECT_STRAIGHT_PATH_RESID) {\n            extract_rectangles(alive, pieces);\n            extract_straight_runs(alive, pieces);\n            extract_paths(alive, pieces);\n            residual_components(alive, pieces);\n        } else { // RECT_RESID\n            extract_rectangles(alive, pieces);\n            residual_components(alive, pieces);\n        }\n        return pieces;\n    };\n\n    auto proxy_score = [&](const vector<Piece>& p0, const vector<Piece>& p1) -> long long {\n        unordered_map<string, vector<int>> a, b;\n        a.reserve(p0.size() * 2 + 10);\n        b.reserve(p1.size() * 2 + 10);\n        for (auto &pc : p0) a[pc.sig].push_back((int)pc.vox.size());\n        for (auto &pc : p1) b[pc.sig].push_back((int)pc.vox.size());\n\n        long long score = 0;\n        for (auto &kv : a) {\n            auto it = b.find(kv.first);\n            if (it == b.end()) continue;\n            auto va = kv.second, vb = it->second;\n            sort(va.begin(), va.end(), greater<int>());\n            sort(vb.begin(), vb.end(), greater<int>());\n            int m = min((int)va.size(), (int)vb.size());\n            for (int i = 0; i < m; i++) {\n                int v = min(va[i], vb[i]);\n                score += 1000LL * v + 1LL * v * v;\n            }\n        }\n        return score;\n    };\n\n    auto choose_best_decompositions = [&](Candidate& cand) {\n        const int MODES = 5;\n        vector<vector<Piece>> dec0(MODES), dec1(MODES);\n        for (int m = 0; m < MODES; m++) dec0[m] = decompose(cand.occ0, m);\n        for (int m = 0; m < MODES; m++) dec1[m] = decompose(cand.occ1, m);\n\n        cand.proxy = LLONG_MIN;\n        for (int a = 0; a < MODES; a++) for (int b = 0; b < MODES; b++) {\n            long long sc = proxy_score(dec0[a], dec1[b]);\n            if (sc > cand.proxy) {\n                cand.proxy = sc;\n                cand.bestP0 = dec0[a];\n                cand.bestP1 = dec1[b];\n            }\n        }\n    };\n\n    auto build_candidate = [&](int intensity, bool reverse_order) -> Candidate {\n        Candidate cand;\n        vector<char> a0 = initial_build(0);\n        vector<char> a1 = initial_build(1);\n\n        int rounds = 5 + intensity / 15;\n        for (int it = 0; it < rounds; it++) {\n            if (!reverse_order) {\n                auto n0 = build_object(0, a1, a0, intensity);\n                auto n1 = build_object(1, n0, a1, intensity);\n                a0.swap(n0);\n                a1.swap(n1);\n            } else {\n                auto n1 = build_object(1, a0, a1, intensity);\n                auto n0 = build_object(0, n1, a0, intensity);\n                a0.swap(n0);\n                a1.swap(n1);\n            }\n        }\n\n        cand.occ0 = move(a0);\n        cand.occ1 = move(a1);\n        choose_best_decompositions(cand);\n        return cand;\n    };\n\n    Candidate best;\n    int multi = (D <= 7 ? 8 : (D <= 10 ? 6 : 5));\n    for (int t = 0; t < multi; t++) {\n        int intensity = 10 + 10 * t;\n        bool rev = (t & 1);\n        Candidate cand = build_candidate(intensity, rev);\n        if (cand.proxy > best.proxy) best = move(cand);\n    }\n\n    auto &pieces0 = best.bestP0;\n    auto &pieces1 = best.bestP1;\n\n    unordered_map<string, vector<int>> mp0, mp1;\n    mp0.reserve(pieces0.size() * 2 + 10);\n    mp1.reserve(pieces1.size() * 2 + 10);\n\n    for (int i = 0; i < (int)pieces0.size(); i++) mp0[pieces0[i].sig].push_back(i);\n    for (int i = 0; i < (int)pieces1.size(); i++) mp1[pieces1[i].sig].push_back(i);\n\n    for (auto &kv : mp0) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            return pieces0[a].vox.size() > pieces0[b].vox.size();\n        });\n    }\n    for (auto &kv : mp1) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            return pieces1[a].vox.size() > pieces1[b].vox.size();\n        });\n    }\n\n    vector<int> ans0(N3, 0), ans1(N3, 0);\n    int nBlocks = 0;\n\n    unordered_set<string> keys;\n    keys.reserve(mp0.size() + mp1.size() + 10);\n    for (auto &kv : mp0) keys.insert(kv.first);\n    for (auto &kv : mp1) keys.insert(kv.first);\n\n    for (const string &sig : keys) {\n        auto it0 = mp0.find(sig);\n        auto it1 = mp1.find(sig);\n        vector<int>* v0 = (it0 == mp0.end() ? nullptr : &it0->second);\n        vector<int>* v1 = (it1 == mp1.end() ? nullptr : &it1->second);\n\n        int c0 = v0 ? (int)v0->size() : 0;\n        int c1 = v1 ? (int)v1->size() : 0;\n        int m = min(c0, c1);\n\n        for (int i = 0; i < m; i++) {\n            ++nBlocks;\n            for (int id : pieces0[(*v0)[i]].vox) ans0[id] = nBlocks;\n            for (int id : pieces1[(*v1)[i]].vox) ans1[id] = nBlocks;\n        }\n        if (v0) {\n            for (int i = m; i < c0; i++) {\n                ++nBlocks;\n                for (int id : pieces0[(*v0)[i]].vox) ans0[id] = nBlocks;\n            }\n        }\n        if (v1) {\n            for (int i = m; i < c1; i++) {\n                ++nBlocks;\n                for (int id : pieces1[(*v1)[i]].vox) ans1[id] = nBlocks;\n            }\n        }\n    }\n\n    cout << nBlocks << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << ans0[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << ans1[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v, w;\n};\n\nstruct DijkstraResult {\n    vector<ll> dist;\n    vector<int> prev_v;\n    vector<int> prev_e;\n};\n\nstatic inline ll sqrll(ll x) { return x * x; }\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        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        g[u].push_back({v, i});\n        g[v].push_back({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    vector<vector<unsigned short>> reqR(N, vector<unsigned short>(K));\n    vector<vector<pair<unsigned short,int>>> sortedReq(N);\n    for (int v = 0; v < N; v++) {\n        sortedReq[v].reserve(K);\n        for (int k = 0; k < K; k++) {\n            ll dx = (ll)x[v] - a[k];\n            ll dy = (ll)y[v] - b[k];\n            long double d = sqrt((long double)dx * dx + (long double)dy * dy);\n            int r = (int)ceill(d - 1e-12L);\n            if (r > 5000) r = 5001;\n            reqR[v][k] = (unsigned short)r;\n            if (r <= 5000) sortedReq[v].push_back({(unsigned short)r, k});\n        }\n        sort(sortedReq[v].begin(), sortedReq[v].end());\n    }\n\n    auto dijkstra = [&](int s) -> DijkstraResult {\n        vector<ll> dist(N, INF64);\n        vector<int> prev_v(N, -1), prev_e(N, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                ll nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    prev_v[to] = v;\n                    prev_e[to] = ei;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        return {dist, prev_v, prev_e};\n    };\n\n    vector<vector<ll>> allDist(N, vector<ll>(N));\n    vector<vector<int>> allPrevV(N), allPrevE(N);\n    for (int s = 0; s < N; s++) {\n        auto res = dijkstra(s);\n        allDist[s] = move(res.dist);\n        allPrevV[s] = move(res.prev_v);\n        allPrevE[s] = move(res.prev_e);\n    }\n\n    auto reconstruct_path = [&](int s, int t, vector<char>& edge_on, vector<char>& vert_on, vector<int>* addedVerts = nullptr) {\n        int cur = t;\n        while (cur != s) {\n            int ei = allPrevE[s][cur];\n            int pv = allPrevV[s][cur];\n            if (ei < 0 || pv < 0) break;\n            edge_on[ei] = 1;\n            if (!vert_on[cur]) {\n                vert_on[cur] = 1;\n                if (addedVerts) addedVerts->push_back(cur);\n            }\n            if (!vert_on[pv]) {\n                vert_on[pv] = 1;\n                if (addedVerts) addedVerts->push_back(pv);\n            }\n            cur = pv;\n        }\n    };\n\n    auto build_network_from_terminals = [&](const vector<int>& terminals) {\n        vector<int> ts = terminals;\n        ts.push_back(0);\n        sort(ts.begin(), ts.end());\n        ts.erase(unique(ts.begin(), ts.end()), ts.end());\n\n        int T = (int)ts.size();\n        vector<ll> mincost(T, INF64);\n        vector<int> parent(T, -1);\n        vector<char> used(T, 0);\n        mincost[0] = 0;\n\n        for (int it = 0; it < T; it++) {\n            int v = -1;\n            for (int i = 0; i < T; i++) if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int to = 0; to < T; to++) if (!used[to]) {\n                ll w = allDist[ts[v]][ts[to]];\n                if (w < mincost[to]) {\n                    mincost[to] = w;\n                    parent[to] = v;\n                }\n            }\n        }\n\n        vector<char> edge_on(M, 0), vert_on(N, 0);\n        vert_on[0] = 1;\n        for (int i = 1; i < T; i++) {\n            reconstruct_path(ts[i], ts[parent[i]], edge_on, vert_on);\n        }\n        return pair(edge_on, vert_on);\n    };\n\n    auto prune_edges = [&](const vector<char>& edge_on, const vector<int>& P) {\n        vector<vector<pair<int,int>>> sg(N);\n        for (int i = 0; i < M; i++) if (edge_on[i]) {\n            int u = edges[i].u, v = edges[i].v;\n            sg[u].push_back({v, i});\n            sg[v].push_back({u, i});\n        }\n\n        vector<char> needV(N, 0), vis(N, 0), keepE(M, 0);\n        needV[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) needV[i] = 1;\n\n        function<bool(int,int)> dfs = [&](int v, int pe) -> bool {\n            vis[v] = 1;\n            bool need = needV[v];\n            for (auto [to, ei] : sg[v]) {\n                if (ei == pe) continue;\n                if (!vis[to]) {\n                    if (dfs(to, ei)) {\n                        keepE[ei] = 1;\n                        need = true;\n                    }\n                }\n            }\n            return need;\n        };\n        dfs(0, -1);\n        return keepE;\n    };\n\n    auto calc_cost = [&](const vector<int>& P, const vector<char>& edge_on) {\n        ll S = 0;\n        for (int i = 0; i < N; i++) S += 1LL * P[i] * P[i];\n        for (int i = 0; i < M; i++) if (edge_on[i]) S += edges[i].w;\n        return S;\n    };\n\n    auto power_cost = [&](const vector<int>& P) {\n        ll S = 0;\n        for (int i = 0; i < N; i++) S += 1LL * P[i] * P[i];\n        return S;\n    };\n\n    auto stations_from_P = [&](const vector<int>& P) {\n        vector<int> st;\n        for (int i = 0; i < N; i++) if (P[i] > 0) st.push_back(i);\n        return st;\n    };\n\n    auto assign_best = [&](const vector<int>& stations) {\n        vector<int> P(N, 0);\n        if (stations.empty()) return P;\n        for (int k = 0; k < K; k++) {\n            int bestV = -1;\n            int bestR = 5001;\n            for (int v : stations) {\n                int r = reqR[v][k];\n                if (r < bestR) {\n                    bestR = r;\n                    bestV = v;\n                }\n            }\n            if (bestV != -1 && bestR <= 5000) {\n                P[bestV] = max(P[bestV], bestR);\n            }\n        }\n        return P;\n    };\n\n    auto one_pass_delete = [&](vector<int> P) {\n        vector<int> stations = stations_from_P(P);\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n\n            sort(stations.begin(), stations.end(), [&](int lhs, int rhs) {\n                return P[lhs] < P[rhs];\n            });\n\n            for (int idx = 0; idx < (int)stations.size(); idx++) {\n                int rem = stations[idx];\n                vector<int> cand;\n                cand.reserve(stations.size() - 1);\n                for (int v : stations) if (v != rem) cand.push_back(v);\n                if (cand.empty()) continue;\n\n                bool ok = true;\n                for (int k = 0; k < K; k++) {\n                    int bestR = 5001;\n                    for (int v : cand) {\n                        int r = reqR[v][k];\n                        if (r < bestR) bestR = r;\n                    }\n                    if (bestR > 5000) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n\n                vector<int> newP = assign_best(cand);\n                if (power_cost(newP) <= power_cost(P)) {\n                    P.swap(newP);\n                    stations.swap(cand);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        return P;\n    };\n\n    auto add_one_station_if_good = [&](vector<int> P, const vector<char>& reachable) {\n        vector<int> curStations = stations_from_P(P);\n        vector<char> used(N, 0);\n        for (int v : curStations) used[v] = 1;\n\n        ll curCost = power_cost(P);\n        ll bestCost = curCost;\n        vector<int> bestP = P;\n        int bestAdd = -1;\n\n        for (int v = 0; v < N; v++) {\n            if (!reachable[v] || used[v]) continue;\n\n            vector<int> candStations = curStations;\n            candStations.push_back(v);\n            vector<int> candP = assign_best(candStations);\n            ll c = power_cost(candP);\n            if (c < bestCost) {\n                bestCost = c;\n                bestP.swap(candP);\n                bestAdd = v;\n            }\n        }\n\n        if (bestAdd != -1) {\n            bestP = one_pass_delete(bestP);\n            return bestP;\n        }\n        return P;\n    };\n\n    auto greedy_construct = [&](double beta) {\n        vector<int> P(N, 0);\n        vector<char> covered(K, 0);\n        int coveredCnt = 0;\n\n        vector<char> connectedV(N, 0), edge_on(M, 0), vert_on(N, 0);\n        connectedV[0] = 1;\n        vert_on[0] = 1;\n        vector<int> terminals;\n\n        vector<ll> connCost(N);\n        for (int v = 0; v < N; v++) connCost[v] = allDist[0][v];\n\n        while (coveredCnt < K) {\n            int bestV = -1, bestR = -1;\n            double bestScore = -1.0;\n\n            for (int v = 0; v < N; v++) {\n                int gain = 0;\n                int prevR = -1;\n                ll baseP2 = 1LL * P[v] * P[v];\n                ll connPenalty = connectedV[v] ? 0LL : connCost[v];\n\n                for (auto [r, k] : sortedReq[v]) {\n                    if (!covered[k]) gain++;\n                    if (r != prevR) {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double cost = (double)deltaPower + beta * (double)connPenalty;\n                            double score = (double)gain / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                        prevR = r;\n                    } else {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double cost = (double)deltaPower + beta * (double)connPenalty;\n                            double score = (double)gain / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) break;\n\n            if (P[bestV] == 0) terminals.push_back(bestV);\n            P[bestV] = max(P[bestV], bestR);\n\n            for (auto [r, k] : sortedReq[bestV]) {\n                if (r > bestR) break;\n                if (!covered[k]) {\n                    covered[k] = 1;\n                    coveredCnt++;\n                }\n            }\n\n            if (!connectedV[bestV]) {\n                ll best = INF64;\n                int bestSrc = -1;\n                for (int s = 0; s < N; s++) if (connectedV[s]) {\n                    if (allDist[s][bestV] < best) {\n                        best = allDist[s][bestV];\n                        bestSrc = s;\n                    }\n                }\n                vector<int> addedVerts;\n                reconstruct_path(bestSrc, bestV, edge_on, vert_on, &addedVerts);\n                for (int vtx : addedVerts) connectedV[vtx] = 1;\n                connectedV[0] = 1;\n\n                for (int nv : addedVerts) {\n                    for (int v = 0; v < N; v++) {\n                        if (allDist[nv][v] < connCost[v]) connCost[v] = allDist[nv][v];\n                    }\n                }\n            }\n        }\n\n        return tuple<vector<int>, vector<int>, vector<char>, vector<char>>(P, terminals, edge_on, vert_on);\n    };\n\n    auto recalc_cover_on_reachable = [&](const vector<char>& reachable) {\n        vector<int> P(N, 0);\n        vector<char> covered(K, 0);\n        int coveredCnt = 0;\n        vector<int> stations;\n\n        while (coveredCnt < K) {\n            int bestV = -1, bestR = -1;\n            double bestScore = -1.0;\n\n            for (int v = 0; v < N; v++) if (reachable[v]) {\n                int gain = 0;\n                int prevR = -1;\n                ll baseP2 = 1LL * P[v] * P[v];\n\n                for (auto [r, k] : sortedReq[v]) {\n                    if (!covered[k]) gain++;\n                    if (r != prevR) {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double score = (double)gain / max(1.0, (double)deltaPower);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                        prevR = r;\n                    } else {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double score = (double)gain / max(1.0, (double)deltaPower);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) break;\n\n            if (P[bestV] == 0) stations.push_back(bestV);\n            P[bestV] = max(P[bestV], bestR);\n\n            for (auto [r, k] : sortedReq[bestV]) {\n                if (r > bestR) break;\n                if (!covered[k]) {\n                    covered[k] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        return assign_best(stations);\n    };\n\n    auto polish_once = [&](vector<int> P) {\n        P = one_pass_delete(P);\n        vector<int> powered = stations_from_P(P);\n        auto [edge1, vert1] = build_network_from_terminals(powered);\n\n        vector<int> P2 = recalc_cover_on_reachable(vert1);\n        P2 = one_pass_delete(P2);\n\n        // New extra split improvement: add one reachable station if it reduces power.\n        P2 = add_one_station_if_good(P2, vert1);\n        P2 = one_pass_delete(P2);\n\n        vector<int> powered2 = stations_from_P(P2);\n        auto [edge2, vert2] = build_network_from_terminals(powered2);\n        auto edge3 = prune_edges(edge2, P2);\n\n        return pair(P2, edge3);\n    };\n\n    ll bestCost = INF64;\n    vector<int> bestP(N, 0);\n    vector<char> bestB(M, 0);\n\n    const double betas[] = {0.08, 0.15, 0.30, 0.55};\n\n    for (double beta : betas) {\n        auto [P0, terminals0, edge0, vert0] = greedy_construct(beta);\n\n        auto [edge1, vert1] = build_network_from_terminals(terminals0);\n\n        vector<int> P1 = recalc_cover_on_reachable(vert1);\n        P1 = one_pass_delete(P1);\n\n        vector<int> powered = stations_from_P(P1);\n        auto [edge2, vert2] = build_network_from_terminals(powered);\n        auto edge3 = prune_edges(edge2, P1);\n\n        ll cost = calc_cost(P1, edge3);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestP = P1;\n            bestB = edge3;\n        }\n\n        auto [P4, edge4] = polish_once(P1);\n        ll cost4 = calc_cost(P4, edge4);\n        if (cost4 < bestCost) {\n            bestCost = cost4;\n            bestP = P4;\n            bestB = edge4;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestB[i] ? 1 : 0);\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 V = 465;\nstatic constexpr int MAXK = 10000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> a(N);\n    for (int i = 0; i < N; i++) {\n        a[i].resize(i + 1);\n        for (int j = 0; j <= i; j++) cin >> a[i][j];\n    }\n\n    vector<pair<int,int>> pos(V);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j <= i; j++) {\n            pos[a[i][j]] = {i, j};\n        }\n    }\n\n    vector<Op> ops;\n    ops.reserve(MAXK);\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y <= x;\n    };\n\n    auto neighbors = [&](int x, int y) {\n        array<pair<int,int>, 6> cand = {{\n            {x-1, y-1}, {x-1, y},\n            {x, y-1},   {x, y+1},\n            {x+1, y},   {x+1, y+1}\n        }};\n        vector<pair<int,int>> res;\n        for (auto [nx, ny] : cand) if (inside(nx, ny)) res.push_back({nx, ny});\n        return res;\n    };\n\n    auto do_swap = [&](int x1, int y1, int x2, int y2) {\n        if ((int)ops.size() >= MAXK) return;\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    };\n\n    auto get_path = [&](pair<int,int> s, pair<int,int> t) {\n        static int dist[N][N];\n        static pair<int,int> pre[N][N];\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j <= i; j++) {\n                dist[i][j] = -1;\n                pre[i][j] = {-1, -1};\n            }\n        }\n        queue<pair<int,int>> q;\n        dist[s.first][s.second] = 0;\n        q.push(s);\n        while (!q.empty()) {\n            auto [x, y] = q.front(); q.pop();\n            if (x == t.first && y == t.second) break;\n            for (auto [nx, ny] : neighbors(x, y)) {\n                if (dist[nx][ny] != -1) continue;\n                dist[nx][ny] = dist[x][y] + 1;\n                pre[nx][ny] = {x, y};\n                q.push({nx, ny});\n            }\n        }\n        vector<pair<int,int>> path;\n        if (dist[t.first][t.second] == -1) return path;\n        pair<int,int> cur = t;\n        while (!(cur == s)) {\n            path.push_back(cur);\n            cur = pre[cur.first][cur.second];\n        }\n        path.push_back(s);\n        reverse(path.begin(), path.end());\n        return path;\n    };\n\n    // Initial constructive phase: same spirit as the best previous version.\n    vector<char> fixedv(V, 0);\n\n    for (int x = 0; x < N; x++) {\n        for (int y = 0; y <= x; y++) {\n            if ((int)ops.size() >= MAXK) break;\n\n            int bestVal = INT_MAX;\n            pair<int,int> bestPos = {-1, -1};\n\n            for (int i = x; i < N; i++) {\n                int j0 = (i == x ? y : 0);\n                for (int j = j0; j <= i; j++) {\n                    int v = a[i][j];\n                    if (!fixedv[v] && v < bestVal) {\n                        bestVal = v;\n                        bestPos = {i, j};\n                    }\n                }\n            }\n\n            if (bestPos.first == -1) continue;\n\n            auto path = get_path(bestPos, {x, y});\n            if (path.empty()) continue;\n\n            // Execute reversely so the chosen ball moves to target.\n            for (int k = (int)path.size() - 1; k >= 1; k--) {\n                if ((int)ops.size() >= MAXK) break;\n                auto [x1, y1] = path[k];\n                auto [x2, y2] = path[k - 1];\n                do_swap(x1, y1, x2, y2);\n            }\n\n            fixedv[bestVal] = 1;\n        }\n        if ((int)ops.size() >= MAXK) break;\n    }\n\n    auto total_bad = [&]() -> int {\n        int bad = 0;\n        for (int x = 0; x < N - 1; x++) {\n            for (int y = 0; y <= x; y++) {\n                if (a[x][y] > a[x+1][y]) bad++;\n                if (a[x][y] > a[x+1][y+1]) bad++;\n            }\n        }\n        return bad;\n    };\n\n    auto local_bad = [&](int x, int y) -> int {\n        int me = a[x][y];\n        int bad = 0;\n        if (x > 0) {\n            if (y > 0 && a[x-1][y-1] > me) bad++;\n            if (y < x && a[x-1][y] > me) bad++;\n        }\n        if (x + 1 < N) {\n            if (me > a[x+1][y]) bad++;\n            if (me > a[x+1][y+1]) bad++;\n        }\n        return bad;\n    };\n\n    // Stronger local repair:\n    // choose the adjacent swap with maximum local gain, repeat.\n    while ((int)ops.size() < MAXK) {\n        int bestGain = 0;\n        int bx1 = -1, by1 = -1, bx2 = -1, by2 = -1;\n\n        for (int x = 0; x < N; x++) {\n            for (int y = 0; y <= x; y++) {\n                for (auto [nx, ny] : neighbors(x, y)) {\n                    if (x > nx || (x == nx && y >= ny)) continue; // consider each edge once\n                    int before = local_bad(x, y) + local_bad(nx, ny);\n                    swap(a[x][y], a[nx][ny]);\n                    int after = local_bad(x, y) + local_bad(nx, ny);\n                    swap(a[x][y], a[nx][ny]);\n                    int gain = before - after;\n                    if (gain > bestGain) {\n                        bestGain = gain;\n                        bx1 = x; by1 = y; bx2 = nx; by2 = ny;\n                    }\n                }\n            }\n        }\n\n        if (bestGain <= 0) break;\n        do_swap(bx1, by1, bx2, by2);\n    }\n\n    // Additional deterministic heap-fix passes.\n    // Often helps if some inversions remain after greedy max-gain phase.\n    bool updated = true;\n    while (updated && (int)ops.size() < MAXK) {\n        updated = false;\n        for (int x = N - 2; x >= 0; x--) {\n            for (int y = 0; y <= x; y++) {\n                if ((int)ops.size() >= MAXK) break;\n                int cur = a[x][y];\n                int c1 = a[x+1][y];\n                int c2 = a[x+1][y+1];\n\n                if (cur > c1 || cur > c2) {\n                    if (c1 < c2) {\n                        do_swap(x, y, x+1, y);\n                    } else {\n                        do_swap(x, y, x+1, y+1);\n                    }\n                    updated = true;\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    return 0;\n}","toyota2023summer-final":"#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 D, N;\n    cin >> D >> N;\n\n    vector<vector<int>> obstacle(D, vector<int>(D, 0));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = 1;\n    }\n\n    const int ex = 0;\n    const int ey = (D - 1) / 2;\n    const int M = D * D - 1 - N;\n    const int INF = 1e9;\n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D;\n    };\n\n    // board: -2 obstacle, -1 empty, >=0 label\n    vector<vector<int>> board(D, vector<int>(D, -1));\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (obstacle[i][j]) board[i][j] = -2;\n        }\n    }\n\n    // Static shortest path distance from entrance ignoring containers.\n    vector<vector<int>> dist0(D, vector<int>(D, INF));\n    {\n        queue<Pos> q;\n        dist0[ex][ey] = 0;\n        q.push({ex, ey});\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + dx[dir], ny = y + dy[dir];\n                if (!inside(nx, ny) || obstacle[nx][ny]) continue;\n                if (dist0[nx][ny] > dist0[x][y] + 1) {\n                    dist0[nx][ny] = dist0[x][y] + 1;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    auto compute_conn_empty = [&]() {\n        vector<vector<int>> vis(D, vector<int>(D, 0));\n        queue<Pos> q;\n        vis[ex][ey] = 1;\n        q.push({ex, ey});\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + dx[dir], ny = y + dy[dir];\n                if (!inside(nx, ny) || vis[nx][ny]) continue;\n                if (board[nx][ny] == -1) {\n                    vis[nx][ny] = 1;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        return vis;\n    };\n\n    auto all_empty_reachable = [&]() -> bool {\n        auto vis = compute_conn_empty();\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (i == ex && j == ey) continue;\n                if (board[i][j] == -1 && !vis[i][j]) return false;\n            }\n        }\n        return true;\n    };\n\n    auto exposed_degree = [&](int x, int y, const vector<vector<int>>& conn) {\n        int cnt = 0;\n        for (int dir = 0; dir < 4; ++dir) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            if (!inside(nx, ny)) continue;\n            if (nx == ex && ny == ey) cnt++;\n            else if (board[nx][ny] == -1 && conn[nx][ny]) cnt++;\n        }\n        return cnt;\n    };\n\n    // Placement phase\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        auto conn = compute_conn_empty();\n\n        vector<Pos> safe;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (i == ex && j == ey) continue;\n                if (board[i][j] != -1) continue;\n                if (!conn[i][j]) continue; // must itself be reachable now\n\n                // Simulate occupying this cell; remaining empty cells must stay all reachable.\n                board[i][j] = M + 1000; // temporary occupied marker\n                bool ok = all_empty_reachable();\n                board[i][j] = -1;\n\n                if (ok) safe.push_back({i, j});\n            }\n        }\n\n        // There should always be at least one safe placement.\n        // To stay strictly legal, if something goes wrong, fall back only to currently reachable cells.\n        vector<Pos> cand = safe;\n        if (cand.empty()) {\n            for (int i = 0; i < D; ++i) {\n                for (int j = 0; j < D; ++j) {\n                    if (i == ex && j == ey) continue;\n                    if (board[i][j] == -1 && conn[i][j]) cand.push_back({i, j});\n                }\n            }\n        }\n\n        Pos best = cand[0];\n        long long bestScore = (1LL << 62);\n\n        for (auto p : cand) {\n            int d = dist0[p.x][p.y];\n            int e = exposed_degree(p.x, p.y, conn);\n\n            // small t => prefer shallow / exposed\n            // large t => prefer deep / less exposed\n            long long score = 0;\n            score += 1000LL * d * (2LL * t - (M - 1));\n            score += -100LL * e * (2LL * t - (M - 1));\n            score += 10LL * abs(p.y - ey);\n            score += p.x;\n            score += p.y;\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = p;\n            }\n        }\n\n        board[best.x][best.y] = t;\n        cout << best.x << ' ' << best.y << '\\n';\n        cout.flush();\n    }\n\n    auto removable_cells = [&]() {\n        auto conn = compute_conn_empty();\n        vector<Pos> res;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (board[i][j] < 0) continue;\n                bool ok = false;\n                for (int dir = 0; dir < 4; ++dir) {\n                    int nx = i + dx[dir], ny = j + dy[dir];\n                    if (!inside(nx, ny)) continue;\n                    if (nx == ex && ny == ey) {\n                        ok = true;\n                        break;\n                    }\n                    if (board[nx][ny] == -1 && conn[nx][ny]) {\n                        ok = true;\n                        break;\n                    }\n                }\n                if (ok) res.push_back({i, j});\n            }\n        }\n        return res;\n    };\n\n    // Retrieval phase\n    for (int step = 0; step < M; ++step) {\n        auto cand = removable_cells();\n\n        // This should never be empty in a legal state.\n        // If empty, we cannot output anything legal; but under our safe placements it should not happen.\n        Pos best = cand[0];\n        int bestLabel = board[best.x][best.y];\n        for (auto p : cand) {\n            if (board[p.x][p.y] < bestLabel) {\n                bestLabel = board[p.x][p.y];\n                best = p;\n            }\n        }\n\n        cout << best.x << ' ' << best.y << '\\n';\n        board[best.x][best.y] = -1;\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXC = 100;\n\nstruct Solver {\n    int n, m;\n    vector<vector<int>> orig, a, bestA;\n    bool origAdj[MAXC + 1][MAXC + 1]{};\n    bool canTouchZero[MAXC + 1]{};\n    int edgeCnt[MAXC + 1][MAXC + 1]{};\n    int colorCells[MAXC + 1]{};\n    mt19937 rng{(uint32_t)chrono::steady_clock::now().time_since_epoch().count()};\n\n    bool inside(int i, int j) const {\n        return 0 <= i && i < n && 0 <= j && j < n;\n    }\n\n    void addEdge(int x, int y, int d) {\n        if (x == y) return;\n        edgeCnt[x][y] += d;\n        edgeCnt[y][x] += d;\n    }\n\n    void buildOriginalInfo() {\n        memset(origAdj, 0, sizeof(origAdj));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = orig[i][j];\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    origAdj[0][c] = origAdj[c][0] = true;\n                }\n                if (i + 1 < n) {\n                    int d = orig[i + 1][j];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n                if (j + 1 < n) {\n                    int d = orig[i][j + 1];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n            }\n        }\n        for (int c = 1; c <= m; c++) canTouchZero[c] = origAdj[0][c];\n    }\n\n    void rebuildState() {\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(colorCells, 0, sizeof(colorCells));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                colorCells[a[i][j]]++;\n            }\n        }\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = a[i][j];\n                if (i == 0) addEdge(0, c, 1);\n                if (i == n - 1) addEdge(0, c, 1);\n                if (j == 0) addEdge(0, c, 1);\n                if (j == n - 1) addEdge(0, c, 1);\n                if (i + 1 < n) addEdge(c, a[i + 1][j], 1);\n                if (j + 1 < n) addEdge(c, a[i][j + 1], 1);\n            }\n        }\n    }\n\n    bool checkAdjRows(const vector<int>& rows) {\n        vector<int> rs = rows;\n        sort(rs.begin(), rs.end());\n        rs.erase(unique(rs.begin(), rs.end()), rs.end());\n        for (int x : rs) {\n            for (int y = 0; y <= m; y++) {\n                bool now = edgeCnt[x][y] > 0;\n                if (now != origAdj[x][y]) return false;\n            }\n        }\n        return true;\n    }\n\n    bool connectedColor(int color) {\n        if (color == 0) return zeroConnected();\n        if (colorCells[color] == 0) return false;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        bool found = false;\n        for (int i = 0; i < n && !found; i++) {\n            for (int j = 0; j < n && !found; j++) {\n                if (a[i][j] == color) {\n                    q.push({i, j});\n                    vis[i][j] = true;\n                    found = true;\n                }\n            }\n        }\n\n        int cnt = 0;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != color) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[color];\n    }\n\n    bool connectedColorLocalHint(int color, int hi, int hj) {\n        if (color == 0) return zeroConnected();\n        if (colorCells[color] == 0) return false;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        bool found = false;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int d = 0; d < 4 && !found; d++) {\n            int ni = hi + di[d], nj = hj + dj[d];\n            if (inside(ni, nj) && a[ni][nj] == color) {\n                q.push({ni, nj});\n                vis[ni][nj] = true;\n                found = true;\n            }\n        }\n        if (!found) {\n            // maybe the component exists elsewhere\n            for (int i = 0; i < n && !found; i++) {\n                for (int j = 0; j < n && !found; j++) {\n                    if (a[i][j] == color) {\n                        q.push({i, j});\n                        vis[i][j] = true;\n                        found = true;\n                    }\n                }\n            }\n        }\n\n        int cnt = 0;\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != color) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[color];\n    }\n\n    bool zeroConnected() {\n        if (colorCells[0] == 0) return true;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        for (int i = 0; i < n; i++) {\n            if (a[i][0] == 0 && !vis[i][0]) vis[i][0] = true, q.push({i, 0});\n            if (a[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 (a[0][j] == 0 && !vis[0][j]) vis[0][j] = true, q.push({0, j});\n            if (a[n - 1][j] == 0 && !vis[n - 1][j]) vis[n - 1][j] = true, q.push({n - 1, j});\n        }\n        if (q.empty()) return false;\n\n        int cnt = 0;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != 0) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[0];\n    }\n\n    int sameDeg(int i, int j) const {\n        int c = a[i][j], s = 0;\n        if (i > 0 && a[i - 1][j] == c) s++;\n        if (i + 1 < n && a[i + 1][j] == c) s++;\n        if (j > 0 && a[i][j - 1] == c) s++;\n        if (j + 1 < n && a[i][j + 1] == c) s++;\n        return s;\n    }\n\n    int zeroNbrs(int i, int j) const {\n        int s = 0;\n        if (i == 0 || a[i - 1][j] == 0) s++;\n        if (i == n - 1 || a[i + 1][j] == 0) s++;\n        if (j == 0 || a[i][j - 1] == 0) s++;\n        if (j == n - 1 || a[i][j + 1] == 0) s++;\n        return s;\n    }\n\n    vector<int> neighborhoodColors(int i, int j, int oldc, int newc) {\n        vector<int> v = {oldc, newc, 0};\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            v.push_back(inside(ni, nj) ? a[ni][nj] : 0);\n        }\n        sort(v.begin(), v.end());\n        v.erase(unique(v.begin(), v.end()), v.end());\n        return v;\n    }\n\n    void applyCellChangeCounts(int i, int j, int oldc, int newc, int sign) {\n        // sign = -1 means remove current contribution of oldc at (i,j)\n        // sign = +1 means add contribution of newc at (i,j)\n        if (i == 0) addEdge(0, (sign == -1 ? oldc : newc), sign);\n        if (i == n - 1) addEdge(0, (sign == -1 ? oldc : newc), sign);\n        if (j == 0) addEdge(0, (sign == -1 ? oldc : newc), sign);\n        if (j == n - 1) addEdge(0, (sign == -1 ? oldc : newc), sign);\n\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\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 oth = a[ni][nj];\n            addEdge((sign == -1 ? oldc : newc), oth, sign);\n        }\n    }\n\n    bool tryChange(int i, int j, int newc) {\n        int oldc = a[i][j];\n        if (oldc == newc) return false;\n        if (oldc != 0 && colorCells[oldc] <= 1) return false;\n\n        if (newc == 0) {\n            if (!canTouchZero[oldc]) return false;\n            static const int di[4] = {-1, 1, 0, 0};\n            static const int dj[4] = {0, 0, -1, 1};\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                int c = inside(ni, nj) ? a[ni][nj] : 0;\n                if (c != 0 && !canTouchZero[c]) return false;\n            }\n        } else {\n            // newc must be a color present in 4-neighborhood typically.\n            // Also if any zero is adjacent after recolor, newc must be able to touch zero.\n            if ((i == 0 || i == n - 1 || j == 0 || j == n - 1) && !canTouchZero[newc]) return false;\n            if (i > 0 && a[i - 1][j] == 0 && !canTouchZero[newc]) return false;\n            if (i + 1 < n && a[i + 1][j] == 0 && !canTouchZero[newc]) return false;\n            if (j > 0 && a[i][j - 1] == 0 && !canTouchZero[newc]) return false;\n            if (j + 1 < n && a[i][j + 1] == 0 && !canTouchZero[newc]) return false;\n        }\n\n        applyCellChangeCounts(i, j, oldc, newc, -1);\n\n        a[i][j] = newc;\n        colorCells[oldc]--;\n        colorCells[newc]++;\n\n        applyCellChangeCounts(i, j, oldc, newc, +1);\n\n        auto touched = neighborhoodColors(i, j, oldc, newc);\n\n        bool ok = true;\n        if (oldc != 0 && !connectedColorLocalHint(oldc, i, j)) ok = false;\n        if (ok && newc != 0 && !connectedColorLocalHint(newc, i, j)) ok = false;\n        if (ok && (oldc == 0 || newc == 0) && !zeroConnected()) ok = false;\n        if (ok && !checkAdjRows(touched)) ok = false;\n\n        if (!ok) {\n            a[i][j] = oldc;\n            rebuildState();\n            return false;\n        }\n        return true;\n    }\n\n    bool erasePass() {\n        vector<pair<array<int,4>, pair<int,int>>> cand;\n        cand.reserve(n * n);\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = a[i][j];\n                if (c == 0 || !canTouchZero[c]) continue;\n                int sd = sameDeg(i, j);\n                int zn = zeroNbrs(i, j);\n                int border = (i == 0 || i == n - 1 || j == 0 || j == n - 1) ? 0 : 1;\n                int rnd = (int)(rng() & 1023);\n                cand.push_back({{sd, -zn, border, rnd}, {i, j}});\n            }\n        }\n        sort(cand.begin(), cand.end(),\n             [](const auto& a, const auto& b) { return a.first < b.first; });\n\n        bool improved = false;\n        for (auto &e : cand) {\n            auto [i, j] = e.second;\n            if (a[i][j] == 0) continue;\n            if (tryChange(i, j, 0)) improved = true;\n        }\n        return improved;\n    }\n\n    bool recolorPass() {\n        vector<tuple<array<int,4>, int, int, int>> moves;\n        moves.reserve(n * n * 2);\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int oldc = a[i][j];\n                if (oldc == 0) continue;\n\n                set<int> neigh;\n                if (i > 0 && a[i - 1][j] != oldc && a[i - 1][j] != 0) neigh.insert(a[i - 1][j]);\n                if (i + 1 < n && a[i + 1][j] != oldc && a[i + 1][j] != 0) neigh.insert(a[i + 1][j]);\n                if (j > 0 && a[i][j - 1] != oldc && a[i][j - 1] != 0) neigh.insert(a[i][j - 1]);\n                if (j + 1 < n && a[i][j + 1] != oldc && a[i][j + 1] != 0) neigh.insert(a[i][j + 1]);\n\n                int sd = sameDeg(i, j);\n                int zn = zeroNbrs(i, j);\n                for (int nc : neigh) {\n                    // prioritize cells that are thin and close to zero\n                    int sameToNew = 0;\n                    if (i > 0 && a[i - 1][j] == nc) sameToNew++;\n                    if (i + 1 < n && a[i + 1][j] == nc) sameToNew++;\n                    if (j > 0 && a[i][j - 1] == nc) sameToNew++;\n                    if (j + 1 < n && a[i][j + 1] == nc) sameToNew++;\n                    int rnd = (int)(rng() & 1023);\n                    moves.push_back({{sd, -sameToNew, -zn, rnd}, i, j, nc});\n                }\n            }\n        }\n\n        sort(moves.begin(), moves.end(),\n             [](const auto& a, const auto& b) { return get<0>(a) < get<0>(b); });\n\n        bool improved = false;\n        int beforeZero = colorCells[0];\n\n        for (auto &mv : moves) {\n            int i = get<1>(mv), j = get<2>(mv), nc = get<3>(mv);\n            if (a[i][j] == 0 || a[i][j] == nc) continue;\n            // Only keep recolor if it is legal and likely useful.\n            int oldc = a[i][j];\n            if (!tryChange(i, j, nc)) continue;\n\n            // Very simple utility filter:\n            // keep if it increased zero-neighbor exposure or reduced local old-color degree.\n            int gain = zeroNbrs(i, j);\n            int keep = gain;\n            if (keep >= 1 || sameDeg(i, j) >= 2) {\n                improved = true;\n            } else {\n                // rollback if not promising enough\n                tryChange(i, j, oldc);\n            }\n        }\n\n        return improved || colorCells[0] > beforeZero;\n    }\n\n    int score() const {\n        return colorCells[0] + 1;\n    }\n\n    void solve() {\n        cin >> n >> m;\n        orig.assign(n, vector<int>(n));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) cin >> orig[i][j];\n        }\n\n        buildOriginalInfo();\n        a = orig;\n        rebuildState();\n        bestA = a;\n        int bestScore = score();\n\n        auto start = chrono::steady_clock::now();\n        int phase = 0;\n\n        while (true) {\n            phase++;\n            bool any = false;\n\n            any |= erasePass();\n            int sc = score();\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestA = a;\n            }\n\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.90) break;\n\n            any |= recolorPass();\n            sc = score();\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestA = a;\n            }\n\n            now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.90) break;\n\n            any |= erasePass();\n            sc = score();\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestA = a;\n            }\n\n            now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > 1.90) break;\n\n            if (!any) break;\n\n            // occasional reshuffle/rebuild for stability\n            if (phase % 3 == 0) rebuildState();\n        }\n\n        a = bestA;\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    }\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}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    // ---------------- interactive ----------------\n    int cmp_single(int a, int b) {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        ++used;\n        if (s == \"<\") return -1;\n        if (s == \">\") return 1;\n        return 0;\n    }\n\n    void dummy_query() {\n        int a = 0, b = min(1, N - 1);\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        ++used;\n    }\n\n    // ---------------- ordering ----------------\n    vector<int> insertion_sort_subset(const vector<int>& items, int budget_limit) {\n        vector<int> ord;\n        if (items.empty()) return ord;\n        ord.push_back(items[0]);\n        for (int ii = 1; ii < (int)items.size(); ++ii) {\n            int x = items[ii];\n            if (used >= budget_limit) {\n                ord.push_back(x);\n                continue;\n            }\n            int l = 0, r = (int)ord.size();\n            while (l < r && used < budget_limit) {\n                int m = (l + r) >> 1;\n                int c = cmp_single(x, ord[m]);\n                if (c < 0) r = m;\n                else l = m + 1;\n            }\n            ord.insert(ord.begin() + l, x);\n        }\n        return ord; // light -> heavy approximately\n    }\n\n    vector<int> build_order_two_phase(int budget_limit) {\n        // Choose number of anchors depending on budget.\n        // Total cost is roughly M log M + (N-M) log M.\n        int M = min(N, max(8, min(24, (int)round(sqrt((double)max(1, Q)) * 2.0))));\n        M = min(M, N);\n\n        vector<int> is_anchor(N, 0), anchors;\n        anchors.reserve(M);\n\n        // spread anchors by index\n        for (int k = 0; k < M; ++k) {\n            int idx = (long long)k * N / M;\n            if (idx >= N) idx = N - 1;\n            while (idx < N && is_anchor[idx]) idx++;\n            if (idx >= N) {\n                idx = N - 1;\n                while (idx >= 0 && is_anchor[idx]) idx--;\n            }\n            if (idx >= 0 && !is_anchor[idx]) {\n                is_anchor[idx] = 1;\n                anchors.push_back(idx);\n            }\n        }\n        // if duplicates reduced count\n        for (int i = 0; (int)anchors.size() < M && i < N; ++i) {\n            if (!is_anchor[i]) {\n                is_anchor[i] = 1;\n                anchors.push_back(i);\n            }\n        }\n\n        // sort anchors\n        vector<int> sorted_anchors = insertion_sort_subset(anchors, budget_limit);\n\n        // classify others into M+1 buckets by binary search on anchors\n        vector<vector<int>> buckets(M + 1);\n        for (int x = 0; x < N; ++x) {\n            if (is_anchor[x]) continue;\n\n            int l = 0, r = M;\n            while (l < r && used < budget_limit) {\n                int m = (l + r) >> 1;\n                if (m == M) {\n                    r = m;\n                    continue;\n                }\n                int c = cmp_single(x, sorted_anchors[m]);\n                if (c < 0) r = m;\n                else l = m + 1;\n            }\n            buckets[l].push_back(x);\n        }\n\n        // Build final order: bucket0, a0, bucket1, a1, ..., bucketM\n        vector<int> ord;\n        ord.reserve(N);\n        for (int i = 0; i < M; ++i) {\n            for (int x : buckets[i]) ord.push_back(x);\n            ord.push_back(sorted_anchors[i]);\n        }\n        for (int x : buckets[M]) ord.push_back(x);\n\n        return ord; // light -> heavy coarse order\n    }\n\n    vector<int> build_order_hybrid(int budget_limit) {\n        // For larger budgets, use plain insertion sort on all items.\n        // For smaller budgets, use two-phase order.\n        int threshold = (int)(N * 4.5);\n        if (Q >= threshold) {\n            vector<int> all(N);\n            iota(all.begin(), all.end(), 0);\n            return insertion_sort_subset(all, budget_limit);\n        } else {\n            return build_order_two_phase(budget_limit);\n        }\n    }\n\n    // ---------------- pseudo weights ----------------\n    vector<int> rank_pos_from_ord(const vector<int>& ord) {\n        vector<int> pos(N);\n        for (int i = 0; i < N; ++i) pos[ord[i]] = i;\n        return pos;\n    }\n\n    vector<double> make_pw_exp(const vector<int>& pos, double alpha = 5.0) {\n        vector<double> pw(N);\n        for (int i = 0; i < N; ++i) {\n            double t = (pos[i] + 0.5) / N;\n            pw[i] = exp(alpha * t);\n        }\n        return pw;\n    }\n\n    // ---------------- objective ----------------\n    vector<double> calc_loads(const vector<int>& asg, const vector<double>& pw) {\n        vector<double> load(D, 0.0);\n        for (int i = 0; i < N; ++i) load[asg[i]] += pw[i];\n        return load;\n    }\n\n    double objective(const vector<int>& asg, const vector<double>& pw) {\n        auto load = calc_loads(asg, pw);\n        double mean = 0.0;\n        for (double x : load) mean += x;\n        mean /= D;\n        double var = 0.0;\n        for (double x : load) {\n            double y = x - mean;\n            var += y * y;\n        }\n        return var / D;\n    }\n\n    // ---------------- assignment ----------------\n    vector<int> greedy_lpt(const vector<int>& ord, const vector<double>& pw, int tie_mode) {\n        vector<int> asg(N, 0);\n        vector<double> load(D, 0.0);\n\n        for (int idx = N - 1; idx >= 0; --idx) {\n            int item = ord[idx];\n            int best = 0;\n            for (int d = 1; d < D; ++d) {\n                if (load[d] < load[best] - 1e-12) best = d;\n                else if (fabs(load[d] - load[best]) <= 1e-12) {\n                    if (tie_mode == 1 && d < best) best = d;\n                    if (tie_mode == 2 && d > best) best = d;\n                }\n            }\n            asg[item] = best;\n            load[best] += pw[item];\n        }\n        return asg;\n    }\n\n    // ---------------- local search ----------------\n    void local_search(vector<int>& asg, const vector<double>& pw, const vector<int>& pos) {\n        double cur = objective(asg, pw);\n\n        vector<int> items(N);\n        iota(items.begin(), items.end(), 0);\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            return pos[a] > pos[b]; // heavy first\n        });\n\n        for (int phase = 0; phase < 8; ++phase) {\n            bool improved = false;\n\n            // 1) best move among top-heavy items\n            {\n                double best = cur;\n                int bestItem = -1, bestTo = -1;\n                int K = min(N, 30);\n                for (int ii = 0; ii < K; ++ii) {\n                    int item = items[ii];\n                    int from = asg[item];\n                    for (int to = 0; to < D; ++to) {\n                        if (to == from) continue;\n                        int old = asg[item];\n                        asg[item] = to;\n                        double sc = objective(asg, pw);\n                        asg[item] = old;\n                        if (sc + 1e-12 < best) {\n                            best = sc;\n                            bestItem = item;\n                            bestTo = to;\n                        }\n                    }\n                }\n                if (bestItem != -1) {\n                    asg[bestItem] = bestTo;\n                    cur = best;\n                    improved = true;\n                }\n            }\n            if (improved) continue;\n\n            // 2) best swap involving one heavy candidate\n            {\n                double best = cur;\n                int besta = -1, bestb = -1;\n\n                int Kheavy = min(N, 24);\n                vector<int> candB;\n                for (int i = 0; i < min(N, 50); ++i) candB.push_back(items[i]);\n                for (int i = max(0, N - 12); i < N; ++i) candB.push_back(items[i]);\n                sort(candB.begin(), candB.end());\n                candB.erase(unique(candB.begin(), candB.end()), candB.end());\n\n                for (int ia = 0; ia < Kheavy; ++ia) {\n                    int a = items[ia];\n                    for (int b : candB) {\n                        if (a == b || asg[a] == asg[b]) continue;\n                        swap(asg[a], asg[b]);\n                        double sc = objective(asg, pw);\n                        swap(asg[a], asg[b]);\n                        if (sc + 1e-12 < best) {\n                            best = sc;\n                            besta = a;\n                            bestb = b;\n                        }\n                    }\n                }\n\n                if (besta != -1) {\n                    swap(asg[besta], asg[bestb]);\n                    cur = best;\n                    improved = true;\n                }\n            }\n            if (improved) continue;\n\n            // 3) fallback best single move over all items\n            {\n                double best = cur;\n                int bestItem = -1, bestTo = -1;\n                for (int item : items) {\n                    int from = asg[item];\n                    for (int to = 0; to < D; ++to) {\n                        if (to == from) continue;\n                        int old = asg[item];\n                        asg[item] = to;\n                        double sc = objective(asg, pw);\n                        asg[item] = old;\n                        if (sc + 1e-12 < best) {\n                            best = sc;\n                            bestItem = item;\n                            bestTo = to;\n                        }\n                    }\n                }\n                if (bestItem != -1) {\n                    asg[bestItem] = bestTo;\n                    cur = best;\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    // ---------------- solve ----------------\n    void solve() {\n        cin >> N >> D >> Q;\n\n        int reserve_dummy = 2;\n        int budget_limit = max(0, Q - reserve_dummy);\n\n        vector<int> ord = build_order_hybrid(budget_limit);\n        vector<int> pos = rank_pos_from_ord(ord);\n        vector<double> pw = make_pw_exp(pos, 5.0);\n\n        vector<int> best_asg;\n        double best_obj = 1e100;\n\n        for (int tie_mode = 0; tie_mode < 3; ++tie_mode) {\n            vector<int> asg = greedy_lpt(ord, pw, tie_mode);\n            local_search(asg, pw, pos);\n            double sc = objective(asg, pw);\n            if (sc < best_obj) {\n                best_obj = sc;\n                best_asg = asg;\n            }\n        }\n\n        while (used < Q) dummy_query();\n\n        for (int i = 0; i < N; ++i) {\n            if (i) cout << ' ';\n            cout << best_asg[i];\n        }\n        cout << '\\n';\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    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Params {\n    int lookaheadW;\n    int beamWidth;\n    int maxDepth;\n    int destCandLimit;\n    int rolloutTargets;\n    long long costWeight;\n    long long exposedBonus;\n    long long abovePenalty;\n    long long stackSizePenalty;\n    long long urg5Penalty;\n    long long urg12Penalty;\n    long long urg25Penalty;\n    long long smallMinHeightPenalty;\n    long long destConflictAll;\n    long long destConflictTop;\n    long long destHeightPenalty;\n    long long destResultHeightPenalty;\n    long long rolloutWeight;\n};\n\nstruct Node {\n    vector<vector<int>> st;\n    vector<pair<int,int>> ops;\n    int cost = 0;\n    long long score = 0;\n};\n\nstruct RunResult {\n    vector<pair<int,int>> ops;\n    long long energy = (1LL << 60);\n};\n\nstruct Engine {\n    int n, m;\n    vector<vector<int>> init_st;\n    Params P;\n\n    Engine(int n_, int m_, const vector<vector<int>>& init_st_, const Params& P_)\n        : n(n_), m(m_), init_st(init_st_), P(P_) {}\n\n    pair<int,int> find_box(const vector<vector<int>>& st, int x) const {\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < (int)st[i].size(); j++) {\n                if (st[i][j] == x) return {i, j};\n            }\n        }\n        return {-1, -1};\n    }\n\n    int min_in_stack(const vector<int>& v) const {\n        if (v.empty()) return (int)1e9;\n        int mn = (int)1e9;\n        for (int x : v) mn = min(mn, x);\n        return mn;\n    }\n\n    int min_top_window(const vector<int>& v, int w = 6) const {\n        if (v.empty()) return (int)1e9;\n        int mn = (int)1e9;\n        int sz = (int)v.size();\n        for (int i = max(0, sz - w); i < sz; i++) mn = min(mn, v[i]);\n        return mn;\n    }\n\n    void apply_move(vector<vector<int>>& st, int from, int pos, int to) const {\n        vector<int> moved(st[from].begin() + pos, st[from].end());\n        st[from].erase(st[from].begin() + pos, st[from].end());\n        st[to].insert(st[to].end(), moved.begin(), moved.end());\n    }\n\n    long long base_heuristic(const vector<vector<int>>& st, int need) const {\n        long long penalty = 0;\n\n        for (int x = need; x <= min(n, need + P.lookaheadW - 1); x++) {\n            auto [s, p] = find_box(st, x);\n            if (s == -1) continue;\n            int above = (int)st[s].size() - 1 - p;\n            int w = need + P.lookaheadW - x;\n\n            penalty += P.abovePenalty * w * above;\n            penalty += P.stackSizePenalty * w * (int)st[s].size();\n\n            for (int i = p + 1; i < (int)st[s].size(); i++) {\n                int y = st[s][i];\n                if (y <= x + 5) penalty += P.urg5Penalty * w;\n                else if (y <= x + 12) penalty += P.urg12Penalty * w;\n                else if (y <= x + 25) penalty += P.urg25Penalty * w;\n                else penalty += 1LL * w;\n            }\n        }\n\n        for (int s = 0; s < m; s++) {\n            int mn = min_in_stack(st[s]);\n            int h = (int)st[s].size();\n            if (mn < (int)1e9) {\n                int urg = max(0, 40 - mn);\n                penalty += P.smallMinHeightPenalty * urg * h;\n            }\n        }\n\n        return penalty;\n    }\n\n    long long destination_bias(const vector<vector<int>>& st, int to, int moved_min, int moved_sz) const {\n        int mn_all = min_in_stack(st[to]);\n        int mn_top = min_top_window(st[to], 6);\n        int h = (int)st[to].size();\n\n        long long val = 0;\n        val += P.destHeightPenalty * h;\n        val += P.destResultHeightPenalty * (h + moved_sz);\n\n        if (!st[to].empty()) {\n            if (mn_all < moved_min) val += P.destConflictAll;\n            if (mn_top < moved_min) val += P.destConflictTop;\n            val += 2LL * max(0, 80 - mn_all);\n            val += 2LL * max(0, 80 - mn_top);\n        }\n        return val;\n    }\n\n    int best_static_destination(const vector<vector<int>>& st, int from, int moved_min, int moved_sz, int need) const {\n        int forbid1 = -1, forbid2 = -1, forbid3 = -1;\n        if (need + 1 <= n) forbid1 = find_box(st, need + 1).first;\n        if (need + 2 <= n) forbid2 = find_box(st, need + 2).first;\n        if (need + 3 <= n) forbid3 = find_box(st, need + 3).first;\n\n        long long best = (1LL << 62);\n        int bestTo = -1;\n        for (int to = 0; to < m; to++) {\n            if (to == from) continue;\n            long long v = destination_bias(st, to, moved_min, moved_sz);\n            if (to == forbid1) v += 1500;\n            if (to == forbid2) v += 800;\n            if (to == forbid3) v += 400;\n            if (v < best) {\n                best = v;\n                bestTo = to;\n            }\n        }\n        return bestTo;\n    }\n\n    long long rollout_estimate(vector<vector<int>> st, int need) const {\n        long long est = 0;\n        int last = min(n, need + P.rolloutTargets - 1);\n\n        for (int x = need; x <= last; x++) {\n            while (true) {\n                auto [s, p] = find_box(st, x);\n                if (s == -1) break;\n                if (p == (int)st[s].size() - 1) {\n                    st[s].pop_back();\n                    break;\n                }\n                int pos = p + 1; // whole blocker suffix\n                int moved_sz = (int)st[s].size() - pos;\n                int moved_min = (int)1e9;\n                for (int i = pos; i < (int)st[s].size(); i++) moved_min = min(moved_min, st[s][i]);\n                int to = best_static_destination(st, s, moved_min, moved_sz, x);\n                est += moved_sz + 1;\n                apply_move(st, s, pos, to);\n            }\n        }\n        return est;\n    }\n\n    long long heuristic(const vector<vector<int>>& st, int need) const {\n        long long h = base_heuristic(st, need);\n        if (P.rolloutTargets > 0) {\n            h += P.rolloutWeight * rollout_estimate(st, need);\n        }\n        return h;\n    }\n\n    vector<int> candidate_cut_positions(const vector<vector<int>>& st, int s, int need_pos) const {\n        vector<int> cand;\n        int top = (int)st[s].size() - 1;\n        if (need_pos == top) return cand;\n        int start = need_pos + 1;\n\n        cand.push_back(start);\n\n        int best = (int)1e9;\n        for (int i = start; i <= top; i++) {\n            if (st[s][i] < best) {\n                best = st[s][i];\n                cand.push_back(i);\n            }\n        }\n\n        cand.push_back(top);\n        if (top - 1 >= start) cand.push_back(top - 1);\n        if (top - 2 >= start) cand.push_back(top - 2);\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    }\n\n    vector<int> candidate_destinations(const vector<vector<int>>& st, int from, int moved_min, int moved_sz, int need) const {\n        vector<pair<long long,int>> cand;\n\n        int forbid1 = -1, forbid2 = -1, forbid3 = -1;\n        if (need + 1 <= n) forbid1 = find_box(st, need + 1).first;\n        if (need + 2 <= n) forbid2 = find_box(st, need + 2).first;\n        if (need + 3 <= n) forbid3 = find_box(st, need + 3).first;\n\n        for (int to = 0; to < m; to++) {\n            if (to == from) continue;\n            long long v = destination_bias(st, to, moved_min, moved_sz);\n            if (to == forbid1) v += 1500;\n            if (to == forbid2) v += 800;\n            if (to == forbid3) v += 400;\n            cand.push_back({v, to});\n        }\n        sort(cand.begin(), cand.end());\n\n        vector<int> res;\n        int lim = min(P.destCandLimit, (int)cand.size());\n        for (int i = 0; i < lim; i++) res.push_back(cand[i].second);\n        return res;\n    }\n\n    string encode_state(const vector<vector<int>>& st) const {\n        string s;\n        s.reserve(512);\n        for (int i = 0; i < m; i++) {\n            for (int x : st[i]) {\n                s.push_back((char)(unsigned char)x);\n                s.push_back((char)(unsigned char)(x >> 8));\n            }\n            s.push_back((char)255);\n        }\n        return s;\n    }\n\n    vector<pair<int,int>> expose_with_beam(const vector<vector<int>>& current, int need) const {\n        auto [ss, pp] = find_box(current, need);\n        if (pp == (int)current[ss].size() - 1) return {};\n\n        Node root;\n        root.st = current;\n        root.cost = 0;\n        root.score = heuristic(root.st, need);\n\n        vector<Node> beam{root};\n        bool found_terminal = false;\n        Node best_terminal;\n        long long best_terminal_key = (1LL << 62);\n\n        for (int depth = 0; depth < P.maxDepth; depth++) {\n            vector<Node> nxt;\n            unordered_map<string, long long> bestSeen;\n            bestSeen.reserve(256);\n\n            for (const auto& node : beam) {\n                auto [s, p] = find_box(node.st, need);\n                if (p == (int)node.st[s].size() - 1) {\n                    long long key = 1000LL * node.cost + heuristic(node.st, need);\n                    if (key < best_terminal_key) {\n                        best_terminal_key = key;\n                        best_terminal = node;\n                        found_terminal = true;\n                    }\n                    continue;\n                }\n\n                vector<int> cuts = candidate_cut_positions(node.st, s, p);\n                for (int pos : cuts) {\n                    int moved_sz = (int)node.st[s].size() - pos;\n                    int moved_min = (int)1e9;\n                    for (int i = pos; i < (int)node.st[s].size(); i++) moved_min = min(moved_min, node.st[s][i]);\n\n                    vector<int> dsts = candidate_destinations(node.st, s, moved_min, moved_sz, need);\n                    for (int to : dsts) {\n                        Node child = node;\n                        int v = child.st[s][pos];\n                        apply_move(child.st, s, pos, to);\n                        child.ops.push_back({v, to + 1});\n                        child.cost += moved_sz + 1;\n\n                        long long h = heuristic(child.st, need);\n                        child.score = P.costWeight * child.cost + h;\n\n                        auto [ns, np] = find_box(child.st, need);\n                        if (np == (int)child.st[ns].size() - 1) child.score -= P.exposedBonus;\n\n                        string key = encode_state(child.st);\n                        auto it = bestSeen.find(key);\n                        if (it == bestSeen.end() || child.score < it->second) {\n                            bestSeen[key] = child.score;\n                            nxt.push_back(std::move(child));\n                        }\n                    }\n                }\n            }\n\n            if (nxt.empty()) break;\n\n            sort(nxt.begin(), nxt.end(), [](const Node& a, const Node& b) {\n                if (a.score != b.score) return a.score < b.score;\n                return a.cost < b.cost;\n            });\n            if ((int)nxt.size() > P.beamWidth) nxt.resize(P.beamWidth);\n            beam = std::move(nxt);\n        }\n\n        for (const auto& node : beam) {\n            auto [s, p] = find_box(node.st, need);\n            if (p == (int)node.st[s].size() - 1) {\n                long long key = 1000LL * node.cost + heuristic(node.st, need);\n                if (key < best_terminal_key) {\n                    best_terminal_key = key;\n                    best_terminal = node;\n                    found_terminal = true;\n                }\n            }\n        }\n\n        if (found_terminal) return best_terminal.ops;\n\n        auto [s, p] = find_box(current, need);\n        vector<int> cuts = candidate_cut_positions(current, s, p);\n\n        long long bestScore = (1LL << 62);\n        pair<int,int> bestMove = {-1, -1};\n\n        for (int pos : cuts) {\n            int moved_sz = (int)current[s].size() - pos;\n            int moved_min = (int)1e9;\n            for (int i = pos; i < (int)current[s].size(); i++) moved_min = min(moved_min, current[s][i]);\n            vector<int> dsts = candidate_destinations(current, s, moved_min, moved_sz, need);\n            for (int to : dsts) {\n                auto st2 = current;\n                apply_move(st2, s, pos, to);\n                long long val = P.costWeight * (moved_sz + 1) + heuristic(st2, need);\n                if (val < bestScore) {\n                    bestScore = val;\n                    bestMove = {pos, to};\n                }\n            }\n        }\n\n        if (bestMove.first != -1) {\n            int v = current[s][bestMove.first];\n            return {{v, bestMove.second + 1}};\n        }\n\n        int pos = p + 1;\n        int v = current[s][pos];\n        int to = -1, besth = (int)1e9;\n        for (int j = 0; j < m; j++) if (j != s) {\n            if ((int)current[j].size() < besth) {\n                besth = (int)current[j].size();\n                to = j;\n            }\n        }\n        return {{v, to + 1}};\n    }\n\n    RunResult run() const {\n        vector<vector<int>> st = init_st;\n        vector<pair<int,int>> ans;\n        long long energy = 0;\n\n        auto apply_real_move = [&](int v, int to1based) {\n            int to = to1based - 1;\n            auto [s, p] = find_box(st, v);\n            int moved_sz = (int)st[s].size() - p;\n            energy += moved_sz + 1;\n            ans.push_back({v, to1based});\n            apply_move(st, s, p, to);\n        };\n\n        auto remove_real = [&](int need) {\n            auto [s, p] = find_box(st, need);\n            ans.push_back({need, 0});\n            st[s].pop_back();\n        };\n\n        for (int need = 1; need <= n; need++) {\n            while (true) {\n                auto [s, p] = find_box(st, need);\n                if (p == (int)st[s].size() - 1) {\n                    remove_real(need);\n                    break;\n                }\n\n                auto ops = expose_with_beam(st, need);\n                if (ops.empty()) continue;\n\n                for (auto [v, to] : ops) {\n                    apply_real_move(v, to);\n                    if ((int)ans.size() > 4900) break;\n                }\n                if ((int)ans.size() > 4900) break;\n            }\n            if ((int)ans.size() > 4900) break;\n        }\n\n        return {ans, energy};\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    vector<vector<int>> init_st(m, vector<int>(n / m));\n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < n / m; j++) cin >> init_st[i][j];\n    }\n\n    vector<Params> plist = {\n        {\n            18, 12, 4, 4, 2,\n            900, 50000,\n            140, 5, 55, 20, 6, 3,\n            2800, 1800, 60, 10,\n            40\n        },\n        {\n            18, 12, 4, 4, 3,\n            890, 51000,\n            142, 5, 56, 20, 6, 3,\n            2820, 1820, 60, 10,\n            30\n        },\n        {\n            18, 12, 4, 4, 2,\n            930, 47000,\n            136, 5, 52, 18, 5, 3,\n            2700, 1750, 58, 10,\n            35\n        }\n    };\n\n    RunResult best;\n    for (const auto& P : plist) {\n        Engine engine(n, m, init_st, P);\n        RunResult r = engine.run();\n        if (r.energy < best.energy) best = std::move(r);\n    }\n\n    for (auto [v, i] : best.ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#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\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n\n    int N;\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    vector<vector<int>> d2(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> d2[i][j];\n\n    const 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++) dirt[id(i,j)] = d2[i][j];\n\n    vector<vector<int>> adj(V);\n    vector<vector<char>> adjDir(V);\n\n    auto add_edge = [&](int a, int b, char c) {\n        adj[a].push_back(b);\n        adjDir[a].push_back(c);\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = id(i, j);\n            if (i > 0 && h[i - 1][j] == '0') add_edge(u, id(i - 1, j), 'U');\n            if (i + 1 < N && h[i][j] == '0') add_edge(u, id(i + 1, j), 'D');\n            if (j > 0 && v[i][j - 1] == '0') add_edge(u, id(i, j - 1), 'L');\n            if (j + 1 < N && v[i][j] == '0') add_edge(u, id(i, j + 1), 'R');\n        }\n    }\n\n    // All-pairs shortest paths via BFS\n    vector<vector<short>> dist(V, vector<short>(V, -1));\n    vector<vector<short>> parent(V, vector<short>(V, -1));\n    vector<vector<char>> parentDir(V, vector<char>(V, '?'));\n\n    {\n        vector<int> q(V);\n        for (int s = 0; s < V; s++) {\n            int ql = 0, qr = 0;\n            q[qr++] = s;\n            dist[s][s] = 0;\n            parent[s][s] = s;\n\n            while (ql < qr) {\n                int u = q[ql++];\n\n                vector<int> ord(adj[u].size());\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int va = adj[u][a], vb = adj[u][b];\n                    if (dirt[va] != dirt[vb]) return dirt[va] > dirt[vb];\n                    return va < vb;\n                });\n\n                for (int idx : ord) {\n                    int to = adj[u][idx];\n                    if (dist[s][to] == -1) {\n                        dist[s][to] = dist[s][u] + 1;\n                        parent[s][to] = u;\n                        parentDir[s][to] = adjDir[u][idx];\n                        q[qr++] = to;\n                    }\n                }\n            }\n        }\n    }\n\n    auto get_path = [&](int s, int t) -> string {\n        if (s == t) return \"\";\n        string revp;\n        int cur = t;\n        while (cur != s) {\n            revp.push_back(parentDir[s][cur]);\n            cur = parent[s][cur];\n        }\n        reverse(revp.begin(), revp.end());\n        return revp;\n    };\n\n    auto build_route = [&](const vector<int>& seq) -> string {\n        string route;\n        int cur = 0;\n        for (int x : seq) {\n            route += get_path(cur, x);\n            cur = x;\n        }\n        route += get_path(cur, 0);\n        return route;\n    };\n\n    auto route_len = [&](const vector<int>& seq) -> int {\n        int cur = 0, len = 0;\n        for (int x : seq) {\n            len += dist[cur][x];\n            cur = x;\n        }\n        len += dist[cur][0];\n        return len;\n    };\n\n    auto score_route = [&](const string& route) -> long long {\n        int L = (int)route.size();\n        if (L <= 0 || L > 100000) return (long long)4e18;\n\n        vector<vector<int>> visits(V);\n        int cur = 0;\n        for (int t = 1; t <= L; t++) {\n            auto [i, j] = pos(cur);\n            char c = route[t - 1];\n            if (c == 'U') --i;\n            else if (c == 'D') ++i;\n            else if (c == 'L') --j;\n            else ++j;\n            cur = id(i, j);\n            visits[cur].push_back(t);\n        }\n        if (cur != 0) return (long long)4e18;\n\n        visits[0].insert(visits[0].begin(), 0);\n\n        long double total = 0;\n        for (int u = 0; u < V; u++) {\n            if (visits[u].empty()) return (long long)4e18;\n            long long sum = 0;\n            auto &vec = visits[u];\n            for (int i = 0; i + 1 < (int)vec.size(); i++) {\n                long long g = vec[i + 1] - vec[i];\n                sum += g * (g - 1) / 2;\n            }\n            long long g = L - vec.back() + vec[0];\n            sum += g * (g - 1) / 2;\n            total += (long double)dirt[u] * (long double)sum;\n        }\n        return llround(total / (long double)L);\n    };\n\n    auto normalize_unique = [&](vector<int> seq) {\n        vector<char> seen(V, 0);\n        vector<int> out;\n        out.reserve(V - 1);\n        for (int x : seq) {\n            if (x == 0) continue;\n            if (!seen[x]) {\n                seen[x] = 1;\n                out.push_back(x);\n            }\n        }\n        for (int x = 1; x < V; x++) if (!seen[x]) out.push_back(x);\n        return out;\n    };\n\n    string bestRoute;\n    long long bestScore = (long long)4e18;\n    vector<int> bestSeq;\n\n    auto try_seq = [&](const vector<int>& seq) {\n        int len = route_len(seq);\n        if (len <= 0 || len > 100000) return;\n        string route = build_route(seq);\n        long long sc = score_route(route);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n            bestSeq = seq;\n        }\n    };\n\n    vector<vector<int>> baseCandidates;\n\n    // Row snake\n    {\n        vector<int> seq;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) seq.push_back(id(i, j));\n            else for (int j = N - 1; j >= 0; j--) seq.push_back(id(i, j));\n        }\n        seq = normalize_unique(seq);\n        baseCandidates.push_back(seq);\n        reverse(seq.begin(), seq.end());\n        baseCandidates.push_back(seq);\n    }\n\n    // Column snake\n    {\n        vector<int> seq;\n        for (int j = 0; j < N; j++) {\n            if (j % 2 == 0) for (int i = 0; i < N; i++) seq.push_back(id(i, j));\n            else for (int i = N - 1; i >= 0; i--) seq.push_back(id(i, j));\n        }\n        seq = normalize_unique(seq);\n        baseCandidates.push_back(seq);\n        reverse(seq.begin(), seq.end());\n        baseCandidates.push_back(seq);\n    }\n\n    // Geometric sorts\n    {\n        vector<int> seq;\n        for (int x = 1; x < V; x++) seq.push_back(x);\n        sort(seq.begin(), seq.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            double ka = ai + aj - 0.003 * dirt[a];\n            double kb = bi + bj - 0.003 * dirt[b];\n            return ka < kb;\n        });\n        baseCandidates.push_back(seq);\n    }\n    {\n        vector<int> seq;\n        for (int x = 1; x < V; x++) seq.push_back(x);\n        sort(seq.begin(), seq.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            double ka = ai - aj - 0.003 * dirt[a];\n            double kb = bi - bj - 0.003 * dirt[b];\n            return ka < kb;\n        });\n        baseCandidates.push_back(seq);\n    }\n\n    // Greedy unique\n    auto greedy_unique = [&](double beta, double gamma) {\n        vector<char> used(V, 0);\n        vector<int> seq;\n        seq.reserve(V - 1);\n        int cur = 0;\n        for (int step = 0; step < V - 1; step++) {\n            int best = -1;\n            double bestVal = -1e100;\n            for (int x = 1; x < V; x++) if (!used[x]) {\n                double val = beta * log((double)dirt[x]) - dist[cur][x] - gamma * dist[0][x];\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = x;\n                }\n            }\n            used[best] = 1;\n            seq.push_back(best);\n            cur = best;\n        }\n        return seq;\n    };\n\n    for (double beta : {1.2, 1.5, 1.8, 2.2, 2.8}) {\n        for (double gamma : {0.0, 0.03, 0.07}) {\n            baseCandidates.push_back(greedy_unique(beta, gamma));\n        }\n    }\n\n    // Tree DFS order\n    auto tree_order = [&](double alpha) {\n        const double INF = 1e100;\n        vector<double> ds(V, INF);\n        vector<int> par(V, -1);\n        priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n        ds[0] = 0;\n        pq.push({0, 0});\n\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top();\n            pq.pop();\n            if (cd != ds[u]) continue;\n            for (int to : adj[u]) {\n                double nd = cd + 1.0 / pow((double)dirt[to], alpha);\n                if (nd + 1e-12 < ds[to]) {\n                    ds[to] = nd;\n                    par[to] = u;\n                    pq.push({nd, to});\n                }\n            }\n        }\n\n        vector<vector<int>> ch(V);\n        for (int x = 1; x < V; x++) ch[par[x]].push_back(x);\n        for (int u = 0; u < V; u++) {\n            sort(ch[u].begin(), ch[u].end(), [&](int a, int b) {\n                if (dirt[a] != dirt[b]) return dirt[a] > dirt[b];\n                return dist[0][a] < dist[0][b];\n            });\n        }\n\n        vector<int> seq;\n        function<void(int)> dfs = [&](int u) {\n            if (u != 0) seq.push_back(u);\n            for (int x : ch[u]) dfs(x);\n        };\n        dfs(0);\n        return seq;\n    };\n\n    for (double alpha : {0.2, 0.4, 0.7, 1.0}) {\n        baseCandidates.push_back(tree_order(alpha));\n    }\n\n    vector<pair<long long,int>> scoredBases;\n    for (int i = 0; i < (int)baseCandidates.size(); i++) {\n        if (timer.elapsed() > 0.85) break;\n        string route = build_route(baseCandidates[i]);\n        long long sc = score_route(route);\n        scoredBases.push_back({sc, i});\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n            bestSeq = baseCandidates[i];\n        }\n    }\n    sort(scoredBases.begin(), scoredBases.end());\n\n    // Important cells: union of top by ratio and top by dirt\n    vector<int> byRatio, byDirt;\n    for (int x = 1; x < V; x++) {\n        byRatio.push_back(x);\n        byDirt.push_back(x);\n    }\n\n    sort(byRatio.begin(), byRatio.end(), [&](int a, int b) {\n        double sa = dirt[a] / (double)(dist[0][a] + 1);\n        double sb = dirt[b] / (double)(dist[0][b] + 1);\n        if (fabs(sa - sb) > 1e-12) return sa > sb;\n        return dirt[a] > dirt[b];\n    });\n    sort(byDirt.begin(), byDirt.end(), [&](int a, int b) {\n        if (dirt[a] != dirt[b]) return dirt[a] > dirt[b];\n        return dist[0][a] < dist[0][b];\n    });\n\n    vector<int> heavy;\n    vector<char> usedHeavy(V, 0);\n    for (int i = 0; i < min(24, (int)byRatio.size()); i++) {\n        int x = byRatio[i];\n        if (!usedHeavy[x]) {\n            usedHeavy[x] = 1;\n            heavy.push_back(x);\n        }\n    }\n    for (int i = 0; i < min(24, (int)byDirt.size()); i++) {\n        int x = byDirt[i];\n        if (!usedHeavy[x]) {\n            usedHeavy[x] = 1;\n            heavy.push_back(x);\n        }\n    }\n\n    auto insert_cost = [&](const vector<int>& seq, int p, int x) {\n        int prev = (p == 0 ? 0 : seq[p - 1]);\n        int next = (p == (int)seq.size() ? 0 : seq[p]);\n        return dist[prev][x] + dist[x][next] - dist[prev][next];\n    };\n\n    mt19937 rng(123456789);\n\n    // Seeded duplicated-base candidates on best few bases\n    int seedElite = min(4, (int)scoredBases.size());\n    for (int ei = 0; ei < seedElite && timer.elapsed() < 1.20; ei++) {\n        vector<int> seq = baseCandidates[scoredBases[ei].second];\n        int curLen = route_len(seq);\n\n        for (int t = 0; t < min(3, (int)heavy.size()); t++) {\n            int x = heavy[t];\n            int bestP = -1;\n            int bestAdd = 1e9;\n            int M = seq.size();\n            for (int k = 0; k < min(M + 1, 24); k++) {\n                int p = (long long)k * (M + 1) / min(M + 1, 24);\n                int add = insert_cost(seq, p, x);\n                if (curLen + add > 100000) continue;\n                if (add < bestAdd) {\n                    bestAdd = add;\n                    bestP = p;\n                }\n            }\n            if (bestP != -1) {\n                seq.insert(seq.begin() + bestP, x);\n                curLen += bestAdd;\n            }\n        }\n        try_seq(seq);\n    }\n\n    int elite = min(8, (int)scoredBases.size());\n    for (int ei = 0; ei < elite && timer.elapsed() < 1.95; ei++) {\n        vector<int> seq = baseCandidates[scoredBases[ei].second];\n        long long curScore = scoredBases[ei].first;\n        int curLen = route_len(seq);\n\n        if (curScore < bestScore) {\n            bestScore = curScore;\n            bestSeq = seq;\n            bestRoute = build_route(seq);\n        }\n\n        bool improved = true;\n        int round = 0;\n        while (improved && timer.elapsed() < 1.95 && round < 10) {\n            improved = false;\n            round++;\n\n            long long bestLocalScore = curScore;\n            vector<int> bestLocalSeq = seq;\n            int bestLocalLen = curLen;\n            int M = seq.size();\n\n            for (int x : heavy) {\n                if (timer.elapsed() > 1.95) break;\n\n                vector<int> posCand;\n                int sample = min(M + 1, 36);\n                for (int k = 0; k < sample; k++) {\n                    int p = (long long)k * (M + 1) / sample;\n                    posCand.push_back(p);\n                }\n\n                for (int idx = 0; idx < M; idx++) {\n                    int y = seq[idx];\n                    if (dist[x][y] <= 3) {\n                        posCand.push_back(idx);\n                        posCand.push_back(idx + 1);\n                    }\n                }\n\n                // start/end are important because of cyclic score\n                posCand.push_back(0);\n                posCand.push_back(M);\n\n                for (int t = 0; t < 6; t++) posCand.push_back(rng() % (M + 1));\n\n                sort(posCand.begin(), posCand.end());\n                posCand.erase(unique(posCand.begin(), posCand.end()), posCand.end());\n\n                for (int p : posCand) {\n                    int add = insert_cost(seq, p, x);\n                    if (curLen + add > 100000) continue;\n                    if (add > 28) continue;\n\n                    vector<int> cand = seq;\n                    cand.insert(cand.begin() + p, x);\n\n                    string route = build_route(cand);\n                    long long sc = score_route(route);\n                    if (sc < bestLocalScore) {\n                        bestLocalScore = sc;\n                        bestLocalSeq.swap(cand);\n                        bestLocalLen = curLen + add;\n                    }\n                }\n            }\n\n            // tiny diversification only\n            for (int t = 0; t < 4 && timer.elapsed() < 1.95; t++) {\n                int l = rng() % seq.size();\n                int r = rng() % seq.size();\n                if (l > r) swap(l, r);\n                if (l == r) continue;\n                vector<int> cand = seq;\n                reverse(cand.begin() + l, cand.begin() + r + 1);\n                int len2 = route_len(cand);\n                if (len2 > 100000) continue;\n                string route = build_route(cand);\n                long long sc = score_route(route);\n                if (sc < bestLocalScore) {\n                    bestLocalScore = sc;\n                    bestLocalSeq.swap(cand);\n                    bestLocalLen = len2;\n                }\n            }\n\n            if (bestLocalScore < curScore) {\n                seq.swap(bestLocalSeq);\n                curScore = bestLocalScore;\n                curLen = bestLocalLen;\n                improved = true;\n                if (curScore < bestScore) {\n                    bestScore = curScore;\n                    bestSeq = seq;\n                    bestRoute = build_route(seq);\n                }\n            }\n        }\n    }\n\n    if (bestRoute.empty()) {\n        vector<int> seq;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) seq.push_back(id(i, j));\n            else for (int j = N - 1; j >= 0; j--) seq.push_back(id(i, j));\n        }\n        seq = normalize_unique(seq);\n        bestRoute = build_route(seq);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#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 Pos {\n    int x, y;\n};\n\nstatic const int INF = 1e9;\n\nint overlap5(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    Timer timer;\n    mt19937 rng(123456789);\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    // Positions by letter\n    vector<vector<Pos>> pos(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            pos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    // Approximate distances\n    int startDist[26];\n    int bestDist[26][26];\n    for (int c = 0; c < 26; c++) {\n        startDist[c] = INF;\n        for (auto &p : pos[c]) {\n            startDist[c] = min(startDist[c], abs(si - p.x) + abs(sj - p.y));\n        }\n    }\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            int d = INF;\n            for (auto &p : pos[a]) for (auto &q : pos[b]) {\n                d = min(d, abs(p.x - q.x) + abs(p.y - q.y));\n            }\n            bestDist[a][b] = d;\n        }\n    }\n\n    // Overlap matrix\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++) if (i != j) {\n            ov[i][j] = overlap5(t[i], t[j]);\n        }\n    }\n\n    auto start_word_cost = [&](int x) -> int {\n        int cost = startDist[t[x][0] - 'A'] + 1;\n        for (int i = 1; i < 5; i++) {\n            cost += bestDist[t[x][i - 1] - 'A'][t[x][i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    auto append_cost = [&](int a, int b) -> int {\n        int o = ov[a][b];\n        string add = t[b].substr(o);\n        if (add.empty()) return 0;\n        int cost = bestDist[t[a][4] - 'A'][add[0] - 'A'] + 1;\n        for (int i = 1; i < (int)add.size(); i++) {\n            cost += bestDist[add[i - 1] - 'A'][add[i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    vector<int> startCost(M);\n    vector<vector<int>> appCost(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) startCost[i] = start_word_cost(i);\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) if (i != j) {\n            appCost[i][j] = append_cost(i, j);\n        }\n    }\n\n    struct Eval {\n        int ovsum;\n        int mov;\n    };\n\n    auto eval_order = [&](const vector<int>& ord) -> Eval {\n        int ovsum = 0;\n        int mov = startCost[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            ovsum += ov[ord[i - 1]][ord[i]];\n            mov += appCost[ord[i - 1]][ord[i]];\n        }\n        return {ovsum, mov};\n    };\n\n    auto better = [&](const Eval& a, const Eval& b) -> bool {\n        if (a.ovsum != b.ovsum) return a.ovsum > b.ovsum;\n        return a.mov < b.mov;\n    };\n\n    auto build_string = [&](const vector<int>& ord) -> string {\n        string s = t[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            s += t[ord[i]].substr(ov[ord[i - 1]][ord[i]]);\n        }\n        return s;\n    };\n\n    auto make_insertion_order = [&](int seed, bool randomized) -> vector<int> {\n        vector<int> ord = {seed};\n        vector<char> used(M, 0);\n        used[seed] = 1;\n\n        int second = -1;\n        Eval bestE{-INF, INF};\n        vector<pair<Eval,int>> cand2;\n        for (int j = 0; j < M; j++) if (!used[j]) {\n            vector<int> tmp = {seed, j};\n            Eval e = eval_order(tmp);\n            cand2.push_back({e, j});\n            if (second == -1 || better(e, bestE)) {\n                second = j;\n                bestE = e;\n            }\n        }\n        if (randomized) {\n            sort(cand2.begin(), cand2.end(), [&](auto &x, auto &y) {\n                return better(x.first, y.first);\n            });\n            int take = min(5, (int)cand2.size());\n            second = cand2[rng() % take].second;\n        }\n\n        ord.push_back(second);\n        used[second] = 1;\n\n        while ((int)ord.size() < M) {\n            struct Cand {\n                Eval e;\n                int x, p;\n            };\n            vector<Cand> cands;\n\n            int L = ord.size();\n            for (int x = 0; x < M; x++) if (!used[x]) {\n                for (int p = 0; p <= L; p++) {\n                    int deltaOv = 0;\n                    int deltaMove = 0;\n\n                    if (p == 0) {\n                        deltaOv = ov[x][ord[0]];\n                        deltaMove = startCost[x] + appCost[x][ord[0]] - startCost[ord[0]];\n                    } else if (p == L) {\n                        int a = ord[L - 1];\n                        deltaOv = ov[a][x];\n                        deltaMove = appCost[a][x];\n                    } else {\n                        int a = ord[p - 1], b = ord[p];\n                        deltaOv = ov[a][x] + ov[x][b] - ov[a][b];\n                        deltaMove = appCost[a][x] + appCost[x][b] - appCost[a][b];\n                    }\n\n                    cands.push_back({{deltaOv, deltaMove}, x, p});\n                }\n            }\n\n            sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n                return better(a.e, b.e);\n            });\n\n            Cand chosen = cands[0];\n            if (randomized) {\n                int take = min(8, (int)cands.size());\n                chosen = cands[rng() % take];\n            }\n\n            ord.insert(ord.begin() + chosen.p, chosen.x);\n            used[chosen.x] = 1;\n        }\n\n        return ord;\n    };\n\n    auto make_greedy_order = [&](int seed, bool randomized) -> vector<int> {\n        vector<int> ord;\n        vector<char> used(M, 0);\n        ord.reserve(M);\n        ord.push_back(seed);\n        used[seed] = 1;\n        int cur = seed;\n\n        while ((int)ord.size() < M) {\n            vector<pair<Eval,int>> cands;\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                cands.push_back({{ov[cur][j], appCost[cur][j]}, j});\n            }\n            sort(cands.begin(), cands.end(), [&](auto &a, auto &b) {\n                return better(a.first, b.first);\n            });\n            int nxt = cands[0].second;\n            if (randomized) {\n                int take = min(5, (int)cands.size());\n                nxt = cands[rng() % take].second;\n            }\n            ord.push_back(nxt);\n            used[nxt] = 1;\n            cur = nxt;\n        }\n\n        return ord;\n    };\n\n    auto improve_order = [&](vector<int> ord) -> vector<int> {\n        Eval cur = eval_order(ord);\n\n        auto try_accept = [&](vector<int>& cand) -> bool {\n            Eval e = eval_order(cand);\n            if (better(e, cur)) {\n                ord.swap(cand);\n                cur = e;\n                return true;\n            }\n            return false;\n        };\n\n        while (timer.elapsed() < 1.82) {\n            bool improved = false;\n\n            // adjacent swap sweep\n            for (int i = 0; i + 1 < M && timer.elapsed() < 1.82; i++) {\n                vector<int> cand = ord;\n                swap(cand[i], cand[i + 1]);\n                if (try_accept(cand)) improved = true;\n            }\n\n            // random swap\n            for (int it = 0; it < 300 && timer.elapsed() < 1.82; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                vector<int> cand = ord;\n                swap(cand[i], cand[j]);\n                if (try_accept(cand)) improved = true;\n            }\n\n            // random relocate\n            for (int it = 0; it < 300 && timer.elapsed() < 1.82; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                vector<int> cand = ord;\n                int v = cand[i];\n                cand.erase(cand.begin() + i);\n                cand.insert(cand.begin() + j, v);\n                if (try_accept(cand)) improved = true;\n            }\n\n            // segment reverse\n            for (int it = 0; it < 100 && timer.elapsed() < 1.82; it++) {\n                int l = rng() % M;\n                int r = rng() % M;\n                if (l > r) swap(l, r);\n                if (r - l < 2) continue;\n                vector<int> cand = ord;\n                reverse(cand.begin() + l, cand.begin() + r + 1);\n                if (try_accept(cand)) improved = true;\n            }\n\n            if (!improved) break;\n        }\n\n        return ord;\n    };\n\n    // choose promising starts\n    vector<pair<int,int>> starters;\n    for (int i = 0; i < M; i++) starters.push_back({startCost[i], i});\n    sort(starters.begin(), starters.end());\n\n    vector<int> bestOrder;\n    Eval bestEval{-INF, INF};\n\n    // more diversified multi-start\n    while (timer.elapsed() < 0.85) {\n        int s;\n        if ((int)starters.size() > 0) {\n            int take = min(20, M);\n            s = starters[rng() % take].second;\n        } else {\n            s = rng() % M;\n        }\n\n        int mode = rng() % 4;\n        vector<int> ord;\n        if (mode == 0) ord = make_insertion_order(s, false);\n        else if (mode == 1) ord = make_insertion_order(s, true);\n        else if (mode == 2) ord = make_greedy_order(s, false);\n        else ord = make_greedy_order(s, true);\n\n        Eval e = eval_order(ord);\n        if (bestOrder.empty() || better(e, bestEval)) {\n            bestOrder = ord;\n            bestEval = e;\n        }\n    }\n\n    bestOrder = improve_order(bestOrder);\n\n    string S = build_string(bestOrder);\n\n    // Safety fallback (practically never needed)\n    if ((int)S.size() > 5000) {\n        S.clear();\n        for (int i = 0; i < M; i++) S += t[i];\n    }\n\n    // Exact DP for optimal positions\n    int L = (int)S.size();\n    vector<vector<int>> dp(L), pre(L);\n\n    {\n        int c = S[0] - 'A';\n        int sz = pos[c].size();\n        dp[0].assign(sz, INF);\n        pre[0].assign(sz, -1);\n        for (int i = 0; i < sz; i++) {\n            dp[0][i] = abs(si - pos[c][i].x) + abs(sj - pos[c][i].y) + 1;\n        }\n    }\n\n    for (int i = 1; i < L; i++) {\n        int pc = S[i - 1] - 'A';\n        int cc = S[i] - 'A';\n        int psz = pos[pc].size();\n        int csz = pos[cc].size();\n        dp[i].assign(csz, INF);\n        pre[i].assign(csz, -1);\n\n        for (int v = 0; v < csz; v++) {\n            int best = INF, bestu = -1;\n            for (int u = 0; u < psz; u++) {\n                int val = dp[i - 1][u]\n                        + abs(pos[pc][u].x - pos[cc][v].x)\n                        + abs(pos[pc][u].y - pos[cc][v].y) + 1;\n                if (val < best) {\n                    best = val;\n                    bestu = u;\n                }\n            }\n            dp[i][v] = best;\n            pre[i][v] = bestu;\n        }\n    }\n\n    int last = 0;\n    for (int i = 1; i < (int)dp[L - 1].size(); i++) {\n        if (dp[L - 1][i] < dp[L - 1][last]) last = i;\n    }\n\n    vector<Pos> ans(L);\n    int cur = last;\n    for (int i = L - 1; i >= 0; i--) {\n        int c = S[i] - 'A';\n        ans[i] = pos[c][cur];\n        if (i > 0) cur = pre[i][cur];\n    }\n\n    for (auto &p : ans) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<int> drillMaskIdx; // indices t such that this placement covers drilledList[t]\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    int h = 0, w = 0;\n    vector<Placement> plc;\n};\n\nstruct Solver {\n    int N, M;\n    double eps;\n    vector<Field> fields;\n\n    int maxOps, ops = 0;\n    vector<int> drilled;      // -1 unknown, else exact reserve\n    vector<int> drilledList;  // cell ids\n    vector<char> hasOil;      // final after full drilling fallback\n\n    Solver() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> M >> eps;\n        fields.resize(M);\n        for (int m = 0; m < M; m++) {\n            int d;\n            cin >> d;\n            fields[m].shape.resize(d);\n            int hi = 0, hj = 0;\n            for (int k = 0; k < d; k++) {\n                int i, j;\n                cin >> i >> j;\n                fields[m].shape[k] = {i, j};\n                hi = max(hi, i);\n                hj = max(hj, j);\n            }\n            fields[m].h = hi + 1;\n            fields[m].w = hj + 1;\n        }\n\n        maxOps = 2 * N * N;\n        drilled.assign(N * N, -1);\n        hasOil.assign(N * N, 0);\n\n        buildPlacements();\n    }\n\n    inline int id(int i, int j) const { return i * N + j; }\n    inline pair<int,int> rc(int c) const { return {c / N, c % N}; }\n\n    void buildPlacements() {\n        for (int m = 0; m < M; m++) {\n            auto &f = fields[m];\n            for (int di = 0; di + f.h <= N; di++) {\n                for (int dj = 0; dj + f.w <= N; dj++) {\n                    Placement p;\n                    for (auto [i, j] : f.shape) {\n                        p.cells.push_back(id(di + i, dj + j));\n                    }\n                    f.plc.push_back(move(p));\n                }\n            }\n        }\n    }\n\n    int drillCell(int c) {\n        auto [i, j] = rc(c);\n        cout << \"q 1 \" << i << \" \" << j << '\\n';\n        cout.flush();\n        int x;\n        cin >> x;\n        ++ops;\n        if (drilled[c] == -1) drilledList.push_back(c);\n        drilled[c] = x;\n        if (x > 0) hasOil[c] = 1;\n        return x;\n    }\n\n    bool answerCells(const vector<int>& cells) {\n        cout << \"a \" << cells.size();\n        for (int c : cells) {\n            auto [i, j] = rc(c);\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << '\\n';\n        cout.flush();\n        int res;\n        cin >> res;\n        ++ops;\n        return res == 1;\n    }\n\n    // ---------- Exact search for small instances ----------\n\n    vector<vector<int>> feasible;   // feasible placements per field under zero-cells only\n    vector<int> order;\n    vector<int> remainCanCover;     // flattened [pos * D + t]\n    vector<int> curSum;\n    vector<int> chosen;\n    vector<int> solChosen;\n    int solutionsFound = 0;\n    int dfsNodeBudget = 200000;     // hard cap for safety\n    int dfsNodes = 0;\n\n    bool placementCompatibleWithZero(int m, int pidx) {\n        for (int c : fields[m].plc[pidx].cells) {\n            if (drilled[c] == 0) return false;\n        }\n        return true;\n    }\n\n    void prepareSearch() {\n        int D = (int)drilledList.size();\n\n        feasible.assign(M, {});\n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                if (placementCompatibleWithZero(m, p)) {\n                    feasible[m].push_back(p);\n                }\n            }\n        }\n\n        order.resize(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return feasible[a].size() < feasible[b].size();\n        });\n\n        for (int m = 0; m < M; m++) {\n            for (int pidx : feasible[m]) {\n                auto &pl = fields[m].plc[pidx];\n                pl.drillMaskIdx.clear();\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    // linear scan over cells of shape; shapes are small enough\n                    for (int x : pl.cells) {\n                        if (x == c) {\n                            pl.drillMaskIdx.push_back(t);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        remainCanCover.assign((M + 1) * max(1, D), 0);\n        if (D > 0) {\n            for (int pos = M - 1; pos >= 0; pos--) {\n                int m = order[pos];\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    int can = 0;\n                    for (int pidx : feasible[m]) {\n                        for (int x : fields[m].plc[pidx].cells) {\n                            if (x == c) {\n                                can = 1;\n                                goto done;\n                            }\n                        }\n                    }\n                done:\n                    remainCanCover[pos * D + t] = remainCanCover[(pos + 1) * D + t] + can;\n                }\n            }\n        }\n\n        curSum.assign(D, 0);\n        chosen.assign(M, -1);\n        solChosen.clear();\n        solutionsFound = 0;\n        dfsNodes = 0;\n    }\n\n    void dfsSearch(int pos) {\n        if (solutionsFound >= 2) return;\n        if (++dfsNodes > dfsNodeBudget) return;\n\n        int D = (int)drilledList.size();\n        if (pos == M) {\n            for (int t = 0; t < D; t++) {\n                if (curSum[t] != drilled[drilledList[t]]) return;\n            }\n            ++solutionsFound;\n            if (solutionsFound == 1) solChosen = chosen;\n            return;\n        }\n\n        int m = order[pos];\n\n        // Try placements in heuristic order: match positive drilled cells more\n        vector<pair<int,int>> cand;\n        cand.reserve(feasible[m].size());\n        for (int pidx : feasible[m]) {\n            int score = 0;\n            for (int t : fields[m].plc[pidx].drillMaskIdx) {\n                if (drilled[drilledList[t]] > 0) score++;\n                else score -= 1000;\n            }\n            cand.push_back({-score, pidx});\n        }\n        sort(cand.begin(), cand.end());\n\n        for (auto [_, pidx] : cand) {\n            auto &pl = fields[m].plc[pidx];\n            bool ok = true;\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]++;\n            }\n\n            for (int t = 0; t < D; t++) {\n                int target = drilled[drilledList[t]];\n                if (curSum[t] > target) { ok = false; break; }\n                int rem = remainCanCover[(pos + 1) * D + t];\n                if (curSum[t] + rem < target) { ok = false; break; }\n            }\n\n            if (ok) {\n                chosen[m] = pidx;\n                dfsSearch(pos + 1);\n                chosen[m] = -1;\n            }\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]--;\n            }\n\n            if (solutionsFound >= 2 || dfsNodes > dfsNodeBudget) return;\n        }\n    }\n\n    bool tryExactSolve(vector<int>& ansCells, bool requireUnique) {\n        prepareSearch();\n\n        for (int m = 0; m < M; m++) {\n            if (feasible[m].empty()) return false;\n        }\n\n        dfsSearch(0);\n\n        if (dfsNodes > dfsNodeBudget) return false;\n        if (solutionsFound == 0) return false;\n        if (requireUnique && solutionsFound != 1) return false;\n\n        vector<char> used(N * N, 0);\n        for (int m = 0; m < M; m++) {\n            int pidx = solChosen[m];\n            if (pidx < 0) return false;\n            for (int c : fields[m].plc[pidx].cells) used[c] = 1;\n        }\n\n        for (int c : drilledList) {\n            if ((drilled[c] == 0 && used[c]) || (drilled[c] > 0 && !used[c])) {\n                return false;\n            }\n        }\n\n        ansCells.clear();\n        for (int c = 0; c < N * N; c++) if (used[c]) ansCells.push_back(c);\n        return true;\n    }\n\n    // ---------- Strategy ----------\n\n    vector<int> informativeOrder() {\n        // deterministic spread: checkerboard center-first-ish\n        vector<int> cells;\n        cells.reserve(N * N);\n        vector<pair<int,int>> tmp;\n        double ci = (N - 1) / 2.0, cj = (N - 1) / 2.0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int parity = (i + j) & 1;\n                int dist = (int)(1000 * (abs(i - ci) + abs(j - cj)));\n                tmp.push_back({parity * 100000 + dist, id(i, j)});\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        for (auto &x : tmp) cells.push_back(x.second);\n        return cells;\n    }\n\n    void fullDrillFallback() {\n        for (int c = 0; c < N * N && ops < maxOps - 1; c++) {\n            if (drilled[c] == -1) drillCell(c);\n        }\n        vector<int> ans;\n        for (int c = 0; c < N * N; c++) if (drilled[c] > 0) ans.push_back(c);\n        answerCells(ans);\n    }\n\n    void solve() {\n        // Only attempt exact reasoning when likely cheap.\n        long long totalPlacements = 0;\n        for (int m = 0; m < M; m++) totalPlacements += fields[m].plc.size();\n\n        bool useSearch = (M <= 8 && totalPlacements <= 700);\n\n        if (!useSearch) {\n            fullDrillFallback();\n            return;\n        }\n\n        // Small-instance mode:\n        // Drill a modest number of informative cells, trying to pin down unique placement combo.\n        vector<int> orderCells = informativeOrder();\n        int initialDrills = min<int>(N * N, max(12, N));\n\n        for (int t = 0; t < initialDrills && ops < maxOps - 1; t++) {\n            int c = orderCells[t];\n            if (drilled[c] == -1) drillCell(c);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // If not yet unique, continue a bit more adaptively: drill cells appearing often in candidate answer.\n        for (int extra = initialDrills; extra < min(N * N, initialDrills + 20) && ops < maxOps - 1; extra++) {\n            int best = -1, bestScore = -1;\n\n            for (int c = 0; c < N * N; c++) if (drilled[c] == -1) {\n                int score = 0;\n                for (int m = 0; m < M; m++) {\n                    for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                        if (!placementCompatibleWithZero(m, p)) continue;\n                        for (int x : fields[m].plc[p].cells) {\n                            if (x == c) { score++; break; }\n                        }\n                    }\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = c;\n                }\n            }\n\n            if (best == -1) break;\n            drillCell(best);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // Fallback: guaranteed correct\n        fullDrillFallback();\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const int W = 1000;\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nstruct DayLayout {\n    vector<int> outer;                  // size R+1\n    vector<vector<int>> inner_pref;     // prefix widths per strip\n    ll penalty = 0;                     // true shortage penalty\n    vector<Rect> rects;                 // size N\n};\n\nstruct Answer {\n    ll total_cost = (1LL << 62);\n    vector<vector<Rect>> days;\n};\n\nstatic inline ll miss_need_cap(int need, int cap) {\n    return max(0, need - cap);\n}\n\nstatic pair<ll, vector<int>> optimize_strip_day(\n    const vector<vector<int>>& actual,\n    int d, int l, int r, int h\n) {\n    int m = r - l;\n    vector<int> width(m, 1);\n    int rem = W - m;\n\n    vector<vector<int>> gain(m, vector<int>(W, 0));\n    for (int z = 0; z < m; z++) {\n        int need = actual[d][l + z];\n        for (int t = 0; t < W; t++) {\n            int c0 = h * t;\n            int c1 = h * (t + 1);\n            gain[z][t] = max(0, need - c0) - max(0, need - c1);\n        }\n    }\n\n    using T = pair<int,int>;\n    priority_queue<T> pq;\n    for (int z = 0; z < m; z++) pq.push({gain[z][1], z});\n\n    while (rem > 0) {\n        auto [g, z] = pq.top(); pq.pop();\n        int t = width[z];\n        int realg = (t < W ? gain[z][t] : 0);\n        if (g != realg) {\n            pq.push({realg, z});\n            continue;\n        }\n        width[z]++;\n        rem--;\n        t = width[z];\n        pq.push({(t < W ? gain[z][t] : 0), z});\n    }\n\n    // Cheap local refinement\n    vector<ll> curmiss(m);\n    for (int z = 0; z < m; z++) {\n        curmiss[z] = miss_need_cap(actual[d][l + z], h * width[z]);\n    }\n\n    bool improved = true;\n    for (int iter = 0; iter < 2 && improved; iter++) {\n        improved = false;\n        ll best_delta = 0;\n        int bi = -1, bj = -1;\n        for (int i = 0; i < m; i++) {\n            if (width[i] <= 1) continue;\n            ll mi_new = miss_need_cap(actual[d][l + i], h * (width[i] - 1));\n            for (int j = 0; j < m; j++) if (i != j) {\n                ll mj_new = miss_need_cap(actual[d][l + j], h * (width[j] + 1));\n                ll delta = (mi_new + mj_new) - (curmiss[i] + curmiss[j]);\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    bi = i;\n                    bj = j;\n                }\n            }\n        }\n        if (best_delta < 0) {\n            width[bi]--;\n            width[bj]++;\n            curmiss[bi] = miss_need_cap(actual[d][l + bi], h * width[bi]);\n            curmiss[bj] = miss_need_cap(actual[d][l + bj], h * width[bj]);\n            improved = true;\n        }\n    }\n\n    ll miss = 0;\n    for (int z = 0; z < m; z++) miss += curmiss[z];\n    return {miss, width};\n}\n\nstatic vector<int> proportional_sizes(const vector<ll>& weights) {\n    int R = (int)weights.size();\n    ll total = 0;\n    for (ll x : weights) total += x;\n    if (total == 0) total = 1;\n\n    vector<int> sz(R, 1);\n    vector<pair<double,int>> frac;\n    int used = 0;\n    for (int i = 0; i < R; i++) {\n        double ideal = (double)W * (double)weights[i] / (double)total;\n        int base = max(1, (int)floor(ideal));\n        sz[i] = base;\n        used += base;\n        frac.push_back({ideal - base, i});\n    }\n\n    if (used > W) {\n        vector<int> ord(R);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) { return sz[a] > sz[b]; });\n        int need = used - W;\n        for (int id : ord) {\n            int dec = min(need, sz[id] - 1);\n            sz[id] -= dec;\n            need -= dec;\n            if (need == 0) break;\n        }\n    } else if (used < W) {\n        int need = W - used;\n        sort(frac.begin(), frac.end(), greater<>());\n        for (int i = 0; i < need; i++) sz[frac[i % R].second]++;\n    }\n    return sz;\n}\n\nstatic DayLayout build_day_layout(\n    const vector<vector<int>>& actual,\n    int d,\n    const vector<int>& cuts,\n    int orientation\n) {\n    int N = (int)actual[0].size();\n    int R = (int)cuts.size() - 1;\n\n    DayLayout dl;\n    dl.rects.assign(N, {0,0,1,1});\n\n    vector<ll> group_sum(R, 0);\n    for (int g = 0; g < R; g++) {\n        for (int k = cuts[g]; k < cuts[g + 1]; k++) group_sum[g] += actual[d][k];\n    }\n\n    vector<int> h = proportional_sizes(group_sum);\n    dl.outer.assign(R + 1, 0);\n    for (int g = 0; g < R; g++) dl.outer[g + 1] = dl.outer[g] + h[g];\n\n    dl.inner_pref.resize(R);\n    ll miss = 0;\n\n    for (int g = 0; g < R; g++) {\n        int l = cuts[g], r = cuts[g + 1];\n        auto [mcur, wcur] = optimize_strip_day(actual, d, l, r, h[g]);\n        miss += mcur;\n        int m = r - l;\n        dl.inner_pref[g].assign(m + 1, 0);\n        for (int z = 0; z < m; z++) dl.inner_pref[g][z + 1] = dl.inner_pref[g][z] + wcur[z];\n    }\n\n    for (int g = 0; g < R; g++) {\n        int l = cuts[g], r = cuts[g + 1];\n        int o0 = dl.outer[g], o1 = dl.outer[g + 1];\n        for (int z = 0; z < r - l; z++) {\n            int x0 = dl.inner_pref[g][z];\n            int x1 = dl.inner_pref[g][z + 1];\n            if (orientation == 0) {\n                dl.rects[l + z] = {o0, x0, o1, x1};\n            } else {\n                dl.rects[l + z] = {x0, o0, x1, o1};\n            }\n        }\n    }\n\n    dl.penalty = miss * 100;\n    return dl;\n}\n\nstatic ll transition_cost_same_topology(\n    const DayLayout& A,\n    const DayLayout& B,\n    const vector<int>& cuts\n) {\n    int R = (int)cuts.size() - 1;\n    ll cost = 0;\n\n    // strip separators\n    for (int g = 1; g < R; g++) {\n        if (A.outer[g] != B.outer[g]) cost += 2LL * W;\n    }\n\n    // inner separators\n    for (int g = 0; g < R; g++) {\n        int m = cuts[g + 1] - cuts[g];\n        int a0 = A.outer[g], a1 = A.outer[g + 1];\n        int b0 = B.outer[g], b1 = B.outer[g + 1];\n        int hA = a1 - a0, hB = b1 - b0;\n\n        for (int z = 1; z < m; z++) {\n            int xA = A.inner_pref[g][z];\n            int xB = B.inner_pref[g][z];\n            if (xA == xB) {\n                cost += abs(a0 - b0) + abs(a1 - b1);\n            } else {\n                cost += hA + hB;\n            }\n        }\n    }\n\n    return cost;\n}\n\nstatic Answer solve_dynamic(\n    const vector<vector<int>>& a,\n    const vector<int>& cuts,\n    int orientation\n) {\n    int D = (int)a.size();\n    int N = (int)a[0].size();\n\n    Answer ans;\n    ans.days.assign(D, vector<Rect>(N));\n\n    vector<DayLayout> days(D);\n    ll total = 0;\n    for (int d = 0; d < D; d++) {\n        days[d] = build_day_layout(a, d, cuts, orientation);\n        total += days[d].penalty;\n        ans.days[d] = days[d].rects;\n    }\n    for (int d = 1; d < D; d++) {\n        total += transition_cost_same_topology(days[d - 1], days[d], cuts);\n    }\n    ans.total_cost = total;\n    return ans;\n}\n\nstatic Answer solve_static(\n    const vector<vector<int>>& a,\n    const vector<int>& cuts,\n    int orientation\n) {\n    int D = (int)a.size();\n    int N = (int)a[0].size();\n\n    vector<vector<int>> agg(1, vector<int>(N, 0));\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) agg[0][k] += a[d][k];\n    }\n\n    DayLayout base = build_day_layout(agg, 0, cuts, orientation);\n\n    Answer ans;\n    ans.days.assign(D, vector<Rect>(N));\n    ll total = 0;\n    for (int d = 0; d < D; d++) {\n        ll miss = 0;\n        for (int k = 0; k < N; k++) {\n            const auto& r = base.rects[k];\n            int area = (r.i1 - r.i0) * (r.j1 - r.j0);\n            if (a[d][k] > area) miss += a[d][k] - area;\n            ans.days[d][k] = r;\n        }\n        total += miss * 100;\n    }\n    ans.total_cost = total;\n    return ans;\n}\n\nstatic vector<int> balanced_cuts_from_prefix(const vector<ll>& pref, int N, int R) {\n    vector<int> cuts;\n    cuts.push_back(0);\n    for (int t = 1; t < R; t++) {\n        ll target = pref[N] * t / R;\n        int pos = (int)(lower_bound(pref.begin(), pref.end(), target) - pref.begin());\n        pos = max(pos, cuts.back() + 1);\n        pos = min(pos, N - (R - t));\n        cuts.push_back(pos);\n    }\n    cuts.push_back(N);\n    return cuts;\n}\n\nstatic vector<int> equal_cuts(int N, int R) {\n    vector<int> cuts(R + 1);\n    cuts[0] = 0;\n    cuts[R] = N;\n    for (int t = 1; t < R; t++) cuts[t] = (int)((ll)N * t / R);\n    for (int t = 1; t < R; t++) cuts[t] = max(cuts[t], cuts[t - 1] + 1);\n    for (int t = R - 1; t >= 1; t--) cuts[t] = min(cuts[t], cuts[t + 1] - 1);\n    return cuts;\n}\n\n// DP partition to make group sums close to equal total/R.\nstatic vector<int> dp_cuts_from_weights(const vector<ll>& w, int R) {\n    int N = (int)w.size();\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; i++) pref[i + 1] = pref[i] + w[i];\n    double target = (double)pref[N] / R;\n\n    const double INF = 1e100;\n    vector<vector<double>> dp(R + 1, vector<double>(N + 1, INF));\n    vector<vector<int>> pre(R + 1, vector<int>(N + 1, -1));\n    dp[0][0] = 0.0;\n\n    for (int g = 0; g < R; g++) {\n        for (int i = 0; i <= N; i++) {\n            if (dp[g][i] >= INF / 2) continue;\n            int minj = i + 1;\n            int maxj = N - (R - g - 1);\n            for (int j = minj; j <= maxj; j++) {\n                double sum = (double)(pref[j] - pref[i]);\n                double cost = (sum - target) * (sum - target);\n                double ndp = dp[g][i] + cost;\n                if (ndp < dp[g + 1][j]) {\n                    dp[g + 1][j] = ndp;\n                    pre[g + 1][j] = i;\n                }\n            }\n        }\n    }\n\n    vector<int> cuts(R + 1);\n    cuts[R] = N;\n    int cur = N;\n    for (int g = R; g >= 1; g--) {\n        cuts[g - 1] = pre[g][cur];\n        cur = cuts[g - 1];\n    }\n    return cuts;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Win, D, N;\n    cin >> Win >> D >> 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    // Several weighting schemes for cut generation\n    vector<ll> sumw(N, 0), maxw(N, 0), earlyw(N, 0), latew(N, 0);\n    for (int k = 0; k < N; k++) {\n        ll s = 0, mx = 0, e = 0, l = 0;\n        for (int d = 0; d < D; d++) {\n            s += a[d][k];\n            mx = max<ll>(mx, a[d][k]);\n            e += 1LL * (D - d) * a[d][k];\n            l += 1LL * (d + 1) * a[d][k];\n        }\n        sumw[k] = s;\n        maxw[k] = mx;\n        earlyw[k] = e;\n        latew[k] = l;\n    }\n\n    auto prefix_of = [&](const vector<ll>& w) {\n        vector<ll> pref(N + 1, 0);\n        for (int i = 0; i < N; i++) pref[i + 1] = pref[i] + w[i];\n        return pref;\n    };\n\n    vector<vector<ll>> weight_sets = {sumw, maxw, earlyw, latew};\n\n    Answer best;\n\n    int maxR = min(N, 5);\n    for (int R = 1; R <= maxR; R++) {\n        vector<vector<int>> candidates;\n        if (R == 1) {\n            candidates.push_back({0, N});\n        } else {\n            candidates.push_back(equal_cuts(N, R));\n\n            for (const auto& w : weight_sets) {\n                auto pref = prefix_of(w);\n                candidates.push_back(balanced_cuts_from_prefix(pref, N, R));\n                candidates.push_back(dp_cuts_from_weights(w, R));\n            }\n\n            // Small perturbations around all current candidates\n            int base_sz = (int)candidates.size();\n            for (int id = 0; id < base_sz; id++) {\n                auto c0 = candidates[id];\n                for (int idx = 1; idx < R; idx++) {\n                    for (int dlt : {-1, +1}) {\n                        auto c = c0;\n                        c[idx] += dlt;\n                        bool ok = true;\n                        for (int i = 1; i < R; i++) {\n                            if (!(c[i - 1] < c[i] && c[i] < c[i + 1])) {\n                                ok = false;\n                                break;\n                            }\n                        }\n                        if (ok) candidates.push_back(c);\n                    }\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        for (const auto& cuts : candidates) {\n            for (int orientation = 0; orientation < 2; orientation++) {\n                {\n                    Answer cur = solve_static(a, cuts, orientation);\n                    if (cur.total_cost < best.total_cost) best = move(cur);\n                }\n                {\n                    Answer cur = solve_dynamic(a, cuts, orientation);\n                    if (cur.total_cost < best.total_cost) best = move(cur);\n                }\n            }\n        }\n    }\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const auto& r = best.days[d][k];\n            cout << r.i0 << ' ' << r.j0 << ' ' << r.i1 << ' ' << r.j1 << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 9;\nstatic constexpr int POS = 7;\nstatic constexpr int MOD = 998244353;\nstatic constexpr int K = 81;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double ms() const {\n        return chrono::duration<double, milli>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct RNG {\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    double rand01() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nusing Board = array<int, 81>;\n\nstruct Action {\n    int m, p, q;\n    int idx[9];\n    int add[9];\n};\n\nstruct Candidate {\n    long long gain;\n    int act;\n};\n\nstruct Node {\n    Board b;\n    long long score;\n    long long eval;\n    vector<unsigned short> seq;\n};\n\nvector<Action> actions;\n\nstatic inline long long cell_gain(int cur, int add) {\n    int s = cur + add;\n    return (s >= MOD) ? (long long)add - MOD : (long long)add;\n}\n\nstatic inline long long action_gain(const Board& b, int act) {\n    const auto& a = actions[act];\n    long long g = 0;\n    for (int i = 0; i < 9; i++) g += cell_gain(b[a.idx[i]], a.add[i]);\n    return g;\n}\n\nstatic inline void apply_action(Board& b, int act) {\n    const auto& a = actions[act];\n    for (int i = 0; i < 9; i++) {\n        int &v = b[a.idx[i]];\n        v += a.add[i];\n        if (v >= MOD) v -= MOD;\n    }\n}\n\nlong long best_single_gain(const Board& b) {\n    long long best = 0;\n    for (int i = 0; i < (int)actions.size(); i++) {\n        long long g = action_gain(b, i);\n        if (g > best) best = g;\n    }\n    return best;\n}\n\nvector<Candidate> top_actions(const Board& b, int need, int random_pool_extra = 0) {\n    vector<Candidate> cand;\n    cand.reserve(actions.size());\n    for (int i = 0; i < (int)actions.size(); i++) {\n        long long g = action_gain(b, i);\n        if (g > 0) cand.push_back({g, i});\n    }\n    if (cand.empty()) return cand;\n\n    int keep = min((int)cand.size(), max(need, need + random_pool_extra));\n    nth_element(cand.begin(), cand.begin() + keep - 1, cand.end(),\n        [](const Candidate& a, const Candidate& b) { return a.gain > b.gain; });\n    cand.resize(keep);\n    sort(cand.begin(), cand.end(),\n        [](const Candidate& a, const Candidate& b) {\n            if (a.gain != b.gain) return a.gain > b.gain;\n            return a.act < b.act;\n        });\n\n    if ((int)cand.size() <= need) return cand;\n\n    vector<Candidate> res;\n    res.reserve(need);\n\n    int fixed = max(1, need / 2);\n    for (int i = 0; i < fixed; i++) res.push_back(cand[i]);\n\n    vector<int> ids;\n    for (int i = fixed; i < (int)cand.size(); i++) ids.push_back(i);\n    while ((int)res.size() < need && !ids.empty()) {\n        int j = rng.randint(0, (int)ids.size() - 1);\n        res.push_back(cand[ids[j]]);\n        ids[j] = ids.back();\n        ids.pop_back();\n    }\n    return res;\n}\n\npair<long long, Board> eval_sequence(const Board& init, const vector<int>& seq) {\n    Board b = init;\n    long long score = 0;\n    for (int act : seq) {\n        long long g = action_gain(b, act);\n        if (g <= 0) break;\n        apply_action(b, act);\n        score += g;\n    }\n    return {score, b};\n}\n\nvector<int> greedy_complete(Board b, int remain, bool randomized = true) {\n    vector<int> seq;\n    seq.reserve(remain);\n    for (int step = 0; step < remain; step++) {\n        auto cand = top_actions(b, randomized ? 14 : 24, randomized ? 18 : 0);\n        if (cand.empty()) break;\n\n        long long bestEval = LLONG_MIN;\n        int bestAct = -1;\n\n        for (auto &c : cand) {\n            Board nb = b;\n            apply_action(nb, c.act);\n            long long h1 = best_single_gain(nb);\n            long long eval = c.gain + h1;\n\n            if (randomized) {\n                // Mild randomization to diversify runs\n                eval += rng.randint(0, 2000);\n            }\n\n            if (eval > bestEval) {\n                bestEval = eval;\n                bestAct = c.act;\n            }\n        }\n\n        if (bestAct < 0) break;\n        apply_action(b, bestAct);\n        seq.push_back(bestAct);\n    }\n    return seq;\n}\n\nvector<int> construct_solution(const Board& initial, const Timer& timer, double deadline_ms) {\n    int BEAM_WIDTH = 56;\n    int BRANCH = 14;\n    int DEPTH = 12;\n\n    vector<Node> beam, nxt;\n    beam.reserve(BEAM_WIDTH);\n    nxt.reserve(BEAM_WIDTH * BRANCH);\n\n    Node root;\n    root.b = initial;\n    root.score = 0;\n    root.eval = 0;\n    beam.push_back(root);\n\n    for (int d = 0; d < DEPTH; d++) {\n        if (timer.ms() > deadline_ms) break;\n        nxt.clear();\n\n        for (const auto& node : beam) {\n            auto cand = top_actions(node.b, BRANCH, 16);\n            if (cand.empty()) {\n                nxt.push_back(node);\n                continue;\n            }\n\n            for (auto &c : cand) {\n                Node child;\n                child.b = node.b;\n                apply_action(child.b, c.act);\n                child.score = node.score + c.gain;\n                child.seq = node.seq;\n                child.seq.push_back((unsigned short)c.act);\n\n                // heuristic = current score + best next gain + small diversity\n                long long h = best_single_gain(child.b);\n                child.eval = child.score + h + rng.randint(0, 1000);\n                nxt.push_back(std::move(child));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        int keep = min((int)nxt.size(), BEAM_WIDTH);\n        nth_element(nxt.begin(), nxt.begin() + keep - 1, nxt.end(),\n            [](const Node& a, const Node& b) {\n                if (a.eval != b.eval) return a.eval > b.eval;\n                return a.score > b.score;\n            });\n        nxt.resize(keep);\n        sort(nxt.begin(), nxt.end(),\n            [](const Node& a, const Node& b) {\n                if (a.eval != b.eval) return a.eval > b.eval;\n                return a.score > b.score;\n            });\n        beam.swap(nxt);\n    }\n\n    long long bestScore = -1;\n    vector<int> bestSeq;\n\n    int use = min(10, (int)beam.size());\n    for (int i = 0; i < use; i++) {\n        if (timer.ms() > deadline_ms) break;\n        vector<int> seq;\n        seq.reserve(K);\n        for (auto x : beam[i].seq) seq.push_back((int)x);\n\n        auto [prefixScore, b] = eval_sequence(initial, seq);\n        auto tail = greedy_complete(b, K - (int)seq.size(), true);\n        seq.insert(seq.end(), tail.begin(), tail.end());\n\n        auto [score, _] = eval_sequence(initial, seq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(seq);\n        }\n    }\n\n    while (timer.ms() < deadline_ms) {\n        auto seq = greedy_complete(initial, K, true);\n        auto [score, _] = eval_sequence(initial, seq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(seq);\n        }\n    }\n\n    return bestSeq;\n}\n\nvoid rebuild_prefix_data(const Board& initial, const vector<int>& seq, vector<Board>& pref, vector<long long>& scr) {\n    pref.assign(seq.size() + 1, Board{});\n    scr.assign(seq.size() + 1, 0);\n    pref[0] = initial;\n\n    int real_len = 0;\n    for (int i = 0; i < (int)seq.size(); i++) {\n        pref[i + 1] = pref[i];\n        long long g = action_gain(pref[i + 1], seq[i]);\n        if (g <= 0) break;\n        apply_action(pref[i + 1], seq[i]);\n        scr[i + 1] = scr[i] + g;\n        real_len = i + 1;\n    }\n\n    pref.resize(real_len + 1);\n    scr.resize(real_len + 1);\n}\n\nvector<int> rebuild_from_prefix(const Board& initial, const vector<int>& prefix) {\n    Board b = initial;\n    vector<int> seq;\n    seq.reserve(K);\n\n    for (int act : prefix) {\n        long long g = action_gain(b, act);\n        if (g <= 0) return seq;\n        apply_action(b, act);\n        seq.push_back(act);\n    }\n\n    auto tail = greedy_complete(b, K - (int)seq.size(), true);\n    seq.insert(seq.end(), tail.begin(), tail.end());\n    return seq;\n}\n\nvoid local_improve(const Board& initial, vector<int>& bestSeq, long long& bestScore,\n                   const Timer& timer, double deadline_ms) {\n    vector<Board> pref;\n    vector<long long> scr;\n    rebuild_prefix_data(initial, bestSeq, pref, scr);\n\n    auto try_update = [&](vector<int>& candSeq) {\n        auto [score, _] = eval_sequence(initial, candSeq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(candSeq);\n            rebuild_prefix_data(initial, bestSeq, pref, scr);\n            return true;\n        }\n        return false;\n    };\n\n    while (timer.ms() < deadline_ms) {\n        int len = (int)pref.size() - 1;\n        if (len <= 0) break;\n\n        int mode = rng.randint(0, 99);\n\n        // 1) Rebuild suffix from t\n        if (mode < 30) {\n            int t = rng.randint(0, len);\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            auto cand = rebuild_from_prefix(initial, prefix);\n            try_update(cand);\n        }\n        // 2) Replace one move at t\n        else if (mode < 75) {\n            int t = rng.randint(0, len - 1);\n            Board b = pref[t];\n            auto candActs = top_actions(b, 10, 12);\n            if (candActs.empty()) continue;\n\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            long long localBest = bestScore;\n            vector<int> localSeq;\n\n            for (auto &ca : candActs) {\n                if (timer.ms() > deadline_ms) break;\n                vector<int> seq = prefix;\n                seq.push_back(ca.act);\n\n                Board nb = b;\n                long long g = action_gain(nb, ca.act);\n                if (g <= 0) continue;\n                apply_action(nb, ca.act);\n\n                auto tail = greedy_complete(nb, K - (int)seq.size(), true);\n                seq.insert(seq.end(), tail.begin(), tail.end());\n\n                auto [score, _] = eval_sequence(initial, seq);\n                if (score > localBest) {\n                    localBest = score;\n                    localSeq = std::move(seq);\n                }\n            }\n\n            if (!localSeq.empty()) {\n                bestScore = localBest;\n                bestSeq = std::move(localSeq);\n                rebuild_prefix_data(initial, bestSeq, pref, scr);\n            }\n        }\n        // 3) Replace two moves at t,t+1 with small 2-step search\n        else {\n            int t = rng.randint(0, max(0, len - 1));\n            Board b = pref[t];\n            auto firsts = top_actions(b, 6, 8);\n            if (firsts.empty()) continue;\n\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            long long localBest = bestScore;\n            vector<int> localSeq;\n\n            for (auto &c1 : firsts) {\n                if (timer.ms() > deadline_ms) break;\n                Board b1 = b;\n                long long g1 = action_gain(b1, c1.act);\n                if (g1 <= 0) continue;\n                apply_action(b1, c1.act);\n\n                auto seconds = top_actions(b1, 5, 6);\n                if (seconds.empty()) {\n                    vector<int> seq = prefix;\n                    seq.push_back(c1.act);\n                    auto tail = greedy_complete(b1, K - (int)seq.size(), true);\n                    seq.insert(seq.end(), tail.begin(), tail.end());\n                    auto [score, _] = eval_sequence(initial, seq);\n                    if (score > localBest) {\n                        localBest = score;\n                        localSeq = std::move(seq);\n                    }\n                    continue;\n                }\n\n                for (auto &c2 : seconds) {\n                    if (timer.ms() > deadline_ms) break;\n                    Board b2 = b1;\n                    long long g2 = action_gain(b2, c2.act);\n                    if (g2 <= 0) continue;\n                    apply_action(b2, c2.act);\n\n                    vector<int> seq = prefix;\n                    seq.push_back(c1.act);\n                    seq.push_back(c2.act);\n\n                    auto tail = greedy_complete(b2, K - (int)seq.size(), true);\n                    seq.insert(seq.end(), tail.begin(), tail.end());\n\n                    auto [score, _] = eval_sequence(initial, seq);\n                    if (score > localBest) {\n                        localBest = score;\n                        localSeq = std::move(seq);\n                    }\n                }\n            }\n\n            if (!localSeq.empty()) {\n                bestScore = localBest;\n                bestSeq = std::move(localSeq);\n                rebuild_prefix_data(initial, bestSeq, pref, scr);\n            }\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin, Min, Kin;\n    cin >> Nin >> Min >> Kin;\n\n    Board initial{};\n    for (int i = 0; i < Nin; i++) {\n        for (int j = 0; j < Nin; j++) {\n            cin >> initial[i * N + j];\n        }\n    }\n\n    vector<array<array<int, 3>, 3>> stamps(Min);\n    for (int m = 0; m < Min; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    actions.clear();\n    actions.reserve(Min * POS * POS);\n    for (int m = 0; m < Min; m++) {\n        for (int p = 0; p < POS; p++) {\n            for (int q = 0; q < POS; q++) {\n                Action a;\n                a.m = m;\n                a.p = p;\n                a.q = q;\n                int t = 0;\n                for (int i = 0; i < 3; i++) {\n                    for (int j = 0; j < 3; j++) {\n                        a.idx[t] = (p + i) * N + (q + j);\n                        a.add[t] = stamps[m][i][j];\n                        t++;\n                    }\n                }\n                actions.push_back(a);\n            }\n        }\n    }\n\n    Timer timer;\n    const double TOTAL_MS = 1850.0;\n\n    long long bestScore = -1;\n    vector<int> bestSeq;\n\n    // Multi-start constructive phase\n    while (timer.ms() < TOTAL_MS * 0.50) {\n        auto seq = construct_solution(initial, timer, TOTAL_MS * 0.50);\n        auto [score, _] = eval_sequence(initial, seq);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = std::move(seq);\n        }\n    }\n\n    // Fallback\n    if (bestSeq.empty()) {\n        bestSeq = greedy_complete(initial, K, false);\n        bestScore = eval_sequence(initial, bestSeq).first;\n    }\n\n    // Strong local improvement phase\n    local_improve(initial, bestSeq, bestScore, timer, TOTAL_MS);\n\n    if ((int)bestSeq.size() > Kin) bestSeq.resize(Kin);\n\n    cout << bestSeq.size() << '\\n';\n    for (int act : bestSeq) {\n        const auto& a = actions[act];\n        cout << a.m << ' ' << a.p << ' ' << a.q << '\\n';\n    }\n\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int TOTAL = 25;\nstatic constexpr int BEAM_WIDTH = 1600;\n\nstruct Node {\n    array<uint8_t, N> ptr{};                 // extracted count per input row\n    array<uint8_t, N> outCnt{};              // dispatched count per output row\n    array<array<uint8_t, N>, N> outSeq{};    // exact dispatched sequence per output row\n    array<uint8_t, N> mask{};                // delivered item mask per output row\n    uint8_t cr = 0, cc = 0;\n    uint8_t delivered = 0;\n    int turns = 0;\n    int inv = 0;\n\n    int prev = -1;\n    uint8_t actionRow = 0;\n};\n\nstatic inline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstatic inline int inversion_add(const Node& nd, int outRow, int x) {\n    int add = 0;\n    for (int i = 0; i < nd.outCnt[outRow]; i++) {\n        if ((int)nd.outSeq[outRow][i] > x) add++;\n    }\n    return add;\n}\n\nstatic inline long long true_score(const Node& nd) {\n    return 1LL * nd.turns + 100LL * nd.inv;\n}\n\nstatic inline long long optimistic_travel_lb(const Node& nd) {\n    int rem = TOTAL - nd.delivered;\n    if (rem == 0) return 0;\n\n    long long lb = 6LL * rem; // each remaining direct-delivery needs at least P,Q and horizontal 4\n    int bestSrc = 1e9;\n    for (int i = 0; i < N; i++) {\n        if (nd.ptr[i] < N) bestSrc = min(bestSrc, manhattan(nd.cr, nd.cc, i, 0));\n    }\n    if (bestSrc < (int)1e9) lb += bestSrc;\n    return lb;\n}\n\n// Heuristic for future inversion pressure.\n// For each output row r and each remaining item x in queues,\n// if there exist smaller undelivered items of same output row still remaining,\n// then dispatching x too early risks inversions.\n// We estimate this pressure from currently visible fronts and near-front items.\nstatic long long inversion_pressure(const Node& nd, const vector<vector<int>>& A) {\n    long long pressure = 0;\n\n    for (int r = 0; r < N; r++) {\n        bool deliveredLocal[N] = {};\n        for (int i = 0; i < nd.outCnt[r]; i++) {\n            deliveredLocal[nd.outSeq[r][i] % N] = true;\n        }\n\n        // For each remaining local id in this row, note whether it's still not delivered.\n        bool remainLocal[N] = {};\n        for (int k = 0; k < N; k++) remainLocal[k] = !deliveredLocal[k];\n\n        // Scan all remaining items in input queues.\n        // Give more weight to front / near-front larger items when smaller ones remain hidden.\n        for (int in = 0; in < N; in++) {\n            for (int d = nd.ptr[in]; d < N; d++) {\n                int x = A[in][d];\n                if (x / N != r) continue;\n                int loc = x % N;\n\n                int smallerRemain = 0;\n                for (int s = 0; s < loc; s++) {\n                    if (remainLocal[s]) smallerRemain++;\n                }\n                if (smallerRemain == 0) continue;\n\n                int depth = d - nd.ptr[in];\n                int w = 0;\n                if (depth == 0) w = 6;\n                else if (depth == 1) w = 3;\n                else if (depth == 2) w = 2;\n                else w = 1;\n\n                pressure += 1LL * w * smallerRemain;\n            }\n        }\n    }\n\n    // Convert rough pressure to score units; inversions cost 100 each.\n    // We use a moderate scale so beam is guided but not dominated.\n    return 12LL * pressure;\n}\n\nstatic inline long long eval_score(const Node& nd, const vector<vector<int>>& A) {\n    return true_score(nd) + optimistic_travel_lb(nd) + inversion_pressure(nd, A);\n}\n\nstatic Node apply_action(const Node& cur, const vector<vector<int>>& A, int inRow) {\n    Node nxt = cur;\n    int x = A[inRow][cur.ptr[inRow]];\n    int outRow = x / N;\n    int idxInRow = x % N;\n\n    nxt.turns += manhattan(cur.cr, cur.cc, inRow, 0);\n    nxt.cr = (uint8_t)inRow;\n    nxt.cc = 0;\n\n    nxt.turns += 1; // P\n    nxt.ptr[inRow]++;\n\n    nxt.turns += manhattan(nxt.cr, nxt.cc, outRow, N - 1);\n    nxt.cr = (uint8_t)outRow;\n    nxt.cc = (uint8_t)(N - 1);\n\n    nxt.turns += 1; // Q\n\n    nxt.inv += inversion_add(cur, outRow, x);\n    nxt.outSeq[outRow][nxt.outCnt[outRow]++] = (uint8_t)x;\n    nxt.mask[outRow] |= (uint8_t)(1u << idxInRow);\n    nxt.delivered++;\n\n    return nxt;\n}\n\n// Better-performing compact dedup signature.\nstatic unsigned long long signature(const Node& nd) {\n    unsigned long long x = 0;\n    for (int i = 0; i < N; i++) x = x * 6 + nd.ptr[i];\n    x = x * 5 + nd.cr;\n    x = x * 5 + nd.cc;\n    for (int i = 0; i < N; i++) x = x * 32 + nd.mask[i];\n    return x;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> 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<vector<Node>> layers(TOTAL + 1);\n    layers[0].push_back(Node());\n\n    for (int depth = 0; depth < TOTAL; depth++) {\n        vector<Node> cand;\n        cand.reserve(layers[depth].size() * N);\n\n        for (int idx = 0; idx < (int)layers[depth].size(); idx++) {\n            const Node& cur = layers[depth][idx];\n            for (int inRow = 0; inRow < N; inRow++) {\n                if (cur.ptr[inRow] >= N) continue;\n                Node nxt = apply_action(cur, A, inRow);\n                nxt.prev = idx;\n                nxt.actionRow = (uint8_t)inRow;\n                cand.push_back(std::move(nxt));\n            }\n        }\n\n        vector<int> ord(cand.size());\n        iota(ord.begin(), ord.end(), 0);\n\n        int preKeep = min<int>((int)ord.size(), BEAM_WIDTH * 4);\n        nth_element(ord.begin(), ord.begin() + preKeep, ord.end(),\n            [&](int a, int b) {\n                long long ea = eval_score(cand[a], A);\n                long long eb = eval_score(cand[b], A);\n                if (ea != eb) return ea < eb;\n                long long ta = true_score(cand[a]);\n                long long tb = true_score(cand[b]);\n                if (ta != tb) return ta < tb;\n                return cand[a].turns < cand[b].turns;\n            });\n        ord.resize(preKeep);\n\n        unordered_map<unsigned long long, int> bestIdx;\n        bestIdx.reserve(preKeep * 2 + 1);\n\n        vector<Node> nxtLayer;\n        nxtLayer.reserve(preKeep);\n\n        auto better = [&](const Node& a, const Node& b) {\n            long long sa = true_score(a), sb = true_score(b);\n            if (sa != sb) return sa < sb;\n            if (a.turns != b.turns) return a.turns < b.turns;\n            if (a.inv != b.inv) return a.inv < b.inv;\n            return eval_score(a, A) < eval_score(b, A);\n        };\n\n        for (int id : ord) {\n            Node& nd = cand[id];\n            auto sig = signature(nd);\n            auto it = bestIdx.find(sig);\n            if (it == bestIdx.end()) {\n                bestIdx[sig] = (int)nxtLayer.size();\n                nxtLayer.push_back(nd);\n            } else if (better(nd, nxtLayer[it->second])) {\n                nxtLayer[it->second] = nd;\n            }\n        }\n\n        sort(nxtLayer.begin(), nxtLayer.end(),\n            [&](const Node& a, const Node& b) {\n                long long ea = eval_score(a, A);\n                long long eb = eval_score(b, A);\n                if (ea != eb) return ea < eb;\n                long long sa = true_score(a), sb = true_score(b);\n                if (sa != sb) return sa < sb;\n                return a.turns < b.turns;\n            });\n\n        if ((int)nxtLayer.size() > BEAM_WIDTH) nxtLayer.resize(BEAM_WIDTH);\n        layers[depth + 1] = std::move(nxtLayer);\n    }\n\n    int best = 0;\n    for (int i = 1; i < (int)layers[TOTAL].size(); i++) {\n        if (true_score(layers[TOTAL][i]) < true_score(layers[TOTAL][best])) {\n            best = i;\n        }\n    }\n\n    vector<int> plan;\n    plan.reserve(TOTAL);\n    int idx = best;\n    for (int depth = TOTAL; depth >= 1; depth--) {\n        const Node& nd = layers[depth][idx];\n        plan.push_back(nd.actionRow);\n        idx = nd.prev;\n    }\n    reverse(plan.begin(), plan.end());\n\n    // Generate actual operations.\n    vector<string> ans(N);\n\n    auto add_turn = [&](char c0, char c1='.', char c2='.', char c3='.', char c4='.') {\n        ans[0].push_back(c0);\n        ans[1].push_back(c1);\n        ans[2].push_back(c2);\n        ans[3].push_back(c3);\n        ans[4].push_back(c4);\n    };\n\n    // Safe mode: only the large crane is active.\n    add_turn('.', 'B', 'B', 'B', 'B');\n\n    int cr = 0, cc = 0;\n    array<int, N> ptr{};\n    ptr.fill(0);\n\n    auto move_large = [&](int tr, int tc) {\n        while (cr < tr) { add_turn('D'); cr++; }\n        while (cr > tr) { add_turn('U'); cr--; }\n        while (cc < tc) { add_turn('R'); cc++; }\n        while (cc > tc) { add_turn('L'); cc--; }\n    };\n\n    for (int inRow : plan) {\n        int x = A[inRow][ptr[inRow]];\n        int outRow = x / N;\n\n        move_large(inRow, 0);\n        add_turn('P');\n        ptr[inRow]++;\n\n        move_large(outRow, N - 1);\n        add_turn('Q');\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (ans[i].empty()) ans[i] = \".\";\n        cout << ans[i] << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int TURN_LIMIT = 100000;\nstatic constexpr ll INF64 = (1LL << 60);\nstatic constexpr int BIG_CAP = 1000000000;\n\nstruct Result {\n    vector<string> ops;\n    ll cost = INF64;\n    bool finished = false;\n};\n\nstruct Simulator {\n    int N;\n    vector<vector<int>> h;\n    int x = 0, y = 0;\n    ll load = 0;\n    ll cost = 0;\n    vector<string> ops;\n\n    int cap;\n    int source_mode; // 0: plain, 1: local deficit density, 2: nearest-deficit lookahead\n\n    Simulator(int n, const vector<vector<int>>& init_h, int cap_, int source_mode_)\n        : N(n), h(init_h), cap(cap_), source_mode(source_mode_) {}\n\n    inline int dist(int x1, int y1, int x2, int y2) const {\n        return abs(x1 - x2) + abs(y1 - y2);\n    }\n\n    bool can_continue(int reserve = 0) const {\n        return (int)ops.size() < TURN_LIMIT - reserve;\n    }\n\n    void emit(const string& s) {\n        if ((int)ops.size() < TURN_LIMIT) ops.push_back(s);\n    }\n\n    void move_one(char c) {\n        emit(string(1, c));\n        cost += 100 + load;\n        if (c == 'U') --x;\n        else if (c == 'D') ++x;\n        else if (c == 'L') --y;\n        else if (c == 'R') ++y;\n    }\n\n    void move_to(int nx, int ny) {\n        while (x < nx && (int)ops.size() < TURN_LIMIT) move_one('D');\n        while (x > nx && (int)ops.size() < TURN_LIMIT) move_one('U');\n        while (y < ny && (int)ops.size() < TURN_LIMIT) move_one('R');\n        while (y > ny && (int)ops.size() < TURN_LIMIT) move_one('L');\n    }\n\n    void pickup(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"+\" + to_string(d));\n        cost += d;\n        h[x][y] -= d;\n        load += d;\n    }\n\n    void dropoff(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"-\" + to_string(d));\n        cost += d;\n        h[x][y] += d;\n        load -= d;\n    }\n\n    bool all_zero() const {\n        if (load != 0) return false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (h[i][j] != 0) return false;\n        return true;\n    }\n\n    int neg_density(int cx, int cy, int radius = 3) const {\n        int sum = 0;\n        for (int i = max(0, cx - radius); i <= min(N - 1, cx + radius); ++i) {\n            for (int j = max(0, cy - radius); j <= min(N - 1, cy + radius); ++j) {\n                if (h[i][j] < 0) {\n                    int d = dist(cx, cy, i, j);\n                    if (d <= radius) {\n                        sum += (-h[i][j]) * (radius + 1 - d);\n                    }\n                }\n            }\n        }\n        return sum;\n    }\n\n    int nearest_negative_dist(int cx, int cy) const {\n        int best = 1e9;\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (h[i][j] < 0) {\n                    best = min(best, dist(cx, cy, i, j));\n                }\n            }\n        }\n        return (best == (int)1e9 ? 0 : best);\n    }\n\n    pair<int,int> find_best_positive() const {\n        ll bestScore = INF64;\n        pair<int,int> best = {-1, -1};\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (h[i][j] <= 0) continue;\n                int d = dist(x, y, i, j);\n                int amt = h[i][j];\n\n                ll score = 100LL * d - 3LL * amt;\n\n                if (source_mode == 1) {\n                    // Mildly prefer positives near deficit clusters\n                    int dens = neg_density(i, j, 3);\n                    score -= 2LL * dens;\n                } else if (source_mode == 2) {\n                    // Mildly prefer positives near some negative cell\n                    int nd = nearest_negative_dist(i, j);\n                    score += 30LL * nd;\n                }\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    }\n\n    pair<int,int> find_best_negative() const {\n        ll bestScore = INF64;\n        pair<int,int> best = {-1, -1};\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (h[i][j] >= 0) continue;\n                int d = dist(x, y, i, j);\n                int need = -h[i][j];\n                int tr = (int)min<ll>(load, need);\n\n                ll score = (100LL + load) * d - 2LL * tr;\n\n                if (score < bestScore) {\n                    bestScore = score;\n                    best = {i, j};\n                }\n            }\n        }\n        return best;\n    }\n\n    void snake_cleanup() {\n        vector<pair<int,int>> ord;\n        ord.reserve(N * N);\n        for (int i = 0; i < N; ++i) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; ++j) ord.push_back({i, j});\n            } else {\n                for (int j = N - 1; j >= 0; --j) ord.push_back({i, j});\n            }\n        }\n\n        auto process_here = [&]() {\n            if (h[x][y] > 0) {\n                int d = (cap >= BIG_CAP ? h[x][y] : min(h[x][y], cap));\n                pickup(d);\n            } else if (h[x][y] < 0) {\n                int d = (int)min<ll>(load, -h[x][y]);\n                dropoff(d);\n            }\n        };\n\n        for (int rep = 0; rep < 10 && !all_zero() && can_continue(1000); ++rep) {\n            if (rep % 2 == 0) {\n                for (auto [i, j] : ord) {\n                    move_to(i, j);\n                    process_here();\n                }\n            } else {\n                for (int k = (int)ord.size() - 1; k >= 0; --k) {\n                    auto [i, j] = ord[k];\n                    move_to(i, j);\n                    process_here();\n                }\n            }\n        }\n    }\n\n    Result run() {\n        while (can_continue(1000)) {\n            if (all_zero()) break;\n\n            if (load == 0) {\n                auto [px, py] = find_best_positive();\n                if (px == -1) break;\n                move_to(px, py);\n                if (h[x][y] > 0) {\n                    int d = (cap >= BIG_CAP ? h[x][y] : min(h[x][y], cap));\n                    pickup(d);\n                }\n            } else {\n                auto [nx, ny] = find_best_negative();\n                if (nx == -1) break;\n                move_to(nx, ny);\n                if (h[x][y] < 0) {\n                    int d = (int)min<ll>(load, -h[x][y]);\n                    dropoff(d);\n                }\n            }\n        }\n\n        if (!all_zero() && can_continue(1000)) {\n            snake_cleanup();\n        }\n\n        Result res;\n        res.ops = ops;\n        res.cost = cost;\n        res.finished = all_zero();\n        return res;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) cin >> h[i][j];\n    }\n\n    vector<int> caps = {15, 25, 40, 70, BIG_CAP};\n    vector<int> source_modes = {0, 1, 2};\n\n    Result best;\n    best.cost = INF64;\n    best.finished = false;\n\n    for (int cap : caps) {\n        for (int mode : source_modes) {\n            Simulator sim(N, h, cap, mode);\n            Result cur = sim.run();\n\n            if (cur.finished && !best.finished) {\n                best = move(cur);\n            } else if (cur.finished == best.finished && cur.cost < best.cost) {\n                best = move(cur);\n            }\n        }\n    }\n\n    for (const string& s : best.ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 6;\nstatic constexpr int M = 15;\nstatic constexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nstatic constexpr int CELL_COUNT = N * N;           // 36\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { // [l, r)\n        return l + (int)(next_u32() % (uint32_t)(r - l));\n    }\n    double next_double() {\n        return (double)next_u32() / 4294967296.0;\n    }\n} rng;\n\nstruct Seed {\n    array<int, M> x{};\n    int sum = 0;\n};\n\nstatic inline double sqr(double x) { return x * x; }\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    vector<Seed> seeds(SEED_COUNT);\n    for (int i = 0; i < SEED_COUNT; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    auto cell_id = [&](int r, int c) { return r * N + c; };\n\n    vector<vector<int>> nbr(CELL_COUNT);\n    vector<pair<int,int>> edges;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int v = cell_id(r, c);\n            if (r + 1 < N) {\n                int u = cell_id(r + 1, c);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n            if (c + 1 < N) {\n                int u = cell_id(r, c + 1);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n        }\n    }\n\n    vector<int> degree(CELL_COUNT);\n    for (int i = 0; i < CELL_COUNT; i++) degree[i] = (int)nbr[i].size();\n\n    vector<int> cell_order(CELL_COUNT);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (degree[a] != degree[b]) return degree[a] > degree[b];\n        int ra = a / N, ca = a % N;\n        int rb = b / N, cb = b % N;\n        int da = abs(ra - 2) + abs(ca - 2);\n        int db = abs(rb - 2) + abs(cb - 2);\n        return da < db;\n    });\n\n    for (int turn = 0; turn < T; turn++) {\n        // ----- turn-aware weights -----\n        double phase = (double)turn / max(1, T - 1); // 0..1\n        // early: diversity, late: sum\n        double W_SUM = 1.0 + 1.6 * phase;\n        double W_TOP = 1.2 - 0.5 * phase;\n        double W_COVER = 1.4 - 0.8 * phase;\n        double W_PAIR_ENV = 1.0 + 0.6 * phase;\n        double W_PAIR_SUM = 0.15 + 0.35 * phase;\n        double W_CELL = 0.35 + 0.45 * phase;\n\n        // ----- global coordinate statistics -----\n        array<int, M> gmax{};\n        array<double, M> gmean{};\n        gmax.fill(0);\n        gmean.fill(0.0);\n        for (int l = 0; l < M; l++) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                gmax[l] = max(gmax[l], seeds[i].x[l]);\n                gmean[l] += seeds[i].x[l];\n            }\n            gmean[l] /= SEED_COUNT;\n        }\n\n        array<double, M> dimWeight{};\n        for (int l = 0; l < M; l++) {\n            // emphasize dimensions with large maxima and where elite values matter\n            dimWeight[l] = 1.0 + 0.02 * gmax[l];\n        }\n\n        // ----- rich seed score -----\n        vector<double> seedScore(SEED_COUNT, 0.0);\n        vector<double> eliteScore(SEED_COUNT, 0.0); // \"specialist importance\"\n        for (int i = 0; i < SEED_COUNT; i++) {\n            double sc = W_SUM * seeds[i].sum;\n            double es = 0.0;\n            for (int l = 0; l < M; l++) {\n                double x = seeds[i].x[l];\n                double rel = (gmax[l] == 0 ? 0.0 : x / gmax[l]);\n                sc += W_TOP * dimWeight[l] * rel * x * 0.35;\n                // sharp bonus near dimension max\n                double nearTop = max(0.0, rel - 0.75);\n                es += dimWeight[l] * nearTop * nearTop * 100.0;\n            }\n            seedScore[i] = sc + 0.4 * es;\n            eliteScore[i] = es;\n        }\n\n        // ----- candidate ordering -----\n        vector<int> ord(SEED_COUNT);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabs(seedScore[a] - seedScore[b]) > 1e-9) return seedScore[a] > seedScore[b];\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n\n        // ----- select 36 seeds: core by score + diverse fill by coordinate coverage -----\n        vector<int> chosen;\n        vector<int> usedSeed(SEED_COUNT, 0);\n\n        int core = 20; // stronger core than before, but leave room for specialists\n        for (int i = 0; i < core; i++) {\n            chosen.push_back(ord[i]);\n            usedSeed[ord[i]] = 1;\n        }\n\n        array<int, M> coverMax{};\n        coverMax.fill(0);\n        for (int s : chosen) {\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[s].x[l]);\n        }\n\n        while ((int)chosen.size() < CELL_COUNT) {\n            int best = -1;\n            double bestGain = -1e100;\n\n            for (int i = 0; i < SEED_COUNT; i++) if (!usedSeed[i]) {\n                double gain = 0.18 * seedScore[i] + 0.30 * eliteScore[i];\n                for (int l = 0; l < M; l++) {\n                    int inc = max(0, seeds[i].x[l] - coverMax[l]);\n                    gain += W_COVER * dimWeight[l] * inc;\n                }\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = i;\n                }\n            }\n\n            chosen.push_back(best);\n            usedSeed[best] = 1;\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[best].x[l]);\n        }\n\n        // local indices [0,35]\n        vector<int> localToSeed = chosen;\n\n        static int envScore[CELL_COUNT][CELL_COUNT];\n        static int sumScore[CELL_COUNT][CELL_COUNT];\n        static int syScore[CELL_COUNT][CELL_COUNT];\n\n        for (int i = 0; i < CELL_COUNT; i++) {\n            envScore[i][i] = sumScore[i][i] = syScore[i][i] = 0;\n            for (int j = i + 1; j < CELL_COUNT; j++) {\n                int a = localToSeed[i], b = localToSeed[j];\n                int env = 0;\n                int ss = seeds[a].sum + seeds[b].sum;\n                int syn = 0;\n                for (int l = 0; l < M; l++) {\n                    int xa = seeds[a].x[l], xb = seeds[b].x[l];\n                    env += max(xa, xb);\n\n                    // synergy bonus: high if both together cover the max well, especially if one is strong where the other is not\n                    int mn = min(xa, xb), mx = max(xa, xb);\n                    syn += mx - mn / 3;\n                }\n                envScore[i][j] = envScore[j][i] = env;\n                sumScore[i][j] = sumScore[j][i] = ss;\n                syScore[i][j] = syScore[j][i] = syn;\n            }\n        }\n\n        vector<double> localSeedCellWeight(CELL_COUNT);\n        for (int i = 0; i < CELL_COUNT; i++) {\n            int s = localToSeed[i];\n            localSeedCellWeight[i] = 0.65 * seeds[s].sum + 0.35 * eliteScore[s];\n        }\n\n        auto objective_edge = [&](int a, int b) -> double {\n            return W_PAIR_ENV * envScore[a][b] + W_PAIR_SUM * sumScore[a][b] + 0.25 * syScore[a][b];\n        };\n\n        auto placementScore = [&](const vector<int>& pl) -> double {\n            double res = 0.0;\n            for (auto [u, v] : edges) res += objective_edge(pl[u], pl[v]);\n            for (int c = 0; c < CELL_COUNT; c++) {\n                res += W_CELL * degree[c] * localSeedCellWeight[pl[c]];\n            }\n            return res;\n        };\n\n        auto deltaSwap = [&](const vector<int>& pl, int a, int b) -> double {\n            if (a == b) return 0.0;\n            int sa = pl[a], sb = pl[b];\n            double before = 0.0, after = 0.0;\n\n            // cell weight term\n            before += W_CELL * degree[a] * localSeedCellWeight[sa];\n            before += W_CELL * degree[b] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[a] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[b] * localSeedCellWeight[sa];\n\n            vector<int> vs;\n            vs.push_back(a);\n            vs.push_back(b);\n            for (int x : nbr[a]) vs.push_back(x);\n            for (int x : nbr[b]) vs.push_back(x);\n            sort(vs.begin(), vs.end());\n            vs.erase(unique(vs.begin(), vs.end()), vs.end());\n\n            set<pair<int,int>> es;\n            for (int u : vs) for (int v : nbr[u]) if (u < v) es.insert({u, v});\n\n            for (auto [u, v] : es) {\n                int pu = pl[u], pv = pl[v];\n                before += objective_edge(pu, pv);\n\n                if (u == a) pu = sb;\n                else if (u == b) pu = sa;\n                if (v == a) pv = sb;\n                else if (v == b) pv = sa;\n                after += objective_edge(pu, pv);\n            }\n\n            return after - before;\n        };\n\n        auto make_greedy = [&](bool randomized) -> vector<int> {\n            vector<int> place(CELL_COUNT, -1);\n            vector<int> used(CELL_COUNT, 0);\n\n            for (int step = 0; step < CELL_COUNT; step++) {\n                int cell = cell_order[step];\n\n                vector<pair<double,int>> cand;\n                cand.reserve(CELL_COUNT);\n                for (int si = 0; si < CELL_COUNT; si++) if (!used[si]) {\n                    double sc = W_CELL * degree[cell] * localSeedCellWeight[si];\n\n                    // adjacency with already placed neighbors\n                    for (int nb : nbr[cell]) {\n                        if (place[nb] != -1) sc += objective_edge(si, place[nb]);\n                    }\n\n                    // slight center preference\n                    int r = cell / N, c = cell % N;\n                    int md = abs(r - 2) + abs(c - 2);\n                    sc -= 0.7 * md * (0.35 * seeds[localToSeed[si]].sum + 0.1 * eliteScore[localToSeed[si]]);\n\n                    cand.push_back({sc, si});\n                }\n\n                sort(cand.begin(), cand.end(), greater<>());\n                int take = 0;\n                if (randomized) {\n                    int lim = min<int>(4, cand.size());\n                    take = rng.next_int(0, lim);\n                }\n                int bestSeed = cand[take].second;\n                place[cell] = bestSeed;\n                used[bestSeed] = 1;\n            }\n\n            // hill climbing\n            double cur = placementScore(place);\n            bool improved = true;\n            for (int it = 0; it < 10 && improved; it++) {\n                improved = false;\n\n                // random order pairs + full sweep flavor\n                vector<int> cells(CELL_COUNT);\n                iota(cells.begin(), cells.end(), 0);\n                shuffle(cells.begin(), cells.end(), std::mt19937(rng.next_u32()));\n\n                for (int xi = 0; xi < CELL_COUNT; xi++) {\n                    int a = cells[xi];\n                    double bestD = 0.0;\n                    int bestB = -1;\n                    for (int yi = xi + 1; yi < CELL_COUNT; yi++) {\n                        int b = cells[yi];\n                        double d = deltaSwap(place, a, b);\n                        if (d > bestD) {\n                            bestD = d;\n                            bestB = b;\n                        }\n                    }\n                    if (bestB != -1) {\n                        swap(place[a], place[bestB]);\n                        cur += bestD;\n                        improved = true;\n                    }\n                }\n            }\n\n            return place;\n        };\n\n        // multi-start\n        vector<int> bestPlace;\n        double bestScore = -1e100;\n\n        int trials = 10;\n        for (int tcase = 0; tcase < trials; tcase++) {\n            bool randomized = (tcase > 0);\n            auto pl = make_greedy(randomized);\n            double sc = placementScore(pl);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPlace = pl;\n            }\n        }\n\n        // output original seed indices\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (c) cout << ' ';\n                cout << localToSeed[bestPlace[cell_id(r, c)]];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // read next generation\n        for (int i = 0; i < SEED_COUNT; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int DX[4] = {0, 1, 0, -1}; // R D L U\nstatic const int DY[4] = {1, 0, -1, 0};\nstatic const char DIRC[4] = {'R', 'D', 'L', 'U'};\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    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    int K = max(1, V - 1);\n    int Vp = K + 1;\n\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) {\n        cout << 0 << ' ' << 1 << '\\n';\n    }\n\n    int rx = N / 2, ry = N / 2;\n    cout << rx << ' ' << ry << '\\n';\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    vector<int> dir(K, 0);   // 0:R 1:D 2:L 3:U\n    vector<int> hold(K, 0);  // whether leaf holds takoyaki\n\n    auto is_surplus = [&](int x, int y) -> bool {\n        return s[x][y] == '1' && t[x][y] == '0';\n    };\n    auto is_deficit = [&](int x, int y) -> bool {\n        return s[x][y] == '0' && t[x][y] == '1';\n    };\n\n    auto rem = [&]() -> int {\n        int diff = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (s[i][j] != t[i][j]) diff++;\n        }\n        return diff / 2;\n    };\n\n    auto hold_count = [&]() -> int {\n        int c = 0;\n        for (int v : hold) c += v;\n        return c;\n    };\n\n    auto step_toward = [&](int tx, int ty) -> char {\n        if (rx < tx && inb(rx + 1, ry)) return 'D';\n        if (rx > tx && inb(rx - 1, ry)) return 'U';\n        if (ry < ty && inb(rx, ry + 1)) return 'R';\n        if (ry > ty && inb(rx, ry - 1)) return 'L';\n        return '.';\n    };\n\n    auto rotate_one_toward = [&](int leaf, int target_dir) -> char {\n        int cur = dir[leaf];\n        int diff = (target_dir - cur + 4) % 4;\n        if (diff == 0) return '.';\n        if (diff == 1) return 'R';\n        if (diff == 3) return 'L';\n        return 'R'; // opposite -> one step\n    };\n\n    auto adjacent_dir = [&](int cx, int cy, int tx, int ty) -> int {\n        for (int d = 0; d < 4; d++) {\n            if (cx + DX[d] == tx && cy + DY[d] == ty) return d;\n        }\n        return -1;\n    };\n\n    auto best_adjacent_root = [&](int tx, int ty) -> Pos {\n        int best = 1e9;\n        Pos res{rx, ry};\n        for (int d = 0; d < 4; d++) {\n            int x = tx - DX[d], y = ty - DY[d];\n            if (!inb(x, y)) continue;\n            int dist = abs(x - rx) + abs(y - ry);\n            if (dist < best) {\n                best = dist;\n                res = {x, y};\n            }\n        }\n        return res;\n    };\n\n    auto all_surplus = [&]() {\n        vector<Pos> v;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (is_surplus(i, j)) v.push_back({i, j});\n        }\n        return v;\n    };\n\n    auto all_deficit = [&]() {\n        vector<Pos> v;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (is_deficit(i, j)) v.push_back({i, j});\n        }\n        return v;\n    };\n\n    const int TURN_LIMIT = 100000;\n    vector<string> ops;\n\n    auto apply_turn = [&](char mv, const vector<char>& rot, const vector<char>& wantAct) -> bool {\n        if ((int)ops.size() >= TURN_LIMIT) return false;\n\n        string cmd(2 * Vp, '.');\n\n        int nrx = rx, nry = ry;\n        cmd[0] = mv;\n        if (mv != '.') {\n            int d = -1;\n            for (int k = 0; k < 4; k++) if (DIRC[k] == mv) d = k;\n            if (d != -1) {\n                int tx = rx + DX[d], ty = ry + DY[d];\n                if (inb(tx, ty)) {\n                    nrx = tx;\n                    nry = ty;\n                }\n            }\n        }\n\n        vector<int> ndir = dir;\n        for (int i = 0; i < K; i++) {\n            cmd[1 + i] = rot[i];\n            if (rot[i] == 'L') ndir[i] = (ndir[i] + 3) % 4;\n            else if (rot[i] == 'R') ndir[i] = (ndir[i] + 1) % 4;\n        }\n\n        // Sequential simulation of P actions\n        vector<string> board = s;\n        vector<int> nhold = hold;\n\n        for (int i = 0; i < K; i++) {\n            if (wantAct[i] != 'P') continue;\n            int x = nrx + DX[ndir[i]];\n            int y = nry + DY[ndir[i]];\n            if (!inb(x, y)) continue;\n\n            if (nhold[i]) {\n                if (board[x][y] == '0' && t[x][y] == '1') {\n                    board[x][y] = '1';\n                    nhold[i] = 0;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            } else {\n                if (board[x][y] == '1' && t[x][y] == '0') {\n                    board[x][y] = '0';\n                    nhold[i] = 1;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            }\n        }\n\n        rx = nrx;\n        ry = nry;\n        dir = ndir;\n        hold = nhold;\n        s.swap(board);\n\n        ops.push_back(cmd);\n        return true;\n    };\n\n    auto bulk_step = [&]() -> bool {\n        if ((int)ops.size() >= TURN_LIMIT) return false;\n\n        int hcnt = hold_count();\n        int ecnt = K - hcnt;\n        bool prefer_place = (hcnt > 0);\n\n        auto eval_pos = [&](int x, int y) -> int {\n            int sur = 0, def = 0;\n            for (int d = 0; d < 4; d++) {\n                int nx = x + DX[d], ny = y + DY[d];\n                if (!inb(nx, ny)) continue;\n                if (is_surplus(nx, ny)) sur++;\n                if (is_deficit(nx, ny)) def++;\n            }\n            sur = min(sur, ecnt);\n            def = min(def, hcnt);\n            int score = sur * 1000 + def * 1000;\n            score += prefer_place ? def * 50 : sur * 50;\n            score -= (abs(x - rx) + abs(y - ry)) * 10;\n            return score;\n        };\n\n        int bestScore = -1e9;\n        Pos target{rx, ry};\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            int sc = eval_pos(x, y);\n            if (sc > bestScore) {\n                bestScore = sc;\n                target = {x, y};\n            }\n        }\n\n        char mv = step_toward(target.x, target.y);\n        int nrx = rx, nry = ry;\n        if (mv == 'R') nry++;\n        else if (mv == 'L') nry--;\n        else if (mv == 'D') nrx++;\n        else if (mv == 'U') nrx--;\n\n        vector<char> rot(K, '.');\n        vector<int> desired(K, -1);\n        vector<int> used(4, 0);\n\n        // holders -> deficits\n        for (int i = 0; i < K; i++) {\n            if (!hold[i]) continue;\n            int bestd = -1, bestcost = 10;\n            for (int d = 0; d < 4; d++) {\n                if (used[d]) continue;\n                int x = nrx + DX[d], y = nry + DY[d];\n                if (!inb(x, y) || !is_deficit(x, y)) continue;\n                int diff = (d - dir[i] + 4) % 4;\n                int cost = (diff == 0 ? 0 : diff == 2 ? 2 : 1);\n                if (cost < bestcost) {\n                    bestcost = cost;\n                    bestd = d;\n                }\n            }\n            if (bestd != -1) {\n                used[bestd] = 1;\n                desired[i] = bestd;\n                rot[i] = rotate_one_toward(i, bestd);\n            }\n        }\n\n        // empties -> surpluses\n        for (int i = 0; i < K; i++) {\n            if (hold[i]) continue;\n            int bestd = -1, bestcost = 10;\n            for (int d = 0; d < 4; d++) {\n                if (used[d]) continue;\n                int x = nrx + DX[d], y = nry + DY[d];\n                if (!inb(x, y) || !is_surplus(x, y)) continue;\n                int diff = (d - dir[i] + 4) % 4;\n                int cost = (diff == 0 ? 0 : diff == 2 ? 2 : 1);\n                if (cost < bestcost) {\n                    bestcost = cost;\n                    bestd = d;\n                }\n            }\n            if (bestd != -1) {\n                used[bestd] = 1;\n                desired[i] = bestd;\n                rot[i] = rotate_one_toward(i, bestd);\n            }\n        }\n\n        vector<char> act(K, '.');\n        vector<int> ndir = dir;\n        for (int i = 0; i < K; i++) {\n            if (rot[i] == 'L') ndir[i] = (ndir[i] + 3) % 4;\n            else if (rot[i] == 'R') ndir[i] = (ndir[i] + 1) % 4;\n        }\n\n        // Sequential legal planning\n        vector<string> board = s;\n        vector<int> nhold = hold;\n        for (int i = 0; i < K; i++) {\n            int x = nrx + DX[ndir[i]], y = nry + DY[ndir[i]];\n            if (!inb(x, y)) continue;\n\n            if (nhold[i]) {\n                if (board[x][y] == '0' && t[x][y] == '1') {\n                    act[i] = 'P';\n                    board[x][y] = '1';\n                    nhold[i] = 0;\n                }\n            } else {\n                if (board[x][y] == '1' && t[x][y] == '0') {\n                    act[i] = 'P';\n                    board[x][y] = '0';\n                    nhold[i] = 1;\n                }\n            }\n        }\n\n        return apply_turn(mv, rot, act);\n    };\n\n    auto exact_deliver_held = [&](int leaf, Pos dst) -> bool {\n        Pos b = best_adjacent_root(dst.x, dst.y);\n\n        while ((rx != b.x || ry != b.y)) {\n            if ((int)ops.size() >= TURN_LIMIT) return false;\n            char mv = step_toward(b.x, b.y);\n            vector<char> rot(K, '.'), act(K, '.');\n            if (!apply_turn(mv, rot, act)) return false;\n        }\n\n        while ((int)ops.size() < TURN_LIMIT) {\n            int d = adjacent_dir(rx, ry, dst.x, dst.y);\n            if (d == -1) return true;\n\n            vector<char> rot(K, '.'), act(K, '.');\n            char rr = rotate_one_toward(leaf, d);\n            rot[leaf] = rr;\n\n            int nd = dir[leaf];\n            if (rr == 'L') nd = (nd + 3) % 4;\n            else if (rr == 'R') nd = (nd + 1) % 4;\n\n            if (nd == d && hold[leaf] && is_deficit(dst.x, dst.y)) {\n                act[leaf] = 'P';\n                return apply_turn('.', rot, act);\n            } else {\n                if (!apply_turn('.', rot, act)) return false;\n            }\n        }\n        return false;\n    };\n\n    auto exact_pick_and_place = [&](int leaf, Pos src, Pos dst) -> bool {\n        Pos a = best_adjacent_root(src.x, src.y);\n        while ((rx != a.x || ry != a.y)) {\n            if ((int)ops.size() >= TURN_LIMIT) return false;\n            char mv = step_toward(a.x, a.y);\n            vector<char> rot(K, '.'), act(K, '.');\n            if (!apply_turn(mv, rot, act)) return false;\n        }\n\n        while ((int)ops.size() < TURN_LIMIT) {\n            int d = adjacent_dir(rx, ry, src.x, src.y);\n            if (d == -1) return false;\n\n            vector<char> rot(K, '.'), act(K, '.');\n            char rr = rotate_one_toward(leaf, d);\n            rot[leaf] = rr;\n\n            int nd = dir[leaf];\n            if (rr == 'L') nd = (nd + 3) % 4;\n            else if (rr == 'R') nd = (nd + 1) % 4;\n\n            if (nd == d && !hold[leaf] && is_surplus(src.x, src.y)) {\n                act[leaf] = 'P';\n                if (!apply_turn('.', rot, act)) return false;\n                break;\n            } else {\n                if (!apply_turn('.', rot, act)) return false;\n            }\n        }\n\n        Pos b = best_adjacent_root(dst.x, dst.y);\n        while ((rx != b.x || ry != b.y)) {\n            if ((int)ops.size() >= TURN_LIMIT) return false;\n            char mv = step_toward(b.x, b.y);\n            vector<char> rot(K, '.'), act(K, '.');\n            if (!apply_turn(mv, rot, act)) return false;\n        }\n\n        while ((int)ops.size() < TURN_LIMIT) {\n            int d = adjacent_dir(rx, ry, dst.x, dst.y);\n            if (d == -1) return false;\n\n            vector<char> rot(K, '.'), act(K, '.');\n            char rr = rotate_one_toward(leaf, d);\n            rot[leaf] = rr;\n\n            int nd = dir[leaf];\n            if (rr == 'L') nd = (nd + 3) % 4;\n            else if (rr == 'R') nd = (nd + 1) % 4;\n\n            if (nd == d && hold[leaf] && is_deficit(dst.x, dst.y)) {\n                act[leaf] = 'P';\n                return apply_turn('.', rot, act);\n            } else {\n                if (!apply_turn('.', rot, act)) return false;\n            }\n        }\n        return false;\n    };\n\n    bool alive = true;\n    while (alive && rem() > 0 && (int)ops.size() < TURN_LIMIT) {\n        int r = rem();\n\n        if (r > 8) {\n            alive = bulk_step();\n            continue;\n        }\n\n        bool progressed = false;\n\n        // deliver already-held items first\n        auto defs = all_deficit();\n        for (int i = 0; alive && i < K && !progressed; i++) {\n            if (!hold[i]) continue;\n            if (defs.empty()) break;\n\n            Pos best = defs[0];\n            int bestDist = 1e9;\n            for (auto &p : defs) {\n                Pos a = best_adjacent_root(p.x, p.y);\n                int dist = abs(rx - a.x) + abs(ry - a.y);\n                if (dist < bestDist) {\n                    bestDist = dist;\n                    best = p;\n                }\n            }\n\n            int before = rem();\n            alive = exact_deliver_held(i, best);\n            if (!alive) break;\n            if (rem() < before) progressed = true;\n        }\n        if (!alive || progressed) continue;\n\n        auto surs = all_surplus();\n        defs = all_deficit();\n        if (surs.empty() || defs.empty()) break;\n\n        int bi = 0, bj = 0, best = 1e9;\n        for (int i = 0; i < (int)surs.size(); i++) {\n            for (int j = 0; j < (int)defs.size(); j++) {\n                int d = abs(surs[i].x - defs[j].x) + abs(surs[i].y - defs[j].y);\n                if (d < best) {\n                    best = d;\n                    bi = i;\n                    bj = j;\n                }\n            }\n        }\n\n        int before = rem();\n        alive = exact_pick_and_place(0, surs[bi], defs[bj]);\n        if (!alive) break;\n\n        if (rem() == before) {\n            if ((int)ops.size() >= TURN_LIMIT) break;\n            vector<char> rot(K, '.'), act(K, '.');\n            alive = apply_turn('.', rot, act);\n        }\n    }\n\n    if ((int)ops.size() > TURN_LIMIT) ops.resize(TURN_LIMIT);\n    for (auto &op : ops) cout << op << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct GridData {\n    int D;\n    int ox, oy;\n    int W, H;\n    vector<int> w;\n};\n\nstruct Candidate {\n    ll score = LLONG_MIN;\n    vector<unsigned char> sel;\n    int H = 0, W = 0, ox = 0, oy = 0, D = 0;\n    vector<pair<int,int>> poly;\n    bool valid = false;\n};\n\nstatic inline long long pack64(int a, int b) {\n    return ((long long)a << 32) ^ (unsigned int)b;\n}\n\nstatic inline int mdist(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nGridData build_grid(const vector<Point>& mac, const vector<Point>& sar, int D) {\n    int minx = 1e9, miny = 1e9, maxx = -1, maxy = -1;\n    auto upd = [&](const Point& p) {\n        int gx = p.x / D, gy = p.y / D;\n        minx = min(minx, gx);\n        maxx = max(maxx, gx);\n        miny = min(miny, gy);\n        maxy = max(maxy, gy);\n    };\n    for (auto &p : mac) upd(p);\n    for (auto &p : sar) upd(p);\n\n    GridData g;\n    g.D = D;\n    g.ox = minx;\n    g.oy = miny;\n    g.W = maxx - minx + 1;\n    g.H = maxy - miny + 1;\n    g.w.assign(g.H * g.W, 0);\n\n    auto id = [&](int r, int c) { return r * g.W + c; };\n    for (auto &p : mac) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r, c)]++;\n    }\n    for (auto &p : sar) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r, c)]--;\n    }\n    return g;\n}\n\nGridData build_grid_subregion(const vector<Point>& mac, const vector<Point>& sar, int D, int gx0, int gx1, int gy0, int gy1) {\n    GridData g;\n    g.D = D;\n    g.ox = gx0;\n    g.oy = gy0;\n    g.W = gx1 - gx0 + 1;\n    g.H = gy1 - gy0 + 1;\n    g.w.assign(g.H * g.W, 0);\n\n    auto add_point = [&](const Point& p, int delta) {\n        int gx = p.x / D, gy = p.y / D;\n        if (gx0 <= gx && gx <= gx1 && gy0 <= gy && gy <= gy1) {\n            int c = gx - gx0;\n            int r = gy - gy0;\n            g.w[r * g.W + c] += delta;\n        }\n    };\n\n    for (auto &p : mac) add_point(p, +1);\n    for (auto &p : sar) add_point(p, -1);\n    return g;\n}\n\nll compute_score(const vector<unsigned char>& sel, const GridData& g) {\n    ll s = 0;\n    for (int i = 0; i < (int)sel.size(); i++) if (sel[i]) s += g.w[i];\n    return s;\n}\n\nint compute_perim_edges(const vector<unsigned char>& sel, int H, int W) {\n    auto id = [&](int r, int c) { return r * W + c; };\n    int pe = 0;\n    for (int r = 0; r < H; r++) for (int c = 0; c < W; c++) if (sel[id(r, c)]) {\n        if (r == 0 || !sel[id(r - 1, c)]) pe++;\n        if (r + 1 == H || !sel[id(r + 1, c)]) pe++;\n        if (c == 0 || !sel[id(r, c - 1)]) pe++;\n        if (c + 1 == W || !sel[id(r, c + 1)]) pe++;\n    }\n    return pe;\n}\n\nbool is_connected_after_removal(const vector<unsigned char>& sel, int H, int W, int rem) {\n    int total = 0, start = -1;\n    for (int i = 0; i < H * W; i++) {\n        if (i == rem) continue;\n        if (sel[i]) total++, start = i;\n    }\n    if (total <= 1) return true;\n\n    vector<unsigned char> vis(H * W, 0);\n    queue<int> q;\n    q.push(start);\n    vis[start] = 1;\n    int cnt = 1;\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int r = v / W, c = v % W;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                int u = id(nr, nc);\n                if (u == rem || !sel[u] || vis[u]) continue;\n                vis[u] = 1;\n                q.push(u);\n                cnt++;\n            }\n        }\n    }\n    return cnt == total;\n}\n\nstruct BuildResult {\n    bool ok = false;\n    vector<pair<int,int>> poly;\n};\n\nBuildResult build_polygon_from_selected(const vector<unsigned char>& sel, int H, int W, int ox, int oy, int D) {\n    struct Edge {\n        int x1, y1, x2, y2;\n        bool operator==(const Edge& o) const {\n            return x1 == o.x1 && y1 == o.y1 && x2 == o.x2 && y2 == o.y2;\n        }\n    };\n    struct EdgeHash {\n        size_t operator()(Edge const& e) const noexcept {\n            uint64_t h = 1469598103934665603ULL;\n            auto add = [&](uint64_t v) {\n                h ^= v + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);\n            };\n            add((uint32_t)e.x1); add((uint32_t)e.y1); add((uint32_t)e.x2); add((uint32_t)e.y2);\n            return (size_t)h;\n        }\n    };\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    unordered_set<Edge, EdgeHash> S;\n    S.reserve(H * W * 2);\n\n    auto toggle = [&](Edge e) {\n        Edge rev{e.x2, e.y2, e.x1, e.y1};\n        auto it = S.find(rev);\n        if (it != S.end()) S.erase(it);\n        else S.insert(e);\n    };\n\n    int cntSel = 0;\n    for (int r = 0; r < H; r++) for (int c = 0; c < W; c++) if (sel[id(r, c)]) {\n        cntSel++;\n        int gx = ox + c, gy = oy + r;\n        int x = gx * D, y = gy * D;\n        toggle({x, y, x + D, y});\n        toggle({x + D, y, x + D, y + D});\n        toggle({x + D, y + D, x, y + D});\n        toggle({x, y + D, x, y});\n    }\n    if (cntSel == 0 || S.empty()) return {};\n\n    unordered_map<long long, vector<pair<int,int>>> out;\n    out.reserve(S.size() * 2);\n    auto pkey = [&](int x, int y) { return pack64(x, y); };\n    for (auto &e : S) out[pkey(e.x1, e.y1)].push_back({e.x2, e.y2});\n\n    auto ekey = [&](int x1, int y1, int x2, int y2) {\n        uint64_t h = 1469598103934665603ULL;\n        auto add = [&](uint64_t v) {\n            h ^= v + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);\n        };\n        add((uint32_t)x1); add((uint32_t)y1); add((uint32_t)x2); add((uint32_t)y2);\n        return (long long)h;\n    };\n\n    unordered_set<long long> used;\n    used.reserve(S.size() * 2);\n\n    int cycles = 0;\n    vector<pair<int,int>> best;\n\n    for (auto &e : S) {\n        long long k0 = ekey(e.x1, e.y1, e.x2, e.y2);\n        if (used.count(k0)) continue;\n\n        cycles++;\n        vector<pair<int,int>> cur;\n        int sx = e.x1, sy = e.y1;\n        int cx = e.x1, cy = e.y1;\n        int nx = e.x2, ny = e.y2;\n        cur.push_back({cx, cy});\n\n        while (true) {\n            long long kk = ekey(cx, cy, nx, ny);\n            if (used.count(kk)) break;\n            used.insert(kk);\n\n            cx = nx; cy = ny;\n            cur.push_back({cx, cy});\n            if (cx == sx && cy == sy) break;\n\n            auto it = out.find(pkey(cx, cy));\n            if (it == out.end()) return {};\n            int cnt = 0;\n            pair<int,int> nxt;\n            for (auto &to : it->second) {\n                long long nk = ekey(cx, cy, to.first, to.second);\n                if (!used.count(nk)) cnt++, nxt = to;\n            }\n            if (cnt != 1) return {};\n            nx = nxt.first;\n            ny = nxt.second;\n        }\n\n        if (!cur.empty() && cur.front() == cur.back()) cur.pop_back();\n        if (cur.size() > best.size()) best = move(cur);\n    }\n\n    if ((int)used.size() != (int)S.size()) return {};\n    if (cycles != 1) return {};\n\n    vector<pair<int,int>> poly;\n    int m = (int)best.size();\n    for (int i = 0; i < m; i++) {\n        auto p0 = best[(i - 1 + m) % m];\n        auto p1 = best[i];\n        auto p2 = best[(i + 1) % m];\n        int dx1 = (p1.first > p0.first) - (p1.first < p0.first);\n        int dy1 = (p1.second > p0.second) - (p1.second < p0.second);\n        int dx2 = (p2.first > p1.first) - (p2.first < p1.first);\n        int dy2 = (p2.second > p1.second) - (p2.second < p1.second);\n        if (dx1 == dx2 && dy1 == dy2) continue;\n        poly.push_back(p1);\n    }\n\n    if ((int)poly.size() < 4 || (int)poly.size() > 1000) return {};\n    {\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != (int)poly.size()) return {};\n    }\n    ll peri = 0;\n    for (int i = 0; i < (int)poly.size(); i++) peri += mdist(poly[i], poly[(i + 1) % poly.size()]);\n    if (peri > 400000) return {};\n    for (auto &p : poly) {\n        if (p.first < 0 || p.first > 100000 || p.second < 0 || p.second > 100000) return {};\n    }\n    return {true, poly};\n}\n\nCandidate candidate_from_rectangle(const GridData& g) {\n    Candidate best;\n    best.H = g.H; best.W = g.W; best.ox = g.ox; best.oy = g.oy; best.D = g.D;\n\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    vector<int> col(W);\n\n    for (int top = 0; top < H; top++) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < H; bot++) {\n            int hc = bot - top + 1;\n            for (int c = 0; c < W; c++) col[c] += g.w[id(bot, c)];\n            int max_wh = 200000 / D - hc;\n            if (max_wh <= 0) continue;\n            int maxWidth = min(W, max_wh);\n\n            ll curBest = LLONG_MIN;\n            int bestL = -1, bestR = -1;\n            for (int l = 0; l < W; l++) {\n                ll s = 0;\n                for (int r = l; r < W && r - l + 1 <= maxWidth; r++) {\n                    s += col[r];\n                    if (s > curBest) curBest = s, bestL = l, bestR = r;\n                }\n            }\n            if (bestL == -1 || curBest <= best.score) continue;\n            vector<unsigned char> sel(H * W, 0);\n            for (int r = top; r <= bot; r++) for (int c = bestL; c <= bestR; c++) sel[id(r, c)] = 1;\n            best.score = curBest;\n            best.sel = move(sel);\n            best.valid = true;\n        }\n    }\n    return best;\n}\n\nCandidate candidate_from_threshold(const GridData& g, int T) {\n    int H = g.H, W = g.W;\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    vector<unsigned char> good(H * W, 0), vis(H * W, 0);\n    for (int i = 0; i < H * W; i++) if (g.w[i] >= T) good[i] = 1;\n\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    ll bestScore = LLONG_MIN;\n    vector<unsigned char> bestSel(H * W, 0);\n\n    for (int s = 0; s < H * W; s++) {\n        if (!good[s] || vis[s]) continue;\n        queue<int> q;\n        vector<int> comp;\n        q.push(s);\n        vis[s] = 1;\n        ll sc = 0;\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            comp.push_back(v);\n            sc += g.w[v];\n            int r = v / W, c = v % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                    int u = id(nr, nc);\n                    if (good[u] && !vis[u]) vis[u] = 1, q.push(u);\n                }\n            }\n        }\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            fill(bestSel.begin(), bestSel.end(), 0);\n            for (int v : comp) bestSel[v] = 1;\n        }\n    }\n\n    Candidate c;\n    c.H = g.H; c.W = g.W; c.ox = g.ox; c.oy = g.oy; c.D = g.D;\n    if (bestScore == LLONG_MIN) return c;\n    c.score = bestScore;\n    c.sel = move(bestSel);\n    c.valid = true;\n    return c;\n}\n\nCandidate candidate_from_greedy(const GridData& g, double pen, int maxSeeds = 18) {\n    Candidate best;\n    best.H = g.H; best.W = g.W; best.ox = g.ox; best.oy = g.oy; best.D = g.D;\n\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    vector<int> ord(H * W);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (g.w[a] != g.w[b]) return g.w[a] > g.w[b];\n        return a < b;\n    });\n\n    maxSeeds = min(maxSeeds, H * W);\n\n    for (int si = 0; si < maxSeeds; si++) {\n        int seed = ord[si];\n        if (g.w[seed] <= 0 && si >= 6) break;\n\n        vector<unsigned char> sel(H * W, 0);\n        vector<int> ver(H * W, 0);\n        ll score = 0;\n        int perim_edges = 0;\n        int perim_limit = 400000 / D;\n\n        auto neigh_sel = [&](int v) {\n            int r = v / W, c = v % W;\n            int cnt = 0;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W && sel[id(nr, nc)]) cnt++;\n            }\n            return cnt;\n        };\n\n        struct Node {\n            double pri;\n            int v, ver;\n            bool operator<(const Node& o) const { return pri < o.pri; }\n        };\n        priority_queue<Node> pq;\n\n        auto push = [&](int v) {\n            if (sel[v]) return;\n            int ns = neigh_sel(v);\n            if (ns == 0) return;\n            int de = 4 - 2 * ns;\n            double pri = g.w[v] * 12.0 - pen * de + ns * 2.0;\n            pq.push({pri, v, ++ver[v]});\n        };\n\n        auto add = [&](int v) {\n            int ns = neigh_sel(v);\n            int de = 4 - 2 * ns;\n            sel[v] = 1;\n            score += g.w[v];\n            perim_edges += de;\n            int r = v / W, c = v % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                    int u = id(nr, nc);\n                    if (!sel[u]) push(u);\n                }\n            }\n        };\n\n        add(seed);\n        {\n            int r = seed / W, c = seed % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) push(id(nr, nc));\n            }\n        }\n\n        int iter = 0, iterLimit = H * W * 4;\n        while (!pq.empty() && iter < iterLimit) {\n            iter++;\n            auto cur = pq.top(); pq.pop();\n            int v = cur.v;\n            if (sel[v] || cur.ver != ver[v]) continue;\n            int ns = neigh_sel(v);\n            if (ns == 0) continue;\n            int de = 4 - 2 * ns;\n            if (perim_edges + de > perim_limit) continue;\n\n            double gain = g.w[v] * 12.0 - pen * de + ns * 2.0;\n            bool ok = false;\n            if (gain >= 0) ok = true;\n            else if (g.w[v] >= 0 && ns >= 2 && gain >= -2.0) ok = true;\n            else if (g.w[v] == -1 && ns >= 3 && gain >= -1.0) ok = true;\n            if (!ok) continue;\n            add(v);\n        }\n\n        if (score > best.score) {\n            best.score = score;\n            best.sel = move(sel);\n            best.valid = true;\n        }\n    }\n    return best;\n}\n\nvoid local_improve(Candidate& cand, const GridData& g, int rounds) {\n    if (!cand.valid) return;\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    auto &sel = cand.sel;\n    ll score = compute_score(sel, g);\n    int perim_edges = compute_perim_edges(sel, H, W);\n    int perim_limit = 400000 / D;\n\n    auto neigh_sel = [&](int v) {\n        int r = v / W, c = v % W;\n        int cnt = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W && sel[id(nr, nc)]) cnt++;\n        }\n        return cnt;\n    };\n\n    auto boundary_selected = [&](int v) {\n        if (!sel[v]) return false;\n        int r = v / W, c = v % W;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!(0 <= nr && nr < H && 0 <= nc && nc < W)) return true;\n            if (!sel[id(nr, nc)]) return true;\n        }\n        return false;\n    };\n\n    for (int step = 0; step < rounds; step++) {\n        double bestMerit = 0.0;\n        int bestType = 0, bestV = -1, bestDE = 0;\n        ll bestDS = 0;\n\n        for (int v = 0; v < H * W; v++) {\n            if (!sel[v]) {\n                int ns = neigh_sel(v);\n                if (ns == 0) continue;\n                int de = 4 - 2 * ns;\n                if (perim_edges + de > perim_limit) continue;\n                ll ds = g.w[v];\n                double merit = ds * 12.0 - de * 2.5 + ns * 1.5;\n                if (merit > bestMerit) {\n                    bestMerit = merit;\n                    bestType = +1;\n                    bestV = v;\n                    bestDE = de;\n                    bestDS = ds;\n                }\n            } else {\n                if (!boundary_selected(v)) continue;\n                int ns = neigh_sel(v);\n                int de = -4 + 2 * ns;\n                ll ds = -g.w[v];\n                double merit = ds * 12.0 - de * 2.5;\n                if (merit <= bestMerit) continue;\n                if (ns >= 2 && !is_connected_after_removal(sel, H, W, v)) continue;\n                if (perim_edges + de > perim_limit) continue;\n                bestMerit = merit;\n                bestType = -1;\n                bestV = v;\n                bestDE = de;\n                bestDS = ds;\n            }\n        }\n\n        if (bestType == 0) break;\n        if (bestType == +1) sel[bestV] = 1;\n        else sel[bestV] = 0;\n        score += bestDS;\n        perim_edges += bestDE;\n    }\n    cand.score = score;\n}\n\nvoid morph_cleanup(Candidate& cand, const GridData& g, int passes) {\n    if (!cand.valid) return;\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n    int perim_limit = 400000 / D;\n\n    auto &sel = cand.sel;\n    auto neigh_sel = [&](const vector<unsigned char>& cur, int v) {\n        int r = v / W, c = v % W;\n        int cnt = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W && cur[id(nr, nc)]) cnt++;\n        }\n        return cnt;\n    };\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed = false;\n        vector<unsigned char> nxt = sel;\n        int pe = compute_perim_edges(sel, H, W);\n\n        for (int v = 0; v < H * W; v++) if (!sel[v]) {\n            int ns = neigh_sel(sel, v);\n            if (ns >= 3) {\n                int de = 4 - 2 * ns;\n                if (pe + de <= perim_limit && (g.w[v] >= -1 || ns == 4)) {\n                    nxt[v] = 1;\n                    pe += de;\n                    changed = true;\n                }\n            }\n        }\n        sel.swap(nxt);\n\n        nxt = sel;\n        pe = compute_perim_edges(sel, H, W);\n        for (int v = 0; v < H * W; v++) if (sel[v]) {\n            int ns = neigh_sel(sel, v);\n            if (ns <= 1 && g.w[v] <= 0) {\n                if (ns >= 2 && !is_connected_after_removal(sel, H, W, v)) continue;\n                int de = -4 + 2 * ns;\n                if (pe + de <= perim_limit) {\n                    nxt[v] = 0;\n                    pe += de;\n                    changed = true;\n                }\n            }\n        }\n        sel.swap(nxt);\n\n        if (!changed) break;\n    }\n    cand.score = compute_score(sel, g);\n}\n\nbool finalize_candidate(Candidate& cand, const GridData& g) {\n    if (!cand.valid) return false;\n    auto br = build_polygon_from_selected(cand.sel, g.H, g.W, g.ox, g.oy, g.D);\n    if (!br.ok) {\n        cand.valid = false;\n        return false;\n    }\n    cand.poly = move(br.poly);\n    cand.score = compute_score(cand.sel, g);\n    cand.valid = true;\n    return true;\n}\n\nvector<int> get_boundary_cells(const Candidate& c, const GridData& g, int lim) {\n    vector<pair<int,int>> tmp;\n    int H = g.H, W = g.W;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    for (int v = 0; v < H * W; v++) if (c.sel[v]) {\n        int r = v / W, cc = v % W;\n        bool boundary = false;\n        int open = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = cc + dc[k];\n            if (!(0 <= nr && nr < H && 0 <= nc && nc < W) || !c.sel[id(nr, nc)]) {\n                boundary = true;\n                open++;\n            }\n        }\n        if (boundary) {\n            int score = g.w[v] * 10 + open;\n            tmp.push_back({score, v});\n        }\n    }\n\n    sort(tmp.begin(), tmp.end(), [&](auto &a, auto &b) { return a.first > b.first; });\n    vector<int> res;\n    for (int i = 0; i < (int)tmp.size() && i < lim; i++) res.push_back(tmp[i].second);\n    return res;\n}\n\npair<vector<unsigned char>, ll> make_corridor_union(\n    const Candidate& A, const Candidate& B, const GridData& g,\n    int a, int b, bool horiz_first\n) {\n    int H = g.H, W = g.W;\n    auto id = [&](int r, int c) { return r * W + c; };\n    vector<unsigned char> sel = A.sel;\n    for (int i = 0; i < H * W; i++) if (B.sel[i]) sel[i] = 1;\n\n    int ar = a / W, ac = a % W;\n    int br = b / W, bc = b % W;\n    ll gain = 0;\n\n    auto add_cell = [&](int r, int c) {\n        int v = id(r, c);\n        if (!sel[v]) sel[v] = 1, gain += g.w[v];\n    };\n\n    int r = ar, c = ac;\n    add_cell(r, c);\n\n    if (horiz_first) {\n        while (c != bc) c += (c < bc ? 1 : -1), add_cell(r, c);\n        while (r != br) r += (r < br ? 1 : -1), add_cell(r, c);\n    } else {\n        while (r != br) r += (r < br ? 1 : -1), add_cell(r, c);\n        while (c != bc) c += (c < bc ? 1 : -1), add_cell(r, c);\n    }\n\n    return {move(sel), gain};\n}\n\nCandidate merge_two_candidates(const Candidate& A, const Candidate& B, const GridData& g) {\n    Candidate res;\n    if (!A.valid || !B.valid) return res;\n\n    int H = g.H, W = g.W;\n    int perim_limit = 400000 / g.D;\n\n    vector<int> BA = get_boundary_cells(A, g, 8);\n    vector<int> BB = get_boundary_cells(B, g, 8);\n    if (BA.empty() || BB.empty()) return res;\n\n    ll bestScore = LLONG_MIN;\n    vector<unsigned char> bestSel;\n\n    for (int a : BA) {\n        int ar = a / W, ac = a % W;\n        for (int b : BB) {\n            int br = b / W, bc = b % W;\n            int dist = abs(ar - br) + abs(ac - bc);\n            if (dist > perim_limit) continue;\n\n            for (int t = 0; t < 2; t++) {\n                auto cur = make_corridor_union(A, B, g, a, b, t == 0);\n                ll sc = compute_score(cur.first, g);\n                int pe = compute_perim_edges(cur.first, H, W);\n                if (pe > perim_limit) continue;\n                sc = sc * 1000 - dist;\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestSel = move(cur.first);\n                }\n            }\n        }\n    }\n\n    if (bestScore == LLONG_MIN) return res;\n    res.H = g.H; res.W = g.W; res.ox = g.ox; res.oy = g.oy; res.D = g.D;\n    res.sel = move(bestSel);\n    res.score = compute_score(res.sel, g);\n    res.valid = true;\n    return res;\n}\n\nbool bbox_of_selection(const Candidate& c, int& r0, int& r1, int& c0, int& c1) {\n    if (!c.valid) return false;\n    bool first = true;\n    for (int r = 0; r < c.H; r++) {\n        for (int cc = 0; cc < c.W; cc++) if (c.sel[r * c.W + cc]) {\n            if (first) {\n                r0 = r1 = r;\n                c0 = c1 = cc;\n                first = false;\n            } else {\n                r0 = min(r0, r);\n                r1 = max(r1, r);\n                c0 = min(c0, cc);\n                c1 = max(c1, cc);\n            }\n        }\n    }\n    return !first;\n}\n\nCandidate refine_to_finer_grid(const Candidate& coarse, const vector<Point>& mac, const vector<Point>& sar) {\n    Candidate bad;\n    if (!coarse.valid) return bad;\n    if (coarse.D < 1600) return bad;\n\n    int D2 = coarse.D / 2;\n    if (D2 < 800) return bad;\n\n    int r0, r1, c0, c1;\n    if (!bbox_of_selection(coarse, r0, r1, c0, c1)) return bad;\n\n    // coarse cell coordinates\n    int cgx0 = coarse.ox + c0;\n    int cgx1 = coarse.ox + c1;\n    int cgy0 = coarse.oy + r0;\n    int cgy1 = coarse.oy + r1;\n\n    int pad = 2;\n    int fgx0 = max(0, (cgx0 - pad) * 2);\n    int fgx1 = min(100000 / D2, (cgx1 + 1 + pad) * 2 - 1);\n    int fgy0 = max(0, (cgy0 - pad) * 2);\n    int fgy1 = min(100000 / D2, (cgy1 + 1 + pad) * 2 - 1);\n\n    GridData fine = build_grid_subregion(mac, sar, D2, fgx0, fgx1, fgy0, fgy1);\n\n    vector<unsigned char> init(fine.H * fine.W, 0);\n\n    for (int fr = 0; fr < fine.H; fr++) {\n        for (int fc = 0; fc < fine.W; fc++) {\n            int fgx = fine.ox + fc;\n            int fgy = fine.oy + fr;\n            int x = fgx * D2 + D2 / 2;\n            int y = fgy * D2 + D2 / 2;\n            int cgx = x / coarse.D;\n            int cgy = y / coarse.D;\n            int cc = cgx - coarse.ox;\n            int cr = cgy - coarse.oy;\n            if (0 <= cr && cr < coarse.H && 0 <= cc && cc < coarse.W) {\n                if (coarse.sel[cr * coarse.W + cc]) init[fr * fine.W + fc] = 1;\n            }\n        }\n    }\n\n    Candidate c;\n    c.H = fine.H;\n    c.W = fine.W;\n    c.ox = fine.ox;\n    c.oy = fine.oy;\n    c.D = fine.D;\n    c.sel = move(init);\n    c.score = compute_score(c.sel, fine);\n    c.valid = true;\n\n    local_improve(c, fine, 50);\n    morph_cleanup(c, fine, 3);\n    local_improve(c, fine, 50);\n\n    if (!finalize_candidate(c, fine)) return bad;\n    return c;\n}\n\nvector<pair<int,int>> fallback_polygon() {\n    return {{0,0}, {1,0}, {1,1}, {0,1}};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<Point> mac(N), sar(N);\n    for (int i = 0; i < N; i++) cin >> mac[i].x >> mac[i].y;\n    for (int i = 0; i < N; i++) cin >> sar[i].x >> sar[i].y;\n\n    vector<int> Ds = {1000, 1200, 1600, 2000, 2500, 3200};\n\n    Candidate best;\n\n    auto improve_and_consider = [&](Candidate c, const GridData& g, bool try_fine) {\n        if (!c.valid) return;\n        local_improve(c, g, 50);\n        morph_cleanup(c, g, 3);\n        local_improve(c, g, 50);\n        if (!finalize_candidate(c, g)) return;\n\n        if (c.score > best.score) best = c;\n\n        if (try_fine) {\n            Candidate f = refine_to_finer_grid(c, mac, sar);\n            if (f.valid && f.score > best.score) best = move(f);\n        }\n    };\n\n    for (int D : Ds) {\n        GridData g = build_grid(mac, sar, D);\n        vector<Candidate> elite_raw;\n\n        auto push_elite = [&](Candidate c) {\n            if (c.valid) elite_raw.push_back(move(c));\n        };\n\n        push_elite(candidate_from_rectangle(g));\n        push_elite(candidate_from_threshold(g, 2));\n        push_elite(candidate_from_threshold(g, 1));\n        for (double pen : {1.5, 2.0, 2.5, 3.0, 4.0}) {\n            push_elite(candidate_from_greedy(g, pen, 18));\n        }\n\n        sort(elite_raw.begin(), elite_raw.end(), [&](const Candidate& a, const Candidate& b) {\n            return a.score > b.score;\n        });\n\n        for (int i = 0; i < (int)elite_raw.size(); i++) {\n            bool try_fine = (i < 2); // refine only top few\n            improve_and_consider(elite_raw[i], g, try_fine);\n        }\n\n        if ((int)elite_raw.size() > 6) elite_raw.resize(6);\n\n        for (int i = 0; i < (int)elite_raw.size(); i++) {\n            for (int j = i + 1; j < (int)elite_raw.size(); j++) {\n                Candidate merged = merge_two_candidates(elite_raw[i], elite_raw[j], g);\n                improve_and_consider(merged, g, false);\n            }\n        }\n    }\n\n    vector<pair<int,int>> out = best.valid ? best.poly : fallback_polygon();\n\n    if ((int)out.size() < 4 || (int)out.size() > 1000) out = fallback_polygon();\n    {\n        set<pair<int,int>> st(out.begin(), out.end());\n        if ((int)st.size() != (int)out.size()) out = fallback_polygon();\n    }\n    for (auto &p : out) {\n        p.first = max(0, min(100000, p.first));\n        p.second = max(0, min(100000, p.second));\n    }\n\n    cout << out.size() << '\\n';\n    for (auto &p : out) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Rect {\n    int w, h;\n};\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct Candidate {\n    vector<Op> ops;\n    ll estW = 0, estH = 0, estScore = (1LL << 60);\n    int family = 0; // 0=columns, 1=rows\n    int mode = 0;\n    int k = 1;\n    int usedN = 0;\n    string tag;\n};\n\nstruct Solver {\n    int N, T, sigma;\n    vector<Rect> a;\n    vector<Candidate> pool;\n    static constexpr int MODES = 5;\n    mt19937 rng{123456789};\n\n    struct Dims {\n        int rot, w, h;\n    };\n    Dims dims[MODES][2][105];\n\n    vector<ll> suffixPenalty;\n\n    void precompute_dims() {\n        for (int mode = 0; mode < MODES; mode++) {\n            for (int i = 0; i < N; i++) {\n                for (int fc = 0; fc < 2; fc++) {\n                    bool forColumn = (fc == 1);\n                    int w = a[i].w, h = a[i].h;\n                    int rot = 0, ww = w, hh = h;\n\n                    auto apply_rot = [&](bool flag) {\n                        if (flag) {\n                            rot = 1;\n                            ww = h;\n                            hh = w;\n                        }\n                    };\n\n                    if (mode == 0) {\n                        if (forColumn) apply_rot(w > h);\n                        else apply_rot(h > w);\n                    } else if (mode == 1) {\n                    } else if (mode == 2) {\n                        if (forColumn) apply_rot(w < h);\n                        else apply_rot(h < w);\n                    } else if (mode == 3) {\n                        if (forColumn) apply_rot(h < w);\n                        else apply_rot(w < h);\n                    } else {\n                        if (forColumn) apply_rot(h > w);\n                        else apply_rot(w > h);\n                    }\n\n                    dims[mode][fc][i] = {rot, ww, hh};\n                }\n            }\n        }\n    }\n\n    void precompute_penalty() {\n        suffixPenalty.assign(N + 1, 0);\n        for (int i = N - 1; i >= 0; i--) {\n            suffixPenalty[i] = suffixPenalty[i + 1] + a[i].w + a[i].h;\n        }\n    }\n\n    struct GroupScore {\n        ll major = 0;\n        ll minor = 0;\n    };\n\n    GroupScore eval_group(int l, int r, int mode, bool forColumn) {\n        GroupScore gs;\n        if (!(0 <= l && l < r && r <= N)) return gs;\n        int fc = forColumn ? 1 : 0;\n        if (forColumn) {\n            ll mxw = 0, sumh = 0;\n            for (int i = l; i < r; i++) {\n                mxw = max<ll>(mxw, dims[mode][fc][i].w);\n                sumh += dims[mode][fc][i].h;\n            }\n            gs.major = mxw;\n            gs.minor = sumh;\n        } else {\n            ll sumw = 0, mxh = 0;\n            for (int i = l; i < r; i++) {\n                sumw += dims[mode][fc][i].w;\n                mxh = max<ll>(mxh, dims[mode][fc][i].h);\n            }\n            gs.major = sumw;\n            gs.minor = mxh;\n        }\n        return gs;\n    }\n\n    bool valid_groups(const vector<pair<int,int>>& groups, int usedN) {\n        if (usedN < 0 || usedN > N) return false;\n        if (usedN == 0) return groups.empty();\n        if (groups.empty()) return false;\n        if (groups.front().first != 0) return false;\n        if (groups.back().second != usedN) return false;\n        for (int i = 0; i < (int)groups.size(); i++) {\n            auto [l, r] = groups[i];\n            if (!(0 <= l && l < r && r <= usedN)) return false;\n            if (i > 0 && groups[i - 1].second != l) return false;\n        }\n        return true;\n    }\n\n    ll eval_partition(const vector<pair<int,int>>& groups, int usedN, int mode, bool forColumn, ll &outW, ll &outH) {\n        if (!valid_groups(groups, usedN)) {\n            outW = outH = (ll)4e18;\n            return (ll)4e18;\n        }\n\n        if (usedN == 0) {\n            outW = outH = 0;\n            return suffixPenalty[0];\n        }\n\n        if (forColumn) {\n            ll totalW = 0, totalH = 0;\n            for (auto [l, r] : groups) {\n                auto gs = eval_group(l, r, mode, true);\n                totalW += gs.major;\n                totalH = max(totalH, gs.minor);\n            }\n            outW = totalW;\n            outH = totalH;\n        } else {\n            ll totalW = 0, totalH = 0;\n            for (auto [l, r] : groups) {\n                auto gs = eval_group(l, r, mode, false);\n                totalW = max(totalW, gs.major);\n                totalH += gs.minor;\n            }\n            outW = totalW;\n            outH = totalH;\n        }\n        return outW + outH + suffixPenalty[usedN];\n    }\n\n    vector<pair<int,int>> groups_equal(int k, int usedN) {\n        vector<pair<int,int>> groups;\n        if (usedN == 0) return groups;\n        k = min(k, usedN);\n        int l = 0;\n        for (int g = 0; g < k; g++) {\n            int r = (ll)usedN * (g + 1) / k;\n            if (r <= l) r = l + 1;\n            if (g == k - 1) r = usedN;\n            groups.push_back({l, r});\n            l = r;\n        }\n        groups.back().second = usedN;\n        return groups;\n    }\n\n    vector<pair<int,int>> groups_balanced_sum(int k, int usedN, int mode, bool forColumn) {\n        vector<pair<int,int>> groups;\n        if (usedN == 0) return groups;\n        k = min(k, usedN);\n\n        vector<ll> weight(usedN);\n        int fc = forColumn ? 1 : 0;\n        for (int i = 0; i < usedN; i++) {\n            weight[i] = forColumn ? dims[mode][fc][i].h : dims[mode][fc][i].w;\n        }\n\n        ll total = 0;\n        for (ll x : weight) total += x;\n\n        int l = 0, p = 0;\n        ll pref = 0;\n        for (int g = 1; g < k; g++) {\n            ll target = total * g / k;\n            while (p < usedN - (k - g) && pref + weight[p] <= target) {\n                pref += weight[p];\n                p++;\n            }\n            int r = max(l + 1, p);\n            groups.push_back({l, r});\n            l = r;\n        }\n        groups.push_back({l, usedN});\n        if (!valid_groups(groups, usedN)) return groups_equal(k, usedN);\n        return groups;\n    }\n\n    vector<pair<int,int>> groups_balanced_target(int k, int usedN, int mode, bool forColumn) {\n        vector<pair<int,int>> groups;\n        if (usedN == 0) return groups;\n        k = min(k, usedN);\n\n        int fc = forColumn ? 1 : 0;\n        ll totalStack = 0;\n        for (int i = 0; i < usedN; i++) {\n            totalStack += forColumn ? dims[mode][fc][i].h : dims[mode][fc][i].w;\n        }\n\n        ll target = max<ll>(1, totalStack / k);\n        int l = 0;\n        ll cur = 0;\n        for (int i = 0; i < usedN; i++) {\n            cur += forColumn ? dims[mode][fc][i].h : dims[mode][fc][i].w;\n            int remainRects = usedN - (i + 1);\n            int remainGroups = k - (int)groups.size() - 1;\n            bool canCut = remainGroups > 0 && remainRects >= remainGroups;\n            if (canCut && cur >= target) {\n                groups.push_back({l, i + 1});\n                l = i + 1;\n                cur = 0;\n            }\n        }\n        groups.push_back({l, usedN});\n        if (!valid_groups(groups, usedN)) return groups_equal(k, usedN);\n        return groups;\n    }\n\n    void local_improve(vector<pair<int,int>>& groups, int usedN, int mode, bool forColumn) {\n        if ((int)groups.size() <= 1 || !valid_groups(groups, usedN)) return;\n\n        ll curW, curH;\n        ll curScore = eval_partition(groups, usedN, mode, forColumn, curW, curH);\n\n        bool improved = true;\n        int iter = 35;\n        while (improved && iter--) {\n            improved = false;\n            for (int i = 0; i + 1 < (int)groups.size(); i++) {\n                int l1 = groups[i].first, r1 = groups[i].second;\n                int r2 = groups[i + 1].second;\n                int bd = r1;\n\n                int bestBd = bd;\n                ll bestScore = curScore;\n                ll bestBalance = llabs(curW - curH);\n\n                int L = max(l1 + 1, bd - 2);\n                int R = min(r2 - 1, bd + 2);\n                for (int nb = L; nb <= R; nb++) {\n                    if (nb == bd) continue;\n                    auto ng = groups;\n                    ng[i] = {l1, nb};\n                    ng[i + 1] = {nb, r2};\n                    if (!valid_groups(ng, usedN)) continue;\n                    ll w, h;\n                    ll sc = eval_partition(ng, usedN, mode, forColumn, w, h);\n                    ll bal = llabs(w - h);\n                    if (sc < bestScore || (sc == bestScore && bal < bestBalance)) {\n                        bestScore = sc;\n                        bestBalance = bal;\n                        bestBd = nb;\n                    }\n                }\n\n                if (bestBd != bd) {\n                    groups[i].second = bestBd;\n                    groups[i + 1].first = bestBd;\n                    curScore = bestScore;\n                    ll w, h;\n                    eval_partition(groups, usedN, mode, forColumn, w, h);\n                    curW = w;\n                    curH = h;\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    Candidate build_candidate(const vector<pair<int,int>>& groups, int usedN, int mode, bool forColumn, const string& tag) {\n        Candidate c;\n        c.family = forColumn ? 0 : 1;\n        c.mode = mode;\n        c.k = (int)groups.size();\n        c.usedN = usedN;\n        c.tag = tag;\n\n        ll W, H;\n        c.estScore = eval_partition(groups, usedN, mode, forColumn, W, H);\n        c.estW = W;\n        c.estH = H;\n\n        vector<int> firsts;\n        int fc = forColumn ? 1 : 0;\n        for (int g = 0; g < (int)groups.size(); g++) {\n            auto [l, r] = groups[g];\n            int first = l;\n            firsts.push_back(first);\n            for (int i = l; i < r; i++) {\n                int rot = dims[mode][fc][i].rot;\n                int b = (i == l ? (g == 0 ? -1 : firsts[g - 1]) : first);\n                c.ops.push_back({i, rot, forColumn ? 'U' : 'L', b});\n            }\n        }\n\n        int prevp = -1;\n        for (auto &op : c.ops) {\n            if (!(0 <= op.p && op.p < usedN)) {\n                c.ops.clear();\n                break;\n            }\n            if (!(op.p > prevp)) {\n                c.ops.clear();\n                break;\n            }\n            if (!(op.b == -1 || (0 <= op.b && op.b < op.p))) {\n                c.ops.clear();\n                break;\n            }\n            prevp = op.p;\n        }\n        if (c.ops.empty() && usedN > 0) {\n            for (int i = 0; i < usedN; i++) c.ops.push_back({i, 0, 'U', -1});\n        }\n\n        return c;\n    }\n\n    void try_add(vector<pair<int,int>> groups, int usedN, int mode, bool forColumn, const string& prefix) {\n        if (!valid_groups(groups, usedN)) return;\n        local_improve(groups, usedN, mode, forColumn);\n        if (!valid_groups(groups, usedN)) return;\n        pool.push_back(build_candidate(\n            groups, usedN, mode, forColumn,\n            prefix + \"_u\" + to_string(usedN) + \"_k\" + to_string((int)groups.size()) + \"_m\" + to_string(mode)\n        ));\n    }\n\n    vector<pair<int,int>> ops_to_groups(const Candidate& c) {\n        vector<pair<int,int>> groups;\n        if (c.usedN == 0) return groups;\n        int start = 0;\n        for (int i = 0; i < (int)c.ops.size(); i++) {\n            if (i == 0) continue;\n            if (c.ops[i].b != c.ops[i-1].b && c.ops[i].p == c.ops[i-1].p + 1) {\n                // not reliable\n            }\n        }\n        // Since our construction outputs groups as contiguous runs,\n        // each group starts where b is -1 or previous group's first index.\n        // Easier: detect first element of each group by \"i==l\" => b = -1 or previous group's first.\n        vector<int> starts;\n        for (auto &op : c.ops) {\n            if (op.b == -1 || op.b != c.ops[max(0, (int)starts.size() ? starts.back() : 0)].p) {\n                // This heuristic is awkward; instead use property:\n                // within group, non-first ops have b = first index of that same group,\n                // so first op of a group is exactly when b != current group's first.\n            }\n        }\n\n        // robust recovery using op sequence:\n        int i = 0;\n        while (i < (int)c.ops.size()) {\n            int l = c.ops[i].p;\n            int first = l;\n            int j = i + 1;\n            while (j < (int)c.ops.size() && c.ops[j].b == first) j++;\n            groups.push_back({l, (j < (int)c.ops.size() ? c.ops[j].p : c.usedN)});\n            i = j;\n        }\n\n        if (!valid_groups(groups, c.usedN)) {\n            groups.clear();\n            groups.push_back({0, c.usedN});\n        }\n        return groups;\n    }\n\n    void add_mutations() {\n        if (pool.empty()) return;\n\n        int baseCount = min<int>((int)pool.size(), 20);\n        int mutsPerBase = 4;\n\n        vector<Candidate> extra;\n        for (int bi = 0; bi < baseCount; bi++) {\n            const Candidate &base = pool[bi];\n            if (base.usedN <= 1 || base.k <= 1) continue;\n\n            auto groups0 = ops_to_groups(base);\n            if (!valid_groups(groups0, base.usedN)) continue;\n\n            for (int rep = 0; rep < mutsPerBase; rep++) {\n                auto groups = groups0;\n\n                int steps = uniform_int_distribution<int>(1, min(4, (int)groups.size() - 1))(rng);\n                for (int s = 0; s < steps; s++) {\n                    int i = uniform_int_distribution<int>(0, (int)groups.size() - 2)(rng);\n                    int l1 = groups[i].first, r1 = groups[i].second;\n                    int r2 = groups[i + 1].second;\n                    int bd = r1;\n\n                    int L = max(l1 + 1, bd - 3);\n                    int R = min(r2 - 1, bd + 3);\n                    if (L > R) continue;\n                    int nb = uniform_int_distribution<int>(L, R)(rng);\n                    groups[i].second = nb;\n                    groups[i + 1].first = nb;\n                }\n\n                if (!valid_groups(groups, base.usedN)) continue;\n                local_improve(groups, base.usedN, base.mode, base.family == 0);\n                if (!valid_groups(groups, base.usedN)) continue;\n\n                extra.push_back(build_candidate(\n                    groups, base.usedN, base.mode, base.family == 0,\n                    \"mut_\" + base.tag + \"_r\" + to_string(rep)\n                ));\n            }\n        }\n\n        for (auto &c : extra) pool.push_back(c);\n    }\n\n    void build_pool() {\n        pool.clear();\n        precompute_dims();\n        precompute_penalty();\n\n        int K = min(N, 16);\n\n        vector<int> usedList = {N};\n        if (N >= 40) {\n            usedList.push_back(max(1, N * 95 / 100));\n            usedList.push_back(max(1, N * 90 / 100));\n            usedList.push_back(max(1, N * 85 / 100));\n        } else {\n            usedList.push_back(max(1, N - 2));\n            usedList.push_back(max(1, N - 4));\n        }\n\n        sort(usedList.begin(), usedList.end());\n        usedList.erase(unique(usedList.begin(), usedList.end()), usedList.end());\n\n        for (int usedN : usedList) {\n            int curK = min(K, usedN);\n            for (int mode = 0; mode < MODES; mode++) {\n                for (int k = 1; k <= curK; k++) {\n                    try_add(groups_equal(k, usedN), usedN, mode, true,  \"col_eq\");\n                    try_add(groups_equal(k, usedN), usedN, mode, false, \"row_eq\");\n\n                    if (k >= 2) {\n                        try_add(groups_balanced_sum(k, usedN, mode, true),  usedN, mode, true,  \"col_bsum\");\n                        try_add(groups_balanced_sum(k, usedN, mode, false), usedN, mode, false, \"row_bsum\");\n                        try_add(groups_balanced_target(k, usedN, mode, true),  usedN, mode, true,  \"col_btgt\");\n                        try_add(groups_balanced_target(k, usedN, mode, false), usedN, mode, false, \"row_btgt\");\n                    }\n                }\n            }\n        }\n\n        unordered_set<string> seen;\n        vector<Candidate> uniq;\n        uniq.reserve(pool.size());\n\n        for (auto &c : pool) {\n            string key;\n            key.reserve(c.ops.size() * 12 + 20);\n            key += \"u\";\n            key += to_string(c.usedN);\n            key += \";\";\n            for (auto &op : c.ops) {\n                key += to_string(op.p);\n                key += ',';\n                key += char('0' + op.r);\n                key += ',';\n                key += op.d;\n                key += ',';\n                key += to_string(op.b);\n                key += ';';\n            }\n            if (seen.insert(key).second) uniq.push_back(c);\n        }\n        pool.swap(uniq);\n\n        sort(pool.begin(), pool.end(), [&](const Candidate& x, const Candidate& y) {\n            if (x.estScore != y.estScore) return x.estScore < y.estScore;\n            ll bx = llabs(x.estW - x.estH), by = llabs(y.estW - y.estH);\n            if (bx != by) return bx < by;\n            if (x.usedN != y.usedN) return x.usedN > y.usedN;\n            if (x.family != y.family) return x.family < y.family;\n            if (x.k != y.k) return x.k < y.k;\n            return x.mode < y.mode;\n        });\n\n        add_mutations();\n\n        seen.clear();\n        uniq.clear();\n        for (auto &c : pool) {\n            string key;\n            key.reserve(c.ops.size() * 12 + 20);\n            key += \"u\";\n            key += to_string(c.usedN);\n            key += \";\";\n            for (auto &op : c.ops) {\n                key += to_string(op.p);\n                key += ',';\n                key += char('0' + op.r);\n                key += ',';\n                key += op.d;\n                key += ',';\n                key += to_string(op.b);\n                key += ';';\n            }\n            if (seen.insert(key).second) uniq.push_back(c);\n        }\n        pool.swap(uniq);\n\n        sort(pool.begin(), pool.end(), [&](const Candidate& x, const Candidate& y) {\n            if (x.estScore != y.estScore) return x.estScore < y.estScore;\n            ll bx = llabs(x.estW - x.estH), by = llabs(y.estW - y.estH);\n            if (bx != by) return bx < by;\n            if (x.usedN != y.usedN) return x.usedN > y.usedN;\n            if (x.family != y.family) return x.family < y.family;\n            if (x.k != y.k) return x.k < y.k;\n            return x.mode < y.mode;\n        });\n\n        if (pool.empty()) {\n            Candidate c;\n            c.tag = \"fallback\";\n            c.usedN = N;\n            for (int i = 0; i < N; i++) c.ops.push_back({i, 0, 'U', -1});\n            pool.push_back(c);\n        }\n    }\n\n    void print_candidate(const Candidate& c) {\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n    }\n\n    void solve() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> T >> sigma;\n        a.resize(N);\n        for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n        build_pool();\n\n        vector<int> order;\n        set<tuple<int,int,int>> usedKey;\n        for (int i = 0; i < (int)pool.size(); i++) {\n            auto key = make_tuple(pool[i].family, pool[i].k, pool[i].usedN);\n            if (!usedKey.count(key)) {\n                usedKey.insert(key);\n                order.push_back(i);\n            }\n            if ((int)order.size() >= min(T, 28)) break;\n        }\n        for (int i = 0; i < (int)pool.size() && (int)order.size() < min(T, 80); i++) {\n            bool exists = false;\n            for (int x : order) if (x == i) { exists = true; break; }\n            if (!exists) order.push_back(i);\n        }\n\n        ll bestMeasured = (1LL << 60);\n        int bestIdx = 0;\n\n        for (int t = 0; t < T; t++) {\n            int idx;\n            if (t < (int)order.size()) {\n                idx = order[t];\n            } else {\n                const Candidate &bc = pool[bestIdx];\n                vector<int> near;\n                near.reserve(96);\n                for (int i = 0; i < (int)pool.size(); i++) {\n                    const Candidate &x = pool[i];\n                    if (x.usedN == bc.usedN && x.family == bc.family && abs(x.k - bc.k) <= 2) near.push_back(i);\n                    else if (x.usedN == bc.usedN && x.mode == bc.mode && abs(x.k - bc.k) <= 1) near.push_back(i);\n                    else if (x.family == bc.family && x.k == bc.k && abs(x.usedN - bc.usedN) <= 4) near.push_back(i);\n                }\n                if (near.empty()) idx = bestIdx;\n                else idx = near[(t - (int)order.size()) % near.size()];\n            }\n\n            cout << \"# \" << pool[idx].tag\n                 << \" est=\" << pool[idx].estW << \"+\" << pool[idx].estH\n                 << \"+\" << suffixPenalty[pool[idx].usedN]\n                 << \"=\" << pool[idx].estScore << \"\\n\";\n            print_candidate(pool[idx]);\n\n            ll Wm, Hm;\n            cin >> Wm >> Hm;\n            ll sm = Wm + Hm + suffixPenalty[pool[idx].usedN];\n            if (sm < bestMeasured) {\n                bestMeasured = sm;\n                bestIdx = idx;\n            }\n        }\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Candidate {\n    int depth;   // target depth\n    int beauty;\n    int parent;\n    int v;\n    bool operator<(const Candidate& other) const {\n        if (depth != other.depth) return depth < other.depth;      // max depth first\n        if (beauty != other.beauty) return beauty < other.beauty;  // then large beauty\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, H;\n    cin >> N >> M >> H;\n    vector<int> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<pair<int,int>> edges(M);\n    vector<vector<int>> g(N);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n\n    vector<pair<int,int>> coord(N);\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        coord[i] = {x, y};\n    }\n\n    // -------- Initial construction --------\n    // Idea:\n    // - small A vertices are better as roots / shallow scaffold\n    // - use a global candidate PQ that prefers deeper assignment and larger A\n    vector<int> parent(N, -2); // -2 = unassigned, -1 = root\n    vector<int> depth(N, -1);\n\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (A[a] != A[b]) return A[a] < A[b];\n        return a < b;\n    });\n\n    priority_queue<Candidate> pq;\n\n    auto add_frontier = [&](int u) {\n        if (depth[u] >= H) return;\n        for (int v : g[u]) {\n            if (parent[v] == -2) {\n                pq.push(Candidate{depth[u] + 1, A[v], u, v});\n            }\n        }\n    };\n\n    // Start from several low-beauty roots gradually.\n    int ptr = 0;\n    while (true) {\n        while (ptr < N && parent[ord[ptr]] != -2) ptr++;\n        if (ptr == N) break;\n\n        int r = ord[ptr];\n        parent[r] = -1;\n        depth[r] = 0;\n        add_frontier(r);\n\n        // Expand as much as possible with current frontier.\n        while (!pq.empty()) {\n            auto cur = pq.top();\n            pq.pop();\n            int v = cur.v, p = cur.parent;\n            if (parent[v] != -2) continue;\n            if (parent[p] == -2) continue;\n            if (depth[p] + 1 != cur.depth) continue;\n            if (cur.depth > H) continue;\n\n            parent[v] = p;\n            depth[v] = cur.depth;\n            add_frontier(v);\n\n            // If everything assigned, done.\n            // (No need to check here, outer loop handles it.)\n        }\n    }\n\n    // Safety fallback\n    for (int i = 0; i < N; i++) {\n        if (parent[i] == -2) {\n            parent[i] = -1;\n            depth[i] = 0;\n        }\n    }\n\n    // -------- Data structures for local improvement --------\n    vector<vector<int>> children(N);\n    vector<int> tin(N), tout(N), subSum(N), subHeight(N);\n    int timer = 0;\n\n    function<void()> rebuild = [&]() {\n        for (int i = 0; i < N; i++) children[i].clear();\n        for (int v = 0; v < N; v++) {\n            if (parent[v] >= 0) children[parent[v]].push_back(v);\n        }\n\n        queue<int> q;\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) {\n                depth[i] = 0;\n                q.push(i);\n            }\n        }\n        while (!q.empty()) {\n            int u = q.front(); q.pop();\n            for (int v : children[u]) {\n                depth[v] = depth[u] + 1;\n                q.push(v);\n            }\n        }\n\n        timer = 0;\n        function<void(int)> dfs = [&](int u) {\n            tin[u] = timer++;\n            subSum[u] = A[u];\n            subHeight[u] = 0;\n            for (int v : children[u]) {\n                dfs(v);\n                subSum[u] += subSum[v];\n                subHeight[u] = max(subHeight[u], subHeight[v] + 1);\n            }\n            tout[u] = timer;\n        };\n        for (int i = 0; i < N; i++) {\n            if (parent[i] == -1) dfs(i);\n        }\n    };\n\n    auto is_ancestor = [&](int a, int b) -> bool {\n        return tin[a] <= tin[b] && tout[b] <= tout[a];\n    };\n\n    rebuild();\n\n    auto score_est = [&]() -> long long {\n        long long s = 1;\n        for (int i = 0; i < N; i++) s += 1LL * (depth[i] + 1) * A[i];\n        return s;\n    };\n\n    // -------- Local improvement: subtree reparenting --------\n    // Move subtree v under neighboring u if gain positive and valid.\n    // Since H is small and N=1000, full rebuild after successful move is acceptable.\n    long long bestScore = score_est();\n\n    bool improved = true;\n    int rounds = 0;\n    while (improved && rounds < 30) {\n        improved = false;\n        rounds++;\n\n        // Try promising vertices first: larger subtree weight and larger A.\n        vector<int> vs(N);\n        iota(vs.begin(), vs.end(), 0);\n        sort(vs.begin(), vs.end(), [&](int a, int b) {\n            long long wa = 1LL * subSum[a] * 100 + A[a];\n            long long wb = 1LL * subSum[b] * 100 + A[b];\n            if (wa != wb) return wa > wb;\n            return a < b;\n        });\n\n        for (int v : vs) {\n            int bestParent = -3;\n            int bestNewDepth = depth[v];\n\n            for (int u : g[v]) {\n                if (u == parent[v]) continue;\n                // Cannot attach under own descendant.\n                if (is_ancestor(v, u)) continue;\n\n                int nd = depth[u] + 1;\n                if (nd <= depth[v]) continue; // only improving moves\n                if (nd + subHeight[v] > H) continue; // subtree must fit\n\n                if (nd > bestNewDepth) {\n                    bestNewDepth = nd;\n                    bestParent = u;\n                }\n            }\n\n            if (bestParent != -3) {\n                int oldParent = parent[v];\n                parent[v] = bestParent;\n                rebuild();\n                long long sc = score_est();\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    improved = true;\n                } else {\n                    // revert\n                    parent[v] = oldParent;\n                    rebuild();\n                }\n            }\n        }\n    }\n\n    // -------- Final validity repair (just in case) --------\n    // Ensure depth <= H and no invalid parent remains. If any issue, make root.\n    rebuild();\n    for (int i = 0; i < N; i++) {\n        if (depth[i] < 0 || depth[i] > H) {\n            parent[i] = -1;\n        }\n    }\n    rebuild();\n\n    // Output\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << parent[i];\n    }\n    cout << '\\n';\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int LIMIT = 4 * N * N; // 1600\nstatic constexpr int MAX_GREEDY_ITERS = 100;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nstruct Cand {\n    char d;\n    int p;\n    int k;\n    int removed;\n};\n\nstruct EvalCand {\n    char d;\n    int p;\n    int k;\n    int removed;\n    int newCost;\n    int gain;\n    bool valid = false;\n};\n\nstatic inline void apply_move(vector<string>& b, char d, int p) {\n    int n = (int)b.size();\n    if (d == 'L') {\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        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        for (int i = 0; i + 1 < n; ++i) b[i][p] = b[i + 1][p];\n        b[n - 1][p] = '.';\n    } else if (d == 'D') {\n        for (int i = n - 1; i >= 1; --i) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n}\n\nstatic inline int safe_limit(const vector<string>& b, char d, int p) {\n    int n = (int)b.size();\n    int safe = 0;\n    if (d == 'L') {\n        while (safe < n && b[p][safe] != 'o') ++safe;\n    } else if (d == 'R') {\n        while (safe < n && b[p][n - 1 - safe] != 'o') ++safe;\n    } else if (d == 'U') {\n        while (safe < n && b[safe][p] != 'o') ++safe;\n    } else { // D\n        while (safe < n && b[n - 1 - safe][p] != 'o') ++safe;\n    }\n    return safe;\n}\n\nstatic inline int fallback_cost_sum(const vector<string>& b) {\n    int n = (int)b.size();\n    int total = 0;\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (b[i][j] != 'x') continue;\n            int best = INT_MAX;\n\n            bool ok = true;\n            for (int r = 0; r < i; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (i + 1));\n\n            ok = true;\n            for (int r = i + 1; r < n; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (n - i));\n\n            ok = true;\n            for (int c = 0; c < j; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (j + 1));\n\n            ok = true;\n            for (int c = j + 1; c < n; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (n - j));\n\n            total += best;\n        }\n    }\n    return total;\n}\n\nstatic inline bool ratio_better(int rem1, int k1, int rem2, int k2) {\n    long long lhs = 1LL * rem1 * k2;\n    long long rhs = 1LL * rem2 * k1;\n    if (lhs != rhs) return lhs > rhs;\n    if (rem1 != rem2) return rem1 > rem2;\n    return k1 < k2;\n}\n\nstatic inline bool eval_better(const EvalCand& a, const EvalCand& b) {\n    if (!b.valid) return true;\n    if (a.gain != b.gain) return a.gain > b.gain;\n    if (a.k != b.k) return a.k < b.k;\n    if (a.removed != b.removed) return a.removed > b.removed;\n    if (a.d != b.d) return a.d < b.d;\n    return a.p < b.p;\n}\n\nstatic inline void add_candidate_unique(vector<Cand>& v, const Cand& c) {\n    for (auto &x : v) {\n        if (x.d == c.d && x.p == c.p && x.k == c.k) return;\n    }\n    v.push_back(c);\n}\n\nstatic inline bool find_best_fallback_action(\n    const vector<string>& b, int &oi, int &oj, char &od, int &olen\n) {\n    int n = (int)b.size();\n    int bestCost = INT_MAX;\n    bool found = false;\n\n    for (int i = 0; i < n; ++i) {\n        for (int j = 0; j < n; ++j) {\n            if (b[i][j] != 'x') continue;\n\n            int localBest = INT_MAX;\n            char localDir = '?';\n            int localLen = -1;\n\n            bool ok = true;\n            for (int r = 0; r < i; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int c = 2 * (i + 1);\n                if (c < localBest) localBest = c, localDir = 'U', localLen = i + 1;\n            }\n\n            ok = true;\n            for (int r = i + 1; r < n; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int c = 2 * (n - i);\n                if (c < localBest) localBest = c, localDir = 'D', localLen = n - i;\n            }\n\n            ok = true;\n            for (int c = 0; c < j; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int cst = 2 * (j + 1);\n                if (cst < localBest) localBest = cst, localDir = 'L', localLen = j + 1;\n            }\n\n            ok = true;\n            for (int c = j + 1; c < n; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int cst = 2 * (n - j);\n                if (cst < localBest) localBest = cst, localDir = 'R', localLen = n - j;\n            }\n\n            if (localBest < bestCost) {\n                bestCost = localBest;\n                oi = i; oj = j; od = localDir; olen = localLen;\n                found = true;\n            }\n        }\n    }\n    return found;\n}\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<Op> ans;\n    const char dirs[4] = {'L', 'R', 'U', 'D'};\n\n    for (int iter = 0; iter < MAX_GREEDY_ITERS; ++iter) {\n        int curCost = fallback_cost_sum(board);\n        int used = (int)ans.size();\n        if (used + curCost >= LIMIT) break;\n\n        vector<Cand> cands;\n        cands.reserve(256);\n\n        for (char d : dirs) {\n            for (int p = 0; p < n; ++p) {\n                int lim = safe_limit(board, d, p);\n                if (lim == 0) continue;\n\n                int removed = 0;\n\n                bool hasPos = false;\n                int bestRatioK = -1, bestRatioRem = -1;\n                int bestAbsK = -1, bestAbsRem = -1;\n                int firstPosK = -1, firstPosRem = -1;\n\n                for (int k = 1; k <= lim; ++k) {\n                    if (d == 'L') {\n                        if (board[p][k - 1] == 'x') ++removed;\n                    } else if (d == 'R') {\n                        if (board[p][n - k] == 'x') ++removed;\n                    } else if (d == 'U') {\n                        if (board[k - 1][p] == 'x') ++removed;\n                    } else { // D\n                        if (board[n - k][p] == 'x') ++removed;\n                    }\n\n                    if (removed <= 0) continue;\n\n                    if (!hasPos) {\n                        hasPos = true;\n                        firstPosK = k;\n                        firstPosRem = removed;\n                        bestRatioK = k;\n                        bestRatioRem = removed;\n                        bestAbsK = k;\n                        bestAbsRem = removed;\n                    } else {\n                        if (ratio_better(removed, k, bestRatioRem, bestRatioK)) {\n                            bestRatioK = k;\n                            bestRatioRem = removed;\n                        }\n                        if (removed > bestAbsRem || (removed == bestAbsRem && k < bestAbsK)) {\n                            bestAbsK = k;\n                            bestAbsRem = removed;\n                        }\n                    }\n                }\n\n                if (hasPos) {\n                    add_candidate_unique(cands, {d, p, firstPosK, firstPosRem});\n                    add_candidate_unique(cands, {d, p, bestRatioK, bestRatioRem});\n                    add_candidate_unique(cands, {d, p, bestAbsK, bestAbsRem});\n                }\n            }\n        }\n\n        EvalCand best;\n\n        for (const auto &cc : cands) {\n            if (used + cc.k > LIMIT) continue;\n\n            vector<string> tmp = board;\n            for (int t = 0; t < cc.k; ++t) apply_move(tmp, cc.d, cc.p);\n\n            int newCost = fallback_cost_sum(tmp);\n            if (used + cc.k + newCost > LIMIT) continue;\n\n            int gain = curCost - (cc.k + newCost);\n            EvalCand ec{cc.d, cc.p, cc.k, cc.removed, newCost, gain, gain > 0};\n            if (ec.valid && eval_better(ec, best)) best = ec;\n        }\n\n        if (!best.valid) break;\n\n        for (int t = 0; t < best.k; ++t) {\n            apply_move(board, best.d, best.p);\n            ans.push_back({best.d, best.p});\n        }\n    }\n\n    // Dynamic guaranteed fallback\n    while (true) {\n        int i, j, len;\n        char dir;\n        if (!find_best_fallback_action(board, i, j, dir, len)) break;\n        if ((int)ans.size() + 2 * len > LIMIT) break; // should not happen if invariant held\n\n        if (dir == 'U') {\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'U', j);\n                ans.push_back({'U', j});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'D', j);\n                ans.push_back({'D', j});\n            }\n        } else if (dir == 'D') {\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'D', j);\n                ans.push_back({'D', j});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'U', j);\n                ans.push_back({'U', j});\n            }\n        } else if (dir == 'L') {\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'L', i);\n                ans.push_back({'L', i});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'R', i);\n                ans.push_back({'R', i});\n            }\n        } else { // R\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'R', i);\n                ans.push_back({'R', i});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'L', i);\n                ans.push_back({'L', i});\n            }\n        }\n    }\n\n    for (auto &op : ans) {\n        cout << op.d << ' ' << op.p << '\\n';\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr long long INF64 = (1LL << 60);\n\nstruct Solution {\n    array<int, MAXN> a{}, b{};\n    long long err = INF64;\n};\n\nstruct Config {\n    int M = 0;\n    vector<int> order;            // special nodes in cycle order\n    vector<char> is_special;      // size N\n    vector<char> is_hub;          // size N, meaningful on special nodes\n    vector<int> attach;           // size N, for non-special x: attached special\n};\n\nint N, L;\narray<int, MAXN> T;\n\n// Fast exact evaluator using cycle decomposition on expanded state space:\n// state id = node * 2 + parity_before_visit\n// parity_before_visit = cnt[node] % 2 before this week's assignment.\nstatic long long evaluate_solution(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    const int S = 2 * N;\n\n    vector<int> seen(S, -1);\n    vector<int> seq_states;\n    seq_states.reserve(S + 5);\n\n    vector<array<int, MAXN>> pref; // cumulative counts after k steps\n    pref.reserve(S + 5);\n    array<int, MAXN> zero{};\n    pref.push_back(zero);\n\n    int cur_node = 0;\n    int cur_par = 0; // before visit to node 0, count is 0 => even parity 0\n    int step = 0;\n\n    while (true) {\n        int sid = cur_node * 2 + cur_par;\n        if (seen[sid] != -1) {\n            int mu = seen[sid];\n            int lambda = step - mu;\n\n            auto get_counts_range = [&](int l, int r) {\n                array<long long, MAXN> res{};\n                for (int i = 0; i < N; ++i) {\n                    res[i] = (long long)pref[r][i] - pref[l][i];\n                }\n                return res;\n            };\n\n            array<long long, MAXN> total{};\n            if (L <= mu) {\n                for (int i = 0; i < N; ++i) total[i] = pref[L][i];\n            } else {\n                for (int i = 0; i < N; ++i) total[i] = pref[mu][i];\n\n                auto cyc = get_counts_range(mu, mu + lambda);\n                long long rem = L - mu;\n                long long q = rem / lambda;\n                int r = (int)(rem % lambda);\n\n                for (int i = 0; i < N; ++i) {\n                    total[i] += cyc[i] * q;\n                    total[i] += (long long)pref[mu + r][i] - pref[mu][i];\n                }\n            }\n\n            long long err = 0;\n            for (int i = 0; i < N; ++i) err += llabs(total[i] - (long long)T[i]);\n            return err;\n        }\n\n        seen[sid] = step;\n        seq_states.push_back(sid);\n\n        // perform one week at cur_node\n        auto nxt_pref = pref.back();\n        nxt_pref[cur_node]++;\n        pref.push_back(nxt_pref);\n\n        int nxt_node = (cur_par == 0 ? a[cur_node] : b[cur_node]); // after visit count becomes odd if cur_par=0\n        int nxt_par = ((pref.back()[nxt_node]) & 1); // parity before next visit equals current count mod 2\n\n        // But pref.back()[nxt_node] is count after current step, exactly what we need.\n        cur_node = nxt_node;\n        cur_par = nxt_par;\n        step++;\n    }\n}\n\nstatic Solution build_solution_from_config(const Config& cfg) {\n    Solution sol;\n    for (int i = 0; i < N; ++i) {\n        sol.a[i] = i;\n        sol.b[i] = i;\n    }\n\n    vector<int> pos(N, -1);\n    for (int i = 0; i < cfg.M; ++i) pos[cfg.order[i]] = i;\n\n    // special cycle\n    for (int i = 0; i < cfg.M; ++i) {\n        int v = cfg.order[i];\n        int nxt = cfg.order[(i + 1) % cfg.M];\n        if (cfg.is_hub[v]) {\n            sol.a[v] = v;\n            sol.b[v] = nxt;\n        } else {\n            sol.a[v] = nxt;\n            sol.b[v] = nxt;\n        }\n    }\n\n    // non-special attachments\n    for (int x = 0; x < N; ++x) {\n        if (cfg.is_special[x]) continue;\n        int s = cfg.attach[x];\n        int p = pos[s];\n        int nxt = cfg.order[(p + 1) % cfg.M];\n        sol.a[x] = nxt;\n        sol.b[x] = nxt;\n    }\n\n    sol.err = evaluate_solution(sol.a, sol.b);\n    return sol;\n}\n\nstatic void update_best(Solution& best, const Solution& cand) {\n    if (cand.err < best.err) best = cand;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    auto st = chrono::high_resolution_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\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        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    Solution best;\n\n    // Fallback 1\n    {\n        array<int, MAXN> a{}, b{};\n        int mx = ord[0];\n        for (int i = 0; i < N; ++i) a[i] = b[i] = mx;\n        a[mx] = mx;\n        b[mx] = mx;\n        Solution s{a, b, evaluate_solution(a, b)};\n        update_best(best, s);\n    }\n\n    // Fallback 2\n    {\n        array<int, MAXN> a{}, b{};\n        for (int i = 0; i < N; ++i) {\n            int v = ord[i];\n            int nxt = ord[(i + 1) % N];\n            a[v] = v;\n            b[v] = nxt;\n        }\n        Solution s{a, b, evaluate_solution(a, b)};\n        update_best(best, s);\n    }\n\n    Config best_cfg;\n\n    vector<int> Ms = {8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 100};\n\n    for (int M : Ms) {\n        if (elapsed() > 1.20) break;\n        M = min(M, N);\n\n        vector<int> special(ord.begin(), ord.begin() + M);\n        vector<int> nonspecial(ord.begin() + M, ord.end());\n\n        vector<vector<int>> orders;\n\n        // descending\n        orders.push_back(special);\n\n        // ascending\n        {\n            auto v = special;\n            reverse(v.begin(), v.end());\n            orders.push_back(v);\n        }\n\n        // big-small alternating\n        {\n            vector<int> v;\n            int l = 0, r = M - 1;\n            while (l <= r) {\n                v.push_back(special[l++]);\n                if (l <= r) v.push_back(special[r--]);\n            }\n            orders.push_back(v);\n        }\n\n        // interleave halves\n        {\n            vector<int> v;\n            int mid = (M + 1) / 2;\n            for (int i = 0; i < mid; ++i) {\n                v.push_back(special[i]);\n                if (i + mid < M) v.push_back(special[i + mid]);\n            }\n            orders.push_back(v);\n        }\n\n        for (const auto& order : orders) {\n            if (elapsed() > 1.35) break;\n\n            vector<int> Hs = {\n                max(1, M / 4),\n                max(1, M / 3),\n                max(1, M / 2),\n                max(1, 2 * M / 3),\n                M\n            };\n            sort(Hs.begin(), Hs.end());\n            Hs.erase(unique(Hs.begin(), Hs.end()), Hs.end());\n\n            for (int H : Hs) {\n                // Several hub-selection schemes\n                for (int hub_mode = 0; hub_mode < 4; ++hub_mode) {\n                    Config cfg;\n                    cfg.M = M;\n                    cfg.order = order;\n                    cfg.is_special.assign(N, 0);\n                    cfg.is_hub.assign(N, 0);\n                    cfg.attach.assign(N, order[0]);\n\n                    for (int v : order) cfg.is_special[v] = 1;\n\n                    if (hub_mode == 0) {\n                        // first H in order\n                        for (int i = 0; i < H; ++i) cfg.is_hub[order[i]] = 1;\n                    } else if (hub_mode == 1) {\n                        // top H by target among special\n                        vector<int> tmp = order;\n                        sort(tmp.begin(), tmp.end(), [&](int x, int y) {\n                            if (T[x] != T[y]) return T[x] > T[y];\n                            return x < y;\n                        });\n                        for (int i = 0; i < H; ++i) cfg.is_hub[tmp[i]] = 1;\n                    } else if (hub_mode == 2) {\n                        // alternating in order\n                        int cnt = 0;\n                        for (int i = 0; i < M && cnt < H; i += 2, ++cnt) cfg.is_hub[order[i]] = 1;\n                        for (int i = 1; i < M && cnt < H; i += 2, ++cnt) cfg.is_hub[order[i]] = 1;\n                    } else {\n                        // every kth style\n                        int stepk = max(1, M / H);\n                        int cnt = 0;\n                        vector<char> used(N, 0);\n                        for (int start = 0; cnt < H && start < stepk; ++start) {\n                            for (int i = start; i < M && cnt < H; i += stepk) {\n                                int v = order[i];\n                                if (!used[v]) {\n                                    used[v] = 1;\n                                    cfg.is_hub[v] = 1;\n                                    cnt++;\n                                }\n                            }\n                        }\n                    }\n\n                    // Attach non-special nodes greedily to special nodes\n                    vector<long long> load(N, 0);\n                    for (int v : order) load[v] = T[v];\n\n                    vector<int> rem = nonspecial;\n                    sort(rem.begin(), rem.end(), [&](int x, int y) {\n                        if (T[x] != T[y]) return T[x] > T[y];\n                        return x < y;\n                    });\n\n                    for (int x : rem) {\n                        int best_s = order[0];\n                        long long best_score = INF64;\n                        for (int s : order) {\n                            // Hub specials are more \"powerful\", so slightly less penalty.\n                            long long score = load[s] + (cfg.is_hub[s] ? 0LL : 300LL);\n                            if (score < best_score) {\n                                best_score = score;\n                                best_s = s;\n                            }\n                        }\n                        cfg.attach[x] = best_s;\n                        load[best_s] += T[x];\n                    }\n\n                    Solution cand = build_solution_from_config(cfg);\n                    if (cand.err < best.err) {\n                        best = cand;\n                        best_cfg = cfg;\n                    }\n                }\n            }\n        }\n    }\n\n    // Small local refinement on the best config\n    if (best_cfg.M > 0) {\n        Config cur = best_cfg;\n        Solution cur_sol = build_solution_from_config(cur);\n\n        uint64_t rng_state = chrono::high_resolution_clock::now().time_since_epoch().count();\n        auto rng64 = [&]() -> uint64_t {\n            rng_state ^= rng_state << 7;\n            rng_state ^= rng_state >> 9;\n            return rng_state;\n        };\n        auto rnd = [&](int l, int r) -> int {\n            return l + (int)(rng64() % (uint64_t)(r - l + 1));\n        };\n\n        while (elapsed() < 1.95) {\n            Config nxt = cur;\n            int op = rnd(0, 2);\n\n            if (op == 0 && nxt.M >= 2) {\n                // swap adjacent/random positions\n                int i = rnd(0, nxt.M - 1);\n                int j = (rng64() & 1) ? (i + 1) % nxt.M : rnd(0, nxt.M - 1);\n                if (i != j) swap(nxt.order[i], nxt.order[j]);\n            } else if (op == 1) {\n                // flip hub status of one special\n                int i = rnd(0, nxt.M - 1);\n                int v = nxt.order[i];\n                nxt.is_hub[v] ^= 1;\n                bool any_hub = false;\n                for (int x : nxt.order) if (nxt.is_hub[x]) any_hub = true;\n                if (!any_hub) nxt.is_hub[v] = 1;\n            } else {\n                // reattach one non-special node\n                vector<int> nonsp;\n                for (int x = 0; x < N; ++x) if (!nxt.is_special[x]) nonsp.push_back(x);\n                if (!nonsp.empty()) {\n                    int x = nonsp[rnd(0, (int)nonsp.size() - 1)];\n                    int s = nxt.order[rnd(0, nxt.M - 1)];\n                    nxt.attach[x] = s;\n                }\n            }\n\n            Solution ns = build_solution_from_config(nxt);\n            if (ns.err < cur_sol.err) {\n                cur = nxt;\n                cur_sol = ns;\n                if (ns.err < best.err) {\n                    best = ns;\n                    best_cfg = nxt;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline long long part1by1(unsigned x) {\n    unsigned long long n = x;\n    n = (n | (n << 16)) & 0x0000FFFF0000FFFFULL;\n    n = (n | (n << 8)) & 0x00FF00FF00FF00FFULL;\n    n = (n | (n << 4)) & 0x0F0F0F0F0F0F0F0FULL;\n    n = (n | (n << 2)) & 0x3333333333333333ULL;\n    n = (n | (n << 1)) & 0x5555555555555555ULL;\n    return (long long)n;\n}\nstatic inline long long morton_key(int x, int y) {\n    return (part1by1((unsigned)x) << 1) | part1by1((unsigned)y);\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n) { 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) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (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, 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\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 main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n    XorShift rng;\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\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), cx(N), cy(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    auto center_dist = [&](int a, int b) -> int {\n        long long dx = 1LL * cx[a] - cx[b];\n        long long dy = 1LL * cy[a] - cy[b];\n        return (int)floor(sqrt((double)(dx * dx + dy * dy)));\n    };\n    auto rect_gap_dist = [&](int a, int b) -> int {\n        int dx = 0, dy = 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        if (ry[a] < ly[b]) dy = ly[b] - ry[a];\n        else if (ry[b] < ly[a]) dy = ly[a] - ry[b];\n        return (int)floor(sqrt((double)(1LL * dx * dx + 1LL * dy * dy)));\n    };\n    auto est_dist = [&](int a, int b) -> int {\n        int dc = center_dist(a, b);\n        int dg = rect_gap_dist(a, b);\n        return (3 * dc + 2 * dg) / 5;\n    };\n\n    auto mst_cost_plain = [&](const vector<int>& vs) -> long long {\n        int n = (int)vs.size();\n        if (n <= 1) return 0;\n        const int INF = 1e9;\n        vector<int> best(n, INF);\n        vector<char> used(n, 0);\n        best[0] = 0;\n        long long res = 0;\n        for (int it = 0; it < n; it++) {\n            int v = -1;\n            for (int i = 0; i < n; i++) if (!used[i]) {\n                if (v == -1 || best[i] < best[v]) v = i;\n            }\n            used[v] = 1;\n            res += best[v];\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                int w = est_dist(vs[v], vs[j]);\n                if (w < best[j]) best[j] = w;\n            }\n        }\n        return res;\n    };\n\n    auto partition_by_order = [&](const vector<int>& ord) -> vector<vector<int>> {\n        vector<vector<int>> groups(M);\n        int ptr = 0;\n        for (int i = 0; i < M; i++) {\n            groups[i].assign(ord.begin() + ptr, ord.begin() + ptr + G[i]);\n            ptr += G[i];\n        }\n        return groups;\n    };\n\n    auto total_cost_plain = [&](const vector<vector<int>>& groups) -> long long {\n        long long sum = 0;\n        for (auto &g : groups) sum += mst_cost_plain(g);\n        return sum;\n    };\n\n    vector<int> all(N);\n    iota(all.begin(), all.end(), 0);\n\n    vector<vector<int>> candidate_orders;\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cy[a] != cy[b]) return cy[a] < cy[b];\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n            if (sa != sb) return sa < sb;\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            int sa = cx[a] - cy[a], sb = cx[b] - cy[b];\n            if (sa != sb) return sa < sb;\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            long long ka = morton_key(cx[a], cy[a]);\n            long long kb = morton_key(cx[b], cy[b]);\n            if (ka != kb) return ka < kb;\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        vector<pair<pair<int,int>, int>> pts;\n        for (int v : all) pts.push_back({{cx[v] / 700, cy[v]}, v});\n        sort(pts.begin(), pts.end(), [&](auto &A, auto &B) {\n            int ba = A.first.first, bb = B.first.first;\n            if (ba != bb) return ba < bb;\n            if (ba & 1) return A.first.second > B.first.second;\n            return A.first.second < B.first.second;\n        });\n        vector<int> ord;\n        for (auto &p : pts) ord.push_back(p.second);\n        candidate_orders.push_back(ord);\n    }\n    {\n        vector<pair<pair<int,int>, int>> pts;\n        for (int v : all) pts.push_back({{cy[v] / 700, cx[v]}, v});\n        sort(pts.begin(), pts.end(), [&](auto &A, auto &B) {\n            int ba = A.first.first, bb = B.first.first;\n            if (ba != bb) return ba < bb;\n            if (ba & 1) return A.first.second > B.first.second;\n            return A.first.second < B.first.second;\n        });\n        vector<int> ord;\n        for (auto &p : pts) ord.push_back(p.second);\n        candidate_orders.push_back(ord);\n    }\n\n    vector<vector<int>> groups;\n    long long best_score = (1LL << 62);\n    for (auto &ord : candidate_orders) {\n        auto cand = partition_by_order(ord);\n        long long sc = total_cost_plain(cand);\n        if (sc < best_score) {\n            best_score = sc;\n            groups = move(cand);\n        }\n    }\n\n    auto make_order = [&](vector<int> U, int type) -> vector<int> {\n        if (type == 0) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            });\n        } else if (type == 1) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            });\n        } else if (type == 2) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n        } else if (type == 3) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                int sa = cx[a] - cy[a], sb = cx[b] - cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n        } else if (type == 4) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                long long ka = morton_key(cx[a], cy[a]);\n                long long kb = morton_key(cx[b], cy[b]);\n                if (ka != kb) return ka < kb;\n                return a < b;\n            });\n        } else {\n            int sx = (rng.next() & 1) ? 1 : -1;\n            int sy = (rng.next() & 1) ? 1 : -1;\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                int va = sx * cx[a] + sy * cy[a];\n                int vb = sx * cx[b] + sy * cy[b];\n                if (va != vb) return va < vb;\n                return a < b;\n            });\n        }\n        return U;\n    };\n\n    auto improve_pair_plain = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        int sa = (int)A.size(), sb = (int)B.size();\n        long long oldv = mst_cost_plain(A) + mst_cost_plain(B);\n        bool improved = false;\n\n        // small boundary swaps\n        long long best = oldv;\n        int besta = -1, bestb = -1;\n        for (int ia = max(0, sa - 10); ia < sa; ia++) {\n            for (int ib = 0; ib < min(sb, 10); ib++) {\n                vector<int> nA = A, nB = B;\n                swap(nA[ia], nB[ib]);\n                long long nv = mst_cost_plain(nA) + mst_cost_plain(nB);\n                if (nv < best) {\n                    best = nv;\n                    besta = ia;\n                    bestb = ib;\n                }\n            }\n        }\n        if (besta != -1) {\n            swap(A[besta], B[bestb]);\n            improved = true;\n            oldv = best;\n        }\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.end());\n            long long nv = mst_cost_plain(A2) + mst_cost_plain(B2);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    auto improve_triple_plain = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        auto &C = groups[gi + 2];\n        int sa = (int)A.size(), sb = (int)B.size(), sc = (int)C.size();\n\n        long long oldv = mst_cost_plain(A) + mst_cost_plain(B) + mst_cost_plain(C);\n        bool improved = false;\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        U.insert(U.end(), C.begin(), C.end());\n\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.begin() + sa + sb);\n            vector<int> C2(ord.begin() + sa + sb, ord.end());\n            long long nv = mst_cost_plain(A2) + mst_cost_plain(B2) + mst_cost_plain(C2);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                C = move(C2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    // Deterministic + randomized pre-query improvement\n    for (int rep = 0; rep < 2; rep++) {\n        bool imp = false;\n        for (int gi = 0; gi + 1 < M; gi++) imp |= improve_pair_plain(gi, 6);\n        for (int gi = 0; gi + 2 < M; gi++) {\n            if (timer.elapsed() > 0.70) break;\n            imp |= improve_triple_plain(gi, 6);\n        }\n        if (!imp) break;\n    }\n    while (timer.elapsed() < 0.95) {\n        if (M >= 3 && (rng.next() & 1)) {\n            int gi = rng.next_int(0, M - 3);\n            improve_triple_plain(gi, 3);\n        } else if (M >= 2) {\n            int gi = rng.next_int(0, M - 2);\n            improve_pair_plain(gi, 3);\n        } else break;\n    }\n\n    // Query phase\n    vector<vector<pair<int,int>>> queried_edges(M);\n    int used_queries = 0;\n\n    auto do_query = [&](const vector<int>& subset) -> vector<pair<int,int>> {\n        cout << \"? \" << subset.size();\n        for (int v : subset) cout << ' ' << v;\n        cout << '\\n';\n        cout.flush();\n        vector<pair<int,int>> ret;\n        ret.reserve((int)subset.size() - 1);\n        for (int i = 0; i < (int)subset.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    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n    sort(gids.begin(), gids.end(), [&](int a, int b) {\n        if (groups[a].size() != groups[b].size()) return groups[a].size() > groups[b].size();\n        return a < b;\n    });\n\n    for (int gi : gids) {\n        if (used_queries >= Q) break;\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        if (sz <= 1) continue;\n\n        vector<vector<int>> local_orders;\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            });\n            local_orders.push_back(ord);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            });\n            local_orders.push_back(ord);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n            local_orders.push_back(ord);\n        }\n\n        int block = min(L, sz);\n        int step = max(1, block / 2);\n        set<vector<int>> seen;\n\n        for (auto &ord : local_orders) {\n            for (int s = 0; s < sz && used_queries < Q; s += step) {\n                int e = min(sz, s + block);\n                if (e - s < 2) break;\n                vector<int> subset(ord.begin() + s, ord.begin() + e);\n                sort(subset.begin(), subset.end());\n                if (!seen.insert(subset).second) {\n                    if (e == sz) break;\n                    continue;\n                }\n                auto ret = do_query(subset);\n                for (auto &p : ret) queried_edges[gi].push_back(p);\n                used_queries++;\n                if (e == sz) break;\n            }\n        }\n    }\n\n    vector<unordered_set<long long>> qset(M);\n    auto enc = [&](int a, int b) -> long long {\n        if (a > b) swap(a, b);\n        return 1LL * a * N + b;\n    };\n    for (int gi = 0; gi < M; gi++) {\n        qset[gi].reserve(queried_edges[gi].size() * 2 + 1);\n        for (auto [a, b] : queried_edges[gi]) qset[gi].insert(enc(a, b));\n    }\n\n    auto mst_cost_query = [&](const vector<int>& vs, const unordered_set<long long>& qs) -> long long {\n        int n = (int)vs.size();\n        if (n <= 1) return 0;\n        const int INF = 1e9;\n        vector<int> best(n, INF);\n        vector<char> used(n, 0);\n        best[0] = 0;\n        long long res = 0;\n        for (int it = 0; it < n; it++) {\n            int v = -1;\n            for (int i = 0; i < n; i++) if (!used[i]) {\n                if (v == -1 || best[i] < best[v]) v = i;\n            }\n            used[v] = 1;\n            res += best[v];\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                int w = est_dist(vs[v], vs[j]);\n                if (qs.count(enc(vs[v], vs[j]))) w = max(0, w - 12);\n                if (w < best[j]) best[j] = w;\n            }\n        }\n        return res;\n    };\n\n    auto improve_pair_query = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        int sa = (int)A.size(), sb = (int)B.size();\n\n        unordered_set<long long> qs;\n        qs.reserve(qset[gi].size() + qset[gi + 1].size() + 1);\n        for (auto x : qset[gi]) qs.insert(x);\n        for (auto x : qset[gi + 1]) qs.insert(x);\n\n        long long oldv = mst_cost_query(A, qs) + mst_cost_query(B, qs);\n        bool improved = false;\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.end());\n            long long nv = mst_cost_query(A2, qs) + mst_cost_query(B2, qs);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    auto improve_triple_query = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        auto &C = groups[gi + 2];\n        int sa = (int)A.size(), sb = (int)B.size(), sc = (int)C.size();\n\n        unordered_set<long long> qs;\n        qs.reserve(qset[gi].size() + qset[gi + 1].size() + qset[gi + 2].size() + 1);\n        for (auto x : qset[gi]) qs.insert(x);\n        for (auto x : qset[gi + 1]) qs.insert(x);\n        for (auto x : qset[gi + 2]) qs.insert(x);\n\n        long long oldv = mst_cost_query(A, qs) + mst_cost_query(B, qs) + mst_cost_query(C, qs);\n        bool improved = false;\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        U.insert(U.end(), C.begin(), C.end());\n\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.begin() + sa + sb);\n            vector<int> C2(ord.begin() + sa + sb, ord.end());\n            long long nv = mst_cost_query(A2, qs) + mst_cost_query(B2, qs) + mst_cost_query(C2, qs);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                C = move(C2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    // Post-query improvement\n    while (timer.elapsed() < 1.50) {\n        if (M >= 3 && (rng.next() % 3 != 0)) {\n            int gi = rng.next_int(0, M - 3);\n            improve_triple_query(gi, 3);\n        } else if (M >= 2) {\n            int gi = rng.next_int(0, M - 2);\n            improve_pair_query(gi, 3);\n        } else break;\n    }\n\n    // Final tree construction\n    vector<vector<pair<int,int>>> answer_edges(M);\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        answer_edges[gi].clear();\n        if (sz <= 1) continue;\n\n        unordered_map<int,int> pos;\n        pos.reserve(sz * 2);\n        for (int i = 0; i < sz; i++) pos[g[i]] = i;\n\n        vector<Edge> cand;\n        auto add_edge = [&](int a, int b) {\n            if (a == b) return;\n            if (a > b) swap(a, b);\n            int w = est_dist(a, b);\n            if (qset[gi].count(enc(a, b))) w = max(0, w - 20);\n            cand.push_back({a, b, w});\n        };\n\n        for (auto [a, b] : queried_edges[gi]) {\n            if (pos.count(a) && pos.count(b)) add_edge(a, b);\n        }\n\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            });\n            for (int i = 0; i < sz; i++) for (int d = 1; d <= 4; d++) if (i + d < sz) add_edge(ord[i], ord[i + d]);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            });\n            for (int i = 0; i < sz; i++) for (int d = 1; d <= 4; d++) if (i + d < sz) add_edge(ord[i], ord[i + d]);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n            for (int i = 0; i < sz; i++) for (int d = 1; d <= 3; d++) if (i + d < sz) add_edge(ord[i], ord[i + d]);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                int sa = cx[a] - cy[a], sb = cx[b] - cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n            for (int i = 0; i < sz; i++) for (int d = 1; d <= 3; d++) if (i + d < sz) add_edge(ord[i], ord[i + d]);\n        }\n\n        int k = min(6, sz - 1);\n        for (int i = 0; i < sz; i++) {\n            vector<pair<int,int>> vv;\n            vv.reserve(sz - 1);\n            for (int j = 0; j < sz; j++) if (i != j) vv.push_back({est_dist(g[i], g[j]), g[j]});\n            if ((int)vv.size() > k) nth_element(vv.begin(), vv.begin() + k, vv.end());\n            int lim = min(k, (int)vv.size());\n            for (int t = 0; t < lim; t++) add_edge(g[i], vv[t].second);\n        }\n\n        sort(cand.begin(), cand.end(), [&](const Edge& a, const Edge& b) {\n            if (a.u != b.u) return a.u < b.u;\n            if (a.v != b.v) return a.v < b.v;\n            return a.w < b.w;\n        });\n        vector<Edge> uniq;\n        uniq.reserve(cand.size());\n        for (auto &e : cand) {\n            if (uniq.empty() || uniq.back().u != e.u || uniq.back().v != e.v) uniq.push_back(e);\n        }\n        cand.swap(uniq);\n        sort(cand.begin(), cand.end());\n\n        DSU dsu(N);\n        for (auto &e : cand) {\n            if (dsu.unite(e.u, e.v)) {\n                answer_edges[gi].push_back({e.u, e.v});\n                if ((int)answer_edges[gi].size() == sz - 1) break;\n            }\n        }\n\n        if ((int)answer_edges[gi].size() < sz - 1) {\n            answer_edges[gi].clear();\n            const int INF = 1e9;\n            vector<int> best(sz, INF), par(sz, -1);\n            vector<char> used(sz, 0);\n            best[0] = 0;\n            for (int it = 0; it < sz; it++) {\n                int v = -1;\n                for (int i = 0; i < sz; i++) if (!used[i]) {\n                    if (v == -1 || best[i] < best[v]) v = i;\n                }\n                used[v] = 1;\n                if (par[v] != -1) answer_edges[gi].push_back({g[v], g[par[v]]});\n                for (int to = 0; to < sz; to++) if (!used[to]) {\n                    int w = est_dist(g[v], g[to]);\n                    if (qset[gi].count(enc(g[v], g[to]))) w = max(0, w - 15);\n                    if (w < best[to]) {\n                        best[to] = w;\n                        par[to] = v;\n                    }\n                }\n            }\n        }\n\n        if ((int)answer_edges[gi].size() != sz - 1) {\n            answer_edges[gi].clear();\n            for (int i = 1; i < sz; i++) answer_edges[gi].push_back({g[i - 1], g[i]});\n        }\n    }\n\n    // Final safety\n    bool bad = false;\n    vector<int> freq(N, 0);\n    for (int gi = 0; gi < M; gi++) {\n        if ((int)groups[gi].size() != G[gi]) bad = true;\n        if ((int)answer_edges[gi].size() != max(0, G[gi] - 1)) bad = true;\n        for (int v : groups[gi]) {\n            if (v < 0 || v >= N) bad = true;\n            else freq[v]++;\n        }\n    }\n    for (int i = 0; i < N; i++) if (freq[i] != 1) bad = true;\n\n    if (bad) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        int ptr = 0;\n        for (int gi = 0; gi < M; gi++) {\n            groups[gi].assign(ord.begin() + ptr, ord.begin() + ptr + G[gi]);\n            ptr += G[gi];\n            answer_edges[gi].clear();\n            for (int i = 1; i < G[gi]; i++) answer_edges[gi].push_back({groups[gi][i - 1], groups[gi][i]});\n        }\n    }\n\n    cout << \"!\\n\";\n    for (int gi = 0; gi < M; gi++) {\n        for (int i = 0; i < (int)groups[gi].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gi][i];\n        }\n        cout << '\\n';\n        for (auto [a, b] : answer_edges[gi]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int INF = 1e9;\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar DCH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n};\n\nstruct Action {\n    char a, d;\n};\n\nstruct Plan {\n    int cost = INF;\n    int tie = 0;\n    vector<Action> acts;\n};\n\ninline bool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nstruct Solver {\n    int M;\n    vector<Pos> pts;\n    bool block[N][N]{};\n    vector<Action> ans;\n    Pos cur;\n\n    Solver(int M_, const vector<Pos>& pts_) : M(M_), pts(pts_) {\n        memset(block, 0, sizeof(block));\n        cur = pts[0];\n    }\n\n    inline void relax(Plan& best, const Plan& cand) {\n        if (cand.cost < best.cost || (cand.cost == best.cost && cand.tie < best.tie)) {\n            best = cand;\n        }\n    }\n\n    Pos slide_result(Pos s, int d) const {\n        int r = s.r, c = s.c;\n        while (true) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc) || block[nr][nc]) break;\n            r = nr; c = nc;\n        }\n        return {r, c};\n    }\n\n    Plan shortest_MS(Pos s, Pos g) {\n        Plan p;\n        static int dist[N][N];\n        static Pos par[N][N];\n        static char pact[N][N];\n        static int pdir[N][N];\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) dist[i][j] = -1;\n\n        queue<Pos> q;\n        dist[s.r][s.c] = 0;\n        q.push(s);\n\n        while (!q.empty()) {\n            Pos v = q.front(); q.pop();\n            if (v == g) break;\n\n            // Move edges\n            for (int d = 0; d < 4; d++) {\n                int nr = v.r + dr[d], nc = v.c + dc[d];\n                if (!inside(nr, nc) || block[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[v.r][v.c] + 1;\n                par[nr][nc] = v;\n                pact[nr][nc] = 'M';\n                pdir[nr][nc] = d;\n                q.push({nr, nc});\n            }\n\n            // Slide edges\n            for (int d = 0; d < 4; d++) {\n                Pos to = slide_result(v, d);\n                if (to == v) continue;\n                if (dist[to.r][to.c] != -1) continue;\n                dist[to.r][to.c] = dist[v.r][v.c] + 1;\n                par[to.r][to.c] = v;\n                pact[to.r][to.c] = 'S';\n                pdir[to.r][to.c] = d;\n                q.push(to);\n            }\n        }\n\n        if (dist[g.r][g.c] == -1) return p;\n        p.cost = dist[g.r][g.c];\n\n        vector<Action> rev;\n        Pos x = g;\n        while (x != s) {\n            rev.push_back({pact[x.r][x.c], DCH[pdir[x.r][x.c]]});\n            x = par[x.r][x.c];\n        }\n        reverse(rev.begin(), rev.end());\n        p.acts = move(rev);\n        return p;\n    }\n\n    vector<int> bfs_move_dirs(Pos s, Pos g) {\n        static int dist[N][N];\n        static Pos par[N][N];\n        static int pard[N][N];\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) dist[i][j] = -1;\n\n        queue<Pos> q;\n        dist[s.r][s.c] = 0;\n        q.push(s);\n\n        while (!q.empty()) {\n            Pos v = q.front(); q.pop();\n            if (v == g) break;\n            for (int d = 0; d < 4; d++) {\n                int nr = v.r + dr[d], nc = v.c + dc[d];\n                if (!inside(nr, nc) || block[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[v.r][v.c] + 1;\n                par[nr][nc] = v;\n                pard[nr][nc] = d;\n                q.push({nr, nc});\n            }\n        }\n\n        if (dist[g.r][g.c] == -1) return {};\n        vector<int> dirs;\n        Pos x = g;\n        while (x != s) {\n            dirs.push_back(pard[x.r][x.c]);\n            x = par[x.r][x.c];\n        }\n        reverse(dirs.begin(), dirs.end());\n        return dirs;\n    }\n\n    // Create one stopper beyond target, then use shortest M/S path under that block.\n    Plan create_stopper_then_ms(Pos s, Pos g, Pos next_goal) {\n        Plan best;\n        Plan baseline = shortest_MS(s, g);\n        int base_cost = baseline.cost;\n\n        for (int d = 0; d < 4; d++) {\n            int br = g.r + dr[d], bc = g.c + dc[d];\n            if (!inside(br, bc)) continue;\n            if (block[br][bc]) continue;\n\n            // Need to stand adjacent to blocker cell to alter it\n            for (int ad = 0; ad < 4; ad++) {\n                int yr = br - dr[ad], yc = bc - dc[ad];\n                if (!inside(yr, yc) || block[yr][yc]) continue;\n                Pos y{yr, yc};\n\n                auto path1 = bfs_move_dirs(s, y);\n                if (path1.empty() && s != y) continue;\n\n                block[br][bc] = true;\n                Plan after = shortest_MS(y, g);\n                block[br][bc] = false;\n\n                if (after.cost >= INF) continue;\n\n                Plan cand;\n                cand.cost = (int)path1.size() + 1 + after.cost;\n\n                // Don't invest too much if not immediately useful\n                if (cand.cost > base_cost + 1) continue;\n\n                cand.tie = 0;\n                if (br == next_goal.r || bc == next_goal.c) cand.tie -= 1;\n\n                for (int dd : path1) cand.acts.push_back({'M', DCH[dd]});\n                cand.acts.push_back({'A', DCH[ad]});\n\n                block[br][bc] = true;\n                Plan after2 = shortest_MS(y, g);\n                block[br][bc] = false;\n                for (auto ac : after2.acts) cand.acts.push_back(ac);\n\n                relax(best, cand);\n            }\n        }\n        return best;\n    }\n\n    // Very cheap persistent anchor idea:\n    // create one anchor at (g.r,1)/(g.r,N-2)/(1,g.c)/(N-2,g.c) if it does not hurt current cost too much.\n    Plan create_anchor_then_ms(Pos s, Pos g, Pos next_goal) {\n        Plan best;\n        Plan baseline = shortest_MS(s, g);\n        int base_cost = baseline.cost;\n\n        vector<Pos> anchors = {\n            {g.r, 1}, {g.r, N - 2}, {1, g.c}, {N - 2, g.c}\n        };\n        bool used[N][N]{};\n\n        for (Pos a : anchors) {\n            if (!inside(a.r, a.c) || block[a.r][a.c] || used[a.r][a.c]) continue;\n            if (a == s || a == g) continue;\n            used[a.r][a.c] = true;\n\n            for (int d = 0; d < 4; d++) {\n                int yr = a.r - dr[d], yc = a.c - dc[d];\n                if (!inside(yr, yc) || block[yr][yc]) continue;\n                Pos y{yr, yc};\n\n                auto path1 = bfs_move_dirs(s, y);\n                if (path1.empty() && s != y) continue;\n\n                block[a.r][a.c] = true;\n                Plan after = shortest_MS(y, g);\n                block[a.r][a.c] = false;\n                if (after.cost >= INF) continue;\n\n                Plan cand;\n                cand.cost = (int)path1.size() + 1 + after.cost;\n                if (cand.cost > base_cost + 1) continue;\n\n                cand.tie = 0;\n                if (a.r == next_goal.r || a.c == next_goal.c) cand.tie -= 2;\n                if (a.r == g.r || a.c == g.c) cand.tie -= 1;\n\n                for (int dd : path1) cand.acts.push_back({'M', DCH[dd]});\n                cand.acts.push_back({'A', DCH[d]});\n\n                block[a.r][a.c] = true;\n                Plan after2 = shortest_MS(y, g);\n                block[a.r][a.c] = false;\n                for (auto ac : after2.acts) cand.acts.push_back(ac);\n\n                relax(best, cand);\n            }\n        }\n\n        return best;\n    }\n\n    void do_action(const Action& ac) {\n        ans.push_back(ac);\n        int d = (ac.d == 'U' ? 0 : ac.d == 'D' ? 1 : ac.d == 'L' ? 2 : 3);\n        if (ac.a == 'M') {\n            cur.r += dr[d];\n            cur.c += dc[d];\n        } else if (ac.a == 'S') {\n            cur = slide_result(cur, d);\n        } else {\n            int nr = cur.r + dr[d], nc = cur.c + dc[d];\n            if (inside(nr, nc)) block[nr][nc] ^= 1;\n        }\n    }\n\n    void execute_plan(const Plan& p) {\n        for (const auto& ac : p.acts) do_action(ac);\n    }\n\n    void solve() {\n        for (int i = 1; i < M; i++) {\n            Pos g = pts[i];\n            Pos next_goal = (i + 1 < M ? pts[i + 1] : g);\n\n            Plan best = shortest_MS(cur, g);\n\n            Plan p1 = create_stopper_then_ms(cur, g, next_goal);\n            relax(best, p1);\n\n            Plan p2 = create_anchor_then_ms(cur, g, next_goal);\n            relax(best, p2);\n\n            if (best.cost >= INF) {\n                auto dirs = bfs_move_dirs(cur, g);\n                for (int d : dirs) do_action({'M', DCH[d]});\n            } else {\n                execute_plan(best);\n            }\n\n            // Safety\n            if (cur != g) {\n                auto dirs = bfs_move_dirs(cur, g);\n                for (int d : dirs) do_action({'M', DCH[d]});\n            }\n        }\n\n        for (auto& ac : ans) {\n            cout << ac.a << ' ' << ac.d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin, M;\n    cin >> Nin >> M;\n    vector<Pos> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].r >> pts[i].c;\n\n    Solver solver(M, pts);\n    solver.solve();\n    return 0;\n}"},"16":{"ahc001":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int LIM = 10000;\n\nstruct Input {\n    int x, y, r;\n};\n\nstruct Rect {\n    int a, b, c, d;\n};\n\nstruct Move {\n    int idx = -1;\n    Rect nr{};\n    double gain = -1e100;\n    bool valid = false;\n};\n\nstatic inline bool overlap1D(int l1, int r1, int l2, int r2) {\n    return max(l1, l2) < min(r1, r2);\n}\n\nstatic inline bool overlap2D(const Rect& p, const Rect& q) {\n    return overlap1D(p.a, p.c, q.a, q.c) && overlap1D(p.b, p.d, q.b, q.d);\n}\n\nstatic inline long long area(const Rect& r) {\n    return 1LL * (r.c - r.a) * (r.d - r.b);\n}\n\nstatic inline double sat(long long s, long long r) {\n    double t = (double)min(s, r) / (double)max(s, r);\n    double u = 1.0 - t;\n    return 1.0 - u * u;\n}\n\nstruct Solver {\n    int n;\n    vector<Input> in;\n    mt19937 rng;\n\n    vector<double> density_priority;\n    vector<int> seedL0, seedR0, seedD0, seedU0;\n    vector<int> seedL1, seedR1, seedD1, seedU1;\n    vector<Rect> best_rects;\n\n    Solver(int n_, vector<Input> in_) : n(n_), in(std::move(in_)) {\n        rng.seed((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n        build_density_priority();\n        build_seed_boxes();\n    }\n\n    void build_density_priority() {\n        density_priority.assign(n, 0.0);\n        for (int i = 0; i < n; i++) {\n            int lx = in[i].x + 1;\n            int rx = LIM - in[i].x;\n            int dy = in[i].y + 1;\n            int uy = LIM - in[i].y;\n            for (int j = 0; j < n; j++) if (i != j) {\n                if (in[j].x < in[i].x) lx = min(lx, in[i].x - in[j].x);\n                if (in[j].x > in[i].x) rx = min(rx, in[j].x - in[i].x);\n                if (in[j].y < in[i].y) dy = min(dy, in[i].y - in[j].y);\n                if (in[j].y > in[i].y) uy = min(uy, in[j].y - in[i].y);\n            }\n            double free_est = 1.0 * (lx + rx) * (dy + uy);\n            density_priority[i] = (double)in[i].r / max(1.0, free_est);\n        }\n    }\n\n    void build_seed_boxes() {\n        seedL0.assign(n, 0); seedR0.assign(n, LIM); seedD0.assign(n, 0); seedU0.assign(n, LIM);\n        seedL1.assign(n, 0); seedR1.assign(n, LIM); seedD1.assign(n, 0); seedU1.assign(n, LIM);\n\n        for (int i = 0; i < n; i++) {\n            int x = in[i].x, y = in[i].y;\n            int bestXL = -1, bestXR = LIM, bestYD = -1, bestYU = LIM;\n\n            for (int j = 0; j < n; j++) if (i != j) {\n                if (in[j].x < x) bestXL = max(bestXL, in[j].x);\n                if (in[j].x > x) bestXR = min(bestXR, in[j].x);\n                if (in[j].y < y) bestYD = max(bestYD, in[j].y);\n                if (in[j].y > y) bestYU = min(bestYU, in[j].y);\n            }\n\n            int L0 = (bestXL >= 0 ? max(0, (bestXL + x + 1) / 2) : 0);\n            int R0 = (bestXR < LIM ? min(LIM, (x + bestXR + 2) / 2) : LIM);\n            int D0 = (bestYD >= 0 ? max(0, (bestYD + y + 1) / 2) : 0);\n            int U0 = (bestYU < LIM ? min(LIM, (y + bestYU + 2) / 2) : LIM);\n\n            L0 = min(L0, x); R0 = max(R0, x + 1);\n            D0 = min(D0, y); U0 = max(U0, y + 1);\n\n            seedL0[i] = L0; seedR0[i] = R0; seedD0[i] = D0; seedU0[i] = U0;\n\n            int L1 = min(x, L0 + max(0, (x - L0) / 4));\n            int R1 = max(x + 1, R0 - max(0, (R0 - (x + 1)) / 4));\n            int D1 = min(y, D0 + max(0, (y - D0) / 4));\n            int U1 = max(y + 1, U0 - max(0, (U0 - (y + 1)) / 4));\n\n            seedL1[i] = L1; seedR1[i] = R1; seedD1[i] = D1; seedU1[i] = U1;\n        }\n    }\n\n    double score_one(int i, const Rect& r) const {\n        return sat(area(r), in[i].r);\n    }\n\n    double total_score(const vector<Rect>& rects) const {\n        double s = 0.0;\n        for (int i = 0; i < n; i++) s += score_one(i, rects[i]);\n        return s;\n    }\n\n    bool contains_point(int i, const Rect& r) const {\n        return r.a <= in[i].x && in[i].x < r.c && r.b <= in[i].y && in[i].y < r.d;\n    }\n\n    bool legal_shape(const Rect& r) const {\n        return 0 <= r.a && r.a < r.c && r.c <= LIM && 0 <= r.b && r.b < r.d && r.d <= LIM;\n    }\n\n    bool can_place(const vector<Rect>& rects, int i, const Rect& nr) const {\n        if (!legal_shape(nr)) return false;\n        if (!contains_point(i, nr)) return false;\n        for (int j = 0; j < n; j++) {\n            if (j == i) continue;\n            if (overlap2D(nr, rects[j])) return false;\n        }\n        return true;\n    }\n\n    int max_left(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && q.c <= r.a) bound = max(bound, q.c);\n        }\n        return r.a - bound;\n    }\n\n    int max_right(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.b, r.d, q.b, q.d) && r.c <= q.a) bound = min(bound, q.a);\n        }\n        return bound - r.c;\n    }\n\n    int max_down(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = 0;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && q.d <= r.b) bound = max(bound, q.d);\n        }\n        return r.b - bound;\n    }\n\n    int max_up(const vector<Rect>& rects, int i) const {\n        const Rect& r = rects[i];\n        int bound = LIM;\n        for (int j = 0; j < n; j++) if (j != i) {\n            const Rect& q = rects[j];\n            if (overlap1D(r.a, r.c, q.a, q.c) && r.d <= q.b) bound = min(bound, q.b);\n        }\n        return bound - r.d;\n    }\n\n    vector<int> collect_1d_candidates(long long curA, long long target, int lim, int unit) const {\n        vector<int> cand;\n        if (lim <= 0) return cand;\n        auto add = [&](int x) {\n            if (1 <= x && x <= lim) cand.push_back(x);\n        };\n\n        add(1); add(2); add(4); add(8);\n        add(lim / 2); add(lim);\n\n        if (curA < target) {\n            int need = (int)((target - curA + unit - 1) / unit);\n            for (int d = -3; d <= 3; d++) add(need + d);\n            add(max(1, need / 2));\n            add(min(lim, need * 2));\n        }\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    }\n\n    Move best_move_for(const vector<Rect>& rects, int i) const {\n        const Rect& cur = rects[i];\n        long long curA = area(cur);\n        long long target = in[i].r;\n        double curScore = score_one(i, cur);\n\n        int L = max_left(rects, i);\n        int R = max_right(rects, i);\n        int D = max_down(rects, i);\n        int U = max_up(rects, i);\n\n        Move best;\n        int w = cur.c - cur.a;\n        int h = cur.d - cur.b;\n\n        auto upd = [&](const Rect& nr) {\n            if (!can_place(rects, i, nr)) return;\n            double g = score_one(i, nr) - curScore;\n            if (g > best.gain) best = {i, nr, g, true};\n        };\n\n        vector<int> candH = collect_1d_candidates(curA, target, max(L, R), h);\n        vector<int> candV = collect_1d_candidates(curA, target, max(D, U), w);\n\n        for (int t : candH) {\n            if (t <= L) { Rect nr = cur; nr.a -= t; upd(nr); }\n            if (t <= R) { Rect nr = cur; nr.c += t; upd(nr); }\n        }\n        for (int t : candV) {\n            if (t <= D) { Rect nr = cur; nr.b -= t; upd(nr); }\n            if (t <= U) { Rect nr = cur; nr.d += t; upd(nr); }\n        }\n\n        if (L + R > 0) {\n            vector<int> cand = collect_1d_candidates(curA, target, L + R, h);\n            for (int tot : cand) {\n                int l = min(L, tot / 2);\n                int r = min(R, tot - l);\n                if (l + r < tot) {\n                    int rem = tot - l - r;\n                    int addL = min(L - l, rem);\n                    l += addL;\n                    r += min(R - r, rem - addL);\n                }\n                if (l + r == tot && tot > 0) {\n                    Rect nr = cur; nr.a -= l; nr.c += r; upd(nr);\n                }\n            }\n        }\n\n        if (D + U > 0) {\n            vector<int> cand = collect_1d_candidates(curA, target, D + U, w);\n            for (int tot : cand) {\n                int d = min(D, tot / 2);\n                int u = min(U, tot - d);\n                if (d + u < tot) {\n                    int rem = tot - d - u;\n                    int addD = min(D - d, rem);\n                    d += addD;\n                    u += min(U - u, rem - addD);\n                }\n                if (d + u == tot && tot > 0) {\n                    Rect nr = cur; nr.b -= d; nr.d += u; upd(nr);\n                }\n            }\n        }\n\n        auto smalls = [&](int lim) {\n            vector<int> v;\n            if (lim <= 0) return v;\n            auto add = [&](int x) { if (1 <= x && x <= lim) v.push_back(x); };\n            add(1); add(2); add(4); add(lim / 2);\n            sort(v.begin(), v.end());\n            v.erase(unique(v.begin(), v.end()), v.end());\n            return v;\n        };\n\n        vector<int> cL = smalls(L), cR = smalls(R), cD = smalls(D), cU = smalls(U);\n        for (int x : cL) for (int y : cD) { Rect nr = cur; nr.a -= x; nr.b -= y; upd(nr); }\n        for (int x : cL) for (int y : cU) { Rect nr = cur; nr.a -= x; nr.d += y; upd(nr); }\n        for (int x : cR) for (int y : cD) { Rect nr = cur; nr.c += x; nr.b -= y; upd(nr); }\n        for (int x : cR) for (int y : cU) { Rect nr = cur; nr.c += x; nr.d += y; upd(nr); }\n\n        return best;\n    }\n\n    bool apply_best_for(vector<Rect>& rects, int i) const {\n        Move mv = best_move_for(rects, i);\n        if (mv.valid && mv.gain > 1e-15) {\n            rects[i] = mv.nr;\n            return true;\n        }\n        return false;\n    }\n\n    bool best_improvement_step(vector<Rect>& rects) const {\n        Move best;\n        for (int i = 0; i < n; i++) {\n            Move mv = best_move_for(rects, i);\n            if (mv.valid && mv.gain > best.gain) best = mv;\n        }\n        if (best.valid && best.gain > 1e-15) {\n            rects[best.idx] = best.nr;\n            return true;\n        }\n        return false;\n    }\n\n    bool tiny_trim_one(vector<Rect>& rects, int i) const {\n        const Rect cur = rects[i];\n        if (area(cur) <= in[i].r) return false;\n\n        double curScore = score_one(i, cur);\n        double bestGain = 1e-18;\n        Rect bestRect = cur;\n\n        auto try_trim = [&](const Rect& nr) {\n            if (!legal_shape(nr)) return;\n            if (!contains_point(i, nr)) return;\n            double g = score_one(i, nr) - curScore;\n            if (g > bestGain) {\n                bestGain = g;\n                bestRect = nr;\n            }\n        };\n\n        if (cur.a < in[i].x) { Rect nr = cur; nr.a++; try_trim(nr); }\n        if (in[i].x + 1 < cur.c) { Rect nr = cur; nr.c--; try_trim(nr); }\n        if (cur.b < in[i].y) { Rect nr = cur; nr.b++; try_trim(nr); }\n        if (in[i].y + 1 < cur.d) { Rect nr = cur; nr.d--; try_trim(nr); }\n\n        if (bestGain > 1e-15) {\n            rects[i] = bestRect;\n            return true;\n        }\n        return false;\n    }\n\n    bool tiny_reshape_one(vector<Rect>& rects, int i) {\n        const Rect cur = rects[i];\n        double curScore = score_one(i, cur);\n        double bestGain = 1e-18;\n        Rect bestRect = cur;\n\n        vector<Rect> cand;\n        cand.reserve(16);\n\n        bool canShrinkL = cur.a < in[i].x;\n        bool canShrinkR = in[i].x + 1 < cur.c;\n        bool canShrinkD = cur.b < in[i].y;\n        bool canShrinkU = in[i].y + 1 < cur.d;\n\n        int L = max_left(rects, i), R = max_right(rects, i), D = max_down(rects, i), U = max_up(rects, i);\n\n        if (canShrinkL && U >= 1) { Rect nr = cur; nr.a++; nr.d++; cand.push_back(nr); }\n        if (canShrinkL && D >= 1) { Rect nr = cur; nr.a++; nr.b--; cand.push_back(nr); }\n        if (canShrinkR && U >= 1) { Rect nr = cur; nr.c--; nr.d++; cand.push_back(nr); }\n        if (canShrinkR && D >= 1) { Rect nr = cur; nr.c--; nr.b--; cand.push_back(nr); }\n\n        if (canShrinkD && L >= 1) { Rect nr = cur; nr.b++; nr.a--; cand.push_back(nr); }\n        if (canShrinkD && R >= 1) { Rect nr = cur; nr.b++; nr.c++; cand.push_back(nr); }\n        if (canShrinkU && L >= 1) { Rect nr = cur; nr.d--; nr.a--; cand.push_back(nr); }\n        if (canShrinkU && R >= 1) { Rect nr = cur; nr.d--; nr.c++; cand.push_back(nr); }\n\n        if (canShrinkL && U >= 2) { Rect nr = cur; nr.a++; nr.d += 2; cand.push_back(nr); }\n        if (canShrinkR && U >= 2) { Rect nr = cur; nr.c--; nr.d += 2; cand.push_back(nr); }\n        if (canShrinkL && D >= 2) { Rect nr = cur; nr.a++; nr.b -= 2; cand.push_back(nr); }\n        if (canShrinkR && D >= 2) { Rect nr = cur; nr.c--; nr.b -= 2; cand.push_back(nr); }\n\n        if (canShrinkD && L >= 2) { Rect nr = cur; nr.b++; nr.a -= 2; cand.push_back(nr); }\n        if (canShrinkD && R >= 2) { Rect nr = cur; nr.b++; nr.c += 2; cand.push_back(nr); }\n        if (canShrinkU && L >= 2) { Rect nr = cur; nr.d--; nr.a -= 2; cand.push_back(nr); }\n        if (canShrinkU && R >= 2) { Rect nr = cur; nr.d--; nr.c += 2; cand.push_back(nr); }\n\n        shuffle(cand.begin(), cand.end(), rng);\n\n        for (const Rect& nr : cand) {\n            if (!can_place(rects, i, nr)) continue;\n            double g = score_one(i, nr) - curScore;\n            if (g > bestGain) {\n                bestGain = g;\n                bestRect = nr;\n            }\n        }\n\n        if (bestGain > 1e-15) {\n            rects[i] = bestRect;\n            return true;\n        }\n        return false;\n    }\n\n    void micro_adjust(vector<Rect>& rects, const vector<int>& ord) const {\n        for (int i : ord) {\n            Rect cur = rects[i];\n            double curScore = score_one(i, cur);\n            Rect bestRect = cur;\n            double bestGain = 1e-18;\n\n            auto upd = [&](const Rect& nr) {\n                if (!can_place(rects, i, nr)) return;\n                double g = score_one(i, nr) - curScore;\n                if (g > bestGain) {\n                    bestGain = g;\n                    bestRect = nr;\n                }\n            };\n\n            int L = max_left(rects, i), R = max_right(rects, i), D = max_down(rects, i), U = max_up(rects, i);\n            if (L >= 1) { Rect nr = cur; nr.a--; upd(nr); }\n            if (R >= 1) { Rect nr = cur; nr.c++; upd(nr); }\n            if (D >= 1) { Rect nr = cur; nr.b--; upd(nr); }\n            if (U >= 1) { Rect nr = cur; nr.d++; upd(nr); }\n\n            if (L >= 1 && D >= 1) { Rect nr = cur; nr.a--; nr.b--; upd(nr); }\n            if (L >= 1 && U >= 1) { Rect nr = cur; nr.a--; nr.d++; upd(nr); }\n            if (R >= 1 && D >= 1) { Rect nr = cur; nr.c++; nr.b--; upd(nr); }\n            if (R >= 1 && U >= 1) { Rect nr = cur; nr.c++; nr.d++; upd(nr); }\n\n            if (bestGain > 1e-15) rects[i] = bestRect;\n        }\n    }\n\n    vector<int> make_order(int mode, const vector<Rect>* rects = nullptr) {\n        vector<int> ord(n);\n        iota(ord.begin(), ord.end(), 0);\n\n        if (mode == 0) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) { return in[i].r > in[j].r; });\n        } else if (mode == 1) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) { return in[i].r < in[j].r; });\n        } else if (mode == 2) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) { return density_priority[i] > density_priority[j]; });\n        } else if (mode == 3 && rects != nullptr) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) {\n                double ai = (double)in[i].r / area((*rects)[i]);\n                double aj = (double)in[j].r / area((*rects)[j]);\n                if (fabs(ai - aj) > 1e-12) return ai > aj;\n                return in[i].r > in[j].r;\n            });\n        } else if (mode == 5 && rects != nullptr) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) {\n                double oi = (double)area((*rects)[i]) / in[i].r;\n                double oj = (double)area((*rects)[j]) / in[j].r;\n                if (fabs(oi - oj) > 1e-12) return oi > oj;\n                return in[i].r > in[j].r;\n            });\n        } else if (mode == 6 && rects != nullptr) {\n            sort(ord.begin(), ord.end(), [&](int i, int j) {\n                double ei = max((double)area((*rects)[i]) / in[i].r, (double)in[i].r / area((*rects)[i]));\n                double ej = max((double)area((*rects)[j]) / in[j].r, (double)in[j].r / area((*rects)[j]));\n                if (fabs(ei - ej) > 1e-12) return ei > ej;\n                return in[i].r > in[j].r;\n            });\n        } else {\n            shuffle(ord.begin(), ord.end(), rng);\n        }\n        return ord;\n    }\n\n    void add_seed_dim_candidates(vector<int>& widths, vector<int>& heights, int BW, int BH, long long target) const {\n        auto addw = [&](int x) { if (1 <= x && x <= BW) widths.push_back(x); };\n        auto addh = [&](int x) { if (1 <= x && x <= BH) heights.push_back(x); };\n\n        int sq = max(1, (int)sqrt((double)target));\n        addw(1); addw(BW); addw(sq / 2); addw(sq); addw(sq * 2);\n        addh(1); addh(BH); addh(sq / 2); addh(sq); addh(sq * 2);\n\n        addw((int)min<long long>(BW, max<long long>(1, target / max(1, BH))));\n        addh((int)min<long long>(BH, max<long long>(1, target / max(1, BW))));\n\n        double rw = sqrt((double)target * BW / max(1, BH));\n        double rh = sqrt((double)target * BH / max(1, BW));\n        addw((int)floor(rw)); addw((int)round(rw)); addw((int)ceil(rw));\n        addh((int)floor(rh)); addh((int)round(rh)); addh((int)ceil(rh));\n\n        vector<int> curW = widths;\n        vector<int> curH = heights;\n        for (int w : curW) addh((int)min<long long>(BH, max<long long>(1, target / max(1, w))));\n        for (int h : curH) addw((int)min<long long>(BW, max<long long>(1, target / max(1, h))));\n\n        sort(widths.begin(), widths.end());\n        widths.erase(unique(widths.begin(), widths.end()), widths.end());\n        sort(heights.begin(), heights.end());\n        heights.erase(unique(heights.begin(), heights.end()), heights.end());\n    }\n\n    void seed_initialize(vector<Rect>& rects, const vector<int>& ord, int seed_mode) {\n        for (int i = 0; i < n; i++) rects[i] = {in[i].x, in[i].y, in[i].x + 1, in[i].y + 1};\n\n        const vector<int> *L, *R, *D, *U;\n        if (seed_mode == 0) {\n            L = &seedL0; R = &seedR0; D = &seedD0; U = &seedU0;\n        } else {\n            L = &seedL1; R = &seedR1; D = &seedD1; U = &seedU1;\n        }\n\n        for (int idx : ord) {\n            Rect cur = rects[idx];\n            double bestScore = score_one(idx, cur);\n            Rect bestRect = cur;\n\n            int boxL = (*L)[idx], boxR = (*R)[idx], boxD = (*D)[idx], boxU = (*U)[idx];\n            int BW = boxR - boxL;\n            int BH = boxU - boxD;\n            long long target = in[idx].r;\n\n            vector<int> widths, heights;\n            add_seed_dim_candidates(widths, heights, BW, BH, target);\n\n            for (int w : widths) for (int h : heights) {\n                int a_min = max(boxL, in[idx].x - w + 1);\n                int a_max = min(in[idx].x, boxR - w);\n                int b_min = max(boxD, in[idx].y - h + 1);\n                int b_max = min(in[idx].y, boxU - h);\n                if (a_min > a_max || b_min > b_max) continue;\n\n                int da = a_max - a_min;\n                int db = b_max - b_min;\n\n                vector<int> acand = {\n                    a_min, a_max, (a_min + a_max) / 2,\n                    a_min + da / 3, a_min + (2 * da) / 3,\n                    max(a_min, min(a_max, in[idx].x - w + 1)),\n                    max(a_min, min(a_max, in[idx].x))\n                };\n                vector<int> bcand = {\n                    b_min, b_max, (b_min + b_max) / 2,\n                    b_min + db / 3, b_min + (2 * db) / 3,\n                    max(b_min, min(b_max, in[idx].y - h + 1)),\n                    max(b_min, min(b_max, in[idx].y))\n                };\n\n                sort(acand.begin(), acand.end());\n                acand.erase(unique(acand.begin(), acand.end()), acand.end());\n                sort(bcand.begin(), bcand.end());\n                bcand.erase(unique(bcand.begin(), bcand.end()), bcand.end());\n\n                for (int a : acand) for (int b : bcand) {\n                    Rect nr{a, b, a + w, b + h};\n                    if (!can_place(rects, idx, nr)) continue;\n                    double sc = score_one(idx, nr);\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestRect = nr;\n                    }\n                }\n            }\n\n            rects[idx] = bestRect;\n        }\n    }\n\n    void mini_polish_after_seed(vector<Rect>& rects, const vector<int>& ord) {\n        for (int rep = 0; rep < 2; rep++) {\n            for (int i : ord) tiny_trim_one(rects, i);\n            for (int i : ord) tiny_reshape_one(rects, i);\n            for (int i : ord) {\n                Rect cur = rects[i];\n                double curScore = score_one(i, cur);\n                Rect bestRect = cur;\n                double bestGain = 1e-18;\n\n                auto upd = [&](const Rect& nr) {\n                    if (!can_place(rects, i, nr)) return;\n                    double g = score_one(i, nr) - curScore;\n                    if (g > bestGain) {\n                        bestGain = g;\n                        bestRect = nr;\n                    }\n                };\n\n                int L = max_left(rects, i), R = max_right(rects, i), D = max_down(rects, i), U = max_up(rects, i);\n                if (L >= 1) { Rect nr = cur; nr.a--; upd(nr); }\n                if (R >= 1) { Rect nr = cur; nr.c++; upd(nr); }\n                if (D >= 1) { Rect nr = cur; nr.b--; upd(nr); }\n                if (U >= 1) { Rect nr = cur; nr.d++; upd(nr); }\n                if (bestGain > 1e-15) rects[i] = bestRect;\n            }\n        }\n\n        // early global-best improvement, just a few steps\n        for (int rep = 0; rep < 3; rep++) {\n            if (!best_improvement_step(rects)) break;\n        }\n    }\n\n    vector<Rect> run_one_strategy(int mode, int seed_mode, bool use_seed, double end_time, chrono::steady_clock::time_point global_start) {\n        vector<Rect> rects(n);\n        vector<int> ord = make_order(mode);\n\n        if (use_seed) {\n            seed_initialize(rects, ord, seed_mode);\n            mini_polish_after_seed(rects, ord);\n        } else {\n            for (int i = 0; i < n; i++) rects[i] = {in[i].x, in[i].y, in[i].x + 1, in[i].y + 1};\n            for (int rep = 0; rep < 2; rep++) {\n                if (!best_improvement_step(rects)) break;\n            }\n        }\n\n        for (int pass = 0; pass < 4; pass++) {\n            vector<int> use_ord = (pass % 2 == 0 ? ord : make_order(3, &rects));\n            for (int i : use_ord) apply_best_for(rects, i);\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) return rects;\n        }\n\n        for (int rep = 0; rep < 16; rep++) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) return rects;\n            if (!best_improvement_step(rects)) break;\n        }\n\n        int idle = 0;\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time * 0.90) break;\n\n            int choice = uniform_int_distribution<int>(0, 2)(rng);\n            vector<int> use_ord;\n            if (choice == 0) use_ord = make_order(3, &rects);\n            else if (choice == 1) use_ord = make_order(5, &rects);\n            else use_ord = make_order(4, &rects);\n\n            bool updated = false;\n            for (int i : use_ord) {\n                if (apply_best_for(rects, i)) updated = true;\n            }\n            if (!updated) {\n                idle++;\n                if (idle >= 4) break;\n            } else {\n                idle = 0;\n            }\n        }\n\n        int err_mix_counter = 0;\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time * 0.985) break;\n\n            bool changed = false;\n            auto ord_over = make_order(5, &rects);\n            auto ord_under = make_order(3, &rects);\n            auto ord_rand = make_order(4, &rects);\n\n            for (int i : ord_over) if (tiny_trim_one(rects, i)) changed = true;\n            for (int i : ord_rand) if (tiny_reshape_one(rects, i)) changed = true;\n            for (int i : ord_under) if (apply_best_for(rects, i)) changed = true;\n\n            if ((err_mix_counter++ & 1) == 0) {\n                auto ord_err = make_order(6, &rects);\n                for (int i : ord_err) {\n                    if (apply_best_for(rects, i)) {\n                        changed = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!changed) break;\n        }\n\n        int tail_counter = 0;\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - global_start).count();\n            if (elapsed > end_time) break;\n\n            auto ord_over = make_order(5, &rects);\n            auto ord_under = make_order(3, &rects);\n            auto ord_rand = make_order(4, &rects);\n\n            for (int i : ord_over) tiny_trim_one(rects, i);\n            for (int i : ord_rand) tiny_reshape_one(rects, i);\n            micro_adjust(rects, ord_under);\n\n            if ((tail_counter++ & 3) == 0) {\n                auto ord_err = make_order(6, &rects);\n                micro_adjust(rects, ord_err);\n            }\n        }\n\n        return rects;\n    }\n\n    void solve() {\n        auto start = chrono::steady_clock::now();\n        uint32_t base_seed = (uint32_t)chrono::steady_clock::now().time_since_epoch().count();\n\n        best_rects.assign(n, {0, 0, 1, 1});\n        double best_score = -1e100;\n\n        vector<tuple<int,int,bool>> configs = {\n            {0,0,true}, {2,0,true}, {3,0,true},\n            {0,1,true}, {2,1,true}, {3,1,true},\n            {0,0,false}, {2,0,false}, {1,0,true}, {4,0,true}\n        };\n\n        vector<pair<double, int>> ranking;\n\n        for (int t = 0; t < (int)configs.size(); t++) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > 1.8) break;\n\n            double remain = 1.9 - elapsed;\n            int left = (int)configs.size() - t;\n            double slice = max(0.06, remain / max(1, left));\n\n            rng.seed(base_seed + 10007u * (t + 1));\n            auto [mode, seed_mode, use_seed] = configs[t];\n            auto rects = run_one_strategy(mode, seed_mode, use_seed, elapsed + slice, start);\n            double sc = total_score(rects);\n            ranking.push_back({sc, t});\n\n            if (sc > best_score) {\n                best_score = sc;\n                best_rects = rects;\n            }\n        }\n\n        sort(ranking.begin(), ranking.end(), greater<>());\n\n        vector<int> chosen;\n        double cutoff = ranking.empty() ? -1e100 : ranking.front().first - 0.20;\n        for (auto [sc, idx] : ranking) {\n            if ((int)chosen.size() >= 6) break;\n            if (sc >= cutoff || (int)chosen.size() < 3) chosen.push_back(idx);\n        }\n        if (chosen.empty()) {\n            for (int i = 0; i < min(5, (int)configs.size()); i++) chosen.push_back(i);\n        }\n\n        int round = 0;\n        while (true) {\n            double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n            if (elapsed > 4.93) break;\n\n            for (int idx : chosen) {\n                elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n                if (elapsed > 4.93) break;\n\n                double remain = 4.97 - elapsed;\n                double slice = max(0.07, remain / max(3, (int)chosen.size()));\n\n                rng.seed(base_seed + 1000003u * (round + 1) + 9176u * (idx + 1));\n                auto [mode, seed_mode, use_seed] = configs[idx];\n                auto rects = run_one_strategy(mode, seed_mode, use_seed, elapsed + slice, start);\n                double sc = total_score(rects);\n\n                if (sc > best_score) {\n                    best_score = sc;\n                    best_rects = rects;\n                }\n            }\n            round++;\n        }\n    }\n\n    void output() const {\n        for (int i = 0; i < n; i++) {\n            cout << best_rects[i].a << ' ' << best_rects[i].b << ' '\n                 << best_rects[i].c << ' ' << best_rects[i].d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<Input> in(n);\n    for (int i = 0; i < n; i++) cin >> in[i].x >> in[i].y >> in[i].r;\n\n    Solver solver(n, in);\n    solver.solve();\n    solver.output();\n    return 0;\n}","ahc002":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXC = 2500;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - st).count();\n    }\n};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { return l + (int)(next_u32() % (uint32_t)(r - l)); }\n    double next_double() { return (double)next_u32() / (double)UINT32_MAX; }\n};\n\nstruct Param {\n    double w_gain;\n    double w_future;\n    double w_reach;\n    double w_mob;\n    double w_dead;\n    double w_small;\n    double look2;\n    double noise;\n    int bfs_depth;\n    int bfs_cap;\n};\n\nstruct EvalResult {\n    double future_score;\n    int reach_cnt;\n    int frontier_sum;\n};\n\nstruct Cand {\n    int dir;\n    int ni, nj;\n    double score;\n};\n\nint si, sj;\nint tid[N][N];\nint pval[N][N];\nint tile_cnt;\n\nvector<pair<int,int>> nbr[N][N];\n\nint vis_stamp[N][N];\nint dista[N][N];\nint cur_stamp = 1;\n\nstring best_path;\nint best_score;\nvector<pair<int,int>> best_pos;\nvector<int> best_pref_score;\nvector<int> best_step_value;\n\ninline double phase_mix(double a, double b, double c, int step) {\n    if (step < 300) {\n        double t = step / 300.0;\n        return a * (1.0 - t) + b * t;\n    } else if (step < 900) {\n        double t = (step - 300) / 600.0;\n        return b * (1.0 - t) + c * t;\n    } else {\n        return c;\n    }\n}\n\nEvalResult bfs_eval(int si0, int sj0, const vector<unsigned char>& usedTile, int depth_limit, int node_cap) {\n    ++cur_stamp;\n    if (cur_stamp == INT_MAX) {\n        memset(vis_stamp, 0, sizeof(vis_stamp));\n        cur_stamp = 1;\n    }\n\n    static const double decay[64] = {\n        1.0,\n        0.94, 0.88, 0.83, 0.78, 0.73, 0.69, 0.65,\n        0.61, 0.57, 0.54, 0.51, 0.48, 0.45, 0.42, 0.40,\n        0.38, 0.36, 0.34, 0.32, 0.30, 0.28, 0.27, 0.26,\n        0.25, 0.24, 0.23, 0.22, 0.21, 0.20, 0.19, 0.18,\n        0.17, 0.16, 0.15, 0.145, 0.14, 0.135, 0.13, 0.125,\n        0.12, 0.115, 0.11, 0.105, 0.10, 0.095, 0.09, 0.085,\n        0.08, 0.075, 0.07, 0.065, 0.06, 0.055, 0.05, 0.045,\n        0.04, 0.038, 0.036, 0.034, 0.032, 0.03, 0.028, 0.026\n    };\n\n    static pair<int,int> q[MAXC];\n    int qh = 0, qt = 0;\n    q[qt++] = {si0, sj0};\n    vis_stamp[si0][sj0] = cur_stamp;\n    dista[si0][sj0] = 0;\n\n    double future_score = 0.0;\n    int reach_cnt = 0;\n    int frontier_sum = 0;\n\n    while (qh < qt && reach_cnt < node_cap) {\n        auto [i, j] = q[qh++];\n        int d = dista[i][j];\n        ++reach_cnt;\n\n        if (d > 0) future_score += pval[i][j] * decay[min(d, 63)];\n\n        int local_frontier = 0;\n        if (d < depth_limit) {\n            for (auto [ni, nj] : nbr[i][j]) {\n                if (usedTile[tid[ni][nj]]) continue;\n                ++local_frontier;\n                if (vis_stamp[ni][nj] == cur_stamp) continue;\n                vis_stamp[ni][nj] = cur_stamp;\n                dista[ni][nj] = d + 1;\n                q[qt++] = {ni, nj};\n            }\n        }\n        frontier_sum += local_frontier;\n    }\n\n    return {future_score, reach_cnt, frontier_sum};\n}\n\ndouble eval_move(int ni, int nj, int step_id, const vector<unsigned char>& usedTile, const Param& base) {\n    int mob = 0;\n    int mask = 0;\n    for (auto [xi, xj] : nbr[ni][nj]) {\n        if (usedTile[tid[xi][xj]]) continue;\n        ++mob;\n        int dd = -1;\n        if (xi == ni - 1) dd = 0;\n        else if (xi == ni + 1) dd = 1;\n        else if (xj == nj - 1) dd = 2;\n        else dd = 3;\n        mask |= 1 << dd;\n    }\n\n    EvalResult e = bfs_eval(ni, nj, usedTile, base.bfs_depth, base.bfs_cap);\n\n    double wg = phase_mix(base.w_gain * 0.90, base.w_gain, base.w_gain * 1.20, step_id);\n    double wf = phase_mix(base.w_future * 1.20, base.w_future, base.w_future * 0.70, step_id);\n    double wr = phase_mix(base.w_reach * 1.25, base.w_reach, base.w_reach * 0.65, step_id);\n    double wm = phase_mix(base.w_mob * 1.15, base.w_mob, base.w_mob * 0.75, step_id);\n    double wd = phase_mix(base.w_dead * 1.20, base.w_dead, base.w_dead * 0.65, step_id);\n    double ws = phase_mix(base.w_small * 1.15, base.w_small, base.w_small * 0.55, step_id);\n\n    double dead_pen = 0.0;\n    if (mob == 0) dead_pen = 1.0;\n    else if (mob == 1 && step_id < 1100) dead_pen = 0.65;\n    else if (mob == 2 && step_id < 850) {\n        bool opposite =\n            (mask == ((1 << 0) | (1 << 1))) ||\n            (mask == ((1 << 2) | (1 << 3)));\n        if (opposite) dead_pen = 0.22;\n    }\n\n    double small_pen = 0.0;\n    if (e.reach_cnt <= 10 && step_id < 1200) small_pen += (11 - e.reach_cnt);\n    if (e.reach_cnt <= 4 && step_id < 1200) small_pen += 5.0;\n\n    double end_bonus = 0.0;\n    if (e.reach_cnt <= 20) end_bonus += 0.35 * pval[ni][nj];\n    if (e.reach_cnt <= 8)  end_bonus += 0.25 * mob;\n\n    double sc = 0.0;\n    sc += wg * pval[ni][nj];\n    sc += wf * e.future_score;\n    sc += wr * e.reach_cnt;\n    sc += wm * mob;\n    sc += 0.10 * e.frontier_sum;\n    sc -= wd * dead_pen;\n    sc -= ws * small_pen;\n    sc += end_bonus;\n    return sc;\n}\n\nstring regrow_suffix(\n    int ci, int cj, int start_step,\n    vector<unsigned char>& usedTile,\n    const Param& par,\n    XorShift& rng,\n    int& gained_score\n) {\n    string suffix;\n    gained_score = 0;\n\n    while (true) {\n        vector<Cand> cand;\n        int step_id = start_step + (int)suffix.size();\n\n        for (int d = 0; d < 4; ++d) {\n            int ni = ci + (d == 0 ? -1 : d == 1 ? 1 : 0);\n            int nj = cj + (d == 2 ? -1 : d == 3 ? 1 : 0);\n            if (ni < 0 || ni >= N || nj < 0 || nj >= N) continue;\n            int nt = tid[ni][nj];\n            if (usedTile[nt]) continue;\n\n            usedTile[nt] = 1;\n            double sc = eval_move(ni, nj, step_id, usedTile, par);\n            usedTile[nt] = 0;\n            sc += (rng.next_double() - 0.5) * par.noise;\n\n            cand.push_back({d, ni, nj, sc});\n        }\n\n        if (cand.empty()) break;\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            return a.score > b.score;\n        });\n\n        int K = min(3, (int)cand.size());\n        for (int idx = 0; idx < K; ++idx) {\n            int n1i = cand[idx].ni, n1j = cand[idx].nj;\n            int t1 = tid[n1i][n1j];\n            usedTile[t1] = 1;\n\n            double best2 = -1e100;\n            bool has2 = false;\n            for (auto [n2i, n2j] : nbr[n1i][n1j]) {\n                int t2 = tid[n2i][n2j];\n                if (usedTile[t2]) continue;\n\n                usedTile[t2] = 1;\n                double sc2 = eval_move(n2i, n2j, step_id + 1, usedTile, par);\n                usedTile[t2] = 0;\n\n                if (!has2 || sc2 > best2) best2 = sc2;\n                has2 = true;\n            }\n            if (has2) cand[idx].score += par.look2 * best2;\n            usedTile[t1] = 0;\n        }\n\n        sort(cand.begin(), cand.end(), [](const Cand& a, const Cand& b) {\n            return a.score > b.score;\n        });\n\n        int pick = 0;\n        double r = rng.next_double();\n        if ((int)cand.size() >= 2 && r < 0.10) pick = 1;\n        if ((int)cand.size() >= 3 && r < 0.02) pick = 2;\n\n        int d = cand[pick].dir;\n        ci += (d == 0 ? -1 : d == 1 ? 1 : 0);\n        cj += (d == 2 ? -1 : d == 3 ? 1 : 0);\n        usedTile[tid[ci][cj]] = 1;\n        suffix.push_back(\"UDLR\"[d]);\n        gained_score += pval[ci][cj];\n    }\n\n    return suffix;\n}\n\nvoid build_prefix_info(const string& path) {\n    int L = (int)path.size();\n    best_pos.assign(L + 1, {0, 0});\n    best_pref_score.assign(L + 1, 0);\n    best_step_value.assign(L + 1, 0);\n\n    int ci = si, cj = sj;\n    best_pos[0] = {ci, cj};\n    best_pref_score[0] = pval[ci][cj];\n    best_step_value[0] = pval[ci][cj];\n\n    for (int i = 0; i < L; ++i) {\n        char c = path[i];\n        if (c == 'U') --ci;\n        else if (c == 'D') ++ci;\n        else if (c == 'L') --cj;\n        else ++cj;\n        best_pos[i + 1] = {ci, cj};\n        best_step_value[i + 1] = pval[ci][cj];\n        best_pref_score[i + 1] = best_pref_score[i] + pval[ci][cj];\n    }\n}\n\nint choose_cut(XorShift& rng) {\n    int L = (int)best_path.size();\n    if (L < 20) return max(1, L / 2);\n\n    int mode = rng.next_int(0, 6);\n\n    if (mode == 0) {\n        int lo = max(1, L * 70 / 100);\n        int hi = max(lo + 1, L * 95 / 100);\n        return rng.next_int(lo, hi);\n    } else if (mode == 1) {\n        int lo = max(1, L * 45 / 100);\n        int hi = max(lo + 1, L * 75 / 100);\n        return rng.next_int(lo, hi);\n    } else if (mode == 2) {\n        int lo = max(1, L * 25 / 100);\n        int hi = max(lo + 1, L * 90 / 100);\n        return rng.next_int(lo, hi);\n    } else if (mode == 3) {\n        int lo = max(1, L * 15 / 100);\n        int hi = max(lo + 1, L * 50 / 100);\n        return rng.next_int(lo, hi);\n    } else if (mode == 4) {\n        // low local-window average\n        int lo = max(1, L * 30 / 100);\n        int hi = max(lo + 1, L * 90 / 100);\n        int win = min(40, max(10, L / 20));\n        vector<pair<double,int>> bads;\n        for (int c = lo; c < hi; c += max(3, win / 3)) {\n            int r = min(L, c + win);\n            double avg = 0.0;\n            for (int i = c + 1; i <= r; ++i) avg += best_step_value[i];\n            avg /= max(1, r - c);\n            bads.push_back({avg, c});\n        }\n        sort(bads.begin(), bads.end(), [](auto& a, auto& b) { return a.first < b.first; });\n        int take = min((int)bads.size(), 5);\n        if (take == 0) return rng.next_int(lo, hi);\n        return bads[rng.next_int(0, take)].second;\n    } else {\n        // low suffix average\n        int lo = max(1, L * 20 / 100);\n        int hi = max(lo + 1, L * 90 / 100);\n        vector<pair<double,int>> bads;\n        int step = max(5, L / 25);\n        for (int c = lo; c < hi; c += step) {\n            int suffix_len = L - c;\n            if (suffix_len <= 0) continue;\n            int suffix_score = best_pref_score[L] - best_pref_score[c];\n            double avg = 1.0 * suffix_score / suffix_len;\n            bads.push_back({avg, c});\n        }\n        sort(bads.begin(), bads.end(), [](auto& a, auto& b) { return a.first < b.first; });\n        int take = min((int)bads.size(), 5);\n        if (take == 0) return rng.next_int(lo, hi);\n        return bads[rng.next_int(0, take)].second;\n    }\n}\n\nParam perturbed_param(const Param& src, XorShift& rng) {\n    Param par = src;\n    par.w_gain += (rng.next_double() - 0.5) * 0.08;\n    par.w_future += (rng.next_double() - 0.5) * 0.015;\n    par.w_reach += (rng.next_double() - 0.5) * 0.16;\n    par.w_mob += (rng.next_double() - 0.5) * 1.6;\n    par.w_dead += (rng.next_double() - 0.5) * 4.0;\n    par.w_small += (rng.next_double() - 0.5) * 0.5;\n    par.look2 += (rng.next_double() - 0.5) * 0.06;\n    return par;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> si >> sj;\n    int mx = -1;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            cin >> tid[i][j];\n            mx = max(mx, tid[i][j]);\n        }\n    }\n    tile_cnt = mx + 1;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) cin >> pval[i][j];\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (i > 0) nbr[i][j].push_back({i - 1, j});\n            if (i + 1 < N) nbr[i][j].push_back({i + 1, j});\n            if (j > 0) nbr[i][j].push_back({i, j - 1});\n            if (j + 1 < N) nbr[i][j].push_back({i, j + 1});\n        }\n    }\n\n    vector<Param> params = {\n        {1.00, 0.090, 1.20, 10.0, 26.0, 2.8, 0.34, 1.2, 11, 130},\n        {0.92, 0.105, 1.35, 12.5, 30.0, 3.1, 0.38, 1.0, 12, 145},\n        {1.16, 0.072, 0.92,  7.2, 21.0, 2.2, 0.28, 1.5, 10, 110},\n        {0.97, 0.098, 1.28, 11.2, 29.0, 3.0, 0.36, 1.1, 12, 140},\n        {1.05, 0.082, 1.08,  8.8, 24.0, 2.6, 0.33, 1.3, 11, 125},\n        {1.12, 0.078, 1.00,  8.0, 22.0, 2.4, 0.31, 1.4, 10, 120},\n        {0.95, 0.102, 1.30, 11.8, 28.5, 3.0, 0.37, 1.0, 12, 150},\n        {1.18, 0.068, 0.88,  6.8, 20.5, 2.1, 0.27, 1.6, 10, 105}\n    };\n\n    Timer timer;\n    XorShift rng;\n\n    best_path = \"\";\n    best_score = pval[si][sj];\n    vector<unsigned char> usedTile(tile_cnt, 0);\n\n    // Construction phase\n    while (timer.elapsed() < 0.85) {\n        Param par = perturbed_param(params[rng.next_int(0, 6)], rng);\n        fill(usedTile.begin(), usedTile.end(), 0);\n        int ci = si, cj = sj;\n        usedTile[tid[ci][cj]] = 1;\n        int gained = 0;\n        string path = regrow_suffix(ci, cj, 0, usedTile, par, rng, gained);\n        int score = pval[si][sj] + gained;\n\n        if (score > best_score) {\n            best_score = score;\n            best_path = path;\n            build_prefix_info(best_path);\n        }\n    }\n\n    if (best_path.empty()) build_prefix_info(best_path);\n\n    // Improvement phase\n    while (timer.elapsed() < 1.90) {\n        int L = (int)best_path.size();\n        if (L < 20) break;\n\n        int cut = choose_cut(rng);\n\n        vector<unsigned char> used(tile_cnt, 0);\n        for (int i = 0; i <= cut; ++i) {\n            auto [x, y] = best_pos[i];\n            used[tid[x][y]] = 1;\n        }\n\n        auto [ci, cj] = best_pos[cut];\n        int prefix_score = best_pref_score[cut];\n        string prefix = best_path.substr(0, cut);\n\n        int tries = 2 + (rng.next_double() < 0.40 ? 1 : 0);\n        int local_best_score = best_score;\n        string local_best_path;\n\n        for (int t = 0; t < tries; ++t) {\n            vector<unsigned char> used2 = used;\n            int pid = (t == 1 ? 6 + rng.next_int(0, 2) : rng.next_int(0, (int)params.size()));\n            Param par = perturbed_param(params[pid], rng);\n\n            int gained = 0;\n            string suffix = regrow_suffix(ci, cj, cut, used2, par, rng, gained);\n            int score = prefix_score + gained;\n\n            if (score > local_best_score) {\n                local_best_score = score;\n                local_best_path = prefix + suffix;\n            }\n        }\n\n        if (!local_best_path.empty() && local_best_score > best_score) {\n            best_score = local_best_score;\n            best_path = local_best_path;\n            build_prefix_info(best_path);\n        }\n    }\n\n    cout << best_path << '\\n';\n    return 0;\n}","ahc003":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int HN = 29;\nstatic constexpr int VN = 29;\nstatic constexpr int V = 900;\n\nstatic constexpr double INIT_COST = 5000.0;\nstatic constexpr double MIN_COST = 500.0;\nstatic constexpr double MAX_COST = 9500.0;\n\nstruct EdgeRef {\n    bool horiz; // true: h[i][j], false: v[i][j]\n    int i, j;\n};\n\nstruct Solver {\n    double h_est[N][HN], v_est[VN][N];\n    double h_prior[N][HN], v_prior[VN][N];\n    double h_sum[N][HN], v_sum[VN][N];\n    int h_cnt[N][HN], v_cnt[VN][N];\n\n    double row_base[N], col_base[N];\n    int row_cnt[N], col_cnt[N];\n\n    int turn = 0;\n\n    Solver() {\n        for (int i = 0; i < N; i++) {\n            row_base[i] = INIT_COST;\n            col_base[i] = INIT_COST;\n            row_cnt[i] = 0;\n            col_cnt[i] = 0;\n        }\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = INIT_COST;\n                h_prior[i][j] = INIT_COST;\n                h_sum[i][j] = 0.0;\n                h_cnt[i][j] = 0;\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = INIT_COST;\n                v_prior[i][j] = INIT_COST;\n                v_sum[i][j] = 0.0;\n                v_cnt[i][j] = 0;\n            }\n        }\n    }\n\n    static double clamp_cost(double x) {\n        return max(MIN_COST, min(MAX_COST, x));\n    }\n\n    void rebuild_bases() {\n        // horizontal row base\n        for (int i = 0; i < N; i++) {\n            double sw = 0.0, s = 0.0;\n            for (int j = 0; j < HN; j++) {\n                double w = 1.0 + 0.25 * h_cnt[i][j];\n                sw += w;\n                s += w * h_est[i][j];\n            }\n            row_base[i] = clamp_cost(s / sw);\n        }\n\n        // vertical column base\n        for (int j = 0; j < N; j++) {\n            double sw = 0.0, s = 0.0;\n            for (int i = 0; i < VN; i++) {\n                double w = 1.0 + 0.25 * v_cnt[i][j];\n                sw += w;\n                s += w * v_est[i][j];\n            }\n            col_base[j] = clamp_cost(s / sw);\n        }\n    }\n\n    // weighted 1-or-2 segment fitting for rows/cols\n    void rebuild_priors() {\n        // horizontal rows\n        for (int i = 0; i < N; i++) {\n            double a[HN], w[HN];\n            for (int j = 0; j < HN; j++) {\n                a[j] = h_est[i][j];\n                w[j] = 1.0 + 0.25 * h_cnt[i][j];\n            }\n\n            double sw[HN + 1] = {}, swa[HN + 1] = {}, swa2[HN + 1] = {};\n            for (int j = 0; j < HN; j++) {\n                sw[j + 1] = sw[j] + w[j];\n                swa[j + 1] = swa[j] + w[j] * a[j];\n                swa2[j + 1] = swa2[j] + w[j] * a[j] * a[j];\n            }\n\n            auto seg = [&](int l, int r) -> pair<double,double> {\n                double W = sw[r] - sw[l];\n                double S = swa[r] - swa[l];\n                double S2 = swa2[r] - swa2[l];\n                double mean = S / W;\n                double cost = S2 - 2.0 * mean * S + mean * mean * W;\n                return {cost, mean};\n            };\n\n            auto [bestCost, mean1] = seg(0, HN);\n            int bestSplit = -1;\n            double bestL = mean1, bestR = mean1;\n\n            for (int sp = 1; sp < HN; sp++) {\n                auto [c1, m1] = seg(0, sp);\n                auto [c2, m2] = seg(sp, HN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestL = m1;\n                    bestR = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int j = 0; j < HN; j++) h_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int j = 0; j < bestSplit; j++) h_prior[i][j] = clamp_cost(bestL);\n                for (int j = bestSplit; j < HN; j++) h_prior[i][j] = clamp_cost(bestR);\n            }\n        }\n\n        // vertical columns\n        for (int j = 0; j < N; j++) {\n            double a[VN], w[VN];\n            for (int i = 0; i < VN; i++) {\n                a[i] = v_est[i][j];\n                w[i] = 1.0 + 0.25 * v_cnt[i][j];\n            }\n\n            double sw[VN + 1] = {}, swa[VN + 1] = {}, swa2[VN + 1] = {};\n            for (int i = 0; i < VN; i++) {\n                sw[i + 1] = sw[i] + w[i];\n                swa[i + 1] = swa[i] + w[i] * a[i];\n                swa2[i + 1] = swa2[i] + w[i] * a[i] * a[i];\n            }\n\n            auto seg = [&](int l, int r) -> pair<double,double> {\n                double W = sw[r] - sw[l];\n                double S = swa[r] - swa[l];\n                double S2 = swa2[r] - swa2[l];\n                double mean = S / W;\n                double cost = S2 - 2.0 * mean * S + mean * mean * W;\n                return {cost, mean};\n            };\n\n            auto [bestCost, mean1] = seg(0, VN);\n            int bestSplit = -1;\n            double bestU = mean1, bestD = mean1;\n\n            for (int sp = 1; sp < VN; sp++) {\n                auto [c1, m1] = seg(0, sp);\n                auto [c2, m2] = seg(sp, VN);\n                double c = c1 + c2;\n                if (c < bestCost) {\n                    bestCost = c;\n                    bestSplit = sp;\n                    bestU = m1;\n                    bestD = m2;\n                }\n            }\n\n            if (bestSplit == -1) {\n                for (int i = 0; i < VN; i++) v_prior[i][j] = clamp_cost(mean1);\n            } else {\n                for (int i = 0; i < bestSplit; i++) v_prior[i][j] = clamp_cost(bestU);\n                for (int i = bestSplit; i < VN; i++) v_prior[i][j] = clamp_cost(bestD);\n            }\n        }\n    }\n\n    double local_weight(int cnt) const {\n        double w = 0.10 + 0.72 * (1.0 - exp(-cnt / 5.0));\n        if (turn < 50) w *= 0.75;\n        return min(0.85, max(0.07, w));\n    }\n\n    double base_weight(int cnt) const {\n        // more helpful when local count is still small\n        double w = 0.28 * exp(-cnt / 7.0);\n        return w;\n    }\n\n    double exploration_bonus(int cnt) const {\n        if (turn >= 120) return 0.0;\n        return 220.0 / sqrt(cnt + 1.0);\n    }\n\n    double blended_h(int i, int j) const {\n        double wl = local_weight(h_cnt[i][j]);\n        double wb = base_weight(h_cnt[i][j]);\n        double wp = 1.0 - wl - wb;\n        double val = wl * h_est[i][j] + wp * h_prior[i][j] + wb * row_base[i];\n        val -= exploration_bonus(h_cnt[i][j]);\n        return clamp_cost(val);\n    }\n\n    double blended_v(int i, int j) const {\n        double wl = local_weight(v_cnt[i][j]);\n        double wb = base_weight(v_cnt[i][j]);\n        double wp = 1.0 - wl - wb;\n        double val = wl * v_est[i][j] + wp * v_prior[i][j] + wb * col_base[j];\n        val -= exploration_bonus(v_cnt[i][j]);\n        return clamp_cost(val);\n    }\n\n    int vid(int i, int j) const { return i * N + j; }\n    pair<int,int> pos(int id) const { return {id / N, id % N}; }\n\n    pair<string, vector<EdgeRef>> shortest_path(int si, int sj, int ti, int tj) {\n        static double dist[V];\n        static int prev[V];\n        static char pm[V];\n\n        for (int i = 0; i < V; i++) {\n            dist[i] = 1e100;\n            prev[i] = -1;\n            pm[i] = '?';\n        }\n\n        using P = pair<double,int>;\n        priority_queue<P, vector<P>, greater<P>> pq;\n\n        int s = vid(si, sj), t = vid(ti, tj);\n        dist[s] = 0.0;\n        pq.push({0.0, s});\n\n        while (!pq.empty()) {\n            auto [d, u] = pq.top();\n            pq.pop();\n            if (d != dist[u]) continue;\n            if (u == t) break;\n\n            auto [i, j] = pos(u);\n\n            if (i > 0) {\n                int v = vid(i - 1, j);\n                double w = blended_v(i - 1, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'U';\n                    pq.push({dist[v], v});\n                }\n            }\n            if (i + 1 < N) {\n                int v = vid(i + 1, j);\n                double w = blended_v(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'D';\n                    pq.push({dist[v], v});\n                }\n            }\n            if (j > 0) {\n                int v = vid(i, j - 1);\n                double w = blended_h(i, j - 1);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'L';\n                    pq.push({dist[v], v});\n                }\n            }\n            if (j + 1 < N) {\n                int v = vid(i, j + 1);\n                double w = blended_h(i, j);\n                if (dist[v] > d + w) {\n                    dist[v] = d + w;\n                    prev[v] = u;\n                    pm[v] = 'R';\n                    pq.push({dist[v], v});\n                }\n            }\n        }\n\n        string path;\n        vector<EdgeRef> edges_rev;\n        int cur = t;\n        while (cur != s) {\n            char mv = pm[cur];\n            path.push_back(mv);\n            auto [i, j] = pos(cur);\n            if (mv == 'U') edges_rev.push_back({false, i, j});\n            else if (mv == 'D') edges_rev.push_back({false, i - 1, j});\n            else if (mv == 'L') edges_rev.push_back({true, i, j});\n            else if (mv == 'R') edges_rev.push_back({true, i, j - 1});\n            else break;\n            cur = prev[cur];\n        }\n        reverse(path.begin(), path.end());\n        reverse(edges_rev.begin(), edges_rev.end());\n        return {path, edges_rev};\n    }\n\n    double path_pred_cost(const vector<EdgeRef>& edges) const {\n        double s = 0.0;\n        for (const auto &e : edges) {\n            s += e.horiz ? blended_h(e.i, e.j) : blended_v(e.i, e.j);\n        }\n        return s;\n    }\n\n    void update_from_feedback(const vector<EdgeRef>& edges, int observed) {\n        if (edges.empty()) return;\n\n        int row_used[N] = {};\n        int col_used[N] = {};\n        int h_total = 0, v_total = 0;\n\n        for (const auto &e : edges) {\n            if (e.horiz) {\n                row_used[e.i]++;\n                h_total++;\n            } else {\n                col_used[e.j]++;\n                v_total++;\n            }\n        }\n\n        double pred = path_pred_cost(edges);\n        pred = max(pred, 1.0);\n        int L = (int)edges.size();\n\n        double ratio = observed / pred;\n        ratio = max(0.83, min(1.20, ratio));\n\n        double add = (observed - pred) / L;\n        add = max(-900.0, min(900.0, add));\n\n        double lr_mul = (turn < 100 ? 0.22 : turn < 300 ? 0.16 : 0.12);\n        double lr_add = (turn < 100 ? 0.05 : turn < 300 ? 0.035 : 0.025);\n        double lr_row = (turn < 120 ? 0.030 : 0.018);\n        double lr_col = (turn < 120 ? 0.030 : 0.018);\n\n        // Row / column aggregate update\n        if (h_total > 0) {\n            for (int i = 0; i < N; i++) if (row_used[i] > 0) {\n                double frac = row_used[i] / (double)h_total;\n                double target = row_base[i] + frac * (observed - pred) / max(1, row_used[i]);\n                row_base[i] = clamp_cost((1.0 - lr_row) * row_base[i] + lr_row * target);\n                row_cnt[i] += row_used[i];\n            }\n        }\n        if (v_total > 0) {\n            for (int j = 0; j < N; j++) if (col_used[j] > 0) {\n                double frac = col_used[j] / (double)v_total;\n                double target = col_base[j] + frac * (observed - pred) / max(1, col_used[j]);\n                col_base[j] = clamp_cost((1.0 - lr_col) * col_base[j] + lr_col * target);\n                col_cnt[j] += col_used[j];\n            }\n        }\n\n        // Local edge updates\n        for (const auto &e : edges) {\n            if (e.horiz) {\n                double cur = h_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = cur + add;\n                double target3 = row_base[e.i];\n                double nv = (1.0 - lr_mul) * cur + lr_mul * target1;\n                nv = (1.0 - lr_add) * nv + lr_add * target2;\n                nv = 0.97 * nv + 0.03 * target3;\n                h_est[e.i][e.j] = clamp_cost(nv);\n\n                h_sum[e.i][e.j] += observed / (double)L;\n                h_cnt[e.i][e.j]++;\n            } else {\n                double cur = v_est[e.i][e.j];\n                double target1 = cur * ratio;\n                double target2 = cur + add;\n                double target3 = col_base[e.j];\n                double nv = (1.0 - lr_mul) * cur + lr_mul * target1;\n                nv = (1.0 - lr_add) * nv + lr_add * target2;\n                nv = 0.97 * nv + 0.03 * target3;\n                v_est[e.i][e.j] = clamp_cost(nv);\n\n                v_sum[e.i][e.j] += observed / (double)L;\n                v_cnt[e.i][e.j]++;\n            }\n        }\n\n        // Weak empirical averaging on enough-visited edges\n        for (const auto &e : edges) {\n            if (e.horiz) {\n                if (h_cnt[e.i][e.j] >= 6) {\n                    double mean = h_sum[e.i][e.j] / h_cnt[e.i][e.j];\n                    h_est[e.i][e.j] = clamp_cost(0.95 * h_est[e.i][e.j] + 0.05 * mean);\n                }\n            } else {\n                if (v_cnt[e.i][e.j] >= 6) {\n                    double mean = v_sum[e.i][e.j] / v_cnt[e.i][e.j];\n                    v_est[e.i][e.j] = clamp_cost(0.95 * v_est[e.i][e.j] + 0.05 * mean);\n                }\n            }\n        }\n\n        // rebuild structured models\n        if (turn < 150 || turn % 5 == 4) {\n            rebuild_bases();\n            rebuild_priors();\n        }\n\n        // gentle smoothing\n        double smooth = (turn < 150 ? 0.012 : 0.006);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < HN; j++) {\n                h_est[i][j] = clamp_cost((1.0 - smooth) * h_est[i][j] + smooth * (0.7 * h_prior[i][j] + 0.3 * row_base[i]));\n            }\n        }\n        for (int i = 0; i < VN; i++) {\n            for (int j = 0; j < N; j++) {\n                v_est[i][j] = clamp_cost((1.0 - smooth) * v_est[i][j] + smooth * (0.7 * v_prior[i][j] + 0.3 * col_base[j]));\n            }\n        }\n    }\n\n    void solve() {\n        rebuild_bases();\n        rebuild_priors();\n\n        for (turn = 0; turn < 1000; turn++) {\n            int si, sj, ti, tj;\n            cin >> si >> sj >> ti >> tj;\n\n            auto [path, edges] = shortest_path(si, sj, ti, tj);\n\n            cout << path << '\\n';\n            cout.flush();\n\n            int observed;\n            cin >> observed;\n            update_from_feedback(edges, observed);\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}","ahc004":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\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 rand01() {\n        return (next() >> 11) * (1.0 / (1ull << 53));\n    }\n} rng;\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 Pattern {\n    string s;\n    int w;\n};\n\nstruct Candidate {\n    string line;               // length 20\n    vector<uint64_t> bits;     // covered unique patterns\n    int coverWeight = 0;       // sum of weights of covered unique patterns\n};\n\nint Nin, M;\nvector<Pattern> pats;\nint P;\n\ninline int cid(char c) { return c - 'A'; }\n\nbool contains_cyclic_line(const string& line, const string& s) {\n    int L = (int)s.size();\n    for (int st = 0; st < N; st++) {\n        bool ok = true;\n        for (int k = 0; k < L; k++) {\n            if (line[(st + k) % N] != s[k]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return true;\n    }\n    return false;\n}\n\nstring minimal_rotation(string s) {\n    // Booth O(n^2) is fine for n=20, but implement simple O(n^2)\n    string best = s;\n    for (int i = 1; i < (int)s.size(); i++) {\n        string t = s.substr(i) + s.substr(0, i);\n        if (t < best) best = t;\n    }\n    return best;\n}\n\nint overlap_suffix_prefix(const string& a, const string& b) {\n    int mx = min((int)a.size(), (int)b.size());\n    for (int k = mx; k >= 1; k--) {\n        bool ok = true;\n        for (int i = 0; i < k; i++) {\n            if (a[(int)a.size() - k + i] != b[i]) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) return k;\n    }\n    return 0;\n}\n\nbool is_substring_noncyclic(const string& a, const string& b) {\n    // is a substring of b\n    return b.find(a) != string::npos;\n}\n\nstring fill_to_20(const string& base, const vector<Pattern>& pats, bool randomize) {\n    if ((int)base.size() >= N) return base.substr(0, N);\n    string s = base;\n    while ((int)s.size() < N) {\n        array<long long, 8> score{};\n        score.fill(1);\n        int pos = (int)s.size();\n        for (auto &p : pats) {\n            const string& t = p.s;\n            for (int st = max(0, pos - (int)t.size() + 1); st <= pos; st++) {\n                int k = pos - st;\n                if (st < 0 || k < 0 || k >= (int)t.size()) continue;\n                bool ok = true;\n                for (int i = 0; i < pos - st; i++) {\n                    if (st + i < (int)s.size() && s[st + i] != t[i]) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (ok) score[cid(t[k])] += p.w;\n            }\n        }\n        int bestc = 0;\n        if (randomize && rng.rand01() < 0.25) {\n            long long sum = 0;\n            for (int c = 0; c < 8; c++) sum += score[c];\n            long long r = rng.next() % sum;\n            long long acc = 0;\n            for (int c = 0; c < 8; c++) {\n                acc += score[c];\n                if (r < acc) { bestc = c; break; }\n            }\n        } else {\n            for (int c = 1; c < 8; c++) if (score[c] > score[bestc]) bestc = c;\n        }\n        s.push_back(char('A' + bestc));\n    }\n    return s;\n}\n\nCandidate make_candidate(const string& line) {\n    Candidate c;\n    c.line = minimal_rotation(line);\n    c.bits.assign((P + 63) >> 6, 0ULL);\n    int sw = 0;\n    for (int i = 0; i < P; i++) {\n        if (contains_cyclic_line(c.line, pats[i].s)) {\n            c.bits[i >> 6] |= 1ULL << (i & 63);\n            sw += pats[i].w;\n        }\n    }\n    c.coverWeight = sw;\n    return c;\n}\n\nvector<Candidate> generate_candidates(double time_limit) {\n    Timer timer;\n    vector<Candidate> cands;\n    unordered_set<string> seen;\n    seen.reserve(4096);\n\n    auto add_candidate = [&](const string& raw) {\n        string line = minimal_rotation(raw.substr(0, N));\n        if (seen.insert(line).second) {\n            cands.push_back(make_candidate(line));\n        }\n    };\n\n    // sort patterns by value\n    vector<int> ord(P);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        long long va = 1LL * pats[a].w * (int)pats[a].s.size() * (int)pats[a].s.size();\n        long long vb = 1LL * pats[b].w * (int)pats[b].s.size() * (int)pats[b].s.size();\n        if (va != vb) return va > vb;\n        return pats[a].s.size() > pats[b].s.size();\n    });\n\n    // deterministic top seeds\n    int topSeeds = min(P, 120);\n    for (int si = 0; si < topSeeds; si++) {\n        string cur = pats[ord[si]].s;\n        vector<int> used(P, 0);\n        used[ord[si]] = 1;\n\n        while ((int)cur.size() < N) {\n            long long bestScore = -1;\n            int bestj = -1;\n            bool bestAppend = true;\n            int bestOv = 0;\n\n            for (int t = 0; t < min(P, 200); t++) {\n                int j = ord[t];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = true;\n                        bestOv = ov1;\n                    }\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size();\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestj = j;\n                        bestAppend = false;\n                        bestOv = ov2;\n                    }\n                }\n            }\n\n            if (bestj == -1) break;\n            used[bestj] = 1;\n            const string& s = pats[bestj].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (bestAppend) cur += s.substr(bestOv);\n            else cur = s + cur.substr(bestOv);\n        }\n        add_candidate(fill_to_20(cur, pats, false));\n    }\n\n    // randomized builds\n    while (timer.elapsed() < time_limit) {\n        int seed = ord[rng.randint(0, min(P, 80) - 1)];\n        string cur = pats[seed].s;\n        vector<int> used(P, 0);\n        used[seed] = 1;\n\n        int steps = rng.randint(8, 20);\n        for (int step = 0; step < steps && (int)cur.size() < N; step++) {\n            vector<pair<long long, tuple<int,bool,int>>> opts;\n            int pool = min(P, 180);\n            for (int it = 0; it < pool; it++) {\n                int j = ord[it];\n                if (used[j]) continue;\n                const string& s = pats[j].s;\n\n                int ov1 = overlap_suffix_prefix(cur, s);\n                int len1 = (int)cur.size() + (int)s.size() - ov1;\n                if (len1 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov1 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, true, ov1}});\n                }\n\n                int ov2 = overlap_suffix_prefix(s, cur);\n                int len2 = (int)s.size() + (int)cur.size() - ov2;\n                if (len2 <= N) {\n                    long long sc = 1LL * pats[j].w * (ov2 + 1) * (int)s.size() + rng.randint(0, 20);\n                    if (is_substring_noncyclic(s, cur)) sc += 1LL * pats[j].w * 1000;\n                    opts.push_back({sc, {j, false, ov2}});\n                }\n            }\n            if (opts.empty()) break;\n            nth_element(opts.begin(),\n                        opts.begin() + min<int>(opts.size(), 5) - 1,\n                        opts.end(),\n                        [&](auto& a, auto& b){ return a.first > b.first; });\n            int pick = rng.randint(0, min<int>(opts.size(), 5) - 1);\n            auto [sc, tup] = opts[pick];\n            auto [j, app, ov] = tup;\n            used[j] = 1;\n            const string& s = pats[j].s;\n            if (is_substring_noncyclic(s, cur)) continue;\n            if (app) cur += s.substr(ov);\n            else cur = s + cur.substr(ov);\n        }\n        add_candidate(fill_to_20(cur, pats, true));\n    }\n\n    // single-pattern direct cyclic fills\n    for (int i = 0; i < min(P, 100); i++) {\n        add_candidate(fill_to_20(pats[ord[i]].s, pats, true));\n    }\n\n    return cands;\n}\n\nint total_weight_from_count(const vector<int>& cnt) {\n    int s = 0;\n    for (int i = 0; i < P; i++) if (cnt[i] > 0) s += pats[i].w;\n    return s;\n}\n\nvector<int> greedy_select_rows(const vector<Candidate>& cands) {\n    int C = (int)cands.size();\n    vector<int> selected;\n    vector<int> cnt(P, 0);\n    vector<char> used(C, 0);\n\n    for (int iter = 0; iter < N; iter++) {\n        int best = -1;\n        long long bestGain = -1;\n\n        for (int i = 0; i < C; i++) if (!used[i]) {\n            long long gain = 0;\n            for (int p = 0; p < P; p++) {\n                if (cnt[p] == 0) {\n                    if ((cands[i].bits[p >> 6] >> (p & 63)) & 1ULL) gain += pats[p].w;\n                }\n            }\n            // slight diversity bonus\n            gain += cands[i].coverWeight / 50;\n            if (gain > bestGain) {\n                bestGain = gain;\n                best = i;\n            }\n        }\n\n        if (best == -1) best = 0;\n        used[best] = 1;\n        selected.push_back(best);\n        for (int p = 0; p < P; p++) {\n            if ((cands[best].bits[p >> 6] >> (p & 63)) & 1ULL) cnt[p]++;\n        }\n    }\n    return selected;\n}\n\nint evaluate_grid(const vector<string>& g) {\n    vector<string> cols(N, string(N, 'A'));\n    for (int j = 0; j < N; j++) for (int i = 0; i < N; i++) cols[j][i] = g[i][j];\n\n    int score = 0;\n    for (int p = 0; p < P; p++) {\n        bool ok = false;\n        for (int i = 0; i < N && !ok; i++) if (contains_cyclic_line(g[i], pats[p].s)) ok = true;\n        for (int j = 0; j < N && !ok; j++) if (contains_cyclic_line(cols[j], pats[p].s)) ok = true;\n        if (ok) score += pats[p].w;\n    }\n    return score;\n}\n\nvector<string> rows_from_selection(const vector<Candidate>& cands, const vector<int>& sel) {\n    vector<string> g(N);\n    for (int i = 0; i < N; i++) g[i] = cands[sel[i]].line;\n    return g;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> Nin >> M;\n    vector<string> input(M);\n    for (int i = 0; i < M; i++) cin >> input[i];\n\n    unordered_map<string, int> mp;\n    mp.reserve(M * 2);\n    for (auto &s : input) mp[s]++;\n\n    pats.clear();\n    pats.reserve(mp.size());\n    for (auto &kv : mp) pats.push_back({kv.first, kv.second});\n    P = (int)pats.size();\n\n    sort(pats.begin(), pats.end(), [&](const Pattern& a, const Pattern& b) {\n        long long va = 1LL * a.w * (int)a.s.size() * (int)a.s.size();\n        long long vb = 1LL * b.w * (int)b.s.size() * (int)b.s.size();\n        if (va != vb) return va > vb;\n        if (a.s.size() != b.s.size()) return a.s.size() > b.s.size();\n        return a.s < b.s;\n    });\n\n    Timer allTimer;\n\n    // Phase 1: generate candidate lines\n    auto cands = generate_candidates(0.9);\n    if (cands.empty()) {\n        string s(N, 'A');\n        for (int i = 0; i < N; i++) cout << s << '\\n';\n        return 0;\n    }\n\n    // Phase 2: select 20 rows greedily\n    auto sel = greedy_select_rows(cands);\n    vector<string> bestGrid = rows_from_selection(cands, sel);\n    int bestScore = evaluate_grid(bestGrid);\n\n    // Phase 3: row replacement local improvement\n    {\n        vector<int> curSel = sel;\n        vector<string> curGrid = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 1.6) {\n            int pos = rng.randint(0, N - 1);\n            int candId = rng.randint(0, (int)cands.size() - 1);\n\n            int old = curSel[pos];\n            if (old == candId) continue;\n            curSel[pos] = candId;\n            curGrid[pos] = cands[candId].line;\n\n            int sc = evaluate_grid(curGrid);\n            if (sc >= curScore || rng.rand01() < 0.01) {\n                curScore = sc;\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestGrid = curGrid;\n                }\n            } else {\n                curSel[pos] = old;\n                curGrid[pos] = cands[old].line;\n            }\n        }\n    }\n\n    // Phase 4: cell-wise hill climbing\n    {\n        vector<string> cur = bestGrid;\n        int curScore = bestScore;\n\n        while (allTimer.elapsed() < 2.95) {\n            int i = rng.randint(0, N - 1);\n            int j = rng.randint(0, N - 1);\n            char oldc = cur[i][j];\n\n            char bestc = oldc;\n            int localBest = curScore;\n\n            array<int, 8> perm{};\n            iota(perm.begin(), perm.end(), 0);\n            shuffle(perm.begin(), perm.end(), std::mt19937((uint32_t)rng.next()));\n\n            int tries = 4;\n            for (int t = 0; t < tries; t++) {\n                char nc = char('A' + perm[t]);\n                if (nc == oldc) continue;\n                cur[i][j] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc > localBest || (sc == localBest && rng.rand01() < 0.05)) {\n                    localBest = sc;\n                    bestc = nc;\n                }\n            }\n\n            cur[i][j] = bestc;\n            curScore = localBest;\n\n            if (curScore > bestScore) {\n                bestScore = curScore;\n                bestGrid = cur;\n            }\n\n            // rare random kick\n            if (rng.rand01() < 0.01) {\n                int x = rng.randint(0, N - 1), y = rng.randint(0, N - 1);\n                char nc = char('A' + rng.randint(0, 7));\n                char bak = cur[x][y];\n                cur[x][y] = nc;\n                int sc = evaluate_grid(cur);\n                if (sc >= curScore || rng.rand01() < 0.2) {\n                    curScore = sc;\n                    if (sc > bestScore) {\n                        bestScore = sc;\n                        bestGrid = cur;\n                    }\n                } else {\n                    cur[x][y] = bak;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        cout << bestGrid[i] << '\\n';\n    }\n    return 0;\n}","ahc005":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int INF = 1e9;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n};\n\nstatic inline double now_sec() {\n    using namespace std::chrono;\n    return duration_cast<duration<double>>(steady_clock::now().time_since_epoch()).count();\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    vector<string> C(N);\n    for (int i = 0; i < N; i++) cin >> C[i];\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n    auto road = [&](int x, int y) -> bool {\n        return inb(x, y) && C[x][y] != '#';\n    };\n    auto w = [&](int x, int y) -> int {\n        return C[x][y] - '0';\n    };\n\n    const int dx[4] = {-1, 1, 0, 0};\n    const int dy[4] = {0, 0, -1, 1};\n\n    vector<Pos> roads;\n    vector<vector<int>> rid(N, vector<int>(N, -1));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n        if (road(i, j)) {\n            rid[i][j] = (int)roads.size();\n            roads.push_back({i, j});\n        }\n    }\n    int R = (int)roads.size();\n\n    vector<vector<int>> deg(N, vector<int>(N, 0));\n    for (auto &p : roads) {\n        int d = 0;\n        for (int k = 0; k < 4; k++) if (road(p.x + dx[k], p.y + dy[k])) d++;\n        deg[p.x][p.y] = d;\n    }\n\n    auto is_corner = [&](int x, int y) -> bool {\n        if (!road(x, y) || deg[x][y] != 2) return false;\n        bool ud = road(x - 1, y) && road(x + 1, y);\n        bool lr = road(x, y - 1) && road(x, y + 1);\n        return !(ud || lr);\n    };\n    auto is_important = [&](int x, int y) -> bool {\n        if (x == si && y == sj) return true;\n        if (deg[x][y] != 2) return true;\n        return is_corner(x, y);\n    };\n\n    vector<vector<int>> visAll(R);\n    vector<int> visAllScore(R);\n    for (auto &p : roads) {\n        int id = rid[p.x][p.y];\n        vector<int> tmp;\n        tmp.push_back(id);\n        for (int dir = 0; dir < 4; dir++) {\n            int nx = p.x, ny = p.y;\n            while (true) {\n                nx += dx[dir];\n                ny += dy[dir];\n                if (!road(nx, ny)) break;\n                tmp.push_back(rid[nx][ny]);\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());\n        visAll[id] = move(tmp);\n        visAllScore[id] = (int)visAll[id].size();\n    }\n\n    vector<Pos> cand;\n    vector<vector<int>> cid(N, vector<int>(N, -1));\n\n    auto add_candidate = [&](int x, int y) {\n        if (!road(x, y)) return;\n        if (cid[x][y] != -1) return;\n        cid[x][y] = (int)cand.size();\n        cand.push_back({x, y});\n    };\n\n    for (auto &p : roads) if (is_important(p.x, p.y)) add_candidate(p.x, p.y);\n\n    for (int i = 0; i < N; i++) {\n        int j = 0;\n        while (j < N) {\n            if (!road(i, j)) { j++; continue; }\n            int k = j;\n            while (k < N && road(i, k)) k++;\n            int len = k - j;\n            if (len >= 6) {\n                for (int y = j + 2; y <= k - 3; y += 3) add_candidate(i, y);\n            }\n            j = k;\n        }\n    }\n    for (int j = 0; j < N; j++) {\n        int i = 0;\n        while (i < N) {\n            if (!road(i, j)) { i++; continue; }\n            int k = i;\n            while (k < N && road(k, j)) k++;\n            int len = k - i;\n            if (len >= 6) {\n                for (int x = i + 2; x <= k - 3; x += 3) add_candidate(x, j);\n            }\n            i = k;\n        }\n    }\n\n    vector<int> ord(R);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        return visAllScore[a] > visAllScore[b];\n    });\n    int EXTRA = min(R, 100);\n    for (int i = 0; i < EXTRA; i++) {\n        auto p = roads[ord[i]];\n        add_candidate(p.x, p.y);\n    }\n\n    add_candidate(si, sj);\n    int M = (int)cand.size();\n    int start = cid[si][sj];\n\n    vector<vector<int>> visible(M);\n    vector<int> visScore(M);\n    for (int id = 0; id < M; id++) {\n        visible[id] = visAll[rid[cand[id].x][cand[id].y]];\n        visScore[id] = (int)visible[id].size();\n    }\n\n    vector<int> baseDist(M);\n    for (int i = 0; i < M; i++) baseDist[i] = abs(cand[i].x - si) + abs(cand[i].y - sj);\n\n    int NN = N * N;\n    auto vid = [&](int x, int y) { return x * N + y; };\n\n    vector<vector<int>> ccost(M, vector<int>(M, INF));\n    {\n        vector<int> dist(NN);\n        for (int s = 0; s < M; s++) {\n            fill(dist.begin(), dist.end(), INF);\n            int sv = vid(cand[s].x, cand[s].y);\n            priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n            dist[sv] = 0;\n            pq.push({0, sv});\n            while (!pq.empty()) {\n                auto [cd, v] = pq.top(); pq.pop();\n                if (cd != dist[v]) continue;\n                int x = v / N, y = v % N;\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + dx[k], ny = y + dy[k];\n                    if (!road(nx, ny)) continue;\n                    int nv = vid(nx, ny);\n                    int nd = cd + w(nx, ny);\n                    if (nd < dist[nv]) {\n                        dist[nv] = nd;\n                        pq.push({nd, nv});\n                    }\n                }\n            }\n            for (int t = 0; t < M; t++) ccost[s][t] = dist[vid(cand[t].x, cand[t].y)];\n        }\n    }\n\n    auto full_cover = [&](const vector<int>& tar) -> bool {\n        vector<char> cov(R, 0);\n        for (int id : tar) for (int r : visible[id]) cov[r] = 1;\n        for (int i = 0; i < R; i++) if (!cov[i]) return false;\n        return true;\n    };\n\n    auto prune_targets_exact = [&](vector<int> tar) {\n        vector<int> cnt(R, 0);\n        for (int id : tar) for (int r : visible[id]) cnt[r]++;\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            vector<pair<pair<int,int>, int>> order;\n            order.reserve(tar.size());\n            for (int id : tar) {\n                if (id == start) continue;\n                int uniq = 0;\n                for (int r : visible[id]) if (cnt[r] == 1) uniq++;\n                order.push_back({{uniq, -baseDist[id]}, id});\n            }\n            sort(order.begin(), order.end());\n\n            for (auto &e : order) {\n                int id = e.second;\n                bool ok = true;\n                for (int r : visible[id]) {\n                    if (cnt[r] <= 1) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n                for (int r : visible[id]) cnt[r]--;\n                vector<int> nt;\n                nt.reserve(tar.size() - 1);\n                for (int x : tar) if (x != id) nt.push_back(x);\n                tar.swap(nt);\n                changed = true;\n                break;\n            }\n        }\n        return tar;\n    };\n\n    XorShift rng;\n    double stime = now_sec();\n    double TL = 2.80;\n\n    vector<int> globalBestTargets;\n    vector<int> globalBestTour;\n    long long globalBestCost = (1LL << 60);\n\n    auto solve_on_targets = [&](const vector<int>& targetsInput) {\n        vector<int> targets = targetsInput;\n        sort(targets.begin(), targets.end());\n        targets.erase(unique(targets.begin(), targets.end()), targets.end());\n\n        int T = (int)targets.size();\n        int sidx = -1;\n        for (int i = 0; i < T; i++) if (targets[i] == start) sidx = i;\n\n        vector<vector<int>> d(T, vector<int>(T, INF));\n        for (int i = 0; i < T; i++) for (int j = 0; j < T; j++) d[i][j] = ccost[targets[i]][targets[j]];\n\n        auto tour_cost = [&](const vector<int>& tr) -> long long {\n            long long res = 0;\n            for (int i = 0; i + 1 < (int)tr.size(); i++) res += d[tr[i]][tr[i + 1]];\n            return res;\n        };\n\n        auto improve_tour = [&](vector<int>& tour) {\n            bool improved = true;\n            int loop = 0;\n            while (improved && loop < 10) {\n                improved = false;\n                loop++;\n\n                for (int i = 1; i + 2 < (int)tour.size(); i++) {\n                    for (int j = i + 1; j + 1 < (int)tour.size(); j++) {\n                        int a = tour[i - 1], b = tour[i];\n                        int c = tour[j], e = tour[j + 1];\n                        long long before = (long long)d[a][b] + d[c][e];\n                        long long after  = (long long)d[a][c] + d[b][e];\n                        if (after < before) {\n                            reverse(tour.begin() + i, tour.begin() + j + 1);\n                            improved = true;\n                        }\n                    }\n                }\n\n                for (int i = 1; i + 1 < (int)tour.size(); i++) {\n                    int x = tour[i];\n                    long long rem = (long long)d[tour[i - 1]][x] + d[x][tour[i + 1]] - d[tour[i - 1]][tour[i + 1]];\n                    int bestPos = -1;\n                    long long bestDelta = 0;\n                    for (int j = 0; j + 1 < (int)tour.size(); j++) {\n                        if (j == i || j + 1 == i) continue;\n                        long long add = (long long)d[tour[j]][x] + d[x][tour[j + 1]] - d[tour[j]][tour[j + 1]];\n                        long long delta = add - rem;\n                        if (delta < bestDelta) {\n                            bestDelta = delta;\n                            bestPos = j;\n                        }\n                    }\n                    if (bestPos != -1) {\n                        vector<int> nt = tour;\n                        nt.erase(nt.begin() + i);\n                        int ins = bestPos + 1;\n                        if (bestPos >= i) ins--;\n                        nt.insert(nt.begin() + ins, x);\n                        tour.swap(nt);\n                        improved = true;\n                        break;\n                    }\n                }\n\n                for (int i = 1; i + 1 < (int)tour.size() && !improved; i++) {\n                    for (int j = i + 1; j + 1 < (int)tour.size(); j++) {\n                        vector<int> nt = tour;\n                        swap(nt[i], nt[j]);\n                        if (tour_cost(nt) < tour_cost(tour)) {\n                            tour.swap(nt);\n                            improved = true;\n                            break;\n                        }\n                    }\n                }\n            }\n        };\n\n        auto build_cheapest_insertion = [&](int seedMode, bool randomized) {\n            vector<int> others;\n            for (int i = 0; i < T; i++) if (i != sidx) others.push_back(i);\n            if (others.empty()) return vector<int>{sidx, sidx};\n\n            int first = others[0];\n            if (seedMode == 0) {\n                int best = INF;\n                for (int x : others) {\n                    int val = d[sidx][x] + d[x][sidx];\n                    if (val < best) best = val, first = x;\n                }\n            } else if (seedMode == 1) {\n                int best = -1;\n                for (int x : others) {\n                    int val = d[sidx][x] + d[x][sidx];\n                    if (val > best) best = val, first = x;\n                }\n            } else {\n                first = others[rng.next_int(0, (int)others.size() - 1)];\n            }\n\n            vector<int> tour = {sidx, first, sidx};\n            vector<char> used(T, 0);\n            used[sidx] = 1;\n            used[first] = 1;\n\n            while (true) {\n                int bestx = -1, bestpos = -1;\n                long long bestinc = (1LL << 60);\n                bool found = false;\n                for (int x : others) if (!used[x]) {\n                    for (int i = 0; i + 1 < (int)tour.size(); i++) {\n                        int a = tour[i], b = tour[i + 1];\n                        long long inc = (long long)d[a][x] + d[x][b] - d[a][b];\n                        if (randomized) inc += rng.next_int(0, 25);\n                        if (inc < bestinc) {\n                            bestinc = inc;\n                            bestx = x;\n                            bestpos = i + 1;\n                            found = true;\n                        }\n                    }\n                }\n                if (!found) break;\n                used[bestx] = 1;\n                tour.insert(tour.begin() + bestpos, bestx);\n            }\n            improve_tour(tour);\n            return tour;\n        };\n\n        auto build_nearest_neighbor = [&](int seedMode) {\n            vector<int> others;\n            for (int i = 0; i < T; i++) if (i != sidx) others.push_back(i);\n            if (others.empty()) return vector<int>{sidx, sidx};\n\n            int cur = others[0];\n            if (seedMode == 0) {\n                int best = INF;\n                for (int x : others) if (d[sidx][x] < best) best = d[sidx][x], cur = x;\n            } else if (seedMode == 1) {\n                int best = -1;\n                for (int x : others) if (d[sidx][x] > best) best = d[sidx][x], cur = x;\n            } else {\n                cur = others[rng.next_int(0, (int)others.size() - 1)];\n            }\n\n            vector<char> used(T, 0);\n            vector<int> tour = {sidx, cur};\n            used[sidx] = used[cur] = 1;\n\n            while (true) {\n                int bestx = -1, bestd = INF;\n                for (int x : others) if (!used[x]) {\n                    if (d[cur][x] < bestd) {\n                        bestd = d[cur][x];\n                        bestx = x;\n                    }\n                }\n                if (bestx == -1) break;\n                used[bestx] = 1;\n                tour.push_back(bestx);\n                cur = bestx;\n            }\n            tour.push_back(sidx);\n            improve_tour(tour);\n            return tour;\n        };\n\n        vector<int> bestTour;\n        long long bestTourCost = (1LL << 60);\n\n        for (int rep = 0; rep < 5; rep++) {\n            auto tr = build_cheapest_insertion(rep % 3, rep & 1);\n            long long cst = tour_cost(tr);\n            if (cst < bestTourCost) bestTourCost = cst, bestTour = tr;\n        }\n        for (int rep = 0; rep < 3; rep++) {\n            auto tr = build_nearest_neighbor(rep);\n            long long cst = tour_cost(tr);\n            if (cst < bestTourCost) bestTourCost = cst, bestTour = tr;\n        }\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n            vector<int> cnt(R, 0);\n            vector<char> used(T, 0);\n            for (int x : bestTour) used[x] = 1;\n            for (int i = 0; i < T; i++) if (used[i]) {\n                for (int r : visible[targets[i]]) cnt[r]++;\n            }\n\n            vector<pair<pair<int,int>, int>> order;\n            order.reserve(bestTour.size());\n            for (int pos = 1; pos + 1 < (int)bestTour.size(); pos++) {\n                int idx = bestTour[pos];\n                if (idx == sidx) continue;\n                int id = targets[idx];\n                int uniq = 0;\n                for (int r : visible[id]) if (cnt[r] == 1) uniq++;\n                order.push_back({{uniq, -baseDist[id]}, pos});\n            }\n            sort(order.begin(), order.end());\n\n            for (auto &it : order) {\n                int pos = it.second;\n                int idx = bestTour[pos];\n                int id = targets[idx];\n                bool ok = true;\n                for (int r : visible[id]) if (cnt[r] <= 1) { ok = false; break; }\n                if (!ok) continue;\n\n                vector<int> ntour;\n                ntour.reserve(bestTour.size() - 1);\n                for (int i = 0; i < (int)bestTour.size(); i++) if (i != pos) ntour.push_back(bestTour[i]);\n                long long nc = tour_cost(ntour);\n                if (nc < bestTourCost) {\n                    bestTour = ntour;\n                    bestTourCost = nc;\n                    changed = true;\n                    break;\n                }\n            }\n        }\n\n        return pair<vector<int>, long long>(bestTour, bestTourCost);\n    };\n\n    auto consider_solution = [&](vector<int> tar) {\n        tar = prune_targets_exact(tar);\n        auto [tour, cost] = solve_on_targets(tar);\n        if (cost < globalBestCost) {\n            globalBestCost = cost;\n            globalBestTargets = tar;\n            globalBestTour = tour;\n            return true;\n        }\n        return false;\n    };\n\n    auto constructor_trial = [&](bool late_phase) {\n        vector<char> cov(R, 0), chosen(M, 0);\n        vector<int> sel;\n        sel.reserve(64);\n        int covCnt = 0;\n\n        chosen[start] = 1;\n        sel.push_back(start);\n        for (int r : visible[start]) if (!cov[r]) cov[r] = 1, covCnt++;\n\n        int mode = rng.next_int(0, late_phase ? 2 : 3);\n        double alpha = 0.7 + 2.2 * rng.next_double();\n        double beta  = 0.01 + 0.25 * rng.next_double();\n        double gamma = 0.5 + 2.2 * rng.next_double();\n        double eta1  = 0.01 + 0.15 * rng.next_double();\n        double eta2  = 0.0005 + 0.01 * rng.next_double();\n\n        while (covCnt < R) {\n            vector<pair<double,int>> candList;\n            candList.reserve(M);\n\n            for (int id = 0; id < M; id++) {\n                if (chosen[id]) continue;\n                int gain = 0;\n                for (int r : visible[id]) gain += !cov[r];\n                if (gain == 0) continue;\n\n                int nearestSel = INF;\n                int avgSample = 0;\n                int sampleCnt = 0;\n                int lim = min<int>(3, sel.size());\n                for (int t = 0; t < lim; t++) {\n                    int sidx2 = sel[sel.size() - 1 - t];\n                    nearestSel = min(nearestSel, ccost[sidx2][id]);\n                    avgSample += ccost[sidx2][id];\n                    sampleCnt++;\n                }\n                if (sampleCnt) avgSample /= sampleCnt;\n\n                double noise = late_phase ? 25.0 : 60.0;\n                double score = gain * 1000.0\n                             + gamma * visScore[id]\n                             - alpha * baseDist[id]\n                             - beta * (double)baseDist[id] * (double)baseDist[id]\n                             - eta1 * nearestSel\n                             - eta2 * avgSample\n                             + rng.next_double() * noise;\n\n                candList.push_back({score, id});\n            }\n\n            if (candList.empty()) break;\n            sort(candList.begin(), candList.end(), greater<pair<double,int>>());\n\n            int pickIdx = 0;\n            if (mode == 0) {\n                pickIdx = 0;\n            } else if (mode == 1) {\n                int rcl = min<int>(2, candList.size());\n                pickIdx = rng.next_int(0, rcl - 1);\n            } else if (mode == 2) {\n                int rcl = min<int>(3, candList.size());\n                int rr = rng.next_int(0, 99);\n                if (rr < 70) pickIdx = 0;\n                else if (rr < 92) pickIdx = min(1, rcl - 1);\n                else pickIdx = rng.next_int(0, rcl - 1);\n            } else {\n                int rcl = min<int>(4, candList.size());\n                int rr = rng.next_int(0, 99);\n                if (rr < 75) pickIdx = 0;\n                else pickIdx = rng.next_int(0, rcl - 1);\n            }\n\n            int chosenId = candList[pickIdx].second;\n            chosen[chosenId] = 1;\n            sel.push_back(chosenId);\n            for (int r : visible[chosenId]) if (!cov[r]) cov[r] = 1, covCnt++;\n        }\n\n        if (covCnt < R) return;\n\n        if (!globalBestTargets.empty() && (int)sel.size() > (int)globalBestTargets.size() + 5) {\n            int skipProb = late_phase ? 60 : 85;\n            if (rng.next_int(0, 99) < skipProb) return;\n        }\n\n        consider_solution(sel);\n    };\n\n    auto elite_refine = [&](int strength) {\n        if (globalBestTargets.empty()) return;\n\n        vector<char> inSet(M, 0);\n        for (int x : globalBestTargets) inSet[x] = 1;\n\n        vector<int> outside;\n        outside.reserve(M);\n        for (int i = 0; i < M; i++) if (!inSet[i]) outside.push_back(i);\n        sort(outside.begin(), outside.end(), [&](int a, int b) {\n            long long sa = 1000LL * visScore[a] - 4LL * baseDist[a];\n            long long sb = 1000LL * visScore[b] - 4LL * baseDist[b];\n            return sa > sb;\n        });\n        int outLim = (strength == 0 ? 12 : 20);\n        if ((int)outside.size() > outLim) outside.resize(outLim);\n\n        vector<int> removable;\n        removable.reserve(globalBestTargets.size());\n        for (int x : globalBestTargets) if (x != start) removable.push_back(x);\n        sort(removable.begin(), removable.end(), [&](int a, int b) {\n            if (baseDist[a] != baseDist[b]) return baseDist[a] > baseDist[b];\n            return visScore[a] < visScore[b];\n        });\n        int remLim = (strength == 0 ? 6 : 10);\n        if ((int)removable.size() > remLim) removable.resize(remLim);\n\n        bool improved = false;\n\n        // replacement\n        for (int rem : removable) {\n            for (int add : outside) {\n                vector<int> nt = globalBestTargets;\n                bool done = false;\n                for (int &x : nt) if (x == rem) {\n                    x = add;\n                    done = true;\n                    break;\n                }\n                if (!done) continue;\n                sort(nt.begin(), nt.end());\n                nt.erase(unique(nt.begin(), nt.end()), nt.end());\n                if (find(nt.begin(), nt.end(), start) == nt.end()) continue;\n                if (!full_cover(nt)) continue;\n                if (consider_solution(nt)) {\n                    improved = true;\n                    break;\n                }\n            }\n            if (improved || now_sec() - stime >= TL - 0.05) break;\n        }\n\n        // drop-and-repair\n        if (!improved && now_sec() - stime < TL - 0.05) {\n            for (int rem : removable) {\n                vector<int> base = globalBestTargets;\n                base.erase(find(base.begin(), base.end(), rem));\n\n                if (full_cover(base)) {\n                    if (consider_solution(base)) {\n                        improved = true;\n                        break;\n                    }\n                } else {\n                    vector<char> cov(R, 0);\n                    for (int id : base) for (int r : visible[id]) cov[r] = 1;\n\n                    vector<pair<int,int>> repairScore; // (gain, candidate)\n                    for (int add : outside) {\n                        int gain = 0;\n                        for (int r : visible[add]) gain += !cov[r];\n                        if (gain > 0) repairScore.push_back({gain, add});\n                    }\n                    sort(repairScore.begin(), repairScore.end(), [&](auto &a, auto &b) {\n                        if (a.first != b.first) return a.first > b.first;\n                        return visScore[a.second] > visScore[b.second];\n                    });\n                    int lim = min<int>(strength == 0 ? 6 : 10, repairScore.size());\n                    for (int i = 0; i < lim; i++) {\n                        int add = repairScore[i].second;\n                        vector<int> nt = base;\n                        nt.push_back(add);\n                        sort(nt.begin(), nt.end());\n                        nt.erase(unique(nt.begin(), nt.end()), nt.end());\n                        if (!full_cover(nt)) continue;\n                        if (consider_solution(nt)) {\n                            improved = true;\n                            break;\n                        }\n                        if (now_sec() - stime >= TL - 0.04) break;\n                    }\n                }\n                if (improved || now_sec() - stime >= TL - 0.04) break;\n            }\n        }\n\n        int addTries = (strength == 0 ? 6 : 10);\n        if (now_sec() - stime < TL - 0.03) {\n            for (int i = 0; i < min<int>(addTries, outside.size()); i++) {\n                vector<int> nt = globalBestTargets;\n                nt.push_back(outside[i]);\n                sort(nt.begin(), nt.end());\n                nt.erase(unique(nt.begin(), nt.end()), nt.end());\n                consider_solution(nt);\n                if (now_sec() - stime >= TL - 0.02) break;\n            }\n        }\n    };\n\n    int loopCnt = 0;\n    while (now_sec() - stime < TL) {\n        loopCnt++;\n        double elapsed = now_sec() - stime;\n        bool late_phase = elapsed > TL * 0.68;\n\n        constructor_trial(late_phase);\n\n        if (!globalBestTargets.empty()) {\n            if (!late_phase) {\n                if (loopCnt % 10 == 0 && now_sec() - stime < TL - 0.12) elite_refine(0);\n            } else {\n                if (loopCnt % 5 == 0 && now_sec() - stime < TL - 0.08) elite_refine(1);\n            }\n        }\n    }\n\n    if (globalBestTargets.empty()) {\n        vector<int> tar = {start};\n        vector<char> cov(R, 0);\n        for (int r : visible[start]) cov[r] = 1;\n        for (int i = 0; i < M; i++) {\n            bool need = false;\n            for (int r : visible[i]) if (!cov[r]) { need = true; break; }\n            if (need) {\n                tar.push_back(i);\n                for (int r : visible[i]) cov[r] = 1;\n            }\n        }\n        consider_solution(tar);\n    }\n\n    vector<int> finalTargets = globalBestTargets;\n    sort(finalTargets.begin(), finalTargets.end());\n    finalTargets.erase(unique(finalTargets.begin(), finalTargets.end()), finalTargets.end());\n\n    int T = (int)finalTargets.size();\n    vector<vector<int>> parentT(T, vector<int>(NN, -1));\n    {\n        vector<int> dist(NN);\n        for (int ti = 0; ti < T; ti++) {\n            fill(dist.begin(), dist.end(), INF);\n            int sv = vid(cand[finalTargets[ti]].x, cand[finalTargets[ti]].y);\n            priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;\n            dist[sv] = 0;\n            pq.push({0, sv});\n            while (!pq.empty()) {\n                auto [cd, v] = pq.top(); pq.pop();\n                if (cd != dist[v]) continue;\n                int x = v / N, y = v % N;\n                for (int k = 0; k < 4; k++) {\n                    int nx = x + dx[k], ny = y + dy[k];\n                    if (!road(nx, ny)) continue;\n                    int nv = vid(nx, ny);\n                    int nd = cd + w(nx, ny);\n                    if (nd < dist[nv]) {\n                        dist[nv] = nd;\n                        parentT[ti][nv] = v;\n                        pq.push({nd, nv});\n                    }\n                }\n            }\n        }\n    }\n\n    auto restore_path = [&](int fromIdx, int toIdx) -> vector<Pos> {\n        auto [tx, ty] = cand[finalTargets[toIdx]];\n        int cur = vid(tx, ty);\n        int s = vid(cand[finalTargets[fromIdx]].x, cand[finalTargets[fromIdx]].y);\n\n        vector<int> rev;\n        while (cur != s) {\n            rev.push_back(cur);\n            cur = parentT[fromIdx][cur];\n            if (cur == -1) return {};\n        }\n        reverse(rev.begin(), rev.end());\n\n        vector<Pos> path;\n        for (int v : rev) path.push_back({v / N, v % N});\n        return path;\n    };\n\n    string ans;\n    int cx = si, cy = sj;\n\n    auto emit_step = [&](int nx, int ny) {\n        if (nx == cx - 1 && ny == cy) ans.push_back('U');\n        else if (nx == cx + 1 && ny == cy) ans.push_back('D');\n        else if (nx == cx && ny == cy - 1) ans.push_back('L');\n        else if (nx == cx && ny == cy + 1) ans.push_back('R');\n        cx = nx;\n        cy = ny;\n    };\n\n    for (int i = 0; i + 1 < (int)globalBestTour.size(); i++) {\n        auto path = restore_path(globalBestTour[i], globalBestTour[i + 1]);\n        for (auto &p : path) emit_step(p.x, p.y);\n    }\n\n    {\n        int x = si, y = sj;\n        bool ok = true;\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n            else ok = false;\n            if (!inb(x, y) || !road(x, y)) ok = false;\n        }\n        if (x != si || y != sj) ok = false;\n\n        vector<char> seen(R, 0);\n        x = si; y = sj;\n        auto mark_vis = [&](int px, int py) {\n            seen[rid[px][py]] = 1;\n            for (int dir = 0; dir < 4; dir++) {\n                int nx = px, ny = py;\n                while (true) {\n                    nx += dx[dir];\n                    ny += dy[dir];\n                    if (!road(nx, ny)) break;\n                    seen[rid[nx][ny]] = 1;\n                }\n            }\n        };\n        mark_vis(x, y);\n        for (char ch : ans) {\n            if (ch == 'U') x--;\n            else if (ch == 'D') x++;\n            else if (ch == 'L') y--;\n            else if (ch == 'R') y++;\n            mark_vis(x, y);\n        }\n        for (int i = 0; i < R; i++) if (!seen[i]) ok = false;\n\n        if (!ok) ans.clear();\n    }\n\n    cout << ans << '\\n';\n    return 0;\n}","future-contest-2022-qual":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct TaskInfo {\n    vector<int> d;\n    int diff_sum = 0;\n    int priority = 1; // longest path to sink\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<TaskInfo> tasks(N);\n    for (int i = 0; i < N; ++i) {\n        tasks[i].d.resize(K);\n        int s = 0;\n        for (int k = 0; k < K; ++k) {\n            cin >> tasks[i].d[k];\n            s += tasks[i].d[k];\n        }\n        tasks[i].diff_sum = s;\n    }\n\n    vector<vector<int>> out(N), in(N);\n    for (int i = 0; i < R; ++i) {\n        int u, v;\n        cin >> u >> v;\n        --u; --v;\n        out[u].push_back(v);\n        in[v].push_back(u);\n    }\n\n    // longest path to sink\n    for (int i = N - 1; i >= 0; --i) {\n        int best = 0;\n        for (int to : out[i]) best = max(best, tasks[to].priority);\n        tasks[i].priority = best + 1;\n    }\n\n    // state\n    vector<int> task_state(N, 0); // 0:not started, 1:in progress, 2:done\n    vector<int> rem_pre(N);\n    for (int i = 0; i < N; ++i) rem_pre[i] = (int)in[i].size();\n\n    vector<int> member_task(M, -1), member_start(M, -1);\n\n    // estimated skills\n    vector<vector<double>> est(M, vector<double>(K, 20.0));\n    vector<int> obs_cnt(M, 0);\n\n    auto predicted_deficit = [&](int task_id, int member_id) -> double {\n        double w = 0.0;\n        const auto &d = tasks[task_id].d;\n        const auto &s = est[member_id];\n        for (int k = 0; k < K; ++k) {\n            if (d[k] > s[k]) w += d[k] - s[k];\n        }\n        return w;\n    };\n\n    auto predicted_time = [&](int task_id, int member_id) -> double {\n        return max(1.0, predicted_deficit(task_id, member_id));\n    };\n\n    auto update_estimate = [&](int member_id, int task_id, int duration) {\n        double target = (duration <= 1 ? 0.0 : (double)duration - 1.0);\n        const auto &d = tasks[task_id].d;\n        auto &s = est[member_id];\n\n        for (int iter = 0; iter < 3; ++iter) {\n            double pred = 0.0;\n            for (int k = 0; k < K; ++k) {\n                if (d[k] > s[k]) pred += d[k] - s[k];\n            }\n            double diff = target - pred;\n\n            double lr = 0.45 / (1.0 + 0.08 * obs_cnt[member_id]);\n            if (fabs(diff) < 0.5) break;\n\n            if (diff < 0) {\n                // estimated skills too low\n                double total_gap = 0.0;\n                for (int k = 0; k < K; ++k) total_gap += max(0.0, (double)d[k] - s[k]);\n                if (total_gap < 1e-9) total_gap = 1.0;\n                double need = -diff * lr;\n                for (int k = 0; k < K; ++k) {\n                    double gap = max(0.0, (double)d[k] - s[k]);\n                    if (gap <= 0) continue;\n                    s[k] += need * (gap / total_gap);\n                    if (s[k] > 80.0) s[k] = 80.0;\n                }\n            } else {\n                // estimated skills too high\n                double total_rel = 0.0;\n                for (int k = 0; k < K; ++k) total_rel += d[k] + 1.0;\n                double need = diff * lr * 0.60;\n                for (int k = 0; k < K; ++k) {\n                    double dec = need * ((d[k] + 1.0) / total_rel);\n                    s[k] -= dec;\n                    if (s[k] < 0.0) s[k] = 0.0;\n                }\n            }\n        }\n\n        obs_cnt[member_id]++;\n    };\n\n    auto unlock_bonus = [&](int task_id) -> int {\n        int cnt = 0;\n        for (int to : out[task_id]) {\n            if (task_state[to] == 0 && rem_pre[to] == 1) cnt++;\n        }\n        return cnt;\n    };\n\n    int day = 0;\n\n    while (true) {\n        ++day;\n\n        vector<int> ready;\n        ready.reserve(N);\n        for (int i = 0; i < N; ++i) {\n            if (task_state[i] == 0 && rem_pre[i] == 0) ready.push_back(i);\n        }\n\n        sort(ready.begin(), ready.end(), [&](int a, int b) {\n            if (tasks[a].priority != tasks[b].priority) return tasks[a].priority > tasks[b].priority;\n            if (tasks[a].diff_sum != tasks[b].diff_sum) return tasks[a].diff_sum > tasks[b].diff_sum;\n            return a < b;\n        });\n\n        const int LIMIT = 200;\n        if ((int)ready.size() > LIMIT) ready.resize(LIMIT);\n\n        vector<int> free_members;\n        for (int j = 0; j < M; ++j) if (member_task[j] == -1) free_members.push_back(j);\n\n        vector<pair<int,int>> assignments;\n        vector<char> used_task(N, 0), used_member(M, 0);\n\n        while (true) {\n            double bestScore = -1e100;\n            int bestMem = -1, bestTask = -1;\n\n            for (int j : free_members) {\n                if (used_member[j]) continue;\n                for (int t : ready) {\n                    if (used_task[t]) continue;\n\n                    double pt = predicted_time(t, j);\n                    double fit_penalty = 22.0 + min(8.0, tasks[t].diff_sum / 25.0);\n\n                    double score =\n                        1000.0 * tasks[t].priority\n                        - fit_penalty * pt\n                        + 2.0 * tasks[t].diff_sum\n                        + 80.0 * unlock_bonus(t);\n\n                    if (obs_cnt[j] < 5) {\n                        score += (5 - obs_cnt[j]) * 3.0;\n                    }\n\n                    if (score > bestScore) {\n                        bestScore = score;\n                        bestMem = j;\n                        bestTask = t;\n                    }\n                }\n            }\n\n            if (bestMem == -1) break;\n\n            used_member[bestMem] = 1;\n            used_task[bestTask] = 1;\n            assignments.push_back({bestMem, bestTask});\n\n            task_state[bestTask] = 1;\n            member_task[bestMem] = bestTask;\n            member_start[bestMem] = day;\n        }\n\n        cout << assignments.size();\n        for (auto [mem, task] : assignments) {\n            cout << ' ' << (mem + 1) << ' ' << (task + 1);\n        }\n        cout << '\\n';\n        cout.flush();\n\n        string first;\n        if (!(cin >> first)) return 0;\n        if (first == \"-1\") return 0;\n\n        int n = stoi(first);\n        vector<int> finished(n);\n        for (int i = 0; i < n; ++i) {\n            cin >> finished[i];\n            --finished[i];\n        }\n\n        for (int mem : finished) {\n            int task = member_task[mem];\n            if (task == -1) continue;\n\n            int duration = day - member_start[mem] + 1;\n            update_estimate(mem, task, duration);\n\n            task_state[task] = 2;\n            member_task[mem] = -1;\n            member_start[mem] = -1;\n\n            for (int to : out[task]) rem_pre[to]--;\n        }\n    }\n\n    return 0;\n}","ahc006":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 1000;\nstatic constexpr int M = 50;\nstatic constexpr int DEPOT_X = 400;\nstatic constexpr int DEPOT_Y = 400;\n\nstruct Order {\n    int a, b, c, d;\n    int id;\n};\n\nstruct Pt {\n    int x, y;\n};\n\nstatic inline int mdist(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\nstatic inline int mdist(const Pt& p, const Pt& q) {\n    return abs(p.x - q.x) + abs(p.y - q.y);\n}\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double ms() const {\n        return chrono::duration_cast<chrono::microseconds>(\n            chrono::steady_clock::now() - st\n        ).count() / 1000.0;\n    }\n};\n\nstruct Solver {\n    vector<Order> ord;\n    mt19937 rng;\n\n    Solver() : ord(N) {\n        rng.seed((uint64_t)chrono::steady_clock::now().time_since_epoch().count());\n    }\n\n    Pt rest_pt(int idx) const { return {ord[idx].a, ord[idx].b}; }\n    Pt dest_pt(int idx) const { return {ord[idx].c, ord[idx].d}; }\n\n    int order_score(int i) const {\n        const auto& o = ord[i];\n        return mdist(DEPOT_X, DEPOT_Y, o.a, o.b)\n             + mdist(o.a, o.b, o.c, o.d)\n             + mdist(o.c, o.d, DEPOT_X, DEPOT_Y);\n    }\n\n    bool validate_solution(const vector<int>& sel, const vector<int>& pord, const vector<int>& dord) const {\n        if ((int)sel.size() != M) return false;\n        if ((int)pord.size() != M || (int)dord.size() != M) return false;\n\n        vector<int> cntSel(N, 0);\n        for (int x : sel) {\n            if (x < 0 || x >= N) return false;\n            cntSel[x]++;\n            if (cntSel[x] > 1) return false;\n        }\n\n        vector<int> cntP(M, 0), cntD(M, 0);\n        for (int x : pord) {\n            if (x < 0 || x >= M) return false;\n            cntP[x]++;\n        }\n        for (int x : dord) {\n            if (x < 0 || x >= M) return false;\n            cntD[x]++;\n        }\n        for (int i = 0; i < M; ++i) {\n            if (cntP[i] != 1 || cntD[i] != 1) return false;\n        }\n        return true;\n    }\n\n    int route_cost(const vector<int>& sel, const vector<int>& pord, const vector<int>& dord) const {\n        Pt cur{DEPOT_X, DEPOT_Y};\n        int cost = 0;\n        for (int pos : pord) {\n            Pt nxt = rest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        for (int pos : dord) {\n            Pt nxt = dest_pt(sel[pos]);\n            cost += mdist(cur, nxt);\n            cur = nxt;\n        }\n        cost += mdist(cur, Pt{DEPOT_X, DEPOT_Y});\n        return cost;\n    }\n\n    vector<int> nearest_pickups(const vector<int>& sel) const {\n        vector<int> res;\n        res.reserve(M);\n        vector<char> used(M, false);\n        Pt cur{DEPOT_X, DEPOT_Y};\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = INT_MAX;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                int d = mdist(cur, rest_pt(sel[i]));\n                if (d < bestd) {\n                    bestd = d;\n                    best = i;\n                }\n            }\n            used[best] = true;\n            res.push_back(best);\n            cur = rest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    vector<int> nearest_deliveries(const vector<int>& sel, const Pt& start) const {\n        vector<int> res;\n        res.reserve(M);\n        vector<char> used(M, false);\n        Pt cur = start;\n        for (int it = 0; it < M; ++it) {\n            int best = -1, bestd = INT_MAX;\n            for (int i = 0; i < M; ++i) if (!used[i]) {\n                int d = mdist(cur, dest_pt(sel[i]));\n                if (d < bestd) {\n                    bestd = d;\n                    best = i;\n                }\n            }\n            used[best] = true;\n            res.push_back(best);\n            cur = dest_pt(sel[best]);\n        }\n        return res;\n    }\n\n    void two_opt_pick(const vector<int>& sel, vector<int>& pord, const vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    Pt A = (l == 0 ? Pt{DEPOT_X, DEPOT_Y} : rest_pt(sel[pord[l - 1]]));\n                    Pt B = rest_pt(sel[pord[l]]);\n                    Pt C = rest_pt(sel[pord[r]]);\n                    Pt D = (r + 1 < M ? rest_pt(sel[pord[r + 1]]) : dest_pt(sel[dord[0]]));\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(pord.begin() + l, pord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    void two_opt_del(const vector<int>& sel, const vector<int>& pord, vector<int>& dord) const {\n        bool improved = true;\n        while (improved) {\n            improved = false;\n            for (int l = 0; l < M; ++l) {\n                for (int r = l + 1; r < M; ++r) {\n                    Pt A = (l == 0 ? rest_pt(sel[pord.back()]) : dest_pt(sel[dord[l - 1]]));\n                    Pt B = dest_pt(sel[dord[l]]);\n                    Pt C = dest_pt(sel[dord[r]]);\n                    Pt D = (r + 1 < M ? dest_pt(sel[dord[r + 1]]) : Pt{DEPOT_X, DEPOT_Y});\n\n                    int before = mdist(A, B) + mdist(C, D);\n                    int after  = mdist(A, C) + mdist(B, D);\n                    if (after < before) {\n                        reverse(dord.begin() + l, dord.begin() + r + 1);\n                        improved = true;\n                    }\n                }\n            }\n        }\n    }\n\n    struct Sol {\n        vector<int> sel, pord, dord;\n        int cost = INT_MAX;\n    };\n\n    Sol build_solution(const vector<int>& sel) const {\n        Sol sol;\n        sol.sel = sel;\n        sol.pord = nearest_pickups(sel);\n        Pt lastPick = rest_pt(sel[sol.pord.back()]);\n        sol.dord = nearest_deliveries(sel, lastPick);\n\n        two_opt_pick(sol.sel, sol.pord, sol.dord);\n        two_opt_del(sol.sel, sol.pord, sol.dord);\n\n        sol.cost = route_cost(sol.sel, sol.pord, sol.dord);\n        return sol;\n    }\n\n    vector<int> sample_subset_from_pool(const vector<int>& pool, const vector<int>& score) {\n        vector<pair<int,int>> cand;\n        cand.reserve(pool.size());\n        for (int idx : pool) {\n            int noisy = score[idx] + uniform_int_distribution<int>(0, 300)(rng);\n            cand.push_back({noisy, idx});\n        }\n        nth_element(cand.begin(), cand.begin() + M, cand.end());\n        cand.resize(M);\n        vector<int> sel;\n        sel.reserve(M);\n        for (auto &p : cand) sel.push_back(p.second);\n        return sel;\n    }\n\n    void solve() {\n        for (int i = 0; i < N; ++i) {\n            cin >> ord[i].a >> ord[i].b >> ord[i].c >> ord[i].d;\n            ord[i].id = i + 1;\n        }\n\n        Timer timer;\n\n        vector<int> score(N);\n        for (int i = 0; i < N; ++i) score[i] = order_score(i);\n\n        vector<int> ranked(N);\n        iota(ranked.begin(), ranked.end(), 0);\n        sort(ranked.begin(), ranked.end(), [&](int x, int y) {\n            return score[x] < score[y];\n        });\n\n        Sol best;\n\n        auto try_candidate = [&](const vector<int>& sel) {\n            Sol sol = build_solution(sel);\n            if (!validate_solution(sol.sel, sol.pord, sol.dord)) return;\n            if (sol.cost < best.cost) best = move(sol);\n        };\n\n        // Multi-start initialization\n        vector<int> poolSizes = {50, 60, 80, 100, 150, 200, 300};\n        for (int K : poolSizes) {\n            if (timer.ms() > 800) break;\n            vector<int> pool(ranked.begin(), ranked.begin() + min(K, N));\n\n            // deterministic top M\n            {\n                vector<int> sel(pool.begin(), pool.begin() + M);\n                try_candidate(sel);\n            }\n\n            // randomized variants\n            int trials = (K <= 100 ? 6 : 4);\n            for (int t = 0; t < trials; ++t) {\n                if (timer.ms() > 1000) break;\n                auto sel = sample_subset_from_pool(pool, score);\n                try_candidate(sel);\n            }\n        }\n\n        if (best.sel.empty()) {\n            best.sel.assign(ranked.begin(), ranked.begin() + M);\n            best = build_solution(best.sel);\n        }\n\n        // Subset replacement hill climbing\n        vector<int> topPool(ranked.begin(), ranked.begin() + 300);\n        while (timer.ms() < 1900) {\n            vector<int> sel = best.sel;\n            vector<char> inSel(N, false);\n            for (int x : sel) inSel[x] = true;\n\n            int outPos = uniform_int_distribution<int>(0, M - 1)(rng);\n            int inIdx;\n            if (uniform_int_distribution<int>(0, 99)(rng) < 85) {\n                inIdx = topPool[uniform_int_distribution<int>(0, (int)topPool.size() - 1)(rng)];\n            } else {\n                inIdx = uniform_int_distribution<int>(0, N - 1)(rng);\n            }\n\n            if (inSel[inIdx]) continue;\n            sel[outPos] = inIdx;\n\n            // uniqueness check\n            {\n                vector<int> cnt(N, 0);\n                bool ok = true;\n                for (int x : sel) {\n                    cnt[x]++;\n                    if (cnt[x] > 1) { ok = false; break; }\n                }\n                if (!ok) continue;\n            }\n\n            Sol sol = build_solution(sel);\n            if (!validate_solution(sol.sel, sol.pord, sol.dord)) continue;\n            if (sol.cost < best.cost) best = move(sol);\n        }\n\n        // final fallback safety\n        if (!validate_solution(best.sel, best.pord, best.dord)) {\n            best.sel.assign(ranked.begin(), ranked.begin() + M);\n            best = build_solution(best.sel);\n        }\n\n        cout << M;\n        for (int idx : best.sel) cout << ' ' << ord[idx].id;\n        cout << '\\n';\n\n        vector<Pt> route;\n        route.reserve(2 * M + 2);\n        route.push_back({DEPOT_X, DEPOT_Y});\n        for (int pos : best.pord) route.push_back(rest_pt(best.sel[pos]));\n        for (int pos : best.dord) route.push_back(dest_pt(best.sel[pos]));\n        route.push_back({DEPOT_X, DEPOT_Y});\n\n        cout << route.size();\n        for (auto &p : route) cout << ' ' << p.x << ' ' << p.y;\n        cout << '\\n';\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc007":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n) { 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 same(int a, int b) { return find(a) == find(b); }\n    int size(int x) { return sz[find(x)]; }\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, d;\n};\n\nstruct KEdge {\n    int w;\n    int type; // 0=accepted, 1=current, 2=future\n    int u, v;\n    bool operator<(const KEdge& other) const {\n        if (w != other.w) return w < other.w;\n        return type < other.type;\n    }\n};\n\nstatic inline int rounded_dist(int x1, int y1, int x2, int y2) {\n    long long dx = x1 - x2;\n    long long dy = y1 - y2;\n    return (int)llround(sqrt((double)(dx * dx + dy * dy)));\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next_u32() % (uint32_t)(r - l + 1));\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    const int N = 400;\n    const int M = 1995;\n\n    vector<int> xs(N), ys(N);\n    for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n    vector<Edge> edges(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v, rounded_dist(xs[u], ys[u], xs[v], ys[v])};\n    }\n\n    vector<int> state(M, -1); // -1 undecided, 0 rejected, 1 accepted\n    DSU accepted(N);\n    XorShift rng;\n\n    auto det_future_weight = [&](int d) -> int {\n        return (7 * d + 2) / 4; // about 1.75*d\n    };\n\n    auto feasible_without_current = [&](int cur) -> bool {\n        DSU dsu(N);\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            } else if (j > cur && state[j] == -1) {\n                dsu.unite(edges[j].u, edges[j].v);\n            }\n        }\n        return dsu.same(edges[cur].u, edges[cur].v);\n    };\n\n    auto deterministic_mst_include = [&](int cur, int lcur) -> bool {\n        vector<KEdge> es;\n        es.reserve(M);\n\n        for (int j = 0; j < M; j++) {\n            if (state[j] == 1) {\n                es.push_back({0, 0, edges[j].u, edges[j].v});\n            } else if (j == cur) {\n                es.push_back({lcur, 1, edges[j].u, edges[j].v});\n            } else if (j > cur && state[j] == -1) {\n                es.push_back({det_future_weight(edges[j].d), 2, edges[j].u, edges[j].v});\n            }\n        }\n\n        sort(es.begin(), es.end());\n        DSU dsu(N);\n        for (auto &e : es) {\n            if (dsu.unite(e.u, e.v)) {\n                if (e.type == 1) return true;\n            }\n        }\n        return false;\n    };\n\n    auto sampled_mst_inclusion_count = [&](int cur, int lcur, int samples) -> int {\n        int cnt = 0;\n        vector<KEdge> es;\n        es.reserve(M);\n\n        for (int s = 0; s < samples; s++) {\n            es.clear();\n            for (int j = 0; j < M; j++) {\n                if (state[j] == 1) {\n                    es.push_back({0, 0, edges[j].u, edges[j].v});\n                } else if (j == cur) {\n                    es.push_back({lcur, 1, edges[j].u, edges[j].v});\n                } else if (j > cur && state[j] == -1) {\n                    int d = edges[j].d;\n                    int w = rng.next_int(d, 3 * d);\n                    es.push_back({w, 2, edges[j].u, edges[j].v});\n                }\n            }\n\n            sort(es.begin(), es.end());\n            DSU dsu(N);\n            bool used = false;\n            for (auto &e : es) {\n                if (dsu.unite(e.u, e.v)) {\n                    if (e.type == 1) {\n                        used = true;\n                        break;\n                    }\n                }\n            }\n            if (used) cnt++;\n        }\n        return cnt;\n    };\n\n    for (int i = 0; i < M; i++) {\n        int l;\n        cin >> l;\n\n        int u = edges[i].u;\n        int v = edges[i].v;\n        int d = edges[i].d;\n        int ans = 0;\n\n        if (accepted.same(u, v)) {\n            ans = 0;\n        } else if (!feasible_without_current(i)) {\n            ans = 1;\n        } else {\n            bool det_in = deterministic_mst_include(i, l);\n            double r = (double)l / (double)d;\n\n            int su = accepted.size(u);\n            int sv = accepted.size(v);\n            long long merge_score = 1LL * su * sv;\n\n            int big_merge_bonus = 0;\n            if (merge_score >= 4000) big_merge_bonus = 1;\n            if (merge_score >= 12000) big_merge_bonus = 2;\n\n            if (det_in) {\n                if (l <= 2 * d) {\n                    ans = 1;\n                } else if (r >= 2.35) {\n                    int c = sampled_mst_inclusion_count(i, l, 5);\n                    ans = (c + big_merge_bonus >= 4 ? 1 : 0);\n                } else {\n                    int c = sampled_mst_inclusion_count(i, l, 3);\n                    ans = (c + min(big_merge_bonus, 1) >= 1 ? 1 : 0);\n                }\n            } else {\n                if (r <= 1.50) {\n                    int c = sampled_mst_inclusion_count(i, l, 5);\n                    ans = (c + min(big_merge_bonus, 1) >= 3 ? 1 : 0);\n                } else {\n                    ans = 0;\n                }\n            }\n        }\n\n        state[i] = ans;\n        if (ans) accepted.unite(u, v);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n\n    return 0;\n}","ahc008":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int TURNS = 300;\n\nstruct Pet {\n    int x, y, t;\n};\nstruct Human {\n    int x, y;\n};\n\nint N, M;\nvector<Pet> pets;\nvector<Human> humans;\nbool wall_[31][31];\n\nint dx[4] = {-1, 1, 0, 0};\nint dy[4] = {0, 0, -1, 1};\nchar MCH[4] = {'U', 'D', 'L', 'R'};\nchar BCH[4] = {'u', 'd', 'l', 'r'};\n\nbool inside(int x, int y) {\n    return 1 <= x && x <= 30 && 1 <= y && y <= 30;\n}\n\nint move_dir(char c) {\n    for (int d = 0; d < 4; d++) if (MCH[d] == c) return d;\n    return -1;\n}\nint build_dir(char c) {\n    for (int d = 0; d < 4; d++) if (BCH[d] == c) return d;\n    return -1;\n}\n\nbool pet_at[31][31];\nbool human_at[31][31];\n\nbool adj_pet(int x, int y) {\n    for (int d = 0; d < 4; d++) {\n        int nx = x + dx[d], ny = y + dy[d];\n        if (inside(nx, ny) && pet_at[nx][ny]) return true;\n    }\n    return false;\n}\n\nbool can_block_startturn(int x, int y) {\n    if (!inside(x, y)) return false;\n    if (pet_at[x][y]) return false;\n    if (human_at[x][y]) return false;\n    if (adj_pet(x, y)) return false;\n    return true;\n}\n\nint manhattan(int x1, int y1, int x2, int y2) {\n    return abs(x1 - x2) + abs(y1 - y2);\n}\n\nstruct Role {\n    // 0 builder, 1 camper\n    int type;\n    int tx, ty;\n};\n\nvector<Role> roles;\n\npair<int,int> bfs_next_step(\n    int sx, int sy, int tx, int ty,\n    const vector<vector<int>>& blocked_future\n) {\n    if (sx == tx && sy == ty) return {sx, sy};\n\n    static int dist[31][31];\n    static pair<int,int> pre[31][31];\n    for (int i = 1; i <= 30; i++) for (int j = 1; j <= 30; j++) {\n        dist[i][j] = -1;\n        pre[i][j] = {-1, -1};\n    }\n\n    queue<pair<int,int>> q;\n    q.push({sx, sy});\n    dist[sx][sy] = 0;\n\n    while (!q.empty()) {\n        auto [x, y] = q.front();\n        q.pop();\n        for (int d = 0; d < 4; d++) {\n            int nx = x + dx[d], ny = y + dy[d];\n            if (!inside(nx, ny)) continue;\n            if (wall_[nx][ny]) continue;\n            if (blocked_future[nx][ny]) continue;\n            if (dist[nx][ny] != -1) continue;\n            dist[nx][ny] = dist[x][y] + 1;\n            pre[nx][ny] = {x, y};\n            q.push({nx, ny});\n        }\n    }\n\n    if (dist[tx][ty] == -1) return {sx, sy};\n\n    int cx = tx, cy = ty;\n    while (pre[cx][cy] != make_pair(sx, sy)) {\n        auto p = pre[cx][cy];\n        if (p.first == -1) return {sx, sy};\n        cx = p.first;\n        cy = p.second;\n    }\n    return {cx, cy};\n}\n\nchar move_toward_safe(\n    int id, int tx, int ty,\n    const vector<vector<int>>& blocked_future,\n    const vector<pair<int,int>>& reserved_moves\n) {\n    int sx = humans[id].x, sy = humans[id].y;\n    auto [nx, ny] = bfs_next_step(sx, sy, tx, ty, blocked_future);\n\n    if (nx != sx || ny != sy) {\n        bool ok = true;\n        for (int j = 0; j < id; j++) {\n            if (reserved_moves[j] == make_pair(nx, ny)) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) {\n            for (int d = 0; d < 4; d++) {\n                if (sx + dx[d] == nx && sy + dy[d] == ny) return MCH[d];\n            }\n        }\n    }\n\n    int bestd = 1e9, bestdir = -1;\n    for (int d = 0; d < 4; d++) {\n        int xx = sx + dx[d], yy = sy + dy[d];\n        if (!inside(xx, yy)) continue;\n        if (wall_[xx][yy]) continue;\n        if (blocked_future[xx][yy]) continue;\n        bool used = false;\n        for (int j = 0; j < id; j++) {\n            if (reserved_moves[j] == make_pair(xx, yy)) {\n                used = true;\n                break;\n            }\n        }\n        if (used) continue;\n        int val = manhattan(xx, yy, tx, ty);\n        if (val < bestd) {\n            bestd = val;\n            bestdir = d;\n        }\n    }\n    if (bestdir == -1) return '.';\n    return MCH[bestdir];\n}\n\nint count_pets_top_initial() {\n    int c = 0;\n    for (auto &p : pets) if (p.x <= 15) c++;\n    return c;\n}\n\nint count_line_built(int row) {\n    int c = 0;\n    for (int y = 1; y <= 30; y++) if (wall_[row][y]) c++;\n    return c;\n}\n\nint edge_dist(int y) {\n    return min(y - 1, 30 - y);\n}\n\nvector<int> assign_builder_columns_global(const vector<int>& builderIds, int barrierRow, int standRow) {\n    vector<int> gaps;\n    for (int y = 1; y <= 30; y++) if (!wall_[barrierRow][y]) gaps.push_back(y);\n\n    vector<int> target(M, 15);\n    if (gaps.empty()) return target;\n\n    int B = builderIds.size();\n    int G = gaps.size();\n    vector<int> bu(B, 1), gu(G, 1);\n\n    for (int step = 0; step < min(B, G); step++) {\n        int bestBi = -1, bestGj = -1;\n        long long bestCost = (1LL << 60);\n        int bestEdge = 1e9;\n\n        for (int i = 0; i < B; i++) if (bu[i]) {\n            int id = builderIds[i];\n            for (int j = 0; j < G; j++) if (gu[j]) {\n                long long cost = 100LL * abs(humans[id].y - gaps[j]) + abs(humans[id].x - standRow);\n                int ed = edge_dist(gaps[j]); // smaller => closer to edge, preferred on tie\n                if (cost < bestCost ||\n                    (cost == bestCost && ed < bestEdge) ||\n                    (cost == bestCost && ed == bestEdge && id < builderIds[bestBi])) {\n                    bestCost = cost;\n                    bestEdge = ed;\n                    bestBi = i;\n                    bestGj = j;\n                }\n            }\n        }\n        if (bestBi == -1) break;\n        target[builderIds[bestBi]] = gaps[bestGj];\n        bu[bestBi] = 0;\n        gu[bestGj] = 0;\n    }\n\n    vector<int> remGaps;\n    for (int j = 0; j < G; j++) if (gu[j]) remGaps.push_back(gaps[j]);\n\n    for (int i = 0; i < B; i++) if (bu[i]) {\n        int id = builderIds[i];\n        if (remGaps.empty()) {\n            target[id] = humans[id].y;\n        } else {\n            int bestY = remGaps[0];\n            long long bestCost = 100LL * abs(humans[id].y - remGaps[0]) + abs(humans[id].x - standRow);\n            int bestEdge = edge_dist(remGaps[0]);\n            for (int y : remGaps) {\n                long long cost = 100LL * abs(humans[id].y - y) + abs(humans[id].x - standRow);\n                int ed = edge_dist(y);\n                if (cost < bestCost || (cost == bestCost && ed < bestEdge)) {\n                    bestCost = cost;\n                    bestEdge = ed;\n                    bestY = y;\n                }\n            }\n            target[id] = bestY;\n        }\n    }\n\n    return target;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N;\n    pets.resize(N);\n    for (int i = 0; i < N; i++) cin >> pets[i].x >> pets[i].y >> pets[i].t;\n    cin >> M;\n    humans.resize(M);\n    for (int i = 0; i < M; i++) cin >> humans[i].x >> humans[i].y;\n\n    memset(wall_, 0, sizeof(wall_));\n\n    int topPets = count_pets_top_initial();\n    int bottomPets = N - topPets;\n\n    int gatherTopAll = 0, gatherBottomAll = 0;\n    for (int i = 0; i < M; i++) {\n        gatherTopAll += abs(humans[i].x - 15);\n        gatherBottomAll += abs(humans[i].x - 16);\n    }\n\n    long long scoreTop = 100LL * topPets + gatherTopAll;\n    long long scoreBottom = 100LL * bottomPets + gatherBottomAll;\n\n    bool secureTop = (scoreTop <= scoreBottom);\n    int standRow = secureTop ? 15 : 16;\n    int barrierRow = secureTop ? 16 : 15;\n\n    roles.assign(M, {0, 15, 15});\n\n    vector<pair<int,int>> corners = {{2,2}, {2,29}, {29,2}, {29,29}};\n    int camper = -1;\n    long long bestScore = (1LL<<60);\n    pair<int,int> camperCorner = {2,2};\n\n    for (int i = 0; i < M; i++) {\n        int distStand = abs(humans[i].x - standRow);\n        int bestCornerDist = 1e9;\n        pair<int,int> bestC = corners[0];\n        for (auto c : corners) {\n            int d = manhattan(humans[i].x, humans[i].y, c.first, c.second);\n            if (d < bestCornerDist) {\n                bestCornerDist = d;\n                bestC = c;\n            }\n        }\n\n        int yIsolation = 30;\n        for (int j = 0; j < M; j++) if (i != j) {\n            yIsolation = min(yIsolation, abs(humans[i].y - humans[j].y));\n        }\n\n        long long val = 8LL * bestCornerDist - 5LL * distStand + 3LL * yIsolation;\n        if (val < bestScore) {\n            bestScore = val;\n            camper = i;\n            camperCorner = bestC;\n        }\n    }\n\n    if (camper != -1) {\n        roles[camper] = {1, camperCorner.first, camperCorner.second};\n    }\n\n    vector<int> builderIds;\n    for (int i = 0; i < M; i++) if (i != camper) builderIds.push_back(i);\n\n    vector<int> builderOrder = builderIds;\n    sort(builderOrder.begin(), builderOrder.end());\n    vector<int> builderRank(M, -1);\n    for (int i = 0; i < (int)builderOrder.size(); i++) builderRank[builderOrder[i]] = i;\n\n    for (int turn = 0; turn < TURNS; turn++) {\n        memset(pet_at, 0, sizeof(pet_at));\n        memset(human_at, 0, sizeof(human_at));\n        for (auto &p : pets) pet_at[p.x][p.y] = true;\n        for (auto &h : humans) human_at[h.x][h.y] = true;\n\n        int built = count_line_built(barrierRow);\n        bool phaseSeal = (built >= 16 || turn >= 160);\n\n        vector<int> targetCol = assign_builder_columns_global(builderIds, barrierRow, standRow);\n\n        string ans(M, '.');\n        vector<vector<int>> blocked_future(31, vector<int>(31, 0));\n        vector<pair<int,int>> reserved_moves(M, {-1, -1});\n\n        for (int i = 0; i < M; i++) {\n            if (roles[i].type != 0) continue;\n            int x = humans[i].x, y = humans[i].y;\n            if (x != standRow) continue;\n\n            int bd = (barrierRow == x + 1 ? 1 : (barrierRow == x - 1 ? 0 : -1));\n            if (bd == -1) continue;\n\n            int bx = x + dx[bd], by = y + dy[bd];\n            if (!inside(bx, by)) continue;\n            if (blocked_future[bx][by]) continue;\n            if (can_block_startturn(bx, by)) {\n                ans[i] = BCH[bd];\n                blocked_future[bx][by] = 1;\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            if (ans[i] != '.') continue;\n\n            int x = humans[i].x, y = humans[i].y;\n\n            if (roles[i].type == 1) {\n                if (manhattan(x, y, roles[i].tx, roles[i].ty) <= 1) {\n                    vector<int> pref;\n                    if (x <= 2) pref.push_back(1);\n                    if (x >= 29) pref.push_back(0);\n                    if (y <= 2) pref.push_back(3);\n                    if (y >= 29) pref.push_back(2);\n\n                    bool done = false;\n                    for (int d : pref) {\n                        int bx = x + dx[d], by = y + dy[d];\n                        if (!inside(bx, by)) continue;\n                        if (blocked_future[bx][by]) continue;\n                        if (can_block_startturn(bx, by)) {\n                            ans[i] = BCH[d];\n                            blocked_future[bx][by] = 1;\n                            done = true;\n                            break;\n                        }\n                    }\n                    if (done) continue;\n                }\n\n                char c = move_toward_safe(i, roles[i].tx, roles[i].ty, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            if (x != standRow) {\n                char c = move_toward_safe(i, standRow, y, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n                continue;\n            }\n\n            if (!phaseSeal) {\n                if (!wall_[barrierRow][y] && !blocked_future[barrierRow][y]) {\n                    ans[i] = '.';\n                    continue;\n                }\n                char c = move_toward_safe(i, standRow, targetCol[i], blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n            } else {\n                int endY = (builderRank[i] * 2 < (int)builderIds.size() ? 1 : 30);\n\n                if (!wall_[barrierRow][y] && !blocked_future[barrierRow][y]) {\n                    ans[i] = '.';\n                    continue;\n                }\n                char c = move_toward_safe(i, standRow, endY, blocked_future, reserved_moves);\n                ans[i] = c;\n                int d = move_dir(c);\n                if (d != -1) reserved_moves[i] = {x + dx[d], y + dy[d]};\n            }\n        }\n\n        {\n            set<pair<int,int>> used;\n            for (int i = 0; i < M; i++) {\n                int md = move_dir(ans[i]);\n                if (md == -1) continue;\n                int nx = humans[i].x + dx[md], ny = humans[i].y + dy[md];\n                bool bad = false;\n                if (!inside(nx, ny)) bad = true;\n                if (!bad && wall_[nx][ny]) bad = true;\n                if (!bad && blocked_future[nx][ny]) bad = true;\n                if (!bad && used.count({nx, ny})) bad = true;\n                if (bad) ans[i] = '.';\n                else used.insert({nx, ny});\n            }\n        }\n\n        cout << ans << '\\n';\n        cout.flush();\n\n        for (int i = 0; i < M; i++) {\n            int md = move_dir(ans[i]);\n            int bd = build_dir(ans[i]);\n\n            if (md != -1) {\n                int nx = humans[i].x + dx[md], ny = humans[i].y + dy[md];\n                if (inside(nx, ny) && !wall_[nx][ny] && !blocked_future[nx][ny]) {\n                    humans[i].x = nx;\n                    humans[i].y = ny;\n                }\n            } else if (bd != -1) {\n                int bx = humans[i].x + dx[bd], by = humans[i].y + dy[bd];\n                if (inside(bx, by) && can_block_startturn(bx, by)) {\n                    wall_[bx][by] = true;\n                }\n            }\n        }\n\n        for (int i = 0; i < N; i++) {\n            string s;\n            cin >> s;\n            if (!cin) return 0;\n            if (s == \".\") continue;\n            for (char c : s) {\n                int d = move_dir(c);\n                if (d == -1) continue;\n                int nx = pets[i].x + dx[d], ny = pets[i].y + dy[d];\n                if (inside(nx, ny) && !wall_[nx][ny]) {\n                    pets[i].x = nx;\n                    pets[i].y = ny;\n                }\n            }\n        }\n    }\n\n    return 0;\n}","ahc009":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int H = 20;\nstatic constexpr int W = 20;\nstatic constexpr int N = H * W;\nstatic constexpr int MAXL = 200;\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 ed = chrono::high_resolution_clock::now();\n        return chrono::duration<double>(ed - 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 l, int r) {\n        return l + (int)(next_u64() % (uint64_t)(r - l + 1));\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nint si, sj, ti, tj;\ndouble pforget;\nstring hs[H];\nstring vs[H - 1];\n\nint nxtCell[N][4];\nint distToTarget[N];\nchar dirch[4] = {'U', 'D', 'L', 'R'};\n\ninline int id(int i, int j) { return i * W + j; }\n\nint c2d(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\ndouble eval_string(const string &s) {\n    int S = id(si, sj), T = id(ti, tj);\n    vector<double> cur(N, 0.0), nx(N, 0.0);\n    cur[S] = 1.0;\n    double ans = 0.0;\n    for (int t = 1; t <= (int)s.size(); t++) {\n        int d = c2d(s[t - 1]);\n        fill(nx.begin(), nx.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == T) {\n                ans += pr * (401 - t);\n                continue;\n            }\n            nx[v] += pr * pforget;\n            nx[nxtCell[v][d]] += pr * (1.0 - pforget);\n        }\n        cur.swap(nx);\n    }\n    return ans;\n}\n\nvector<double> distribution_after(const string &s) {\n    int S = id(si, sj), T = id(ti, tj);\n    vector<double> cur(N, 0.0), nx(N, 0.0);\n    cur[S] = 1.0;\n    for (char c : s) {\n        int d = c2d(c);\n        fill(nx.begin(), nx.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == T) continue;\n            nx[v] += pr * pforget;\n            nx[nxtCell[v][d]] += pr * (1.0 - pforget);\n        }\n        cur.swap(nx);\n    }\n    return cur;\n}\n\nvoid bfs_target() {\n    fill(distToTarget, distToTarget + N, (int)1e9);\n    int T = id(ti, tj);\n    queue<int> q;\n    distToTarget[T] = 0;\n    q.push(T);\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int i = v / W, j = v % W;\n        if (i > 0) {\n            int u = id(i - 1, j);\n            if (nxtCell[u][1] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n        if (i + 1 < H) {\n            int u = id(i + 1, j);\n            if (nxtCell[u][0] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n        if (j > 0) {\n            int u = id(i, j - 1);\n            if (nxtCell[u][3] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n        if (j + 1 < W) {\n            int u = id(i, j + 1);\n            if (nxtCell[u][2] == v && distToTarget[u] > distToTarget[v] + 1) {\n                distToTarget[u] = distToTarget[v] + 1;\n                q.push(u);\n            }\n        }\n    }\n}\n\nstring random_shortest_to_target() {\n    int S = id(si, sj), T = id(ti, tj);\n    string s;\n    int cur = S;\n    while (cur != T) {\n        vector<int> cand;\n        for (int d = 0; d < 4; d++) {\n            int to = nxtCell[cur][d];\n            if (to == cur) continue;\n            if (distToTarget[to] + 1 == distToTarget[cur]) cand.push_back(d);\n        }\n        if (cand.empty()) break;\n        int d = cand[rng.next_int(0, (int)cand.size() - 1)];\n        s.push_back(dirch[d]);\n        cur = nxtCell[cur][d];\n    }\n    return s;\n}\n\nstring repeat_each(const string &base, int k, int lim = MAXL) {\n    string s;\n    s.reserve(min(lim, (int)base.size() * k));\n    for (char c : base) {\n        for (int i = 0; i < k && (int)s.size() < lim; i++) s.push_back(c);\n    }\n    return s;\n}\n\nstring build_suffix_from_dist(vector<double> cur, int len) {\n    int T = id(ti, tj);\n    vector<double> nx(N, 0.0);\n    string suf;\n    suf.reserve(len);\n\n    for (int step = 0; step < len; step++) {\n        int bestD = 0;\n        double bestScore = -1e100;\n        for (int d = 0; d < 4; d++) {\n            double sc = 0.0;\n            for (int v = 0; v < N; v++) {\n                double pr = cur[v];\n                if (pr == 0.0) continue;\n                if (v == T) {\n                    sc += pr * 1e6;\n                    continue;\n                }\n                int to = nxtCell[v][d];\n                sc += pr * ((1.0 - pforget) * (distToTarget[v] - distToTarget[to]));\n                if (to == T) sc += pr * (1.0 - pforget) * 1000.0;\n            }\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestD = d;\n            }\n        }\n\n        suf.push_back(dirch[bestD]);\n        fill(nx.begin(), nx.end(), 0.0);\n        for (int v = 0; v < N; v++) {\n            double pr = cur[v];\n            if (pr == 0.0) continue;\n            if (v == T) {\n                nx[v] += pr;\n            } else {\n                nx[v] += pr * pforget;\n                nx[nxtCell[v][bestD]] += pr * (1.0 - pforget);\n            }\n        }\n        cur.swap(nx);\n    }\n    return suf;\n}\n\nstring build_candidate(const string &base, int totalLen, int rep) {\n    string pref = repeat_each(base, rep, totalLen);\n    if ((int)pref.size() < totalLen) {\n        auto dist = distribution_after(pref);\n        pref += build_suffix_from_dist(dist, totalLen - (int)pref.size());\n    }\n    return pref;\n}\n\nbool coordinate_optimize(string &s) {\n    int L = (int)s.size();\n    if (L == 0) return false;\n    int S = id(si, sj), T = id(ti, tj);\n\n    vector<vector<double>> pref(L + 1, vector<double>(N, 0.0));\n    vector<vector<double>> suf(L + 1, vector<double>(N, 0.0));\n\n    pref[0][S] = 1.0;\n    for (int t = 0; t < L; t++) {\n        int d = c2d(s[t]);\n        for (int v = 0; v < N; v++) {\n            double pr = pref[t][v];\n            if (pr == 0.0 || v == T) continue;\n            pref[t + 1][v] += pr * pforget;\n            int to = nxtCell[v][d];\n            if (to != T) pref[t + 1][to] += pr * (1.0 - pforget);\n        }\n    }\n\n    for (int v = 0; v < N; v++) suf[L][v] = 0.0;\n    for (int t = L - 1; t >= 0; t--) {\n        int reward = 401 - (t + 1);\n        int d = c2d(s[t]);\n        for (int v = 0; v < N; v++) {\n            if (v == T) {\n                suf[t][v] = 0.0;\n                continue;\n            }\n            int to = nxtCell[v][d];\n            double val = pforget * suf[t + 1][v];\n            if (to == T) val += (1.0 - pforget) * reward;\n            else val += (1.0 - pforget) * suf[t + 1][to];\n            suf[t][v] = val;\n        }\n    }\n\n    bool improved = false;\n    for (int t = 0; t < L; t++) {\n        int reward = 401 - (t + 1);\n        char bestC = s[t];\n        double bestVal = -1e100;\n\n        for (int d = 0; d < 4; d++) {\n            double total = 0.0;\n            for (int v = 0; v < N; v++) {\n                double pr = pref[t][v];\n                if (pr == 0.0 || v == T) continue;\n                int to = nxtCell[v][d];\n                double add = pforget * suf[t + 1][v];\n                if (to == T) add += (1.0 - pforget) * reward;\n                else add += (1.0 - pforget) * suf[t + 1][to];\n                total += pr * add;\n            }\n            if (total > bestVal) {\n                bestVal = total;\n                bestC = dirch[d];\n            }\n        }\n\n        if (bestC != s[t]) {\n            s[t] = bestC;\n            improved = true;\n        }\n    }\n    return improved;\n}\n\nstring mutate(const string &s, const vector<string> &pathPool) {\n    string t = s;\n    int op = rng.next_int(0, 99);\n\n    if (op < 16 && !t.empty()) {\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t[i] = dirch[rng.next_int(0, 3)];\n    } else if (op < 28 && (int)t.size() < MAXL) {\n        int i = rng.next_int(0, (int)t.size());\n        t.insert(t.begin() + i, dirch[rng.next_int(0, 3)]);\n    } else if (op < 38 && !t.empty()) {\n        int i = rng.next_int(0, (int)t.size() - 1);\n        t.erase(t.begin() + i);\n    } else if (op < 52 && !t.empty()) {\n        int l = rng.next_int(0, (int)t.size() - 1);\n        int r = rng.next_int(l, min((int)t.size() - 1, l + 7));\n        string seg = t.substr(l, r - l + 1);\n        if ((int)t.size() + (int)seg.size() <= MAXL) {\n            int pos = rng.next_int(0, (int)t.size());\n            t.insert(pos, seg);\n        }\n    } else if (op < 66 && !t.empty()) {\n        int l = rng.next_int(0, (int)t.size() - 1);\n        int r = rng.next_int(l, min((int)t.size() - 1, l + 9));\n        for (int i = l; i <= r; i++) t[i] = dirch[rng.next_int(0, 3)];\n    } else if (op < 78 && !pathPool.empty()) {\n        string seg = pathPool[rng.next_int(0, (int)pathPool.size() - 1)];\n        if (seg.empty()) seg = \"R\";\n        if ((int)seg.size() > 12) {\n            int l = rng.next_int(0, (int)seg.size() - 1);\n            int r = rng.next_int(l, min((int)seg.size() - 1, l + 11));\n            seg = seg.substr(l, r - l + 1);\n        }\n        int pos = rng.next_int(0, (int)t.size());\n        int del = min((int)t.size() - pos, rng.next_int(0, 8));\n        t.erase(pos, del);\n        if ((int)t.size() + (int)seg.size() > MAXL) seg.resize(MAXL - (int)t.size());\n        t.insert(pos, seg);\n    } else if (op < 90 && !t.empty()) {\n        int cut = rng.next_int(0, (int)t.size());\n        string pref = t.substr(0, cut);\n        auto dist = distribution_after(pref);\n        t = pref + build_suffix_from_dist(dist, MAXL - cut);\n    } else {\n        if (!t.empty()) {\n            int i = rng.next_int(0, (int)t.size() - 1);\n            char c = t[i];\n            int l = i, r = i;\n            while (l > 0 && t[l - 1] == c) l--;\n            while (r + 1 < (int)t.size() && t[r + 1] == c) r++;\n            int len = r - l + 1;\n            int newlen = max(1, min(10, len + rng.next_int(-2, 3)));\n            string rep(newlen, c);\n            t.replace(l, len, rep);\n            if ((int)t.size() > MAXL) t.resize(MAXL);\n        }\n    }\n\n    if ((int)t.size() > MAXL) t.resize(MAXL);\n    return t;\n}\n\nstruct Cand {\n    string s;\n    double val;\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 < H; i++) cin >> hs[i];\n    for (int i = 0; i < H - 1; i++) cin >> vs[i];\n\n    for (int i = 0; i < H; i++) {\n        for (int j = 0; j < W; j++) {\n            int v = id(i, j);\n            if (i == 0 || vs[i - 1][j] == '1') nxtCell[v][0] = v;\n            else nxtCell[v][0] = id(i - 1, j);\n            if (i == H - 1 || vs[i][j] == '1') nxtCell[v][1] = v;\n            else nxtCell[v][1] = id(i + 1, j);\n            if (j == 0 || hs[i][j - 1] == '1') nxtCell[v][2] = v;\n            else nxtCell[v][2] = id(i, j - 1);\n            if (j == W - 1 || hs[i][j] == '1') nxtCell[v][3] = v;\n            else nxtCell[v][3] = id(i, j + 1);\n        }\n    }\n\n    bfs_target();\n    Timer timer;\n    const double TL = 1.95;\n\n    vector<string> pathPool;\n    for (int i = 0; i < 50; i++) pathPool.push_back(random_shortest_to_target());\n    sort(pathPool.begin(), pathPool.end());\n    pathPool.erase(unique(pathPool.begin(), pathPool.end()), pathPool.end());\n    if (pathPool.empty()) pathPool.push_back(\"\");\n\n    vector<int> lens = {60, 80, 100, 120, 140, 160, 180, 200};\n    vector<int> reps;\n    if (pforget <= 0.15) reps = {1,2,3,4};\n    else if (pforget <= 0.25) reps = {2,3,4,5};\n    else if (pforget <= 0.35) reps = {3,4,5,6};\n    else reps = {4,5,6,7,8};\n\n    vector<Cand> elite;\n    auto push_elite = [&](const string &s, double v) {\n        for (auto &e : elite) {\n            if (e.s == s) {\n                if (v > e.val) e.val = v;\n                return;\n            }\n        }\n        elite.push_back({s, v});\n        sort(elite.begin(), elite.end(), [](const Cand &a, const Cand &b) { return a.val > b.val; });\n        const int ELIM = 10;\n        if ((int)elite.size() > ELIM) elite.resize(ELIM);\n    };\n\n    // Seed generation\n    for (const string &base : pathPool) {\n        if (timer.elapsed() > 0.55) break;\n        for (int L : lens) {\n            for (int k : reps) {\n                string cand = build_candidate(base, L, k);\n                if (rng.next_double() < 0.75) coordinate_optimize(cand);\n                double v = eval_string(cand);\n                push_elite(cand, v);\n            }\n        }\n    }\n\n    if (elite.empty()) {\n        string s = pathPool[0];\n        double v = eval_string(s);\n        push_elite(s, v);\n    }\n\n    // Direct polishing on elites\n    for (int round = 0; round < 2 && timer.elapsed() < 0.85; round++) {\n        vector<Cand> now = elite;\n        for (auto &e : now) {\n            string cand = e.s;\n            bool ch = coordinate_optimize(cand);\n            double v = eval_string(cand);\n            if (v > e.val || ch) push_elite(cand, v);\n            if (timer.elapsed() >= 0.85) break;\n        }\n    }\n\n    int iter = 0;\n    while (true) {\n        double tm = timer.elapsed();\n        if (tm > TL) break;\n        iter++;\n\n        int idx = rng.next_int(0, (int)elite.size() - 1);\n        string base = elite[idx].s;\n        double baseVal = elite[idx].val;\n\n        string cand = mutate(base, pathPool);\n        if (rng.next_double() < 0.20) coordinate_optimize(cand);\n        double nv = eval_string(cand);\n\n        double progress = tm / TL;\n        double temp = 1200.0 * (1.0 - progress) + 1e-9;\n        double diff = nv - baseVal;\n\n        if (diff >= 0 || rng.next_double() < exp(diff / temp)) {\n            push_elite(cand, nv);\n        }\n\n        if ((iter % 200) == 0) {\n            string b = pathPool[rng.next_int(0, (int)pathPool.size() - 1)];\n            int L = lens[rng.next_int(0, (int)lens.size() - 1)];\n            int k = reps[rng.next_int(0, (int)reps.size() - 1)];\n            string cand2 = build_candidate(b, L, k);\n            if (rng.next_double() < 0.5) coordinate_optimize(cand2);\n            double v2 = eval_string(cand2);\n            push_elite(cand2, v2);\n        }\n    }\n\n    string best = elite[0].s;\n    double bestVal = elite[0].val;\n\n    while (timer.elapsed() < TL) {\n        string cand = best;\n        bool ch = coordinate_optimize(cand);\n        double v = eval_string(cand);\n        if (v > bestVal) {\n            bestVal = v;\n            best = cand;\n        } else if (!ch) {\n            break;\n        } else {\n            break;\n        }\n    }\n\n    if ((int)best.size() > MAXL) best.resize(MAXL);\n    cout << best << '\\n';\n    return 0;\n}","ahc010":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 30;\nstatic constexpr int NN = N * N;\n\nstatic const int di[4] = {0, -1, 0, 1}; // L U R D\nstatic const int dj[4] = {-1, 0, 1, 0};\n\nstatic const int TO[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\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\ninline int rotTile(int t, int r) {\n    r &= 3;\n    while (r--) {\n        if (t <= 3) t = (t + 1) & 3;\n        else if (t <= 5) t = 9 - t;\n        else t = 13 - t;\n    }\n    return t;\n}\n\ninline int maskOfTile(int t) {\n    int m = 0;\n    for (int d = 0; d < 4; d++) if (TO[t][d] != -1) m |= (1 << d);\n    return m;\n}\n\nstruct Solver {\n    array<string, N> s;\n    int base[N][N];\n    int rotTileId[N][N][4];\n    int rotMask[N][N][4];\n    mt19937 rng;\n\n    Solver() : rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()) {}\n\n    void readInput() {\n        for (int i = 0; i < N; i++) {\n            cin >> s[i];\n            for (int j = 0; j < N; j++) {\n                base[i][j] = s[i][j] - '0';\n                for (int r = 0; r < 4; r++) {\n                    rotTileId[i][j][r] = rotTile(base[i][j], r);\n                    rotMask[i][j][r] = maskOfTile(rotTileId[i][j][r]);\n                }\n            }\n        }\n    }\n\n    long long exactScore(const array<unsigned char, NN>& rot) const {\n        static int tile[N][N];\n        static unsigned char vis[N][N][4];\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            tile[i][j] = rotTileId[i][j][rot[i * N + j]];\n        }\n        memset(vis, 0, sizeof(vis));\n\n        int best1 = 0, best2 = 0;\n\n        for (int si = 0; si < N; si++) for (int sj = 0; sj < N; sj++) for (int sd = 0; sd < 4; sd++) {\n            if (vis[si][sj][sd]) continue;\n\n            int i = si, j = sj, d = sd, len = 0;\n            bool ok = true;\n\n            while (true) {\n                if (vis[i][j][d]) {\n                    ok = false;\n                    break;\n                }\n                vis[i][j][d] = 1;\n                int d2 = TO[tile[i][j]][d];\n                if (d2 == -1) {\n                    ok = false;\n                    break;\n                }\n                i += di[d2];\n                j += dj[d2];\n                if (i < 0 || i >= N || j < 0 || j >= N) {\n                    ok = false;\n                    break;\n                }\n                d = (d2 + 2) & 3;\n                ++len;\n                if (i == si && j == sj && d == sd) break;\n                if (len > 4 * NN + 10) {\n                    ok = false;\n                    break;\n                }\n            }\n\n            if (ok) {\n                if (len > best1) {\n                    best2 = best1;\n                    best1 = len;\n                } else if (len > best2) {\n                    best2 = len;\n                }\n            }\n        }\n\n        return best2 == 0 ? 0 : 1LL * best1 * best2;\n    }\n\n    inline int cellContribution(const array<unsigned char, NN>& rot, int i, int j) const {\n        int m = rotMask[i][j][rot[i * N + j]];\n        int sc = 0;\n\n        if (j + 1 < N) {\n            int m2 = rotMask[i][j + 1][rot[i * N + (j + 1)]];\n            if (((m >> 2) & 1) && ((m2 >> 0) & 1)) sc += 1;\n        } else if ((m >> 2) & 1) {\n            sc -= 1;\n        }\n\n        if (i + 1 < N) {\n            int m2 = rotMask[i + 1][j][rot[(i + 1) * N + j]];\n            if (((m >> 3) & 1) && ((m2 >> 1) & 1)) sc += 1;\n        } else if ((m >> 3) & 1) {\n            sc -= 1;\n        }\n\n        if (j == 0 && ((m >> 0) & 1)) sc -= 1;\n        if (i == 0 && ((m >> 1) & 1)) sc -= 1;\n\n        return sc;\n    }\n\n    inline int affected1(const array<unsigned char, NN>& rot, int i, int j) const {\n        int sc = 0;\n        for (int ni = max(0, i - 1); ni <= min(N - 1, i + 1); ni++) {\n            for (int nj = max(0, j - 1); nj <= min(N - 1, j + 1); nj++) {\n                sc += cellContribution(rot, ni, nj);\n            }\n        }\n        return sc;\n    }\n\n    inline int affected2x2(const array<unsigned char, NN>& rot, int i, int j) const {\n        int sc = 0;\n        for (int ni = max(0, i - 1); ni <= min(N - 1, i + 2); ni++) {\n            for (int nj = max(0, j - 1); nj <= min(N - 1, j + 2); nj++) {\n                sc += cellContribution(rot, ni, nj);\n            }\n        }\n        return sc;\n    }\n\n    void quickLocalPass(array<unsigned char, NN>& rot, int rounds = 1) {\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n        for (int rep = 0; rep < rounds; rep++) {\n            shuffle(ord.begin(), ord.end(), rng);\n            bool improved = false;\n            for (int idx : ord) {\n                int i = idx / N, j = idx % N;\n                int before = affected1(rot, i, j);\n                unsigned char old = rot[idx], bestR = old;\n                int bestDelta = 0;\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int delta = affected1(rot, i, j) - before;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = old;\n                if (bestDelta > 0) {\n                    rot[idx] = bestR;\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n    }\n\n    array<unsigned char, NN> makeInitial(int type) {\n        array<unsigned char, NN> rot{};\n\n        if (type == 0) {\n            rot.fill(0);\n        } else if (type == 1) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = (i + j) & 3;\n        } else if (type == 2) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = i & 3;\n        } else if (type == 3) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) rot[i * N + j] = j & 3;\n        } else if (type == 4) {\n            for (int k = 0; k < NN; k++) rot[k] = rng() & 3;\n        } else if (type == 5) {\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n                int best = 0, bestCost = 1e9;\n                for (int r = 0; r < 4; r++) {\n                    int m = rotMask[i][j][r];\n                    int cost = 0;\n                    if (i == 0 && ((m >> 1) & 1)) cost++;\n                    if (i == N - 1 && ((m >> 3) & 1)) cost++;\n                    if (j == 0 && ((m >> 0) & 1)) cost++;\n                    if (j == N - 1 && ((m >> 2) & 1)) cost++;\n                    cost = cost * 10 + (rng() & 3);\n                    if (cost < bestCost) {\n                        bestCost = cost;\n                        best = r;\n                    }\n                }\n                rot[i * N + j] = best;\n            }\n            quickLocalPass(rot, 1);\n        } else {\n            for (int k = 0; k < NN; k++) rot[k] = rng() & 3;\n            quickLocalPass(rot, 1);\n        }\n\n        return rot;\n    }\n\n    void optimizeLocal(array<unsigned char, NN>& rot, Timer& timer, double endTime) {\n        vector<int> ord(NN);\n        iota(ord.begin(), ord.end(), 0);\n\n        while (timer.elapsed() < endTime) {\n            bool improved = false;\n            shuffle(ord.begin(), ord.end(), rng);\n            for (int idx : ord) {\n                if (timer.elapsed() >= endTime) return;\n                int i = idx / N, j = idx % N;\n                int before = affected1(rot, i, j);\n                unsigned char old = rot[idx], bestR = old;\n                int bestDelta = 0;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int delta = affected1(rot, i, j) - before;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = old;\n                if (bestDelta > 0) {\n                    rot[idx] = bestR;\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n    }\n\n    vector<int> collectBadCells(const array<unsigned char, NN>& rot) {\n        vector<int> cells;\n        vector<char> used(NN, 0);\n\n        auto add = [&](int i, int j) {\n            if (i < 0 || i >= N || j < 0 || j >= N) return;\n            int idx = i * N + j;\n            if (!used[idx]) {\n                used[idx] = 1;\n                cells.push_back(idx);\n            }\n        };\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int m = rotMask[i][j][rot[i * N + j]];\n\n            if (j == 0 && ((m >> 0) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n            if (i == 0 && ((m >> 1) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n            if (j == N - 1 && ((m >> 2) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n            if (i == N - 1 && ((m >> 3) & 1)) {\n                for (int a = -1; a <= 1; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n            }\n\n            if (j + 1 < N) {\n                int m2 = rotMask[i][j + 1][rot[i * N + (j + 1)]];\n                if (((m >> 2) & 1) != ((m2 >> 0) & 1)) {\n                    for (int a = -1; a <= 1; a++) for (int b = -1; b <= 2; b++) add(i + a, j + b);\n                }\n            }\n            if (i + 1 < N) {\n                int m2 = rotMask[i + 1][j][rot[(i + 1) * N + j]];\n                if (((m >> 3) & 1) != ((m2 >> 1) & 1)) {\n                    for (int a = -1; a <= 2; a++) for (int b = -1; b <= 1; b++) add(i + a, j + b);\n                }\n            }\n        }\n\n        while ((int)cells.size() < 120) {\n            int idx = (int)(rng() % NN);\n            if (!used[idx]) {\n                used[idx] = 1;\n                cells.push_back(idx);\n            }\n        }\n\n        shuffle(cells.begin(), cells.end(), rng);\n        return cells;\n    }\n\n    void localCleanupAround(array<unsigned char, NN>& rot, int ci, int cj) {\n        vector<int> ord;\n        for (int i = max(0, ci - 1); i <= min(N - 1, ci + 2); i++) {\n            for (int j = max(0, cj - 1); j <= min(N - 1, cj + 2); j++) {\n                ord.push_back(i * N + j);\n            }\n        }\n        for (int rep = 0; rep < 2; rep++) {\n            bool improved = false;\n            for (int idx : ord) {\n                int i = idx / N, j = idx % N;\n                int before = affected1(rot, i, j);\n                unsigned char old = rot[idx], bestR = old;\n                int bestDelta = 0;\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int delta = affected1(rot, i, j) - before;\n                    if (delta > bestDelta) {\n                        bestDelta = delta;\n                        bestR = nr;\n                    }\n                }\n                rot[idx] = old;\n                if (bestDelta > 0) {\n                    rot[idx] = bestR;\n                    improved = true;\n                }\n            }\n            if (!improved) break;\n        }\n    }\n\n    void targeted1Cell(array<unsigned char, NN>& rot, long long& curScore, Timer& timer, double endTime) {\n        while (timer.elapsed() < endTime) {\n            auto cells = collectBadCells(rot);\n            bool improved = false;\n\n            for (int pos = 0; pos < (int)cells.size(); pos++) {\n                if (timer.elapsed() >= endTime) return;\n                int idx = cells[pos];\n                int i = idx / N, j = idx % N;\n                int beforeLocal = affected1(rot, i, j);\n                unsigned char old = rot[idx], bestR = old;\n                long long bestSc = curScore;\n                int bestLocal = -1e9;\n\n                for (unsigned char nr = 0; nr < 4; nr++) {\n                    if (nr == old) continue;\n                    rot[idx] = nr;\n                    int localDelta = affected1(rot, i, j) - beforeLocal;\n                    if (localDelta < 0) continue;\n                    long long sc = exactScore(rot);\n                    if (sc > bestSc || (sc == bestSc && localDelta > bestLocal)) {\n                        bestSc = sc;\n                        bestLocal = localDelta;\n                        bestR = nr;\n                    }\n                }\n\n                if (bestR == old && (pos % 8 == 0)) {\n                    for (unsigned char nr = 0; nr < 4; nr++) {\n                        if (nr == old) continue;\n                        rot[idx] = nr;\n                        int localDelta = affected1(rot, i, j) - beforeLocal;\n                        if (localDelta != -1) continue;\n                        long long sc = exactScore(rot);\n                        if (sc > bestSc || (sc == bestSc && localDelta > bestLocal)) {\n                            bestSc = sc;\n                            bestLocal = localDelta;\n                            bestR = nr;\n                        }\n                    }\n                }\n\n                rot[idx] = old;\n\n                if (bestR != old) {\n                    rot[idx] = bestR;\n                    curScore = bestSc;\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void targeted2x2(array<unsigned char, NN>& rot, long long& curScore, Timer& timer, double endTime) {\n        while (timer.elapsed() < endTime) {\n            auto cells = collectBadCells(rot);\n            vector<pair<int,int>> blocks;\n            vector<int> weight((N - 1) * (N - 1), 0);\n            vector<char> used((N - 1) * (N - 1), 0);\n\n            for (int idx : cells) {\n                int i = idx / N, j = idx % N;\n                for (int bi = max(0, i - 1); bi <= min(N - 2, i); bi++) {\n                    for (int bj = max(0, j - 1); bj <= min(N - 2, j); bj++) {\n                        int id = bi * (N - 1) + bj;\n                        weight[id]++;\n                        if (!used[id]) {\n                            used[id] = 1;\n                            blocks.push_back({bi, bj});\n                        }\n                    }\n                }\n            }\n\n            shuffle(blocks.begin(), blocks.end(), rng);\n            sort(blocks.begin(), blocks.end(), [&](const auto& p1, const auto& p2) {\n                int id1 = p1.first * (N - 1) + p1.second;\n                int id2 = p2.first * (N - 1) + p2.second;\n                return weight[id1] > weight[id2];\n            });\n\n            bool improved = false;\n\n            for (auto [i, j] : blocks) {\n                if (timer.elapsed() >= endTime) return;\n                int bid = i * (N - 1) + j;\n                bool strongBlock = (weight[bid] >= 3);\n\n                int ids[4] = {i * N + j, i * N + (j + 1), (i + 1) * N + j, (i + 1) * N + (j + 1)};\n                unsigned char old[4] = {rot[ids[0]], rot[ids[1]], rot[ids[2]], rot[ids[3]]};\n                int before = affected2x2(rot, i, j);\n\n                struct Cand {\n                    int localDelta;\n                    unsigned char a, b, c, d;\n                };\n                vector<Cand> cand;\n                cand.reserve(256);\n\n                for (unsigned char a = 0; a < 4; a++) for (unsigned char b = 0; b < 4; b++)\n                for (unsigned char c = 0; c < 4; c++) for (unsigned char d = 0; d < 4; d++) {\n                    rot[ids[0]] = a; rot[ids[1]] = b; rot[ids[2]] = c; rot[ids[3]] = d;\n                    int delta = affected2x2(rot, i, j) - before;\n                    cand.push_back({delta, a, b, c, d});\n                }\n\n                rot[ids[0]] = old[0];\n                rot[ids[1]] = old[1];\n                rot[ids[2]] = old[2];\n                rot[ids[3]] = old[3];\n\n                int K = min<int>(6, cand.size());\n                nth_element(cand.begin(), cand.begin() + K, cand.end(),\n                            [](const Cand& x, const Cand& y){ return x.localDelta > y.localDelta; });\n\n                long long bestSc = curScore;\n                int bestLocal = -1e9;\n                unsigned char br[4] = {old[0], old[1], old[2], old[3]};\n\n                for (int t = 0; t < K; t++) {\n                    auto &x = cand[t];\n                    if (x.localDelta < (strongBlock ? -1 : 0)) continue;\n                    rot[ids[0]] = x.a; rot[ids[1]] = x.b; rot[ids[2]] = x.c; rot[ids[3]] = x.d;\n                    long long sc = exactScore(rot);\n                    if (sc > bestSc || (sc == bestSc && x.localDelta > bestLocal)) {\n                        bestSc = sc;\n                        bestLocal = x.localDelta;\n                        br[0] = x.a; br[1] = x.b; br[2] = x.c; br[3] = x.d;\n                    }\n                }\n\n                rot[ids[0]] = old[0];\n                rot[ids[1]] = old[1];\n                rot[ids[2]] = old[2];\n                rot[ids[3]] = old[3];\n\n                bool changed = !(br[0] == old[0] && br[1] == old[1] && br[2] == old[2] && br[3] == old[3]);\n                if (changed) {\n                    rot[ids[0]] = br[0];\n                    rot[ids[1]] = br[1];\n                    rot[ids[2]] = br[2];\n                    rot[ids[3]] = br[3];\n                    localCleanupAround(rot, i, j);\n                    curScore = exactScore(rot);\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void randomKick(array<unsigned char, NN>& rot, int k) {\n        for (int t = 0; t < k; t++) {\n            int idx = (int)(rng() % NN);\n            rot[idx] = rng() & 3;\n        }\n    }\n\n    void badCellKick(array<unsigned char, NN>& rot, int k) {\n        auto cells = collectBadCells(rot);\n        if (cells.empty()) return;\n        for (int t = 0; t < k; t++) {\n            int idx = cells[rng() % cells.size()];\n            rot[idx] = rng() & 3;\n        }\n    }\n\n    void solve() {\n        Timer timer;\n        const double TL = 1.95;\n\n        array<unsigned char, NN> globalBest = makeInitial(0);\n        long long globalBestScore = exactScore(globalBest);\n\n        int trial = 0;\n        while (timer.elapsed() < TL * 0.82) {\n            array<unsigned char, NN> rot;\n            if (trial < 7) rot = makeInitial(trial);\n            else rot = makeInitial(4 + (rng() % 3)); // 4,5,6\n\n            double rem = TL - timer.elapsed();\n            if (rem <= 0) break;\n\n            optimizeLocal(rot, timer, min(TL, timer.elapsed() + min(0.12, rem * 0.30)));\n\n            long long sc = exactScore(rot);\n            if (sc > globalBestScore) {\n                globalBestScore = sc;\n                globalBest = rot;\n            }\n\n            if (timer.elapsed() < TL) {\n                targeted1Cell(rot, sc, timer, min(TL, timer.elapsed() + 0.24));\n                if (sc > globalBestScore) {\n                    globalBestScore = sc;\n                    globalBest = rot;\n                }\n            }\n\n            if (timer.elapsed() < TL) {\n                targeted2x2(rot, sc, timer, min(TL, timer.elapsed() + 0.46));\n                if (sc > globalBestScore) {\n                    globalBestScore = sc;\n                    globalBest = rot;\n                }\n            }\n\n            if (timer.elapsed() < TL) {\n                auto kicked = rot;\n                randomKick(kicked, 8);\n                optimizeLocal(kicked, timer, min(TL, timer.elapsed() + 0.04));\n                long long sc2 = exactScore(kicked);\n                targeted1Cell(kicked, sc2, timer, min(TL, timer.elapsed() + 0.14));\n                if (sc2 > globalBestScore) {\n                    globalBestScore = sc2;\n                    globalBest = kicked;\n                }\n            }\n\n            trial++;\n        }\n\n        // Late-stage refinement from global best with focused bad-cell kicks\n        while (timer.elapsed() < TL) {\n            auto rot = globalBest;\n            badCellKick(rot, 6);\n            quickLocalPass(rot, 1);\n            long long sc = exactScore(rot);\n\n            if (timer.elapsed() < TL) {\n                targeted1Cell(rot, sc, timer, min(TL, timer.elapsed() + 0.06));\n            }\n            if (timer.elapsed() < TL) {\n                targeted2x2(rot, sc, timer, min(TL, timer.elapsed() + 0.08));\n            }\n\n            if (sc > globalBestScore) {\n                globalBestScore = sc;\n                globalBest = rot;\n            } else {\n                // tiny diversification\n                auto rot2 = globalBest;\n                randomKick(rot2, 4);\n                quickLocalPass(rot2, 1);\n                long long sc2 = exactScore(rot2);\n                if (timer.elapsed() < TL) {\n                    targeted1Cell(rot2, sc2, timer, min(TL, timer.elapsed() + 0.04));\n                }\n                if (sc2 > globalBestScore) {\n                    globalBestScore = sc2;\n                    globalBest = rot2;\n                }\n            }\n        }\n\n        string ans(NN, '0');\n        for (int i = 0; i < NN; i++) ans[i] = char('0' + globalBest[i]);\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.readInput();\n    solver.solve();\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\nstatic constexpr int DI[4] = {-1, 1, 0, 0};\nstatic constexpr int DJ[4] = {0, 0, -1, 1};\nstatic constexpr char DC[4] = {'U', 'D', 'L', 'R'};\n\nint N, Tlim;\nvector<unsigned char> init_board;\nint init_empty;\n\ninline int opp(int d) { return d ^ 1; }\ninline int c2d(char c) { return c == 'U' ? 0 : c == 'D' ? 1 : c == 'L' ? 2 : 3; }\n\ninline bool can_move(int empty_pos, int d) {\n    int i = empty_pos / N, j = empty_pos % N;\n    int ni = i + DI[d], nj = j + DJ[d];\n    return 0 <= ni && ni < N && 0 <= nj && nj < N;\n}\n\ninline void apply_move(vector<unsigned char>& board, int& empty_pos, int d) {\n    int ei = empty_pos / N, ej = empty_pos % N;\n    int ni = ei + DI[d], nj = ej + DJ[d];\n    int np = ni * N + nj;\n    swap(board[empty_pos], board[np]);\n    empty_pos = np;\n}\n\nstruct Eval {\n    int largestTree;\n    int matchedEdges;\n    int largestComponent;\n    int cyclePenalty;\n};\n\nEval evaluate_board_detail(const vector<unsigned char>& board) {\n    int V = N * N;\n    static int g[100][4];\n    static int deg[100];\n    static unsigned char alive[100];\n    static unsigned char vis[100];\n\n    for (int p = 0; p < V; ++p) {\n        deg[p] = 0;\n        alive[p] = (board[p] != 0);\n        vis[p] = 0;\n    }\n\n    auto has = [&](int mask, int bit) -> bool { return (mask & bit) != 0; };\n\n    int matchedEdges = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            int p = i * N + j;\n            if (!alive[p]) continue;\n            int m = board[p];\n            if (i + 1 < N) {\n                int q = (i + 1) * N + j;\n                if (alive[q] && has(m, 8) && has(board[q], 2)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                    ++matchedEdges;\n                }\n            }\n            if (j + 1 < N) {\n                int q = i * N + (j + 1);\n                if (alive[q] && has(m, 4) && has(board[q], 1)) {\n                    g[p][deg[p]++] = q;\n                    g[q][deg[q]++] = p;\n                    ++matchedEdges;\n                }\n            }\n        }\n    }\n\n    int largestTree = 0;\n    int largestComponent = 0;\n    int cyclePenalty = 0;\n\n    int q[100];\n    for (int s = 0; s < V; ++s) {\n        if (!alive[s] || vis[s]) continue;\n        int head = 0, tail = 0;\n        q[tail++] = s;\n        vis[s] = 1;\n        int vc = 0, sumdeg = 0;\n        while (head < tail) {\n            int v = q[head++];\n            ++vc;\n            sumdeg += deg[v];\n            for (int k = 0; k < deg[v]; ++k) {\n                int to = g[v][k];\n                if (!vis[to]) {\n                    vis[to] = 1;\n                    q[tail++] = to;\n                }\n            }\n        }\n        int ec = sumdeg / 2;\n        largestComponent = max(largestComponent, vc);\n        if (ec == vc - 1) largestTree = max(largestTree, vc);\n        if (ec > vc - 1) cyclePenalty += ec - (vc - 1);\n    }\n\n    return {largestTree, matchedEdges, largestComponent, cyclePenalty};\n}\n\ninline bool better_eval(const Eval& a, const Eval& b) {\n    if (a.largestTree != b.largestTree) return a.largestTree > b.largestTree;\n    if (a.matchedEdges != b.matchedEdges) return a.matchedEdges > b.matchedEdges;\n    if (a.largestComponent != b.largestComponent) return a.largestComponent > b.largestComponent;\n    if (a.cyclePenalty != b.cyclePenalty) return a.cyclePenalty < b.cyclePenalty;\n    return false;\n}\n\nstruct Candidate {\n    string ops;\n    int bestLen = 0;\n    Eval bestEval{0,0,0,0};\n};\n\ninline bool better_cand(const Candidate& a, const Candidate& b) {\n    if (better_eval(a.bestEval, b.bestEval)) return true;\n    if (better_eval(b.bestEval, a.bestEval)) return false;\n    return a.bestLen < b.bestLen;\n}\n\nmt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());\n\nvoid replay_prefix(const string& ops, int upto, vector<unsigned char>& board, int& empty, int& prevDir) {\n    board = init_board;\n    empty = init_empty;\n    prevDir = -1;\n    for (int i = 0; i < upto; ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) break;\n        apply_move(board, empty, d);\n        prevDir = d;\n    }\n}\n\nCandidate evaluate_sequence(const string& ops) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n\n    Candidate res;\n    res.ops = ops;\n    res.bestLen = 0;\n    res.bestEval = evaluate_board_detail(board);\n\n    for (int i = 0; i < (int)ops.size(); ++i) {\n        int d = c2d(ops[i]);\n        if (!can_move(empty, d)) {\n            res.ops.resize(i);\n            break;\n        }\n        apply_move(board, empty, d);\n        Eval e = evaluate_board_detail(board);\n        if (better_eval(e, res.bestEval) ||\n            (!better_eval(res.bestEval, e) && i + 1 < res.bestLen)) {\n            res.bestEval = e;\n            res.bestLen = i + 1;\n        }\n    }\n    return res;\n}\n\nstring random_legal_suffix(int empty, int maxAdd, int prevDir = -1, bool prefer_no_back = true) {\n    string s;\n    s.reserve(maxAdd);\n    for (int step = 0; step < maxAdd; ++step) {\n        int cand[4], cnt = 0;\n        for (int d = 0; d < 4; ++d) {\n            if (!can_move(empty, d)) continue;\n            if (prefer_no_back && prevDir != -1 && d == opp(prevDir)) continue;\n            cand[cnt++] = d;\n        }\n        if (cnt == 0) {\n            for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n        }\n        int d = cand[rng() % cnt];\n        s.push_back(DC[d]);\n        int ei = empty / N, ej = empty % N;\n        int ni = ei + DI[d], nj = ej + DJ[d];\n        empty = ni * N + nj;\n        prevDir = d;\n    }\n    return s;\n}\n\nint greedy_choose_move(const vector<unsigned char>& board, int empty, int prevDir) {\n    Eval bestE{-1,-1,-1,(int)1e9};\n    int bestD = -1;\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n    shuffle(cand, cand + cnt, rng);\n\n    for (int ii = 0; ii < cnt; ++ii) {\n        int d = cand[ii];\n        vector<unsigned char> nb = board;\n        int ne = empty;\n        apply_move(nb, ne, d);\n        Eval e = evaluate_board_detail(nb);\n        if (bestD == -1 || better_eval(e, bestE) ||\n            (!better_eval(bestE, e) && prevDir != -1 && bestD == opp(prevDir) && d != opp(prevDir))) {\n            bestE = e;\n            bestD = d;\n        }\n    }\n    return bestD;\n}\n\nint greedy_choose_move2(const vector<unsigned char>& board, int empty, int prevDir) {\n    bool first = true;\n    Eval bestFirst{-1,-1,-1,(int)1e9};\n    Eval bestSecond{-1,-1,-1,(int)1e9};\n    int bestD = -1;\n\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n    shuffle(cand, cand + cnt, rng);\n\n    for (int ii = 0; ii < cnt; ++ii) {\n        int d = cand[ii];\n        vector<unsigned char> b1 = board;\n        int e1 = empty;\n        apply_move(b1, e1, d);\n        Eval eFirst = evaluate_board_detail(b1);\n\n        Eval eSecond = eFirst;\n        bool childFirst = true;\n        int cand2[4], cnt2 = 0;\n        for (int d2 = 0; d2 < 4; ++d2) {\n            if (!can_move(e1, d2)) continue;\n            cand2[cnt2++] = d2;\n        }\n        for (int jj = 0; jj < cnt2; ++jj) {\n            int d2 = cand2[jj];\n            vector<unsigned char> b2 = b1;\n            int e2 = e1;\n            apply_move(b2, e2, d2);\n            Eval eChild = evaluate_board_detail(b2);\n            if (childFirst || better_eval(eChild, eSecond)) {\n                childFirst = false;\n                eSecond = eChild;\n            }\n        }\n\n        if (first ||\n            better_eval(eSecond, bestSecond) ||\n            (!better_eval(bestSecond, eSecond) && better_eval(eFirst, bestFirst)) ||\n            (!better_eval(bestSecond, eSecond) && !better_eval(eSecond, bestSecond) &&\n             !better_eval(bestFirst, eFirst) && prevDir != -1 && bestD == opp(prevDir) && d != opp(prevDir))) {\n            first = false;\n            bestFirst = eFirst;\n            bestSecond = eSecond;\n            bestD = d;\n        }\n    }\n    return bestD;\n}\n\nstring mixed_suffix(vector<unsigned char> board, int empty, int len, int prevDir) {\n    string ops;\n    ops.reserve(len);\n    for (int step = 0; step < len; ++step) {\n        int mode = rng() % 100;\n        int d = -1;\n        if (mode < 35) d = greedy_choose_move(board, empty, prevDir);\n        else if (mode < 55) d = greedy_choose_move2(board, empty, prevDir);\n        else {\n            int cand[4], cnt = 0;\n            for (int k = 0; k < 4; ++k) {\n                if (!can_move(empty, k)) continue;\n                if (prevDir != -1 && k == opp(prevDir) && mode < 85) continue;\n                cand[cnt++] = k;\n            }\n            if (cnt == 0) for (int k = 0; k < 4; ++k) if (can_move(empty, k)) cand[cnt++] = k;\n            d = cand[rng() % cnt];\n        }\n        ops.push_back(DC[d]);\n        apply_move(board, empty, d);\n        prevDir = d;\n    }\n    return ops;\n}\n\nCandidate make_random_candidate() {\n    uniform_int_distribution<int> lenDist(0, Tlim);\n    int L = lenDist(rng);\n    string ops = ((rng() % 100) < 50)\n        ? random_legal_suffix(init_empty, L, -1, true)\n        : mixed_suffix(init_board, init_empty, L, -1);\n    return evaluate_sequence(ops);\n}\n\nCandidate make_biased_seed() {\n    int L;\n    int r = rng() % 100;\n    if (r < 45) L = min(Tlim, 4 + (int)(rng() % 20));\n    else if (r < 80) L = min(Tlim, 12 + (int)(rng() % 35));\n    else L = rng() % (Tlim + 1);\n    string ops = mixed_suffix(init_board, init_empty, L, -1);\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_cut_regrow(const Candidate& base) {\n    int L = (int)base.ops.size();\n    int cut = 0;\n    if (L > 0) {\n        int mode = rng() % 6;\n        if (mode == 0) {\n            uniform_int_distribution<int> dist(0, L);\n            cut = dist(rng);\n        } else if (mode == 1) {\n            int lo = max(0, base.bestLen - 10), hi = min(L, base.bestLen + 10);\n            uniform_int_distribution<int> dist(lo, hi);\n            cut = dist(rng);\n        } else if (mode == 2) {\n            cut = base.bestLen;\n        } else if (mode == 3) {\n            uniform_int_distribution<int> dist(max(0, base.bestLen - 30), min(L, base.bestLen + 5));\n            cut = dist(rng);\n        } else {\n            uniform_int_distribution<int> dist(0, min(L, base.bestLen));\n            cut = dist(rng);\n        }\n    }\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, cut, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, cut);\n    int rem = Tlim - cut;\n\n    int add;\n    int lenMode = rng() % 100;\n    if (lenMode < 35) add = min(rem, 5 + (int)(rng() % 20));\n    else if (lenMode < 75) add = rng() % (rem + 1);\n    else add = min(rem, max(0, base.bestLen - cut) + (int)(rng() % 25));\n\n    int genMode = rng() % 100;\n    if (genMode < 50) ops += mixed_suffix(board, empty, add, prevDir);\n    else ops += random_legal_suffix(empty, add, prevDir, true);\n\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_edit(const Candidate& base) {\n    if (base.ops.empty()) return make_random_candidate();\n    int L = (int)base.ops.size();\n    int pos = rng() % L;\n\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, pos, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, pos);\n\n    int cand[4], cnt = 0;\n    for (int d = 0; d < 4; ++d) if (can_move(empty, d)) cand[cnt++] = d;\n    shuffle(cand, cand + cnt, rng);\n\n    int chosen = cand[0];\n    int chooser = rng() % 100;\n    if (chooser < 50) {\n        Eval bestE{-1,-1,-1,(int)1e9};\n        for (int ii = 0; ii < cnt; ++ii) {\n            int d = cand[ii];\n            vector<unsigned char> nb = board;\n            int ne = empty;\n            apply_move(nb, ne, d);\n            Eval e = evaluate_board_detail(nb);\n            if (ii == 0 || better_eval(e, bestE)) {\n                bestE = e;\n                chosen = d;\n            }\n        }\n    } else if (chooser < 80) {\n        chosen = greedy_choose_move2(board, empty, prevDir);\n    }\n\n    ops.push_back(DC[chosen]);\n    apply_move(board, empty, chosen);\n    prevDir = chosen;\n\n    int remCap = Tlim - (int)ops.size();\n    int tail = remCap > 0 ? (rng() % (remCap + 1)) : 0;\n    if ((rng() % 100) < 60) ops += mixed_suffix(board, empty, tail, prevDir);\n    else ops += random_legal_suffix(empty, tail, prevDir, true);\n\n    return evaluate_sequence(ops);\n}\n\nCandidate mutate_insert_delete(const Candidate& base) {\n    vector<unsigned char> board = init_board;\n    int empty = init_empty;\n    int prevDir = -1;\n\n    string ops;\n    ops.reserve(Tlim);\n\n    int i = 0;\n    while (i < (int)base.ops.size() && (int)ops.size() < Tlim) {\n        if ((rng() % 100) < 12 && (int)ops.size() < Tlim) {\n            int chooser = rng() % 100;\n            int d;\n            if (chooser < 45) d = greedy_choose_move(board, empty, prevDir);\n            else if (chooser < 65) d = greedy_choose_move2(board, empty, prevDir);\n            else {\n                int cand[4], cnt = 0;\n                for (int k = 0; k < 4; ++k) if (can_move(empty, k)) cand[cnt++] = k;\n                d = cand[rng() % cnt];\n            }\n            ops.push_back(DC[d]);\n            apply_move(board, empty, d);\n            prevDir = d;\n        }\n\n        if ((rng() % 100) < 16) {\n            ++i;\n            continue;\n        }\n\n        int d = c2d(base.ops[i]);\n        if (!can_move(empty, d)) break;\n        ops.push_back(base.ops[i]);\n        apply_move(board, empty, d);\n        prevDir = d;\n        ++i;\n    }\n\n    int rem = Tlim - (int)ops.size();\n    int add = rem > 0 ? (rng() % (min(rem, 30) + 1)) : 0;\n    if ((rng() % 100) < 60) ops += mixed_suffix(board, empty, add, prevDir);\n    else ops += random_legal_suffix(empty, add, prevDir, true);\n\n    return evaluate_sequence(ops);\n}\n\nCandidate intensify_bestprefix(const Candidate& base) {\n    int cut = base.bestLen;\n    vector<unsigned char> board;\n    int empty, prevDir;\n    replay_prefix(base.ops, cut, board, empty, prevDir);\n\n    string ops = base.ops.substr(0, cut);\n    int rem = Tlim - cut;\n    int add;\n    int mode = rng() % 100;\n    if (mode < 50) add = min(rem, 8 + (int)(rng() % 24));\n    else if (mode < 85) add = min(rem, 20 + (int)(rng() % 40));\n    else add = rng() % (rem + 1);\n\n    ops += mixed_suffix(board, empty, add, prevDir);\n    return evaluate_sequence(ops);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> Tlim;\n    init_board.assign(N * N, 0);\n    for (int i = 0; i < N; ++i) {\n        string s;\n        cin >> s;\n        for (int j = 0; j < N; ++j) {\n            char c = s[j];\n            int v = ('0' <= c && c <= '9') ? c - '0' : 10 + (c - 'a');\n            init_board[i * N + j] = (unsigned char)v;\n            if (v == 0) init_empty = i * N + j;\n        }\n    }\n\n    Timer timer;\n    const double TL = 2.90;\n    const int BEAM = 18;\n\n    vector<Candidate> pool;\n    pool.reserve(BEAM * 3);\n\n    Candidate best;\n    best.ops = \"\";\n    best.bestLen = 0;\n    best.bestEval = evaluate_board_detail(init_board);\n    pool.push_back(best);\n\n    while ((int)pool.size() < BEAM && timer.elapsed() < 0.30) {\n        Candidate c;\n        if ((int)pool.size() < BEAM / 2) c = make_biased_seed();\n        else c = make_random_candidate();\n        if (better_cand(c, best)) best = c;\n        pool.push_back(c);\n    }\n\n    auto shrink_pool = [&]() {\n        sort(pool.begin(), pool.end(), better_cand);\n        vector<Candidate> np;\n        for (auto& c : pool) {\n            bool dup = false;\n            for (auto& x : np) {\n                if (c.bestLen == x.bestLen &&\n                    c.bestEval.largestTree == x.bestEval.largestTree &&\n                    c.bestEval.matchedEdges == x.bestEval.matchedEdges &&\n                    c.ops == x.ops) {\n                    dup = true;\n                    break;\n                }\n            }\n            if (!dup) np.push_back(c);\n            if ((int)np.size() >= BEAM) break;\n        }\n        pool.swap(np);\n        if (!pool.empty() && better_cand(pool[0], best)) best = pool[0];\n    };\n\n    shrink_pool();\n\n    while (timer.elapsed() < TL) {\n        int ps = pool.size();\n        int r = rng() % 100;\n        int idx;\n        if (r < 55) idx = rng() % min(6, ps);\n        else if (r < 85) idx = rng() % min(12, ps);\n        else idx = rng() % ps;\n\n        Candidate cand;\n        int typ = rng() % 100;\n        if (typ < 10) cand = make_random_candidate();\n        else if (typ < 45) cand = mutate_cut_regrow(pool[idx]);\n        else if (typ < 68) cand = mutate_edit(pool[idx]);\n        else if (typ < 86) cand = mutate_insert_delete(pool[idx]);\n        else cand = intensify_bestprefix(pool[idx]);\n\n        pool.push_back(cand);\n        if (better_cand(cand, best)) best = cand;\n\n        if ((int)pool.size() >= BEAM * 2) shrink_pool();\n    }\n\n    cout << best.ops.substr(0, best.bestLen) << '\\n';\n    return 0;\n}","ahc012":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pt {\n    int x, y;\n};\n\nstatic const long long LIM = 1000000000LL;\nstatic const double PI = acos(-1.0);\n\nstatic inline long long clampLL(long long x) {\n    return max(-LIM, min(LIM, x));\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, K;\n    cin >> N >> K;\n    array<int, 11> a{};\n    for (int d = 1; d <= 10; d++) cin >> a[d];\n    vector<Pt> p(N);\n    for (int i = 0; i < N; i++) cin >> p[i].x >> p[i].y;\n\n    // Exact DP for the best partition under the \"all cuts parallel\" model.\n    // dp[s][u] = best matched count using exactly s strawberries in useful pieces\n    // and exactly u useful pieces.\n    //\n    // We build it by sizes 1..10 with bounded multiplicities.\n    vector<vector<int>> dp(N + 1, vector<int>(K + 2, -1e9));\n    struct Prev {\n        short ps, pu, d;\n    };\n    vector<vector<Prev>> prv(N + 1, vector<Prev>(K + 2, {-1, -1, -1}));\n\n    dp[0][0] = 0;\n\n    for (int d = 1; d <= 10; d++) {\n        // Add up to a[d] beneficial pieces of size d.\n        for (int rep = 0; rep < a[d]; rep++) {\n            auto ndp = dp;\n            auto nprv = prv;\n            for (int s = 0; s + d <= N; s++) {\n                for (int u = 0; u + 1 <= K + 1; u++) {\n                    if (dp[s][u] < 0) continue;\n                    if (dp[s][u] + 1 > ndp[s + d][u + 1]) {\n                        ndp[s + d][u + 1] = dp[s][u] + 1;\n                        nprv[s + d][u + 1] = {(short)s, (short)u, (short)d};\n                    }\n                }\n            }\n            dp.swap(ndp);\n            prv.swap(nprv);\n        }\n    }\n\n    // Find best feasible state.\n    // If s == N, total pieces = u.\n    // If s < N, we need one leftover piece, so total pieces = u + 1 <= K+1.\n    int bestScore = -1, bestS = 0, bestU = 0;\n    for (int s = 0; s <= N; s++) {\n        for (int u = 0; u <= K + 1; u++) {\n            if (dp[s][u] < 0) continue;\n            bool ok = false;\n            if (s == N) {\n                ok = (u <= K + 1);\n            } else {\n                ok = (u + 1 <= K + 1);\n            }\n            if (!ok) continue;\n            if (dp[s][u] > bestScore) {\n                bestScore = dp[s][u];\n                bestS = s;\n                bestU = u;\n            }\n        }\n    }\n\n    // Reconstruct useful piece sizes.\n    vector<int> useful;\n    int cs = bestS, cu = bestU;\n    while (cs != 0 || cu != 0) {\n        auto pr = prv[cs][cu];\n        if (pr.d == -1) break;\n        useful.push_back(pr.d);\n        cs = pr.ps;\n        cu = pr.pu;\n    }\n    reverse(useful.begin(), useful.end());\n\n    // Add leftover if any.\n    int used = 0;\n    for (int x : useful) used += x;\n    vector<int> groups = useful;\n    if (used < N) groups.push_back(N - used);\n\n    // To be safe, pieces <= 101\n    while ((int)groups.size() > K + 1) {\n        int x = groups.back(); groups.pop_back();\n        groups.back() += x;\n    }\n\n    // Choose a fixed direction and sort by projection.\n    // Since any direction works for the parallel partition model, this is enough.\n    double theta = 0.3141592653589793; // arbitrary, not axis-aligned\n    double c = cos(theta), s = sin(theta);\n\n    vector<double> proj(N);\n    vector<int> ord(N);\n    iota(ord.begin(), ord.end(), 0);\n    for (int i = 0; i < N; i++) {\n        proj[i] = p[i].x * c + p[i].y * s;\n    }\n    sort(ord.begin(), ord.end(), [&](int i, int j) {\n        if (proj[i] != proj[j]) return proj[i] < proj[j];\n        return i < j;\n    });\n\n    // Place cuts between cumulative group boundaries.\n    vector<double> alphas;\n    int pref = 0;\n    for (int i = 0; i + 1 < (int)groups.size(); i++) {\n        pref += groups[i];\n        if (pref <= 0 || pref >= N) continue;\n        double t1 = proj[ord[pref - 1]];\n        double t2 = proj[ord[pref]];\n        alphas.push_back((t1 + t2) * 0.5);\n    }\n\n    cout << alphas.size() << '\\n';\n\n    const double T = 200000.0;\n    for (double alpha : alphas) {\n        // Line: c*x + s*y = alpha\n        // Point on line: alpha*(c,s)\n        // Direction vector: (-s,c)\n        double x0 = alpha * c;\n        double y0 = alpha * s;\n        double dx = -s, dy = c;\n\n        long long x1 = llround(x0 + T * dx);\n        long long y1 = llround(y0 + T * dy);\n        long long x2 = llround(x0 - T * dx);\n        long long y2 = llround(y0 - T * dy);\n\n        x1 = clampLL(x1);\n        y1 = clampLL(y1);\n        x2 = clampLL(x2);\n        y2 = clampLL(y2);\n\n        if (x1 == x2 && y1 == y2) {\n            if (x2 < LIM) x2++;\n            else x2--;\n        }\n\n        cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\\n';\n    }\n\n    return 0;\n}","ahc014":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Timer {\n    chrono::high_resolution_clock::time_point st;\n    Timer() { st = chrono::high_resolution_clock::now(); }\n    double elapsed() const {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\n    }\n};\n\nstruct Op {\n    int x1, y1, x2, y2, x3, y3, x4, y4;\n};\n\nstruct Candidate {\n    double score;\n    Op op;\n};\n\nstruct Solver {\n    int N, M, c;\n    vector<pair<int,int>> initDots;\n    long long Ssum;\n\n    Solver(int N_, int M_, const vector<pair<int,int>>& pts) : N(N_), M(M_), initDots(pts) {\n        c = (N - 1) / 2;\n        Ssum = 0;\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            long long dx = x - c, dy = y - c;\n            Ssum += dx * dx + dy * dy + 1;\n        }\n    }\n\n    int weight(int x, int y) const {\n        int dx = x - c, dy = y - c;\n        return dx * dx + dy * dy + 1;\n    }\n\n    struct State {\n        int N;\n        vector<vector<char>> dot;\n        vector<vector<char>> usedH, usedV, usedD1, usedD2;\n        vector<pair<int,int>> dots;\n        vector<Op> ops;\n        long long wsum = 0;\n        State(int N_=0): N(N_) {}\n    };\n\n    struct Undo {\n        vector<tuple<int,int,int>> segs; // kind, a, b\n        bool addedDot = false;\n        int x = -1, y = -1;\n        long long addW = 0;\n        bool pushedDot = false;\n        bool pushedOp = false;\n    };\n\n    State initial_state() const {\n        State st(N);\n        st.dot.assign(N, vector<char>(N, 0));\n        st.usedH.assign(max(0, N - 1), vector<char>(N, 0));\n        st.usedV.assign(N, vector<char>(max(0, N - 1), 0));\n        st.usedD1.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        st.usedD2.assign(max(0, N - 1), vector<char>(max(0, N - 1), 0));\n        for (auto [x, y] : initDots) {\n            st.dot[x][y] = 1;\n            st.dots.push_back({x, y});\n            st.wsum += weight(x, y);\n        }\n        return st;\n    }\n\n    bool inside(int x, int y) const {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    }\n\n    bool getSegUsed(const State& st, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            return st.usedV[x1][y1];\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            return st.usedH[x1][y1];\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            return st.usedD1[x1][y1];\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            return st.usedD2[x1][yl];\n        }\n    }\n\n    void setSegUsed(State& st, Undo* ud, int x1, int y1, int x2, int y2) const {\n        if (x1 == x2) {\n            if (y1 > y2) swap(y1, y2);\n            st.usedV[x1][y1] = 1;\n            if (ud) ud->segs.push_back({1, x1, y1});\n        } else if (y1 == y2) {\n            if (x1 > x2) swap(x1, x2);\n            st.usedH[x1][y1] = 1;\n            if (ud) ud->segs.push_back({0, x1, y1});\n        } else if (x2 - x1 == y2 - y1) {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            st.usedD1[x1][y1] = 1;\n            if (ud) ud->segs.push_back({2, x1, y1});\n        } else {\n            if (x1 > x2) {\n                swap(x1, x2);\n                swap(y1, y2);\n            }\n            int yl = min(y1, y2);\n            st.usedD2[x1][yl] = 1;\n            if (ud) ud->segs.push_back({3, x1, yl});\n        }\n    }\n\n    bool edge_clear_and_unused(const State& st, int ax, int ay, int bx, int by) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            if (getSegUsed(st, x, y, nx, ny)) return false;\n            if (t + 1 < len && st.dot[nx][ny]) return false;\n            x = nx; y = ny;\n        }\n        return true;\n    }\n\n    void mark_edge(State& st, int ax, int ay, int bx, int by, Undo* ud=nullptr) const {\n        int dx = (bx > ax) ? 1 : (bx < ax ? -1 : 0);\n        int dy = (by > ay) ? 1 : (by < ay ? -1 : 0);\n        int len = max(abs(bx - ax), abs(by - ay));\n        int x = ax, y = ay;\n        for (int t = 0; t < len; t++) {\n            int nx = x + dx, ny = y + dy;\n            setSegUsed(st, ud, x, y, nx, ny);\n            x = nx; y = ny;\n        }\n    }\n\n    bool legal_rect(const State& st, const Op& op) const {\n        int x1=op.x1,y1=op.y1,x2=op.x2,y2=op.y2,x3=op.x3,y3=op.y3,x4=op.x4,y4=op.y4;\n        if (!inside(x1,y1)||!inside(x2,y2)||!inside(x3,y3)||!inside(x4,y4)) return false;\n        if (st.dot[x1][y1]) return false;\n        if (!st.dot[x2][y2] || !st.dot[x3][y3] || !st.dot[x4][y4]) return false;\n\n        auto ok_edge = [&](int ax, int ay, int bx, int by) {\n            int dx = bx - ax, dy = by - ay;\n            if (dx == 0 && dy != 0) return true;\n            if (dy == 0 && dx != 0) return true;\n            if (abs(dx) == abs(dy) && dx != 0) return true;\n            return false;\n        };\n        if (!ok_edge(x1,y1,x2,y2) || !ok_edge(x2,y2,x3,y3) ||\n            !ok_edge(x3,y3,x4,y4) || !ok_edge(x4,y4,x1,y1)) return false;\n\n        int ax = x2 - x1, ay = y2 - y1;\n        int bx = x4 - x1, by = y4 - y1;\n        if ((ax == 0 && ay == 0) || (bx == 0 && by == 0)) return false;\n        if (ax * bx + ay * by != 0) return false;\n        if (x3 != x2 + bx || y3 != y2 + by) return false;\n        if (x3 != x4 + ax || y3 != y4 + ay) return false;\n\n        if (!edge_clear_and_unused(st, x1,y1,x2,y2)) return false;\n        if (!edge_clear_and_unused(st, x2,y2,x3,y3)) return false;\n        if (!edge_clear_and_unused(st, x3,y3,x4,y4)) return false;\n        if (!edge_clear_and_unused(st, x4,y4,x1,y1)) return false;\n        return true;\n    }\n\n    void apply(State& st, const Op& op) const {\n        st.dot[op.x1][op.y1] = 1;\n        st.dots.push_back({op.x1, op.y1});\n        st.wsum += weight(op.x1, op.y1);\n        mark_edge(st, op.x1, op.y1, op.x2, op.y2);\n        mark_edge(st, op.x2, op.y2, op.x3, op.y3);\n        mark_edge(st, op.x3, op.y3, op.x4, op.y4);\n        mark_edge(st, op.x4, op.y4, op.x1, op.y1);\n        st.ops.push_back(op);\n    }\n\n    void apply_undo(State& st, const Op& op, Undo& ud, bool recordOp=false) const {\n        ud.segs.clear();\n        ud.addedDot = true;\n        ud.x = op.x1;\n        ud.y = op.y1;\n        ud.addW = weight(op.x1, op.y1);\n\n        st.dot[op.x1][op.y1] = 1;\n        st.wsum += ud.addW;\n        st.dots.push_back({op.x1, op.y1});\n        ud.pushedDot = true;\n\n        mark_edge(st, op.x1, op.y1, op.x2, op.y2, &ud);\n        mark_edge(st, op.x2, op.y2, op.x3, op.y3, &ud);\n        mark_edge(st, op.x3, op.y3, op.x4, op.y4, &ud);\n        mark_edge(st, op.x4, op.y4, op.x1, op.y1, &ud);\n\n        if (recordOp) {\n            st.ops.push_back(op);\n            ud.pushedOp = true;\n        } else {\n            ud.pushedOp = false;\n        }\n    }\n\n    void revert(State& st, const Undo& ud) const {\n        for (int i = (int)ud.segs.size() - 1; i >= 0; i--) {\n            auto [kind, a, b] = ud.segs[i];\n            if (kind == 0) st.usedH[a][b] = 0;\n            else if (kind == 1) st.usedV[a][b] = 0;\n            else if (kind == 2) st.usedD1[a][b] = 0;\n            else st.usedD2[a][b] = 0;\n        }\n        if (ud.addedDot) {\n            st.dot[ud.x][ud.y] = 0;\n            st.wsum -= ud.addW;\n        }\n        if (ud.pushedDot) st.dots.pop_back();\n        if (ud.pushedOp) st.ops.pop_back();\n    }\n\n    long long calc_score(const State& st) const {\n        double val = 1e6 * (double)(N * N) / (double)M * (double)st.wsum / (double)Ssum;\n        return llround(val);\n    }\n\n    double eval_small(const Op& op, int mode) const {\n        int w = weight(op.x1, op.y1);\n        int l1 = max(abs(op.x2-op.x1), abs(op.y2-op.y1));\n        int l2 = max(abs(op.x4-op.x1), abs(op.y4-op.y1));\n        int per = l1 + l2;\n        int dist = abs(op.x1 - c) + abs(op.y1 - c);\n        if (mode == 0) return 800.0 * w - 350.0 * per + 15.0 * dist;\n        if (mode == 1) return 700.0 * w - 420.0 * per + 10.0 * dist;\n        if (mode == 2) return 1000.0 * w - 300.0 * per + 20.0 * dist;\n        if (mode == 3) return 880.0 * w - 330.0 * per + 22.0 * dist;\n        return 760.0 * w - 390.0 * per + 30.0 * dist;\n    }\n\n    double eval_large(const Op& op, int mode, int opCount, double noise=0.0) const {\n        int w = weight(op.x1, op.y1);\n        int l1 = max(abs(op.x2-op.x1), abs(op.y2-op.y1));\n        int l2 = max(abs(op.x4-op.x1), abs(op.y4-op.y1));\n        int per = l1 + l2;\n        int dist = abs(op.x1 - c) + abs(op.y1 - c);\n\n        double relax = (opCount >= N / 2 ? 0.85 : 1.0);\n        if (opCount >= N) relax = 0.72;\n\n        if (mode == 0) return 2200.0 * w - (150.0 * relax) * per + 35.0 * dist + noise;\n        if (mode == 1) return 1800.0 * w - (200.0 * relax) * per + 25.0 * dist + noise;\n        if (mode == 2) return 3000.0 * w - (110.0 * relax) * per + 50.0 * dist + noise;\n        if (mode == 3) return 2500.0 * w - (135.0 * relax) * per + 42.0 * dist + noise;\n        return 2050.0 * w - (170.0 * relax) * per + 65.0 * dist + noise;\n    }\n\n    bool closure_small(State& st, int mode, int maxLen, double endTime, const Timer& timer) const {\n        vector<Candidate> top;\n        auto push_top = [&](double sc, const Op& op) {\n            top.push_back({sc, op});\n            sort(top.begin(), top.end(), [](const Candidate& a, const Candidate& b){ return a.score > b.score; });\n            if ((int)top.size() > 8) top.pop_back();\n        };\n\n        for (int x1 = 0; x1 < N; x1++) {\n            if (timer.elapsed() > endTime) break;\n            for (int y1 = 0; y1 < N; y1++) {\n                if (st.dot[x1][y1]) continue;\n\n                for (int dx = 1; dx <= maxLen; dx++) for (int dy = 1; dy <= maxLen; dy++) {\n                    Op cand[4] = {\n                        {x1,y1, x1+dx,y1, x1+dx,y1+dy, x1,y1+dy},\n                        {x1,y1, x1,y1+dy, x1-dx,y1+dy, x1-dx,y1},\n                        {x1,y1, x1-dx,y1, x1-dx,y1-dy, x1,y1-dy},\n                        {x1,y1, x1,y1-dy, x1+dx,y1-dy, x1+dx,y1}\n                    };\n                    for (int k = 0; k < 4; k++) {\n                        if (legal_rect(st, cand[k])) push_top(eval_small(cand[k], mode), cand[k]);\n                    }\n                }\n\n                for (int d1 = 1; d1 <= maxLen; d1++) for (int d2 = 1; d2 <= maxLen; d2++) {\n                    static const int sgn[4][2] = {{1,1},{1,-1},{-1,1},{-1,-1}};\n                    for (int k = 0; k < 4; k++) {\n                        int ax = sgn[k][0] * d1, ay = sgn[k][1] * d1;\n                        int bx1 = -sgn[k][1] * d2, by1 =  sgn[k][0] * d2;\n                        int bx2 =  sgn[k][1] * d2, by2 = -sgn[k][0] * d2;\n                        Op op1{x1,y1, x1+ax,y1+ay, x1+ax+bx1,y1+ay+by1, x1+bx1,y1+by1};\n                        Op op2{x1,y1, x1+ax,y1+ay, x1+ax+bx2,y1+ay+by2, x1+bx2,y1+by2};\n                        if (inside(op1.x2,op1.y2)&&inside(op1.x3,op1.y3)&&inside(op1.x4,op1.y4) && legal_rect(st, op1)) {\n                            push_top(eval_small(op1, mode), op1);\n                        }\n                        if (inside(op2.x2,op2.y2)&&inside(op2.x3,op2.y3)&&inside(op2.x4,op2.y4) && legal_rect(st, op2)) {\n                            push_top(eval_small(op2, mode), op2);\n                        }\n                    }\n                }\n            }\n        }\n\n        if (top.empty()) return false;\n\n        double bestVal = -1e100;\n        int bestIdx = 0;\n        Undo ud1, ud2;\n        for (int i = 0; i < (int)top.size(); i++) {\n            apply_undo(st, top[i].op, ud1, false);\n            double future = 0.0;\n\n            Candidate second{-1e100, {}};\n            for (int x = max(0, top[i].op.x1 - 3); x <= min(N - 1, top[i].op.x1 + 3); x++) {\n                for (int y = max(0, top[i].op.y1 - 3); y <= min(N - 1, top[i].op.y1 + 3); y++) {\n                    if (st.dot[x][y]) continue;\n                    for (int dx = 1; dx <= 2; dx++) for (int dy = 1; dy <= 2; dy++) {\n                        Op cands[4] = {\n                            {x,y, x+dx,y, x+dx,y+dy, x,y+dy},\n                            {x,y, x,y+dy, x-dx,y+dy, x-dx,y},\n                            {x,y, x-dx,y, x-dx,y-dy, x,y-dy},\n                            {x,y, x,y-dy, x+dx,y-dy, x+dx,y}\n                        };\n                        for (int k = 0; k < 4; k++) {\n                            if (legal_rect(st, cands[k])) {\n                                double sc = eval_small(cands[k], mode);\n                                if (sc > second.score) second = {sc, cands[k]};\n                            }\n                        }\n                    }\n                }\n            }\n            if (second.score > -1e50) future = 0.35 * second.score;\n            double total = top[i].score + future;\n            if (total > bestVal) {\n                bestVal = total;\n                bestIdx = i;\n            }\n            revert(st, ud1);\n        }\n\n        apply(st, top[bestIdx].op);\n        return true;\n    }\n\n    vector<Candidate> enumerate_structure_candidates(const State& st, int mode, mt19937& rng, int capDots, int maxD) const {\n        vector<Candidate> cand;\n        vector<pair<int,int>> pts = st.dots;\n\n        if ((int)pts.size() > capDots) {\n            vector<pair<int,int>> heavy = pts;\n            sort(heavy.begin(), heavy.end(), [&](auto& a, auto& b){\n                return weight(a.first, a.second) > weight(b.first, b.second);\n            });\n            vector<pair<int,int>> sel;\n            int keep = capDots * 3 / 4;\n            keep = min(keep, (int)heavy.size());\n            for (int i = 0; i < keep; i++) sel.push_back(heavy[i]);\n\n            shuffle(pts.begin(), pts.end(), rng);\n            for (auto &p : pts) {\n                if ((int)sel.size() >= capDots) break;\n                sel.push_back(p);\n            }\n            pts.swap(sel);\n        }\n\n        unordered_map<int, vector<int>> byX, byY;\n        byX.reserve(2 * pts.size() + 10);\n        byY.reserve(2 * pts.size() + 10);\n        for (auto [x, y] : pts) {\n            byX[x].push_back(y);\n            byY[y].push_back(x);\n        }\n\n        auto add_if = [&](const Op& op) {\n            if (legal_rect(st, op)) {\n                double noise = uniform_real_distribution<double>(0.0, 1e-7)(rng);\n                cand.push_back({eval_large(op, mode, (int)st.ops.size(), noise), op});\n            }\n        };\n\n        for (auto [x2, y2] : pts) {\n            auto itx = byX.find(x2);\n            auto ity = byY.find(y2);\n            if (itx == byX.end() || ity == byY.end()) continue;\n\n            auto ys = itx->second;\n            auto xs = ity->second;\n            if ((int)ys.size() > 18) {\n                shuffle(ys.begin(), ys.end(), rng);\n                ys.resize(18);\n            }\n            if ((int)xs.size() > 18) {\n                shuffle(xs.begin(), xs.end(), rng);\n                xs.resize(18);\n            }\n\n            for (int y4 : ys) {\n                if (y4 == y2) continue;\n                for (int x1 : xs) {\n                    if (x1 == x2) continue;\n                    int y1 = y4;\n                    if (!inside(x1,y1)) continue;\n                    if (!st.dot[x2][y4] || !st.dot[x1][y2]) continue;\n                    Op op{x1,y1, x2,y4, x2,y2, x1,y2};\n                    add_if(op);\n                }\n            }\n        }\n\n        for (auto [x2, y2] : pts) {\n            for (int d = 1; d <= maxD; d++) {\n                static const int sx[4] = {1,1,-1,-1};\n                static const int sy[4] = {1,-1,1,-1};\n                for (int k = 0; k < 4; k++) {\n                    int ax = sx[k] * d, ay = sy[k] * d;\n                    int x1 = x2 - ax, y1 = y2 - ay;\n\n                    int bx = -ay, by = ax;\n                    Op op1{x1,y1, x2,y2, x2+bx,y2+by, x1+bx,y1+by};\n                    if (inside(op1.x1,op1.y1)&&inside(op1.x3,op1.y3)&&inside(op1.x4,op1.y4)) add_if(op1);\n\n                    bx = ay; by = -ax;\n                    Op op2{x1,y1, x2,y2, x2+bx,y2+by, x1+bx,y1+by};\n                    if (inside(op2.x1,op2.y1)&&inside(op2.x3,op2.y3)&&inside(op2.x4,op2.y4)) add_if(op2);\n                }\n            }\n        }\n\n        sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b){\n            if (a.op.x1 != b.op.x1) return a.op.x1 < b.op.x1;\n            if (a.op.y1 != b.op.y1) return a.op.y1 < b.op.y1;\n            if (a.op.x2 != b.op.x2) return a.op.x2 < b.op.x2;\n            if (a.op.y2 != b.op.y2) return a.op.y2 < b.op.y2;\n            if (a.op.x3 != b.op.x3) return a.op.x3 < b.op.x3;\n            if (a.op.y3 != b.op.y3) return a.op.y3 < b.op.y3;\n            if (a.op.x4 != b.op.x4) return a.op.x4 < b.op.x4;\n            if (a.op.y4 != b.op.y4) return a.op.y4 < b.op.y4;\n            return a.score > b.score;\n        });\n\n        vector<Candidate> uniq;\n        uniq.reserve(cand.size());\n        for (int i = 0; i < (int)cand.size(); i++) {\n            if (i == 0 || memcmp(&cand[i].op, &cand[i-1].op, sizeof(Op)) != 0) uniq.push_back(cand[i]);\n        }\n\n        sort(uniq.begin(), uniq.end(), [](const Candidate& a, const Candidate& b){\n            return a.score > b.score;\n        });\n        if ((int)uniq.size() > 280) uniq.resize(280);\n        return uniq;\n    }\n\n    double best_followup_value(State& st, int mode, mt19937& rng, int topSecond, int maxD) const {\n        auto cand2 = enumerate_structure_candidates(st, mode, rng, 180, maxD);\n        double best = 0.0;\n        int lim = min<int>(topSecond, cand2.size());\n        for (int i = 0; i < lim; i++) {\n            if (legal_rect(st, cand2[i].op)) best = max(best, cand2[i].score);\n        }\n        return best;\n    }\n\n    bool broad_step_with_lookahead(State& st, int mode, mt19937& rng, double timeBudgetFactor, int maxD) const {\n        auto cand = enumerate_structure_candidates(st, mode, rng, 230, maxD);\n        if (cand.empty()) return false;\n\n        bool useLookahead = timeBudgetFactor > 0.18;\n        if (!useLookahead) {\n            for (int i = 0; i < min<int>(18, cand.size()); i++) {\n                if (legal_rect(st, cand[i].op)) {\n                    apply(st, cand[i].op);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        int firstLim = min<int>((timeBudgetFactor > 0.55 ? 8 : 5), cand.size());\n        int secondLim = (timeBudgetFactor > 0.55 ? 10 : 6);\n\n        double bestVal = -1e100;\n        int bestIdx = -1;\n        Undo ud;\n\n        for (int i = 0; i < firstLim; i++) {\n            if (!legal_rect(st, cand[i].op)) continue;\n            apply_undo(st, cand[i].op, ud, false);\n            double future = best_followup_value(st, mode, rng, secondLim, max(4, maxD - 2));\n            double total = cand[i].score + 0.45 * future;\n            if (total > bestVal) {\n                bestVal = total;\n                bestIdx = i;\n            }\n            revert(st, ud);\n        }\n\n        if (bestIdx == -1) {\n            for (int i = 0; i < min<int>(20, cand.size()); i++) {\n                if (legal_rect(st, cand[i].op)) {\n                    apply(st, cand[i].op);\n                    return true;\n                }\n            }\n            return false;\n        }\n\n        apply(st, cand[bestIdx].op);\n        return true;\n    }\n\n    State run_one(int mode, uint64_t seed, double endTime, const Timer& timer) const {\n        mt19937 rng((uint32_t)seed);\n        State st = initial_state();\n\n        int smallLen = (mode == 1 ? 4 : (mode == 4 ? 2 : 3));\n        int closureLimit = (mode == 4 ? 700 : 1000);\n\n        while (closureLimit-- > 0 && timer.elapsed() < endTime * 0.42) {\n            if (!closure_small(st, mode, smallLen, endTime * 0.42, timer)) break;\n        }\n\n        int stagnation = 0;\n        int maxD = (mode == 1 ? 8 : mode == 2 ? 12 : mode == 4 ? 7 : 10);\n\n        while (timer.elapsed() < endTime) {\n            double progress = timer.elapsed() / endTime;\n            bool moved = broad_step_with_lookahead(st, mode, rng, 1.0 - progress, maxD);\n\n            if (!moved) {\n                stagnation++;\n                if (stagnation >= 3) break;\n                if (!closure_small(st, mode, 2, endTime, timer)) {\n                    if (stagnation >= 2) break;\n                } else {\n                    stagnation = 0;\n                }\n            } else {\n                stagnation = 0;\n            }\n        }\n\n        return st;\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    vector<pair<int,int>> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].first >> pts[i].second;\n\n    Timer timer;\n    Solver solver(N, M, pts);\n\n    auto best = solver.initial_state();\n    long long bestScore = solver.calc_score(best);\n\n    int iter = 0;\n    const int MODE_CNT = 5;\n\n    while (timer.elapsed() < 4.82) {\n        double remain = 4.90 - timer.elapsed();\n        if (remain < 0.08) break;\n\n        int mode = iter % MODE_CNT;\n        double slice;\n        if (iter < MODE_CNT) slice = min(remain, 0.72);\n        else if (iter < 3 * MODE_CNT) slice = min(remain, 0.38);\n        else slice = min(remain, 0.22);\n\n        uint64_t seed = 1234567ULL + 100003ULL * iter + 10000019ULL * mode + 911382323ULL;\n\n        auto st = solver.run_one(mode, seed, timer.elapsed() + slice, timer);\n        long long sc = solver.calc_score(st);\n        if (sc > bestScore) {\n            bestScore = sc;\n            best = move(st);\n        }\n        iter++;\n    }\n\n    cout << best.ops.size() << '\\n';\n    for (auto &op : best.ops) {\n        cout << op.x1 << ' ' << op.y1 << ' '\n             << op.x2 << ' ' << op.y2 << ' '\n             << op.x3 << ' ' << op.y3 << ' '\n             << op.x4 << ' ' << op.y4 << '\\n';\n    }\n    return 0;\n}","ahc015":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 10;\n\nstruct Pos {\n    int r, c;\n};\n\nstruct Board {\n    uint8_t a[N][N];\n    Board() { memset(a, 0, sizeof(a)); }\n\n    inline void place_by_index(int p, int flavor) {\n        int cnt = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) {\n                ++cnt;\n                if (cnt == p) {\n                    a[i][j] = (uint8_t)flavor;\n                    return;\n                }\n            }\n        }\n        assert(false);\n    }\n\n    inline vector<Pos> empty_cells_ordered() const {\n        vector<Pos> e;\n        e.reserve(100);\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (a[i][j] == 0) e.push_back({i, j});\n        }\n        return e;\n    }\n\n    inline Board tilted(char dir) const {\n        Board b;\n        if (dir == 'L') {\n            for (int i = 0; i < N; i++) {\n                int t = 0;\n                for (int j = 0; j < N; j++) if (a[i][j]) b.a[i][t++] = a[i][j];\n            }\n        } else if (dir == 'R') {\n            for (int i = 0; i < N; i++) {\n                int t = N - 1;\n                for (int j = N - 1; j >= 0; j--) if (a[i][j]) b.a[i][t--] = a[i][j];\n            }\n        } else if (dir == 'F') {\n            for (int j = 0; j < N; j++) {\n                int t = 0;\n                for (int i = 0; i < N; i++) if (a[i][j]) b.a[t++][j] = a[i][j];\n            }\n        } else if (dir == 'B') {\n            for (int j = 0; j < N; j++) {\n                int t = N - 1;\n                for (int i = N - 1; i >= 0; i--) if (a[i][j]) b.a[t--][j] = a[i][j];\n            }\n        } else {\n            assert(false);\n        }\n        return b;\n    }\n};\n\nstruct EvalInfo {\n    long long compSq = 0;\n    int sameAdj = 0;\n    int diffAdj = 0;\n    int compCnt[4] = {};\n    int cnt[4] = {};\n    int minr[4], maxr[4], minc[4], maxc[4];\n    int rowCnt[4][N]{};\n    int colCnt[4][N]{};\n\n    EvalInfo() {\n        for (int i = 0; i < 4; i++) {\n            minr[i] = minc[i] = N;\n            maxr[i] = maxc[i] = -1;\n        }\n    }\n};\n\nstruct Policy {\n    int type; // 0 corner, 1 hband, 2 vband\n    Pos anchor[4];\n    int bandRow[4];\n    int bandCol[4];\n};\n\nstruct Solver {\n    vector<int> f;\n    int totalCnt[4]{};\n    vector<Policy> policies;\n    mutable uint64_t seed = 88172645463393265ull;\n    mutable unordered_map<uint64_t, double> evalCachePol;\n\n    Solver(const vector<int>& flavors) : f(flavors) {\n        for (int x : f) totalCnt[x]++;\n        build_policies();\n    }\n\n    inline uint64_t next_rand() const {\n        uint64_t x = seed;\n        x ^= x << 7;\n        x ^= x >> 9;\n        seed = x;\n        return x;\n    }\n\n    inline uint64_t hash_board(const Board& b, int turn, int extra = 0) const {\n        uint64_t h = 1469598103934665603ull ^ (uint64_t)(turn * 131 + extra * 10007);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                h ^= (uint64_t)(b.a[i][j] + 1 + 7 * (i * 10 + j));\n                h *= 1099511628211ull;\n            }\n        }\n        return h;\n    }\n\n    void build_policies() {\n        vector<int> ord = {1,2,3};\n        sort(ord.begin(), ord.end(), [&](int x, int y){ return totalCnt[x] > totalCnt[y]; });\n\n        {\n            Policy p;\n            p.type = 0;\n            p.anchor[ord[0]] = {0,0};\n            p.anchor[ord[1]] = {9,9};\n            p.anchor[ord[2]] = {0,9};\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 0;\n            p.anchor[ord[0]] = {0,0};\n            p.anchor[ord[1]] = {9,9};\n            p.anchor[ord[2]] = {9,0};\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 0;\n            p.anchor[ord[0]] = {0,9};\n            p.anchor[ord[1]] = {9,0};\n            p.anchor[ord[2]] = {0,0};\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 1;\n            p.bandRow[ord[0]] = 1;\n            p.bandRow[ord[1]] = 4;\n            p.bandRow[ord[2]] = 8;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 1;\n            p.bandRow[ord[0]] = 1;\n            p.bandRow[ord[1]] = 8;\n            p.bandRow[ord[2]] = 4;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 1;\n            p.bandRow[ord[0]] = 2;\n            p.bandRow[ord[1]] = 5;\n            p.bandRow[ord[2]] = 7;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 2;\n            p.bandCol[ord[0]] = 1;\n            p.bandCol[ord[1]] = 4;\n            p.bandCol[ord[2]] = 8;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 2;\n            p.bandCol[ord[0]] = 1;\n            p.bandCol[ord[1]] = 8;\n            p.bandCol[ord[2]] = 4;\n            policies.push_back(p);\n        }\n        {\n            Policy p;\n            p.type = 2;\n            p.bandCol[ord[0]] = 2;\n            p.bandCol[ord[1]] = 5;\n            p.bandCol[ord[2]] = 7;\n            policies.push_back(p);\n        }\n    }\n\n    EvalInfo analyze(const Board& b) const {\n        EvalInfo er;\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int x = b.a[i][j];\n            if (!x) continue;\n            er.cnt[x]++;\n            er.minr[x] = min(er.minr[x], i);\n            er.maxr[x] = max(er.maxr[x], i);\n            er.minc[x] = min(er.minc[x], j);\n            er.maxc[x] = max(er.maxc[x], j);\n            er.rowCnt[x][i]++;\n            er.colCnt[x][j]++;\n\n            if (i + 1 < N && b.a[i+1][j]) {\n                if (b.a[i+1][j] == x) er.sameAdj++;\n                else er.diffAdj++;\n            }\n            if (j + 1 < N && b.a[i][j+1]) {\n                if (b.a[i][j+1] == x) er.sameAdj++;\n                else er.diffAdj++;\n            }\n        }\n\n        bool vis[N][N];\n        memset(vis, 0, sizeof(vis));\n        static const int dr[4] = {-1, 1, 0, 0};\n        static const int dc[4] = {0, 0, -1, 1};\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            int col = b.a[i][j];\n            if (!col || vis[i][j]) continue;\n            er.compCnt[col]++;\n            int sz = 0;\n            queue<pair<int,int>> q;\n            q.push({i,j});\n            vis[i][j] = true;\n            while (!q.empty()) {\n                auto [r,c] = q.front(); q.pop();\n                ++sz;\n                for (int k = 0; k < 4; k++) {\n                    int nr = r + dr[k], nc = c + dc[k];\n                    if (nr < 0 || nr >= N || nc < 0 || nc >= N) continue;\n                    if (!vis[nr][nc] && b.a[nr][nc] == col) {\n                        vis[nr][nc] = true;\n                        q.push({nr,nc});\n                    }\n                }\n            }\n            er.compSq += 1LL * sz * sz;\n        }\n\n        return er;\n    }\n\n    double score_with_policy(const Board& b, const EvalInfo& er, int turn, int pid) const {\n        const Policy& p = policies[pid];\n        double score = 0.0;\n\n        double wComp = (turn <= 80 ? 3450.0 : turn <= 93 ? 3900.0 : 4300.0);\n        double wCompCnt = (turn <= 80 ? 175.0 : turn <= 93 ? 240.0 : 280.0);\n        score += wComp * er.compSq;\n        score += 245.0 * er.sameAdj;\n        score -= 155.0 * er.diffAdj;\n        score -= wCompCnt * (er.compCnt[1] + er.compCnt[2] + er.compCnt[3]);\n\n        for (int c = 1; c <= 3; c++) {\n            if (er.cnt[c] == 0) continue;\n            int area = (er.maxr[c] - er.minr[c] + 1) * (er.maxc[c] - er.minc[c] + 1);\n            score -= 18.0 * area;\n            score += 14.0 * er.cnt[c] * er.cnt[c] / max(1, area);\n        }\n\n        if (p.type == 0) {\n            double w = (turn <= 25 ? 14.0 : turn <= 70 ? 7.0 : turn <= 85 ? 2.5 : turn <= 93 ? 1.0 : 0.4);\n            for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (b.a[i][j]) {\n                int c = b.a[i][j];\n                score -= w * (abs(i - p.anchor[c].r) + abs(j - p.anchor[c].c));\n            }\n        } else if (p.type == 1) {\n            double wr = (turn <= 25 ? 18.0 : turn <= 70 ? 10.0 : turn <= 85 ? 4.0 : turn <= 93 ? 1.5 : 0.6);\n            for (int c = 1; c <= 3; c++) {\n                for (int i = 0; i < N; i++) {\n                    score -= wr * er.rowCnt[c][i] * abs(i - p.bandRow[c]);\n                    score += 2.0 * er.rowCnt[c][i] * er.rowCnt[c][i];\n                }\n            }\n        } else {\n            double wc = (turn <= 25 ? 18.0 : turn <= 70 ? 10.0 : turn <= 85 ? 4.0 : turn <= 93 ? 1.5 : 0.6);\n            for (int c = 1; c <= 3; c++) {\n                for (int j = 0; j < N; j++) {\n                    score -= wc * er.colCnt[c][j] * abs(j - p.bandCol[c]);\n                    score += 2.0 * er.colCnt[c][j] * er.colCnt[c][j];\n                }\n            }\n        }\n\n        return score;\n    }\n\n    double eval_policy(const Board& b, int turn, int pid) const {\n        uint64_t h = hash_board(b, turn, pid + 1);\n        auto it = evalCachePol.find(h);\n        if (it != evalCachePol.end()) return it->second;\n        EvalInfo er = analyze(b);\n        double v = score_with_policy(b, er, turn, pid);\n        evalCachePol.emplace(h, v);\n        return v;\n    }\n\n    vector<pair<double,int>> eval_all_policies(const Board& b, int turn) const {\n        vector<pair<double,int>> vals;\n        vals.reserve(policies.size());\n        for (int pid = 0; pid < (int)policies.size(); pid++) {\n            vals.push_back({eval_policy(b, turn, pid), pid});\n        }\n        sort(vals.begin(), vals.end(), greater<pair<double,int>>());\n        return vals;\n    }\n\n    int sampled_empty_index(int m, int mode) const {\n        if (m <= 1) return 0;\n        switch (mode % 9) {\n            case 0: return 0;\n            case 1: return m - 1;\n            case 2: return m / 2;\n            case 3: return m / 3;\n            case 4: return (2 * m) / 3;\n            case 5: return (m > 2 ? 1 : 0);\n            case 6: return (m > 3 ? m - 2 : m - 1);\n            case 7: return (m > 4 ? m / 4 : m / 2);\n            default: return (int)(next_rand() % m);\n        }\n    }\n\n    char greedy_move_fixed_policy(const Board& b, int turn, int pid) const {\n        static const char dirs[4] = {'F','B','L','R'};\n        char bestDir = 'F';\n        double bestScore = -1e100;\n        for (char d : dirs) {\n            Board nb = b.tilted(d);\n            double sc = eval_policy(nb, turn, pid);\n            if (d == 'F') sc += 0.003;\n            else if (d == 'L') sc += 0.002;\n            else if (d == 'R') sc += 0.001;\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = d;\n            }\n        }\n        return bestDir;\n    }\n\n    double late_exact2(Board b, int turn, int sampleMode, int pid) const {\n        // For very late turns: after insertion, branch over next move, then one more move.\n        int rem = 100 - turn;\n        if (rem <= 0) return eval_policy(b, turn, pid);\n\n        int t1 = turn + 1;\n        int fl1 = f[t1 - 1];\n        auto e1 = b.empty_cells_ordered();\n        if (e1.empty()) return eval_policy(b, turn, pid);\n        int idx1 = sampled_empty_index((int)e1.size(), sampleMode);\n        b.a[e1[idx1].r][e1[idx1].c] = (uint8_t)fl1;\n\n        static const char dirs[4] = {'F','B','L','R'};\n        double best = -1e100;\n\n        for (char d1 : dirs) {\n            Board b1 = b.tilted(d1);\n            if (t1 == 100) {\n                best = max(best, eval_policy(b1, t1, pid));\n                continue;\n            }\n\n            int t2 = turn + 2;\n            int fl2 = f[t2 - 1];\n            auto e2 = b1.empty_cells_ordered();\n            if (e2.empty()) {\n                best = max(best, eval_policy(b1, t1, pid));\n                continue;\n            }\n            int idx2 = sampled_empty_index((int)e2.size(), sampleMode + 1);\n            Board b2 = b1;\n            b2.a[e2[idx2].r][e2[idx2].c] = (uint8_t)fl2;\n\n            double best2 = -1e100;\n            for (char d2 : dirs) {\n                Board b3 = b2.tilted(d2);\n                best2 = max(best2, eval_policy(b3, t2, pid));\n            }\n            best = max(best, best2);\n        }\n        return best;\n    }\n\n    double rollout(Board b, int turn, int sampleMode, int pid) const {\n        if (turn >= 94) {\n            return late_exact2(b, turn, sampleMode, pid);\n        }\n\n        int depth;\n        if (turn <= 20) depth = 2;\n        else if (turn <= 70) depth = 3;\n        else if (turn <= 85) depth = 4;\n        else depth = 5;\n        depth = min(depth, 100 - turn);\n\n        if (turn >= 85 && depth >= 1) {\n            int t = turn + 1;\n            int flavor = f[t - 1];\n            auto empties = b.empty_cells_ordered();\n            int m = (int)empties.size();\n            if (m == 0) return eval_policy(b, turn, pid);\n\n            double bestBranch = -1e100;\n            for (int branch = 0; branch < 2; branch++) {\n                int idx = sampled_empty_index(m, sampleMode + branch);\n                Board bb = b;\n                bb.a[empties[idx].r][empties[idx].c] = (uint8_t)flavor;\n                char mv = greedy_move_fixed_policy(bb, t, pid);\n                bb = bb.tilted(mv);\n\n                for (int step = 1; step < depth; step++) {\n                    int tt = turn + step + 1;\n                    int ff = f[tt - 1];\n                    auto e2 = bb.empty_cells_ordered();\n                    int mm = (int)e2.size();\n                    if (mm == 0) break;\n                    int idx2 = sampled_empty_index(mm, sampleMode + 2 * step + branch);\n                    bb.a[e2[idx2].r][e2[idx2].c] = (uint8_t)ff;\n                    char mv2 = greedy_move_fixed_policy(bb, tt, pid);\n                    bb = bb.tilted(mv2);\n                }\n                bestBranch = max(bestBranch, eval_policy(bb, turn + depth, pid));\n            }\n            return bestBranch;\n        }\n\n        for (int step = 0; step < depth; step++) {\n            int t = turn + step + 1;\n            int flavor = f[t - 1];\n            auto empties = b.empty_cells_ordered();\n            int m = (int)empties.size();\n            if (m == 0) break;\n            int idx = sampled_empty_index(m, sampleMode + 2 * step);\n            b.a[empties[idx].r][empties[idx].c] = (uint8_t)flavor;\n            char mv = greedy_move_fixed_policy(b, t, pid);\n            b = b.tilted(mv);\n        }\n        return eval_policy(b, turn + depth, pid);\n    }\n\n    vector<int> select_hedge_policies(const vector<pair<double,int>>& vals) const {\n        vector<int> res;\n        res.push_back(vals[0].second);\n\n        double bestScore = vals[0].first;\n        int bestType = policies[vals[0].second].type;\n\n        int diversePid = -1;\n        double diverseScore = -1e100;\n        for (int i = 1; i < (int)vals.size() && i < 5; i++) {\n            int pid = vals[i].second;\n            if (policies[pid].type != bestType) {\n                if (vals[i].first > diverseScore) {\n                    diverseScore = vals[i].first;\n                    diversePid = pid;\n                }\n            }\n        }\n\n        if (diversePid != -1 && bestScore - diverseScore < 1400.0) {\n            res.push_back(diversePid);\n            return res;\n        }\n\n        if ((int)vals.size() >= 2 && bestScore - vals[1].first < 1200.0) {\n            res.push_back(vals[1].second);\n        }\n        return res;\n    }\n\n    char decide(const Board& board, int turn) const {\n        evalCachePol.clear();\n        evalCachePol.reserve(4096);\n\n        static const char dirs[4] = {'F','B','L','R'};\n        char bestDir = 'F';\n        double bestScore = -1e100;\n\n        int samples;\n        if (turn <= 20) samples = 2;\n        else if (turn <= 75) samples = 3;\n        else if (turn <= 90) samples = 4;\n        else samples = 5;\n\n        for (char d : dirs) {\n            Board tb = board.tilted(d);\n            auto vals = eval_all_policies(tb, turn);\n            double immediate = vals[0].first;\n\n            vector<int> usedPolicies = select_hedge_policies(vals);\n\n            double sum = 0.0, mn = 1e100, mx = -1e100;\n            int cnt = 0;\n            for (int pid : usedPolicies) {\n                for (int s = 0; s < samples; s++) {\n                    double v = rollout(tb, turn, s + pid * 3, pid);\n                    sum += v;\n                    mn = min(mn, v);\n                    mx = max(mx, v);\n                    cnt++;\n                }\n            }\n            double avg = sum / cnt;\n\n            double sc;\n            if (turn <= 25) {\n                sc = 0.55 * immediate + 0.40 * avg + 0.05 * mx;\n            } else if (turn <= 70) {\n                sc = 0.35 * immediate + 0.50 * avg + 0.15 * mn;\n            } else if (turn <= 85) {\n                sc = 0.25 * immediate + 0.55 * avg + 0.20 * mn;\n            } else {\n                sc = 0.18 * immediate + 0.60 * avg + 0.22 * mn;\n            }\n\n            if (d == 'F') sc += 0.003;\n            else if (d == 'L') sc += 0.002;\n            else if (d == 'R') sc += 0.001;\n\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestDir = d;\n            }\n        }\n\n        return bestDir;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<int> f(100);\n    for (int i = 0; i < 100; i++) {\n        if (!(cin >> f[i])) return 0;\n    }\n\n    Solver solver(f);\n    Board board;\n\n    for (int t = 1; t <= 100; t++) {\n        int p;\n        cin >> p;\n        board.place_by_index(p, f[t - 1]);\n\n        char ans = solver.decide(board, t);\n        board = board.tilted(ans);\n\n        cout << ans << '\\n';\n        cout.flush();\n    }\n    return 0;\n}","ahc016":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ull;\n    uint64_t next_u64() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    double next_double() {\n        return (next_u64() >> 11) * (1.0 / (1ull << 53));\n    }\n    uint32_t next_u32() { return (uint32_t)next_u64(); }\n    int randint(int l, int r) {\n        return l + (int)(next_u32() % (uint32_t)(r - l + 1));\n    }\n};\n\nstatic int edge_index(int N, int i, int j) {\n    return i * (2 * N - i - 1) / 2 + (j - i - 1);\n}\n\nstatic string make_threshold_graph(int N, int x) {\n    string s(N * (N - 1) / 2, '0');\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (i < x || j < x) s[edge_index(N, i, j)] = '1';\n        }\n    }\n    return s;\n}\n\nstatic vector<int> get_sorted_degrees(int N, const string& g, int& edge_cnt) {\n    vector<int> deg(N, 0);\n    edge_cnt = 0;\n    int p = 0;\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            if (g[p++] == '1') {\n                deg[i]++;\n                deg[j]++;\n                edge_cnt++;\n            }\n        }\n    }\n    sort(deg.begin(), deg.end());\n    return deg;\n}\n\nenum PlacementType {\n    LINEAR = 0,\n    QUAD_LOW = 1,\n    QUAD_HIGH = 2,\n    CENTER = 3\n};\n\nstruct Params {\n    double w_edge;\n    double w_split;\n};\n\nstruct Model {\n    int N, M;\n    PlacementType pt;\n    Params prm;\n    vector<int> xs;\n    vector<string> graphs;\n    vector<double> exp_edges;\n    vector<double> mu_low, mu_high;\n    vector<double> exp_pref, exp_suff;\n};\n\nstatic vector<int> build_xs(int M, int N, PlacementType pt) {\n    vector<int> xs(M, 0);\n    if (M == 1) {\n        xs[0] = 0;\n        return xs;\n    }\n\n    for (int k = 0; k < M; k++) {\n        double t = (double)k / (M - 1);\n        double y;\n        if (pt == LINEAR) y = t;\n        else if (pt == QUAD_LOW) y = t * t;\n        else if (pt == QUAD_HIGH) y = 1.0 - (1.0 - t) * (1.0 - t);\n        else y = 0.5 - 0.5 * cos(M_PI * t); // CENTER\n        xs[k] = (int)llround(y * (N - 1));\n    }\n\n    for (int k = 1; k < M; k++) xs[k] = max(xs[k], xs[k - 1] + 1);\n    for (int k = M - 1; k >= 0; k--) xs[k] = min(xs[k], N);\n    for (int k = M - 2; k >= 0; k--) xs[k] = min(xs[k], xs[k + 1] - 1);\n    for (int k = 0; k < M; k++) xs[k] = max(0, min(N, xs[k]));\n    for (int k = 1; k < M; k++) {\n        if (xs[k] <= xs[k - 1]) xs[k] = min(N, xs[k - 1] + 1);\n    }\n    return xs;\n}\n\nstatic Model build_model(int M, double eps, int N, PlacementType pt, Params prm) {\n    Model md;\n    md.N = N;\n    md.M = M;\n    md.pt = pt;\n    md.prm = prm;\n    md.xs = build_xs(M, N, pt);\n    md.graphs.resize(M);\n    md.exp_edges.resize(M);\n    md.mu_low.resize(M);\n    md.mu_high.resize(M);\n    md.exp_pref.resize(M);\n    md.exp_suff.resize(M);\n\n    for (int k = 0; k < M; k++) {\n        int x = md.xs[k];\n        md.graphs[k] = make_threshold_graph(N, x);\n\n        double muL = x * (1.0 - eps) + (N - 1 - x) * eps;\n        double muH = (N - 1) * (1.0 - eps);\n\n        md.mu_low[k] = muL;\n        md.mu_high[k] = muH;\n\n        int cut = N - x;\n        md.exp_pref[k] = cut * muL;\n        md.exp_suff[k] = x * muH;\n\n        double m0 = 1.0 * x * (2 * N - x - 1) / 2.0;\n        double total = 1.0 * N * (N - 1) / 2.0;\n        md.exp_edges[k] = m0 * (1.0 - eps) + (total - m0) * eps;\n    }\n\n    return md;\n}\n\nstatic int decode_model(const Model& md, const vector<int>& deg, int edges) {\n    int N = md.N;\n    vector<double> ps(N + 1, 0.0), ps2(N + 1, 0.0);\n    for (int i = 0; i < N; i++) {\n        ps[i + 1] = ps[i] + deg[i];\n        ps2[i + 1] = ps2[i] + 1.0 * deg[i] * deg[i];\n    }\n\n    int best = 0;\n    double bestScore = 1e100;\n\n    for (int k = 0; k < md.M; k++) {\n        int x = md.xs[k];\n        int cut = N - x;\n\n        double muL = md.mu_low[k];\n        double muH = md.mu_high[k];\n\n        double sseL = 0.0, sseH = 0.0;\n        double pref = 0.0, suff = 0.0;\n\n        if (cut > 0) {\n            double sum = ps[cut];\n            double sum2 = ps2[cut];\n            pref = sum;\n            sseL = sum2 - 2.0 * muL * sum + cut * muL * muL;\n        }\n        if (cut < N) {\n            double sum = ps[N] - ps[cut];\n            double sum2 = ps2[N] - ps2[cut];\n            suff = sum;\n            int cnt = N - cut;\n            sseH = sum2 - 2.0 * muH * sum + cnt * muH * muH;\n        }\n\n        double ed = edges - md.exp_edges[k];\n        double dp = pref - md.exp_pref[k];\n        double ds = suff - md.exp_suff[k];\n\n        double score = sseL + sseH\n                     + md.prm.w_edge * ed * ed\n                     + md.prm.w_split * (dp * dp + ds * ds) / max(1, N);\n\n        if (score < bestScore) {\n            bestScore = score;\n            best = k;\n        }\n    }\n    return best;\n}\n\nstatic int simulate_one(XorShift& rng, const Model& md, double eps, int s) {\n    int N = md.N;\n    int x = md.xs[s];\n\n    vector<int> deg(N, 0);\n    int edges = 0;\n\n    for (int i = 0; i < N; i++) {\n        for (int j = i + 1; j < N; j++) {\n            bool e = (i < x || j < x);\n            if (rng.next_double() < eps) e = !e;\n            if (e) {\n                deg[i]++;\n                deg[j]++;\n                edges++;\n            }\n        }\n    }\n\n    sort(deg.begin(), deg.end());\n    return decode_model(md, deg, edges);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int M;\n    double eps;\n    cin >> M >> eps;\n\n    int base_gap;\n    if (eps <= 0.02) base_gap = 1;\n    else if (eps <= 0.05) base_gap = 2;\n    else if (eps <= 0.10) base_gap = 3;\n    else if (eps <= 0.15) base_gap = 4;\n    else if (eps <= 0.20) base_gap = 5;\n    else if (eps <= 0.25) base_gap = 6;\n    else if (eps <= 0.30) base_gap = 7;\n    else if (eps <= 0.35) base_gap = 8;\n    else base_gap = 9;\n\n    vector<int> candN;\n    for (int dg = -3; dg <= 5; dg++) {\n        int gap = max(1, base_gap + dg);\n        int N = (M - 1) * gap + 1;\n        N = max(4, min(100, N));\n        if (N >= M - 1) candN.push_back(N);\n    }\n    for (int extra : {M - 1, M + 4, M + 9, M + 14, M + 19, M + 24, 100}) {\n        int N = max(4, min(100, extra));\n        if (N >= M - 1) candN.push_back(N);\n    }\n    sort(candN.begin(), candN.end());\n    candN.erase(unique(candN.begin(), candN.end()), candN.end());\n\n    vector<PlacementType> placements = {LINEAR, QUAD_LOW, QUAD_HIGH, CENTER};\n    vector<Params> param_list = {\n        {0.20, 0.00},\n        {0.35, 0.00},\n        {0.50, 0.00},\n        {0.35, 0.05},\n        {0.35, 0.10},\n        {0.50, 0.05}\n    };\n\n    vector<Model> models;\n    for (int N : candN) {\n        for (auto pt : placements) {\n            for (auto prm : param_list) {\n                models.push_back(build_model(M, eps, N, pt, prm));\n            }\n        }\n    }\n\n    XorShift rng;\n    vector<pair<double,int>> first_pass;\n    first_pass.reserve(models.size());\n\n    // pass 1: all models, light MC\n    for (int i = 0; i < (int)models.size(); i++) {\n        const Model& md = models[i];\n        int trials = 60;\n        int err = 0;\n        for (int t = 0; t < trials; t++) {\n            int s = rng.randint(0, M - 1);\n            int pred = simulate_one(rng, md, eps, s);\n            if (pred != s) err++;\n        }\n        double val = pow(0.9, err) / md.N;\n        first_pass.push_back({-val, i});\n    }\n\n    sort(first_pass.begin(), first_pass.end());\n\n    int topk = min<int>(12, first_pass.size());\n    Model best_model;\n    double best_value = -1.0;\n\n    // pass 2: top models, stronger MC\n    for (int z = 0; z < topk; z++) {\n        const Model& md = models[first_pass[z].second];\n        int trials = 220;\n        int err = 0;\n        for (int t = 0; t < trials; t++) {\n            int s = rng.randint(0, M - 1);\n            int pred = simulate_one(rng, md, eps, s);\n            if (pred != s) err++;\n        }\n        double val = pow(0.9, err) / md.N;\n        if (val > best_value) {\n            best_value = val;\n            best_model = md;\n        }\n    }\n\n    cout << best_model.N << '\\n';\n    for (int k = 0; k < M; k++) {\n        cout << best_model.graphs[k] << '\\n';\n    }\n    cout.flush();\n\n    for (int q = 0; q < 100; q++) {\n        string H;\n        cin >> H;\n\n        int edges;\n        vector<int> deg = get_sorted_degrees(best_model.N, H, edges);\n        int ans = decode_model(best_model, deg, edges);\n\n        cout << ans << '\\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\nstatic const long long INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v, w;\n    int cell;\n    double imp = 0.0;\n};\n\nstruct Solver {\n    int N, M, D, K;\n    vector<Edge> edges;\n    vector<int> xs, ys;\n    vector<vector<pair<int,int>>> g;\n    int G = 8, C;\n\n    Timer timer;\n    mt19937 rng{123456789};\n\n    vector<int> day_of;\n    vector<int> load;\n    vector<double> day_imp;\n    vector<vector<int>> by_day;\n\n    // extra state\n    vector<vector<int>> cell_cnt;   // [day][cell]\n    vector<vector<int>> vday_cnt;   // [day][vertex]\n\n    // sampled evaluation\n    vector<int> sample_roots;\n    vector<vector<long long>> base_dist;\n    vector<double> day_score;\n    double total_score = 0.0;\n\n    int get_cell(double x, double y) {\n        int gx = min(G - 1, max(0, (int)(x * G / 1001.0)));\n        int gy = min(G - 1, max(0, (int)(y * G / 1001.0)));\n        return gy * G + gx;\n    }\n\n    void read_input() {\n        cin >> N >> M >> D >> K;\n        edges.resize(M);\n        g.assign(N, {});\n        for (int i = 0; i < M; i++) {\n            int u, v, w;\n            cin >> u >> v >> w;\n            --u; --v;\n            edges[i] = {u, v, w, -1, 0.0};\n            g[u].push_back({v, i});\n            g[v].push_back({u, i});\n        }\n        xs.resize(N);\n        ys.resize(N);\n        for (int i = 0; i < N; i++) cin >> xs[i] >> ys[i];\n\n        C = G * G;\n        for (int i = 0; i < M; i++) {\n            double mx = 0.5 * (xs[edges[i].u] + xs[edges[i].v]);\n            double my = 0.5 * (ys[edges[i].u] + ys[edges[i].v]);\n            edges[i].cell = get_cell(mx, my);\n        }\n    }\n\n    void dijkstra_normal(int s, vector<long long>& dist, vector<int>* parent_e = nullptr) {\n        dist.assign(N, INF64);\n        vector<int> pe;\n        if (parent_e) pe.assign(N, -1);\n\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 [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    if (parent_e) pe[to] = ei;\n                    pq.push({nd, to});\n                } else if (parent_e && nd == dist[to] && (pe[to] == -1 || ei < pe[to])) {\n                    pe[to] = ei;\n                }\n            }\n        }\n        if (parent_e) *parent_e = move(pe);\n    }\n\n    void dijkstra_removed_day(int s, int removed_day, vector<long long>& dist) {\n        dist.assign(N, INF64);\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 [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                if (day_of[ei] == removed_day) continue;\n                long long nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    pq.push({nd, to});\n                }\n            }\n        }\n    }\n\n    void compute_importance() {\n        vector<int> roots;\n        roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n        roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n        roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n        roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n        for (int t = 0; (int)roots.size() < min(24, max(8, 2 * D)); t++) {\n            int r = (int)((1LL * t * 911382323 + 972663749) % N);\n            roots.push_back(r);\n        }\n        sort(roots.begin(), roots.end());\n        roots.erase(unique(roots.begin(), roots.end()), roots.end());\n\n        vector<double> imp(M, 0.0), vcen(N, 0.0);\n        vector<long long> dist;\n        vector<int> parent_e;\n\n        for (int s : roots) {\n            if (timer.elapsed() > 1.05) break;\n            dijkstra_normal(s, dist, &parent_e);\n\n            double sumd = 0.0;\n            for (int i = 0; i < N; i++) if (dist[i] < INF64 / 4) sumd += dist[i];\n            double inv = (sumd > 0 ? 1.0 / sumd : 0.0);\n\n            for (int v = 0; v < N; v++) {\n                if (v == s) continue;\n                if (parent_e[v] != -1) {\n                    double add = 1.0 + 3.0 * (1.0 - dist[v] * inv);\n                    imp[parent_e[v]] += add;\n                }\n                if (dist[v] < INF64 / 4) {\n                    vcen[v] += (1.0 - dist[v] * inv);\n                }\n            }\n        }\n\n        for (int i = 0; i < M; i++) {\n            int u = edges[i].u, v = edges[i].v;\n            double val = imp[i];\n            val += 0.10 * g[u].size() + 0.10 * g[v].size();\n            val += 1.15 * (vcen[u] + vcen[v]);\n            val += 0.000002 * edges[i].w;\n            edges[i].imp = val;\n        }\n    }\n\n    void rebuild_by_day() {\n        by_day.assign(D, {});\n        for (int i = 0; i < M; i++) by_day[day_of[i]].push_back(i);\n    }\n\n    void build_initial_solution() {\n        day_of.assign(M, -1);\n        load.assign(D, 0);\n        day_imp.assign(D, 0.0);\n        cell_cnt.assign(D, vector<int>(C, 0));\n        vday_cnt.assign(D, vector<int>(N, 0));\n\n        vector<vector<int>> cell_edges(C);\n        vector<double> cell_imp(C, 0.0);\n        for (int i = 0; i < M; i++) {\n            cell_edges[edges[i].cell].push_back(i);\n            cell_imp[edges[i].cell] += edges[i].imp;\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 cell_imp[a] > cell_imp[b];\n        });\n\n        for (int c : cells) {\n            auto &vec = cell_edges[c];\n            sort(vec.begin(), vec.end(), [&](int a, int b) {\n                if (edges[a].imp != edges[b].imp) return edges[a].imp > edges[b].imp;\n                return edges[a].w > edges[b].w;\n            });\n\n            int ptr = 0;\n            for (int ei : vec) {\n                double best = 1e100;\n                int bestd = -1;\n                auto &e = edges[ei];\n                for (int tt = 0; tt < D; tt++) {\n                    int d = (ptr + tt) % D;\n                    if (load[d] >= K) continue;\n\n                    double cost = 0.0;\n                    cost += 18.0 * cell_cnt[d][c];\n                    cost += 15.0 * (vday_cnt[d][e.u] + vday_cnt[d][e.v]);\n                    cost += 9.0 * load[d];\n                    cost += 0.40 * day_imp[d];\n                    cost += 0.7 * e.imp * cell_cnt[d][c];\n                    cost += 0.8 * e.imp * (vday_cnt[d][e.u] + vday_cnt[d][e.v]);\n\n                    if (cost < best) {\n                        best = cost;\n                        bestd = d;\n                    }\n                }\n                ptr = (ptr + 1) % D;\n                if (bestd == -1) {\n                    for (int d = 0; d < D; d++) if (load[d] < K) { bestd = d; break; }\n                }\n\n                day_of[ei] = bestd;\n                load[bestd]++;\n                day_imp[bestd] += e.imp;\n                cell_cnt[bestd][c]++;\n                vday_cnt[bestd][e.u]++;\n                vday_cnt[bestd][e.v]++;\n            }\n        }\n\n        rebuild_by_day();\n    }\n\n    void choose_sample_roots() {\n        sample_roots.clear();\n        sample_roots.push_back(min_element(xs.begin(), xs.end()) - xs.begin());\n        sample_roots.push_back(max_element(xs.begin(), xs.end()) - xs.begin());\n        sample_roots.push_back(min_element(ys.begin(), ys.end()) - ys.begin());\n        sample_roots.push_back(max_element(ys.begin(), ys.end()) - ys.begin());\n\n        vector<int> idx(N);\n        iota(idx.begin(), idx.end(), 0);\n        sort(idx.begin(), idx.end(), [&](int a, int b) {\n            return g[a].size() > g[b].size();\n        });\n        for (int i = 0; i < min(2, N); i++) sample_roots.push_back(idx[i]);\n\n        sort(sample_roots.begin(), sample_roots.end());\n        sample_roots.erase(unique(sample_roots.begin(), sample_roots.end()), sample_roots.end());\n        if ((int)sample_roots.size() > 6) sample_roots.resize(6);\n    }\n\n    void precompute_base_dist() {\n        choose_sample_roots();\n        base_dist.assign(sample_roots.size(), vector<long long>());\n        for (int i = 0; i < (int)sample_roots.size(); i++) {\n            dijkstra_normal(sample_roots[i], base_dist[i]);\n        }\n    }\n\n    double eval_day(int day) {\n        vector<long long> dist;\n        double sum = 0.0;\n        for (int si = 0; si < (int)sample_roots.size(); si++) {\n            dijkstra_removed_day(sample_roots[si], day, dist);\n            for (int v = 0; v < N; v++) {\n                if (v == sample_roots[si]) continue;\n                long long bd = base_dist[si][v];\n                long long nd = dist[v];\n                if (nd >= INF64 / 4) nd = 1000000000LL;\n                sum += (double)(nd - bd);\n            }\n        }\n        return sum;\n    }\n\n    void init_scores() {\n        day_score.assign(D, 0.0);\n        total_score = 0.0;\n        for (int d = 0; d < D; d++) {\n            day_score[d] = eval_day(d);\n            total_score += day_score[d];\n        }\n    }\n\n    void apply_move(int ei, int from, int to) {\n        const auto &e = edges[ei];\n        day_of[ei] = to;\n        load[from]--;\n        load[to]++;\n        day_imp[from] -= e.imp;\n        day_imp[to] += e.imp;\n        cell_cnt[from][e.cell]--;\n        cell_cnt[to][e.cell]++;\n        vday_cnt[from][e.u]--;\n        vday_cnt[from][e.v]--;\n        vday_cnt[to][e.u]++;\n        vday_cnt[to][e.v]++;\n    }\n\n    void rollback_move(int ei, int from, int to) {\n        const auto &e = edges[ei];\n        day_of[ei] = from;\n        load[from]++;\n        load[to]--;\n        day_imp[from] += e.imp;\n        day_imp[to] -= e.imp;\n        cell_cnt[from][e.cell]++;\n        cell_cnt[to][e.cell]--;\n        vday_cnt[from][e.u]++;\n        vday_cnt[from][e.v]++;\n        vday_cnt[to][e.u]--;\n        vday_cnt[to][e.v]--;\n    }\n\n    void apply_swap(int e1, int d1, int e2, int d2) {\n        const auto &a = edges[e1];\n        const auto &b = edges[e2];\n        day_of[e1] = d2;\n        day_of[e2] = d1;\n        day_imp[d1] += b.imp - a.imp;\n        day_imp[d2] += a.imp - b.imp;\n        cell_cnt[d1][a.cell]--;\n        cell_cnt[d1][b.cell]++;\n        cell_cnt[d2][b.cell]--;\n        cell_cnt[d2][a.cell]++;\n        vday_cnt[d1][a.u]--;\n        vday_cnt[d1][a.v]--;\n        vday_cnt[d2][a.u]++;\n        vday_cnt[d2][a.v]++;\n        vday_cnt[d2][b.u]--;\n        vday_cnt[d2][b.v]--;\n        vday_cnt[d1][b.u]++;\n        vday_cnt[d1][b.v]++;\n    }\n\n    void rollback_swap(int e1, int d1, int e2, int d2) {\n        apply_swap(e1, d2, e2, d1);\n    }\n\n    void focused_improvement() {\n        for (int round = 0; round < 16 && timer.elapsed() < 4.55; round++) {\n            rebuild_by_day();\n            int worst = max_element(day_score.begin(), day_score.end()) - day_score.begin();\n            if (by_day[worst].empty()) break;\n\n            vector<int> cand = by_day[worst];\n            sort(cand.begin(), cand.end(), [&](int a, int b) {\n                double sa = edges[a].imp\n                    + 8.0 * cell_cnt[worst][edges[a].cell]\n                    + 10.0 * (vday_cnt[worst][edges[a].u] + vday_cnt[worst][edges[a].v]);\n                double sb = edges[b].imp\n                    + 8.0 * cell_cnt[worst][edges[b].cell]\n                    + 10.0 * (vday_cnt[worst][edges[b].u] + vday_cnt[worst][edges[b].v]);\n                return sa > sb;\n            });\n\n            bool improved = false;\n            int lim = min<int>(16, cand.size());\n            for (int i = 0; i < lim && timer.elapsed() < 4.55; i++) {\n                int ei = cand[i];\n                int from = worst;\n                const auto &e = edges[ei];\n\n                vector<int> days(D);\n                iota(days.begin(), days.end(), 0);\n                sort(days.begin(), days.end(), [&](int a, int b) {\n                    if (a == from) return false;\n                    if (b == from) return true;\n                    double ca = day_score[a]\n                        + 20.0 * cell_cnt[a][e.cell]\n                        + 18.0 * (vday_cnt[a][e.u] + vday_cnt[a][e.v])\n                        + 2.0 * load[a];\n                    double cb = day_score[b]\n                        + 20.0 * cell_cnt[b][e.cell]\n                        + 18.0 * (vday_cnt[b][e.u] + vday_cnt[b][e.v])\n                        + 2.0 * load[b];\n                    return ca < cb;\n                });\n\n                for (int z = 0; z < min(D, 8) && timer.elapsed() < 4.55; z++) {\n                    int to = days[z];\n                    if (to == from || load[to] >= K) continue;\n\n                    apply_move(ei, from, to);\n                    double new_from = eval_day(from);\n                    double new_to = eval_day(to);\n                    double new_total = total_score - day_score[from] - day_score[to] + new_from + new_to;\n\n                    if (new_total < total_score) {\n                        total_score = new_total;\n                        day_score[from] = new_from;\n                        day_score[to] = new_to;\n                        improved = true;\n                        break;\n                    } else {\n                        rollback_move(ei, from, to);\n                    }\n                }\n                if (improved) break;\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    void random_local_search() {\n        int iter = 0;\n        while (timer.elapsed() < 5.55) {\n            iter++;\n            if ((iter & 255) == 0) rebuild_by_day();\n\n            if ((rng() & 1) == 0) {\n                int ei = rng() % M;\n                int from = day_of[ei];\n                int to = rng() % D;\n                if (from == to || load[to] >= K) continue;\n\n                const auto &e = edges[ei];\n                double rough =\n                    8.0 * (cell_cnt[to][e.cell] - cell_cnt[from][e.cell]) +\n                    10.0 * ((vday_cnt[to][e.u] + vday_cnt[to][e.v]) - (vday_cnt[from][e.u] + vday_cnt[from][e.v])) +\n                    1.0 * (load[to] - load[from]);\n                if (rough > 4.0 && (rng() & 3)) continue;\n\n                apply_move(ei, from, to);\n                double new_from = eval_day(from);\n                double new_to = eval_day(to);\n                double new_total = total_score - day_score[from] - day_score[to] + new_from + new_to;\n\n                if (new_total <= total_score) {\n                    total_score = new_total;\n                    day_score[from] = new_from;\n                    day_score[to] = new_to;\n                } else {\n                    rollback_move(ei, from, to);\n                }\n            } else {\n                int d1 = rng() % D;\n                int d2 = rng() % D;\n                if (d1 == d2) continue;\n                if (by_day[d1].empty() || by_day[d2].empty()) continue;\n\n                int e1 = by_day[d1][rng() % by_day[d1].size()];\n                int e2 = by_day[d2][rng() % by_day[d2].size()];\n                if (e1 == e2) continue;\n                if (day_of[e1] != d1 || day_of[e2] != d2) continue;\n\n                apply_swap(e1, d1, e2, d2);\n                double new_d1 = eval_day(d1);\n                double new_d2 = eval_day(d2);\n                double new_total = total_score - day_score[d1] - day_score[d2] + new_d1 + new_d2;\n\n                if (new_total <= total_score) {\n                    total_score = new_total;\n                    day_score[d1] = new_d1;\n                    day_score[d2] = new_d2;\n                } else {\n                    rollback_swap(e1, d1, e2, d2);\n                }\n            }\n        }\n    }\n\n    void repair_feasibility() {\n        vector<int> cnt(D, 0);\n        for (int i = 0; i < M; i++) cnt[day_of[i]]++;\n        for (int d = 0; d < D; d++) {\n            while (cnt[d] > K) {\n                int nd = -1;\n                for (int t = 0; t < D; t++) if (cnt[t] < K) { nd = t; break; }\n                if (nd == -1) break;\n                for (int i = 0; i < M; i++) {\n                    if (day_of[i] == d) {\n                        day_of[i] = nd;\n                        cnt[d]--;\n                        cnt[nd]++;\n                        break;\n                    }\n                }\n            }\n        }\n    }\n\n    void solve() {\n        read_input();\n        compute_importance();\n        build_initial_solution();\n        precompute_base_dist();\n        init_scores();\n        focused_improvement();\n        random_local_search();\n        repair_feasibility();\n\n        for (int i = 0; i < M; i++) {\n            if (i) cout << ' ';\n            cout << day_of[i] + 1;\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}","ahc019":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic const int DX6[6] = {1,-1,0,0,0,0};\nstatic const int DY6[6] = {0,0,1,-1,0,0};\nstatic const int DZ6[6] = {0,0,0,0,1,-1};\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n} rng;\n\nstruct P3 {\n    int x, y, z;\n};\n\nstruct Rot {\n    int p[3];\n    int s[3];\n};\n\nstruct Piece {\n    vector<int> vox;\n    string sig;\n};\n\nstruct Candidate {\n    vector<char> occ0, occ1;\n    vector<Piece> bestP0, bestP1;\n    long long proxy = LLONG_MIN;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D;\n    cin >> D;\n    vector<string> f[2], r[2];\n    for (int t = 0; t < 2; t++) {\n        f[t].resize(D);\n        r[t].resize(D);\n        for (int i = 0; i < D; i++) cin >> f[t][i];\n        for (int i = 0; i < D; i++) cin >> r[t][i];\n    }\n\n    auto idx = [&](int x, int y, int z) -> int {\n        return (x * D + y) * D + z;\n    };\n    auto inside = [&](int x, int y, int z) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D && 0 <= z && z < D;\n    };\n    auto decode = [&](int v) -> P3 {\n        int z = v % D;\n        int t = v / D;\n        int y = t % D;\n        int x = t / D;\n        return {x, y, z};\n    };\n\n    const int N3 = D * D * D;\n\n    vector<Rot> rots;\n    {\n        vector<int> perm = {0,1,2};\n        do {\n            int sign_perm = 1;\n            for (int i = 0; i < 3; i++) for (int j = i + 1; j < 3; j++) {\n                if (perm[i] > perm[j]) sign_perm *= -1;\n            }\n            for (int sx : {-1, 1}) for (int sy : {-1, 1}) for (int sz : {-1, 1}) {\n                if (sign_perm * sx * sy * sz == 1) {\n                    Rot rt;\n                    rt.p[0] = perm[0];\n                    rt.p[1] = perm[1];\n                    rt.p[2] = perm[2];\n                    rt.s[0] = sx;\n                    rt.s[1] = sy;\n                    rt.s[2] = sz;\n                    rots.push_back(rt);\n                }\n            }\n        } while (next_permutation(perm.begin(), perm.end()));\n    }\n\n    auto rotate_point = [&](const P3& a, const Rot& rt) -> P3 {\n        int v[3] = {a.x, a.y, a.z};\n        return P3{\n            rt.s[0] * v[rt.p[0]],\n            rt.s[1] * v[rt.p[1]],\n            rt.s[2] * v[rt.p[2]]\n        };\n    };\n\n    auto canonical_signature_from_vox = [&](const vector<int>& vox) -> string {\n        vector<P3> cells;\n        cells.reserve(vox.size());\n        int minx = 1e9, miny = 1e9, minz = 1e9;\n        for (int v : vox) {\n            auto p = decode(v);\n            minx = min(minx, p.x);\n            miny = min(miny, p.y);\n            minz = min(minz, p.z);\n            cells.push_back(p);\n        }\n        for (auto &p : cells) {\n            p.x -= minx;\n            p.y -= miny;\n            p.z -= minz;\n        }\n\n        string best;\n        bool first = true;\n        for (const auto& rt : rots) {\n            vector<array<int,3>> q;\n            q.reserve(cells.size());\n            int bx = 1e9, by = 1e9, bz = 1e9;\n            for (auto &p : cells) {\n                P3 t = rotate_point(p, rt);\n                bx = min(bx, t.x);\n                by = min(by, t.y);\n                bz = min(bz, t.z);\n                q.push_back({t.x, t.y, t.z});\n            }\n            for (auto &a : q) {\n                a[0] -= bx;\n                a[1] -= by;\n                a[2] -= bz;\n            }\n            sort(q.begin(), q.end());\n            string s;\n            s.reserve(q.size() * 12);\n            for (auto &a : q) {\n                s += to_string(a[0]);\n                s.push_back(',');\n                s += to_string(a[1]);\n                s.push_back(',');\n                s += to_string(a[2]);\n                s.push_back(';');\n            }\n            if (first || s < best) {\n                best = move(s);\n                first = false;\n            }\n        }\n        return best;\n    };\n\n    auto initial_build = [&](int t) -> vector<char> {\n        vector<char> occ(N3, 0);\n        for (int z = 0; z < D; z++) {\n            vector<int> X, Y;\n            for (int x = 0; x < D; x++) if (f[t][z][x] == '1') X.push_back(x);\n            for (int y = 0; y < D; y++) if (r[t][z][y] == '1') Y.push_back(y);\n            int a = (int)X.size(), b = (int)Y.size();\n            if (a == 0 || b == 0) continue;\n            if (a <= b) {\n                for (int i = 0; i < a; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = a; i < b; i++) occ[idx(X[0], Y[i], z)] = 1;\n            } else {\n                for (int i = 0; i < b; i++) occ[idx(X[i], Y[i], z)] = 1;\n                for (int i = b; i < a; i++) occ[idx(X[i], Y[0], z)] = 1;\n            }\n        }\n        return occ;\n    };\n\n    auto build_layer_variants = [&](int cur, int z, const vector<char>& refOcc, const vector<char>& selfOcc, int variants) {\n        vector<vector<pair<int,int>>> ret;\n        vector<int> X, Y;\n        for (int x = 0; x < D; x++) if (f[cur][z][x] == '1') X.push_back(x);\n        for (int y = 0; y < D; y++) if (r[cur][z][y] == '1') Y.push_back(y);\n        int a = (int)X.size(), b = (int)Y.size();\n        if (a == 0 || b == 0) {\n            ret.push_back({});\n            return ret;\n        }\n\n        for (int tr = 0; tr < variants; tr++) {\n            vector<int> px = X, py = Y;\n            shuffle(px.begin(), px.end(), std::mt19937(rng.next_u32()));\n            shuffle(py.begin(), py.end(), std::mt19937(rng.next_u32()));\n\n            vector<pair<int,int>> cells;\n            int m = min(a, b);\n            for (int i = 0; i < m; i++) cells.push_back({px[i], py[i]});\n\n            if (a > b) {\n                int bestY = Y[0];\n                long long bestYScore = LLONG_MIN;\n                for (int candY : Y) {\n                    long long sc = 0;\n                    for (int i = b; i < a; i++) {\n                        int x = px[i];\n                        int id = idx(x, candY, z);\n                        if (refOcc[id]) sc += 24;\n                        if (selfOcc[id]) sc += 12;\n                        if (z > 0 && selfOcc[idx(x, candY, z-1)]) sc += 10;\n                        if (z + 1 < D && selfOcc[idx(x, candY, z+1)]) sc += 10;\n                    }\n                    if (sc > bestYScore) bestYScore = sc, bestY = candY;\n                }\n                for (int i = b; i < a; i++) cells.push_back({px[i], bestY});\n            } else if (b > a) {\n                int bestX = X[0];\n                long long bestXScore = LLONG_MIN;\n                for (int candX : X) {\n                    long long sc = 0;\n                    for (int j = a; j < b; j++) {\n                        int y = py[j];\n                        int id = idx(candX, y, z);\n                        if (refOcc[id]) sc += 24;\n                        if (selfOcc[id]) sc += 12;\n                        if (z > 0 && selfOcc[idx(candX, y, z-1)]) sc += 10;\n                        if (z + 1 < D && selfOcc[idx(candX, y, z+1)]) sc += 10;\n                    }\n                    if (sc > bestXScore) bestXScore = sc, bestX = candX;\n                }\n                for (int j = a; j < b; j++) cells.push_back({bestX, py[j]});\n            }\n\n            ret.push_back(move(cells));\n        }\n        return ret;\n    };\n\n    auto choose_best_layer = [&](int cur, int z, const vector<char>& refOcc, const vector<char>& selfHint, const vector<char>& builtPrefix, int variants) {\n        auto candLayers = build_layer_variants(cur, z, refOcc, selfHint, variants);\n        long long bestScore = LLONG_MIN;\n        vector<pair<int,int>> best;\n        for (auto &cells : candLayers) {\n            unordered_set<int> S;\n            S.reserve(cells.size() * 2 + 10);\n            long long score = 0;\n            for (auto [x, y] : cells) {\n                int id = idx(x, y, z);\n                S.insert(id);\n                if (refOcc[id]) score += 60;\n                if (selfHint[id]) score += 25;\n                if (z > 0 && builtPrefix[idx(x, y, z-1)]) score += 18;\n                if (z + 1 < D && selfHint[idx(x, y, z+1)]) score += 5;\n            }\n            for (auto [x, y] : cells) {\n                int cnt = 0;\n                if (x > 0 && S.count(idx(x-1, y, z))) cnt++;\n                if (x + 1 < D && S.count(idx(x+1, y, z))) cnt++;\n                if (y > 0 && S.count(idx(x, y-1, z))) cnt++;\n                if (y + 1 < D && S.count(idx(x, y+1, z))) cnt++;\n                score += 7LL * cnt;\n            }\n            if (score > bestScore) {\n                bestScore = score;\n                best = cells;\n            }\n        }\n        return best;\n    };\n\n    auto build_object = [&](int cur, const vector<char>& refOcc, const vector<char>& selfHint, int intensity) -> vector<char> {\n        vector<char> occ(N3, 0);\n        int baseTrials = (D <= 7 ? 80 : (D <= 10 ? 55 : 35));\n        int variants = baseTrials + intensity;\n        for (int z = 0; z < D; z++) {\n            auto best = choose_best_layer(cur, z, refOcc, selfHint, occ, variants);\n            for (auto [x, y] : best) occ[idx(x, y, z)] = 1;\n        }\n        return occ;\n    };\n\n    auto extract_cuboids = [&](vector<char>& alive, vector<Piece>& pieces) {\n        while (true) {\n            int bestVol = 0;\n            vector<int> bestVox;\n\n            for (int x1 = 0; x1 < D; x1++) for (int y1 = 0; y1 < D; y1++) for (int z1 = 0; z1 < D; z1++) {\n                if (!alive[idx(x1, y1, z1)]) continue;\n                for (int x2 = x1; x2 < D; x2++) for (int y2 = y1; y2 < D; y2++) for (int z2 = z1; z2 < D; z2++) {\n                    int vol = (x2 - x1 + 1) * (y2 - y1 + 1) * (z2 - z1 + 1);\n                    if (vol <= bestVol) continue;\n                    bool full = true;\n                    vector<int> vox;\n                    vox.reserve(vol);\n                    for (int x = x1; x <= x2 && full; x++) {\n                        for (int y = y1; y <= y2 && full; y++) {\n                            for (int z = z1; z <= z2; z++) {\n                                int id = idx(x, y, z);\n                                if (!alive[id]) {\n                                    full = false;\n                                    break;\n                                }\n                                vox.push_back(id);\n                            }\n                        }\n                    }\n                    if (full) {\n                        bestVol = vol;\n                        bestVox = move(vox);\n                    }\n                }\n            }\n\n            if (bestVol < 2) break;\n            Piece pc;\n            pc.vox = bestVox;\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n            for (int v : bestVox) alive[v] = 0;\n        }\n    };\n\n    auto extract_rectangles = [&](vector<char>& alive, vector<Piece>& pieces) {\n        while (true) {\n            int bestArea = 0;\n            vector<int> bestVox;\n\n            for (int z = 0; z < D; z++) {\n                for (int x1 = 0; x1 < D; x1++) for (int y1 = 0; y1 < D; y1++) {\n                    if (!alive[idx(x1, y1, z)]) continue;\n                    for (int x2 = x1; x2 < D; x2++) for (int y2 = y1; y2 < D; y2++) {\n                        int area = (x2 - x1 + 1) * (y2 - y1 + 1);\n                        if (area <= bestArea) continue;\n                        bool full = true;\n                        vector<int> vox;\n                        vox.reserve(area);\n                        for (int x = x1; x <= x2 && full; x++) {\n                            for (int y = y1; y <= y2; y++) {\n                                int id = idx(x, y, z);\n                                if (!alive[id]) {\n                                    full = false;\n                                    break;\n                                }\n                                vox.push_back(id);\n                            }\n                        }\n                        if (full) {\n                            bestArea = area;\n                            bestVox = move(vox);\n                        }\n                    }\n                }\n            }\n\n            if (bestArea < 2) break;\n            Piece pc;\n            pc.vox = bestVox;\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n            for (int v : bestVox) alive[v] = 0;\n        }\n    };\n\n    auto extract_straight_runs = [&](vector<char>& alive, vector<Piece>& pieces) {\n        while (true) {\n            int bestLen = 0;\n            vector<int> bestVox;\n            for (int x = 0; x < D; x++) for (int y = 0; y < D; y++) for (int z = 0; z < D; z++) {\n                int s = idx(x, y, z);\n                if (!alive[s]) continue;\n\n                if (x == 0 || !alive[idx(x-1, y, z)]) {\n                    vector<int> cur;\n                    for (int nx = x; nx < D && alive[idx(nx, y, z)]; nx++) cur.push_back(idx(nx, y, z));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n                if (y == 0 || !alive[idx(x, y-1, z)]) {\n                    vector<int> cur;\n                    for (int ny = y; ny < D && alive[idx(x, ny, z)]; ny++) cur.push_back(idx(x, ny, z));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n                if (z == 0 || !alive[idx(x, y, z-1)]) {\n                    vector<int> cur;\n                    for (int nz = z; nz < D && alive[idx(x, y, nz)]; nz++) cur.push_back(idx(x, y, nz));\n                    if ((int)cur.size() > bestLen) bestLen = (int)cur.size(), bestVox = move(cur);\n                }\n            }\n\n            if (bestLen < 2) break;\n            Piece pc;\n            pc.vox = bestVox;\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n            for (int v : bestVox) alive[v] = 0;\n        }\n    };\n\n    auto extract_paths = [&](vector<char>& alive, vector<Piece>& pieces) {\n        vector<char> vis(N3, 0);\n        vector<int> parent(N3), dist(N3), mark(N3, 0);\n\n        auto bfs_farthest = [&](int start) -> int {\n            fill(parent.begin(), parent.end(), -1);\n            fill(dist.begin(), dist.end(), -1);\n            queue<int> q;\n            q.push(start);\n            dist[start] = 0;\n            int best = start;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                if (dist[v] > dist[best]) best = v;\n                auto p = decode(v);\n                for (int dir = 0; dir < 6; dir++) {\n                    int nx = p.x + DX6[dir];\n                    int ny = p.y + DY6[dir];\n                    int nz = p.z + DZ6[dir];\n                    if (!inside(nx, ny, nz)) continue;\n                    int to = idx(nx, ny, nz);\n                    if (!alive[to] || !mark[to] || dist[to] != -1) continue;\n                    dist[to] = dist[v] + 1;\n                    parent[to] = v;\n                    q.push(to);\n                }\n            }\n            return best;\n        };\n\n        bool progress = true;\n        while (progress) {\n            progress = false;\n            vis.assign(N3, 0);\n            for (int s = 0; s < N3; s++) {\n                if (!alive[s] || vis[s]) continue;\n\n                vector<int> comp;\n                queue<int> q;\n                q.push(s);\n                vis[s] = 1;\n                while (!q.empty()) {\n                    int v = q.front(); q.pop();\n                    comp.push_back(v);\n                    auto p = decode(v);\n                    for (int dir = 0; dir < 6; dir++) {\n                        int nx = p.x + DX6[dir];\n                        int ny = p.y + DY6[dir];\n                        int nz = p.z + DZ6[dir];\n                        if (!inside(nx, ny, nz)) continue;\n                        int to = idx(nx, ny, nz);\n                        if (alive[to] && !vis[to]) {\n                            vis[to] = 1;\n                            q.push(to);\n                        }\n                    }\n                }\n\n                if ((int)comp.size() < 2) continue;\n                for (int v : comp) mark[v] = 1;\n                int a = bfs_farthest(comp[0]);\n                int b = bfs_farthest(a);\n\n                if (dist[b] >= 1) {\n                    vector<int> path;\n                    for (int v = b; v != -1; v = parent[v]) path.push_back(v);\n                    if ((int)path.size() >= 2) {\n                        Piece pc;\n                        pc.vox = path;\n                        pc.sig = canonical_signature_from_vox(pc.vox);\n                        pieces.push_back(move(pc));\n                        for (int v : path) alive[v] = 0;\n                        progress = true;\n                    }\n                }\n                for (int v : comp) mark[v] = 0;\n            }\n        }\n    };\n\n    auto residual_components = [&](const vector<char>& alive, vector<Piece>& pieces) {\n        vector<char> vis(N3, 0);\n        for (int s = 0; s < N3; s++) {\n            if (!alive[s] || vis[s]) continue;\n            queue<int> q;\n            q.push(s);\n            vis[s] = 1;\n            vector<int> vox;\n            while (!q.empty()) {\n                int v = q.front(); q.pop();\n                vox.push_back(v);\n                auto p = decode(v);\n                for (int dir = 0; dir < 6; dir++) {\n                    int nx = p.x + DX6[dir];\n                    int ny = p.y + DY6[dir];\n                    int nz = p.z + DZ6[dir];\n                    if (!inside(nx, ny, nz)) continue;\n                    int to = idx(nx, ny, nz);\n                    if (alive[to] && !vis[to]) {\n                        vis[to] = 1;\n                        q.push(to);\n                    }\n                }\n            }\n            Piece pc;\n            pc.vox = move(vox);\n            pc.sig = canonical_signature_from_vox(pc.vox);\n            pieces.push_back(move(pc));\n        }\n    };\n\n    enum DecompMode {\n        STRAIGHT_PATH_RESID = 0,\n        PATH_STRAIGHT_RESID = 1,\n        COMPONENT_ONLY = 2,\n        RECT_STRAIGHT_PATH_RESID = 3,\n        RECT_RESID = 4,\n        CUBOID_RECT_STRAIGHT_PATH_RESID = 5,\n        CUBOID_RESID = 6\n    };\n\n    auto decompose = [&](const vector<char>& occ, int mode) -> vector<Piece> {\n        vector<char> alive = occ;\n        vector<Piece> pieces;\n        if (mode == STRAIGHT_PATH_RESID) {\n            extract_straight_runs(alive, pieces);\n            extract_paths(alive, pieces);\n            residual_components(alive, pieces);\n        } else if (mode == PATH_STRAIGHT_RESID) {\n            extract_paths(alive, pieces);\n            extract_straight_runs(alive, pieces);\n            residual_components(alive, pieces);\n        } else if (mode == COMPONENT_ONLY) {\n            residual_components(alive, pieces);\n        } else if (mode == RECT_STRAIGHT_PATH_RESID) {\n            extract_rectangles(alive, pieces);\n            extract_straight_runs(alive, pieces);\n            extract_paths(alive, pieces);\n            residual_components(alive, pieces);\n        } else if (mode == RECT_RESID) {\n            extract_rectangles(alive, pieces);\n            residual_components(alive, pieces);\n        } else if (mode == CUBOID_RECT_STRAIGHT_PATH_RESID) {\n            extract_cuboids(alive, pieces);\n            extract_rectangles(alive, pieces);\n            extract_straight_runs(alive, pieces);\n            extract_paths(alive, pieces);\n            residual_components(alive, pieces);\n        } else {\n            extract_cuboids(alive, pieces);\n            residual_components(alive, pieces);\n        }\n        return pieces;\n    };\n\n    auto proxy_score = [&](const vector<Piece>& p0, const vector<Piece>& p1) -> long long {\n        unordered_map<string, vector<int>> a, b;\n        a.reserve(p0.size() * 2 + 10);\n        b.reserve(p1.size() * 2 + 10);\n        for (auto &pc : p0) a[pc.sig].push_back((int)pc.vox.size());\n        for (auto &pc : p1) b[pc.sig].push_back((int)pc.vox.size());\n\n        long long score = 0;\n        for (auto &kv : a) {\n            auto it = b.find(kv.first);\n            if (it == b.end()) continue;\n            auto va = kv.second, vb = it->second;\n            sort(va.begin(), va.end(), greater<int>());\n            sort(vb.begin(), vb.end(), greater<int>());\n            int m = min((int)va.size(), (int)vb.size());\n            for (int i = 0; i < m; i++) {\n                int v = min(va[i], vb[i]);\n                score += 1000LL * v + 1LL * v * v;\n            }\n        }\n        return score;\n    };\n\n    auto choose_best_decompositions = [&](Candidate& cand) {\n        const int MODES = 7;\n        vector<vector<Piece>> dec0(MODES), dec1(MODES);\n        for (int m = 0; m < MODES; m++) dec0[m] = decompose(cand.occ0, m);\n        for (int m = 0; m < MODES; m++) dec1[m] = decompose(cand.occ1, m);\n\n        cand.proxy = LLONG_MIN;\n        for (int a = 0; a < MODES; a++) for (int b = 0; b < MODES; b++) {\n            long long sc = proxy_score(dec0[a], dec1[b]);\n            if (sc > cand.proxy) {\n                cand.proxy = sc;\n                cand.bestP0 = dec0[a];\n                cand.bestP1 = dec1[b];\n            }\n        }\n    };\n\n    auto build_candidate = [&](int intensity, bool reverse_order) -> Candidate {\n        Candidate cand;\n        vector<char> a0 = initial_build(0);\n        vector<char> a1 = initial_build(1);\n\n        int rounds = 5 + intensity / 15;\n        for (int it = 0; it < rounds; it++) {\n            if (!reverse_order) {\n                auto n0 = build_object(0, a1, a0, intensity);\n                auto n1 = build_object(1, n0, a1, intensity);\n                a0.swap(n0);\n                a1.swap(n1);\n            } else {\n                auto n1 = build_object(1, a0, a1, intensity);\n                auto n0 = build_object(0, n1, a0, intensity);\n                a0.swap(n0);\n                a1.swap(n1);\n            }\n        }\n\n        cand.occ0 = move(a0);\n        cand.occ1 = move(a1);\n        choose_best_decompositions(cand);\n        return cand;\n    };\n\n    Candidate best;\n    int multi = (D <= 7 ? 10 : (D <= 10 ? 7 : 5));\n    for (int t = 0; t < multi; t++) {\n        int intensity = 10 + 10 * (t % 6);\n        bool rev = (t & 1);\n        Candidate cand = build_candidate(intensity, rev);\n        if (cand.proxy > best.proxy) best = move(cand);\n    }\n\n    auto &pieces0 = best.bestP0;\n    auto &pieces1 = best.bestP1;\n\n    unordered_map<string, vector<int>> mp0, mp1;\n    mp0.reserve(pieces0.size() * 2 + 10);\n    mp1.reserve(pieces1.size() * 2 + 10);\n\n    for (int i = 0; i < (int)pieces0.size(); i++) mp0[pieces0[i].sig].push_back(i);\n    for (int i = 0; i < (int)pieces1.size(); i++) mp1[pieces1[i].sig].push_back(i);\n\n    for (auto &kv : mp0) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            return pieces0[a].vox.size() > pieces0[b].vox.size();\n        });\n    }\n    for (auto &kv : mp1) {\n        auto &v = kv.second;\n        sort(v.begin(), v.end(), [&](int a, int b) {\n            return pieces1[a].vox.size() > pieces1[b].vox.size();\n        });\n    }\n\n    vector<int> ans0(N3, 0), ans1(N3, 0);\n    int nBlocks = 0;\n\n    unordered_set<string> keys;\n    keys.reserve(mp0.size() + mp1.size() + 10);\n    for (auto &kv : mp0) keys.insert(kv.first);\n    for (auto &kv : mp1) keys.insert(kv.first);\n\n    for (const string &sig : keys) {\n        auto it0 = mp0.find(sig);\n        auto it1 = mp1.find(sig);\n        vector<int>* v0 = (it0 == mp0.end() ? nullptr : &it0->second);\n        vector<int>* v1 = (it1 == mp1.end() ? nullptr : &it1->second);\n\n        int c0 = v0 ? (int)v0->size() : 0;\n        int c1 = v1 ? (int)v1->size() : 0;\n        int m = min(c0, c1);\n\n        for (int i = 0; i < m; i++) {\n            ++nBlocks;\n            for (int id : pieces0[(*v0)[i]].vox) ans0[id] = nBlocks;\n            for (int id : pieces1[(*v1)[i]].vox) ans1[id] = nBlocks;\n        }\n        if (v0) {\n            for (int i = m; i < c0; i++) {\n                ++nBlocks;\n                for (int id : pieces0[(*v0)[i]].vox) ans0[id] = nBlocks;\n            }\n        }\n        if (v1) {\n            for (int i = m; i < c1; i++) {\n                ++nBlocks;\n                for (int id : pieces1[(*v1)[i]].vox) ans1[id] = nBlocks;\n            }\n        }\n    }\n\n    cout << nBlocks << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << ans0[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < N3; i++) {\n        if (i) cout << ' ';\n        cout << ans1[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc020":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nconst ll INF64 = (1LL << 60);\n\nstruct Edge {\n    int u, v, w;\n};\n\nstruct DijkstraResult {\n    vector<ll> dist;\n    vector<int> prev_v;\n    vector<int> prev_e;\n};\n\nstatic inline ll sqrll(ll x) { return x * x; }\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        int u, v, w;\n        cin >> u >> v >> w;\n        --u; --v;\n        edges[i] = {u, v, w};\n        g[u].push_back({v, i});\n        g[v].push_back({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    vector<vector<unsigned short>> reqR(N, vector<unsigned short>(K));\n    vector<vector<pair<unsigned short,int>>> sortedReq(N);\n    for (int v = 0; v < N; v++) {\n        sortedReq[v].reserve(K);\n        for (int k = 0; k < K; k++) {\n            ll dx = (ll)x[v] - a[k];\n            ll dy = (ll)y[v] - b[k];\n            long double d = sqrt((long double)dx * dx + (long double)dy * dy);\n            int r = (int)ceill(d - 1e-12L);\n            if (r > 5000) r = 5001;\n            reqR[v][k] = (unsigned short)r;\n            if (r <= 5000) sortedReq[v].push_back({(unsigned short)r, k});\n        }\n        sort(sortedReq[v].begin(), sortedReq[v].end());\n    }\n\n    auto dijkstra = [&](int s) -> DijkstraResult {\n        vector<ll> dist(N, INF64);\n        vector<int> prev_v(N, -1), prev_e(N, -1);\n        priority_queue<pair<ll,int>, vector<pair<ll,int>>, greater<pair<ll,int>>> pq;\n        dist[s] = 0;\n        pq.push({0, s});\n        while (!pq.empty()) {\n            auto [cd, v] = pq.top(); pq.pop();\n            if (cd != dist[v]) continue;\n            for (auto [to, ei] : g[v]) {\n                ll nd = cd + edges[ei].w;\n                if (nd < dist[to]) {\n                    dist[to] = nd;\n                    prev_v[to] = v;\n                    prev_e[to] = ei;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        return {dist, prev_v, prev_e};\n    };\n\n    vector<vector<ll>> allDist(N, vector<ll>(N));\n    vector<vector<int>> allPrevV(N), allPrevE(N);\n    for (int s = 0; s < N; s++) {\n        auto res = dijkstra(s);\n        allDist[s] = move(res.dist);\n        allPrevV[s] = move(res.prev_v);\n        allPrevE[s] = move(res.prev_e);\n    }\n\n    auto reconstruct_path = [&](int s, int t, vector<char>& edge_on, vector<char>& vert_on, vector<int>* addedVerts = nullptr) {\n        int cur = t;\n        while (cur != s) {\n            int ei = allPrevE[s][cur];\n            int pv = allPrevV[s][cur];\n            if (ei < 0 || pv < 0) break;\n            edge_on[ei] = 1;\n            if (!vert_on[cur]) {\n                vert_on[cur] = 1;\n                if (addedVerts) addedVerts->push_back(cur);\n            }\n            if (!vert_on[pv]) {\n                vert_on[pv] = 1;\n                if (addedVerts) addedVerts->push_back(pv);\n            }\n            cur = pv;\n        }\n    };\n\n    auto build_network_from_terminals = [&](const vector<int>& terminals) {\n        vector<int> ts = terminals;\n        ts.push_back(0);\n        sort(ts.begin(), ts.end());\n        ts.erase(unique(ts.begin(), ts.end()), ts.end());\n\n        int T = (int)ts.size();\n        vector<ll> mincost(T, INF64);\n        vector<int> parent(T, -1);\n        vector<char> used(T, 0);\n        mincost[0] = 0;\n\n        for (int it = 0; it < T; it++) {\n            int v = -1;\n            for (int i = 0; i < T; i++) if (!used[i] && (v == -1 || mincost[i] < mincost[v])) v = i;\n            used[v] = 1;\n            for (int to = 0; to < T; to++) if (!used[to]) {\n                ll w = allDist[ts[v]][ts[to]];\n                if (w < mincost[to]) {\n                    mincost[to] = w;\n                    parent[to] = v;\n                }\n            }\n        }\n\n        vector<char> edge_on(M, 0), vert_on(N, 0);\n        vert_on[0] = 1;\n        for (int i = 1; i < T; i++) {\n            reconstruct_path(ts[i], ts[parent[i]], edge_on, vert_on);\n        }\n        return pair(edge_on, vert_on);\n    };\n\n    auto prune_edges = [&](const vector<char>& edge_on, const vector<int>& P) {\n        vector<vector<pair<int,int>>> sg(N);\n        for (int i = 0; i < M; i++) if (edge_on[i]) {\n            int u = edges[i].u, v = edges[i].v;\n            sg[u].push_back({v, i});\n            sg[v].push_back({u, i});\n        }\n\n        vector<char> needV(N, 0), vis(N, 0), keepE(M, 0);\n        needV[0] = 1;\n        for (int i = 0; i < N; i++) if (P[i] > 0) needV[i] = 1;\n\n        function<bool(int,int)> dfs = [&](int v, int pe) -> bool {\n            vis[v] = 1;\n            bool need = needV[v];\n            for (auto [to, ei] : sg[v]) {\n                if (ei == pe) continue;\n                if (!vis[to]) {\n                    if (dfs(to, ei)) {\n                        keepE[ei] = 1;\n                        need = true;\n                    }\n                }\n            }\n            return need;\n        };\n        dfs(0, -1);\n        return keepE;\n    };\n\n    auto calc_cost = [&](const vector<int>& P, const vector<char>& edge_on) {\n        ll S = 0;\n        for (int i = 0; i < N; i++) S += 1LL * P[i] * P[i];\n        for (int i = 0; i < M; i++) if (edge_on[i]) S += edges[i].w;\n        return S;\n    };\n\n    auto power_cost = [&](const vector<int>& P) {\n        ll S = 0;\n        for (int i = 0; i < N; i++) S += 1LL * P[i] * P[i];\n        return S;\n    };\n\n    auto stations_from_P = [&](const vector<int>& P) {\n        vector<int> st;\n        for (int i = 0; i < N; i++) if (P[i] > 0) st.push_back(i);\n        return st;\n    };\n\n    auto assign_best = [&](const vector<int>& stations) {\n        vector<int> P(N, 0);\n        if (stations.empty()) return P;\n        for (int k = 0; k < K; k++) {\n            int bestV = -1;\n            int bestR = 5001;\n            for (int v : stations) {\n                int r = reqR[v][k];\n                if (r < bestR) {\n                    bestR = r;\n                    bestV = v;\n                }\n            }\n            if (bestV != -1 && bestR <= 5000) {\n                P[bestV] = max(P[bestV], bestR);\n            }\n        }\n        return P;\n    };\n\n    auto one_pass_delete = [&](vector<int> P) {\n        vector<int> stations = stations_from_P(P);\n\n        bool changed = true;\n        while (changed) {\n            changed = false;\n\n            sort(stations.begin(), stations.end(), [&](int lhs, int rhs) {\n                return P[lhs] < P[rhs];\n            });\n\n            for (int idx = 0; idx < (int)stations.size(); idx++) {\n                int rem = stations[idx];\n                vector<int> cand;\n                cand.reserve(stations.size() - 1);\n                for (int v : stations) if (v != rem) cand.push_back(v);\n                if (cand.empty()) continue;\n\n                bool ok = true;\n                for (int k = 0; k < K; k++) {\n                    int bestR = 5001;\n                    for (int v : cand) {\n                        int r = reqR[v][k];\n                        if (r < bestR) bestR = r;\n                    }\n                    if (bestR > 5000) {\n                        ok = false;\n                        break;\n                    }\n                }\n                if (!ok) continue;\n\n                vector<int> newP = assign_best(cand);\n                if (power_cost(newP) <= power_cost(P)) {\n                    P.swap(newP);\n                    stations.swap(cand);\n                    changed = true;\n                    break;\n                }\n            }\n        }\n        return P;\n    };\n\n    auto add_one_station_if_good = [&](vector<int> P, const vector<char>& reachable) {\n        vector<int> curStations = stations_from_P(P);\n        vector<char> used(N, 0);\n        for (int v : curStations) used[v] = 1;\n\n        ll curCost = power_cost(P);\n        ll bestCost = curCost;\n        vector<int> bestP = P;\n        int bestAdd = -1;\n\n        for (int v = 0; v < N; v++) {\n            if (!reachable[v] || used[v]) continue;\n\n            vector<int> candStations = curStations;\n            candStations.push_back(v);\n            vector<int> candP = assign_best(candStations);\n            ll c = power_cost(candP);\n            if (c < bestCost) {\n                bestCost = c;\n                bestP.swap(candP);\n                bestAdd = v;\n            }\n        }\n\n        if (bestAdd != -1) {\n            bestP = one_pass_delete(bestP);\n            return bestP;\n        }\n        return P;\n    };\n\n    auto greedy_construct = [&](double beta) {\n        vector<int> P(N, 0);\n        vector<char> covered(K, 0);\n        int coveredCnt = 0;\n\n        vector<char> connectedV(N, 0), edge_on(M, 0), vert_on(N, 0);\n        connectedV[0] = 1;\n        vert_on[0] = 1;\n        vector<int> terminals;\n\n        vector<ll> connCost(N);\n        for (int v = 0; v < N; v++) connCost[v] = allDist[0][v];\n\n        while (coveredCnt < K) {\n            int bestV = -1, bestR = -1;\n            double bestScore = -1.0;\n\n            for (int v = 0; v < N; v++) {\n                int gain = 0;\n                int prevR = -1;\n                ll baseP2 = 1LL * P[v] * P[v];\n                ll connPenalty = connectedV[v] ? 0LL : connCost[v];\n\n                for (auto [r, k] : sortedReq[v]) {\n                    if (!covered[k]) gain++;\n                    if (r != prevR) {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double cost = (double)deltaPower + beta * (double)connPenalty;\n                            double score = (double)gain / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                        prevR = r;\n                    } else {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double cost = (double)deltaPower + beta * (double)connPenalty;\n                            double score = (double)gain / max(1.0, cost);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) break;\n\n            if (P[bestV] == 0) terminals.push_back(bestV);\n            P[bestV] = max(P[bestV], bestR);\n\n            for (auto [r, k] : sortedReq[bestV]) {\n                if (r > bestR) break;\n                if (!covered[k]) {\n                    covered[k] = 1;\n                    coveredCnt++;\n                }\n            }\n\n            if (!connectedV[bestV]) {\n                ll best = INF64;\n                int bestSrc = -1;\n                for (int s = 0; s < N; s++) if (connectedV[s]) {\n                    if (allDist[s][bestV] < best) {\n                        best = allDist[s][bestV];\n                        bestSrc = s;\n                    }\n                }\n                vector<int> addedVerts;\n                reconstruct_path(bestSrc, bestV, edge_on, vert_on, &addedVerts);\n                for (int vtx : addedVerts) connectedV[vtx] = 1;\n                connectedV[0] = 1;\n\n                for (int nv : addedVerts) {\n                    for (int v = 0; v < N; v++) {\n                        if (allDist[nv][v] < connCost[v]) connCost[v] = allDist[nv][v];\n                    }\n                }\n            }\n        }\n\n        return tuple<vector<int>, vector<int>, vector<char>, vector<char>>(P, terminals, edge_on, vert_on);\n    };\n\n    auto recalc_cover_on_reachable = [&](const vector<char>& reachable) {\n        vector<int> P(N, 0);\n        vector<char> covered(K, 0);\n        int coveredCnt = 0;\n        vector<int> stations;\n\n        while (coveredCnt < K) {\n            int bestV = -1, bestR = -1;\n            double bestScore = -1.0;\n\n            for (int v = 0; v < N; v++) if (reachable[v]) {\n                int gain = 0;\n                int prevR = -1;\n                ll baseP2 = 1LL * P[v] * P[v];\n\n                for (auto [r, k] : sortedReq[v]) {\n                    if (!covered[k]) gain++;\n                    if (r != prevR) {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double score = (double)gain / max(1.0, (double)deltaPower);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                        prevR = r;\n                    } else {\n                        if (gain > 0 && r > P[v]) {\n                            ll deltaPower = 1LL * r * r - baseP2;\n                            double score = (double)gain / max(1.0, (double)deltaPower);\n                            if (score > bestScore) {\n                                bestScore = score;\n                                bestV = v;\n                                bestR = r;\n                            }\n                        }\n                    }\n                }\n            }\n\n            if (bestV == -1) break;\n\n            if (P[bestV] == 0) stations.push_back(bestV);\n            P[bestV] = max(P[bestV], bestR);\n\n            for (auto [r, k] : sortedReq[bestV]) {\n                if (r > bestR) break;\n                if (!covered[k]) {\n                    covered[k] = 1;\n                    coveredCnt++;\n                }\n            }\n        }\n\n        return assign_best(stations);\n    };\n\n    auto polish_once = [&](vector<int> P) {\n        P = one_pass_delete(P);\n        vector<int> powered = stations_from_P(P);\n        auto [edge1, vert1] = build_network_from_terminals(powered);\n\n        vector<int> P2 = recalc_cover_on_reachable(vert1);\n        P2 = one_pass_delete(P2);\n\n        // New extra split improvement: add one reachable station if it reduces power.\n        P2 = add_one_station_if_good(P2, vert1);\n        P2 = one_pass_delete(P2);\n\n        vector<int> powered2 = stations_from_P(P2);\n        auto [edge2, vert2] = build_network_from_terminals(powered2);\n        auto edge3 = prune_edges(edge2, P2);\n\n        return pair(P2, edge3);\n    };\n\n    ll bestCost = INF64;\n    vector<int> bestP(N, 0);\n    vector<char> bestB(M, 0);\n\n    const double betas[] = {0.08, 0.15, 0.30, 0.55};\n\n    for (double beta : betas) {\n        auto [P0, terminals0, edge0, vert0] = greedy_construct(beta);\n\n        auto [edge1, vert1] = build_network_from_terminals(terminals0);\n\n        vector<int> P1 = recalc_cover_on_reachable(vert1);\n        P1 = one_pass_delete(P1);\n\n        vector<int> powered = stations_from_P(P1);\n        auto [edge2, vert2] = build_network_from_terminals(powered);\n        auto edge3 = prune_edges(edge2, P1);\n\n        ll cost = calc_cost(P1, edge3);\n        if (cost < bestCost) {\n            bestCost = cost;\n            bestP = P1;\n            bestB = edge3;\n        }\n\n        auto [P4, edge4] = polish_once(P1);\n        ll cost4 = calc_cost(P4, edge4);\n        if (cost4 < bestCost) {\n            bestCost = cost4;\n            bestP = P4;\n            bestB = edge4;\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << bestP[i];\n    }\n    cout << '\\n';\n    for (int i = 0; i < M; i++) {\n        if (i) cout << ' ';\n        cout << (bestB[i] ? 1 : 0);\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 V = 465;\nstatic constexpr int MAXK = 10000;\nstatic constexpr int INF_INT = 1000000000;\n\nstruct Op {\n    int x1, y1, x2, y2;\n};\n\nstruct Result {\n    vector<Op> ops;\n    int score;\n    int E;\n    int K;\n};\n\nstatic inline bool inside(int x, int y) {\n    return 0 <= x && x < N && 0 <= y && y <= x;\n}\n\nstatic inline bool adjacent(int x1, int y1, int x2, int y2) {\n    int dx = x2 - x1;\n    int dy = y2 - y1;\n    return\n        (dx == -1 && dy == -1) ||\n        (dx == -1 && dy == 0) ||\n        (dx == 0 && dy == -1) ||\n        (dx == 0 && dy == 1) ||\n        (dx == 1 && dy == 0) ||\n        (dx == 1 && dy == 1);\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    vector<vector<int>> initA(N);\n    for (int i = 0; i < N; i++) {\n        initA[i].resize(i + 1);\n        for (int j = 0; j <= i; j++) cin >> initA[i][j];\n    }\n\n    auto run_variant = [&](int nb_mode, int repair_mode, int order_mode, int pick_mode) -> Result {\n        vector<vector<int>> a = initA;\n        vector<pair<int,int>> pos(V);\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j <= i; j++) pos[a[i][j]] = {i, j};\n        }\n\n        vector<Op> ops;\n        ops.reserve(MAXK);\n\n        auto do_swap = [&](int x1, int y1, int x2, int y2) -> bool {\n            if ((int)ops.size() >= MAXK) return false;\n            if (!inside(x1, y1) || !inside(x2, y2)) return false;\n            if (!adjacent(x1, y1, x2, y2)) 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        auto neighbors = [&](int x, int y) {\n            vector<pair<int,int>> res;\n            pair<int,int> cand[6];\n            if (nb_mode == 0) {\n                cand[0] = {x - 1, y - 1};\n                cand[1] = {x - 1, y};\n                cand[2] = {x, y - 1};\n                cand[3] = {x, y + 1};\n                cand[4] = {x + 1, y};\n                cand[5] = {x + 1, y + 1};\n            } else if (nb_mode == 1) {\n                cand[0] = {x - 1, y};\n                cand[1] = {x - 1, y - 1};\n                cand[2] = {x, y + 1};\n                cand[3] = {x, y - 1};\n                cand[4] = {x + 1, y + 1};\n                cand[5] = {x + 1, y};\n            } else if (nb_mode == 2) {\n                cand[0] = {x, y - 1};\n                cand[1] = {x, y + 1};\n                cand[2] = {x - 1, y - 1};\n                cand[3] = {x - 1, y};\n                cand[4] = {x + 1, y};\n                cand[5] = {x + 1, y + 1};\n            } else {\n                cand[0] = {x, y + 1};\n                cand[1] = {x, y - 1};\n                cand[2] = {x - 1, y};\n                cand[3] = {x - 1, y - 1};\n                cand[4] = {x + 1, y + 1};\n                cand[5] = {x + 1, y};\n            }\n            for (auto [nx, ny] : cand) if (inside(nx, ny)) res.push_back({nx, ny});\n            return res;\n        };\n\n        auto get_path = [&](pair<int,int> s, pair<int,int> t) {\n            static int dist[N][N];\n            static pair<int,int> pre[N][N];\n            for (int i = 0; i < N; i++) {\n                for (int j = 0; j <= i; j++) {\n                    dist[i][j] = -1;\n                    pre[i][j] = {-1, -1};\n                }\n            }\n\n            queue<pair<int,int>> q;\n            dist[s.first][s.second] = 0;\n            q.push(s);\n\n            while (!q.empty()) {\n                auto [x, y] = q.front();\n                q.pop();\n                if (x == t.first && y == t.second) break;\n                for (auto [nx, ny] : neighbors(x, y)) {\n                    if (dist[nx][ny] != -1) continue;\n                    dist[nx][ny] = dist[x][y] + 1;\n                    pre[nx][ny] = {x, y};\n                    q.push({nx, ny});\n                }\n            }\n\n            vector<pair<int,int>> path;\n            if (dist[t.first][t.second] == -1) return path;\n            pair<int,int> cur = t;\n            while (!(cur == s)) {\n                path.push_back(cur);\n                cur = pre[cur.first][cur.second];\n            }\n            path.push_back(s);\n            reverse(path.begin(), path.end());\n            return path;\n        };\n\n        auto local_bad = [&](int x, int y) -> int {\n            int me = a[x][y];\n            int bad = 0;\n            if (x > 0) {\n                if (y > 0 && a[x - 1][y - 1] > me) bad++;\n                if (y < x && a[x - 1][y] > me) bad++;\n            }\n            if (x + 1 < N) {\n                if (me > a[x + 1][y]) bad++;\n                if (me > a[x + 1][y + 1]) bad++;\n            }\n            return bad;\n        };\n\n        auto count_E = [&]() -> int {\n            int E = 0;\n            for (int x = 0; x < N - 1; x++) {\n                for (int y = 0; y <= x; y++) {\n                    if (a[x][y] > a[x + 1][y]) E++;\n                    if (a[x][y] > a[x + 1][y + 1]) E++;\n                }\n            }\n            return E;\n        };\n\n        auto pass_max_gain = [&]() {\n            while ((int)ops.size() < MAXK) {\n                int bestGain = 0;\n                int bx1 = -1, by1 = -1, bx2 = -1, by2 = -1;\n\n                for (int x = 0; x < N; x++) {\n                    for (int y = 0; y <= x; y++) {\n                        for (auto [nx, ny] : neighbors(x, y)) {\n                            if (x > nx || (x == nx && y >= ny)) continue;\n                            int before = local_bad(x, y) + local_bad(nx, ny);\n                            swap(a[x][y], a[nx][ny]);\n                            int after = local_bad(x, y) + local_bad(nx, ny);\n                            swap(a[x][y], a[nx][ny]);\n                            int gain = before - after;\n                            if (gain > bestGain) {\n                                bestGain = gain;\n                                bx1 = x; by1 = y; bx2 = nx; by2 = ny;\n                            }\n                        }\n                    }\n                }\n\n                if (bestGain <= 0) break;\n                if (!do_swap(bx1, by1, bx2, by2)) break;\n            }\n        };\n\n        auto pass_heap_fix = [&](bool rev) {\n            bool updated = true;\n            while (updated && (int)ops.size() < MAXK) {\n                updated = false;\n                for (int x = N - 2; x >= 0 && (int)ops.size() < MAXK; x--) {\n                    if (!rev) {\n                        for (int y = 0; y <= x && (int)ops.size() < MAXK; y++) {\n                            int p = a[x][y];\n                            int c1 = a[x + 1][y];\n                            int c2 = a[x + 1][y + 1];\n                            if (p > c1 || p > c2) {\n                                bool ok;\n                                if (c1 < c2) ok = do_swap(x, y, x + 1, y);\n                                else ok = do_swap(x, y, x + 1, y + 1);\n                                if (!ok) break;\n                                updated = true;\n                            }\n                        }\n                    } else {\n                        for (int y = x; y >= 0 && (int)ops.size() < MAXK; y--) {\n                            int p = a[x][y];\n                            int c1 = a[x + 1][y];\n                            int c2 = a[x + 1][y + 1];\n                            if (p > c1 || p > c2) {\n                                bool ok;\n                                if (c1 < c2) ok = do_swap(x, y, x + 1, y);\n                                else ok = do_swap(x, y, x + 1, y + 1);\n                                if (!ok) break;\n                                updated = true;\n                            }\n                        }\n                    }\n                }\n            }\n        };\n\n        auto row_order = [&](int x) {\n            vector<int> ys;\n            ys.reserve(x + 1);\n            if (order_mode == 0) {\n                for (int y = 0; y <= x; y++) ys.push_back(y);\n            } else if (order_mode == 1) {\n                for (int y = x; y >= 0; y--) ys.push_back(y);\n            } else if (order_mode == 2) {\n                int mid = x / 2;\n                ys.push_back(mid);\n                for (int d = 1; (int)ys.size() < x + 1; d++) {\n                    if (mid - d >= 0) ys.push_back(mid - d);\n                    if (mid + d <= x) ys.push_back(mid + d);\n                }\n            } else {\n                int l = 0, r = x;\n                while (l <= r) {\n                    ys.push_back(l);\n                    if (l != r) ys.push_back(r);\n                    l++;\n                    r--;\n                }\n            }\n            return ys;\n        };\n\n        vector<char> fixedv(V, 0);\n\n        for (int x = 0; x < N && (int)ops.size() < MAXK; x++) {\n            auto ys = row_order(x);\n            vector<char> done_row(x + 1, 0);\n\n            for (int y : ys) {\n                if ((int)ops.size() >= MAXK) break;\n\n                vector<pair<int, pair<int,int>>> cands;\n                int need = (pick_mode == 0 ? 1 : (pick_mode == 1 ? 3 : 2));\n\n                for (int i = x; i < N; i++) {\n                    for (int j = 0; j <= i; j++) {\n                        if (i == x && done_row[j]) continue;\n                        int v = a[i][j];\n                        if (fixedv[v]) continue;\n                        cands.push_back({v, {i, j}});\n                    }\n                }\n\n                if (cands.empty()) continue;\n                sort(cands.begin(), cands.end(), [](auto &l, auto &r) {\n                    return l.first < r.first;\n                });\n                if ((int)cands.size() > need) cands.resize(need);\n\n                int chosen_idx = 0;\n                vector<pair<int,int>> chosen_path;\n\n                if (pick_mode == 0) {\n                    chosen_path = get_path(cands[0].second, {x, y});\n                    if (chosen_path.empty()) continue;\n                } else {\n                    long long bestScore = (1LL << 60);\n                    for (int idx = 0; idx < (int)cands.size(); idx++) {\n                        auto path = get_path(cands[idx].second, {x, y});\n                        if (path.empty()) continue;\n                        int dist = (int)path.size() - 1;\n                        long long score;\n                        if (pick_mode == 1) score = 8LL * idx + dist;\n                        else score = 12LL * idx + dist;\n                        if (score < bestScore) {\n                            bestScore = score;\n                            chosen_idx = idx;\n                            chosen_path = move(path);\n                        }\n                    }\n                    if (chosen_path.empty()) continue;\n                }\n\n                int chosenVal = cands[chosen_idx].first;\n\n                for (int k = (int)chosen_path.size() - 1; k >= 1; k--) {\n                    if ((int)ops.size() >= MAXK) break;\n                    auto [x1, y1] = chosen_path[k];\n                    auto [x2, y2] = chosen_path[k - 1];\n                    if (!do_swap(x1, y1, x2, y2)) break;\n                }\n\n                fixedv[chosenVal] = 1;\n                done_row[y] = 1;\n            }\n        }\n\n        if (repair_mode == 0) {\n            pass_max_gain();\n            pass_heap_fix(false);\n        } else if (repair_mode == 1) {\n            pass_max_gain();\n            pass_heap_fix(true);\n        } else if (repair_mode == 2) {\n            pass_heap_fix(false);\n            pass_max_gain();\n        } else if (repair_mode == 3) {\n            pass_heap_fix(true);\n            pass_max_gain();\n        } else if (repair_mode == 4) {\n            pass_heap_fix(false);\n        } else {\n            pass_heap_fix(true);\n        }\n\n        int E = count_E();\n        int K = (int)ops.size();\n        int score = (E == 0 ? 100000 - 5 * K : 50000 - 50 * E);\n\n        Result res;\n        res.ops = move(ops);\n        res.score = score;\n        res.E = E;\n        res.K = K;\n        return res;\n    };\n\n    vector<tuple<int,int,int,int>> variants = {\n        // strong baseline-like variants\n        {0, 0, 0, 0}, {0, 2, 0, 0}, {1, 0, 0, 0}, {1, 3, 0, 0},\n        {2, 4, 0, 0}, {3, 1, 0, 0},\n\n        // row-order diversified baseline variants\n        {0, 0, 1, 0}, {1, 2, 1, 0}, {2, 5, 1, 0}, {3, 3, 1, 0},\n        {0, 4, 2, 0}, {1, 5, 2, 0}, {2, 0, 2, 0}, {3, 2, 2, 0},\n        {0, 0, 3, 0}, {1, 2, 3, 0}, {2, 4, 3, 0}, {3, 5, 3, 0},\n\n        // conservative candidate-choice variants\n        {0, 0, 0, 1}, {1, 3, 0, 1},\n        {0, 0, 2, 1}, {2, 0, 2, 1},\n        {1, 2, 3, 2}, {3, 2, 3, 2}\n    };\n\n    Result best;\n    best.score = -INF_INT;\n    best.E = INF_INT;\n    best.K = INF_INT;\n\n    for (auto [nb_mode, repair_mode, order_mode, pick_mode] : variants) {\n        Result cur = run_variant(nb_mode, repair_mode, order_mode, pick_mode);\n        if (cur.score > best.score || (cur.score == best.score && cur.K < best.K)) {\n            best = move(cur);\n        }\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 Pos {\n    int x, y;\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int D, N;\n    cin >> D >> N;\n\n    vector<vector<int>> obstacle(D, vector<int>(D, 0));\n    for (int k = 0; k < N; ++k) {\n        int r, c;\n        cin >> r >> c;\n        obstacle[r][c] = 1;\n    }\n\n    const int ex = 0;\n    const int ey = (D - 1) / 2;\n    const int M = D * D - 1 - N;\n    const int INF = 1e9;\n    const int dx[4] = {1, -1, 0, 0};\n    const int dy[4] = {0, 0, 1, -1};\n\n    auto inside = [&](int x, int y) -> bool {\n        return 0 <= x && x < D && 0 <= y && y < D;\n    };\n\n    // board: -2 obstacle, -1 empty, >=0 label\n    vector<vector<int>> board(D, vector<int>(D, -1));\n    for (int i = 0; i < D; ++i) {\n        for (int j = 0; j < D; ++j) {\n            if (obstacle[i][j]) board[i][j] = -2;\n        }\n    }\n\n    // Static shortest distances from entrance\n    vector<vector<int>> dist0(D, vector<int>(D, INF));\n    {\n        queue<Pos> q;\n        dist0[ex][ey] = 0;\n        q.push({ex, ey});\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + dx[dir], ny = y + dy[dir];\n                if (!inside(nx, ny) || obstacle[nx][ny]) continue;\n                if (dist0[nx][ny] > dist0[x][y] + 1) {\n                    dist0[nx][ny] = dist0[x][y] + 1;\n                    q.push({nx, ny});\n                }\n            }\n        }\n    }\n\n    auto compute_conn_empty = [&](const vector<vector<int>>& b) {\n        vector<vector<int>> vis(D, vector<int>(D, 0));\n        queue<Pos> q;\n        vis[ex][ey] = 1;\n        q.push({ex, ey});\n        while (!q.empty()) {\n            auto [x, y] = q.front();\n            q.pop();\n            for (int dir = 0; dir < 4; ++dir) {\n                int nx = x + dx[dir], ny = y + dy[dir];\n                if (!inside(nx, ny) || vis[nx][ny]) continue;\n                if (b[nx][ny] == -1) {\n                    vis[nx][ny] = 1;\n                    q.push({nx, ny});\n                }\n            }\n        }\n        return vis;\n    };\n\n    auto all_empty_reachable = [&](const vector<vector<int>>& b) -> bool {\n        auto vis = compute_conn_empty(b);\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (i == ex && j == ey) continue;\n                if (b[i][j] == -1 && !vis[i][j]) return false;\n            }\n        }\n        return true;\n    };\n\n    auto exposure = [&](int x, int y, const vector<vector<int>>& b, const vector<vector<int>>& conn) -> int {\n        int cnt = 0;\n        for (int dir = 0; dir < 4; ++dir) {\n            int nx = x + dx[dir], ny = y + dy[dir];\n            if (!inside(nx, ny)) continue;\n            if (nx == ex && ny == ey) cnt++;\n            else if (b[nx][ny] == -1 && conn[nx][ny]) cnt++;\n        }\n        return cnt;\n    };\n\n    auto removable_cells = [&](const vector<vector<int>>& b) {\n        auto conn = compute_conn_empty(b);\n        vector<Pos> res;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (b[i][j] < 0) continue;\n                bool ok = false;\n                for (int dir = 0; dir < 4; ++dir) {\n                    int nx = i + dx[dir], ny = j + dy[dir];\n                    if (!inside(nx, ny)) continue;\n                    if (nx == ex && ny == ey) {\n                        ok = true;\n                        break;\n                    }\n                    if (b[nx][ny] == -1 && conn[nx][ny]) {\n                        ok = true;\n                        break;\n                    }\n                }\n                if (ok) res.push_back({i, j});\n            }\n        }\n        return res;\n    };\n\n    auto peel_rank = [&](vector<vector<int>> b, int tx, int ty, bool early_mode) -> int {\n        int rank = 0;\n        while (true) {\n            auto cand = removable_cells(b);\n            if (cand.empty()) return rank;\n            auto conn = compute_conn_empty(b);\n\n            auto better = [&](const Pos& a, const Pos& c) {\n                int da = dist0[a.x][a.y];\n                int dc = dist0[c.x][c.y];\n                int ea = exposure(a.x, a.y, b, conn);\n                int ec = exposure(c.x, c.y, b, conn);\n\n                if (early_mode) {\n                    if (da != dc) return da < dc;\n                    if (ea != ec) return ea > ec;\n                } else {\n                    if (da != dc) return da > dc;\n                    if (ea != ec) return ea < ec;\n                }\n                if (a.x != c.x) return a.x < c.x;\n                return a.y < c.y;\n            };\n\n            Pos best = cand[0];\n            for (auto p : cand) {\n                if (better(p, best)) best = p;\n            }\n\n            if (best.x == tx && best.y == ty) return rank;\n            b[best.x][best.y] = -1;\n            rank++;\n        }\n    };\n\n    int placed_count = 0;\n\n    // Placement phase\n    for (int step = 0; step < M; ++step) {\n        int t;\n        cin >> t;\n\n        auto conn = compute_conn_empty(board);\n\n        vector<Pos> safe;\n        for (int i = 0; i < D; ++i) {\n            for (int j = 0; j < D; ++j) {\n                if (i == ex && j == ey) continue;\n                if (board[i][j] != -1) continue;\n                if (!conn[i][j]) continue;\n\n                board[i][j] = M + 1000;\n                bool ok = all_empty_reachable(board);\n                board[i][j] = -1;\n\n                if (ok) safe.push_back({i, j});\n            }\n        }\n\n        Pos best = safe[0];\n        long long best1 = (1LL << 62);\n        long long best2 = (1LL << 62);\n        long long best3 = (1LL << 62);\n\n        int K = placed_count + 1;\n        long long denom = max(1, M - 1);\n        long long targetScaled = 1LL * t * K * denom / M; // target * denom\n\n        for (auto p : safe) {\n            board[p.x][p.y] = t;\n\n            int peelA = peel_rank(board, p.x, p.y, true);\n            int peelB = peel_rank(board, p.x, p.y, false);\n            int rankA = peelA;\n            int rankB = (K - 1) - peelB;\n\n            auto conn2 = compute_conn_empty(board);\n            int d = dist0[p.x][p.y];\n            int e = exposure(p.x, p.y, board, conn2);\n\n            board[p.x][p.y] = -1;\n\n            long long blendNum = 1LL * (M - 1 - t) * rankA + 1LL * t * rankB;\n            long long key1 = llabs(blendNum - targetScaled);\n            long long key2 = llabs((long long)rankA - rankB);\n\n            long long key3 = 0;\n            key3 += 1000LL * d * (2LL * t - (M - 1));\n            key3 += -100LL * e * (2LL * t - (M - 1));\n            key3 += 10LL * abs(p.y - ey);\n            key3 += p.x;\n            key3 += p.y;\n\n            if (key1 < best1 ||\n                (key1 == best1 && key2 < best2) ||\n                (key1 == best1 && key2 == best2 && key3 < best3)) {\n                best1 = key1;\n                best2 = key2;\n                best3 = key3;\n                best = p;\n            }\n        }\n\n        board[best.x][best.y] = t;\n        placed_count++;\n\n        cout << best.x << ' ' << best.y << '\\n';\n        cout.flush();\n    }\n\n    // Retrieval phase: greedy smallest visible label\n    for (int step = 0; step < M; ++step) {\n        auto cand = removable_cells(board);\n\n        Pos best = cand[0];\n        int bestLabel = board[best.x][best.y];\n        for (auto p : cand) {\n            if (board[p.x][p.y] < bestLabel) {\n                bestLabel = board[p.x][p.y];\n                best = p;\n            }\n        }\n\n        cout << best.x << ' ' << best.y << '\\n';\n        board[best.x][best.y] = -1;\n    }\n    cout.flush();\n\n    return 0;\n}","ahc024":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 50;\nstatic constexpr int MAXC = 100;\n\nstruct Solver {\n    int n, m;\n    vector<vector<int>> orig, a, bestA;\n    bool origAdj[MAXC + 1][MAXC + 1]{};\n    bool canTouchZero[MAXC + 1]{};\n    int edgeCnt[MAXC + 1][MAXC + 1]{};\n    int colorCells[MAXC + 1]{};\n    int bestZero = 0;\n    mt19937 rng{(uint32_t)chrono::steady_clock::now().time_since_epoch().count()};\n\n    bool inside(int i, int j) const {\n        return 0 <= i && i < n && 0 <= j && j < n;\n    }\n\n    void addEdge(int x, int y, int d) {\n        if (x == y) return;\n        edgeCnt[x][y] += d;\n        edgeCnt[y][x] += d;\n    }\n\n    void buildOriginalInfo() {\n        memset(origAdj, 0, sizeof(origAdj));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = orig[i][j];\n                if (i == 0 || i == n - 1 || j == 0 || j == n - 1) {\n                    origAdj[0][c] = origAdj[c][0] = true;\n                }\n                if (i + 1 < n) {\n                    int d = orig[i + 1][j];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n                if (j + 1 < n) {\n                    int d = orig[i][j + 1];\n                    if (c != d) origAdj[c][d] = origAdj[d][c] = true;\n                }\n            }\n        }\n        for (int c = 1; c <= m; c++) canTouchZero[c] = origAdj[0][c];\n    }\n\n    void rebuildState() {\n        memset(edgeCnt, 0, sizeof(edgeCnt));\n        memset(colorCells, 0, sizeof(colorCells));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) colorCells[a[i][j]]++;\n        }\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int c = a[i][j];\n                if (i == 0) addEdge(0, c, 1);\n                if (i == n - 1) addEdge(0, c, 1);\n                if (j == 0) addEdge(0, c, 1);\n                if (j == n - 1) addEdge(0, c, 1);\n                if (i + 1 < n) addEdge(c, a[i + 1][j], 1);\n                if (j + 1 < n) addEdge(c, a[i][j + 1], 1);\n            }\n        }\n    }\n\n    void updateBest() {\n        if (colorCells[0] > bestZero) {\n            bestZero = colorCells[0];\n            bestA = a;\n        }\n    }\n\n    int sameDeg(int i, int j) const {\n        int c = a[i][j];\n        int s = 0;\n        if (i > 0 && a[i - 1][j] == c) s++;\n        if (i + 1 < n && a[i + 1][j] == c) s++;\n        if (j > 0 && a[i][j - 1] == c) s++;\n        if (j + 1 < n && a[i][j + 1] == c) s++;\n        return s;\n    }\n\n    int zeroNbrs(int i, int j) const {\n        int s = 0;\n        if (i == 0 || a[i - 1][j] == 0) s++;\n        if (i == n - 1 || a[i + 1][j] == 0) s++;\n        if (j == 0 || a[i][j - 1] == 0) s++;\n        if (j == n - 1 || a[i][j + 1] == 0) s++;\n        return s;\n    }\n\n    bool frontierCell(int i, int j) const {\n        int c = a[i][j];\n        if (c == 0) return false;\n        if (i == 0 || i == n - 1 || j == 0 || j == n - 1) return true;\n        if (a[i - 1][j] == 0 || a[i + 1][j] == 0 || a[i][j - 1] == 0 || a[i][j + 1] == 0) return true;\n        if (a[i - 1][j] != c || a[i + 1][j] != c || a[i][j - 1] != c || a[i][j + 1] != c) return true;\n        return false;\n    }\n\n    bool checkAdjRows(const vector<int>& rows) {\n        vector<int> rs = rows;\n        sort(rs.begin(), rs.end());\n        rs.erase(unique(rs.begin(), rs.end()), rs.end());\n        for (int x : rs) {\n            for (int y = 0; y <= m; y++) {\n                bool now = edgeCnt[x][y] > 0;\n                if (now != origAdj[x][y]) return false;\n            }\n        }\n        return true;\n    }\n\n    bool zeroConnected() {\n        if (colorCells[0] == 0) return true;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        for (int i = 0; i < n; i++) {\n            if (a[i][0] == 0 && !vis[i][0]) vis[i][0] = true, q.push({i, 0});\n            if (a[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 (a[0][j] == 0 && !vis[0][j]) vis[0][j] = true, q.push({0, j});\n            if (a[n - 1][j] == 0 && !vis[n - 1][j]) vis[n - 1][j] = true, q.push({n - 1, j});\n        }\n        if (q.empty()) return false;\n\n        int cnt = 0;\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); 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] || a[ni][nj] != 0) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n        return cnt == colorCells[0];\n    }\n\n    bool oldColorConnectedAfterRemovingCenter(int color, int ci, int cj) {\n        pair<int,int> nei[4];\n        int k = 0;\n        if (ci > 0 && a[ci - 1][cj] == color) nei[k++] = {ci - 1, cj};\n        if (ci + 1 < n && a[ci + 1][cj] == color) nei[k++] = {ci + 1, cj};\n        if (cj > 0 && a[ci][cj - 1] == color) nei[k++] = {ci, cj - 1};\n        if (cj + 1 < n && a[ci][cj + 1] == color) nei[k++] = {ci, cj + 1};\n\n        if (k <= 1) return true;\n\n        static bool vis[N][N];\n        for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) vis[i][j] = false;\n\n        queue<pair<int,int>> q;\n        q.push(nei[0]);\n        vis[nei[0].first][nei[0].second] = true;\n\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        while (!q.empty()) {\n            auto [i, j] = q.front(); q.pop();\n            for (int d = 0; d < 4; d++) {\n                int ni = i + di[d], nj = j + dj[d];\n                if (!inside(ni, nj)) continue;\n                if (ni == ci && nj == cj) continue;\n                if (vis[ni][nj] || a[ni][nj] != color) continue;\n                vis[ni][nj] = true;\n                q.push({ni, nj});\n            }\n        }\n\n        for (int t = 1; t < k; t++) {\n            if (!vis[nei[t].first][nei[t].second]) return false;\n        }\n        return true;\n    }\n\n    vector<int> touchedColors(int i, int j, int oldc, int newc) {\n        vector<int> v = {0, oldc, newc};\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            v.push_back(inside(ni, nj) ? a[ni][nj] : 0);\n        }\n        sort(v.begin(), v.end());\n        v.erase(unique(v.begin(), v.end()), v.end());\n        return v;\n    }\n\n    void applyCellContribution(int i, int j, int c, int sign) {\n        if (i == 0) addEdge(0, c, sign);\n        if (i == n - 1) addEdge(0, c, sign);\n        if (j == 0) addEdge(0, c, sign);\n        if (j == n - 1) addEdge(0, c, sign);\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\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            addEdge(c, a[ni][nj], sign);\n        }\n    }\n\n    bool cheapEraseFilter(int i, int j) const {\n        int c = a[i][j];\n        if (c == 0) return false;\n        if (!canTouchZero[c]) return false;\n        if (colorCells[c] <= 1) return false;\n        if (!frontierCell(i, j)) return false;\n\n        int sd = sameDeg(i, j);\n        int zn = zeroNbrs(i, j);\n        if (sd >= 4) return false;\n        if (sd >= 3 && zn == 0) return false;\n\n        static const int di[4] = {-1, 1, 0, 0};\n        static const int dj[4] = {0, 0, -1, 1};\n        for (int d = 0; d < 4; d++) {\n            int ni = i + di[d], nj = j + dj[d];\n            int nc = inside(ni, nj) ? a[ni][nj] : 0;\n            if (nc != 0 && !canTouchZero[nc]) return false;\n        }\n        return true;\n    }\n\n    bool tryChange(int i, int j, int newc) {\n        int oldc = a[i][j];\n        if (oldc == newc) return false;\n        if (oldc != 0 && colorCells[oldc] <= 1) return false;\n\n        if (newc == 0) {\n            if (!cheapEraseFilter(i, j)) return false;\n        } else {\n            bool adj = false;\n            if (i > 0 && a[i - 1][j] == newc) adj = true;\n            if (i + 1 < n && a[i + 1][j] == newc) adj = true;\n            if (j > 0 && a[i][j - 1] == newc) adj = true;\n            if (j + 1 < n && a[i][j + 1] == newc) adj = true;\n            if (!adj) return false;\n\n            if ((i == 0 || i == n - 1 || j == 0 || j == n - 1) && !canTouchZero[newc]) return false;\n            if (i > 0 && a[i - 1][j] == 0 && !canTouchZero[newc]) return false;\n            if (i + 1 < n && a[i + 1][j] == 0 && !canTouchZero[newc]) return false;\n            if (j > 0 && a[i][j - 1] == 0 && !canTouchZero[newc]) return false;\n            if (j + 1 < n && a[i][j + 1] == 0 && !canTouchZero[newc]) return false;\n        }\n\n        if (oldc != 0 && !oldColorConnectedAfterRemovingCenter(oldc, i, j)) return false;\n\n        applyCellContribution(i, j, oldc, -1);\n        a[i][j] = newc;\n        colorCells[oldc]--;\n        colorCells[newc]++;\n        applyCellContribution(i, j, newc, +1);\n\n        bool ok = true;\n        if (newc == 0 || oldc == 0) {\n            if (!zeroConnected()) ok = false;\n        }\n        if (ok) {\n            auto rows = touchedColors(i, j, oldc, newc);\n            if (!checkAdjRows(rows)) ok = false;\n        }\n\n        if (!ok) {\n            a[i][j] = oldc;\n            rebuildState();\n            return false;\n        }\n\n        updateBest();\n        return true;\n    }\n\n    void enqueueNeighborhood(int ci, int cj, deque<pair<int,int>>& dq, vector<vector<unsigned char>>& inq) {\n        for (int di = -2; di <= 2; di++) {\n            for (int dj = -2; dj <= 2; dj++) {\n                if (abs(di) + abs(dj) > 2) continue;\n                int ni = ci + di, nj = cj + dj;\n                if (!inside(ni, nj)) continue;\n                if (!inq[ni][nj]) {\n                    inq[ni][nj] = 1;\n                    dq.push_back({ni, nj});\n                }\n            }\n        }\n    }\n\n    bool tryLocalRecolor(int i, int j) {\n        int oldc = a[i][j];\n        if (oldc == 0 || !frontierCell(i, j)) return false;\n        if (sameDeg(i, j) >= 4) return false;\n\n        vector<pair<array<int,4>, int>> cand;\n        set<int> neigh;\n        if (i > 0 && a[i - 1][j] != 0 && a[i - 1][j] != oldc) neigh.insert(a[i - 1][j]);\n        if (i + 1 < n && a[i + 1][j] != 0 && a[i + 1][j] != oldc) neigh.insert(a[i + 1][j]);\n        if (j > 0 && a[i][j - 1] != 0 && a[i][j - 1] != oldc) neigh.insert(a[i][j - 1]);\n        if (j + 1 < n && a[i][j + 1] != 0 && a[i][j + 1] != oldc) neigh.insert(a[i][j + 1]);\n\n        int zn = zeroNbrs(i, j);\n        int sd = sameDeg(i, j);\n        for (int nc : neigh) {\n            int gain = 0;\n            if (i > 0 && a[i - 1][j] == nc) gain++;\n            if (i + 1 < n && a[i + 1][j] == nc) gain++;\n            if (j > 0 && a[i][j - 1] == nc) gain++;\n            if (j + 1 < n && a[i][j + 1] == nc) gain++;\n            cand.push_back({{-gain, -zn, sd, canTouchZero[nc] ? 0 : 1}, nc});\n        }\n        sort(cand.begin(), cand.end());\n\n        for (auto &e : cand) {\n            int nc = e.second;\n            if (tryChange(i, j, nc)) return true;\n        }\n        return false;\n    }\n\n    bool localCascade(const chrono::steady_clock::time_point& start, double TL,\n                      const vector<pair<int,int>>& seeds, int maxSteps) {\n        deque<pair<int,int>> dq;\n        vector<vector<unsigned char>> inq(n, vector<unsigned char>(n, 0));\n        for (auto [i, j] : seeds) enqueueNeighborhood(i, j, dq, inq);\n\n        bool improved = false;\n        int steps = 0;\n        while (!dq.empty() && steps < maxSteps) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > TL) break;\n\n            auto [i, j] = dq.front();\n            dq.pop_front();\n            inq[i][j] = 0;\n            steps++;\n\n            if (a[i][j] == 0) continue;\n\n            if (tryChange(i, j, 0)) {\n                improved = true;\n                enqueueNeighborhood(i, j, dq, inq);\n                continue;\n            }\n            if (tryLocalRecolor(i, j)) {\n                improved = true;\n                enqueueNeighborhood(i, j, dq, inq);\n                continue;\n            }\n        }\n        return improved;\n    }\n\n    bool erasePass(const chrono::steady_clock::time_point& start, double TL, int successLimit) {\n        vector<pair<array<int,4>, pair<int,int>>> cand;\n        cand.reserve(n * n);\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                if (!cheapEraseFilter(i, j)) continue;\n                int sd = sameDeg(i, j);\n                int zn = zeroNbrs(i, j);\n                int border = (i == 0 || i == n - 1 || j == 0 || j == n - 1) ? 0 : 1;\n                int rnd = int(rng() & 15);\n                cand.push_back({{sd, -zn, border, rnd}, {i, j}});\n            }\n        }\n\n        sort(cand.begin(), cand.end(),\n             [](const auto& x, const auto& y) { return x.first < y.first; });\n\n        bool improved = false;\n        int successCnt = 0;\n        for (auto &e : cand) {\n            auto [i, j] = e.second;\n            if (a[i][j] != 0 && tryChange(i, j, 0)) {\n                improved = true;\n                successCnt++;\n                vector<pair<int,int>> seeds = {{i, j}};\n                localCascade(start, TL, seeds, 28);\n            }\n\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > TL) break;\n            if (successCnt >= successLimit) break;\n        }\n        return improved;\n    }\n\n    bool recolorBurst(const chrono::steady_clock::time_point& start, double TL,\n                      int acceptLimit, int attemptLimit) {\n        vector<tuple<array<int,5>, int, int, int>> cand;\n        cand.reserve(3000);\n\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) {\n                int oldc = a[i][j];\n                if (oldc == 0) continue;\n                if (!frontierCell(i, j)) continue;\n\n                int sd = sameDeg(i, j);\n                if (sd >= 4) continue;\n\n                set<int> neigh;\n                if (i > 0 && a[i - 1][j] != 0 && a[i - 1][j] != oldc) neigh.insert(a[i - 1][j]);\n                if (i + 1 < n && a[i + 1][j] != 0 && a[i + 1][j] != oldc) neigh.insert(a[i + 1][j]);\n                if (j > 0 && a[i][j - 1] != 0 && a[i][j - 1] != oldc) neigh.insert(a[i][j - 1]);\n                if (j + 1 < n && a[i][j + 1] != 0 && a[i][j + 1] != oldc) neigh.insert(a[i][j + 1]);\n\n                int zn = zeroNbrs(i, j);\n                for (int nc : neigh) {\n                    int gain = 0;\n                    if (i > 0 && a[i - 1][j] == nc) gain++;\n                    if (i + 1 < n && a[i + 1][j] == nc) gain++;\n                    if (j > 0 && a[i][j - 1] == nc) gain++;\n                    if (j + 1 < n && a[i][j + 1] == nc) gain++;\n                    int zpref = canTouchZero[nc] ? 0 : 1;\n                    int rnd = int(rng() & 15);\n                    cand.push_back({{sd, -zn, -gain, zpref, rnd}, i, j, nc});\n                }\n            }\n        }\n\n        sort(cand.begin(), cand.end(),\n             [](const auto& x, const auto& y) { return get<0>(x) < get<0>(y); });\n\n        bool improved = false;\n        int attempts = 0, accepted = 0;\n        for (auto &e : cand) {\n            int i = get<1>(e), j = get<2>(e), nc = get<3>(e);\n            if (a[i][j] == 0 || a[i][j] == nc) continue;\n\n            attempts++;\n            if (tryChange(i, j, nc)) {\n                improved = true;\n                accepted++;\n                vector<pair<int,int>> seeds = {{i, j}};\n                localCascade(start, TL, seeds, 32);\n            }\n\n            auto now = chrono::steady_clock::now();\n            if (accepted >= acceptLimit || attempts >= attemptLimit ||\n                chrono::duration<double>(now - start).count() > TL) break;\n        }\n        return improved;\n    }\n\n    void runPhase(const chrono::steady_clock::time_point& start, double endTime,\n                  int rbAccept, int rbAttempt, int epSuccess) {\n        while (true) {\n            auto now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > endTime) break;\n\n            bool any = false;\n            any |= recolorBurst(start, endTime, rbAccept, rbAttempt);\n            rebuildState();\n\n            now = chrono::steady_clock::now();\n            if (chrono::duration<double>(now - start).count() > endTime) break;\n\n            any |= erasePass(start, endTime, epSuccess);\n            rebuildState();\n\n            if (!any) break;\n        }\n    }\n\n    void solve() {\n        cin >> n >> m;\n        orig.assign(n, vector<int>(n));\n        for (int i = 0; i < n; i++) {\n            for (int j = 0; j < n; j++) cin >> orig[i][j];\n        }\n\n        buildOriginalInfo();\n        bestA = orig;\n        bestZero = 0;\n\n        auto start = chrono::steady_clock::now();\n        const double TL = 1.90;\n\n        // Main trajectory from original\n        a = orig;\n        rebuildState();\n        updateBest();\n\n        erasePass(start, TL * 0.52, 260);\n        rebuildState();\n        updateBest();\n\n        runPhase(start, TL * 0.80, 55, 420, 320);\n\n        // Continuation from best-so-far\n        auto now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() < TL * 0.93) {\n            a = bestA;\n            rebuildState();\n            runPhase(start, TL * 0.97, 45, 320, 240);\n        }\n\n        // Short alternate trajectory from original for diversification\n        now = chrono::steady_clock::now();\n        if (chrono::duration<double>(now - start).count() < TL * 0.985) {\n            a = orig;\n            rebuildState();\n            runPhase(start, TL, 24, 150, 100);\n        }\n\n        a = bestA;\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    }\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}","ahc025":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Solver {\n    int N, D, Q;\n    int used = 0;\n\n    // ---------------- interactive ----------------\n    int cmp_single(int a, int b) {\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        ++used;\n        if (s == \"<\") return -1;\n        if (s == \">\") return 1;\n        return 0;\n    }\n\n    void dummy_query() {\n        int a = 0, b = min(1, N - 1);\n        cout << 1 << ' ' << 1 << ' ' << a << ' ' << b << '\\n';\n        cout.flush();\n        string s;\n        cin >> s;\n        ++used;\n    }\n\n    // ---------------- ordering ----------------\n    vector<int> insertion_sort_subset(const vector<int>& items, int budget_limit) {\n        vector<int> ord;\n        if (items.empty()) return ord;\n        ord.push_back(items[0]);\n        for (int ii = 1; ii < (int)items.size(); ++ii) {\n            int x = items[ii];\n            if (used >= budget_limit) {\n                ord.push_back(x);\n                continue;\n            }\n            int l = 0, r = (int)ord.size();\n            while (l < r && used < budget_limit) {\n                int m = (l + r) >> 1;\n                int c = cmp_single(x, ord[m]);\n                if (c < 0) r = m;\n                else l = m + 1;\n            }\n            ord.insert(ord.begin() + l, x);\n        }\n        return ord; // light -> heavy approximately\n    }\n\n    vector<int> build_order_two_phase(int budget_limit) {\n        // Choose number of anchors depending on budget.\n        // Total cost is roughly M log M + (N-M) log M.\n        int M = min(N, max(8, min(24, (int)round(sqrt((double)max(1, Q)) * 2.0))));\n        M = min(M, N);\n\n        vector<int> is_anchor(N, 0), anchors;\n        anchors.reserve(M);\n\n        // spread anchors by index\n        for (int k = 0; k < M; ++k) {\n            int idx = (long long)k * N / M;\n            if (idx >= N) idx = N - 1;\n            while (idx < N && is_anchor[idx]) idx++;\n            if (idx >= N) {\n                idx = N - 1;\n                while (idx >= 0 && is_anchor[idx]) idx--;\n            }\n            if (idx >= 0 && !is_anchor[idx]) {\n                is_anchor[idx] = 1;\n                anchors.push_back(idx);\n            }\n        }\n        // if duplicates reduced count\n        for (int i = 0; (int)anchors.size() < M && i < N; ++i) {\n            if (!is_anchor[i]) {\n                is_anchor[i] = 1;\n                anchors.push_back(i);\n            }\n        }\n\n        // sort anchors\n        vector<int> sorted_anchors = insertion_sort_subset(anchors, budget_limit);\n\n        // classify others into M+1 buckets by binary search on anchors\n        vector<vector<int>> buckets(M + 1);\n        for (int x = 0; x < N; ++x) {\n            if (is_anchor[x]) continue;\n\n            int l = 0, r = M;\n            while (l < r && used < budget_limit) {\n                int m = (l + r) >> 1;\n                if (m == M) {\n                    r = m;\n                    continue;\n                }\n                int c = cmp_single(x, sorted_anchors[m]);\n                if (c < 0) r = m;\n                else l = m + 1;\n            }\n            buckets[l].push_back(x);\n        }\n\n        // Build final order: bucket0, a0, bucket1, a1, ..., bucketM\n        vector<int> ord;\n        ord.reserve(N);\n        for (int i = 0; i < M; ++i) {\n            for (int x : buckets[i]) ord.push_back(x);\n            ord.push_back(sorted_anchors[i]);\n        }\n        for (int x : buckets[M]) ord.push_back(x);\n\n        return ord; // light -> heavy coarse order\n    }\n\n    vector<int> build_order_hybrid(int budget_limit) {\n        // For larger budgets, use plain insertion sort on all items.\n        // For smaller budgets, use two-phase order.\n        int threshold = (int)(N * 4.5);\n        if (Q >= threshold) {\n            vector<int> all(N);\n            iota(all.begin(), all.end(), 0);\n            return insertion_sort_subset(all, budget_limit);\n        } else {\n            return build_order_two_phase(budget_limit);\n        }\n    }\n\n    // ---------------- pseudo weights ----------------\n    vector<int> rank_pos_from_ord(const vector<int>& ord) {\n        vector<int> pos(N);\n        for (int i = 0; i < N; ++i) pos[ord[i]] = i;\n        return pos;\n    }\n\n    vector<double> make_pw_exp(const vector<int>& pos, double alpha = 5.0) {\n        vector<double> pw(N);\n        for (int i = 0; i < N; ++i) {\n            double t = (pos[i] + 0.5) / N;\n            pw[i] = exp(alpha * t);\n        }\n        return pw;\n    }\n\n    // ---------------- objective ----------------\n    vector<double> calc_loads(const vector<int>& asg, const vector<double>& pw) {\n        vector<double> load(D, 0.0);\n        for (int i = 0; i < N; ++i) load[asg[i]] += pw[i];\n        return load;\n    }\n\n    double objective(const vector<int>& asg, const vector<double>& pw) {\n        auto load = calc_loads(asg, pw);\n        double mean = 0.0;\n        for (double x : load) mean += x;\n        mean /= D;\n        double var = 0.0;\n        for (double x : load) {\n            double y = x - mean;\n            var += y * y;\n        }\n        return var / D;\n    }\n\n    // ---------------- assignment ----------------\n    vector<int> greedy_lpt(const vector<int>& ord, const vector<double>& pw, int tie_mode) {\n        vector<int> asg(N, 0);\n        vector<double> load(D, 0.0);\n\n        for (int idx = N - 1; idx >= 0; --idx) {\n            int item = ord[idx];\n            int best = 0;\n            for (int d = 1; d < D; ++d) {\n                if (load[d] < load[best] - 1e-12) best = d;\n                else if (fabs(load[d] - load[best]) <= 1e-12) {\n                    if (tie_mode == 1 && d < best) best = d;\n                    if (tie_mode == 2 && d > best) best = d;\n                }\n            }\n            asg[item] = best;\n            load[best] += pw[item];\n        }\n        return asg;\n    }\n\n    // ---------------- local search ----------------\n    void local_search(vector<int>& asg, const vector<double>& pw, const vector<int>& pos) {\n        double cur = objective(asg, pw);\n\n        vector<int> items(N);\n        iota(items.begin(), items.end(), 0);\n        sort(items.begin(), items.end(), [&](int a, int b) {\n            return pos[a] > pos[b]; // heavy first\n        });\n\n        for (int phase = 0; phase < 8; ++phase) {\n            bool improved = false;\n\n            // 1) best move among top-heavy items\n            {\n                double best = cur;\n                int bestItem = -1, bestTo = -1;\n                int K = min(N, 30);\n                for (int ii = 0; ii < K; ++ii) {\n                    int item = items[ii];\n                    int from = asg[item];\n                    for (int to = 0; to < D; ++to) {\n                        if (to == from) continue;\n                        int old = asg[item];\n                        asg[item] = to;\n                        double sc = objective(asg, pw);\n                        asg[item] = old;\n                        if (sc + 1e-12 < best) {\n                            best = sc;\n                            bestItem = item;\n                            bestTo = to;\n                        }\n                    }\n                }\n                if (bestItem != -1) {\n                    asg[bestItem] = bestTo;\n                    cur = best;\n                    improved = true;\n                }\n            }\n            if (improved) continue;\n\n            // 2) best swap involving one heavy candidate\n            {\n                double best = cur;\n                int besta = -1, bestb = -1;\n\n                int Kheavy = min(N, 24);\n                vector<int> candB;\n                for (int i = 0; i < min(N, 50); ++i) candB.push_back(items[i]);\n                for (int i = max(0, N - 12); i < N; ++i) candB.push_back(items[i]);\n                sort(candB.begin(), candB.end());\n                candB.erase(unique(candB.begin(), candB.end()), candB.end());\n\n                for (int ia = 0; ia < Kheavy; ++ia) {\n                    int a = items[ia];\n                    for (int b : candB) {\n                        if (a == b || asg[a] == asg[b]) continue;\n                        swap(asg[a], asg[b]);\n                        double sc = objective(asg, pw);\n                        swap(asg[a], asg[b]);\n                        if (sc + 1e-12 < best) {\n                            best = sc;\n                            besta = a;\n                            bestb = b;\n                        }\n                    }\n                }\n\n                if (besta != -1) {\n                    swap(asg[besta], asg[bestb]);\n                    cur = best;\n                    improved = true;\n                }\n            }\n            if (improved) continue;\n\n            // 3) fallback best single move over all items\n            {\n                double best = cur;\n                int bestItem = -1, bestTo = -1;\n                for (int item : items) {\n                    int from = asg[item];\n                    for (int to = 0; to < D; ++to) {\n                        if (to == from) continue;\n                        int old = asg[item];\n                        asg[item] = to;\n                        double sc = objective(asg, pw);\n                        asg[item] = old;\n                        if (sc + 1e-12 < best) {\n                            best = sc;\n                            bestItem = item;\n                            bestTo = to;\n                        }\n                    }\n                }\n                if (bestItem != -1) {\n                    asg[bestItem] = bestTo;\n                    cur = best;\n                    improved = true;\n                }\n            }\n\n            if (!improved) break;\n        }\n    }\n\n    // ---------------- solve ----------------\n    void solve() {\n        cin >> N >> D >> Q;\n\n        int reserve_dummy = 2;\n        int budget_limit = max(0, Q - reserve_dummy);\n\n        vector<int> ord = build_order_hybrid(budget_limit);\n        vector<int> pos = rank_pos_from_ord(ord);\n        vector<double> pw = make_pw_exp(pos, 5.0);\n\n        vector<int> best_asg;\n        double best_obj = 1e100;\n\n        for (int tie_mode = 0; tie_mode < 3; ++tie_mode) {\n            vector<int> asg = greedy_lpt(ord, pw, tie_mode);\n            local_search(asg, pw, pos);\n            double sc = objective(asg, pw);\n            if (sc < best_obj) {\n                best_obj = sc;\n                best_asg = asg;\n            }\n        }\n\n        while (used < Q) dummy_query();\n\n        for (int i = 0; i < N; ++i) {\n            if (i) cout << ' ';\n            cout << best_asg[i];\n        }\n        cout << '\\n';\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    return 0;\n}","ahc026":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Params {\n    int lookaheadW;\n    int beamWidth;\n    int maxDepth;\n    int destCandLimit;\n    int rolloutTargets;\n    long long costWeight;\n    long long exposedBonus;\n    long long abovePenalty;\n    long long stackSizePenalty;\n    long long urg5Penalty;\n    long long urg12Penalty;\n    long long urg25Penalty;\n    long long smallMinHeightPenalty;\n    long long destConflictAll;\n    long long destConflictTop;\n    long long destHeightPenalty;\n    long long destResultHeightPenalty;\n    long long rolloutWeight;\n};\n\nstruct Node {\n    vector<vector<int>> st;\n    vector<pair<int,int>> ops;\n    int cost = 0;\n    long long score = 0;\n};\n\nstruct RunResult {\n    vector<pair<int,int>> ops;\n    long long energy = (1LL << 60);\n};\n\nstruct Engine {\n    int n, m;\n    vector<vector<int>> init_st;\n    Params P;\n\n    Engine(int n_, int m_, const vector<vector<int>>& init_st_, const Params& P_)\n        : n(n_), m(m_), init_st(init_st_), P(P_) {}\n\n    pair<int,int> find_box(const vector<vector<int>>& st, int x) const {\n        for (int i = 0; i < m; i++) {\n            for (int j = 0; j < (int)st[i].size(); j++) {\n                if (st[i][j] == x) return {i, j};\n            }\n        }\n        return {-1, -1};\n    }\n\n    int min_in_stack(const vector<int>& v) const {\n        if (v.empty()) return (int)1e9;\n        int mn = (int)1e9;\n        for (int x : v) mn = min(mn, x);\n        return mn;\n    }\n\n    int min_top_window(const vector<int>& v, int w = 6) const {\n        if (v.empty()) return (int)1e9;\n        int mn = (int)1e9;\n        int sz = (int)v.size();\n        for (int i = max(0, sz - w); i < sz; i++) mn = min(mn, v[i]);\n        return mn;\n    }\n\n    void apply_move(vector<vector<int>>& st, int from, int pos, int to) const {\n        vector<int> moved(st[from].begin() + pos, st[from].end());\n        st[from].erase(st[from].begin() + pos, st[from].end());\n        st[to].insert(st[to].end(), moved.begin(), moved.end());\n    }\n\n    long long base_heuristic(const vector<vector<int>>& st, int need) const {\n        long long penalty = 0;\n\n        for (int x = need; x <= min(n, need + P.lookaheadW - 1); x++) {\n            auto [s, p] = find_box(st, x);\n            if (s == -1) continue;\n            int above = (int)st[s].size() - 1 - p;\n            int w = need + P.lookaheadW - x;\n\n            penalty += P.abovePenalty * w * above;\n            penalty += P.stackSizePenalty * w * (int)st[s].size();\n\n            for (int i = p + 1; i < (int)st[s].size(); i++) {\n                int y = st[s][i];\n                if (y <= x + 5) penalty += P.urg5Penalty * w;\n                else if (y <= x + 12) penalty += P.urg12Penalty * w;\n                else if (y <= x + 25) penalty += P.urg25Penalty * w;\n                else penalty += 1LL * w;\n            }\n        }\n\n        for (int s = 0; s < m; s++) {\n            int mn = min_in_stack(st[s]);\n            int h = (int)st[s].size();\n            if (mn < (int)1e9) {\n                int urg = max(0, 40 - mn);\n                penalty += P.smallMinHeightPenalty * urg * h;\n            }\n        }\n\n        return penalty;\n    }\n\n    long long destination_bias(const vector<vector<int>>& st, int to, int moved_min, int moved_sz) const {\n        int mn_all = min_in_stack(st[to]);\n        int mn_top = min_top_window(st[to], 6);\n        int h = (int)st[to].size();\n\n        long long val = 0;\n        val += P.destHeightPenalty * h;\n        val += P.destResultHeightPenalty * (h + moved_sz);\n\n        if (!st[to].empty()) {\n            if (mn_all < moved_min) val += P.destConflictAll;\n            if (mn_top < moved_min) val += P.destConflictTop;\n            val += 2LL * max(0, 80 - mn_all);\n            val += 2LL * max(0, 80 - mn_top);\n        }\n        return val;\n    }\n\n    int best_static_destination(const vector<vector<int>>& st, int from, int moved_min, int moved_sz, int need) const {\n        int forbid1 = -1, forbid2 = -1, forbid3 = -1;\n        if (need + 1 <= n) forbid1 = find_box(st, need + 1).first;\n        if (need + 2 <= n) forbid2 = find_box(st, need + 2).first;\n        if (need + 3 <= n) forbid3 = find_box(st, need + 3).first;\n\n        long long best = (1LL << 62);\n        int bestTo = -1;\n        for (int to = 0; to < m; to++) {\n            if (to == from) continue;\n            long long v = destination_bias(st, to, moved_min, moved_sz);\n            if (to == forbid1) v += 1500;\n            if (to == forbid2) v += 800;\n            if (to == forbid3) v += 400;\n            if (v < best) {\n                best = v;\n                bestTo = to;\n            }\n        }\n        return bestTo;\n    }\n\n    long long static_state_score(const vector<vector<int>>& st, int need) const {\n        long long s = 0;\n        for (int x = need; x <= min(n, need + 5); x++) {\n            auto [i, p] = find_box(st, x);\n            if (i == -1) continue;\n            int above = (int)st[i].size() - 1 - p;\n            s += 200LL * above + 5LL * st[i].size();\n        }\n        return s;\n    }\n\n    long long rollout_estimate(vector<vector<int>> st, int need) const {\n        long long est = 0;\n        int last = min(n, need + P.rolloutTargets - 1);\n\n        for (int x = need; x <= last; x++) {\n            while (true) {\n                auto [s, p] = find_box(st, x);\n                if (s == -1) break;\n                if (p == (int)st[s].size() - 1) {\n                    st[s].pop_back();\n                    break;\n                }\n\n                int top = (int)st[s].size() - 1;\n                int start = p + 1;\n\n                int posA = start;\n                int szA = top - posA + 1;\n                int mnA = (int)1e9;\n                for (int i = posA; i <= top; i++) mnA = min(mnA, st[s][i]);\n                int toA = best_static_destination(st, s, mnA, szA, x);\n                auto stA = st;\n                apply_move(stA, s, posA, toA);\n                long long scoreA = (szA + 1) * 1000LL + static_state_score(stA, x);\n\n                int posB = start;\n                int mnVal = st[s][start];\n                for (int i = start; i <= top; i++) {\n                    if (st[s][i] < mnVal) {\n                        mnVal = st[s][i];\n                        posB = i;\n                    }\n                }\n                int szB = top - posB + 1;\n                int mnB = mnVal;\n                int toB = best_static_destination(st, s, mnB, szB, x);\n                auto stB = st;\n                apply_move(stB, s, posB, toB);\n                long long scoreB = (szB + 1) * 1000LL + static_state_score(stB, x);\n\n                if (scoreA <= scoreB) {\n                    est += szA + 1;\n                    st.swap(stA);\n                } else {\n                    est += szB + 1;\n                    st.swap(stB);\n                }\n            }\n        }\n        return est;\n    }\n\n    long long heuristic(const vector<vector<int>>& st, int need) const {\n        long long h = base_heuristic(st, need);\n        if (P.rolloutTargets > 0) h += P.rolloutWeight * rollout_estimate(st, need);\n        return h;\n    }\n\n    vector<int> candidate_cut_positions(const vector<vector<int>>& st, int s, int need_pos) const {\n        vector<int> cand;\n        int top = (int)st[s].size() - 1;\n        if (need_pos == top) return cand;\n        int start = need_pos + 1;\n\n        cand.push_back(start);\n        if (start + 1 <= top) cand.push_back(start + 1);\n        if (start + 2 <= top) cand.push_back(start + 2);\n\n        int best = (int)1e9;\n        for (int i = start; i <= top; i++) {\n            if (st[s][i] < best) {\n                best = st[s][i];\n                cand.push_back(i);\n            }\n        }\n\n        best = (int)1e9;\n        for (int i = top; i >= start; i--) {\n            if (st[s][i] < best) {\n                best = st[s][i];\n                cand.push_back(i);\n            }\n        }\n\n        cand.push_back(top);\n        if (top - 1 >= start) cand.push_back(top - 1);\n        if (top - 2 >= start) cand.push_back(top - 2);\n\n        sort(cand.begin(), cand.end());\n        cand.erase(unique(cand.begin(), cand.end()), cand.end());\n        return cand;\n    }\n\n    int adaptive_beam_width(const vector<vector<int>>& st, int need) const {\n        auto [s, p] = find_box(st, need);\n        int blockers = (int)st[s].size() - 1 - p;\n        if (blockers <= 2) return P.beamWidth + 8;\n        if (blockers <= 5) return P.beamWidth + 4;\n        return P.beamWidth;\n    }\n\n    vector<int> candidate_destinations(const vector<vector<int>>& st, int from, int moved_min, int moved_sz, int need) const {\n        vector<pair<long long,int>> cand;\n\n        int forbid1 = -1, forbid2 = -1, forbid3 = -1;\n        if (need + 1 <= n) forbid1 = find_box(st, need + 1).first;\n        if (need + 2 <= n) forbid2 = find_box(st, need + 2).first;\n        if (need + 3 <= n) forbid3 = find_box(st, need + 3).first;\n\n        for (int to = 0; to < m; to++) {\n            if (to == from) continue;\n            long long v = destination_bias(st, to, moved_min, moved_sz);\n            if (to == forbid1) v += 1500;\n            if (to == forbid2) v += 800;\n            if (to == forbid3) v += 400;\n            cand.push_back({v, to});\n        }\n        sort(cand.begin(), cand.end());\n\n        vector<int> res;\n        int lim = min(P.destCandLimit, (int)cand.size());\n        for (int i = 0; i < lim; i++) res.push_back(cand[i].second);\n        return res;\n    }\n\n    string encode_state(const vector<vector<int>>& st) const {\n        string s;\n        s.reserve(512);\n        for (int i = 0; i < m; i++) {\n            for (int x : st[i]) {\n                s.push_back((char)(unsigned char)x);\n                s.push_back((char)(unsigned char)(x >> 8));\n            }\n            s.push_back((char)255);\n        }\n        return s;\n    }\n\n    vector<pair<int,int>> expose_with_beam(const vector<vector<int>>& current, int need) const {\n        auto [ss, pp] = find_box(current, need);\n        if (pp == (int)current[ss].size() - 1) return {};\n\n        Node root;\n        root.st = current;\n        root.cost = 0;\n        root.score = heuristic(root.st, need);\n\n        vector<Node> beam{root};\n        bool found_terminal = false;\n        Node best_terminal;\n        long long best_terminal_key = (1LL << 62);\n\n        int bw = adaptive_beam_width(current, need);\n\n        for (int depth = 0; depth < P.maxDepth; depth++) {\n            vector<Node> nxt;\n            unordered_map<string, long long> bestSeen;\n            bestSeen.reserve(512);\n\n            for (const auto& node : beam) {\n                auto [s, p] = find_box(node.st, need);\n                if (p == (int)node.st[s].size() - 1) {\n                    long long key = 1000LL * node.cost + heuristic(node.st, need);\n                    if (key < best_terminal_key) {\n                        best_terminal_key = key;\n                        best_terminal = node;\n                        found_terminal = true;\n                    }\n                    continue;\n                }\n\n                vector<int> cuts = candidate_cut_positions(node.st, s, p);\n                for (int pos : cuts) {\n                    int moved_sz = (int)node.st[s].size() - pos;\n                    int moved_min = (int)1e9;\n                    for (int i = pos; i < (int)node.st[s].size(); i++) moved_min = min(moved_min, node.st[s][i]);\n\n                    vector<int> dsts = candidate_destinations(node.st, s, moved_min, moved_sz, need);\n                    for (int to : dsts) {\n                        Node child = node;\n                        int v = child.st[s][pos];\n                        apply_move(child.st, s, pos, to);\n                        child.ops.push_back({v, to + 1});\n                        child.cost += moved_sz + 1;\n\n                        long long h = heuristic(child.st, need);\n                        child.score = P.costWeight * child.cost + h;\n\n                        auto [ns, np] = find_box(child.st, need);\n                        if (np == (int)child.st[ns].size() - 1) child.score -= P.exposedBonus;\n\n                        string key = encode_state(child.st);\n                        auto it = bestSeen.find(key);\n                        if (it == bestSeen.end() || child.score < it->second) {\n                            bestSeen[key] = child.score;\n                            nxt.push_back(std::move(child));\n                        }\n                    }\n                }\n            }\n\n            if (nxt.empty()) break;\n\n            sort(nxt.begin(), nxt.end(), [](const Node& a, const Node& b) {\n                if (a.score != b.score) return a.score < b.score;\n                return a.cost < b.cost;\n            });\n            if ((int)nxt.size() > bw) nxt.resize(bw);\n            beam = std::move(nxt);\n        }\n\n        for (const auto& node : beam) {\n            auto [s, p] = find_box(node.st, need);\n            if (p == (int)node.st[s].size() - 1) {\n                long long key = 1000LL * node.cost + heuristic(node.st, need);\n                if (key < best_terminal_key) {\n                    best_terminal_key = key;\n                    best_terminal = node;\n                    found_terminal = true;\n                }\n            }\n        }\n\n        if (found_terminal) return best_terminal.ops;\n\n        auto [s, p] = find_box(current, need);\n        vector<int> cuts = candidate_cut_positions(current, s, p);\n\n        long long bestScore = (1LL << 62);\n        pair<int,int> bestMove = {-1, -1};\n\n        for (int pos : cuts) {\n            int moved_sz = (int)current[s].size() - pos;\n            int moved_min = (int)1e9;\n            for (int i = pos; i < (int)current[s].size(); i++) moved_min = min(moved_min, current[s][i]);\n            vector<int> dsts = candidate_destinations(current, s, moved_min, moved_sz, need);\n            for (int to : dsts) {\n                auto st2 = current;\n                apply_move(st2, s, pos, to);\n                long long val = P.costWeight * (moved_sz + 1) + heuristic(st2, need);\n                if (val < bestScore) {\n                    bestScore = val;\n                    bestMove = {pos, to};\n                }\n            }\n        }\n\n        if (bestMove.first != -1) {\n            int v = current[s][bestMove.first];\n            return {{v, bestMove.second + 1}};\n        }\n\n        int pos = p + 1;\n        int v = current[s][pos];\n        int to = -1, besth = (int)1e9;\n        for (int j = 0; j < m; j++) if (j != s) {\n            if ((int)current[j].size() < besth) {\n                besth = (int)current[j].size();\n                to = j;\n            }\n        }\n        return {{v, to + 1}};\n    }\n\n    RunResult run() const {\n        vector<vector<int>> st = init_st;\n        vector<pair<int,int>> ans;\n        long long energy = 0;\n\n        auto apply_real_move = [&](int v, int to1based) {\n            int to = to1based - 1;\n            auto [s, p] = find_box(st, v);\n            int moved_sz = (int)st[s].size() - p;\n            energy += moved_sz + 1;\n            ans.push_back({v, to1based});\n            apply_move(st, s, p, to);\n        };\n\n        auto remove_real = [&](int need) {\n            auto [s, p] = find_box(st, need);\n            ans.push_back({need, 0});\n            st[s].pop_back();\n        };\n\n        for (int need = 1; need <= n; need++) {\n            while (true) {\n                auto [s, p] = find_box(st, need);\n                if (p == (int)st[s].size() - 1) {\n                    remove_real(need);\n                    break;\n                }\n\n                auto ops = expose_with_beam(st, need);\n                if (ops.empty()) continue;\n\n                for (auto [v, to] : ops) {\n                    apply_real_move(v, to);\n                    if ((int)ans.size() > 4900) break;\n                }\n                if ((int)ans.size() > 4900) break;\n            }\n            if ((int)ans.size() > 4900) break;\n        }\n\n        return {ans, energy};\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    vector<vector<int>> init_st(m, vector<int>(n / m));\n    for (int i = 0; i < m; i++) {\n        for (int j = 0; j < n / m; j++) cin >> init_st[i][j];\n    }\n\n    vector<Params> plist = {\n        // base best\n        {\n            18, 12, 4, 5, 2,\n            900, 50000,\n            140, 5, 55, 20, 6, 3,\n            2800, 1800, 60, 10,\n            40\n        },\n        // stronger rollout\n        {\n            18, 12, 4, 5, 3,\n            895, 50000,\n            140, 5, 55, 20, 6, 3,\n            2800, 1800, 60, 10,\n            34\n        },\n        // slightly broader destination exploration\n        {\n            18, 12, 4, 6, 2,\n            905, 50000,\n            139, 5, 54, 20, 6, 3,\n            2780, 1780, 60, 10,\n            38\n        },\n        // deeper-evaluation style\n        {\n            18, 12, 4, 5, 3,\n            885, 50500,\n            141, 5, 56, 21, 6, 3,\n            2820, 1820, 60, 10,\n            36\n        }\n    };\n\n    RunResult best;\n    for (const auto& P : plist) {\n        Engine engine(n, m, init_st, P);\n        RunResult r = engine.run();\n        if (r.energy < best.energy) best = std::move(r);\n    }\n\n    for (auto [v, i] : best.ops) {\n        cout << v << ' ' << i << '\\n';\n    }\n    return 0;\n}","ahc027":"#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 StartCand {\n    long long score;\n    vector<int> seq;\n    bool operator<(const StartCand& other) const {\n        return score < other.score;\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    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    vector<vector<int>> d2(N, vector<int>(N));\n    for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) cin >> d2[i][j];\n\n    const 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++) dirt[id(i, j)] = d2[i][j];\n\n    vector<vector<int>> adj(V);\n    vector<vector<char>> adjDir(V);\n\n    auto add_edge = [&](int a, int b, char c) {\n        adj[a].push_back(b);\n        adjDir[a].push_back(c);\n    };\n\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            int u = id(i, j);\n            if (i > 0 && h[i - 1][j] == '0') add_edge(u, id(i - 1, j), 'U');\n            if (i + 1 < N && h[i][j] == '0') add_edge(u, id(i + 1, j), 'D');\n            if (j > 0 && v[i][j - 1] == '0') add_edge(u, id(i, j - 1), 'L');\n            if (j + 1 < N && v[i][j] == '0') add_edge(u, id(i, j + 1), 'R');\n        }\n    }\n\n    // All-pairs shortest paths by BFS\n    vector<vector<short>> dist(V, vector<short>(V, -1));\n    vector<vector<short>> parent(V, vector<short>(V, -1));\n    vector<vector<char>> parentDir(V, vector<char>(V, '?'));\n    {\n        vector<int> q(V);\n        for (int s = 0; s < V; s++) {\n            int ql = 0, qr = 0;\n            q[qr++] = s;\n            dist[s][s] = 0;\n            parent[s][s] = s;\n            while (ql < qr) {\n                int u = q[ql++];\n                vector<int> ord(adj[u].size());\n                iota(ord.begin(), ord.end(), 0);\n                sort(ord.begin(), ord.end(), [&](int a, int b) {\n                    int va = adj[u][a], vb = adj[u][b];\n                    if (dirt[va] != dirt[vb]) return dirt[va] > dirt[vb];\n                    return va < vb;\n                });\n                for (int idx : ord) {\n                    int to = adj[u][idx];\n                    if (dist[s][to] == -1) {\n                        dist[s][to] = dist[s][u] + 1;\n                        parent[s][to] = u;\n                        parentDir[s][to] = adjDir[u][idx];\n                        q[qr++] = to;\n                    }\n                }\n            }\n        }\n    }\n\n    auto get_path = [&](int s, int t) -> string {\n        if (s == t) return \"\";\n        string revp;\n        int cur = t;\n        while (cur != s) {\n            revp.push_back(parentDir[s][cur]);\n            cur = parent[s][cur];\n        }\n        reverse(revp.begin(), revp.end());\n        return revp;\n    };\n\n    auto build_route = [&](const vector<int>& seq) -> string {\n        string route;\n        int cur = 0;\n        for (int x : seq) {\n            route += get_path(cur, x);\n            cur = x;\n        }\n        route += get_path(cur, 0);\n        return route;\n    };\n\n    auto route_len = [&](const vector<int>& seq) -> int {\n        int cur = 0, len = 0;\n        for (int x : seq) {\n            len += dist[cur][x];\n            cur = x;\n        }\n        len += dist[cur][0];\n        return len;\n    };\n\n    auto score_route = [&](const string& route) -> long long {\n        int L = (int)route.size();\n        if (L <= 0 || L > 100000) return (long long)4e18;\n\n        vector<vector<int>> visits(V);\n        int cur = 0;\n        for (int t = 1; t <= L; t++) {\n            auto [i, j] = pos(cur);\n            char c = route[t - 1];\n            if (c == 'U') --i;\n            else if (c == 'D') ++i;\n            else if (c == 'L') --j;\n            else ++j;\n            cur = id(i, j);\n            visits[cur].push_back(t);\n        }\n        if (cur != 0) return (long long)4e18;\n\n        visits[0].insert(visits[0].begin(), 0);\n\n        long double total = 0;\n        for (int u = 0; u < V; u++) {\n            if (visits[u].empty()) return (long long)4e18;\n            long long sum = 0;\n            auto &vec = visits[u];\n            for (int i = 0; i + 1 < (int)vec.size(); i++) {\n                long long g = vec[i + 1] - vec[i];\n                sum += g * (g - 1) / 2;\n            }\n            long long g = L - vec.back() + vec[0];\n            sum += g * (g - 1) / 2;\n            total += (long double)dirt[u] * (long double)sum;\n        }\n        return llround(total / (long double)L);\n    };\n\n    auto normalize_unique = [&](vector<int> seq) {\n        vector<char> seen(V, 0);\n        vector<int> out;\n        out.reserve(V - 1);\n        for (int x : seq) {\n            if (x == 0) continue;\n            if (!seen[x]) {\n                seen[x] = 1;\n                out.push_back(x);\n            }\n        }\n        for (int x = 1; x < V; x++) if (!seen[x]) out.push_back(x);\n        return out;\n    };\n\n    string bestRoute;\n    long long bestScore = (long long)4e18;\n    vector<int> bestSeq;\n\n    auto try_seq = [&](const vector<int>& seq) -> long long {\n        int len = route_len(seq);\n        if (len <= 0 || len > 100000) return (long long)4e18;\n        string route = build_route(seq);\n        long long sc = score_route(route);\n        if (sc < bestScore) {\n            bestScore = sc;\n            bestRoute = route;\n            bestSeq = seq;\n        }\n        return sc;\n    };\n\n    vector<vector<int>> baseCandidates;\n\n    // Row snake\n    {\n        vector<int> seq;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) seq.push_back(id(i, j));\n            else for (int j = N - 1; j >= 0; j--) seq.push_back(id(i, j));\n        }\n        seq = normalize_unique(seq);\n        baseCandidates.push_back(seq);\n        reverse(seq.begin(), seq.end());\n        baseCandidates.push_back(seq);\n    }\n\n    // Col snake\n    {\n        vector<int> seq;\n        for (int j = 0; j < N; j++) {\n            if (j % 2 == 0) for (int i = 0; i < N; i++) seq.push_back(id(i, j));\n            else for (int i = N - 1; i >= 0; i--) seq.push_back(id(i, j));\n        }\n        seq = normalize_unique(seq);\n        baseCandidates.push_back(seq);\n        reverse(seq.begin(), seq.end());\n        baseCandidates.push_back(seq);\n    }\n\n    // Geometric sorts\n    {\n        vector<int> seq;\n        for (int x = 1; x < V; x++) seq.push_back(x);\n        sort(seq.begin(), seq.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            double ka = ai + aj - 0.003 * dirt[a];\n            double kb = bi + bj - 0.003 * dirt[b];\n            return ka < kb;\n        });\n        baseCandidates.push_back(seq);\n    }\n    {\n        vector<int> seq;\n        for (int x = 1; x < V; x++) seq.push_back(x);\n        sort(seq.begin(), seq.end(), [&](int a, int b) {\n            auto [ai, aj] = pos(a);\n            auto [bi, bj] = pos(b);\n            double ka = ai - aj - 0.003 * dirt[a];\n            double kb = bi - bj - 0.003 * dirt[b];\n            return ka < kb;\n        });\n        baseCandidates.push_back(seq);\n    }\n\n    // Greedy unique\n    auto greedy_unique = [&](double beta, double gamma) {\n        vector<char> used(V, 0);\n        vector<int> seq;\n        seq.reserve(V - 1);\n        int cur = 0;\n        for (int step = 0; step < V - 1; step++) {\n            int best = -1;\n            double bestVal = -1e100;\n            for (int x = 1; x < V; x++) if (!used[x]) {\n                double val = beta * log((double)dirt[x]) - dist[cur][x] - gamma * dist[0][x];\n                if (val > bestVal) {\n                    bestVal = val;\n                    best = x;\n                }\n            }\n            used[best] = 1;\n            seq.push_back(best);\n            cur = best;\n        }\n        return seq;\n    };\n\n    for (double beta : {1.2, 1.5, 1.8, 2.2, 2.8}) {\n        for (double gamma : {0.0, 0.03, 0.07}) {\n            baseCandidates.push_back(greedy_unique(beta, gamma));\n        }\n    }\n\n    // Tree DFS order\n    auto tree_order = [&](double alpha) {\n        const double INF = 1e100;\n        vector<double> ds(V, INF);\n        vector<int> par(V, -1);\n        priority_queue<pair<double,int>, vector<pair<double,int>>, greater<pair<double,int>>> pq;\n        ds[0] = 0;\n        pq.push({0, 0});\n        while (!pq.empty()) {\n            auto [cd, u] = pq.top();\n            pq.pop();\n            if (cd != ds[u]) continue;\n            for (int to : adj[u]) {\n                double nd = cd + 1.0 / pow((double)dirt[to], alpha);\n                if (nd + 1e-12 < ds[to]) {\n                    ds[to] = nd;\n                    par[to] = u;\n                    pq.push({nd, to});\n                }\n            }\n        }\n        vector<vector<int>> ch(V);\n        for (int x = 1; x < V; x++) ch[par[x]].push_back(x);\n        for (int u = 0; u < V; u++) {\n            sort(ch[u].begin(), ch[u].end(), [&](int a, int b) {\n                if (dirt[a] != dirt[b]) return dirt[a] > dirt[b];\n                return dist[0][a] < dist[0][b];\n            });\n        }\n        vector<int> seq;\n        function<void(int)> dfs = [&](int u) {\n            if (u != 0) seq.push_back(u);\n            for (int x : ch[u]) dfs(x);\n        };\n        dfs(0);\n        return seq;\n    };\n\n    for (double alpha : {0.2, 0.4, 0.7, 1.0}) {\n        baseCandidates.push_back(tree_order(alpha));\n    }\n\n    vector<StartCand> starts;\n    for (int i = 0; i < (int)baseCandidates.size(); i++) {\n        if (timer.elapsed() > 0.82) break;\n        long long sc = try_seq(baseCandidates[i]);\n        starts.push_back({sc, baseCandidates[i]});\n    }\n    sort(starts.begin(), starts.end());\n\n    // Important cells\n    vector<int> byRatio, byDirt;\n    for (int x = 1; x < V; x++) {\n        byRatio.push_back(x);\n        byDirt.push_back(x);\n    }\n    sort(byRatio.begin(), byRatio.end(), [&](int a, int b) {\n        double sa = dirt[a] / (double)(dist[0][a] + 1);\n        double sb = dirt[b] / (double)(dist[0][b] + 1);\n        if (fabs(sa - sb) > 1e-12) return sa > sb;\n        return dirt[a] > dirt[b];\n    });\n    sort(byDirt.begin(), byDirt.end(), [&](int a, int b) {\n        if (dirt[a] != dirt[b]) return dirt[a] > dirt[b];\n        return dist[0][a] < dist[0][b];\n    });\n\n    vector<int> heavy;\n    vector<char> usedHeavy(V, 0);\n    for (int i = 0; i < min(24, (int)byRatio.size()); i++) {\n        int x = byRatio[i];\n        if (!usedHeavy[x]) {\n            usedHeavy[x] = 1;\n            heavy.push_back(x);\n        }\n    }\n    for (int i = 0; i < min(24, (int)byDirt.size()); i++) {\n        int x = byDirt[i];\n        if (!usedHeavy[x]) {\n            usedHeavy[x] = 1;\n            heavy.push_back(x);\n        }\n    }\n\n    auto insert_cost = [&](const vector<int>& seq, int p, int x) {\n        int prev = (p == 0 ? 0 : seq[p - 1]);\n        int next = (p == (int)seq.size() ? 0 : seq[p]);\n        return dist[prev][x] + dist[x][next] - dist[prev][next];\n    };\n\n    mt19937 rng(123456789);\n\n    // Seeded duplicated routes become additional local-search starts\n    int seedElite = min(5, (int)starts.size());\n    for (int ei = 0; ei < seedElite && timer.elapsed() < 1.10; ei++) {\n        for (int variant = 0; variant < 2 && timer.elapsed() < 1.10; variant++) {\n            vector<int> seq = starts[ei].seq;\n            int curLen = route_len(seq);\n\n            for (int t = 0; t < min(4, (int)heavy.size()); t++) {\n                int x = heavy[t];\n                vector<pair<int,int>> cands; // {add, pos}\n                int M = seq.size();\n                int sample = min(M + 1, 28);\n                for (int k = 0; k < sample; k++) {\n                    int p = (long long)k * (M + 1) / sample;\n                    int add = insert_cost(seq, p, x);\n                    if (curLen + add > 100000) continue;\n                    cands.push_back({add, p});\n                }\n                if (cands.empty()) continue;\n                sort(cands.begin(), cands.end());\n\n                int pick = 0;\n                if (variant == 1 && t == 0 && (int)cands.size() >= 2) pick = 1; // second-cheapest for first heavy\n                int bestAdd = cands[pick].first;\n                int bestP = cands[pick].second;\n\n                seq.insert(seq.begin() + bestP, x);\n                curLen += bestAdd;\n            }\n            long long sc = try_seq(seq);\n            starts.push_back({sc, seq});\n        }\n    }\n\n    sort(starts.begin(), starts.end());\n    if ((int)starts.size() > 14) starts.resize(14);\n\n    auto best_single_insertion = [&](const vector<int>& seq, int curLen, long long curScore, double timeLimit)\n        -> tuple<bool, vector<int>, int, long long> {\n\n        long long bestLocalScore = curScore;\n        vector<int> bestLocalSeq = seq;\n        int bestLocalLen = curLen;\n        int M = seq.size();\n\n        for (int x : heavy) {\n            if (timer.elapsed() > timeLimit) break;\n\n            vector<int> posCand;\n            int sample = min(M + 1, 36);\n            for (int k = 0; k < sample; k++) {\n                int p = (long long)k * (M + 1) / sample;\n                posCand.push_back(p);\n            }\n            for (int idx = 0; idx < M; idx++) {\n                int y = seq[idx];\n                if (dist[x][y] <= 3) {\n                    posCand.push_back(idx);\n                    posCand.push_back(idx + 1);\n                }\n            }\n            posCand.push_back(0);\n            posCand.push_back(M);\n            for (int t = 0; t < 10; t++) posCand.push_back(rng() % (M + 1));\n\n            sort(posCand.begin(), posCand.end());\n            posCand.erase(unique(posCand.begin(), posCand.end()), posCand.end());\n\n            for (int p : posCand) {\n                int add = insert_cost(seq, p, x);\n                if (curLen + add > 100000) continue;\n                if (add > 28) continue;\n\n                vector<int> cand = seq;\n                cand.insert(cand.begin() + p, x);\n                string route = build_route(cand);\n                long long sc = score_route(route);\n                if (sc < bestLocalScore) {\n                    bestLocalScore = sc;\n                    bestLocalSeq.swap(cand);\n                    bestLocalLen = curLen + add;\n                }\n            }\n        }\n\n        bool improved = (bestLocalScore < curScore);\n        return {improved, bestLocalSeq, bestLocalLen, bestLocalScore};\n    };\n\n    for (int si = 0; si < (int)starts.size() && timer.elapsed() < 1.95; si++) {\n        vector<int> seq = starts[si].seq;\n        long long curScore = starts[si].score;\n        int curLen = route_len(seq);\n\n        bool improved = true;\n        int round = 0;\n        while (improved && timer.elapsed() < 1.95 && round < 11) {\n            improved = false;\n            round++;\n\n            auto [ok1, seq1, len1, sc1] = best_single_insertion(seq, curLen, curScore, 1.92);\n            if (ok1) {\n                seq = seq1;\n                curLen = len1;\n                curScore = sc1;\n                improved = true;\n                if (curScore < bestScore) {\n                    bestScore = curScore;\n                    bestSeq = seq;\n                    bestRoute = build_route(seq);\n                }\n\n                if (timer.elapsed() < 1.89) {\n                    auto [ok2, seq2, len2, sc2] = best_single_insertion(seq, curLen, curScore, 1.92);\n                    if (ok2) {\n                        seq = seq2;\n                        curLen = len2;\n                        curScore = sc2;\n                        improved = true;\n                        if (curScore < bestScore) {\n                            bestScore = curScore;\n                            bestSeq = seq;\n                            bestRoute = build_route(seq);\n                        }\n                    }\n                }\n\n                if (timer.elapsed() < 1.86) {\n                    auto [ok3, seq3, len3, sc3] = best_single_insertion(seq, curLen, curScore, 1.92);\n                    if (ok3) {\n                        seq = seq3;\n                        curLen = len3;\n                        curScore = sc3;\n                        improved = true;\n                        if (curScore < bestScore) {\n                            bestScore = curScore;\n                            bestSeq = seq;\n                            bestRoute = build_route(seq);\n                        }\n                    }\n                }\n            }\n\n            // tiny diversification only\n            for (int t = 0; t < 2 && timer.elapsed() < 1.95; t++) {\n                int l = rng() % seq.size();\n                int r = rng() % seq.size();\n                if (l > r) swap(l, r);\n                if (l == r) continue;\n                vector<int> cand = seq;\n                reverse(cand.begin() + l, cand.begin() + r + 1);\n                int len2 = route_len(cand);\n                if (len2 > 100000) continue;\n                string route = build_route(cand);\n                long long sc = score_route(route);\n                if (sc < curScore) {\n                    seq.swap(cand);\n                    curLen = len2;\n                    curScore = sc;\n                    improved = true;\n                    if (curScore < bestScore) {\n                        bestScore = curScore;\n                        bestSeq = seq;\n                        bestRoute = route;\n                    }\n                }\n            }\n        }\n    }\n\n    if (bestRoute.empty()) {\n        vector<int> seq;\n        for (int i = 0; i < N; i++) {\n            if (i % 2 == 0) for (int j = 0; j < N; j++) seq.push_back(id(i, j));\n            else for (int j = N - 1; j >= 0; j--) seq.push_back(id(i, j));\n        }\n        seq = normalize_unique(seq);\n        bestRoute = build_route(seq);\n    }\n\n    cout << bestRoute << '\\n';\n    return 0;\n}","ahc028":"#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 Pos {\n    int x, y;\n};\n\nstatic const int INF = 1e9;\n\nint overlap5(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    Timer timer;\n    mt19937 rng(123456789);\n\n    int N, M;\n    cin >> N >> M;\n    int si, sj;\n    cin >> si >> sj;\n\n    vector<string> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<string> t(M);\n    for (int i = 0; i < M; i++) cin >> t[i];\n\n    // Positions by letter\n    vector<vector<Pos>> pos(26);\n    for (int i = 0; i < N; i++) {\n        for (int j = 0; j < N; j++) {\n            pos[A[i][j] - 'A'].push_back({i, j});\n        }\n    }\n\n    // Approximate distances\n    int startDist[26];\n    int bestDist[26][26];\n    for (int c = 0; c < 26; c++) {\n        startDist[c] = INF;\n        for (auto &p : pos[c]) {\n            startDist[c] = min(startDist[c], abs(si - p.x) + abs(sj - p.y));\n        }\n    }\n    for (int a = 0; a < 26; a++) {\n        for (int b = 0; b < 26; b++) {\n            int d = INF;\n            for (auto &p : pos[a]) for (auto &q : pos[b]) {\n                d = min(d, abs(p.x - q.x) + abs(p.y - q.y));\n            }\n            bestDist[a][b] = d;\n        }\n    }\n\n    // Overlap matrix\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++) if (i != j) {\n            ov[i][j] = overlap5(t[i], t[j]);\n        }\n    }\n\n    auto start_word_cost = [&](int x) -> int {\n        int cost = startDist[t[x][0] - 'A'] + 1;\n        for (int i = 1; i < 5; i++) {\n            cost += bestDist[t[x][i - 1] - 'A'][t[x][i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    auto append_cost = [&](int a, int b) -> int {\n        int o = ov[a][b];\n        string add = t[b].substr(o);\n        if (add.empty()) return 0;\n        int cost = bestDist[t[a][4] - 'A'][add[0] - 'A'] + 1;\n        for (int i = 1; i < (int)add.size(); i++) {\n            cost += bestDist[add[i - 1] - 'A'][add[i] - 'A'] + 1;\n        }\n        return cost;\n    };\n\n    vector<int> startCost(M);\n    vector<vector<int>> appCost(M, vector<int>(M, 0));\n    for (int i = 0; i < M; i++) startCost[i] = start_word_cost(i);\n    for (int i = 0; i < M; i++) {\n        for (int j = 0; j < M; j++) if (i != j) {\n            appCost[i][j] = append_cost(i, j);\n        }\n    }\n\n    struct Eval {\n        int ovsum;\n        int mov;\n    };\n\n    auto eval_order = [&](const vector<int>& ord) -> Eval {\n        int ovsum = 0;\n        int mov = startCost[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            ovsum += ov[ord[i - 1]][ord[i]];\n            mov += appCost[ord[i - 1]][ord[i]];\n        }\n        return {ovsum, mov};\n    };\n\n    auto better = [&](const Eval& a, const Eval& b) -> bool {\n        if (a.ovsum != b.ovsum) return a.ovsum > b.ovsum;\n        return a.mov < b.mov;\n    };\n\n    auto build_string = [&](const vector<int>& ord) -> string {\n        string s = t[ord[0]];\n        for (int i = 1; i < (int)ord.size(); i++) {\n            s += t[ord[i]].substr(ov[ord[i - 1]][ord[i]]);\n        }\n        return s;\n    };\n\n    auto make_insertion_order = [&](int seed, bool randomized) -> vector<int> {\n        vector<int> ord = {seed};\n        vector<char> used(M, 0);\n        used[seed] = 1;\n\n        int second = -1;\n        Eval bestE{-INF, INF};\n        vector<pair<Eval,int>> cand2;\n        for (int j = 0; j < M; j++) if (!used[j]) {\n            vector<int> tmp = {seed, j};\n            Eval e = eval_order(tmp);\n            cand2.push_back({e, j});\n            if (second == -1 || better(e, bestE)) {\n                second = j;\n                bestE = e;\n            }\n        }\n        if (randomized) {\n            sort(cand2.begin(), cand2.end(), [&](auto &x, auto &y) {\n                return better(x.first, y.first);\n            });\n            int take = min(5, (int)cand2.size());\n            second = cand2[rng() % take].second;\n        }\n\n        ord.push_back(second);\n        used[second] = 1;\n\n        while ((int)ord.size() < M) {\n            struct Cand {\n                Eval e;\n                int x, p;\n            };\n            vector<Cand> cands;\n\n            int L = ord.size();\n            for (int x = 0; x < M; x++) if (!used[x]) {\n                for (int p = 0; p <= L; p++) {\n                    int deltaOv = 0;\n                    int deltaMove = 0;\n\n                    if (p == 0) {\n                        deltaOv = ov[x][ord[0]];\n                        deltaMove = startCost[x] + appCost[x][ord[0]] - startCost[ord[0]];\n                    } else if (p == L) {\n                        int a = ord[L - 1];\n                        deltaOv = ov[a][x];\n                        deltaMove = appCost[a][x];\n                    } else {\n                        int a = ord[p - 1], b = ord[p];\n                        deltaOv = ov[a][x] + ov[x][b] - ov[a][b];\n                        deltaMove = appCost[a][x] + appCost[x][b] - appCost[a][b];\n                    }\n\n                    cands.push_back({{deltaOv, deltaMove}, x, p});\n                }\n            }\n\n            sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n                return better(a.e, b.e);\n            });\n\n            Cand chosen = cands[0];\n            if (randomized) {\n                int take = min(8, (int)cands.size());\n                chosen = cands[rng() % take];\n            }\n\n            ord.insert(ord.begin() + chosen.p, chosen.x);\n            used[chosen.x] = 1;\n        }\n\n        return ord;\n    };\n\n    auto make_greedy_order = [&](int seed, bool randomized) -> vector<int> {\n        vector<int> ord;\n        vector<char> used(M, 0);\n        ord.reserve(M);\n        ord.push_back(seed);\n        used[seed] = 1;\n        int cur = seed;\n\n        while ((int)ord.size() < M) {\n            vector<pair<Eval,int>> cands;\n            for (int j = 0; j < M; j++) if (!used[j]) {\n                cands.push_back({{ov[cur][j], appCost[cur][j]}, j});\n            }\n            sort(cands.begin(), cands.end(), [&](auto &a, auto &b) {\n                return better(a.first, b.first);\n            });\n            int nxt = cands[0].second;\n            if (randomized) {\n                int take = min(5, (int)cands.size());\n                nxt = cands[rng() % take].second;\n            }\n            ord.push_back(nxt);\n            used[nxt] = 1;\n            cur = nxt;\n        }\n\n        return ord;\n    };\n\n    auto improve_order = [&](vector<int> ord) -> vector<int> {\n        Eval cur = eval_order(ord);\n\n        auto try_accept = [&](vector<int>& cand) -> bool {\n            Eval e = eval_order(cand);\n            if (better(e, cur)) {\n                ord.swap(cand);\n                cur = e;\n                return true;\n            }\n            return false;\n        };\n\n        while (timer.elapsed() < 1.82) {\n            bool improved = false;\n\n            // adjacent swap sweep\n            for (int i = 0; i + 1 < M && timer.elapsed() < 1.82; i++) {\n                vector<int> cand = ord;\n                swap(cand[i], cand[i + 1]);\n                if (try_accept(cand)) improved = true;\n            }\n\n            // random swap\n            for (int it = 0; it < 300 && timer.elapsed() < 1.82; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                vector<int> cand = ord;\n                swap(cand[i], cand[j]);\n                if (try_accept(cand)) improved = true;\n            }\n\n            // random relocate\n            for (int it = 0; it < 300 && timer.elapsed() < 1.82; it++) {\n                int i = rng() % M;\n                int j = rng() % M;\n                if (i == j) continue;\n                vector<int> cand = ord;\n                int v = cand[i];\n                cand.erase(cand.begin() + i);\n                cand.insert(cand.begin() + j, v);\n                if (try_accept(cand)) improved = true;\n            }\n\n            // segment reverse\n            for (int it = 0; it < 100 && timer.elapsed() < 1.82; it++) {\n                int l = rng() % M;\n                int r = rng() % M;\n                if (l > r) swap(l, r);\n                if (r - l < 2) continue;\n                vector<int> cand = ord;\n                reverse(cand.begin() + l, cand.begin() + r + 1);\n                if (try_accept(cand)) improved = true;\n            }\n\n            if (!improved) break;\n        }\n\n        return ord;\n    };\n\n    // choose promising starts\n    vector<pair<int,int>> starters;\n    for (int i = 0; i < M; i++) starters.push_back({startCost[i], i});\n    sort(starters.begin(), starters.end());\n\n    vector<int> bestOrder;\n    Eval bestEval{-INF, INF};\n\n    // more diversified multi-start\n    while (timer.elapsed() < 0.85) {\n        int s;\n        if ((int)starters.size() > 0) {\n            int take = min(20, M);\n            s = starters[rng() % take].second;\n        } else {\n            s = rng() % M;\n        }\n\n        int mode = rng() % 4;\n        vector<int> ord;\n        if (mode == 0) ord = make_insertion_order(s, false);\n        else if (mode == 1) ord = make_insertion_order(s, true);\n        else if (mode == 2) ord = make_greedy_order(s, false);\n        else ord = make_greedy_order(s, true);\n\n        Eval e = eval_order(ord);\n        if (bestOrder.empty() || better(e, bestEval)) {\n            bestOrder = ord;\n            bestEval = e;\n        }\n    }\n\n    bestOrder = improve_order(bestOrder);\n\n    string S = build_string(bestOrder);\n\n    // Safety fallback (practically never needed)\n    if ((int)S.size() > 5000) {\n        S.clear();\n        for (int i = 0; i < M; i++) S += t[i];\n    }\n\n    // Exact DP for optimal positions\n    int L = (int)S.size();\n    vector<vector<int>> dp(L), pre(L);\n\n    {\n        int c = S[0] - 'A';\n        int sz = pos[c].size();\n        dp[0].assign(sz, INF);\n        pre[0].assign(sz, -1);\n        for (int i = 0; i < sz; i++) {\n            dp[0][i] = abs(si - pos[c][i].x) + abs(sj - pos[c][i].y) + 1;\n        }\n    }\n\n    for (int i = 1; i < L; i++) {\n        int pc = S[i - 1] - 'A';\n        int cc = S[i] - 'A';\n        int psz = pos[pc].size();\n        int csz = pos[cc].size();\n        dp[i].assign(csz, INF);\n        pre[i].assign(csz, -1);\n\n        for (int v = 0; v < csz; v++) {\n            int best = INF, bestu = -1;\n            for (int u = 0; u < psz; u++) {\n                int val = dp[i - 1][u]\n                        + abs(pos[pc][u].x - pos[cc][v].x)\n                        + abs(pos[pc][u].y - pos[cc][v].y) + 1;\n                if (val < best) {\n                    best = val;\n                    bestu = u;\n                }\n            }\n            dp[i][v] = best;\n            pre[i][v] = bestu;\n        }\n    }\n\n    int last = 0;\n    for (int i = 1; i < (int)dp[L - 1].size(); i++) {\n        if (dp[L - 1][i] < dp[L - 1][last]) last = i;\n    }\n\n    vector<Pos> ans(L);\n    int cur = last;\n    for (int i = L - 1; i >= 0; i--) {\n        int c = S[i] - 'A';\n        ans[i] = pos[c][cur];\n        if (i > 0) cur = pre[i][cur];\n    }\n\n    for (auto &p : ans) {\n        cout << p.x << ' ' << p.y << '\\n';\n    }\n\n    return 0;\n}","ahc030":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Placement {\n    vector<int> cells;\n    vector<int> drillMaskIdx; // indices t such that this placement covers drilledList[t]\n};\n\nstruct Field {\n    vector<pair<int,int>> shape;\n    int h = 0, w = 0;\n    vector<Placement> plc;\n};\n\nstruct Solver {\n    int N, M;\n    double eps;\n    vector<Field> fields;\n\n    int maxOps, ops = 0;\n    vector<int> drilled;      // -1 unknown, else exact reserve\n    vector<int> drilledList;  // cell ids\n    vector<char> hasOil;      // final after full drilling fallback\n\n    Solver() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> M >> eps;\n        fields.resize(M);\n        for (int m = 0; m < M; m++) {\n            int d;\n            cin >> d;\n            fields[m].shape.resize(d);\n            int hi = 0, hj = 0;\n            for (int k = 0; k < d; k++) {\n                int i, j;\n                cin >> i >> j;\n                fields[m].shape[k] = {i, j};\n                hi = max(hi, i);\n                hj = max(hj, j);\n            }\n            fields[m].h = hi + 1;\n            fields[m].w = hj + 1;\n        }\n\n        maxOps = 2 * N * N;\n        drilled.assign(N * N, -1);\n        hasOil.assign(N * N, 0);\n\n        buildPlacements();\n    }\n\n    inline int id(int i, int j) const { return i * N + j; }\n    inline pair<int,int> rc(int c) const { return {c / N, c % N}; }\n\n    void buildPlacements() {\n        for (int m = 0; m < M; m++) {\n            auto &f = fields[m];\n            for (int di = 0; di + f.h <= N; di++) {\n                for (int dj = 0; dj + f.w <= N; dj++) {\n                    Placement p;\n                    for (auto [i, j] : f.shape) {\n                        p.cells.push_back(id(di + i, dj + j));\n                    }\n                    f.plc.push_back(move(p));\n                }\n            }\n        }\n    }\n\n    int drillCell(int c) {\n        auto [i, j] = rc(c);\n        cout << \"q 1 \" << i << \" \" << j << '\\n';\n        cout.flush();\n        int x;\n        cin >> x;\n        ++ops;\n        if (drilled[c] == -1) drilledList.push_back(c);\n        drilled[c] = x;\n        if (x > 0) hasOil[c] = 1;\n        return x;\n    }\n\n    bool answerCells(const vector<int>& cells) {\n        cout << \"a \" << cells.size();\n        for (int c : cells) {\n            auto [i, j] = rc(c);\n            cout << ' ' << i << ' ' << j;\n        }\n        cout << '\\n';\n        cout.flush();\n        int res;\n        cin >> res;\n        ++ops;\n        return res == 1;\n    }\n\n    // ---------- Exact search for small instances ----------\n\n    vector<vector<int>> feasible;   // feasible placements per field under zero-cells only\n    vector<int> order;\n    vector<int> remainCanCover;     // flattened [pos * D + t]\n    vector<int> curSum;\n    vector<int> chosen;\n    vector<int> solChosen;\n    int solutionsFound = 0;\n    int dfsNodeBudget = 200000;     // hard cap for safety\n    int dfsNodes = 0;\n\n    bool placementCompatibleWithZero(int m, int pidx) {\n        for (int c : fields[m].plc[pidx].cells) {\n            if (drilled[c] == 0) return false;\n        }\n        return true;\n    }\n\n    void prepareSearch() {\n        int D = (int)drilledList.size();\n\n        feasible.assign(M, {});\n        for (int m = 0; m < M; m++) {\n            for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                if (placementCompatibleWithZero(m, p)) {\n                    feasible[m].push_back(p);\n                }\n            }\n        }\n\n        order.resize(M);\n        iota(order.begin(), order.end(), 0);\n        sort(order.begin(), order.end(), [&](int a, int b) {\n            return feasible[a].size() < feasible[b].size();\n        });\n\n        for (int m = 0; m < M; m++) {\n            for (int pidx : feasible[m]) {\n                auto &pl = fields[m].plc[pidx];\n                pl.drillMaskIdx.clear();\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    // linear scan over cells of shape; shapes are small enough\n                    for (int x : pl.cells) {\n                        if (x == c) {\n                            pl.drillMaskIdx.push_back(t);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        remainCanCover.assign((M + 1) * max(1, D), 0);\n        if (D > 0) {\n            for (int pos = M - 1; pos >= 0; pos--) {\n                int m = order[pos];\n                for (int t = 0; t < D; t++) {\n                    int c = drilledList[t];\n                    int can = 0;\n                    for (int pidx : feasible[m]) {\n                        for (int x : fields[m].plc[pidx].cells) {\n                            if (x == c) {\n                                can = 1;\n                                goto done;\n                            }\n                        }\n                    }\n                done:\n                    remainCanCover[pos * D + t] = remainCanCover[(pos + 1) * D + t] + can;\n                }\n            }\n        }\n\n        curSum.assign(D, 0);\n        chosen.assign(M, -1);\n        solChosen.clear();\n        solutionsFound = 0;\n        dfsNodes = 0;\n    }\n\n    void dfsSearch(int pos) {\n        if (solutionsFound >= 2) return;\n        if (++dfsNodes > dfsNodeBudget) return;\n\n        int D = (int)drilledList.size();\n        if (pos == M) {\n            for (int t = 0; t < D; t++) {\n                if (curSum[t] != drilled[drilledList[t]]) return;\n            }\n            ++solutionsFound;\n            if (solutionsFound == 1) solChosen = chosen;\n            return;\n        }\n\n        int m = order[pos];\n\n        // Try placements in heuristic order: match positive drilled cells more\n        vector<pair<int,int>> cand;\n        cand.reserve(feasible[m].size());\n        for (int pidx : feasible[m]) {\n            int score = 0;\n            for (int t : fields[m].plc[pidx].drillMaskIdx) {\n                if (drilled[drilledList[t]] > 0) score++;\n                else score -= 1000;\n            }\n            cand.push_back({-score, pidx});\n        }\n        sort(cand.begin(), cand.end());\n\n        for (auto [_, pidx] : cand) {\n            auto &pl = fields[m].plc[pidx];\n            bool ok = true;\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]++;\n            }\n\n            for (int t = 0; t < D; t++) {\n                int target = drilled[drilledList[t]];\n                if (curSum[t] > target) { ok = false; break; }\n                int rem = remainCanCover[(pos + 1) * D + t];\n                if (curSum[t] + rem < target) { ok = false; break; }\n            }\n\n            if (ok) {\n                chosen[m] = pidx;\n                dfsSearch(pos + 1);\n                chosen[m] = -1;\n            }\n\n            for (int t : pl.drillMaskIdx) {\n                curSum[t]--;\n            }\n\n            if (solutionsFound >= 2 || dfsNodes > dfsNodeBudget) return;\n        }\n    }\n\n    bool tryExactSolve(vector<int>& ansCells, bool requireUnique) {\n        prepareSearch();\n\n        for (int m = 0; m < M; m++) {\n            if (feasible[m].empty()) return false;\n        }\n\n        dfsSearch(0);\n\n        if (dfsNodes > dfsNodeBudget) return false;\n        if (solutionsFound == 0) return false;\n        if (requireUnique && solutionsFound != 1) return false;\n\n        vector<char> used(N * N, 0);\n        for (int m = 0; m < M; m++) {\n            int pidx = solChosen[m];\n            if (pidx < 0) return false;\n            for (int c : fields[m].plc[pidx].cells) used[c] = 1;\n        }\n\n        for (int c : drilledList) {\n            if ((drilled[c] == 0 && used[c]) || (drilled[c] > 0 && !used[c])) {\n                return false;\n            }\n        }\n\n        ansCells.clear();\n        for (int c = 0; c < N * N; c++) if (used[c]) ansCells.push_back(c);\n        return true;\n    }\n\n    // ---------- Strategy ----------\n\n    vector<int> informativeOrder() {\n        // deterministic spread: checkerboard center-first-ish\n        vector<int> cells;\n        cells.reserve(N * N);\n        vector<pair<int,int>> tmp;\n        double ci = (N - 1) / 2.0, cj = (N - 1) / 2.0;\n        for (int i = 0; i < N; i++) {\n            for (int j = 0; j < N; j++) {\n                int parity = (i + j) & 1;\n                int dist = (int)(1000 * (abs(i - ci) + abs(j - cj)));\n                tmp.push_back({parity * 100000 + dist, id(i, j)});\n            }\n        }\n        sort(tmp.begin(), tmp.end());\n        for (auto &x : tmp) cells.push_back(x.second);\n        return cells;\n    }\n\n    void fullDrillFallback() {\n        for (int c = 0; c < N * N && ops < maxOps - 1; c++) {\n            if (drilled[c] == -1) drillCell(c);\n        }\n        vector<int> ans;\n        for (int c = 0; c < N * N; c++) if (drilled[c] > 0) ans.push_back(c);\n        answerCells(ans);\n    }\n\n    void solve() {\n        // Only attempt exact reasoning when likely cheap.\n        long long totalPlacements = 0;\n        for (int m = 0; m < M; m++) totalPlacements += fields[m].plc.size();\n\n        bool useSearch = (M <= 8 && totalPlacements <= 700);\n\n        if (!useSearch) {\n            fullDrillFallback();\n            return;\n        }\n\n        // Small-instance mode:\n        // Drill a modest number of informative cells, trying to pin down unique placement combo.\n        vector<int> orderCells = informativeOrder();\n        int initialDrills = min<int>(N * N, max(12, N));\n\n        for (int t = 0; t < initialDrills && ops < maxOps - 1; t++) {\n            int c = orderCells[t];\n            if (drilled[c] == -1) drillCell(c);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // If not yet unique, continue a bit more adaptively: drill cells appearing often in candidate answer.\n        for (int extra = initialDrills; extra < min(N * N, initialDrills + 20) && ops < maxOps - 1; extra++) {\n            int best = -1, bestScore = -1;\n\n            for (int c = 0; c < N * N; c++) if (drilled[c] == -1) {\n                int score = 0;\n                for (int m = 0; m < M; m++) {\n                    for (int p = 0; p < (int)fields[m].plc.size(); p++) {\n                        if (!placementCompatibleWithZero(m, p)) continue;\n                        for (int x : fields[m].plc[p].cells) {\n                            if (x == c) { score++; break; }\n                        }\n                    }\n                }\n                if (score > bestScore) {\n                    bestScore = score;\n                    best = c;\n                }\n            }\n\n            if (best == -1) break;\n            drillCell(best);\n\n            vector<int> ans;\n            if (tryExactSolve(ans, true)) {\n                if (answerCells(ans)) return;\n            }\n        }\n\n        // Fallback: guaranteed correct\n        fullDrillFallback();\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc031":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\nstatic const int W = 1000;\nstatic const ll INF64 = (1LL << 62);\n\nstruct Rect {\n    int i0, j0, i1, j1;\n};\n\nstruct DayLayout {\n    vector<int> outer;\n    vector<vector<int>> inner_pref;\n    ll penalty = 0;\n    vector<Rect> rects;\n};\n\nstruct Answer {\n    ll total_cost = INF64;\n    vector<vector<Rect>> days;\n};\n\nstruct TopoCand {\n    vector<int> cuts;\n    int orientation;\n    ll cheap_score;\n};\n\nstatic inline ll miss_need_cap(int need, int cap) {\n    return max(0, need - cap);\n}\n\nstatic vector<int> normalize_sizes_from_weights(const vector<ll>& weights) {\n    int R = (int)weights.size();\n    ll total = 0;\n    for (ll x : weights) total += x;\n    if (total == 0) total = 1;\n\n    vector<int> sz(R, 1);\n    vector<pair<double,int>> frac;\n    int used = 0;\n    for (int i = 0; i < R; i++) {\n        double ideal = (double)W * (double)weights[i] / (double)total;\n        int base = max(1, (int)floor(ideal));\n        sz[i] = base;\n        used += base;\n        frac.push_back({ideal - base, i});\n    }\n\n    if (used > W) {\n        vector<int> ord(R);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) { return sz[a] > sz[b]; });\n        int need = used - W;\n        for (int id : ord) {\n            int dec = min(need, sz[id] - 1);\n            sz[id] -= dec;\n            need -= dec;\n            if (need == 0) break;\n        }\n    } else if (used < W) {\n        int need = W - used;\n        sort(frac.begin(), frac.end(), greater<>());\n        for (int i = 0; i < need; i++) sz[frac[i % R].second]++;\n    }\n    return sz;\n}\n\nstatic vector<int> uniform_sizes(int R) {\n    vector<int> h(R, W / R);\n    for (int i = 0; i < W % R; i++) h[i]++;\n    return h;\n}\n\nstatic pair<ll, vector<int>> optimize_strip_day_fixed_h(\n    const vector<vector<int>>& actual,\n    int d, int l, int r, int h,\n    int local_passes\n) {\n    int m = r - l;\n    vector<int> width(m, 1);\n    int rem = W - m;\n\n    vector<vector<int>> gain(m, vector<int>(W, 0));\n    for (int z = 0; z < m; z++) {\n        int need = actual[d][l + z];\n        for (int t = 0; t < W; t++) {\n            int c0 = h * t;\n            int c1 = h * (t + 1);\n            gain[z][t] = max(0, need - c0) - max(0, need - c1);\n        }\n    }\n\n    using T = pair<int,int>;\n    priority_queue<T> pq;\n    for (int z = 0; z < m; z++) pq.push({gain[z][1], z});\n\n    while (rem > 0) {\n        auto [g, z] = pq.top(); pq.pop();\n        int t = width[z];\n        int realg = (t < W ? gain[z][t] : 0);\n        if (g != realg) {\n            pq.push({realg, z});\n            continue;\n        }\n        width[z]++;\n        rem--;\n        t = width[z];\n        pq.push({(t < W ? gain[z][t] : 0), z});\n    }\n\n    vector<ll> curmiss(m);\n    for (int z = 0; z < m; z++) curmiss[z] = miss_need_cap(actual[d][l + z], h * width[z]);\n\n    for (int pass = 0; pass < local_passes; pass++) {\n        ll best_delta = 0;\n        int bi = -1, bj = -1;\n        for (int i = 0; i < m; i++) {\n            if (width[i] <= 1) continue;\n            ll mi_new = miss_need_cap(actual[d][l + i], h * (width[i] - 1));\n            for (int j = 0; j < m; j++) if (i != j) {\n                ll mj_new = miss_need_cap(actual[d][l + j], h * (width[j] + 1));\n                ll delta = (mi_new + mj_new) - (curmiss[i] + curmiss[j]);\n                if (delta < best_delta) {\n                    best_delta = delta;\n                    bi = i;\n                    bj = j;\n                }\n            }\n        }\n        if (best_delta < 0) {\n            width[bi]--;\n            width[bj]++;\n            curmiss[bi] = miss_need_cap(actual[d][l + bi], h * width[bi]);\n            curmiss[bj] = miss_need_cap(actual[d][l + bj], h * width[bj]);\n        } else {\n            break;\n        }\n    }\n\n    ll miss = 0;\n    for (int z = 0; z < m; z++) miss += curmiss[z];\n    return {miss, width};\n}\n\nstatic DayLayout build_day_layout_fixed_heights(\n    const vector<vector<int>>& actual,\n    int d,\n    const vector<int>& cuts,\n    int orientation,\n    const vector<int>& h,\n    int local_passes\n) {\n    int N = (int)actual[0].size();\n    int R = (int)cuts.size() - 1;\n\n    DayLayout dl;\n    dl.rects.assign(N, {0,0,1,1});\n    dl.outer.assign(R + 1, 0);\n    for (int g = 0; g < R; g++) dl.outer[g + 1] = dl.outer[g] + h[g];\n    dl.inner_pref.resize(R);\n\n    ll miss = 0;\n    for (int g = 0; g < R; g++) {\n        int l = cuts[g], r = cuts[g + 1];\n        auto [mcur, wcur] = optimize_strip_day_fixed_h(actual, d, l, r, h[g], local_passes);\n        miss += mcur;\n        int m = r - l;\n        dl.inner_pref[g].assign(m + 1, 0);\n        for (int z = 0; z < m; z++) dl.inner_pref[g][z + 1] = dl.inner_pref[g][z] + wcur[z];\n    }\n\n    for (int g = 0; g < R; g++) {\n        int l = cuts[g], r = cuts[g + 1];\n        int o0 = dl.outer[g], o1 = dl.outer[g + 1];\n        for (int z = 0; z < r - l; z++) {\n            int x0 = dl.inner_pref[g][z];\n            int x1 = dl.inner_pref[g][z + 1];\n            if (orientation == 0) dl.rects[l + z] = {o0, x0, o1, x1};\n            else dl.rects[l + z] = {x0, o0, x1, o1};\n        }\n    }\n\n    dl.penalty = miss * 100;\n    return dl;\n}\n\nstatic ll transition_cost_same_topology(\n    const DayLayout& A,\n    const DayLayout& B,\n    const vector<int>& cuts\n) {\n    int R = (int)cuts.size() - 1;\n    ll cost = 0;\n    for (int g = 1; g < R; g++) {\n        if (A.outer[g] != B.outer[g]) cost += 2LL * W;\n    }\n    for (int g = 0; g < R; g++) {\n        int m = cuts[g + 1] - cuts[g];\n        int a0 = A.outer[g], a1 = A.outer[g + 1];\n        int b0 = B.outer[g], b1 = B.outer[g + 1];\n        int hA = a1 - a0, hB = b1 - b0;\n        for (int z = 1; z < m; z++) {\n            int xA = A.inner_pref[g][z];\n            int xB = B.inner_pref[g][z];\n            if (xA == xB) cost += abs(a0 - b0) + abs(a1 - b1);\n            else cost += hA + hB;\n        }\n    }\n    return cost;\n}\n\nstatic Answer solve_static(\n    const vector<vector<int>>& a,\n    const vector<int>& cuts,\n    int orientation\n) {\n    int D = (int)a.size();\n    int N = (int)a[0].size();\n    int R = (int)cuts.size() - 1;\n\n    vector<ll> agg_group(R, 0);\n    for (int g = 0; g < R; g++) {\n        for (int d = 0; d < D; d++) for (int k = cuts[g]; k < cuts[g + 1]; k++) agg_group[g] += a[d][k];\n    }\n    vector<int> h = normalize_sizes_from_weights(agg_group);\n\n    vector<vector<int>> agg(1, vector<int>(N, 0));\n    for (int d = 0; d < D; d++) for (int k = 0; k < N; k++) agg[0][k] += a[d][k];\n    DayLayout base = build_day_layout_fixed_heights(agg, 0, cuts, orientation, h, 1);\n\n    Answer ans;\n    ans.days.assign(D, vector<Rect>(N));\n    ll total = 0;\n    for (int d = 0; d < D; d++) {\n        ll miss = 0;\n        for (int k = 0; k < N; k++) {\n            const auto& r = base.rects[k];\n            int area = (r.i1 - r.i0) * (r.j1 - r.j0);\n            if (a[d][k] > area) miss += a[d][k] - area;\n            ans.days[d][k] = r;\n        }\n        total += miss * 100;\n    }\n    ans.total_cost = total;\n    return ans;\n}\n\nstatic Answer solve_dynamic_independent(\n    const vector<vector<int>>& a,\n    const vector<int>& cuts,\n    int orientation\n) {\n    int D = (int)a.size();\n    int N = (int)a[0].size();\n    int R = (int)cuts.size() - 1;\n\n    vector<DayLayout> days(D);\n    Answer ans;\n    ans.days.assign(D, vector<Rect>(N));\n    ll total = 0;\n\n    for (int d = 0; d < D; d++) {\n        vector<ll> w(R, 0);\n        for (int g = 0; g < R; g++) {\n            for (int k = cuts[g]; k < cuts[g + 1]; k++) w[g] += a[d][k];\n        }\n        vector<int> h = normalize_sizes_from_weights(w);\n        days[d] = build_day_layout_fixed_heights(a, d, cuts, orientation, h, 1);\n        total += days[d].penalty;\n        ans.days[d] = days[d].rects;\n    }\n    for (int d = 1; d < D; d++) total += transition_cost_same_topology(days[d - 1], days[d], cuts);\n\n    ans.total_cost = total;\n    return ans;\n}\n\nstatic vector<int> make_group_heights(\n    const vector<vector<int>>& a,\n    const vector<int>& cuts,\n    int d,\n    int mode,\n    const vector<int>& static_heights,\n    const vector<int>& max_heights\n) {\n    int D = (int)a.size();\n    int R = (int)cuts.size() - 1;\n    if (mode == 4) return uniform_sizes(R);\n    if (mode == 5) return static_heights;\n    if (mode == 6) return max_heights;\n\n    vector<ll> w(R, 0);\n    auto add_day = [&](int day, int mul) {\n        if (day < 0 || day >= D) return;\n        for (int g = 0; g < R; g++) {\n            ll s = 0;\n            for (int k = cuts[g]; k < cuts[g + 1]; k++) s += a[day][k];\n            w[g] += 1LL * mul * s;\n        }\n    };\n\n    if (mode == 0) add_day(d, 100);\n    else if (mode == 1) { add_day(d - 1, 100); add_day(d, 100); }\n    else if (mode == 2) { add_day(d, 100); add_day(d + 1, 100); }\n    else { add_day(d - 1, 100); add_day(d, 100); add_day(d + 1, 100); }\n\n    return normalize_sizes_from_weights(w);\n}\n\nstatic Answer solve_dynamic_dp_heights(\n    const vector<vector<int>>& a,\n    const vector<int>& cuts,\n    int orientation\n) {\n    int D = (int)a.size();\n    int N = (int)a[0].size();\n    int R = (int)cuts.size() - 1;\n\n    vector<ll> agg_group(R, 0), mx_group(R, 0);\n    for (int g = 0; g < R; g++) {\n        for (int d = 0; d < D; d++) {\n            ll s = 0;\n            for (int k = cuts[g]; k < cuts[g + 1]; k++) s += a[d][k];\n            agg_group[g] += s;\n            mx_group[g] = max(mx_group[g], s);\n        }\n    }\n    vector<int> static_heights = normalize_sizes_from_weights(agg_group);\n    vector<int> max_heights = normalize_sizes_from_weights(mx_group);\n\n    vector<vector<DayLayout>> cand(D);\n\n    for (int d = 0; d < D; d++) {\n        vector<vector<int>> hs;\n        for (int mode = 0; mode < 7; mode++) hs.push_back(make_group_heights(a, cuts, d, mode, static_heights, max_heights));\n        sort(hs.begin(), hs.end());\n        hs.erase(unique(hs.begin(), hs.end()), hs.end());\n\n        cand[d].reserve(hs.size());\n        for (auto& h : hs) cand[d].push_back(build_day_layout_fixed_heights(a, d, cuts, orientation, h, 2));\n\n        sort(cand[d].begin(), cand[d].end(), [&](const DayLayout& A, const DayLayout& B) {\n            return A.penalty < B.penalty;\n        });\n        if ((int)cand[d].size() > 8) cand[d].resize(8);\n    }\n\n    vector<vector<ll>> dp(D);\n    vector<vector<int>> pre(D);\n    for (int d = 0; d < D; d++) {\n        int M = (int)cand[d].size();\n        dp[d].assign(M, INF64);\n        pre[d].assign(M, -1);\n    }\n\n    for (int i = 0; i < (int)cand[0].size(); i++) dp[0][i] = cand[0][i].penalty;\n\n    for (int d = 1; d < D; d++) {\n        for (int j = 0; j < (int)cand[d].size(); j++) {\n            ll add = cand[d][j].penalty;\n            for (int i = 0; i < (int)cand[d - 1].size(); i++) {\n                ll tr = transition_cost_same_topology(cand[d - 1][i], cand[d][j], cuts);\n                ll val = dp[d - 1][i] + tr + add;\n                if (val < dp[d][j]) {\n                    dp[d][j] = val;\n                    pre[d][j] = i;\n                }\n            }\n        }\n    }\n\n    int best_last = 0;\n    for (int i = 1; i < (int)cand[D - 1].size(); i++) {\n        if (dp[D - 1][i] < dp[D - 1][best_last]) best_last = i;\n    }\n\n    vector<int> path(D);\n    path[D - 1] = best_last;\n    for (int d = D - 1; d >= 1; d--) path[d - 1] = pre[d][path[d]];\n\n    Answer ans;\n    ans.total_cost = dp[D - 1][best_last];\n    ans.days.assign(D, vector<Rect>(N));\n    for (int d = 0; d < D; d++) ans.days[d] = cand[d][path[d]].rects;\n    return ans;\n}\n\nstatic vector<int> balanced_cuts_from_prefix(const vector<ll>& pref, int N, int R) {\n    vector<int> cuts;\n    cuts.push_back(0);\n    for (int t = 1; t < R; t++) {\n        ll target = pref[N] * t / R;\n        int pos = (int)(lower_bound(pref.begin(), pref.end(), target) - pref.begin());\n        pos = max(pos, cuts.back() + 1);\n        pos = min(pos, N - (R - t));\n        cuts.push_back(pos);\n    }\n    cuts.push_back(N);\n    return cuts;\n}\n\nstatic vector<int> equal_cuts(int N, int R) {\n    vector<int> cuts(R + 1);\n    cuts[0] = 0;\n    cuts[R] = N;\n    for (int t = 1; t < R; t++) cuts[t] = (int)((ll)N * t / R);\n    for (int t = 1; t < R; t++) cuts[t] = max(cuts[t], cuts[t - 1] + 1);\n    for (int t = R - 1; t >= 1; t--) cuts[t] = min(cuts[t], cuts[t + 1] - 1);\n    return cuts;\n}\n\nstatic vector<int> dp_cuts_from_weights(const vector<ll>& w, int R) {\n    int N = (int)w.size();\n    vector<ll> pref(N + 1, 0);\n    for (int i = 0; i < N; i++) pref[i + 1] = pref[i] + w[i];\n    double target = (double)pref[N] / R;\n\n    const double INF = 1e100;\n    vector<vector<double>> dp(R + 1, vector<double>(N + 1, INF));\n    vector<vector<int>> pre(R + 1, vector<int>(N + 1, -1));\n    dp[0][0] = 0.0;\n\n    for (int g = 0; g < R; g++) {\n        for (int i = 0; i <= N; i++) {\n            if (dp[g][i] >= INF / 2) continue;\n            int minj = i + 1;\n            int maxj = N - (R - g - 1);\n            for (int j = minj; j <= maxj; j++) {\n                double sum = (double)(pref[j] - pref[i]);\n                double cost = (sum - target) * (sum - target);\n                double ndp = dp[g][i] + cost;\n                if (ndp < dp[g + 1][j]) {\n                    dp[g + 1][j] = ndp;\n                    pre[g + 1][j] = i;\n                }\n            }\n        }\n    }\n\n    vector<int> cuts(R + 1);\n    cuts[R] = N;\n    int cur = N;\n    for (int g = R; g >= 1; g--) {\n        cuts[g - 1] = pre[g][cur];\n        cur = cuts[g - 1];\n    }\n    return cuts;\n}\n\nstatic bool too_similar(const TopoCand& a, const TopoCand& b) {\n    if ((int)a.cuts.size() != (int)b.cuts.size()) return false;\n    if (a.orientation != b.orientation) return false;\n    int R = (int)a.cuts.size() - 1;\n    int maxdiff = 0, sumdiff = 0;\n    for (int i = 1; i < R; i++) {\n        int d = abs(a.cuts[i] - b.cuts[i]);\n        maxdiff = max(maxdiff, d);\n        sumdiff += d;\n    }\n    return maxdiff <= 1 && sumdiff <= 2;\n}\n\nstatic vector<TopoCand> select_top_nonredundant(const vector<TopoCand>& pool, int want, int scan_limit) {\n    vector<TopoCand> res;\n    int lim = min<int>(scan_limit, pool.size());\n    for (int i = 0; i < lim; i++) {\n        bool ok = true;\n        for (auto& s : res) {\n            if (too_similar(pool[i], s)) {\n                ok = false;\n                break;\n            }\n        }\n        if (ok) res.push_back(pool[i]);\n        if ((int)res.size() >= want) break;\n    }\n    for (int i = 0; i < lim && (int)res.size() < want; i++) {\n        bool already = false;\n        for (auto& s : res) {\n            if (pool[i].cuts == s.cuts && pool[i].orientation == s.orientation && pool[i].cheap_score == s.cheap_score) {\n                already = true;\n                break;\n            }\n        }\n        if (!already) res.push_back(pool[i]);\n    }\n    return res;\n}\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_ms = [&]() -> double {\n        return chrono::duration<double, milli>(chrono::steady_clock::now() - start_time).count();\n    };\n\n    int Win, D, N;\n    cin >> Win >> D >> N;\n    vector<vector<int>> a(D, vector<int>(N));\n    for (int d = 0; d < D; d++) for (int k = 0; k < N; k++) cin >> a[d][k];\n\n    vector<ll> sumw(N, 0), maxw(N, 0), earlyw(N, 0), latew(N, 0);\n    for (int k = 0; k < N; k++) {\n        for (int d = 0; d < D; d++) {\n            sumw[k] += a[d][k];\n            maxw[k] = max<ll>(maxw[k], a[d][k]);\n            earlyw[k] += 1LL * (D - d) * a[d][k];\n            latew[k] += 1LL * (d + 1) * a[d][k];\n        }\n    }\n\n    auto prefix_of = [&](const vector<ll>& w) {\n        vector<ll> pref(N + 1, 0);\n        for (int i = 0; i < N; i++) pref[i + 1] = pref[i] + w[i];\n        return pref;\n    };\n\n    vector<vector<ll>> weight_sets = {sumw, maxw, earlyw, latew};\n\n    Answer best;\n    vector<TopoCand> pool;\n\n    int maxR = min(N, 5);\n    for (int R = 1; R <= maxR; R++) {\n        vector<vector<int>> candidates;\n        if (R == 1) {\n            candidates.push_back({0, N});\n        } else {\n            candidates.push_back(equal_cuts(N, R));\n            for (const auto& w : weight_sets) {\n                auto pref = prefix_of(w);\n                candidates.push_back(balanced_cuts_from_prefix(pref, N, R));\n                candidates.push_back(dp_cuts_from_weights(w, R));\n            }\n            int base_sz = (int)candidates.size();\n            for (int id = 0; id < base_sz; id++) {\n                auto c0 = candidates[id];\n                for (int idx = 1; idx < R; idx++) {\n                    for (int dlt : {-1, +1}) {\n                        auto c = c0;\n                        c[idx] += dlt;\n                        bool ok = true;\n                        for (int i = 1; i < R; i++) {\n                            if (!(c[i - 1] < c[i] && c[i] < c[i + 1])) { ok = false; break; }\n                        }\n                        if (ok) candidates.push_back(c);\n                    }\n                }\n            }\n        }\n\n        sort(candidates.begin(), candidates.end());\n        candidates.erase(unique(candidates.begin(), candidates.end()), candidates.end());\n\n        for (const auto& cuts : candidates) {\n            for (int orientation = 0; orientation < 2; orientation++) {\n                Answer cur_static = solve_static(a, cuts, orientation);\n                if (cur_static.total_cost < best.total_cost) best = cur_static;\n\n                Answer cur_dyn = solve_dynamic_independent(a, cuts, orientation);\n                if (cur_dyn.total_cost < best.total_cost) best = cur_dyn;\n                pool.push_back({cuts, orientation, cur_dyn.total_cost});\n\n                if (elapsed_ms() > 2100.0) break;\n            }\n            if (elapsed_ms() > 2100.0) break;\n        }\n        if (elapsed_ms() > 2100.0) break;\n    }\n\n    sort(pool.begin(), pool.end(), [&](const TopoCand& x, const TopoCand& y) {\n        return x.cheap_score < y.cheap_score;\n    });\n\n    vector<TopoCand> refine_list = select_top_nonredundant(pool, 10, 35);\n\n    for (auto& tc : refine_list) {\n        if (elapsed_ms() > 2750.0) break;\n        Answer cur = solve_dynamic_dp_heights(a, tc.cuts, tc.orientation);\n        if (cur.total_cost < best.total_cost) best = move(cur);\n    }\n\n    for (int d = 0; d < D; d++) {\n        for (int k = 0; k < N; k++) {\n            const auto& r = best.days[d][k];\n            cout << r.i0 << ' ' << r.j0 << ' ' << r.i1 << ' ' << r.j1 << '\\n';\n        }\n    }\n    return 0;\n}","ahc032":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 9;\nstatic constexpr int POS = 7;\nstatic constexpr int MOD = 998244353;\nstatic constexpr int MAXK = 81;\n\nstruct Timer {\n    chrono::steady_clock::time_point st;\n    Timer() : st(chrono::steady_clock::now()) {}\n    double ms() const {\n        return chrono::duration<double, milli>(chrono::steady_clock::now() - st).count();\n    }\n};\n\nstruct RNG {\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    double rand01() {\n        return (next() >> 11) * (1.0 / (1ULL << 53));\n    }\n} rng;\n\nusing Board = array<int, 81>;\n\nstruct Action {\n    int m, p, q;\n    int idx[9];\n    int add[9];\n};\n\nstruct Candidate {\n    long long gain;\n    int act;\n};\n\nstruct Node {\n    Board b;\n    long long score;\n    long long eval;\n    vector<unsigned short> seq;\n};\n\nvector<Action> actions;\n\nstatic inline long long cell_gain(int cur, int add) {\n    int x = cur + add;\n    return (x >= MOD) ? (long long)add - MOD : (long long)add;\n}\n\nstatic inline long long action_gain(const Board& b, int act_id) {\n    const Action& a = actions[act_id];\n    long long g = 0;\n    for (int k = 0; k < 9; k++) g += cell_gain(b[a.idx[k]], a.add[k]);\n    return g;\n}\n\nstatic inline void apply_action(Board& b, int act_id) {\n    const Action& a = actions[act_id];\n    for (int k = 0; k < 9; k++) {\n        int &v = b[a.idx[k]];\n        v += a.add[k];\n        if (v >= MOD) v -= MOD;\n    }\n}\n\nvector<Candidate> top_actions(const Board& b, int need, int extra_random = 0) {\n    vector<Candidate> cand;\n    cand.reserve(actions.size());\n    for (int i = 0; i < (int)actions.size(); i++) {\n        long long g = action_gain(b, i);\n        if (g > 0) cand.push_back({g, i});\n    }\n    if (cand.empty()) return cand;\n\n    int keep = min((int)cand.size(), max(need, need + extra_random));\n    nth_element(cand.begin(), cand.begin() + keep - 1, cand.end(),\n        [](const Candidate& a, const Candidate& b) {\n            return a.gain > b.gain;\n        });\n    cand.resize(keep);\n    sort(cand.begin(), cand.end(), [](const Candidate& a, const Candidate& b) {\n        if (a.gain != b.gain) return a.gain > b.gain;\n        return a.act < b.act;\n    });\n\n    if ((int)cand.size() <= need) return cand;\n\n    vector<Candidate> res;\n    res.reserve(need);\n    int fixed = max(1, need / 2);\n    for (int i = 0; i < fixed; i++) res.push_back(cand[i]);\n\n    vector<int> ids;\n    for (int i = fixed; i < (int)cand.size(); i++) ids.push_back(i);\n    while ((int)res.size() < need && !ids.empty()) {\n        int pos = rng.randint(0, (int)ids.size() - 1);\n        res.push_back(cand[ids[pos]]);\n        ids[pos] = ids.back();\n        ids.pop_back();\n    }\n    return res;\n}\n\nlong long best_single_gain(const Board& b) {\n    long long best = 0;\n    for (int i = 0; i < (int)actions.size(); i++) {\n        long long g = action_gain(b, i);\n        if (g > best) best = g;\n    }\n    return best;\n}\n\nvector<int> greedy_complete(Board b, int remain, bool randomized) {\n    vector<int> seq;\n    seq.reserve(remain);\n\n    for (int step = 0; step < remain; step++) {\n        auto cand = top_actions(b, randomized ? 12 : 24, randomized ? 20 : 0);\n        if (cand.empty()) break;\n\n        long long bestEval = LLONG_MIN;\n        int bestAct = -1;\n\n        for (auto &c : cand) {\n            Board nb = b;\n            apply_action(nb, c.act);\n            long long g2 = best_single_gain(nb);\n            long long eval = c.gain + g2;\n            if (randomized) eval += rng.randint(0, 1000);\n            if (eval > bestEval) {\n                bestEval = eval;\n                bestAct = c.act;\n            }\n        }\n\n        if (bestAct < 0) break;\n        apply_action(b, bestAct);\n        seq.push_back(bestAct);\n    }\n\n    return seq;\n}\n\npair<long long, Board> eval_sequence(const Board& init, const vector<int>& seq, bool stop_on_nonpos = true) {\n    Board b = init;\n    long long total = 0;\n    for (int act : seq) {\n        long long g = action_gain(b, act);\n        if (stop_on_nonpos && g <= 0) break;\n        apply_action(b, act);\n        total += g;\n    }\n    return {total, b};\n}\n\nvector<int> construct_solution(const Board& initial, const Timer& timer, double soft_limit_ms) {\n    int BEAM_WIDTH = 48;\n    int BRANCH = 14;\n    int DEPTH = 11;\n\n    vector<Node> beam, nxt;\n    beam.reserve(BEAM_WIDTH);\n    nxt.reserve(BEAM_WIDTH * BRANCH);\n\n    Node root;\n    root.b = initial;\n    root.score = 0;\n    root.eval = 0;\n    beam.push_back(root);\n\n    for (int d = 0; d < DEPTH; d++) {\n        if (timer.ms() > soft_limit_ms) break;\n        nxt.clear();\n\n        for (const auto& node : beam) {\n            auto cand = top_actions(node.b, BRANCH, 16);\n            if (cand.empty()) {\n                nxt.push_back(node);\n                continue;\n            }\n            for (auto &c : cand) {\n                Node child;\n                child.b = node.b;\n                apply_action(child.b, c.act);\n                child.score = node.score + c.gain;\n                child.seq = node.seq;\n                child.seq.push_back((unsigned short)c.act);\n                long long h = best_single_gain(child.b);\n                child.eval = child.score + h;\n                nxt.push_back(std::move(child));\n            }\n        }\n\n        if (nxt.empty()) break;\n\n        int keep = min((int)nxt.size(), BEAM_WIDTH);\n        nth_element(nxt.begin(), nxt.begin() + keep - 1, nxt.end(),\n            [](const Node& a, const Node& b) {\n                if (a.eval != b.eval) return a.eval > b.eval;\n                return a.score > b.score;\n            });\n        nxt.resize(keep);\n        sort(nxt.begin(), nxt.end(), [](const Node& a, const Node& b) {\n            if (a.eval != b.eval) return a.eval > b.eval;\n            return a.score > b.score;\n        });\n        beam.swap(nxt);\n    }\n\n    long long bestScore = LLONG_MIN;\n    vector<int> bestSeq;\n\n    int trial_from_beam = min(10, (int)beam.size());\n    for (int i = 0; i < trial_from_beam; i++) {\n        if (timer.ms() > soft_limit_ms) break;\n\n        vector<int> seq;\n        seq.reserve(MAXK);\n        for (auto x : beam[i].seq) seq.push_back((int)x);\n\n        auto [prefixScore, b] = eval_sequence(initial, seq, true);\n        auto tail = greedy_complete(b, MAXK - (int)seq.size(), true);\n        seq.insert(seq.end(), tail.begin(), tail.end());\n\n        auto [fullScore, _] = eval_sequence(initial, seq, true);\n        if (fullScore > bestScore) {\n            bestScore = fullScore;\n            bestSeq = seq;\n        }\n    }\n\n    while (timer.ms() < soft_limit_ms) {\n        auto seq = greedy_complete(initial, MAXK, true);\n        auto [score, _] = eval_sequence(initial, seq, true);\n        if (score > bestScore) {\n            bestScore = score;\n            bestSeq = seq;\n        } else if (bestSeq.empty()) {\n            bestSeq = seq;\n            bestScore = score;\n        }\n    }\n\n    return bestSeq;\n}\n\nvoid rebuild_prefix_data(const Board& initial, const vector<int>& seq, vector<Board>& pref) {\n    pref.resize(seq.size() + 1);\n    pref[0] = initial;\n    int real_len = 0;\n    for (int i = 0; i < (int)seq.size(); i++) {\n        pref[i + 1] = pref[i];\n        long long g = action_gain(pref[i + 1], seq[i]);\n        if (g <= 0) break;\n        apply_action(pref[i + 1], seq[i]);\n        real_len = i + 1;\n    }\n    pref.resize(real_len + 1);\n}\n\nint sample_early_biased(int len_exclusive) {\n    if (len_exclusive <= 1) return 0;\n    double u = rng.rand01();\n    int t = (int)(u * u * len_exclusive);\n    if (t < 0) t = 0;\n    if (t >= len_exclusive) t = len_exclusive - 1;\n    return t;\n}\n\nbool deterministic_prefix_repair(const Board& initial, vector<int>& bestSeq, long long& bestScore, double deadline_ms, const Timer& timer) {\n    vector<Board> pref;\n    rebuild_prefix_data(initial, bestSeq, pref);\n    int len = (int)pref.size() - 1;\n    if (len <= 0) return false;\n\n    bool improved = false;\n    int LIMIT_T = min(len, 12);\n\n    for (int t = 0; t < LIMIT_T; t++) {\n        if (timer.ms() > deadline_ms) break;\n\n        Board b = pref[t];\n        vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n\n        // rebuild suffix only\n        {\n            vector<int> seq = prefix;\n            auto tail = greedy_complete(b, MAXK - (int)seq.size(), false);\n            seq.insert(seq.end(), tail.begin(), tail.end());\n            auto [score, _] = eval_sequence(initial, seq, true);\n            if (score > bestScore) {\n                bestScore = score;\n                bestSeq = std::move(seq);\n                rebuild_prefix_data(initial, bestSeq, pref);\n                len = (int)pref.size() - 1;\n                improved = true;\n                if (t >= len) break;\n                b = pref[t];\n                prefix.assign(bestSeq.begin(), bestSeq.begin() + t);\n            }\n        }\n\n        if (timer.ms() > deadline_ms) break;\n\n        // replace one move at t\n        auto cand = top_actions(b, 8, 0);\n        for (auto &c : cand) {\n            if (timer.ms() > deadline_ms) break;\n            Board nb = b;\n            long long g = action_gain(nb, c.act);\n            if (g <= 0) continue;\n            apply_action(nb, c.act);\n\n            vector<int> seq = prefix;\n            seq.push_back(c.act);\n            auto tail = greedy_complete(nb, MAXK - (int)seq.size(), false);\n            seq.insert(seq.end(), tail.begin(), tail.end());\n\n            auto [score, _] = eval_sequence(initial, seq, true);\n            if (score > bestScore) {\n                bestScore = score;\n                bestSeq = std::move(seq);\n                rebuild_prefix_data(initial, bestSeq, pref);\n                len = (int)pref.size() - 1;\n                improved = true;\n                break;\n            }\n        }\n    }\n    return improved;\n}\n\nvoid local_improve(const Board& initial, vector<int>& bestSeq, long long& bestScore,\n                   const Timer& timer, double time_limit_ms) {\n    if (bestSeq.empty()) return;\n\n    vector<Board> pref;\n    rebuild_prefix_data(initial, bestSeq, pref);\n\n    while (timer.ms() < time_limit_ms) {\n        int len = (int)pref.size() - 1;\n        if (len <= 0) break;\n\n        int t = sample_early_biased(len);\n        Board b = pref[t];\n\n        int mode = rng.randint(0, 99);\n\n        // Rebuild suffix\n        if (mode < 30) {\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            auto seq = prefix;\n            auto tail = greedy_complete(b, MAXK - (int)seq.size(), true);\n            seq.insert(seq.end(), tail.begin(), tail.end());\n\n            auto [score, _] = eval_sequence(initial, seq, true);\n            if (score > bestScore) {\n                bestScore = score;\n                bestSeq = std::move(seq);\n                rebuild_prefix_data(initial, bestSeq, pref);\n            }\n            continue;\n        }\n\n        // Replace one move\n        if (mode < 75) {\n            auto cand = top_actions(b, 10, 12);\n            if (cand.empty()) continue;\n\n            vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n            long long localBest = bestScore;\n            vector<int> localBestSeq;\n\n            for (auto &c : cand) {\n                if (timer.ms() > time_limit_ms) break;\n\n                Board nb = b;\n                long long g = action_gain(nb, c.act);\n                if (g <= 0) continue;\n                apply_action(nb, c.act);\n\n                vector<int> seq = prefix;\n                seq.push_back(c.act);\n\n                auto tail = greedy_complete(nb, MAXK - (int)seq.size(), true);\n                seq.insert(seq.end(), tail.begin(), tail.end());\n\n                auto [score, _] = eval_sequence(initial, seq, true);\n                if (score > localBest) {\n                    localBest = score;\n                    localBestSeq = std::move(seq);\n                }\n            }\n\n            if (!localBestSeq.empty()) {\n                bestScore = localBest;\n                bestSeq = std::move(localBestSeq);\n                rebuild_prefix_data(initial, bestSeq, pref);\n            }\n            continue;\n        }\n\n        // Replace two moves\n        auto firsts = top_actions(b, 6, 8);\n        if (firsts.empty()) continue;\n\n        vector<int> prefix(bestSeq.begin(), bestSeq.begin() + t);\n        long long localBest = bestScore;\n        vector<int> localBestSeq;\n\n        for (auto &c1 : firsts) {\n            if (timer.ms() > time_limit_ms) break;\n            Board b1 = b;\n            long long g1 = action_gain(b1, c1.act);\n            if (g1 <= 0) continue;\n            apply_action(b1, c1.act);\n\n            auto seconds = top_actions(b1, 5, 6);\n\n            {\n                vector<int> seq = prefix;\n                seq.push_back(c1.act);\n                auto tail = greedy_complete(b1, MAXK - (int)seq.size(), true);\n                seq.insert(seq.end(), tail.begin(), tail.end());\n                auto [score, _] = eval_sequence(initial, seq, true);\n                if (score > localBest) {\n                    localBest = score;\n                    localBestSeq = std::move(seq);\n                }\n            }\n\n            for (auto &c2 : seconds) {\n                if (timer.ms() > time_limit_ms) break;\n                Board b2 = b1;\n                long long g2 = action_gain(b2, c2.act);\n                if (g2 <= 0) continue;\n                apply_action(b2, c2.act);\n\n                vector<int> seq = prefix;\n                seq.push_back(c1.act);\n                seq.push_back(c2.act);\n\n                auto tail = greedy_complete(b2, MAXK - (int)seq.size(), true);\n                seq.insert(seq.end(), tail.begin(), tail.end());\n\n                auto [score, _] = eval_sequence(initial, seq, true);\n                if (score > localBest) {\n                    localBest = score;\n                    localBestSeq = std::move(seq);\n                }\n            }\n        }\n\n        if (!localBestSeq.empty()) {\n            bestScore = localBest;\n            bestSeq = std::move(localBestSeq);\n            rebuild_prefix_data(initial, bestSeq, pref);\n        }\n    }\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin, Min, Kin;\n    cin >> Nin >> Min >> Kin;\n\n    Board initial{};\n    for (int i = 0; i < Nin; i++) {\n        for (int j = 0; j < Nin; j++) {\n            cin >> initial[i * N + j];\n        }\n    }\n\n    vector<array<array<int,3>,3>> stamps(Min);\n    for (int m = 0; m < Min; m++) {\n        for (int i = 0; i < 3; i++) {\n            for (int j = 0; j < 3; j++) {\n                cin >> stamps[m][i][j];\n            }\n        }\n    }\n\n    actions.clear();\n    actions.reserve(Min * 49);\n    for (int m = 0; m < Min; m++) {\n        for (int p = 0; p < 7; p++) {\n            for (int q = 0; q < 7; q++) {\n                Action a;\n                a.m = m;\n                a.p = p;\n                a.q = q;\n                int t = 0;\n                for (int i = 0; i < 3; i++) {\n                    for (int j = 0; j < 3; j++) {\n                        a.idx[t] = (p + i) * 9 + (q + j);\n                        a.add[t] = stamps[m][i][j];\n                        t++;\n                    }\n                }\n                actions.push_back(a);\n            }\n        }\n    }\n\n    Timer timer;\n    const double TOTAL_LIMIT = 1850.0;\n\n    vector<pair<long long, vector<int>>> elites;\n\n    while (timer.ms() < TOTAL_LIMIT * 0.42) {\n        auto seq = construct_solution(initial, timer, min(TOTAL_LIMIT * 0.42, TOTAL_LIMIT - 350.0));\n        auto [score, _] = eval_sequence(initial, seq, true);\n\n        elites.push_back({score, seq});\n        sort(elites.begin(), elites.end(), [](auto& a, auto& b) { return a.first > b.first; });\n        if ((int)elites.size() > 4) elites.resize(4);\n    }\n\n    if (elites.empty()) {\n        auto seq = greedy_complete(initial, MAXK, false);\n        auto [score, _] = eval_sequence(initial, seq, true);\n        elites.push_back({score, seq});\n    }\n\n    long long globalBestScore = -1;\n    vector<int> globalBestSeq;\n\n    int E = elites.size();\n    for (int i = 0; i < E; i++) {\n        auto seq = elites[i].second;\n        long long score = elites[i].first;\n\n        double chunk_end = TOTAL_LIMIT * (0.42 + (0.58 * (i + 1) / E));\n\n        // deterministic early-prefix repair first\n        deterministic_prefix_repair(initial, seq, score, min(chunk_end, timer.ms() + 120.0), timer);\n\n        // then randomized local improvement\n        local_improve(initial, seq, score, timer, chunk_end);\n\n        if (score > globalBestScore) {\n            globalBestScore = score;\n            globalBestSeq = std::move(seq);\n        }\n    }\n\n    if ((int)globalBestSeq.size() > Kin) globalBestSeq.resize(Kin);\n\n    cout << globalBestSeq.size() << '\\n';\n    for (int act : globalBestSeq) {\n        const auto& a = actions[act];\n        cout << a.m << ' ' << a.p << ' ' << a.q << '\\n';\n    }\n    return 0;\n}","ahc033":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 5;\nstatic constexpr int TOTAL = 25;\nstatic constexpr int BASE = 6;\nstatic constexpr int PTR_STATES = 7776;\nstatic constexpr long long INF = (1LL << 60);\n\nstruct PlanResult {\n    long long score = INF;\n    vector<string> ops;\n};\n\nstatic inline int manhattan(int r1, int c1, int r2, int c2) {\n    return abs(r1 - r2) + abs(c1 - c2);\n}\n\nstruct Simulator {\n    vector<string> ans;\n    Simulator() { ans.assign(N, \"\"); }\n\n    void add_turn(char c0, char c1='.', char c2='.', char c3='.', char c4='.') {\n        ans[0].push_back(c0);\n        ans[1].push_back(c1);\n        ans[2].push_back(c2);\n        ans[3].push_back(c3);\n        ans[4].push_back(c4);\n    }\n};\n\nstatic PlanResult solve_direct_dp(const vector<vector<int>>& A) {\n    vector<array<int, N>> dec(PTR_STATES);\n    for (int s = 0; s < PTR_STATES; s++) {\n        int x = s;\n        for (int i = N - 1; i >= 0; i--) {\n            dec[s][i] = x % BASE;\n            x /= BASE;\n        }\n    }\n\n    auto encode = [&](const array<int, N>& ptr) -> int {\n        int s = 0;\n        for (int i = 0; i < N; i++) s = s * BASE + ptr[i];\n        return s;\n    };\n\n    auto pos_rc = [&](int pid) -> pair<int,int> {\n        if (pid == 0) return {0, 0};\n        return {pid - 1, 4};\n    };\n\n    vector<array<int, N>> deliveredMask(PTR_STATES);\n    for (int s = 0; s < PTR_STATES; s++) {\n        array<int, N> mask{};\n        mask.fill(0);\n        for (int in = 0; in < N; in++) {\n            for (int k = 0; k < dec[s][in]; k++) {\n                int x = A[in][k];\n                mask[x / N] |= 1 << (x % N);\n            }\n        }\n        deliveredMask[s] = mask;\n    }\n\n    vector<array<long long, 6>> dp(PTR_STATES);\n    vector<array<int, 6>> nxtRow(PTR_STATES);\n    for (int s = 0; s < PTR_STATES; s++) {\n        for (int p = 0; p < 6; p++) {\n            dp[s][p] = INF;\n            nxtRow[s][p] = -1;\n        }\n    }\n\n    array<int, N> fullPtr{};\n    fullPtr.fill(N);\n    int FULL = encode(fullPtr);\n    for (int p = 0; p < 6; p++) dp[FULL][p] = 0;\n\n    vector<vector<int>> buckets(TOTAL + 1);\n    for (int s = 0; s < PTR_STATES; s++) {\n        int sum = 0;\n        for (int i = 0; i < N; i++) sum += dec[s][i];\n        buckets[sum].push_back(s);\n    }\n\n    for (int sum = TOTAL - 1; sum >= 0; sum--) {\n        for (int s : buckets[sum]) {\n            const auto& ptr = dec[s];\n            const auto& mask = deliveredMask[s];\n\n            for (int pid = 0; pid < 6; pid++) {\n                auto [cr, cc] = pos_rc(pid);\n                long long best = INF;\n                int bestRow = -1;\n\n                for (int in = 0; in < N; in++) {\n                    if (ptr[in] >= N) continue;\n                    int x = A[in][ptr[in]];\n                    int out = x / N;\n                    int loc = x % N;\n\n                    long long add = 0;\n                    add += abs(cr - in) + abs(cc - 0);\n                    add += 1;\n                    add += abs(in - out) + 4;\n                    add += 1;\n\n                    int biggerBefore = 0;\n                    for (int b = loc + 1; b < N; b++) if (mask[out] & (1 << b)) biggerBefore++;\n                    add += 100LL * biggerBefore;\n\n                    auto nptr = ptr;\n                    nptr[in]++;\n                    int ns = encode(nptr);\n                    int npid = out + 1;\n\n                    long long cand = add + dp[ns][npid];\n                    if (cand < best) {\n                        best = cand;\n                        bestRow = in;\n                    }\n                }\n\n                dp[s][pid] = best;\n                nxtRow[s][pid] = bestRow;\n            }\n        }\n    }\n\n    vector<int> plan;\n    {\n        array<int, N> ptr{};\n        ptr.fill(0);\n        int s = encode(ptr), pid = 0;\n        while (s != FULL) {\n            int in = nxtRow[s][pid];\n            plan.push_back(in);\n            int x = A[in][dec[s][in]];\n            int out = x / N;\n            ptr = dec[s];\n            ptr[in]++;\n            s = encode(ptr);\n            pid = out + 1;\n        }\n    }\n\n    Simulator sim;\n    sim.add_turn('.', 'B', 'B', 'B', 'B');\n\n    int cr = 0, cc = 0;\n    array<int, N> ptr{};\n    ptr.fill(0);\n    array<vector<int>, N> outSeq;\n    long long turns = 1, inv = 0;\n\n    auto move = [&](int tr, int tc) {\n        while (cr < tr) { sim.add_turn('D'); cr++; turns++; }\n        while (cr > tr) { sim.add_turn('U'); cr--; turns++; }\n        while (cc < tc) { sim.add_turn('R'); cc++; turns++; }\n        while (cc > tc) { sim.add_turn('L'); cc--; turns++; }\n    };\n\n    for (int in : plan) {\n        int x = A[in][ptr[in]];\n        int out = x / N;\n\n        move(in, 0);\n        sim.add_turn('P'); turns++;\n        ptr[in]++;\n\n        move(out, 4);\n        sim.add_turn('Q'); turns++;\n\n        for (int y : outSeq[out]) if (y > x) inv++;\n        outSeq[out].push_back(x);\n    }\n\n    return {turns + 100LL * inv, sim.ans};\n}\n\nstruct Params {\n    long long wrongBufGatePenalty;\n    long long wrongDirectPenalty;\n    long long bufferBaseBonus;\n    long long directDistWeight;\n    long long bufferDistWeight;\n    long long bufferWrongNeedExtra;\n};\n\nstatic int next_need(const array<vector<int>, N>& outSeq, int r) {\n    bool used[N] = {};\n    for (int x : outSeq[r]) used[x % N] = true;\n    int m = 0;\n    while (m < N && used[m]) m++;\n    return m;\n}\n\nstatic PlanResult solve_buffer_greedy_param(const vector<vector<int>>& A, const Params& P) {\n    Simulator sim;\n    sim.add_turn('.', 'B', 'B', 'B', 'B');\n\n    array<int, N> ptr{};\n    ptr.fill(0);\n    array<int, N> buffer;\n    buffer.fill(-1);\n    array<vector<int>, N> outSeq;\n\n    int cr = 0, cc = 0;\n    long long turns = 1, inv = 0;\n    int delivered = 0;\n\n    auto move = [&](int tr, int tc) {\n        while (cr < tr) { sim.add_turn('D'); cr++; turns++; }\n        while (cr > tr) { sim.add_turn('U'); cr--; turns++; }\n        while (cc < tc) { sim.add_turn('R'); cc++; turns++; }\n        while (cc > tc) { sim.add_turn('L'); cc--; turns++; }\n    };\n\n    while (delivered < TOTAL) {\n        struct Cand {\n            long long key;\n            int type; // 0=buffer->gate, 1=src->gate, 2=src->buffer\n            int row;\n        };\n        vector<Cand> cands;\n\n        for (int r = 0; r < N; r++) {\n            if (buffer[r] == -1) continue;\n            int loc = buffer[r];\n            int need = next_need(outSeq, r);\n            long long dist = manhattan(cr, cc, r, 3);\n            long long key = P.directDistWeight * dist + 3; // move + P + R + Q\n            if (loc != need) key += P.wrongBufGatePenalty;\n            cands.push_back({key, 0, r});\n        }\n\n        for (int in = 0; in < N; in++) {\n            if (ptr[in] >= N) continue;\n            int x = A[in][ptr[in]];\n            int out = x / N;\n            int loc = x % N;\n            int need = next_need(outSeq, out);\n\n            {\n                long long dist = manhattan(cr, cc, in, 0) + manhattan(in, 0, out, 4);\n                long long key = P.directDistWeight * dist + 2;\n                if (loc != need) key += P.wrongDirectPenalty;\n                cands.push_back({key, 1, in});\n            }\n\n            if (buffer[out] == -1 && loc != need) {\n                long long dist = manhattan(cr, cc, in, 0) + manhattan(in, 0, out, 3);\n                long long key = P.bufferDistWeight * dist + 2;\n                key += P.bufferBaseBonus;\n                key += P.bufferWrongNeedExtra * abs(loc - need);\n                cands.push_back({key, 2, in});\n            }\n        }\n\n        sort(cands.begin(), cands.end(), [&](const Cand& a, const Cand& b) {\n            if (a.key != b.key) return a.key < b.key;\n            return a.type < b.type;\n        });\n\n        Cand best = cands[0];\n\n        if (best.type == 0) {\n            int r = best.row;\n            int loc = buffer[r];\n            int x = 5 * r + loc;\n\n            move(r, 3);\n            sim.add_turn('P'); turns++;\n            move(r, 4);\n            sim.add_turn('Q'); turns++;\n\n            buffer[r] = -1;\n            for (int y : outSeq[r]) if (y > x) inv++;\n            outSeq[r].push_back(x);\n            delivered++;\n        } else if (best.type == 1) {\n            int in = best.row;\n            int x = A[in][ptr[in]];\n            int out = x / N;\n\n            move(in, 0);\n            sim.add_turn('P'); turns++;\n            ptr[in]++;\n\n            move(out, 4);\n            sim.add_turn('Q'); turns++;\n\n            for (int y : outSeq[out]) if (y > x) inv++;\n            outSeq[out].push_back(x);\n            delivered++;\n        } else {\n            int in = best.row;\n            int x = A[in][ptr[in]];\n            int out = x / N;\n\n            move(in, 0);\n            sim.add_turn('P'); turns++;\n            ptr[in]++;\n\n            move(out, 3);\n            sim.add_turn('Q'); turns++;\n\n            buffer[out] = x % N;\n        }\n    }\n\n    return {turns + 100LL * inv, sim.ans};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> 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_list = {\n        // original-like\n        {1000000LL, 200000LL, 50000LL, 1LL, 1LL, 0LL},\n        // slightly stronger buffering preference\n        {1200000LL, 250000LL, 30000LL, 1LL, 1LL, 0LL},\n        // distance matters more\n        {1000000LL, 220000LL, 50000LL, 2LL, 2LL, 0LL},\n        // buffer more when badly out of order\n        {1000000LL, 220000LL, 40000LL, 1LL, 1LL, 10000LL},\n        // aggressive wrong-order punishment\n        {1500000LL, 350000LL, 20000LL, 1LL, 1LL, 5000LL},\n        // slightly prefer buffering over bad direct\n        {900000LL, 260000LL, 10000LL, 1LL, 1LL, 15000LL},\n    };\n\n    PlanResult best = solve_direct_dp(A);\n    for (const auto& p : params_list) {\n        PlanResult cand = solve_buffer_greedy_param(A, p);\n        if (cand.score < best.score) best = cand;\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (best.ops[i].empty()) cout << \".\\n\";\n        else cout << best.ops[i] << '\\n';\n    }\n    return 0;\n}","ahc034":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstatic constexpr int TURN_LIMIT = 100000;\nstatic constexpr ll INF64 = (1LL << 60);\nstatic constexpr int BIG_CAP = 1000000000;\n\nstruct Result {\n    vector<string> ops;\n    ll cost = INF64;\n    bool finished = false;\n};\n\nstruct Sim {\n    int N;\n    vector<vector<int>> h;\n    int x = 0, y = 0;\n    ll load = 0;\n    ll cost = 0;\n    vector<string> ops;\n\n    int cap;\n    int source_mode;   // 0: plain, 3: frontier\n    int sink_mode;     // 0: plain, 1: frontier\n    int source_k;      // -1 means all\n    int sink_k;        // positive small integer\n    bool use_prepass;\n\n    Sim(int n, const vector<vector<int>>& init_h, int cap_, int source_mode_, int sink_mode_, int source_k_, int sink_k_, bool use_prepass_)\n        : N(n), h(init_h), cap(cap_), source_mode(source_mode_), sink_mode(sink_mode_),\n          source_k(source_k_), sink_k(sink_k_), use_prepass(use_prepass_) {}\n\n    inline int dist(int x1, int y1, int x2, int y2) const {\n        return abs(x1 - x2) + abs(y1 - y2);\n    }\n\n    bool can_continue(int reserve = 0) const {\n        return (int)ops.size() < TURN_LIMIT - reserve;\n    }\n\n    void emit(const string& s) {\n        if ((int)ops.size() < TURN_LIMIT) ops.push_back(s);\n    }\n\n    void move_one(char c) {\n        emit(string(1, c));\n        cost += 100 + load;\n        if (c == 'U') --x;\n        else if (c == 'D') ++x;\n        else if (c == 'L') --y;\n        else if (c == 'R') ++y;\n    }\n\n    void move_to(int nx, int ny) {\n        while (x < nx && (int)ops.size() < TURN_LIMIT) move_one('D');\n        while (x > nx && (int)ops.size() < TURN_LIMIT) move_one('U');\n        while (y < ny && (int)ops.size() < TURN_LIMIT) move_one('R');\n        while (y > ny && (int)ops.size() < TURN_LIMIT) move_one('L');\n    }\n\n    void pickup(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"+\" + to_string(d));\n        cost += d;\n        h[x][y] -= d;\n        load += d;\n    }\n\n    void dropoff(int d) {\n        if (d <= 0 || (int)ops.size() >= TURN_LIMIT) return;\n        emit(\"-\" + to_string(d));\n        cost += d;\n        h[x][y] += d;\n        load -= d;\n    }\n\n    bool all_zero() const {\n        if (load != 0) return false;\n        for (int i = 0; i < N; ++i)\n            for (int j = 0; j < N; ++j)\n                if (h[i][j] != 0) return false;\n        return true;\n    }\n\n    int neg_density(int cx, int cy, int radius = 3) const {\n        int sum = 0;\n        for (int i = max(0, cx - radius); i <= min(N - 1, cx + radius); ++i) {\n            for (int j = max(0, cy - radius); j <= min(N - 1, cy + radius); ++j) {\n                if (h[i][j] < 0) {\n                    int d = abs(cx - i) + abs(cy - j);\n                    if (d <= radius) sum += (-h[i][j]) * (radius + 1 - d);\n                }\n            }\n        }\n        return sum;\n    }\n\n    int pos_density(int cx, int cy, int radius = 3) const {\n        int sum = 0;\n        for (int i = max(0, cx - radius); i <= min(N - 1, cx + radius); ++i) {\n            for (int j = max(0, cy - radius); j <= min(N - 1, cy + radius); ++j) {\n                if (h[i][j] > 0) {\n                    int d = abs(cx - i) + abs(cy - j);\n                    if (d <= radius) sum += h[i][j] * (radius + 1 - d);\n                }\n            }\n        }\n        return sum;\n    }\n\n    vector<pair<int,int>> collect_nearest(bool want_positive, int k, int cx, int cy) const {\n        vector<tuple<int,int,int>> buf;\n        buf.reserve(N * N);\n\n        for (int i = 0; i < N; ++i) {\n            for (int j = 0; j < N; ++j) {\n                if (want_positive) {\n                    if (h[i][j] > 0) buf.emplace_back(abs(cx - i) + abs(cy - j), i, j);\n                } else {\n                    if (h[i][j] < 0) buf.emplace_back(abs(cx - i) + abs(cy - j), i, j);\n                }\n            }\n        }\n\n        if (buf.empty()) return {};\n\n        if (k == -1 || k >= (int)buf.size()) {\n            vector<pair<int,int>> res;\n            res.reserve(buf.size());\n            for (auto &[d, i, j] : buf) res.push_back({i, j});\n            return res;\n        }\n\n        nth_element(buf.begin(), buf.begin() + k, buf.end());\n        buf.resize(k);\n\n        vector<pair<int,int>> res;\n        res.reserve(k);\n        for (auto &[d, i, j] : buf) res.push_back({i, j});\n        return res;\n    }\n\n    pair<int,int> find_best_positive() const {\n        auto cand = collect_nearest(true, source_k, x, y);\n        ll bestScore = INF64;\n        pair<int,int> best = {-1, -1};\n\n        for (auto [i, j] : cand) {\n            int d = dist(x, y, i, j);\n            int amt = h[i][j];\n            ll score = 100LL * d - 3LL * amt;\n\n            if (source_mode == 3) {\n                score -= 2LL * neg_density(i, j, 3);\n                score += 1LL * pos_density(i, j, 3);\n            }\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = {i, j};\n            }\n        }\n        return best;\n    }\n\n    pair<int,int> find_best_negative() const {\n        auto cand = collect_nearest(false, sink_k, x, y);\n        ll bestScore = INF64;\n        pair<int,int> best = {-1, -1};\n\n        for (auto [i, j] : cand) {\n            int d = dist(x, y, i, j);\n            int need = -h[i][j];\n            int tr = (int)min<ll>(load, need);\n            ll score = (100LL + load) * d - 2LL * tr;\n\n            if (sink_mode == 1) {\n                score -= 2LL * pos_density(i, j, 3);\n                score += 1LL * neg_density(i, j, 3);\n            }\n\n            if (score < bestScore) {\n                bestScore = score;\n                best = {i, j};\n            }\n        }\n        return best;\n    }\n\n    void snake_pass_once() {\n        vector<pair<int,int>> ord;\n        ord.reserve(N * N);\n        for (int i = 0; i < N; ++i) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; ++j) ord.push_back({i, j});\n            } else {\n                for (int j = N - 1; j >= 0; --j) ord.push_back({i, j});\n            }\n        }\n\n        auto process_here = [&]() {\n            if (h[x][y] > 0) {\n                pickup(min(h[x][y], cap));\n            } else if (h[x][y] < 0 && load > 0) {\n                dropoff((int)min<ll>(load, -h[x][y]));\n            }\n        };\n\n        for (auto [i, j] : ord) {\n            if (!can_continue(2000)) break;\n            move_to(i, j);\n            process_here();\n        }\n    }\n\n    void snake_cleanup() {\n        vector<pair<int,int>> ord;\n        ord.reserve(N * N);\n        for (int i = 0; i < N; ++i) {\n            if (i % 2 == 0) {\n                for (int j = 0; j < N; ++j) ord.push_back({i, j});\n            } else {\n                for (int j = N - 1; j >= 0; --j) ord.push_back({i, j});\n            }\n        }\n\n        auto process_here = [&]() {\n            if (h[x][y] > 0) {\n                pickup(min(h[x][y], cap));\n            } else if (h[x][y] < 0) {\n                dropoff((int)min<ll>(load, -h[x][y]));\n            }\n        };\n\n        for (int rep = 0; rep < 8 && !all_zero() && can_continue(1000); ++rep) {\n            if (rep % 2 == 0) {\n                for (auto [i, j] : ord) {\n                    move_to(i, j);\n                    process_here();\n                }\n            } else {\n                for (int k = (int)ord.size() - 1; k >= 0; --k) {\n                    auto [i, j] = ord[k];\n                    move_to(i, j);\n                    process_here();\n                }\n            }\n        }\n    }\n\n    Result run() {\n        if (use_prepass && can_continue(3000)) {\n            snake_pass_once();\n        }\n\n        while (can_continue(1000)) {\n            if (all_zero()) break;\n\n            if (load == 0) {\n                auto [px, py] = find_best_positive();\n                if (px == -1) break;\n                move_to(px, py);\n                if (h[x][y] > 0) pickup(min(h[x][y], cap));\n            } else {\n                auto [nx, ny] = find_best_negative();\n                if (nx == -1) break;\n                move_to(nx, ny);\n                if (h[x][y] < 0) dropoff((int)min<ll>(load, -h[x][y]));\n            }\n        }\n\n        if (!all_zero() && can_continue(1000)) {\n            snake_cleanup();\n        }\n\n        Result r;\n        r.ops = ops;\n        r.cost = cost;\n        r.finished = all_zero();\n        return r;\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N;\n    cin >> N;\n    vector<vector<int>> h(N, vector<int>(N));\n    for (int i = 0; i < N; ++i)\n        for (int j = 0; j < N; ++j)\n            cin >> h[i][j];\n\n    vector<int> caps = {25, 40, 70, BIG_CAP};\n    vector<int> source_modes = {0, 3};\n    vector<int> sink_modes = {0, 1};\n    vector<int> source_ks = {-1, 8};\n    vector<int> sink_ks = {8, 4};\n    vector<bool> prepasses = {false, true};\n\n    Result best;\n    best.cost = INF64;\n    best.finished = false;\n\n    for (int cap : caps) {\n        for (int sm : source_modes) {\n            for (int tm : sink_modes) {\n                for (int sk : source_ks) {\n                    for (int tk : sink_ks) {\n                        for (bool pp : prepasses) {\n                            Sim sim(N, h, cap, sm, tm, sk, tk, pp);\n                            Result cur = sim.run();\n\n                            if (cur.finished && !best.finished) {\n                                best = move(cur);\n                            } else if (cur.finished == best.finished && cur.cost < best.cost) {\n                                best = move(cur);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    for (const string& s : best.ops) {\n        cout << s << '\\n';\n    }\n    return 0;\n}","ahc035":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 6;\nstatic constexpr int M = 15;\nstatic constexpr int SEED_COUNT = 2 * N * (N - 1); // 60\nstatic constexpr int CELL_COUNT = N * N;           // 36\n\nstruct XorShift {\n    uint64_t x = 88172645463325252ull;\n    uint32_t next_u32() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return (uint32_t)x;\n    }\n    int next_int(int l, int r) { // [l, r)\n        return l + (int)(next_u32() % (uint32_t)(r - l));\n    }\n    double next_double() {\n        return (double)next_u32() / 4294967296.0;\n    }\n} rng;\n\nstruct Seed {\n    array<int, M> x{};\n    int sum = 0;\n};\n\nstatic inline double sqr(double x) { return x * x; }\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    vector<Seed> seeds(SEED_COUNT);\n    for (int i = 0; i < SEED_COUNT; i++) {\n        int s = 0;\n        for (int j = 0; j < M; j++) {\n            cin >> seeds[i].x[j];\n            s += seeds[i].x[j];\n        }\n        seeds[i].sum = s;\n    }\n\n    auto cell_id = [&](int r, int c) { return r * N + c; };\n\n    vector<vector<int>> nbr(CELL_COUNT);\n    vector<pair<int,int>> edges;\n    for (int r = 0; r < N; r++) {\n        for (int c = 0; c < N; c++) {\n            int v = cell_id(r, c);\n            if (r + 1 < N) {\n                int u = cell_id(r + 1, c);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n            if (c + 1 < N) {\n                int u = cell_id(r, c + 1);\n                nbr[v].push_back(u);\n                nbr[u].push_back(v);\n                edges.push_back({v, u});\n            }\n        }\n    }\n\n    vector<int> degree(CELL_COUNT);\n    for (int i = 0; i < CELL_COUNT; i++) degree[i] = (int)nbr[i].size();\n\n    vector<int> cell_order(CELL_COUNT);\n    iota(cell_order.begin(), cell_order.end(), 0);\n    sort(cell_order.begin(), cell_order.end(), [&](int a, int b) {\n        if (degree[a] != degree[b]) return degree[a] > degree[b];\n        int ra = a / N, ca = a % N;\n        int rb = b / N, cb = b % N;\n        int da = abs(ra - 2) + abs(ca - 2);\n        int db = abs(rb - 2) + abs(cb - 2);\n        return da < db;\n    });\n\n    for (int turn = 0; turn < T; turn++) {\n        // ----- turn-aware weights -----\n        double phase = (double)turn / max(1, T - 1); // 0..1\n        // early: diversity, late: sum\n        double W_SUM = 1.0 + 1.6 * phase;\n        double W_TOP = 1.2 - 0.5 * phase;\n        double W_COVER = 1.4 - 0.8 * phase;\n        double W_PAIR_ENV = 1.0 + 0.6 * phase;\n        double W_PAIR_SUM = 0.15 + 0.35 * phase;\n        double W_CELL = 0.35 + 0.45 * phase;\n\n        // ----- global coordinate statistics -----\n        array<int, M> gmax{};\n        array<double, M> gmean{};\n        gmax.fill(0);\n        gmean.fill(0.0);\n        for (int l = 0; l < M; l++) {\n            for (int i = 0; i < SEED_COUNT; i++) {\n                gmax[l] = max(gmax[l], seeds[i].x[l]);\n                gmean[l] += seeds[i].x[l];\n            }\n            gmean[l] /= SEED_COUNT;\n        }\n\n        array<double, M> dimWeight{};\n        for (int l = 0; l < M; l++) {\n            // emphasize dimensions with large maxima and where elite values matter\n            dimWeight[l] = 1.0 + 0.02 * gmax[l];\n        }\n\n        // ----- rich seed score -----\n        vector<double> seedScore(SEED_COUNT, 0.0);\n        vector<double> eliteScore(SEED_COUNT, 0.0); // \"specialist importance\"\n        for (int i = 0; i < SEED_COUNT; i++) {\n            double sc = W_SUM * seeds[i].sum;\n            double es = 0.0;\n            for (int l = 0; l < M; l++) {\n                double x = seeds[i].x[l];\n                double rel = (gmax[l] == 0 ? 0.0 : x / gmax[l]);\n                sc += W_TOP * dimWeight[l] * rel * x * 0.35;\n                // sharp bonus near dimension max\n                double nearTop = max(0.0, rel - 0.75);\n                es += dimWeight[l] * nearTop * nearTop * 100.0;\n            }\n            seedScore[i] = sc + 0.4 * es;\n            eliteScore[i] = es;\n        }\n\n        // ----- candidate ordering -----\n        vector<int> ord(SEED_COUNT);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (fabs(seedScore[a] - seedScore[b]) > 1e-9) return seedScore[a] > seedScore[b];\n            if (seeds[a].sum != seeds[b].sum) return seeds[a].sum > seeds[b].sum;\n            return a < b;\n        });\n\n        // ----- select 36 seeds: core by score + diverse fill by coordinate coverage -----\n        vector<int> chosen;\n        vector<int> usedSeed(SEED_COUNT, 0);\n\n        int core = 20; // stronger core than before, but leave room for specialists\n        for (int i = 0; i < core; i++) {\n            chosen.push_back(ord[i]);\n            usedSeed[ord[i]] = 1;\n        }\n\n        array<int, M> coverMax{};\n        coverMax.fill(0);\n        for (int s : chosen) {\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[s].x[l]);\n        }\n\n        while ((int)chosen.size() < CELL_COUNT) {\n            int best = -1;\n            double bestGain = -1e100;\n\n            for (int i = 0; i < SEED_COUNT; i++) if (!usedSeed[i]) {\n                double gain = 0.18 * seedScore[i] + 0.30 * eliteScore[i];\n                for (int l = 0; l < M; l++) {\n                    int inc = max(0, seeds[i].x[l] - coverMax[l]);\n                    gain += W_COVER * dimWeight[l] * inc;\n                }\n                if (gain > bestGain) {\n                    bestGain = gain;\n                    best = i;\n                }\n            }\n\n            chosen.push_back(best);\n            usedSeed[best] = 1;\n            for (int l = 0; l < M; l++) coverMax[l] = max(coverMax[l], seeds[best].x[l]);\n        }\n\n        // local indices [0,35]\n        vector<int> localToSeed = chosen;\n\n        static int envScore[CELL_COUNT][CELL_COUNT];\n        static int sumScore[CELL_COUNT][CELL_COUNT];\n        static int syScore[CELL_COUNT][CELL_COUNT];\n\n        for (int i = 0; i < CELL_COUNT; i++) {\n            envScore[i][i] = sumScore[i][i] = syScore[i][i] = 0;\n            for (int j = i + 1; j < CELL_COUNT; j++) {\n                int a = localToSeed[i], b = localToSeed[j];\n                int env = 0;\n                int ss = seeds[a].sum + seeds[b].sum;\n                int syn = 0;\n                for (int l = 0; l < M; l++) {\n                    int xa = seeds[a].x[l], xb = seeds[b].x[l];\n                    env += max(xa, xb);\n\n                    // synergy bonus: high if both together cover the max well, especially if one is strong where the other is not\n                    int mn = min(xa, xb), mx = max(xa, xb);\n                    syn += mx - mn / 3;\n                }\n                envScore[i][j] = envScore[j][i] = env;\n                sumScore[i][j] = sumScore[j][i] = ss;\n                syScore[i][j] = syScore[j][i] = syn;\n            }\n        }\n\n        vector<double> localSeedCellWeight(CELL_COUNT);\n        for (int i = 0; i < CELL_COUNT; i++) {\n            int s = localToSeed[i];\n            localSeedCellWeight[i] = 0.65 * seeds[s].sum + 0.35 * eliteScore[s];\n        }\n\n        auto objective_edge = [&](int a, int b) -> double {\n            return W_PAIR_ENV * envScore[a][b] + W_PAIR_SUM * sumScore[a][b] + 0.25 * syScore[a][b];\n        };\n\n        auto placementScore = [&](const vector<int>& pl) -> double {\n            double res = 0.0;\n            for (auto [u, v] : edges) res += objective_edge(pl[u], pl[v]);\n            for (int c = 0; c < CELL_COUNT; c++) {\n                res += W_CELL * degree[c] * localSeedCellWeight[pl[c]];\n            }\n            return res;\n        };\n\n        auto deltaSwap = [&](const vector<int>& pl, int a, int b) -> double {\n            if (a == b) return 0.0;\n            int sa = pl[a], sb = pl[b];\n            double before = 0.0, after = 0.0;\n\n            // cell weight term\n            before += W_CELL * degree[a] * localSeedCellWeight[sa];\n            before += W_CELL * degree[b] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[a] * localSeedCellWeight[sb];\n            after  += W_CELL * degree[b] * localSeedCellWeight[sa];\n\n            vector<int> vs;\n            vs.push_back(a);\n            vs.push_back(b);\n            for (int x : nbr[a]) vs.push_back(x);\n            for (int x : nbr[b]) vs.push_back(x);\n            sort(vs.begin(), vs.end());\n            vs.erase(unique(vs.begin(), vs.end()), vs.end());\n\n            set<pair<int,int>> es;\n            for (int u : vs) for (int v : nbr[u]) if (u < v) es.insert({u, v});\n\n            for (auto [u, v] : es) {\n                int pu = pl[u], pv = pl[v];\n                before += objective_edge(pu, pv);\n\n                if (u == a) pu = sb;\n                else if (u == b) pu = sa;\n                if (v == a) pv = sb;\n                else if (v == b) pv = sa;\n                after += objective_edge(pu, pv);\n            }\n\n            return after - before;\n        };\n\n        auto make_greedy = [&](bool randomized) -> vector<int> {\n            vector<int> place(CELL_COUNT, -1);\n            vector<int> used(CELL_COUNT, 0);\n\n            for (int step = 0; step < CELL_COUNT; step++) {\n                int cell = cell_order[step];\n\n                vector<pair<double,int>> cand;\n                cand.reserve(CELL_COUNT);\n                for (int si = 0; si < CELL_COUNT; si++) if (!used[si]) {\n                    double sc = W_CELL * degree[cell] * localSeedCellWeight[si];\n\n                    // adjacency with already placed neighbors\n                    for (int nb : nbr[cell]) {\n                        if (place[nb] != -1) sc += objective_edge(si, place[nb]);\n                    }\n\n                    // slight center preference\n                    int r = cell / N, c = cell % N;\n                    int md = abs(r - 2) + abs(c - 2);\n                    sc -= 0.7 * md * (0.35 * seeds[localToSeed[si]].sum + 0.1 * eliteScore[localToSeed[si]]);\n\n                    cand.push_back({sc, si});\n                }\n\n                sort(cand.begin(), cand.end(), greater<>());\n                int take = 0;\n                if (randomized) {\n                    int lim = min<int>(4, cand.size());\n                    take = rng.next_int(0, lim);\n                }\n                int bestSeed = cand[take].second;\n                place[cell] = bestSeed;\n                used[bestSeed] = 1;\n            }\n\n            // hill climbing\n            double cur = placementScore(place);\n            bool improved = true;\n            for (int it = 0; it < 10 && improved; it++) {\n                improved = false;\n\n                // random order pairs + full sweep flavor\n                vector<int> cells(CELL_COUNT);\n                iota(cells.begin(), cells.end(), 0);\n                shuffle(cells.begin(), cells.end(), std::mt19937(rng.next_u32()));\n\n                for (int xi = 0; xi < CELL_COUNT; xi++) {\n                    int a = cells[xi];\n                    double bestD = 0.0;\n                    int bestB = -1;\n                    for (int yi = xi + 1; yi < CELL_COUNT; yi++) {\n                        int b = cells[yi];\n                        double d = deltaSwap(place, a, b);\n                        if (d > bestD) {\n                            bestD = d;\n                            bestB = b;\n                        }\n                    }\n                    if (bestB != -1) {\n                        swap(place[a], place[bestB]);\n                        cur += bestD;\n                        improved = true;\n                    }\n                }\n            }\n\n            return place;\n        };\n\n        // multi-start\n        vector<int> bestPlace;\n        double bestScore = -1e100;\n\n        int trials = 10;\n        for (int tcase = 0; tcase < trials; tcase++) {\n            bool randomized = (tcase > 0);\n            auto pl = make_greedy(randomized);\n            double sc = placementScore(pl);\n            if (sc > bestScore) {\n                bestScore = sc;\n                bestPlace = pl;\n            }\n        }\n\n        // output original seed indices\n        for (int r = 0; r < N; r++) {\n            for (int c = 0; c < N; c++) {\n                if (c) cout << ' ';\n                cout << localToSeed[bestPlace[cell_id(r, c)]];\n            }\n            cout << '\\n';\n        }\n        cout.flush();\n\n        // read next generation\n        for (int i = 0; i < SEED_COUNT; i++) {\n            int s = 0;\n            for (int j = 0; j < M; j++) {\n                cin >> seeds[i].x[j];\n                s += seeds[i].x[j];\n            }\n            seeds[i].sum = s;\n        }\n    }\n\n    return 0;\n}","ahc038":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Pos {\n    int x, y;\n};\n\nstatic const int DX[4] = {0, 1, 0, -1}; // R D L U\nstatic const int DY[4] = {1, 0, -1, 0};\nstatic const char DIRC[4] = {'R', 'D', 'L', 'U'};\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    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    int K = max(1, V - 1);\n    int Vp = K + 1;\n\n    cout << Vp << '\\n';\n    for (int i = 1; i < Vp; i++) cout << 0 << ' ' << 1 << '\\n';\n\n    int rx = N / 2, ry = N / 2;\n    cout << rx << ' ' << ry << '\\n';\n\n    auto inb = [&](int x, int y) -> bool {\n        return 0 <= x && x < N && 0 <= y && y < N;\n    };\n\n    vector<int> dir(K, 0);\n    vector<int> hold(K, 0);\n\n    auto is_surplus = [&](int x, int y) -> bool {\n        return s[x][y] == '1' && t[x][y] == '0';\n    };\n    auto is_deficit = [&](int x, int y) -> bool {\n        return s[x][y] == '0' && t[x][y] == '1';\n    };\n\n    auto remaining = [&]() -> int {\n        int diff = 0;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) {\n            if (s[i][j] != t[i][j]) diff++;\n        }\n        return diff / 2;\n    };\n\n    auto hold_count = [&]() -> int {\n        int c = 0;\n        for (int v : hold) c += v;\n        return c;\n    };\n\n    auto step_toward = [&](int tx, int ty) -> char {\n        if (rx < tx && inb(rx + 1, ry)) return 'D';\n        if (rx > tx && inb(rx - 1, ry)) return 'U';\n        if (ry < ty && inb(rx, ry + 1)) return 'R';\n        if (ry > ty && inb(rx, ry - 1)) return 'L';\n        return '.';\n    };\n\n    auto rot_cost = [&](int cur, int target) -> int {\n        int diff = (target - cur + 4) % 4;\n        if (diff == 0) return 0;\n        if (diff == 2) return 2;\n        return 1;\n    };\n\n    auto rotate_one_toward = [&](int leaf, int target_dir) -> char {\n        int cur = dir[leaf];\n        int diff = (target_dir - cur + 4) % 4;\n        if (diff == 0) return '.';\n        if (diff == 1) return 'R';\n        if (diff == 3) return 'L';\n        return 'R';\n    };\n\n    auto adjacent_dir = [&](int cx, int cy, int tx, int ty) -> int {\n        for (int d = 0; d < 4; d++) {\n            if (cx + DX[d] == tx && cy + DY[d] == ty) return d;\n        }\n        return -1;\n    };\n\n    auto best_adjacent_root = [&](int tx, int ty) -> Pos {\n        int best = 1e9;\n        Pos res{rx, ry};\n        for (int d = 0; d < 4; d++) {\n            int x = tx - DX[d], y = ty - DY[d];\n            if (!inb(x, y)) continue;\n            int dist = abs(x - rx) + abs(y - ry);\n            if (dist < best) {\n                best = dist;\n                res = {x, y};\n            }\n        }\n        return res;\n    };\n\n    auto all_surplus = [&]() {\n        vector<Pos> v;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (is_surplus(i, j)) v.push_back({i, j});\n        return v;\n    };\n\n    auto all_deficit = [&]() {\n        vector<Pos> v;\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (is_deficit(i, j)) v.push_back({i, j});\n        return v;\n    };\n\n    const int TURN_LIMIT = 100000;\n    vector<string> ops;\n\n    auto apply_turn = [&](char mv, const vector<char>& rot, const vector<char>& wantAct) -> bool {\n        if ((int)ops.size() >= TURN_LIMIT) return false;\n\n        string cmd(2 * Vp, '.');\n\n        int nrx = rx, nry = ry;\n        cmd[0] = mv;\n        if (mv != '.') {\n            int d = -1;\n            for (int k = 0; k < 4; k++) if (DIRC[k] == mv) d = k;\n            if (d != -1) {\n                int tx = rx + DX[d], ty = ry + DY[d];\n                if (inb(tx, ty)) {\n                    nrx = tx;\n                    nry = ty;\n                }\n            }\n        }\n\n        vector<int> ndir = dir;\n        for (int i = 0; i < K; i++) {\n            cmd[1 + i] = rot[i];\n            if (rot[i] == 'L') ndir[i] = (ndir[i] + 3) % 4;\n            else if (rot[i] == 'R') ndir[i] = (ndir[i] + 1) % 4;\n        }\n\n        vector<string> board = s;\n        vector<int> nhold = hold;\n        for (int i = 0; i < K; i++) {\n            if (wantAct[i] != 'P') continue;\n            int x = nrx + DX[ndir[i]], y = nry + DY[ndir[i]];\n            if (!inb(x, y)) continue;\n\n            if (nhold[i]) {\n                if (board[x][y] == '0' && t[x][y] == '1') {\n                    board[x][y] = '1';\n                    nhold[i] = 0;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            } else {\n                if (board[x][y] == '1' && t[x][y] == '0') {\n                    board[x][y] = '0';\n                    nhold[i] = 1;\n                    cmd[Vp + (i + 1)] = 'P';\n                }\n            }\n        }\n\n        rx = nrx;\n        ry = nry;\n        dir = ndir;\n        hold = nhold;\n        s.swap(board);\n        ops.push_back(cmd);\n        return true;\n    };\n\n    auto move_root_to = [&](Pos p) -> bool {\n        while ((rx != p.x || ry != p.y) && (int)ops.size() < TURN_LIMIT) {\n            char mv = step_toward(p.x, p.y);\n            vector<char> rot(K, '.'), act(K, '.');\n            if (!apply_turn(mv, rot, act)) return false;\n        }\n        return rx == p.x && ry == p.y;\n    };\n\n    auto rotate_and_pick = [&](int leaf, Pos src) -> bool {\n        while ((int)ops.size() < TURN_LIMIT) {\n            int d = adjacent_dir(rx, ry, src.x, src.y);\n            if (d == -1) return false;\n            vector<char> rot(K, '.'), act(K, '.');\n            char rr = rotate_one_toward(leaf, d);\n            rot[leaf] = rr;\n\n            int nd = dir[leaf];\n            if (rr == 'L') nd = (nd + 3) % 4;\n            else if (rr == 'R') nd = (nd + 1) % 4;\n\n            if (nd == d && !hold[leaf] && is_surplus(src.x, src.y)) {\n                act[leaf] = 'P';\n                return apply_turn('.', rot, act);\n            } else {\n                if (!apply_turn('.', rot, act)) return false;\n            }\n        }\n        return false;\n    };\n\n    auto rotate_and_place = [&](int leaf, Pos dst) -> bool {\n        while ((int)ops.size() < TURN_LIMIT) {\n            int d = adjacent_dir(rx, ry, dst.x, dst.y);\n            if (d == -1) return false;\n            vector<char> rot(K, '.'), act(K, '.');\n            char rr = rotate_one_toward(leaf, d);\n            rot[leaf] = rr;\n\n            int nd = dir[leaf];\n            if (rr == 'L') nd = (nd + 3) % 4;\n            else if (rr == 'R') nd = (nd + 1) % 4;\n\n            if (nd == d && hold[leaf] && is_deficit(dst.x, dst.y)) {\n                act[leaf] = 'P';\n                return apply_turn('.', rot, act);\n            } else {\n                if (!apply_turn('.', rot, act)) return false;\n            }\n        }\n        return false;\n    };\n\n    auto exact_pick_and_place = [&](int leaf, Pos src, Pos dst) -> bool {\n        Pos a = best_adjacent_root(src.x, src.y);\n        if (!move_root_to(a)) return false;\n        if (!rotate_and_pick(leaf, src)) return false;\n        Pos b = best_adjacent_root(dst.x, dst.y);\n        if (!move_root_to(b)) return false;\n        return rotate_and_place(leaf, dst);\n    };\n\n    auto exact_place_held = [&](int leaf, Pos dst) -> bool {\n        Pos a = best_adjacent_root(dst.x, dst.y);\n        if (!move_root_to(a)) return false;\n        return rotate_and_place(leaf, dst);\n    };\n\n    auto bulk_step = [&]() -> bool {\n        int hcnt = hold_count();\n        int ecnt = K - hcnt;\n\n        vector<Pos> surs = all_surplus();\n        vector<Pos> defs = all_deficit();\n\n        vector<vector<int>> distSur(N, vector<int>(N, 0));\n        vector<vector<int>> distDef(N, vector<int>(N, 0));\n\n        if (ecnt > 0 && !surs.empty()) {\n            for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n                int best = 1e9;\n                for (auto &p : surs) best = min(best, abs(x - p.x) + abs(y - p.y) - 1);\n                distSur[x][y] = max(best, 0);\n            }\n        }\n\n        if (hcnt > 0 && !defs.empty()) {\n            for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n                int best = 1e9;\n                for (auto &p : defs) best = min(best, abs(x - p.x) + abs(y - p.y) - 1);\n                distDef[x][y] = max(best, 0);\n            }\n        }\n\n        auto eval_pos = [&](int x, int y) -> int {\n            int sur = 0, def = 0;\n            for (int d = 0; d < 4; d++) {\n                int nx = x + DX[d], ny = y + DY[d];\n                if (!inb(nx, ny)) continue;\n                if (is_surplus(nx, ny)) sur++;\n                if (is_deficit(nx, ny)) def++;\n            }\n            sur = min(sur, ecnt);\n            def = min(def, hcnt);\n\n            int score = 1000 * sur + 1100 * def;\n            score -= 2 * (abs(x - rx) + abs(y - ry));\n            if (ecnt > 0) score -= 3 * distSur[x][y];\n            if (hcnt > 0) score -= 3 * distDef[x][y];\n            return score;\n        };\n\n        Pos best{rx, ry};\n        int bestScore = eval_pos(rx, ry);\n        for (int x = 0; x < N; x++) for (int y = 0; y < N; y++) {\n            int sc = eval_pos(x, y);\n            if (sc > bestScore) {\n                bestScore = sc;\n                best = {x, y};\n            }\n        }\n\n        char mv = step_toward(best.x, best.y);\n        int nrx = rx, nry = ry;\n        if (mv == 'R') nry++;\n        else if (mv == 'L') nry--;\n        else if (mv == 'D') nrx++;\n        else if (mv == 'U') nrx--;\n\n        vector<char> rot(K, '.');\n        vector<int> used(4, 0);\n\n        for (int i = 0; i < K; i++) {\n            if (!hold[i]) continue;\n            int bestd = -1, bestcost = 10;\n            for (int d = 0; d < 4; d++) {\n                if (used[d]) continue;\n                int x = nrx + DX[d], y = nry + DY[d];\n                if (!inb(x, y) || !is_deficit(x, y)) continue;\n                int diff = (d - dir[i] + 4) % 4;\n                int cost = (diff == 0 ? 0 : diff == 2 ? 2 : 1);\n                if (cost < bestcost) {\n                    bestcost = cost;\n                    bestd = d;\n                }\n            }\n            if (bestd != -1) {\n                used[bestd] = 1;\n                rot[i] = rotate_one_toward(i, bestd);\n            }\n        }\n\n        for (int i = 0; i < K; i++) {\n            if (hold[i]) continue;\n            int bestd = -1, bestcost = 10;\n            for (int d = 0; d < 4; d++) {\n                if (used[d]) continue;\n                int x = nrx + DX[d], y = nry + DY[d];\n                if (!inb(x, y) || !is_surplus(x, y)) continue;\n                int diff = (d - dir[i] + 4) % 4;\n                int cost = (diff == 0 ? 0 : diff == 2 ? 2 : 1);\n                if (cost < bestcost) {\n                    bestcost = cost;\n                    bestd = d;\n                }\n            }\n            if (bestd != -1) {\n                used[bestd] = 1;\n                rot[i] = rotate_one_toward(i, bestd);\n            }\n        }\n\n        vector<int> ndir = dir;\n        for (int i = 0; i < K; i++) {\n            if (rot[i] == 'L') ndir[i] = (ndir[i] + 3) % 4;\n            else if (rot[i] == 'R') ndir[i] = (ndir[i] + 1) % 4;\n        }\n\n        vector<char> act(K, '.');\n        vector<string> board = s;\n        vector<int> nhold = hold;\n        for (int i = 0; i < K; i++) {\n            int x = nrx + DX[ndir[i]], y = nry + DY[ndir[i]];\n            if (!inb(x, y)) continue;\n            if (nhold[i]) {\n                if (board[x][y] == '0' && t[x][y] == '1') {\n                    act[i] = 'P';\n                    board[x][y] = '1';\n                    nhold[i] = 0;\n                }\n            } else {\n                if (board[x][y] == '1' && t[x][y] == '0') {\n                    act[i] = 'P';\n                    board[x][y] = '0';\n                    nhold[i] = 1;\n                }\n            }\n        }\n\n        return apply_turn(mv, rot, act);\n    };\n\n    auto final_tiny_step = [&]() -> bool {\n        int r = remaining();\n        if (r == 0) return true;\n\n        auto defs = all_deficit();\n\n        // Prefer delivering held items if any.\n        int bestHeldLeaf = -1;\n        Pos bestHeldDst{-1, -1};\n        int bestHeldScore = 1e9;\n\n        for (int leaf = 0; leaf < K; leaf++) if (hold[leaf]) {\n            for (auto &dst : defs) {\n                Pos adj = best_adjacent_root(dst.x, dst.y);\n                int moveCost = abs(rx - adj.x) + abs(ry - adj.y);\n                int d = adjacent_dir(adj.x, adj.y, dst.x, dst.y);\n                int rc = rot_cost(dir[leaf], d);\n                int score = moveCost + rc;\n                if (score < bestHeldScore) {\n                    bestHeldScore = score;\n                    bestHeldLeaf = leaf;\n                    bestHeldDst = dst;\n                }\n            }\n        }\n\n        if (bestHeldLeaf != -1) {\n            return exact_place_held(bestHeldLeaf, bestHeldDst);\n        }\n\n        auto surs = all_surplus();\n        if (surs.empty() || defs.empty()) return true;\n\n        int bestLeaf = -1, bi = -1, bj = -1;\n        int bestScore = 1e9;\n        for (int leaf = 0; leaf < K; leaf++) if (!hold[leaf]) {\n            for (int i = 0; i < (int)surs.size(); i++) {\n                Pos adjS = best_adjacent_root(surs[i].x, surs[i].y);\n                int move1 = abs(rx - adjS.x) + abs(ry - adjS.y);\n                int ds = adjacent_dir(adjS.x, adjS.y, surs[i].x, surs[i].y);\n                int rc1 = rot_cost(dir[leaf], ds);\n\n                for (int j = 0; j < (int)defs.size(); j++) {\n                    Pos adjD = best_adjacent_root(defs[j].x, defs[j].y);\n                    int move2 = abs(adjS.x - adjD.x) + abs(adjS.y - adjD.y);\n                    int dd = adjacent_dir(adjD.x, adjD.y, defs[j].x, defs[j].y);\n                    int rc2 = 1; // conservative approximation after pick\n                    if (dd == ds) rc2 = 0;\n                    else if ((dd - ds + 4) % 4 == 2) rc2 = 2;\n                    int score = move1 + rc1 + move2 + rc2;\n                    if (score < bestScore) {\n                        bestScore = score;\n                        bestLeaf = leaf;\n                        bi = i;\n                        bj = j;\n                    }\n                }\n            }\n        }\n\n        if (bestLeaf != -1) return exact_pick_and_place(bestLeaf, surs[bi], defs[bj]);\n        return true;\n    };\n\n    bool alive = true;\n    while (alive && remaining() > 0 && (int)ops.size() < TURN_LIMIT) {\n        int r = remaining();\n\n        if (r <= 2) {\n            int before = remaining();\n            alive = final_tiny_step();\n            if (!alive) break;\n            if (remaining() == before) {\n                vector<char> rot(K, '.'), act(K, '.');\n                alive = apply_turn('.', rot, act);\n            }\n        } else if (r <= 8) {\n            bool progressed = false;\n\n            auto defs = all_deficit();\n\n            while (!progressed) {\n                int bestLeaf = -1;\n                Pos bestDst{-1, -1};\n                int bestCost = 1e9;\n                for (int i = 0; i < K; i++) {\n                    if (!hold[i]) continue;\n                    for (auto &p : defs) {\n                        Pos a = best_adjacent_root(p.x, p.y);\n                        int dist = abs(rx - a.x) + abs(ry - a.y);\n                        if (dist < bestCost) {\n                            bestCost = dist;\n                            bestLeaf = i;\n                            bestDst = p;\n                        }\n                    }\n                }\n                if (bestLeaf == -1) break;\n\n                int before = remaining();\n                alive = exact_place_held(bestLeaf, bestDst);\n                if (!alive) break;\n                if (remaining() < before) progressed = true;\n                else break;\n            }\n            if (!alive) break;\n            if (progressed) continue;\n\n            auto surs = all_surplus();\n            defs = all_deficit();\n            if (surs.empty() || defs.empty()) break;\n\n            int bestLeaf = 0;\n            int bi = 0, bj = 0;\n            int bestScore = 1e9;\n            for (int leaf = 0; leaf < K; leaf++) {\n                if (hold[leaf]) continue;\n                for (int i = 0; i < (int)surs.size(); i++) {\n                    Pos a = best_adjacent_root(surs[i].x, surs[i].y);\n                    int d1 = abs(rx - a.x) + abs(ry - a.y);\n                    for (int j = 0; j < (int)defs.size(); j++) {\n                        int d2 = abs(surs[i].x - defs[j].x) + abs(surs[i].y - defs[j].y);\n                        int score = d1 + d2;\n                        if (score < bestScore) {\n                            bestScore = score;\n                            bestLeaf = leaf;\n                            bi = i;\n                            bj = j;\n                        }\n                    }\n                }\n            }\n\n            int before = remaining();\n            alive = exact_pick_and_place(bestLeaf, surs[bi], defs[bj]);\n            if (!alive) break;\n            if (remaining() == before) {\n                vector<char> rot(K, '.'), act(K, '.');\n                alive = apply_turn('.', rot, act);\n            }\n        } else {\n            alive = bulk_step();\n        }\n    }\n\n    if ((int)ops.size() > TURN_LIMIT) ops.resize(TURN_LIMIT);\n    for (auto &op : ops) cout << op << '\\n';\n    return 0;\n}","ahc039":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Point {\n    int x, y;\n};\n\nstruct GridData {\n    int D;\n    int ox, oy;\n    int W, H;\n    vector<int> w;\n};\n\nstruct Candidate {\n    ll score = LLONG_MIN;\n    vector<unsigned char> sel;\n    int H = 0, W = 0, ox = 0, oy = 0, D = 0;\n    vector<pair<int,int>> poly;\n    bool valid = false;\n};\n\nstatic inline long long pack64(int a, int b) {\n    return ((long long)a << 32) ^ (unsigned int)b;\n}\n\nstatic inline int mdist(pair<int,int> a, pair<int,int> b) {\n    return abs(a.first - b.first) + abs(a.second - b.second);\n}\n\nGridData build_grid(const vector<Point>& mac, const vector<Point>& sar, int D) {\n    int minx = 1e9, miny = 1e9, maxx = -1, maxy = -1;\n    auto upd = [&](const Point& p) {\n        int gx = p.x / D, gy = p.y / D;\n        minx = min(minx, gx);\n        maxx = max(maxx, gx);\n        miny = min(miny, gy);\n        maxy = max(maxy, gy);\n    };\n    for (auto &p : mac) upd(p);\n    for (auto &p : sar) upd(p);\n\n    GridData g;\n    g.D = D;\n    g.ox = minx;\n    g.oy = miny;\n    g.W = maxx - minx + 1;\n    g.H = maxy - miny + 1;\n    g.w.assign(g.H * g.W, 0);\n\n    auto id = [&](int r, int c) { return r * g.W + c; };\n    for (auto &p : mac) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r, c)]++;\n    }\n    for (auto &p : sar) {\n        int c = p.x / D - g.ox;\n        int r = p.y / D - g.oy;\n        g.w[id(r, c)]--;\n    }\n    return g;\n}\n\nGridData build_grid_subregion(const vector<Point>& mac, const vector<Point>& sar, int D, int gx0, int gx1, int gy0, int gy1) {\n    GridData g;\n    g.D = D;\n    g.ox = gx0;\n    g.oy = gy0;\n    g.W = gx1 - gx0 + 1;\n    g.H = gy1 - gy0 + 1;\n    g.w.assign(g.H * g.W, 0);\n\n    auto add_point = [&](const Point& p, int delta) {\n        int gx = p.x / D, gy = p.y / D;\n        if (gx0 <= gx && gx <= gx1 && gy0 <= gy && gy <= gy1) {\n            int c = gx - gx0;\n            int r = gy - gy0;\n            g.w[r * g.W + c] += delta;\n        }\n    };\n\n    for (auto &p : mac) add_point(p, +1);\n    for (auto &p : sar) add_point(p, -1);\n    return g;\n}\n\nll compute_score(const vector<unsigned char>& sel, const GridData& g) {\n    ll s = 0;\n    for (int i = 0; i < (int)sel.size(); i++) if (sel[i]) s += g.w[i];\n    return s;\n}\n\nint compute_perim_edges(const vector<unsigned char>& sel, int H, int W) {\n    auto id = [&](int r, int c) { return r * W + c; };\n    int pe = 0;\n    for (int r = 0; r < H; r++) for (int c = 0; c < W; c++) if (sel[id(r, c)]) {\n        if (r == 0 || !sel[id(r - 1, c)]) pe++;\n        if (r + 1 == H || !sel[id(r + 1, c)]) pe++;\n        if (c == 0 || !sel[id(r, c - 1)]) pe++;\n        if (c + 1 == W || !sel[id(r, c + 1)]) pe++;\n    }\n    return pe;\n}\n\nbool is_connected_after_removal(const vector<unsigned char>& sel, int H, int W, int rem) {\n    int total = 0, start = -1;\n    for (int i = 0; i < H * W; i++) {\n        if (i == rem) continue;\n        if (sel[i]) total++, start = i;\n    }\n    if (total <= 1) return true;\n\n    vector<unsigned char> vis(H * W, 0);\n    queue<int> q;\n    q.push(start);\n    vis[start] = 1;\n    int cnt = 1;\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    while (!q.empty()) {\n        int v = q.front(); q.pop();\n        int r = v / W, c = v % W;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                int u = id(nr, nc);\n                if (u == rem || !sel[u] || vis[u]) continue;\n                vis[u] = 1;\n                q.push(u);\n                cnt++;\n            }\n        }\n    }\n    return cnt == total;\n}\n\nstruct BuildResult {\n    bool ok = false;\n    vector<pair<int,int>> poly;\n};\n\nBuildResult build_polygon_from_selected(const vector<unsigned char>& sel, int H, int W, int ox, int oy, int D) {\n    struct Edge {\n        int x1, y1, x2, y2;\n        bool operator==(const Edge& o) const {\n            return x1 == o.x1 && y1 == o.y1 && x2 == o.x2 && y2 == o.y2;\n        }\n    };\n    struct EdgeHash {\n        size_t operator()(Edge const& e) const noexcept {\n            uint64_t h = 1469598103934665603ULL;\n            auto add = [&](uint64_t v) {\n                h ^= v + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);\n            };\n            add((uint32_t)e.x1); add((uint32_t)e.y1); add((uint32_t)e.x2); add((uint32_t)e.y2);\n            return (size_t)h;\n        }\n    };\n\n    auto id = [&](int r, int c) { return r * W + c; };\n    unordered_set<Edge, EdgeHash> S;\n    S.reserve(H * W * 2);\n\n    auto toggle = [&](Edge e) {\n        Edge rev{e.x2, e.y2, e.x1, e.y1};\n        auto it = S.find(rev);\n        if (it != S.end()) S.erase(it);\n        else S.insert(e);\n    };\n\n    int cntSel = 0;\n    for (int r = 0; r < H; r++) for (int c = 0; c < W; c++) if (sel[id(r, c)]) {\n        cntSel++;\n        int gx = ox + c, gy = oy + r;\n        int x = gx * D, y = gy * D;\n        toggle({x, y, x + D, y});\n        toggle({x + D, y, x + D, y + D});\n        toggle({x + D, y + D, x, y + D});\n        toggle({x, y + D, x, y});\n    }\n    if (cntSel == 0 || S.empty()) return {};\n\n    unordered_map<long long, vector<pair<int,int>>> out;\n    out.reserve(S.size() * 2);\n    auto pkey = [&](int x, int y) { return pack64(x, y); };\n    for (auto &e : S) out[pkey(e.x1, e.y1)].push_back({e.x2, e.y2});\n\n    auto ekey = [&](int x1, int y1, int x2, int y2) {\n        uint64_t h = 1469598103934665603ULL;\n        auto add = [&](uint64_t v) {\n            h ^= v + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2);\n        };\n        add((uint32_t)x1); add((uint32_t)y1); add((uint32_t)x2); add((uint32_t)y2);\n        return (long long)h;\n    };\n\n    unordered_set<long long> used;\n    used.reserve(S.size() * 2);\n\n    int cycles = 0;\n    vector<pair<int,int>> best;\n\n    for (auto &e : S) {\n        long long k0 = ekey(e.x1, e.y1, e.x2, e.y2);\n        if (used.count(k0)) continue;\n\n        cycles++;\n        vector<pair<int,int>> cur;\n        int sx = e.x1, sy = e.y1;\n        int cx = e.x1, cy = e.y1;\n        int nx = e.x2, ny = e.y2;\n        cur.push_back({cx, cy});\n\n        while (true) {\n            long long kk = ekey(cx, cy, nx, ny);\n            if (used.count(kk)) break;\n            used.insert(kk);\n\n            cx = nx; cy = ny;\n            cur.push_back({cx, cy});\n            if (cx == sx && cy == sy) break;\n\n            auto it = out.find(pkey(cx, cy));\n            if (it == out.end()) return {};\n            int cnt = 0;\n            pair<int,int> nxt;\n            for (auto &to : it->second) {\n                long long nk = ekey(cx, cy, to.first, to.second);\n                if (!used.count(nk)) cnt++, nxt = to;\n            }\n            if (cnt != 1) return {};\n            nx = nxt.first;\n            ny = nxt.second;\n        }\n\n        if (!cur.empty() && cur.front() == cur.back()) cur.pop_back();\n        if (cur.size() > best.size()) best = move(cur);\n    }\n\n    if ((int)used.size() != (int)S.size()) return {};\n    if (cycles != 1) return {};\n\n    vector<pair<int,int>> poly;\n    int m = (int)best.size();\n    for (int i = 0; i < m; i++) {\n        auto p0 = best[(i - 1 + m) % m];\n        auto p1 = best[i];\n        auto p2 = best[(i + 1) % m];\n        int dx1 = (p1.first > p0.first) - (p1.first < p0.first);\n        int dy1 = (p1.second > p0.second) - (p1.second < p0.second);\n        int dx2 = (p2.first > p1.first) - (p2.first < p1.first);\n        int dy2 = (p2.second > p1.second) - (p2.second < p1.second);\n        if (dx1 == dx2 && dy1 == dy2) continue;\n        poly.push_back(p1);\n    }\n\n    if ((int)poly.size() < 4 || (int)poly.size() > 1000) return {};\n    {\n        set<pair<int,int>> st(poly.begin(), poly.end());\n        if ((int)st.size() != (int)poly.size()) return {};\n    }\n    ll peri = 0;\n    for (int i = 0; i < (int)poly.size(); i++) peri += mdist(poly[i], poly[(i + 1) % poly.size()]);\n    if (peri > 400000) return {};\n    for (auto &p : poly) {\n        if (p.first < 0 || p.first > 100000 || p.second < 0 || p.second > 100000) return {};\n    }\n    return {true, poly};\n}\n\nCandidate candidate_from_rectangle(const GridData& g) {\n    Candidate best;\n    best.H = g.H; best.W = g.W; best.ox = g.ox; best.oy = g.oy; best.D = g.D;\n\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    vector<int> col(W);\n\n    for (int top = 0; top < H; top++) {\n        fill(col.begin(), col.end(), 0);\n        for (int bot = top; bot < H; bot++) {\n            int hc = bot - top + 1;\n            for (int c = 0; c < W; c++) col[c] += g.w[id(bot, c)];\n            int max_wh = 200000 / D - hc;\n            if (max_wh <= 0) continue;\n            int maxWidth = min(W, max_wh);\n\n            ll curBest = LLONG_MIN;\n            int bestL = -1, bestR = -1;\n            for (int l = 0; l < W; l++) {\n                ll s = 0;\n                for (int r = l; r < W && r - l + 1 <= maxWidth; r++) {\n                    s += col[r];\n                    if (s > curBest) curBest = s, bestL = l, bestR = r;\n                }\n            }\n            if (bestL == -1 || curBest <= best.score) continue;\n            vector<unsigned char> sel(H * W, 0);\n            for (int r = top; r <= bot; r++) for (int c = bestL; c <= bestR; c++) sel[id(r, c)] = 1;\n            best.score = curBest;\n            best.sel = move(sel);\n            best.valid = true;\n        }\n    }\n    return best;\n}\n\nCandidate candidate_from_threshold(const GridData& g, int T) {\n    int H = g.H, W = g.W;\n    auto id = [&](int r, int c) { return r * W + c; };\n\n    vector<unsigned char> good(H * W, 0), vis(H * W, 0);\n    for (int i = 0; i < H * W; i++) if (g.w[i] >= T) good[i] = 1;\n\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    ll bestScore = LLONG_MIN;\n    vector<unsigned char> bestSel(H * W, 0);\n\n    for (int s = 0; s < H * W; s++) {\n        if (!good[s] || vis[s]) continue;\n        queue<int> q;\n        vector<int> comp;\n        q.push(s);\n        vis[s] = 1;\n        ll sc = 0;\n\n        while (!q.empty()) {\n            int v = q.front(); q.pop();\n            comp.push_back(v);\n            sc += g.w[v];\n            int r = v / W, c = v % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                    int u = id(nr, nc);\n                    if (good[u] && !vis[u]) vis[u] = 1, q.push(u);\n                }\n            }\n        }\n\n        if (sc > bestScore) {\n            bestScore = sc;\n            fill(bestSel.begin(), bestSel.end(), 0);\n            for (int v : comp) bestSel[v] = 1;\n        }\n    }\n\n    Candidate c;\n    c.H = g.H; c.W = g.W; c.ox = g.ox; c.oy = g.oy; c.D = g.D;\n    if (bestScore == LLONG_MIN) return c;\n    c.score = bestScore;\n    c.sel = move(bestSel);\n    c.valid = true;\n    return c;\n}\n\nCandidate candidate_from_greedy(const GridData& g, double pen, int maxSeeds = 14) {\n    Candidate best;\n    best.H = g.H; best.W = g.W; best.ox = g.ox; best.oy = g.oy; best.D = g.D;\n\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    vector<int> ord(H * W);\n    iota(ord.begin(), ord.end(), 0);\n    sort(ord.begin(), ord.end(), [&](int a, int b) {\n        if (g.w[a] != g.w[b]) return g.w[a] > g.w[b];\n        return a < b;\n    });\n\n    maxSeeds = min(maxSeeds, H * W);\n\n    for (int si = 0; si < maxSeeds; si++) {\n        int seed = ord[si];\n        if (g.w[seed] <= 0 && si >= 5) break;\n\n        vector<unsigned char> sel(H * W, 0);\n        vector<int> ver(H * W, 0);\n        ll score = 0;\n        int perim_edges = 0;\n        int perim_limit = 400000 / D;\n\n        auto neigh_sel = [&](int v) {\n            int r = v / W, c = v % W;\n            int cnt = 0;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W && sel[id(nr, nc)]) cnt++;\n            }\n            return cnt;\n        };\n\n        struct Node {\n            double pri;\n            int v, ver;\n            bool operator<(const Node& o) const { return pri < o.pri; }\n        };\n        priority_queue<Node> pq;\n\n        auto push = [&](int v) {\n            if (sel[v]) return;\n            int ns = neigh_sel(v);\n            if (ns == 0) return;\n            int de = 4 - 2 * ns;\n            double pri = g.w[v] * 12.0 - pen * de + ns * 2.0;\n            pq.push({pri, v, ++ver[v]});\n        };\n\n        auto add = [&](int v) {\n            int ns = neigh_sel(v);\n            int de = 4 - 2 * ns;\n            sel[v] = 1;\n            score += g.w[v];\n            perim_edges += de;\n            int r = v / W, c = v % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) {\n                    int u = id(nr, nc);\n                    if (!sel[u]) push(u);\n                }\n            }\n        };\n\n        add(seed);\n        {\n            int r = seed / W, c = seed % W;\n            for (int k = 0; k < 4; k++) {\n                int nr = r + dr[k], nc = c + dc[k];\n                if (0 <= nr && nr < H && 0 <= nc && nc < W) push(id(nr, nc));\n            }\n        }\n\n        int iter = 0, iterLimit = H * W * 3;\n        while (!pq.empty() && iter < iterLimit) {\n            iter++;\n            auto cur = pq.top(); pq.pop();\n            int v = cur.v;\n            if (sel[v] || cur.ver != ver[v]) continue;\n            int ns = neigh_sel(v);\n            if (ns == 0) continue;\n            int de = 4 - 2 * ns;\n            if (perim_edges + de > perim_limit) continue;\n\n            double gain = g.w[v] * 12.0 - pen * de + ns * 2.0;\n            bool ok = false;\n            if (gain >= 0) ok = true;\n            else if (g.w[v] >= 0 && ns >= 2 && gain >= -2.0) ok = true;\n            else if (g.w[v] == -1 && ns >= 3 && gain >= -1.0) ok = true;\n            if (!ok) continue;\n            add(v);\n        }\n\n        if (score > best.score) {\n            best.score = score;\n            best.sel = move(sel);\n            best.valid = true;\n        }\n    }\n    return best;\n}\n\nvoid local_improve(Candidate& cand, const GridData& g, int rounds) {\n    if (!cand.valid) return;\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    auto &sel = cand.sel;\n    ll score = compute_score(sel, g);\n    int perim_edges = compute_perim_edges(sel, H, W);\n    int perim_limit = 400000 / D;\n\n    auto neigh_sel = [&](int v) {\n        int r = v / W, c = v % W;\n        int cnt = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W && sel[id(nr, nc)]) cnt++;\n        }\n        return cnt;\n    };\n\n    auto boundary_selected = [&](int v) {\n        if (!sel[v]) return false;\n        int r = v / W, c = v % W;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!(0 <= nr && nr < H && 0 <= nc && nc < W)) return true;\n            if (!sel[id(nr, nc)]) return true;\n        }\n        return false;\n    };\n\n    for (int step = 0; step < rounds; step++) {\n        double bestMerit = 0.0;\n        int bestType = 0, bestV = -1, bestDE = 0;\n        ll bestDS = 0;\n\n        for (int v = 0; v < H * W; v++) {\n            if (!sel[v]) {\n                int ns = neigh_sel(v);\n                if (ns == 0) continue;\n                int de = 4 - 2 * ns;\n                if (perim_edges + de > perim_limit) continue;\n                ll ds = g.w[v];\n                double merit = ds * 12.0 - de * 2.5 + ns * 1.5;\n                if (merit > bestMerit) {\n                    bestMerit = merit;\n                    bestType = +1;\n                    bestV = v;\n                    bestDE = de;\n                    bestDS = ds;\n                }\n            } else {\n                if (!boundary_selected(v)) continue;\n                int ns = neigh_sel(v);\n                int de = -4 + 2 * ns;\n                ll ds = -g.w[v];\n                double merit = ds * 12.0 - de * 2.5;\n                if (merit <= bestMerit) continue;\n                if (ns >= 2 && !is_connected_after_removal(sel, H, W, v)) continue;\n                if (perim_edges + de > perim_limit) continue;\n                bestMerit = merit;\n                bestType = -1;\n                bestV = v;\n                bestDE = de;\n                bestDS = ds;\n            }\n        }\n\n        if (bestType == 0) break;\n        if (bestType == +1) sel[bestV] = 1;\n        else sel[bestV] = 0;\n        score += bestDS;\n        perim_edges += bestDE;\n    }\n    cand.score = score;\n}\n\nvoid morph_cleanup(Candidate& cand, const GridData& g, int passes) {\n    if (!cand.valid) return;\n    int H = g.H, W = g.W, D = g.D;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n    int perim_limit = 400000 / D;\n\n    auto &sel = cand.sel;\n    auto neigh_sel = [&](const vector<unsigned char>& cur, int v) {\n        int r = v / W, c = v % W;\n        int cnt = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W && cur[id(nr, nc)]) cnt++;\n        }\n        return cnt;\n    };\n\n    for (int pass = 0; pass < passes; pass++) {\n        bool changed = false;\n        vector<unsigned char> nxt = sel;\n        int pe = compute_perim_edges(sel, H, W);\n\n        for (int v = 0; v < H * W; v++) if (!sel[v]) {\n            int ns = neigh_sel(sel, v);\n            if (ns >= 3) {\n                int de = 4 - 2 * ns;\n                if (pe + de <= perim_limit && (g.w[v] >= -1 || ns == 4)) {\n                    nxt[v] = 1;\n                    pe += de;\n                    changed = true;\n                }\n            }\n        }\n        sel.swap(nxt);\n\n        nxt = sel;\n        pe = compute_perim_edges(sel, H, W);\n        for (int v = 0; v < H * W; v++) if (sel[v]) {\n            int ns = neigh_sel(sel, v);\n            if (ns <= 1 && g.w[v] <= 0) {\n                if (ns >= 2 && !is_connected_after_removal(sel, H, W, v)) continue;\n                int de = -4 + 2 * ns;\n                if (pe + de <= perim_limit) {\n                    nxt[v] = 0;\n                    pe += de;\n                    changed = true;\n                }\n            }\n        }\n        sel.swap(nxt);\n\n        if (!changed) break;\n    }\n    cand.score = compute_score(sel, g);\n}\n\nbool finalize_candidate(Candidate& cand, const GridData& g) {\n    if (!cand.valid) return false;\n    auto br = build_polygon_from_selected(cand.sel, g.H, g.W, g.ox, g.oy, g.D);\n    if (!br.ok) {\n        cand.valid = false;\n        return false;\n    }\n    cand.poly = move(br.poly);\n    cand.score = compute_score(cand.sel, g);\n    cand.valid = true;\n    return true;\n}\n\nvector<int> get_boundary_cells(const Candidate& c, const GridData& g, int lim) {\n    vector<pair<int,int>> tmp;\n    int H = g.H, W = g.W;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1, 0, 1, 0};\n    const int dc[4] = {0, 1, 0, -1};\n\n    for (int v = 0; v < H * W; v++) if (c.sel[v]) {\n        int r = v / W, cc = v % W;\n        bool boundary = false;\n        int open = 0;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = cc + dc[k];\n            if (!(0 <= nr && nr < H && 0 <= nc && nc < W) || !c.sel[id(nr, nc)]) {\n                boundary = true;\n                open++;\n            }\n        }\n        if (boundary) {\n            int score = g.w[v] * 10 + open;\n            tmp.push_back({score, v});\n        }\n    }\n\n    sort(tmp.begin(), tmp.end(), [&](auto &a, auto &b) { return a.first > b.first; });\n    vector<int> res;\n    for (int i = 0; i < (int)tmp.size() && i < lim; i++) res.push_back(tmp[i].second);\n    return res;\n}\n\npair<vector<unsigned char>, ll> make_corridor_union(\n    const Candidate& A, const Candidate& B, const GridData& g,\n    int a, int b, bool horiz_first\n) {\n    int H = g.H, W = g.W;\n    auto id = [&](int r, int c) { return r * W + c; };\n    vector<unsigned char> sel = A.sel;\n    for (int i = 0; i < H * W; i++) if (B.sel[i]) sel[i] = 1;\n\n    int ar = a / W, ac = a % W;\n    int br = b / W, bc = b % W;\n    ll gain = 0;\n\n    auto add_cell = [&](int r, int c) {\n        int v = id(r, c);\n        if (!sel[v]) sel[v] = 1, gain += g.w[v];\n    };\n\n    int r = ar, c = ac;\n    add_cell(r, c);\n\n    if (horiz_first) {\n        while (c != bc) c += (c < bc ? 1 : -1), add_cell(r, c);\n        while (r != br) r += (r < br ? 1 : -1), add_cell(r, c);\n    } else {\n        while (r != br) r += (r < br ? 1 : -1), add_cell(r, c);\n        while (c != bc) c += (c < bc ? 1 : -1), add_cell(r, c);\n    }\n\n    return {move(sel), gain};\n}\n\nCandidate merge_two_candidates(const Candidate& A, const Candidate& B, const GridData& g) {\n    Candidate res;\n    if (!A.valid || !B.valid) return res;\n\n    int H = g.H, W = g.W;\n    int perim_limit = 400000 / g.D;\n\n    vector<int> BA = get_boundary_cells(A, g, 6);\n    vector<int> BB = get_boundary_cells(B, g, 6);\n    if (BA.empty() || BB.empty()) return res;\n\n    ll bestScore = LLONG_MIN;\n    vector<unsigned char> bestSel;\n\n    for (int a : BA) {\n        int ar = a / W, ac = a % W;\n        for (int b : BB) {\n            int br = b / W, bc = b % W;\n            int dist = abs(ar - br) + abs(ac - bc);\n            if (dist > perim_limit) continue;\n\n            for (int t = 0; t < 2; t++) {\n                auto cur = make_corridor_union(A, B, g, a, b, t == 0);\n                int pe = compute_perim_edges(cur.first, H, W);\n                if (pe > perim_limit) continue;\n                ll sc = compute_score(cur.first, g) * 1000LL - dist;\n                if (sc > bestScore) {\n                    bestScore = sc;\n                    bestSel = move(cur.first);\n                }\n            }\n        }\n    }\n\n    if (bestScore == LLONG_MIN) return res;\n    res.H = g.H; res.W = g.W; res.ox = g.ox; res.oy = g.oy; res.D = g.D;\n    res.sel = move(bestSel);\n    res.score = compute_score(res.sel, g);\n    res.valid = true;\n    return res;\n}\n\nbool bbox_of_selection(const Candidate& c, int& r0, int& r1, int& c0, int& c1) {\n    if (!c.valid) return false;\n    bool first = true;\n    for (int r = 0; r < c.H; r++) for (int cc = 0; cc < c.W; cc++) if (c.sel[r * c.W + cc]) {\n        if (first) {\n            r0 = r1 = r;\n            c0 = c1 = cc;\n            first = false;\n        } else {\n            r0 = min(r0, r); r1 = max(r1, r);\n            c0 = min(c0, cc); c1 = max(c1, cc);\n        }\n    }\n    return !first;\n}\n\nvector<unsigned char> dilate_sel(const vector<unsigned char>& sel, int H, int W) {\n    vector<unsigned char> out = sel;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1,0,1,0};\n    const int dc[4] = {0,1,0,-1};\n    for (int r = 0; r < H; r++) for (int c = 0; c < W; c++) if (sel[id(r,c)]) {\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (0 <= nr && nr < H && 0 <= nc && nc < W) out[id(nr,nc)] = 1;\n        }\n    }\n    return out;\n}\n\nvector<unsigned char> erode_sel(const vector<unsigned char>& sel, int H, int W) {\n    vector<unsigned char> out = sel;\n    auto id = [&](int r, int c) { return r * W + c; };\n    const int dr[4] = {-1,0,1,0};\n    const int dc[4] = {0,1,0,-1};\n    for (int r = 0; r < H; r++) for (int c = 0; c < W; c++) if (sel[id(r,c)]) {\n        bool keep = true;\n        for (int k = 0; k < 4; k++) {\n            int nr = r + dr[k], nc = c + dc[k];\n            if (!(0 <= nr && nr < H && 0 <= nc && nc < W) || !sel[id(nr,nc)]) {\n                keep = false;\n                break;\n            }\n        }\n        if (!keep) out[id(r,c)] = 0;\n    }\n    return out;\n}\n\nCandidate refine_to_finer_grid_multistart(const Candidate& coarse, const vector<Point>& mac, const vector<Point>& sar, int pad = 2) {\n    Candidate bad;\n    if (!coarse.valid) return bad;\n    if (coarse.D < 1600) return bad;\n\n    int D2 = coarse.D / 2;\n    if (D2 < 800) return bad;\n\n    int r0, r1, c0, c1;\n    if (!bbox_of_selection(coarse, r0, r1, c0, c1)) return bad;\n\n    int cgx0 = coarse.ox + c0;\n    int cgx1 = coarse.ox + c1;\n    int cgy0 = coarse.oy + r0;\n    int cgy1 = coarse.oy + r1;\n\n    int fgx0 = max(0, (cgx0 - pad) * 2);\n    int fgx1 = min(100000 / D2, (cgx1 + 1 + pad) * 2 - 1);\n    int fgy0 = max(0, (cgy0 - pad) * 2);\n    int fgy1 = min(100000 / D2, (cgy1 + 1 + pad) * 2 - 1);\n\n    GridData fine = build_grid_subregion(mac, sar, D2, fgx0, fgx1, fgy0, fgy1);\n\n    vector<unsigned char> base(fine.H * fine.W, 0);\n    for (int fr = 0; fr < fine.H; fr++) {\n        for (int fc = 0; fc < fine.W; fc++) {\n            int fgx = fine.ox + fc;\n            int fgy = fine.oy + fr;\n            int x = fgx * D2 + D2 / 2;\n            int y = fgy * D2 + D2 / 2;\n            int cgx = x / coarse.D;\n            int cgy = y / coarse.D;\n            int cc = cgx - coarse.ox;\n            int cr = cgy - coarse.oy;\n            if (0 <= cr && cr < coarse.H && 0 <= cc && cc < coarse.W) {\n                if (coarse.sel[cr * coarse.W + cc]) base[fr * fine.W + fc] = 1;\n            }\n        }\n    }\n\n    vector<vector<unsigned char>> initials;\n    initials.push_back(base);\n    initials.push_back(dilate_sel(base, fine.H, fine.W));\n    initials.push_back(erode_sel(base, fine.H, fine.W));\n\n    Candidate best;\n    for (auto &init : initials) {\n        Candidate c;\n        c.H = fine.H; c.W = fine.W; c.ox = fine.ox; c.oy = fine.oy; c.D = fine.D;\n        c.sel = init;\n        c.score = compute_score(c.sel, fine);\n        c.valid = true;\n\n        local_improve(c, fine, 25);\n        morph_cleanup(c, fine, 2);\n        local_improve(c, fine, 25);\n\n        if (!finalize_candidate(c, fine)) continue;\n        if (c.score > best.score) best = move(c);\n    }\n    return best;\n}\n\nvector<pair<int,int>> fallback_polygon() {\n    return {{0,0}, {1,0}, {1,1}, {0,1}};\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    int N;\n    cin >> N;\n    vector<Point> mac(N), sar(N);\n    for (int i = 0; i < N; i++) cin >> mac[i].x >> mac[i].y;\n    for (int i = 0; i < N; i++) cin >> sar[i].x >> sar[i].y;\n\n    vector<int> Ds = {1200, 1600, 2000, 2500, 3200};\n\n    Candidate best;\n    Candidate bestMergedGlobal;\n    Candidate bestSingleGlobal;\n\n    auto elapsed_sec = [&]() -> double {\n        auto now = chrono::steady_clock::now();\n        return chrono::duration<double>(now - start_time).count();\n    };\n\n    auto improve_and_consider = [&](Candidate c, const GridData& g, bool try_fine, bool is_merge) {\n        if (!c.valid) return c;\n        local_improve(c, g, 30);\n        morph_cleanup(c, g, 2);\n        local_improve(c, g, 30);\n        if (!finalize_candidate(c, g)) {\n            c.valid = false;\n            return c;\n        }\n\n        if (c.score > best.score) best = c;\n        if (is_merge) {\n            if (c.score > bestMergedGlobal.score) bestMergedGlobal = c;\n        } else {\n            if (c.score > bestSingleGlobal.score) bestSingleGlobal = c;\n        }\n\n        if (try_fine && elapsed_sec() < 1.45) {\n            Candidate f = refine_to_finer_grid_multistart(c, mac, sar, 2);\n            if (f.valid) {\n                if (f.score > best.score) best = f;\n                if (!is_merge && f.score > bestSingleGlobal.score) bestSingleGlobal = f;\n            }\n        }\n        return c;\n    };\n\n    for (int D : Ds) {\n        GridData g = build_grid(mac, sar, D);\n        vector<Candidate> elite_raw;\n\n        auto push_elite = [&](Candidate c) {\n            if (c.valid) elite_raw.push_back(move(c));\n        };\n\n        push_elite(candidate_from_rectangle(g));\n        push_elite(candidate_from_threshold(g, 2));\n        push_elite(candidate_from_threshold(g, 1));\n        for (double pen : {1.8, 2.5, 3.5}) {\n            push_elite(candidate_from_greedy(g, pen, 14));\n        }\n\n        sort(elite_raw.begin(), elite_raw.end(), [&](const Candidate& a, const Candidate& b) {\n            return a.score > b.score;\n        });\n\n        for (int i = 0; i < (int)elite_raw.size(); i++) {\n            bool try_fine = (i == 0);\n            improve_and_consider(elite_raw[i], g, try_fine, false);\n        }\n\n        if ((int)elite_raw.size() > 4) elite_raw.resize(4);\n\n        for (int i = 0; i < (int)elite_raw.size(); i++) {\n            for (int j = i + 1; j < (int)elite_raw.size(); j++) {\n                Candidate merged = merge_two_candidates(elite_raw[i], elite_raw[j], g);\n                improve_and_consider(merged, g, false, true);\n            }\n        }\n    }\n\n    if (best.valid && best.D >= 1600 && elapsed_sec() < 1.45) {\n        Candidate polished = refine_to_finer_grid_multistart(best, mac, sar, 2);\n        if (polished.valid && polished.score > best.score) best = move(polished);\n    }\n\n    if (bestMergedGlobal.valid && bestMergedGlobal.D >= 1600 && elapsed_sec() < 1.30) {\n        Candidate polishedMerged = refine_to_finer_grid_multistart(bestMergedGlobal, mac, sar, 2);\n        if (polishedMerged.valid && polishedMerged.score > best.score) best = move(polishedMerged);\n    }\n\n    if (best.valid && best.D >= 1600 && elapsed_sec() < 1.20) {\n        Candidate polished2 = refine_to_finer_grid_multistart(best, mac, sar, 2);\n        if (polished2.valid && polished2.score > best.score) best = move(polished2);\n    }\n\n    if (bestSingleGlobal.valid && bestSingleGlobal.D >= 1600 && elapsed_sec() < 1.10) {\n        Candidate polishedSingle = refine_to_finer_grid_multistart(bestSingleGlobal, mac, sar, 2);\n        if (polishedSingle.valid && polishedSingle.score > best.score) best = move(polishedSingle);\n    }\n\n    // Wider local box only if there is plenty of time.\n    if (best.valid && best.D >= 1600 && elapsed_sec() < 1.00) {\n        Candidate wider = refine_to_finer_grid_multistart(best, mac, sar, 3);\n        if (wider.valid && wider.score > best.score) best = move(wider);\n    }\n\n    vector<pair<int,int>> out = best.valid ? best.poly : fallback_polygon();\n\n    if ((int)out.size() < 4 || (int)out.size() > 1000) out = fallback_polygon();\n    {\n        set<pair<int,int>> st(out.begin(), out.end());\n        if ((int)st.size() != (int)out.size()) out = fallback_polygon();\n    }\n    for (auto &p : out) {\n        p.first = max(0, min(100000, p.first));\n        p.second = max(0, min(100000, p.second));\n    }\n\n    cout << out.size() << '\\n';\n    for (auto &p : out) {\n        cout << p.first << ' ' << p.second << '\\n';\n    }\n    return 0;\n}","ahc040":"#include <bits/stdc++.h>\nusing namespace std;\n\nusing ll = long long;\n\nstruct Rect {\n    int w, h;\n};\n\nstruct Op {\n    int p, r;\n    char d;\n    int b;\n};\n\nstruct Candidate {\n    vector<Op> ops;\n    ll estW = 0, estH = 0, estScore = (1LL << 60);\n    int family = 0; // 0=columns, 1=rows\n    int mode = 0;\n    int k = 1;\n    int usedN = 0;\n    string tag;\n};\n\nstruct Solver {\n    int N, T, sigma;\n    vector<Rect> a;\n    vector<Candidate> pool;\n    static constexpr int MODES = 5;\n    mt19937 rng{123456789};\n\n    struct Dims {\n        int rot, w, h;\n    };\n    Dims dims[MODES][2][105];\n    vector<ll> suffixPenalty;\n\n    void precompute_dims() {\n        for (int mode = 0; mode < MODES; mode++) {\n            for (int i = 0; i < N; i++) {\n                for (int fc = 0; fc < 2; fc++) {\n                    bool forColumn = (fc == 1);\n                    int w = a[i].w, h = a[i].h;\n                    int rot = 0, ww = w, hh = h;\n                    auto apply_rot = [&](bool flag) {\n                        if (flag) {\n                            rot = 1;\n                            ww = h;\n                            hh = w;\n                        }\n                    };\n\n                    if (mode == 0) {\n                        if (forColumn) apply_rot(w > h);\n                        else apply_rot(h > w);\n                    } else if (mode == 1) {\n                    } else if (mode == 2) {\n                        if (forColumn) apply_rot(w < h);\n                        else apply_rot(h < w);\n                    } else if (mode == 3) {\n                        if (forColumn) apply_rot(h < w);\n                        else apply_rot(w < h);\n                    } else {\n                        if (forColumn) apply_rot(h > w);\n                        else apply_rot(w > h);\n                    }\n                    dims[mode][fc][i] = {rot, ww, hh};\n                }\n            }\n        }\n    }\n\n    void precompute_penalty() {\n        suffixPenalty.assign(N + 1, 0);\n        for (int i = N - 1; i >= 0; i--) {\n            suffixPenalty[i] = suffixPenalty[i + 1] + a[i].w + a[i].h;\n        }\n    }\n\n    struct GroupScore {\n        ll major = 0;\n        ll minor = 0;\n    };\n\n    GroupScore eval_group(int l, int r, int mode, bool forColumn) {\n        GroupScore gs;\n        if (!(0 <= l && l < r && r <= N)) return gs;\n        int fc = forColumn ? 1 : 0;\n        if (forColumn) {\n            ll mxw = 0, sumh = 0;\n            for (int i = l; i < r; i++) {\n                mxw = max<ll>(mxw, dims[mode][fc][i].w);\n                sumh += dims[mode][fc][i].h;\n            }\n            gs.major = mxw;   // width\n            gs.minor = sumh;  // height\n        } else {\n            ll sumw = 0, mxh = 0;\n            for (int i = l; i < r; i++) {\n                sumw += dims[mode][fc][i].w;\n                mxh = max<ll>(mxh, dims[mode][fc][i].h);\n            }\n            gs.major = sumw;  // width\n            gs.minor = mxh;   // height\n        }\n        return gs;\n    }\n\n    bool valid_groups(const vector<pair<int,int>>& groups, int usedN) {\n        if (usedN < 0 || usedN > N) return false;\n        if (usedN == 0) return groups.empty();\n        if (groups.empty()) return false;\n        if (groups.front().first != 0) return false;\n        if (groups.back().second != usedN) return false;\n        for (int i = 0; i < (int)groups.size(); i++) {\n            auto [l, r] = groups[i];\n            if (!(0 <= l && l < r && r <= usedN)) return false;\n            if (i > 0 && groups[i - 1].second != l) return false;\n        }\n        return true;\n    }\n\n    ll eval_partition(const vector<pair<int,int>>& groups, int usedN, int mode, bool forColumn, ll &outW, ll &outH) {\n        if (!valid_groups(groups, usedN)) {\n            outW = outH = (ll)4e18;\n            return (ll)4e18;\n        }\n\n        if (usedN == 0) {\n            outW = outH = 0;\n            return suffixPenalty[0];\n        }\n\n        if (forColumn) {\n            ll totalW = 0, totalH = 0;\n            for (auto [l, r] : groups) {\n                auto gs = eval_group(l, r, mode, true);\n                totalW += gs.major;\n                totalH = max(totalH, gs.minor);\n            }\n            outW = totalW;\n            outH = totalH;\n        } else {\n            ll totalW = 0, totalH = 0;\n            for (auto [l, r] : groups) {\n                auto gs = eval_group(l, r, mode, false);\n                totalW = max(totalW, gs.major);\n                totalH += gs.minor;\n            }\n            outW = totalW;\n            outH = totalH;\n        }\n        return outW + outH + suffixPenalty[usedN];\n    }\n\n    vector<pair<int,int>> groups_equal(int k, int usedN) {\n        vector<pair<int,int>> groups;\n        if (usedN == 0) return groups;\n        k = min(k, usedN);\n        int l = 0;\n        for (int g = 0; g < k; g++) {\n            int r = (ll)usedN * (g + 1) / k;\n            if (r <= l) r = l + 1;\n            if (g == k - 1) r = usedN;\n            groups.push_back({l, r});\n            l = r;\n        }\n        groups.back().second = usedN;\n        return groups;\n    }\n\n    vector<pair<int,int>> groups_balanced_sum(int k, int usedN, int mode, bool forColumn) {\n        vector<pair<int,int>> groups;\n        if (usedN == 0) return groups;\n        k = min(k, usedN);\n\n        vector<ll> weight(usedN);\n        int fc = forColumn ? 1 : 0;\n        for (int i = 0; i < usedN; i++) {\n            weight[i] = forColumn ? dims[mode][fc][i].h : dims[mode][fc][i].w;\n        }\n\n        ll total = 0;\n        for (ll x : weight) total += x;\n\n        int l = 0, p = 0;\n        ll pref = 0;\n        for (int g = 1; g < k; g++) {\n            ll target = total * g / k;\n            while (p < usedN - (k - g) && pref + weight[p] <= target) {\n                pref += weight[p];\n                p++;\n            }\n            int r = max(l + 1, p);\n            groups.push_back({l, r});\n            l = r;\n        }\n        groups.push_back({l, usedN});\n        if (!valid_groups(groups, usedN)) return groups_equal(k, usedN);\n        return groups;\n    }\n\n    vector<pair<int,int>> groups_balanced_target(int k, int usedN, int mode, bool forColumn) {\n        vector<pair<int,int>> groups;\n        if (usedN == 0) return groups;\n        k = min(k, usedN);\n\n        int fc = forColumn ? 1 : 0;\n        ll totalStack = 0;\n        for (int i = 0; i < usedN; i++) {\n            totalStack += forColumn ? dims[mode][fc][i].h : dims[mode][fc][i].w;\n        }\n\n        ll target = max<ll>(1, totalStack / k);\n        int l = 0;\n        ll cur = 0;\n        for (int i = 0; i < usedN; i++) {\n            cur += forColumn ? dims[mode][fc][i].h : dims[mode][fc][i].w;\n            int remainRects = usedN - (i + 1);\n            int remainGroups = k - (int)groups.size() - 1;\n            bool canCut = remainGroups > 0 && remainRects >= remainGroups;\n            if (canCut && cur >= target) {\n                groups.push_back({l, i + 1});\n                l = i + 1;\n                cur = 0;\n            }\n        }\n        groups.push_back({l, usedN});\n        if (!valid_groups(groups, usedN)) return groups_equal(k, usedN);\n        return groups;\n    }\n\n    vector<pair<int,int>> groups_dp_seed(int k, int usedN, int mode, bool forColumn, int alpha) {\n        vector<pair<int,int>> empty;\n        if (usedN == 0) return empty;\n        k = min(k, usedN);\n        const ll INF = (1LL << 60);\n\n        static ll cost[105][105];\n        for (int l = 0; l < usedN; l++) {\n            ll a = 0, b = 0;\n            if (forColumn) {\n                ll mxw = 0, sumh = 0;\n                for (int r = l + 1; r <= usedN; r++) {\n                    mxw = max<ll>(mxw, dims[mode][1][r - 1].w);\n                    sumh += dims[mode][1][r - 1].h;\n                    cost[l][r] = mxw + (ll)alpha * sumh / 1000;\n                }\n            } else {\n                ll sumw = 0, mxh = 0;\n                for (int r = l + 1; r <= usedN; r++) {\n                    sumw += dims[mode][0][r - 1].w;\n                    mxh = max<ll>(mxh, dims[mode][0][r - 1].h);\n                    cost[l][r] = sumw + (ll)alpha * mxh / 1000;\n                }\n            }\n        }\n\n        static ll dp[25][105];\n        static int pre[25][105];\n        for (int i = 0; i <= k; i++) {\n            for (int j = 0; j <= usedN; j++) {\n                dp[i][j] = INF;\n                pre[i][j] = -1;\n            }\n        }\n        dp[0][0] = 0;\n\n        for (int g = 0; g < k; g++) {\n            for (int i = 0; i < usedN; i++) {\n                if (dp[g][i] >= INF) continue;\n                for (int r = i + 1; r <= usedN; r++) {\n                    if (usedN - r < (k - g - 1)) break;\n                    ll ndp = dp[g][i] + cost[i][r];\n                    if (ndp < dp[g + 1][r]) {\n                        dp[g + 1][r] = ndp;\n                        pre[g + 1][r] = i;\n                    }\n                }\n            }\n        }\n\n        if (dp[k][usedN] >= INF) return groups_equal(k, usedN);\n\n        vector<pair<int,int>> groups;\n        int cur = usedN;\n        for (int g = k; g >= 1; g--) {\n            int p = pre[g][cur];\n            if (p < 0) return groups_equal(k, usedN);\n            groups.push_back({p, cur});\n            cur = p;\n        }\n        reverse(groups.begin(), groups.end());\n        if (!valid_groups(groups, usedN)) return groups_equal(k, usedN);\n        return groups;\n    }\n\n    void local_improve(vector<pair<int,int>>& groups, int usedN, int mode, bool forColumn) {\n        if ((int)groups.size() <= 1 || !valid_groups(groups, usedN)) return;\n\n        ll curW, curH;\n        ll curScore = eval_partition(groups, usedN, mode, forColumn, curW, curH);\n\n        bool improved = true;\n        int iter = 35;\n        while (improved && iter--) {\n            improved = false;\n            for (int i = 0; i + 1 < (int)groups.size(); i++) {\n                int l1 = groups[i].first, r1 = groups[i].second;\n                int r2 = groups[i + 1].second;\n                int bd = r1;\n\n                int bestBd = bd;\n                ll bestScore = curScore;\n                ll bestBalance = llabs(curW - curH);\n\n                int L = max(l1 + 1, bd - 2);\n                int R = min(r2 - 1, bd + 2);\n                for (int nb = L; nb <= R; nb++) {\n                    if (nb == bd) continue;\n                    auto ng = groups;\n                    ng[i] = {l1, nb};\n                    ng[i + 1] = {nb, r2};\n                    if (!valid_groups(ng, usedN)) continue;\n                    ll w, h;\n                    ll sc = eval_partition(ng, usedN, mode, forColumn, w, h);\n                    ll bal = llabs(w - h);\n                    if (sc < bestScore || (sc == bestScore && bal < bestBalance)) {\n                        bestScore = sc;\n                        bestBalance = bal;\n                        bestBd = nb;\n                    }\n                }\n\n                if (bestBd != bd) {\n                    groups[i].second = bestBd;\n                    groups[i + 1].first = bestBd;\n                    curScore = bestScore;\n                    ll w, h;\n                    eval_partition(groups, usedN, mode, forColumn, w, h);\n                    curW = w;\n                    curH = h;\n                    improved = true;\n                }\n            }\n        }\n    }\n\n    Candidate build_candidate(const vector<pair<int,int>>& groups, int usedN, int mode, bool forColumn, const string& tag) {\n        Candidate c;\n        c.family = forColumn ? 0 : 1;\n        c.mode = mode;\n        c.k = (int)groups.size();\n        c.usedN = usedN;\n        c.tag = tag;\n\n        ll W, H;\n        c.estScore = eval_partition(groups, usedN, mode, forColumn, W, H);\n        c.estW = W;\n        c.estH = H;\n\n        vector<int> firsts;\n        int fc = forColumn ? 1 : 0;\n        for (int g = 0; g < (int)groups.size(); g++) {\n            auto [l, r] = groups[g];\n            int first = l;\n            firsts.push_back(first);\n            for (int i = l; i < r; i++) {\n                int rot = dims[mode][fc][i].rot;\n                int b = (i == l ? (g == 0 ? -1 : firsts[g - 1]) : first);\n                c.ops.push_back({i, rot, forColumn ? 'U' : 'L', b});\n            }\n        }\n\n        int prevp = -1;\n        for (auto &op : c.ops) {\n            if (!(0 <= op.p && op.p < usedN)) {\n                c.ops.clear();\n                break;\n            }\n            if (!(op.p > prevp)) {\n                c.ops.clear();\n                break;\n            }\n            if (!(op.b == -1 || (0 <= op.b && op.b < op.p))) {\n                c.ops.clear();\n                break;\n            }\n            prevp = op.p;\n        }\n        if (c.ops.empty() && usedN > 0) {\n            for (int i = 0; i < usedN; i++) c.ops.push_back({i, 0, 'U', -1});\n        }\n\n        return c;\n    }\n\n    void try_add(vector<pair<int,int>> groups, int usedN, int mode, bool forColumn, const string& prefix) {\n        if (!valid_groups(groups, usedN)) return;\n        local_improve(groups, usedN, mode, forColumn);\n        if (!valid_groups(groups, usedN)) return;\n        pool.push_back(build_candidate(\n            groups, usedN, mode, forColumn,\n            prefix + \"_u\" + to_string(usedN) + \"_k\" + to_string((int)groups.size()) + \"_m\" + to_string(mode)\n        ));\n    }\n\n    vector<pair<int,int>> ops_to_groups(const Candidate& c) {\n        vector<pair<int,int>> groups;\n        if (c.usedN == 0) return groups;\n\n        int i = 0;\n        while (i < (int)c.ops.size()) {\n            int l = c.ops[i].p;\n            int first = l;\n            int j = i + 1;\n            while (j < (int)c.ops.size() && c.ops[j].b == first) j++;\n            int r = (j < (int)c.ops.size() ? c.ops[j].p : c.usedN);\n            groups.push_back({l, r});\n            i = j;\n        }\n\n        if (!valid_groups(groups, c.usedN)) {\n            groups.clear();\n            groups.push_back({0, c.usedN});\n        }\n        return groups;\n    }\n\n    Candidate mutate_candidate(const Candidate& base, int strength, int repId) {\n        auto groups = ops_to_groups(base);\n        if (!valid_groups(groups, base.usedN) || (int)groups.size() <= 1) return base;\n\n        int moves = min((int)groups.size() - 1, max(1, strength));\n        for (int s = 0; s < moves; s++) {\n            int i = uniform_int_distribution<int>(0, (int)groups.size() - 2)(rng);\n            int l1 = groups[i].first, r1 = groups[i].second;\n            int r2 = groups[i + 1].second;\n            int bd = r1;\n\n            int span = 1 + strength;\n            int L = max(l1 + 1, bd - span);\n            int R = min(r2 - 1, bd + span);\n            if (L > R) continue;\n            int nb = uniform_int_distribution<int>(L, R)(rng);\n            groups[i].second = nb;\n            groups[i + 1].first = nb;\n        }\n\n        if (!valid_groups(groups, base.usedN)) return base;\n        local_improve(groups, base.usedN, base.mode, base.family == 0);\n        if (!valid_groups(groups, base.usedN)) return base;\n\n        return build_candidate(\n            groups, base.usedN, base.mode, base.family == 0,\n            \"mut_\" + base.tag + \"_s\" + to_string(strength) + \"_r\" + to_string(repId)\n        );\n    }\n\n    void add_offline_mutations() {\n        if (pool.empty()) return;\n\n        int baseCount = min<int>((int)pool.size(), 24);\n        vector<Candidate> extra;\n\n        for (int bi = 0; bi < baseCount; bi++) {\n            const Candidate &base = pool[bi];\n            if (base.usedN <= 1 || base.k <= 1) continue;\n\n            int repMax = 5;\n            for (int rep = 0; rep < repMax; rep++) {\n                int strength = 1 + (rep % 4);\n                extra.push_back(mutate_candidate(base, strength, rep));\n            }\n        }\n\n        for (auto &c : extra) pool.push_back(c);\n    }\n\n    void dedup_and_sort_pool() {\n        unordered_set<string> seen;\n        vector<Candidate> uniq;\n        uniq.reserve(pool.size());\n\n        for (auto &c : pool) {\n            string key;\n            key.reserve(c.ops.size() * 12 + 20);\n            key += \"u\";\n            key += to_string(c.usedN);\n            key += \";\";\n            for (auto &op : c.ops) {\n                key += to_string(op.p);\n                key += ',';\n                key += char('0' + op.r);\n                key += ',';\n                key += op.d;\n                key += ',';\n                key += to_string(op.b);\n                key += ';';\n            }\n            if (seen.insert(key).second) uniq.push_back(c);\n        }\n        pool.swap(uniq);\n\n        sort(pool.begin(), pool.end(), [&](const Candidate& x, const Candidate& y) {\n            if (x.estScore != y.estScore) return x.estScore < y.estScore;\n            ll bx = llabs(x.estW - x.estH), by = llabs(y.estW - y.estH);\n            if (bx != by) return bx < by;\n            if (x.usedN != y.usedN) return x.usedN > y.usedN;\n            if (x.family != y.family) return x.family < y.family;\n            if (x.k != y.k) return x.k < y.k;\n            return x.mode < y.mode;\n        });\n    }\n\n    void build_pool() {\n        pool.clear();\n        precompute_dims();\n        precompute_penalty();\n\n        int K = min(N, 16);\n        vector<int> usedList = {N};\n        if (N >= 40) {\n            usedList.push_back(max(1, N * 95 / 100));\n            usedList.push_back(max(1, N * 90 / 100));\n            usedList.push_back(max(1, N * 85 / 100));\n        } else {\n            usedList.push_back(max(1, N - 2));\n            usedList.push_back(max(1, N - 4));\n        }\n        sort(usedList.begin(), usedList.end());\n        usedList.erase(unique(usedList.begin(), usedList.end()), usedList.end());\n\n        for (int usedN : usedList) {\n            int curK = min(K, usedN);\n            for (int mode = 0; mode < MODES; mode++) {\n                for (int k = 1; k <= curK; k++) {\n                    try_add(groups_equal(k, usedN), usedN, mode, true,  \"col_eq\");\n                    try_add(groups_equal(k, usedN), usedN, mode, false, \"row_eq\");\n\n                    if (k >= 2) {\n                        try_add(groups_balanced_sum(k, usedN, mode, true),  usedN, mode, true,  \"col_bsum\");\n                        try_add(groups_balanced_sum(k, usedN, mode, false), usedN, mode, false, \"row_bsum\");\n                        try_add(groups_balanced_target(k, usedN, mode, true),  usedN, mode, true,  \"col_btgt\");\n                        try_add(groups_balanced_target(k, usedN, mode, false), usedN, mode, false, \"row_btgt\");\n                    }\n                }\n            }\n\n            // Add a few DP seeds for stronger partitions\n            vector<int> dpModes = {0, 1, 3};\n            vector<int> alphas = {250, 500, 1000};\n            for (int mode : dpModes) {\n                for (int k = 2; k <= min(curK, 12); k++) {\n                    for (int alpha : alphas) {\n                        try_add(groups_dp_seed(k, usedN, mode, true, alpha), usedN, mode, true,\n                                \"col_dp\" + to_string(alpha));\n                        try_add(groups_dp_seed(k, usedN, mode, false, alpha), usedN, mode, false,\n                                \"row_dp\" + to_string(alpha));\n                    }\n                }\n            }\n        }\n\n        dedup_and_sort_pool();\n        add_offline_mutations();\n        dedup_and_sort_pool();\n\n        if (pool.empty()) {\n            Candidate c;\n            c.tag = \"fallback\";\n            c.usedN = N;\n            for (int i = 0; i < N; i++) c.ops.push_back({i, 0, 'U', -1});\n            pool.push_back(c);\n        }\n    }\n\n    int aspect_bucket(const Candidate& c) {\n        if (c.estW == 0 || c.estH == 0) return 0;\n        double r = (double)c.estW / (double)c.estH;\n        if (r < 0.60) return 0;\n        if (r < 0.80) return 1;\n        if (r < 1.00) return 2;\n        if (r < 1.25) return 3;\n        if (r < 1.60) return 4;\n        return 5;\n    }\n\n    void print_candidate(const Candidate& c) {\n        cout << c.ops.size() << '\\n';\n        for (auto &op : c.ops) {\n            cout << op.p << ' ' << op.r << ' ' << op.d << ' ' << op.b << '\\n';\n        }\n        cout.flush();\n    }\n\n    ll neighborhood_cost(const Candidate& a, const Candidate& b) {\n        ll cost = 0;\n        cost += 2000000LL * (a.family != b.family);\n        cost += 250000LL * llabs(a.k - b.k);\n        cost += 60000LL * llabs(a.usedN - b.usedN);\n        cost += 120000LL * llabs(a.mode - b.mode);\n        cost += 120000LL * llabs(aspect_bucket(a) - aspect_bucket(b));\n        cost += llabs(a.estScore - b.estScore) / 10;\n        return cost;\n    }\n\n    void solve() {\n        ios::sync_with_stdio(false);\n        cin.tie(nullptr);\n\n        cin >> N >> T >> sigma;\n        a.resize(N);\n        for (int i = 0; i < N; i++) cin >> a[i].w >> a[i].h;\n\n        build_pool();\n\n        int P = (int)pool.size();\n        vector<int> tested(P, 0);\n        vector<ll> measured(P, (1LL << 60));\n\n        vector<int> initialOrder;\n        set<tuple<int,int,int,int>> usedKey;\n\n        for (int i = 0; i < P; i++) {\n            auto key = make_tuple(pool[i].family, pool[i].k, pool[i].usedN, pool[i].mode);\n            if (!usedKey.count(key)) {\n                usedKey.insert(key);\n                initialOrder.push_back(i);\n            }\n            if ((int)initialOrder.size() >= min(T, 36)) break;\n        }\n\n        for (int i = 0; i < P && (int)initialOrder.size() < min(T, 110); i++) {\n            bool exists = false;\n            for (int x : initialOrder) if (x == i) { exists = true; break; }\n            if (!exists) initialOrder.push_back(i);\n        }\n\n        ll bestMeasured = (1LL << 60);\n        int bestIdx = 0;\n\n        for (int t = 0; t < T; t++) {\n            int idx = -1;\n\n            if (t < (int)initialOrder.size()) {\n                idx = initialOrder[t];\n            } else {\n                vector<int> anchors;\n                vector<pair<ll,int>> ord;\n                for (int i = 0; i < P; i++) if (tested[i]) ord.push_back({measured[i], i});\n                sort(ord.begin(), ord.end());\n\n                int take = min<int>(5, ord.size());\n                for (int i = 0; i < take; i++) anchors.push_back(ord[i].second);\n                if (anchors.empty()) anchors.push_back(bestIdx);\n\n                ll bestRank = (1LL << 62);\n                for (int i = 0; i < P; i++) {\n                    if (tested[i]) continue;\n                    ll rank = (1LL << 62);\n                    for (int aidx : anchors) {\n                        rank = min(rank, neighborhood_cost(pool[i], pool[aidx]));\n                    }\n                    if (rank < bestRank) {\n                        bestRank = rank;\n                        idx = i;\n                    }\n                }\n\n                if (idx == -1) idx = bestIdx;\n            }\n\n            cout << \"# \" << pool[idx].tag\n                 << \" est=\" << pool[idx].estW << \"+\" << pool[idx].estH\n                 << \"+\" << suffixPenalty[pool[idx].usedN]\n                 << \"=\" << pool[idx].estScore << \"\\n\";\n            print_candidate(pool[idx]);\n\n            ll Wm, Hm;\n            cin >> Wm >> Hm;\n            ll sm = Wm + Hm + suffixPenalty[pool[idx].usedN];\n\n            tested[idx] = 1;\n            measured[idx] = sm;\n\n            if (sm < bestMeasured) {\n                bestMeasured = sm;\n                bestIdx = idx;\n            }\n        }\n    }\n};\n\nint main() {\n    Solver solver;\n    solver.solve();\n    return 0;\n}","ahc041":"#include <bits/stdc++.h>\nusing namespace std;\n\nstruct Candidate {\n    int depth;\n    int beauty;\n    int parent;\n    int vertex;\n    bool operator<(const Candidate& other) const {\n        if (depth != other.depth) return depth < other.depth;\n        if (beauty != other.beauty) return beauty < other.beauty;\n        if (parent != other.parent) return parent < other.parent;\n        return vertex < other.vertex;\n    }\n};\n\nstruct Result {\n    vector<int> parent;\n    long long score;\n};\n\nstatic uint64_t rng_state =\n    chrono::steady_clock::now().time_since_epoch().count();\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 double frand() {\n    return (rng64() >> 11) * (1.0 / (1ULL << 53));\n}\n\nstatic Result build_with_order(\n    int N, int H,\n    const vector<int>& A,\n    const vector<vector<int>>& g,\n    const vector<int>& ord\n) {\n    vector<int> parent(N, -2);\n    vector<int> depth(N, -1);\n\n    priority_queue<Candidate> pq;\n\n    auto add_frontier = [&](int u) {\n        if (depth[u] >= H) return;\n        for (int v : g[u]) {\n            if (parent[v] == -2) {\n                pq.push(Candidate{depth[u] + 1, A[v], u, v});\n            }\n        }\n    };\n\n    int ptr = 0;\n    while (true) {\n        while (ptr < N && parent[ord[ptr]] != -2) ptr++;\n        if (ptr == N) break;\n\n        int r = ord[ptr];\n        parent[r] = -1;\n        depth[r] = 0;\n        add_frontier(r);\n\n        while (!pq.empty()) {\n            Candidate cur = pq.top();\n            pq.pop();\n\n            int v = cur.vertex;\n            int p = cur.parent;\n\n            if (parent[v] != -2) continue;\n            if (parent[p] == -2) continue;\n            if (depth[p] + 1 != cur.depth) continue;\n            if (cur.depth > H) continue;\n\n            parent[v] = p;\n            depth[v] = cur.depth;\n            add_frontier(v);\n        }\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (parent[i] == -2) {\n            parent[i] = -1;\n            depth[i] = 0;\n        }\n    }\n\n    long long score = 1;\n    for (int i = 0; i < N; i++) {\n        score += 1LL * (depth[i] + 1) * A[i];\n    }\n\n    return {parent, score};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int N, M, H;\n    cin >> N >> M >> H;\n\n    vector<int> A(N);\n    for (int i = 0; i < N; i++) cin >> A[i];\n\n    vector<vector<int>> g(N);\n    vector<pair<int,int>> edges(M);\n    for (int i = 0; i < M; i++) {\n        int u, v;\n        cin >> u >> v;\n        edges[i] = {u, v};\n        g[u].push_back(v);\n        g[v].push_back(u);\n    }\n\n    vector<pair<int,int>> pos(N);\n    for (int i = 0; i < N; i++) {\n        int x, y;\n        cin >> x >> y;\n        pos[i] = {x, y};\n    }\n\n    vector<int> deg(N);\n    for (int i = 0; i < N; i++) deg[i] = (int)g[i].size();\n\n    long long sx = 0, sy = 0;\n    for (int i = 0; i < N; i++) {\n        sx += pos[i].first;\n        sy += pos[i].second;\n    }\n    double cx = (double)sx / N;\n    double cy = (double)sy / N;\n\n    vector<double> dist2(N);\n    for (int i = 0; i < N; i++) {\n        double dx = pos[i].first - cx;\n        double dy = pos[i].second - cy;\n        dist2[i] = dx * dx + dy * dy;\n    }\n\n    vector<double> avgNbrA(N, 0.0), maxNbrA(N, 0.0);\n    for (int i = 0; i < N; i++) {\n        if (deg[i] == 0) continue;\n        for (int to : g[i]) {\n            avgNbrA[i] += A[to];\n            maxNbrA[i] = max(maxNbrA[i], (double)A[to]);\n        }\n        avgNbrA[i] /= deg[i];\n    }\n\n    vector<int> base(N);\n    iota(base.begin(), base.end(), 0);\n\n    Result best{{}, -1};\n\n    auto try_order = [&](vector<int>& ord) {\n        Result cur = build_with_order(N, H, A, g, ord);\n        if (cur.score > best.score) best = std::move(cur);\n    };\n\n    auto try_key = [&](const vector<double>& key) {\n        auto ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (key[a] != key[b]) return key[a] < key[b];\n            if (A[a] != A[b]) return A[a] < A[b];\n            return a < b;\n        });\n        try_order(ord);\n    };\n\n    // Strong deterministic seeds\n    {\n        auto ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] < A[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    {\n        auto ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (A[a] != A[b]) return A[a] < A[b];\n            if (deg[a] != deg[b]) return deg[a] > deg[b];\n            return a < b;\n        });\n        try_order(ord);\n    }\n    {\n        auto ord = base;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            long long lhs = 1LL * A[a] * (deg[b] + 1);\n            long long rhs = 1LL * A[b] * (deg[a] + 1);\n            if (lhs != rhs) return lhs < rhs;\n            return a < b;\n        });\n        try_order(ord);\n    }\n    {\n        vector<double> key(N);\n        for (int i = 0; i < N; i++) key[i] = A[i] - 0.35 * deg[i] - 0.08 * avgNbrA[i];\n        try_key(key);\n    }\n    {\n        vector<double> key(N);\n        for (int i = 0; i < N; i++) key[i] = A[i] - 0.25 * deg[i] - 0.08 * avgNbrA[i] + 0.0005 * dist2[i];\n        try_key(key);\n    }\n    {\n        vector<double> key(N);\n        for (int i = 0; i < N; i++) key[i] = A[i] - 0.25 * deg[i] - 0.08 * avgNbrA[i] - 0.0005 * dist2[i];\n        try_key(key);\n    }\n    {\n        vector<double> key(N);\n        for (int i = 0; i < N; i++) key[i] = A[i] - 0.45 * deg[i];\n        try_key(key);\n    }\n    {\n        vector<double> key(N);\n        for (int i = 0; i < N; i++) key[i] = A[i] - 0.20 * deg[i] - 0.12 * maxNbrA[i];\n        try_key(key);\n    }\n\n    auto start = chrono::steady_clock::now();\n\n    // Focused randomized search around promising families\n    while (true) {\n        double elapsed = chrono::duration<double>(chrono::steady_clock::now() - start).count();\n        if (elapsed > 1.92) break;\n\n        int mode = (int)(rng64() % 6);\n        vector<double> key(N);\n\n        if (mode == 0) {\n            double wd = 0.25 + 0.30 * frand();\n            double wa = 0.04 + 0.10 * frand();\n            for (int i = 0; i < N; i++) {\n                key[i] = A[i] - wd * deg[i] - wa * avgNbrA[i] + 0.3 * frand();\n            }\n        } else if (mode == 1) {\n            double wd = 0.15 + 0.25 * frand();\n            double wa = 0.04 + 0.10 * frand();\n            double wg = (frand() * 2.0 - 1.0) * 0.0012;\n            for (int i = 0; i < N; i++) {\n                key[i] = A[i] - wd * deg[i] - wa * avgNbrA[i] + wg * dist2[i] + 0.3 * frand();\n            }\n        } else if (mode == 2) {\n            double wd = 0.25 + 0.35 * frand();\n            for (int i = 0; i < N; i++) {\n                key[i] = A[i] - wd * deg[i] + 0.5 * frand();\n            }\n        } else if (mode == 3) {\n            double wd = 0.12 + 0.25 * frand();\n            double wm = 0.05 + 0.12 * frand();\n            for (int i = 0; i < N; i++) {\n                key[i] = A[i] - wd * deg[i] - wm * maxNbrA[i] + 0.3 * frand();\n            }\n        } else if (mode == 4) {\n            double scale = 50.0 + 100.0 * frand();\n            double dd = 4.0 + 8.0 * frand();\n            double gg = (frand() * 2.0 - 1.0) * 0.08;\n            for (int i = 0; i < N; i++) {\n                key[i] = scale * A[i] - dd * deg[i] + gg * (dist2[i] / 1000.0) + (rng64() % 50);\n            }\n        } else {\n            double wd = 0.20 + 0.30 * frand();\n            double wa = 0.04 + 0.08 * frand();\n            double wm = 0.02 + 0.08 * frand();\n            for (int i = 0; i < N; i++) {\n                key[i] = A[i] - wd * deg[i] - wa * avgNbrA[i] - wm * maxNbrA[i] + 0.3 * frand();\n            }\n        }\n\n        try_key(key);\n    }\n\n    for (int i = 0; i < N; i++) {\n        if (i) cout << ' ';\n        cout << best.parent[i];\n    }\n    cout << '\\n';\n\n    return 0;\n}","ahc042":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int LIMIT = 4 * N * N; // 1600\nstatic constexpr int MAX_GREEDY_ITERS = 100;\nstatic constexpr int NUM_POLICIES = 4;\n\nstruct Op {\n    char d;\n    int p;\n};\n\nstruct Cand {\n    char d;\n    int p;\n    int k;\n    int removed;\n};\n\nstruct EvalCand {\n    char d;\n    int p;\n    int k;\n    int removed;\n    int newCost;\n    int gain;\n    bool valid = false;\n};\n\nstatic inline void apply_move(vector<string>& b, char d, int p) {\n    if (d == 'L') {\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        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        for (int i = 0; i + 1 < N; ++i) b[i][p] = b[i + 1][p];\n        b[N - 1][p] = '.';\n    } else if (d == 'D') {\n        for (int i = N - 1; i >= 1; --i) b[i][p] = b[i - 1][p];\n        b[0][p] = '.';\n    }\n}\n\nstatic inline int safe_limit(const vector<string>& b, char d, int p) {\n    int safe = 0;\n    if (d == 'L') {\n        while (safe < N && b[p][safe] != 'o') ++safe;\n    } else if (d == 'R') {\n        while (safe < N && b[p][N - 1 - safe] != 'o') ++safe;\n    } else if (d == 'U') {\n        while (safe < N && b[safe][p] != 'o') ++safe;\n    } else { // D\n        while (safe < N && b[N - 1 - safe][p] != 'o') ++safe;\n    }\n    return safe;\n}\n\nstatic inline int count_oni(const vector<string>& b) {\n    int x = 0;\n    for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) x += (b[i][j] == 'x');\n    return x;\n}\n\nstatic inline int fallback_cost_sum(const vector<string>& b) {\n    int total = 0;\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (b[i][j] != 'x') continue;\n            int best = INT_MAX;\n\n            bool ok = true;\n            for (int r = 0; r < i; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (i + 1));\n\n            ok = true;\n            for (int r = i + 1; r < N; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (N - i));\n\n            ok = true;\n            for (int c = 0; c < j; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (j + 1));\n\n            ok = true;\n            for (int c = j + 1; c < N; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) best = min(best, 2 * (N - j));\n\n            total += best;\n        }\n    }\n    return total;\n}\n\nstatic inline bool ratio_better(int rem1, int k1, int rem2, int k2) {\n    long long lhs = 1LL * rem1 * k2;\n    long long rhs = 1LL * rem2 * k1;\n    if (lhs != rhs) return lhs > rhs;\n    if (rem1 != rem2) return rem1 > rem2;\n    return k1 < k2;\n}\n\nstatic inline void add_candidate_unique(vector<Cand>& v, const Cand& c) {\n    for (auto &x : v) {\n        if (x.d == c.d && x.p == c.p && x.k == c.k) return;\n    }\n    v.push_back(c);\n}\n\nstatic inline bool find_best_fallback_action(\n    const vector<string>& b, int &oi, int &oj, char &od, int &olen\n) {\n    int bestCost = INT_MAX;\n    bool found = false;\n\n    for (int i = 0; i < N; ++i) {\n        for (int j = 0; j < N; ++j) {\n            if (b[i][j] != 'x') continue;\n\n            int localBest = INT_MAX;\n            char localDir = '?';\n            int localLen = -1;\n\n            bool ok = true;\n            for (int r = 0; r < i; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int c = 2 * (i + 1);\n                if (c < localBest) localBest = c, localDir = 'U', localLen = i + 1;\n            }\n\n            ok = true;\n            for (int r = i + 1; r < N; ++r) {\n                if (b[r][j] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int c = 2 * (N - i);\n                if (c < localBest) localBest = c, localDir = 'D', localLen = N - i;\n            }\n\n            ok = true;\n            for (int c = 0; c < j; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int cst = 2 * (j + 1);\n                if (cst < localBest) localBest = cst, localDir = 'L', localLen = j + 1;\n            }\n\n            ok = true;\n            for (int c = j + 1; c < N; ++c) {\n                if (b[i][c] == 'o') { ok = false; break; }\n            }\n            if (ok) {\n                int cst = 2 * (N - j);\n                if (cst < localBest) localBest = cst, localDir = 'R', localLen = N - j;\n            }\n\n            if (localBest < bestCost) {\n                bestCost = localBest;\n                oi = i;\n                oj = j;\n                od = localDir;\n                olen = localLen;\n                found = true;\n            }\n        }\n    }\n    return found;\n}\n\nstatic inline bool better_eval(const EvalCand& a, const EvalCand& b, int policy) {\n    if (!b.valid) return true;\n    if (a.gain != b.gain) return a.gain > b.gain;\n\n    if (policy == 0) {\n        if (a.removed != b.removed) return a.removed > b.removed;\n        if (a.k != b.k) return a.k < b.k;\n    } else if (policy == 1) {\n        if (a.k != b.k) return a.k < b.k;\n        if (a.removed != b.removed) return a.removed > b.removed;\n    } else if (policy == 2) {\n        long long lhs = 1LL * a.removed * b.k;\n        long long rhs = 1LL * b.removed * a.k;\n        if (lhs != rhs) return lhs > rhs;\n        if (a.removed != b.removed) return a.removed > b.removed;\n        if (a.k != b.k) return a.k < b.k;\n    } else { // policy == 3\n        if (a.removed != b.removed) return a.removed > b.removed;\n        if (a.k != b.k) return a.k > b.k;\n    }\n\n    if (a.d != b.d) return a.d < b.d;\n    return a.p < b.p;\n}\n\nstatic vector<Cand> generate_candidates(const vector<string>& board) {\n    vector<Cand> cands;\n    cands.reserve(320);\n    const char dirs[4] = {'L', 'R', 'U', 'D'};\n\n    for (char d : dirs) {\n        for (int p = 0; p < N; ++p) {\n            int lim = safe_limit(board, d, p);\n            if (lim == 0) continue;\n\n            int removed = 0;\n            bool hasPos = false;\n\n            int firstPosK = -1, firstPosRem = -1;\n            int bestRatioK = -1, bestRatioRem = -1;\n            int bestAbsK = -1, bestAbsRem = -1;\n            int longestMaxK = -1, longestMaxRem = -1;\n\n            for (int k = 1; k <= lim; ++k) {\n                if (d == 'L') {\n                    if (board[p][k - 1] == 'x') ++removed;\n                } else if (d == 'R') {\n                    if (board[p][N - k] == 'x') ++removed;\n                } else if (d == 'U') {\n                    if (board[k - 1][p] == 'x') ++removed;\n                } else {\n                    if (board[N - k][p] == 'x') ++removed;\n                }\n\n                if (removed <= 0) continue;\n\n                if (!hasPos) {\n                    hasPos = true;\n                    firstPosK = k;\n                    firstPosRem = removed;\n                    bestRatioK = k;\n                    bestRatioRem = removed;\n                    bestAbsK = k;\n                    bestAbsRem = removed;\n                    longestMaxK = k;\n                    longestMaxRem = removed;\n                } else {\n                    if (ratio_better(removed, k, bestRatioRem, bestRatioK)) {\n                        bestRatioK = k;\n                        bestRatioRem = removed;\n                    }\n                    if (removed > bestAbsRem || (removed == bestAbsRem && k < bestAbsK)) {\n                        bestAbsK = k;\n                        bestAbsRem = removed;\n                    }\n                    if (removed > longestMaxRem || (removed == longestMaxRem && k > longestMaxK)) {\n                        longestMaxK = k;\n                        longestMaxRem = removed;\n                    }\n                }\n            }\n\n            if (hasPos) {\n                add_candidate_unique(cands, {d, p, firstPosK, firstPosRem});\n                add_candidate_unique(cands, {d, p, bestRatioK, bestRatioRem});\n                add_candidate_unique(cands, {d, p, bestAbsK, bestAbsRem});\n                add_candidate_unique(cands, {d, p, longestMaxK, longestMaxRem});\n            }\n        }\n    }\n    return cands;\n}\n\nstatic bool try_setup_rescue(vector<string>& board, vector<Op>& ans) {\n    int used = (int)ans.size();\n    int curCost = fallback_cost_sum(board);\n    int xcnt = count_oni(board);\n\n    // Only use this in tight endgames.\n    if (!(xcnt <= 6 || used + curCost >= LIMIT - 40)) return false;\n\n    EvalCand best;\n    const char dirs[4] = {'L', 'R', 'U', 'D'};\n    for (char d : dirs) {\n        for (int p = 0; p < N; ++p) {\n            if (safe_limit(board, d, p) < 1) continue;\n            if (used + 1 > LIMIT) continue;\n\n            vector<string> tmp = board;\n            int removed = 0;\n            if (d == 'L') removed = (tmp[p][0] == 'x');\n            else if (d == 'R') removed = (tmp[p][N - 1] == 'x');\n            else if (d == 'U') removed = (tmp[0][p] == 'x');\n            else removed = (tmp[N - 1][p] == 'x');\n\n            apply_move(tmp, d, p);\n            int newCost = fallback_cost_sum(tmp);\n            if (used + 1 + newCost > LIMIT) continue;\n\n            int gain = curCost - (1 + newCost);\n            EvalCand ec{d, p, 1, removed, newCost, gain, gain > 0};\n            if (ec.valid) {\n                if (!best.valid ||\n                    ec.gain > best.gain ||\n                    (ec.gain == best.gain && ec.removed > best.removed) ||\n                    (ec.gain == best.gain && ec.removed == best.removed && ec.d < best.d) ||\n                    (ec.gain == best.gain && ec.removed == best.removed && ec.d == best.d && ec.p < best.p)) {\n                    best = ec;\n                }\n            }\n        }\n    }\n\n    if (!best.valid) return false;\n    apply_move(board, best.d, best.p);\n    ans.push_back({best.d, best.p});\n    return true;\n}\n\nstatic pair<vector<Op>, int> solve_one(const vector<string>& initial, int policy) {\n    vector<string> board = initial;\n    vector<Op> ans;\n\n    for (int iter = 0; iter < MAX_GREEDY_ITERS; ++iter) {\n        int curCost = fallback_cost_sum(board);\n        int used = (int)ans.size();\n        if (used + curCost >= LIMIT) break;\n\n        auto cands = generate_candidates(board);\n\n        EvalCand best;\n        for (const auto &cc : cands) {\n            if (used + cc.k > LIMIT) continue;\n\n            vector<string> tmp = board;\n            for (int t = 0; t < cc.k; ++t) apply_move(tmp, cc.d, cc.p);\n\n            int newCost = fallback_cost_sum(tmp);\n            if (used + cc.k + newCost > LIMIT) continue;\n\n            int gain = curCost - (cc.k + newCost);\n            EvalCand ec{cc.d, cc.p, cc.k, cc.removed, newCost, gain, gain > 0};\n            if (ec.valid && better_eval(ec, best, policy)) best = ec;\n        }\n\n        if (best.valid) {\n            for (int t = 0; t < best.k; ++t) {\n                apply_move(board, best.d, best.p);\n                ans.push_back({best.d, best.p});\n            }\n            continue;\n        }\n\n        // Targeted setup rescue only in hard endgames.\n        if (try_setup_rescue(board, ans)) continue;\n\n        break;\n    }\n\n    while (true) {\n        int i, j, len;\n        char dir;\n        if (!find_best_fallback_action(board, i, j, dir, len)) break;\n        if ((int)ans.size() + 2 * len > LIMIT) break;\n\n        if (dir == 'U') {\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'U', j);\n                ans.push_back({'U', j});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'D', j);\n                ans.push_back({'D', j});\n            }\n        } else if (dir == 'D') {\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'D', j);\n                ans.push_back({'D', j});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'U', j);\n                ans.push_back({'U', j});\n            }\n        } else if (dir == 'L') {\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'L', i);\n                ans.push_back({'L', i});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'R', i);\n                ans.push_back({'R', i});\n            }\n        } else { // R\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'R', i);\n                ans.push_back({'R', i});\n            }\n            for (int t = 0; t < len; ++t) {\n                apply_move(board, 'L', i);\n                ans.push_back({'L', i});\n            }\n        }\n    }\n\n    int X = count_oni(board);\n    int Y = 0;\n    int score = (X == 0 && Y == 0) ? (8 * N * N - (int)ans.size()) : (4 * N * N - N * (X + Y));\n    return {ans, score};\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int n;\n    cin >> n;\n    vector<string> initial(n);\n    for (int i = 0; i < n; ++i) cin >> initial[i];\n\n    vector<Op> bestAns;\n    int bestScore = -1;\n\n    for (int policy = 0; policy < NUM_POLICIES; ++policy) {\n        auto [candAns, candScore] = solve_one(initial, policy);\n        if (candScore > bestScore) {\n            bestScore = candScore;\n            bestAns = move(candAns);\n        }\n    }\n\n    for (auto &op : bestAns) {\n        cout << op.d << ' ' << op.p << '\\n';\n    }\n    return 0;\n}","ahc044":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int MAXN = 100;\nstatic constexpr long long INF64 = (1LL << 60);\n\nstruct Solution {\n    array<int, MAXN> a{}, b{};\n    long long err = INF64;\n};\n\nstruct Config {\n    int M = 0;\n    vector<int> order;            // special nodes in cycle order\n    vector<char> is_special;      // size N\n    vector<char> is_hub;          // size N, meaningful on special nodes\n    vector<int> attach;           // size N, for non-special x: attached special\n};\n\nint N, L;\narray<int, MAXN> T;\n\n// Fast exact evaluator using cycle decomposition on expanded state space:\n// state id = node * 2 + parity_before_visit\n// parity_before_visit = cnt[node] % 2 before this week's assignment.\nstatic long long evaluate_solution(const array<int, MAXN>& a, const array<int, MAXN>& b) {\n    const int S = 2 * N;\n\n    vector<int> seen(S, -1);\n    vector<int> seq_states;\n    seq_states.reserve(S + 5);\n\n    vector<array<int, MAXN>> pref; // cumulative counts after k steps\n    pref.reserve(S + 5);\n    array<int, MAXN> zero{};\n    pref.push_back(zero);\n\n    int cur_node = 0;\n    int cur_par = 0; // before visit to node 0, count is 0 => even parity 0\n    int step = 0;\n\n    while (true) {\n        int sid = cur_node * 2 + cur_par;\n        if (seen[sid] != -1) {\n            int mu = seen[sid];\n            int lambda = step - mu;\n\n            auto get_counts_range = [&](int l, int r) {\n                array<long long, MAXN> res{};\n                for (int i = 0; i < N; ++i) {\n                    res[i] = (long long)pref[r][i] - pref[l][i];\n                }\n                return res;\n            };\n\n            array<long long, MAXN> total{};\n            if (L <= mu) {\n                for (int i = 0; i < N; ++i) total[i] = pref[L][i];\n            } else {\n                for (int i = 0; i < N; ++i) total[i] = pref[mu][i];\n\n                auto cyc = get_counts_range(mu, mu + lambda);\n                long long rem = L - mu;\n                long long q = rem / lambda;\n                int r = (int)(rem % lambda);\n\n                for (int i = 0; i < N; ++i) {\n                    total[i] += cyc[i] * q;\n                    total[i] += (long long)pref[mu + r][i] - pref[mu][i];\n                }\n            }\n\n            long long err = 0;\n            for (int i = 0; i < N; ++i) err += llabs(total[i] - (long long)T[i]);\n            return err;\n        }\n\n        seen[sid] = step;\n        seq_states.push_back(sid);\n\n        // perform one week at cur_node\n        auto nxt_pref = pref.back();\n        nxt_pref[cur_node]++;\n        pref.push_back(nxt_pref);\n\n        int nxt_node = (cur_par == 0 ? a[cur_node] : b[cur_node]); // after visit count becomes odd if cur_par=0\n        int nxt_par = ((pref.back()[nxt_node]) & 1); // parity before next visit equals current count mod 2\n\n        // But pref.back()[nxt_node] is count after current step, exactly what we need.\n        cur_node = nxt_node;\n        cur_par = nxt_par;\n        step++;\n    }\n}\n\nstatic Solution build_solution_from_config(const Config& cfg) {\n    Solution sol;\n    for (int i = 0; i < N; ++i) {\n        sol.a[i] = i;\n        sol.b[i] = i;\n    }\n\n    vector<int> pos(N, -1);\n    for (int i = 0; i < cfg.M; ++i) pos[cfg.order[i]] = i;\n\n    // special cycle\n    for (int i = 0; i < cfg.M; ++i) {\n        int v = cfg.order[i];\n        int nxt = cfg.order[(i + 1) % cfg.M];\n        if (cfg.is_hub[v]) {\n            sol.a[v] = v;\n            sol.b[v] = nxt;\n        } else {\n            sol.a[v] = nxt;\n            sol.b[v] = nxt;\n        }\n    }\n\n    // non-special attachments\n    for (int x = 0; x < N; ++x) {\n        if (cfg.is_special[x]) continue;\n        int s = cfg.attach[x];\n        int p = pos[s];\n        int nxt = cfg.order[(p + 1) % cfg.M];\n        sol.a[x] = nxt;\n        sol.b[x] = nxt;\n    }\n\n    sol.err = evaluate_solution(sol.a, sol.b);\n    return sol;\n}\n\nstatic void update_best(Solution& best, const Solution& cand) {\n    if (cand.err < best.err) best = cand;\n}\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    cin >> N >> L;\n    for (int i = 0; i < N; ++i) cin >> T[i];\n\n    auto st = chrono::high_resolution_clock::now();\n    auto elapsed = [&]() -> double {\n        return chrono::duration<double>(chrono::high_resolution_clock::now() - st).count();\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        if (T[x] != T[y]) return T[x] > T[y];\n        return x < y;\n    });\n\n    Solution best;\n\n    // Fallback 1\n    {\n        array<int, MAXN> a{}, b{};\n        int mx = ord[0];\n        for (int i = 0; i < N; ++i) a[i] = b[i] = mx;\n        a[mx] = mx;\n        b[mx] = mx;\n        Solution s{a, b, evaluate_solution(a, b)};\n        update_best(best, s);\n    }\n\n    // Fallback 2\n    {\n        array<int, MAXN> a{}, b{};\n        for (int i = 0; i < N; ++i) {\n            int v = ord[i];\n            int nxt = ord[(i + 1) % N];\n            a[v] = v;\n            b[v] = nxt;\n        }\n        Solution s{a, b, evaluate_solution(a, b)};\n        update_best(best, s);\n    }\n\n    Config best_cfg;\n\n    vector<int> Ms = {8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 100};\n\n    for (int M : Ms) {\n        if (elapsed() > 1.20) break;\n        M = min(M, N);\n\n        vector<int> special(ord.begin(), ord.begin() + M);\n        vector<int> nonspecial(ord.begin() + M, ord.end());\n\n        vector<vector<int>> orders;\n\n        // descending\n        orders.push_back(special);\n\n        // ascending\n        {\n            auto v = special;\n            reverse(v.begin(), v.end());\n            orders.push_back(v);\n        }\n\n        // big-small alternating\n        {\n            vector<int> v;\n            int l = 0, r = M - 1;\n            while (l <= r) {\n                v.push_back(special[l++]);\n                if (l <= r) v.push_back(special[r--]);\n            }\n            orders.push_back(v);\n        }\n\n        // interleave halves\n        {\n            vector<int> v;\n            int mid = (M + 1) / 2;\n            for (int i = 0; i < mid; ++i) {\n                v.push_back(special[i]);\n                if (i + mid < M) v.push_back(special[i + mid]);\n            }\n            orders.push_back(v);\n        }\n\n        for (const auto& order : orders) {\n            if (elapsed() > 1.35) break;\n\n            vector<int> Hs = {\n                max(1, M / 4),\n                max(1, M / 3),\n                max(1, M / 2),\n                max(1, 2 * M / 3),\n                M\n            };\n            sort(Hs.begin(), Hs.end());\n            Hs.erase(unique(Hs.begin(), Hs.end()), Hs.end());\n\n            for (int H : Hs) {\n                // Several hub-selection schemes\n                for (int hub_mode = 0; hub_mode < 4; ++hub_mode) {\n                    Config cfg;\n                    cfg.M = M;\n                    cfg.order = order;\n                    cfg.is_special.assign(N, 0);\n                    cfg.is_hub.assign(N, 0);\n                    cfg.attach.assign(N, order[0]);\n\n                    for (int v : order) cfg.is_special[v] = 1;\n\n                    if (hub_mode == 0) {\n                        // first H in order\n                        for (int i = 0; i < H; ++i) cfg.is_hub[order[i]] = 1;\n                    } else if (hub_mode == 1) {\n                        // top H by target among special\n                        vector<int> tmp = order;\n                        sort(tmp.begin(), tmp.end(), [&](int x, int y) {\n                            if (T[x] != T[y]) return T[x] > T[y];\n                            return x < y;\n                        });\n                        for (int i = 0; i < H; ++i) cfg.is_hub[tmp[i]] = 1;\n                    } else if (hub_mode == 2) {\n                        // alternating in order\n                        int cnt = 0;\n                        for (int i = 0; i < M && cnt < H; i += 2, ++cnt) cfg.is_hub[order[i]] = 1;\n                        for (int i = 1; i < M && cnt < H; i += 2, ++cnt) cfg.is_hub[order[i]] = 1;\n                    } else {\n                        // every kth style\n                        int stepk = max(1, M / H);\n                        int cnt = 0;\n                        vector<char> used(N, 0);\n                        for (int start = 0; cnt < H && start < stepk; ++start) {\n                            for (int i = start; i < M && cnt < H; i += stepk) {\n                                int v = order[i];\n                                if (!used[v]) {\n                                    used[v] = 1;\n                                    cfg.is_hub[v] = 1;\n                                    cnt++;\n                                }\n                            }\n                        }\n                    }\n\n                    // Attach non-special nodes greedily to special nodes\n                    vector<long long> load(N, 0);\n                    for (int v : order) load[v] = T[v];\n\n                    vector<int> rem = nonspecial;\n                    sort(rem.begin(), rem.end(), [&](int x, int y) {\n                        if (T[x] != T[y]) return T[x] > T[y];\n                        return x < y;\n                    });\n\n                    for (int x : rem) {\n                        int best_s = order[0];\n                        long long best_score = INF64;\n                        for (int s : order) {\n                            // Hub specials are more \"powerful\", so slightly less penalty.\n                            long long score = load[s] + (cfg.is_hub[s] ? 0LL : 300LL);\n                            if (score < best_score) {\n                                best_score = score;\n                                best_s = s;\n                            }\n                        }\n                        cfg.attach[x] = best_s;\n                        load[best_s] += T[x];\n                    }\n\n                    Solution cand = build_solution_from_config(cfg);\n                    if (cand.err < best.err) {\n                        best = cand;\n                        best_cfg = cfg;\n                    }\n                }\n            }\n        }\n    }\n\n    // Small local refinement on the best config\n    if (best_cfg.M > 0) {\n        Config cur = best_cfg;\n        Solution cur_sol = build_solution_from_config(cur);\n\n        uint64_t rng_state = chrono::high_resolution_clock::now().time_since_epoch().count();\n        auto rng64 = [&]() -> uint64_t {\n            rng_state ^= rng_state << 7;\n            rng_state ^= rng_state >> 9;\n            return rng_state;\n        };\n        auto rnd = [&](int l, int r) -> int {\n            return l + (int)(rng64() % (uint64_t)(r - l + 1));\n        };\n\n        while (elapsed() < 1.95) {\n            Config nxt = cur;\n            int op = rnd(0, 2);\n\n            if (op == 0 && nxt.M >= 2) {\n                // swap adjacent/random positions\n                int i = rnd(0, nxt.M - 1);\n                int j = (rng64() & 1) ? (i + 1) % nxt.M : rnd(0, nxt.M - 1);\n                if (i != j) swap(nxt.order[i], nxt.order[j]);\n            } else if (op == 1) {\n                // flip hub status of one special\n                int i = rnd(0, nxt.M - 1);\n                int v = nxt.order[i];\n                nxt.is_hub[v] ^= 1;\n                bool any_hub = false;\n                for (int x : nxt.order) if (nxt.is_hub[x]) any_hub = true;\n                if (!any_hub) nxt.is_hub[v] = 1;\n            } else {\n                // reattach one non-special node\n                vector<int> nonsp;\n                for (int x = 0; x < N; ++x) if (!nxt.is_special[x]) nonsp.push_back(x);\n                if (!nonsp.empty()) {\n                    int x = nonsp[rnd(0, (int)nonsp.size() - 1)];\n                    int s = nxt.order[rnd(0, nxt.M - 1)];\n                    nxt.attach[x] = s;\n                }\n            }\n\n            Solution ns = build_solution_from_config(nxt);\n            if (ns.err < cur_sol.err) {\n                cur = nxt;\n                cur_sol = ns;\n                if (ns.err < best.err) {\n                    best = ns;\n                    best_cfg = nxt;\n                }\n            }\n        }\n    }\n\n    for (int i = 0; i < N; ++i) {\n        cout << best.a[i] << ' ' << best.b[i] << '\\n';\n    }\n    return 0;\n}","ahc045":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic inline long long part1by1(unsigned x) {\n    unsigned long long n = x;\n    n = (n | (n << 16)) & 0x0000FFFF0000FFFFULL;\n    n = (n | (n << 8)) & 0x00FF00FF00FF00FFULL;\n    n = (n | (n << 4)) & 0x0F0F0F0F0F0F0F0FULL;\n    n = (n | (n << 2)) & 0x3333333333333333ULL;\n    n = (n | (n << 1)) & 0x5555555555555555ULL;\n    return (long long)n;\n}\nstatic inline long long morton_key(int x, int y) {\n    return (part1by1((unsigned)x) << 1) | part1by1((unsigned)y);\n}\n\nstruct XorShift {\n    uint64_t x = 88172645463393265ULL;\n    uint64_t next() {\n        x ^= x << 7;\n        x ^= x >> 9;\n        return x;\n    }\n    int next_int(int l, int r) {\n        return l + (int)(next() % (uint64_t)(r - l + 1));\n    }\n};\n\nstruct DSU {\n    vector<int> p, sz;\n    DSU() {}\n    DSU(int n) { 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) { return p[x] == x ? x : p[x] = find(p[x]); }\n    bool unite(int a, int b) {\n        a = find(a); b = find(b);\n        if (a == b) return false;\n        if (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, 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\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 main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    Timer timer;\n    XorShift rng;\n\n    int N, M, Q, L, W;\n    cin >> N >> M >> Q >> L >> W;\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), cx(N), cy(N);\n    for (int i = 0; i < N; i++) {\n        cin >> lx[i] >> rx[i] >> ly[i] >> ry[i];\n        cx[i] = (lx[i] + rx[i]) / 2;\n        cy[i] = (ly[i] + ry[i]) / 2;\n    }\n\n    auto center_dist = [&](int a, int b) -> int {\n        long long dx = 1LL * cx[a] - cx[b];\n        long long dy = 1LL * cy[a] - cy[b];\n        return (int)floor(sqrt((double)(dx * dx + dy * dy)));\n    };\n\n    auto rect_gap_dist = [&](int a, int b) -> int {\n        int dx = 0, dy = 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        if (ry[a] < ly[b]) dy = ly[b] - ry[a];\n        else if (ry[b] < ly[a]) dy = ly[a] - ry[b];\n        return (int)floor(sqrt((double)(1LL * dx * dx + 1LL * dy * dy)));\n    };\n\n    auto est_dist = [&](int a, int b) -> int {\n        int dc = center_dist(a, b);\n        int dg = rect_gap_dist(a, b);\n        return (3 * dc + 2 * dg) / 5;\n    };\n\n    auto mst_cost_plain = [&](const vector<int>& vs) -> long long {\n        int n = (int)vs.size();\n        if (n <= 1) return 0;\n        const int INF = 1e9;\n        vector<int> best(n, INF);\n        vector<char> used(n, 0);\n        best[0] = 0;\n        long long res = 0;\n        for (int it = 0; it < n; it++) {\n            int v = -1;\n            for (int i = 0; i < n; i++) if (!used[i]) {\n                if (v == -1 || best[i] < best[v]) v = i;\n            }\n            used[v] = 1;\n            res += best[v];\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                int w = est_dist(vs[v], vs[j]);\n                if (w < best[j]) best[j] = w;\n            }\n        }\n        return res;\n    };\n\n    auto partition_by_order = [&](const vector<int>& ord) -> vector<vector<int>> {\n        vector<vector<int>> groups(M);\n        int ptr = 0;\n        for (int i = 0; i < M; i++) {\n            groups[i].assign(ord.begin() + ptr, ord.begin() + ptr + G[i]);\n            ptr += G[i];\n        }\n        return groups;\n    };\n\n    auto total_cost_plain = [&](const vector<vector<int>>& groups) -> long long {\n        long long sum = 0;\n        for (auto &g : groups) sum += mst_cost_plain(g);\n        return sum;\n    };\n\n    vector<int> all(N);\n    iota(all.begin(), all.end(), 0);\n\n    vector<vector<int>> candidate_orders;\n\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cy[a] != cy[b]) return cy[a] < cy[b];\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n            if (sa != sb) return sa < sb;\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            int sa = cx[a] - cy[a], sb = cx[b] - cy[b];\n            if (sa != sb) return sa < sb;\n            return cx[a] < cx[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        auto ord = all;\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            long long ka = morton_key(cx[a], cy[a]);\n            long long kb = morton_key(cx[b], cy[b]);\n            if (ka != kb) return ka < kb;\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        candidate_orders.push_back(ord);\n    }\n    {\n        vector<pair<pair<int,int>, int>> pts;\n        for (int v : all) pts.push_back({{cx[v] / 700, cy[v]}, v});\n        sort(pts.begin(), pts.end(), [&](auto &A, auto &B) {\n            int ba = A.first.first, bb = B.first.first;\n            if (ba != bb) return ba < bb;\n            if (ba & 1) return A.first.second > B.first.second;\n            return A.first.second < B.first.second;\n        });\n        vector<int> ord;\n        for (auto &p : pts) ord.push_back(p.second);\n        candidate_orders.push_back(ord);\n    }\n    {\n        vector<pair<pair<int,int>, int>> pts;\n        for (int v : all) pts.push_back({{cy[v] / 700, cx[v]}, v});\n        sort(pts.begin(), pts.end(), [&](auto &A, auto &B) {\n            int ba = A.first.first, bb = B.first.first;\n            if (ba != bb) return ba < bb;\n            if (ba & 1) return A.first.second > B.first.second;\n            return A.first.second < B.first.second;\n        });\n        vector<int> ord;\n        for (auto &p : pts) ord.push_back(p.second);\n        candidate_orders.push_back(ord);\n    }\n    // New low-risk candidate: recursive kd-like alternating split order.\n    {\n        vector<int> ord = all, out;\n        out.reserve(N);\n        function<void(vector<int>&, int)> rec = [&](vector<int>& v, int dep) {\n            if (v.empty()) return;\n            if ((int)v.size() <= 16) {\n                sort(v.begin(), v.end(), [&](int a, int b) {\n                    if (dep & 1) {\n                        if (cy[a] != cy[b]) return cy[a] < cy[b];\n                        return cx[a] < cx[b];\n                    } else {\n                        if (cx[a] != cx[b]) return cx[a] < cx[b];\n                        return cy[a] < cy[b];\n                    }\n                });\n                for (int x : v) out.push_back(x);\n                return;\n            }\n            nth_element(v.begin(), v.begin() + v.size() / 2, v.end(), [&](int a, int b) {\n                if (dep & 1) {\n                    if (cy[a] != cy[b]) return cy[a] < cy[b];\n                    return cx[a] < cx[b];\n                } else {\n                    if (cx[a] != cx[b]) return cx[a] < cx[b];\n                    return cy[a] < cy[b];\n                }\n            });\n            vector<int> Ls(v.begin(), v.begin() + v.size() / 2);\n            vector<int> Rs(v.begin() + v.size() / 2, v.end());\n            rec(Ls, dep + 1);\n            rec(Rs, dep + 1);\n        };\n        rec(ord, 0);\n        candidate_orders.push_back(out);\n    }\n\n    vector<vector<int>> groups;\n    long long best_score = (1LL << 62);\n    for (auto &ord : candidate_orders) {\n        auto cand = partition_by_order(ord);\n        long long sc = total_cost_plain(cand);\n        if (sc < best_score) {\n            best_score = sc;\n            groups = move(cand);\n        }\n    }\n\n    auto make_order = [&](vector<int> U, int type) -> vector<int> {\n        if (type == 0) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            });\n        } else if (type == 1) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            });\n        } else if (type == 2) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n        } else if (type == 3) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                int sa = cx[a] - cy[a], sb = cx[b] - cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n        } else if (type == 4) {\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                long long ka = morton_key(cx[a], cy[a]);\n                long long kb = morton_key(cx[b], cy[b]);\n                if (ka != kb) return ka < kb;\n                return a < b;\n            });\n        } else {\n            int sx = (rng.next() & 1) ? 1 : -1;\n            int sy = (rng.next() & 1) ? 1 : -1;\n            sort(U.begin(), U.end(), [&](int a, int b) {\n                int va = sx * cx[a] + sy * cy[a];\n                int vb = sx * cx[b] + sy * cy[b];\n                if (va != vb) return va < vb;\n                return a < b;\n            });\n        }\n        return U;\n    };\n\n    auto improve_pair_plain = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        int sa = (int)A.size(), sb = (int)B.size();\n        long long oldv = mst_cost_plain(A) + mst_cost_plain(B);\n        bool improved = false;\n\n        long long best = oldv;\n        int besta = -1, bestb = -1;\n        for (int ia = max(0, sa - 10); ia < sa; ia++) {\n            for (int ib = 0; ib < min(sb, 10); ib++) {\n                vector<int> nA = A, nB = B;\n                swap(nA[ia], nB[ib]);\n                long long nv = mst_cost_plain(nA) + mst_cost_plain(nB);\n                if (nv < best) {\n                    best = nv;\n                    besta = ia;\n                    bestb = ib;\n                }\n            }\n        }\n        if (besta != -1) {\n            swap(A[besta], B[bestb]);\n            improved = true;\n            oldv = best;\n        }\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.end());\n            long long nv = mst_cost_plain(A2) + mst_cost_plain(B2);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    auto improve_triple_plain = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        auto &C = groups[gi + 2];\n        int sa = (int)A.size(), sb = (int)B.size(), sc = (int)C.size();\n\n        long long oldv = mst_cost_plain(A) + mst_cost_plain(B) + mst_cost_plain(C);\n        bool improved = false;\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        U.insert(U.end(), C.begin(), C.end());\n\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.begin() + sa + sb);\n            vector<int> C2(ord.begin() + sa + sb, ord.end());\n            long long nv = mst_cost_plain(A2) + mst_cost_plain(B2) + mst_cost_plain(C2);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                C = move(C2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    for (int rep = 0; rep < 2; rep++) {\n        bool imp = false;\n        for (int gi = 0; gi + 1 < M; gi++) imp |= improve_pair_plain(gi, 6);\n        for (int gi = 0; gi + 2 < M; gi++) {\n            if (timer.elapsed() > 0.70) break;\n            imp |= improve_triple_plain(gi, 6);\n        }\n        if (!imp) break;\n    }\n    while (timer.elapsed() < 0.95) {\n        if (M >= 3 && (rng.next() & 1)) {\n            int gi = rng.next_int(0, M - 3);\n            improve_triple_plain(gi, 3);\n        } else if (M >= 2) {\n            int gi = rng.next_int(0, M - 2);\n            improve_pair_plain(gi, 3);\n        } else break;\n    }\n\n    vector<vector<pair<int,int>>> queried_edges(M);\n    int used_queries = 0;\n\n    auto do_query = [&](const vector<int>& subset) -> vector<pair<int,int>> {\n        cout << \"? \" << subset.size();\n        for (int v : subset) cout << ' ' << v;\n        cout << '\\n';\n        cout.flush();\n        vector<pair<int,int>> ret;\n        ret.reserve((int)subset.size() - 1);\n        for (int i = 0; i < (int)subset.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    vector<int> gids(M);\n    iota(gids.begin(), gids.end(), 0);\n    sort(gids.begin(), gids.end(), [&](int a, int b) {\n        if (groups[a].size() != groups[b].size()) return groups[a].size() > groups[b].size();\n        return a < b;\n    });\n\n    for (int gi : gids) {\n        if (used_queries >= Q) break;\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        if (sz <= 1) continue;\n\n        vector<vector<int>> local_orders;\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            });\n            local_orders.push_back(ord);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            });\n            local_orders.push_back(ord);\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n            local_orders.push_back(ord);\n        }\n\n        int block = min(L, sz);\n        int step = max(1, block / 2);\n        set<vector<int>> seen;\n\n        for (auto &ord : local_orders) {\n            for (int s = 0; s < sz && used_queries < Q; s += step) {\n                int e = min(sz, s + block);\n                if (e - s < 2) break;\n                vector<int> subset(ord.begin() + s, ord.begin() + e);\n                sort(subset.begin(), subset.end());\n                if (!seen.insert(subset).second) {\n                    if (e == sz) break;\n                    continue;\n                }\n                auto ret = do_query(subset);\n                for (auto &p : ret) queried_edges[gi].push_back(p);\n                used_queries++;\n                if (e == sz) break;\n            }\n        }\n    }\n\n    vector<unordered_set<long long>> qset(M);\n    auto enc = [&](int a, int b) -> long long {\n        if (a > b) swap(a, b);\n        return 1LL * a * N + b;\n    };\n    for (int gi = 0; gi < M; gi++) {\n        qset[gi].reserve(queried_edges[gi].size() * 2 + 1);\n        for (auto [a, b] : queried_edges[gi]) qset[gi].insert(enc(a, b));\n    }\n\n    auto mst_cost_query = [&](const vector<int>& vs, const unordered_set<long long>& qs) -> long long {\n        int n = (int)vs.size();\n        if (n <= 1) return 0;\n        const int INF = 1e9;\n        vector<int> best(n, INF);\n        vector<char> used(n, 0);\n        best[0] = 0;\n        long long res = 0;\n        for (int it = 0; it < n; it++) {\n            int v = -1;\n            for (int i = 0; i < n; i++) if (!used[i]) {\n                if (v == -1 || best[i] < best[v]) v = i;\n            }\n            used[v] = 1;\n            res += best[v];\n            for (int j = 0; j < n; j++) if (!used[j]) {\n                int w = est_dist(vs[v], vs[j]);\n                if (qs.count(enc(vs[v], vs[j]))) w = max(0, w - 12);\n                if (w < best[j]) best[j] = w;\n            }\n        }\n        return res;\n    };\n\n    auto improve_pair_query = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        int sa = (int)A.size(), sb = (int)B.size();\n\n        unordered_set<long long> qs;\n        qs.reserve(qset[gi].size() + qset[gi + 1].size() + 1);\n        for (auto x : qset[gi]) qs.insert(x);\n        for (auto x : qset[gi + 1]) qs.insert(x);\n\n        long long oldv = mst_cost_query(A, qs) + mst_cost_query(B, qs);\n        bool improved = false;\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.end());\n            long long nv = mst_cost_query(A2, qs) + mst_cost_query(B2, qs);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    auto improve_triple_query = [&](int gi, int mode_cnt) -> bool {\n        auto &A = groups[gi];\n        auto &B = groups[gi + 1];\n        auto &C = groups[gi + 2];\n        int sa = (int)A.size(), sb = (int)B.size(), sc = (int)C.size();\n\n        unordered_set<long long> qs;\n        qs.reserve(qset[gi].size() + qset[gi + 1].size() + qset[gi + 2].size() + 1);\n        for (auto x : qset[gi]) qs.insert(x);\n        for (auto x : qset[gi + 1]) qs.insert(x);\n        for (auto x : qset[gi + 2]) qs.insert(x);\n\n        long long oldv = mst_cost_query(A, qs) + mst_cost_query(B, qs) + mst_cost_query(C, qs);\n        bool improved = false;\n\n        vector<int> U = A;\n        U.insert(U.end(), B.begin(), B.end());\n        U.insert(U.end(), C.begin(), C.end());\n\n        for (int t = 0; t < mode_cnt; t++) {\n            auto ord = make_order(U, t < 5 ? t : 5);\n            vector<int> A2(ord.begin(), ord.begin() + sa);\n            vector<int> B2(ord.begin() + sa, ord.begin() + sa + sb);\n            vector<int> C2(ord.begin() + sa + sb, ord.end());\n            long long nv = mst_cost_query(A2, qs) + mst_cost_query(B2, qs) + mst_cost_query(C2, qs);\n            if (nv < oldv) {\n                A = move(A2);\n                B = move(B2);\n                C = move(C2);\n                oldv = nv;\n                improved = true;\n            }\n        }\n        return improved;\n    };\n\n    while (timer.elapsed() < 1.50) {\n        if (M >= 3 && (rng.next() % 3 != 0)) {\n            int gi = rng.next_int(0, M - 3);\n            improve_triple_query(gi, 3);\n        } else if (M >= 2) {\n            int gi = rng.next_int(0, M - 2);\n            improve_pair_query(gi, 3);\n        } else break;\n    }\n\n    vector<vector<pair<int,int>>> answer_edges(M);\n\n    for (int gi = 0; gi < M; gi++) {\n        auto &g = groups[gi];\n        int sz = (int)g.size();\n        answer_edges[gi].clear();\n        if (sz <= 1) continue;\n\n        unordered_map<int,int> pos;\n        pos.reserve(sz * 2);\n        for (int i = 0; i < sz; i++) pos[g[i]] = i;\n\n        vector<Edge> cand;\n        auto add_edge = [&](int a, int b) {\n            if (a == b) return;\n            if (a > b) swap(a, b);\n            int w = est_dist(a, b);\n            if (qset[gi].count(enc(a, b))) w = max(0, w - 20);\n            cand.push_back({a, b, w});\n        };\n\n        for (auto [a, b] : queried_edges[gi]) {\n            if (pos.count(a) && pos.count(b)) add_edge(a, b);\n        }\n\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cx[a] != cx[b]) return cx[a] < cx[b];\n                return cy[a] < cy[b];\n            });\n            for (int i = 0; i < sz; i++) {\n                for (int d = 1; d <= 4; d++) {\n                    if (i + d < sz) add_edge(ord[i], ord[i + d]);\n                }\n            }\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                if (cy[a] != cy[b]) return cy[a] < cy[b];\n                return cx[a] < cx[b];\n            });\n            for (int i = 0; i < sz; i++) {\n                for (int d = 1; d <= 4; d++) {\n                    if (i + d < sz) add_edge(ord[i], ord[i + d]);\n                }\n            }\n        }\n        {\n            auto ord = g;\n            sort(ord.begin(), ord.end(), [&](int a, int b) {\n                int sa = cx[a] + cy[a], sb = cx[b] + cy[b];\n                if (sa != sb) return sa < sb;\n                return cx[a] < cx[b];\n            });\n            for (int i = 0; i < sz; i++) {\n                for (int d = 1; d <= 3; d++) {\n                    if (i + d < sz) add_edge(ord[i], ord[i + d]);\n                }\n            }\n        }\n\n        int k = min(6, sz - 1);\n        for (int i = 0; i < sz; i++) {\n            vector<pair<int,int>> vv;\n            vv.reserve(sz - 1);\n            for (int j = 0; j < sz; j++) if (i != j) {\n                vv.push_back({est_dist(g[i], g[j]), g[j]});\n            }\n            if ((int)vv.size() > k) nth_element(vv.begin(), vv.begin() + k, vv.end());\n            int lim = min(k, (int)vv.size());\n            for (int t = 0; t < lim; t++) add_edge(g[i], vv[t].second);\n        }\n\n        sort(cand.begin(), cand.end(), [&](const Edge& a, const Edge& b) {\n            if (a.u != b.u) return a.u < b.u;\n            if (a.v != b.v) return a.v < b.v;\n            return a.w < b.w;\n        });\n        vector<Edge> uniq;\n        uniq.reserve(cand.size());\n        for (auto &e : cand) {\n            if (uniq.empty() || uniq.back().u != e.u || uniq.back().v != e.v) uniq.push_back(e);\n        }\n        cand.swap(uniq);\n        sort(cand.begin(), cand.end());\n\n        DSU dsu(N);\n        for (auto &e : cand) {\n            if (dsu.unite(e.u, e.v)) {\n                answer_edges[gi].push_back({e.u, e.v});\n                if ((int)answer_edges[gi].size() == sz - 1) break;\n            }\n        }\n\n        if ((int)answer_edges[gi].size() < sz - 1) {\n            answer_edges[gi].clear();\n            const int INF = 1e9;\n            vector<int> best(sz, INF), par(sz, -1);\n            vector<char> used(sz, 0);\n            best[0] = 0;\n            for (int it = 0; it < sz; it++) {\n                int v = -1;\n                for (int i = 0; i < sz; i++) if (!used[i]) {\n                    if (v == -1 || best[i] < best[v]) v = i;\n                }\n                used[v] = 1;\n                if (par[v] != -1) answer_edges[gi].push_back({g[v], g[par[v]]});\n                for (int to = 0; to < sz; to++) if (!used[to]) {\n                    int w = est_dist(g[v], g[to]);\n                    if (qset[gi].count(enc(g[v], g[to]))) w = max(0, w - 15);\n                    if (w < best[to]) {\n                        best[to] = w;\n                        par[to] = v;\n                    }\n                }\n            }\n        }\n\n        if ((int)answer_edges[gi].size() != sz - 1) {\n            answer_edges[gi].clear();\n            for (int i = 1; i < sz; i++) answer_edges[gi].push_back({g[i - 1], g[i]});\n        }\n    }\n\n    bool bad = false;\n    vector<int> freq(N, 0);\n    for (int gi = 0; gi < M; gi++) {\n        if ((int)groups[gi].size() != G[gi]) bad = true;\n        if ((int)answer_edges[gi].size() != max(0, G[gi] - 1)) bad = true;\n        for (int v : groups[gi]) {\n            if (v < 0 || v >= N) bad = true;\n            else freq[v]++;\n        }\n    }\n    for (int i = 0; i < N; i++) if (freq[i] != 1) bad = true;\n\n    if (bad) {\n        vector<int> ord(N);\n        iota(ord.begin(), ord.end(), 0);\n        sort(ord.begin(), ord.end(), [&](int a, int b) {\n            if (cx[a] != cx[b]) return cx[a] < cx[b];\n            return cy[a] < cy[b];\n        });\n        int ptr = 0;\n        for (int gi = 0; gi < M; gi++) {\n            groups[gi].assign(ord.begin() + ptr, ord.begin() + ptr + G[gi]);\n            ptr += G[gi];\n            answer_edges[gi].clear();\n            for (int i = 1; i < G[gi]; i++) answer_edges[gi].push_back({groups[gi][i - 1], groups[gi][i]});\n        }\n    }\n\n    cout << \"!\\n\";\n    for (int gi = 0; gi < M; gi++) {\n        for (int i = 0; i < (int)groups[gi].size(); i++) {\n            if (i) cout << ' ';\n            cout << groups[gi][i];\n        }\n        cout << '\\n';\n        for (auto [a, b] : answer_edges[gi]) {\n            cout << a << ' ' << b << '\\n';\n        }\n    }\n    cout.flush();\n\n    return 0;\n}","ahc046":"#include <bits/stdc++.h>\nusing namespace std;\n\nstatic constexpr int N = 20;\nstatic constexpr int INF = 1e9;\n\nint dr[4] = {-1, 1, 0, 0};\nint dc[4] = {0, 0, -1, 1};\nchar DCH[4] = {'U', 'D', 'L', 'R'};\n\nstruct Pos {\n    int r, c;\n    bool operator==(const Pos& o) const { return r == o.r && c == o.c; }\n    bool operator!=(const Pos& o) const { return !(*this == o); }\n};\n\nstruct Action {\n    char a, d;\n};\n\nstruct Plan {\n    int cost = INF;\n    int tie = 0;\n    vector<Action> acts;\n};\n\ninline bool inside(int r, int c) {\n    return 0 <= r && r < N && 0 <= c && c < N;\n}\n\nstruct Solver {\n    int M;\n    vector<Pos> pts;\n    bool block[N][N]{};\n    vector<Action> ans;\n    Pos cur;\n\n    Solver(int M_, const vector<Pos>& pts_) : M(M_), pts(pts_) {\n        memset(block, 0, sizeof(block));\n        cur = pts[0];\n    }\n\n    inline void relax(Plan& best, const Plan& cand) {\n        if (cand.cost < best.cost || (cand.cost == best.cost && cand.tie < best.tie)) {\n            best = cand;\n        }\n    }\n\n    Pos slide_result(Pos s, int d) const {\n        int r = s.r, c = s.c;\n        while (true) {\n            int nr = r + dr[d], nc = c + dc[d];\n            if (!inside(nr, nc) || block[nr][nc]) break;\n            r = nr; c = nc;\n        }\n        return {r, c};\n    }\n\n    Plan shortest_MS(Pos s, Pos g) {\n        Plan p;\n        static int dist[N][N];\n        static Pos par[N][N];\n        static char pact[N][N];\n        static int pdir[N][N];\n\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) dist[i][j] = -1;\n\n        queue<Pos> q;\n        dist[s.r][s.c] = 0;\n        q.push(s);\n\n        while (!q.empty()) {\n            Pos v = q.front(); q.pop();\n            if (v == g) break;\n\n            // Move edges\n            for (int d = 0; d < 4; d++) {\n                int nr = v.r + dr[d], nc = v.c + dc[d];\n                if (!inside(nr, nc) || block[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[v.r][v.c] + 1;\n                par[nr][nc] = v;\n                pact[nr][nc] = 'M';\n                pdir[nr][nc] = d;\n                q.push({nr, nc});\n            }\n\n            // Slide edges\n            for (int d = 0; d < 4; d++) {\n                Pos to = slide_result(v, d);\n                if (to == v) continue;\n                if (dist[to.r][to.c] != -1) continue;\n                dist[to.r][to.c] = dist[v.r][v.c] + 1;\n                par[to.r][to.c] = v;\n                pact[to.r][to.c] = 'S';\n                pdir[to.r][to.c] = d;\n                q.push(to);\n            }\n        }\n\n        if (dist[g.r][g.c] == -1) return p;\n        p.cost = dist[g.r][g.c];\n\n        vector<Action> rev;\n        Pos x = g;\n        while (x != s) {\n            rev.push_back({pact[x.r][x.c], DCH[pdir[x.r][x.c]]});\n            x = par[x.r][x.c];\n        }\n        reverse(rev.begin(), rev.end());\n        p.acts = move(rev);\n        return p;\n    }\n\n    vector<int> bfs_move_dirs(Pos s, Pos g) {\n        static int dist[N][N];\n        static Pos par[N][N];\n        static int pard[N][N];\n        for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) dist[i][j] = -1;\n\n        queue<Pos> q;\n        dist[s.r][s.c] = 0;\n        q.push(s);\n\n        while (!q.empty()) {\n            Pos v = q.front(); q.pop();\n            if (v == g) break;\n            for (int d = 0; d < 4; d++) {\n                int nr = v.r + dr[d], nc = v.c + dc[d];\n                if (!inside(nr, nc) || block[nr][nc]) continue;\n                if (dist[nr][nc] != -1) continue;\n                dist[nr][nc] = dist[v.r][v.c] + 1;\n                par[nr][nc] = v;\n                pard[nr][nc] = d;\n                q.push({nr, nc});\n            }\n        }\n\n        if (dist[g.r][g.c] == -1) return {};\n        vector<int> dirs;\n        Pos x = g;\n        while (x != s) {\n            dirs.push_back(pard[x.r][x.c]);\n            x = par[x.r][x.c];\n        }\n        reverse(dirs.begin(), dirs.end());\n        return dirs;\n    }\n\n    // Create one stopper beyond target, then use shortest M/S path under that block.\n    Plan create_stopper_then_ms(Pos s, Pos g, Pos next_goal) {\n        Plan best;\n        Plan baseline = shortest_MS(s, g);\n        int base_cost = baseline.cost;\n\n        for (int d = 0; d < 4; d++) {\n            int br = g.r + dr[d], bc = g.c + dc[d];\n            if (!inside(br, bc)) continue;\n            if (block[br][bc]) continue;\n\n            // Need to stand adjacent to blocker cell to alter it\n            for (int ad = 0; ad < 4; ad++) {\n                int yr = br - dr[ad], yc = bc - dc[ad];\n                if (!inside(yr, yc) || block[yr][yc]) continue;\n                Pos y{yr, yc};\n\n                auto path1 = bfs_move_dirs(s, y);\n                if (path1.empty() && s != y) continue;\n\n                block[br][bc] = true;\n                Plan after = shortest_MS(y, g);\n                block[br][bc] = false;\n\n                if (after.cost >= INF) continue;\n\n                Plan cand;\n                cand.cost = (int)path1.size() + 1 + after.cost;\n\n                // Don't invest too much if not immediately useful\n                if (cand.cost > base_cost + 1) continue;\n\n                cand.tie = 0;\n                if (br == next_goal.r || bc == next_goal.c) cand.tie -= 1;\n\n                for (int dd : path1) cand.acts.push_back({'M', DCH[dd]});\n                cand.acts.push_back({'A', DCH[ad]});\n\n                block[br][bc] = true;\n                Plan after2 = shortest_MS(y, g);\n                block[br][bc] = false;\n                for (auto ac : after2.acts) cand.acts.push_back(ac);\n\n                relax(best, cand);\n            }\n        }\n        return best;\n    }\n\n    // Very cheap persistent anchor idea:\n    // create one anchor at (g.r,1)/(g.r,N-2)/(1,g.c)/(N-2,g.c) if it does not hurt current cost too much.\n    Plan create_anchor_then_ms(Pos s, Pos g, Pos next_goal) {\n        Plan best;\n        Plan baseline = shortest_MS(s, g);\n        int base_cost = baseline.cost;\n\n        vector<Pos> anchors = {\n            {g.r, 1}, {g.r, N - 2}, {1, g.c}, {N - 2, g.c}\n        };\n        bool used[N][N]{};\n\n        for (Pos a : anchors) {\n            if (!inside(a.r, a.c) || block[a.r][a.c] || used[a.r][a.c]) continue;\n            if (a == s || a == g) continue;\n            used[a.r][a.c] = true;\n\n            for (int d = 0; d < 4; d++) {\n                int yr = a.r - dr[d], yc = a.c - dc[d];\n                if (!inside(yr, yc) || block[yr][yc]) continue;\n                Pos y{yr, yc};\n\n                auto path1 = bfs_move_dirs(s, y);\n                if (path1.empty() && s != y) continue;\n\n                block[a.r][a.c] = true;\n                Plan after = shortest_MS(y, g);\n                block[a.r][a.c] = false;\n                if (after.cost >= INF) continue;\n\n                Plan cand;\n                cand.cost = (int)path1.size() + 1 + after.cost;\n                if (cand.cost > base_cost + 1) continue;\n\n                cand.tie = 0;\n                if (a.r == next_goal.r || a.c == next_goal.c) cand.tie -= 2;\n                if (a.r == g.r || a.c == g.c) cand.tie -= 1;\n\n                for (int dd : path1) cand.acts.push_back({'M', DCH[dd]});\n                cand.acts.push_back({'A', DCH[d]});\n\n                block[a.r][a.c] = true;\n                Plan after2 = shortest_MS(y, g);\n                block[a.r][a.c] = false;\n                for (auto ac : after2.acts) cand.acts.push_back(ac);\n\n                relax(best, cand);\n            }\n        }\n\n        return best;\n    }\n\n    void do_action(const Action& ac) {\n        ans.push_back(ac);\n        int d = (ac.d == 'U' ? 0 : ac.d == 'D' ? 1 : ac.d == 'L' ? 2 : 3);\n        if (ac.a == 'M') {\n            cur.r += dr[d];\n            cur.c += dc[d];\n        } else if (ac.a == 'S') {\n            cur = slide_result(cur, d);\n        } else {\n            int nr = cur.r + dr[d], nc = cur.c + dc[d];\n            if (inside(nr, nc)) block[nr][nc] ^= 1;\n        }\n    }\n\n    void execute_plan(const Plan& p) {\n        for (const auto& ac : p.acts) do_action(ac);\n    }\n\n    void solve() {\n        for (int i = 1; i < M; i++) {\n            Pos g = pts[i];\n            Pos next_goal = (i + 1 < M ? pts[i + 1] : g);\n\n            Plan best = shortest_MS(cur, g);\n\n            Plan p1 = create_stopper_then_ms(cur, g, next_goal);\n            relax(best, p1);\n\n            Plan p2 = create_anchor_then_ms(cur, g, next_goal);\n            relax(best, p2);\n\n            if (best.cost >= INF) {\n                auto dirs = bfs_move_dirs(cur, g);\n                for (int d : dirs) do_action({'M', DCH[d]});\n            } else {\n                execute_plan(best);\n            }\n\n            // Safety\n            if (cur != g) {\n                auto dirs = bfs_move_dirs(cur, g);\n                for (int d : dirs) do_action({'M', DCH[d]});\n            }\n        }\n\n        for (auto& ac : ans) {\n            cout << ac.a << ' ' << ac.d << '\\n';\n        }\n    }\n};\n\nint main() {\n    ios::sync_with_stdio(false);\n    cin.tie(nullptr);\n\n    int Nin, M;\n    cin >> Nin >> M;\n    vector<Pos> pts(M);\n    for (int i = 0; i < M; i++) cin >> pts[i].r >> pts[i].c;\n\n    Solver solver(M, pts);\n    solver.solve();\n    return 0;\n}"}}}